Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add clang sanitizers #20

Merged
merged 13 commits into from
Nov 27, 2024
38 changes: 38 additions & 0 deletions .github/workflows/clang-sanitizers-linux-nix-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Build and Test sanitizers on Linux with clang

on:
workflow_call:

jobs:
build-and-test:
name: "Build and test Linux with clang"
runs-on: [self-hosted, Linux, X64, aws_autoscaling]
continue-on-error: true
steps:
# https://github.com/actions/checkout/issues/1552
- name: Clean up after previous checkout
run: chmod +w -R ${GITHUB_WORKSPACE}; rm -rf ${GITHUB_WORKSPACE}/*;

- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Run checks
run: |
nix build -L .?#checks.x86_64-linux.all-clang-sanitize
mkdir results
cp result/test-logs/*_test.xml results/
continue-on-error: true
env:
NIX_CONFIG: |
cores = 4

- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action/linux@v2
with:
check_name: "Sanitizers Test Results"
files: "results/*.xml"
comment_mode: ${{ github.event.pull_request.head.repo.fork && 'off' || 'always' }} # Don't create PR comment from fork runs
action_fail_on_inconclusive: true # fail, if no reports

45 changes: 45 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Nightly Testing

on:
schedule:
- cron: '0 0 * * *'

jobs:
test-linux-sanitizers:
name: Linux placeholder testing and sanitize with clang
uses: ./.github/workflows/clang-sanitizers-linux-nix-check.yml
if: |
always() && !cancelled()
secrets: inherit

post-telemetry:
name: Post test results in Open Telemetry format
runs-on: [self-hosted, Linux, X64, aws_autoscaling]
needs:
- test-linux-sanitizers
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Post logs to Sig Noz
run: |
ls -l -a
nix build -L .?#checks.x86_64-linux.all-clang-sanitize
cat ./result/test-logs/test_errors.txt
export UndefinedBehaviorSanitizer=$(grep UndefinedBehaviorSanitizer result/test-logs/test_errors.txt | wc -l)
export AddressSanitizer=$(grep AddressSanitizer result/test-logs/test_errors.txt | wc -l)
export LeakSanitizer=$(grep LeakSanitizer result/test-logs/test_errors.txt | wc -l)
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
python3 --version
sudo yum update -y
sudo yum install -y python3-pip
pip3 install -r requirements.txt
/home/ec2-user/.local/bin/opentelemetry-instrument \
--traces_exporter console,otlp \
--metrics_exporter console,otlp \
--logs_exporter console,otlp \
--service_name nightly-build \
python3 ./parse_tests.py

1 change: 0 additions & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,3 @@ jobs:
if: |
always() && !cancelled()
secrets: inherit

1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,6 @@ callgrind.*
/*.c
/*.cpp
/*.h
/*.py
/*.key
/*.pem
/*.der
Expand Down
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options (-fcolor-diagnostics)
endif ()

if(DEFINED CMAKE_BUILD_TYPE AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
if(DEFINED CMAKE_BUILD_TYPE)
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -ggdb")
set(BOOST_FORCEINLINE "OFF") # improves debugging traces
endif()
endif()

option(SANITIZE "Build sanitizers" FALSE)
Expand Down
8 changes: 7 additions & 1 deletion crypto3.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
enableDebug ? false,
runTests ? false,
sanitize ? false,
benchmarkTests ? false,
}:
let
inherit (lib) optional;
Expand All @@ -34,6 +35,7 @@ in stdenv.mkDerivation {
(if runTests then "-DBUILD_CRYPTO3_TESTS=TRUE" else "-DBUILD_CRYPTO3_TESTS=False")
(if enableDebug then "-DCMAKE_BUILD_TYPE=Debug" else "-DCMAKE_BUILD_TYPE=Release")
(if sanitize then "-DSANITIZE=ON" else "-DSANITIZE=OFF")
(if benchmarkTests then "-DBUILD_CRYPTO3_BENCH_TESTS=ON" else "-DBUILD_CRYPTO3_BENCH_TESTS=OFF")
"-G Ninja"
];

Expand All @@ -42,9 +44,13 @@ in stdenv.mkDerivation {
checkPhase = ''
# JUNIT file without explicit file name is generated after the name of the master test suite inside `CMAKE_CURRENT_SOURCE_DIR`
export BOOST_TEST_LOGGER=JUNIT:HRF
cd crypto3 && ctest --verbose --output-on-failure -R && cd ..
cd crypto3
# remove || true after all tests are fixed under clang-sanitizers check:
ctest --verbose --output-on-failure -R > test_errors.txt || true
cd ..
mkdir -p ${placeholder "out"}/test-logs
find .. -type f -name '*_test.xml' -exec cp {} ${placeholder "out"}/test-logs \;
cp crypto3/test_errors.txt ${placeholder "out"}/test-logs \
'';

shellHook = ''
Expand Down
2 changes: 1 addition & 1 deletion crypto3/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ set(BENCHMARK_NAMES

"multiprecision/modular_adaptor_fixed"

"zk/lpc"
#"zk/lpc"
akokoshn marked this conversation as resolved.
Show resolved Hide resolved
"zk/pedersen"
)

Expand Down
2 changes: 1 addition & 1 deletion crypto3/benchmarks/algebra/curves.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void benchmark_curve_operations(std::string const& curve_name)
return A *= B;
});

if constexpr (has_template_g2_type<curve_type>::value) {
if constexpr (has_type_g2_type<curve_type>::value) {
using g2_type = typename curve_type::template g2_type<>;

using g2_field = typename g2_type::field_type;
Expand Down
46 changes: 41 additions & 5 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,24 @@
enableDebug = true;
runTests = true;
});
crypto3-sanitize = (pkgs.callPackage ./crypto3.nix {
enableDebug = true;
crypto3-clang-sanitize = (pkgs.callPackage ./crypto3.nix {
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = true;
enableDebug = false;
sanitize = true;
});
crypto3-clang-sanitize-bench = (pkgs.callPackage ./crypto3.nix {
akokoshn marked this conversation as resolved.
Show resolved Hide resolved
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = true;
enableDebug = false;
sanitize = true;
benchmarkTests = true;
});
crypto3-clang-bench = (pkgs.callPackage ./crypto3.nix {
runTests = true;
enableDebug = false;
benchmarkTests = true;
});
crypto3-clang-debug = (pkgs.callPackage ./crypto3.nix {
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = false;
Expand Down Expand Up @@ -90,7 +103,7 @@
# fetched from the cache.
all = pkgs.symlinkJoin {
name = "all";
paths = [ crypto3 proof-producer];
paths = [ crypto3 parallel-crypto3 proof-producer];
};
default = all;
};
Expand All @@ -100,6 +113,11 @@
runTests = true;
enableDebug = false;
});
crypto3-gcc-bench = (pkgs.callPackage ./crypto3.nix {
runTests = true;
enableDebug = false;
benchmarkTests = true;
});
crypto3-clang = (pkgs.callPackage ./crypto3.nix {
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = true;
Expand All @@ -111,6 +129,13 @@
enableDebug = false;
sanitize = true;
});
crypto3-clang-sanitize-bench = (pkgs.callPackage ./crypto3.nix {
akokoshn marked this conversation as resolved.
Show resolved Hide resolved
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = true;
enableDebug = false;
sanitize = true;
benchmarkTests = true;
});

parallel-crypto3-gcc = (pkgs.callPackage ./parallel-crypto3.nix {
runTests = true;
Expand All @@ -121,6 +146,11 @@
runTests = true;
enableDebug = false;
});
parallel-crypto3-clang-sanitize = (pkgs.callPackage ./parallel-crypto3.nix {
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = true;
enableDebug = false;
});

proof-producer-gcc = (pkgs.callPackage ./proof-producer.nix {
runTests = true;
Expand All @@ -131,14 +161,20 @@
runTests = true;
enableDebug = false;
});
proof-producer-clang-sanitize = (pkgs.callPackage ./proof-producer.nix {
stdenv = pkgs.llvmPackages_19.stdenv;
runTests = true;
enableDebug = false;
sanitize = true;
});

all-clang = pkgs.symlinkJoin {
name = "all";
paths = [ crypto3-clang parallel-crypto3-clang proof-producer-clang ];
};
all-sanitizers = pkgs.symlinkJoin {
all-clang-sanitize = pkgs.symlinkJoin {
name = "all";
paths = [ crypto3-clang-sanitize ];
paths = [ crypto3-clang-sanitize parallel-crypto3-clang-sanitize proof-producer-clang-sanitize ];
};
all-gcc = pkgs.symlinkJoin {
name = "all";
Expand Down
10 changes: 9 additions & 1 deletion parallel-crypto3.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
enableDebugging,
enableDebug ? false,
runTests ? false,
sanitize? false,
}:
let
inherit (lib) optional;
Expand All @@ -32,13 +33,20 @@ in stdenv.mkDerivation {
[
(if runTests then "-DBUILD_PARALLEL_CRYPTO3_TESTS=TRUE" else "")
(if enableDebug then "-DCMAKE_BUILD_TYPE=Debug" else "-DCMAKE_BUILD_TYPE=Release")
(if sanitize then "-DSANITIZE=ON" else "-DSANITIZE=OFF")
"-DPARALLEL_CRYPTO3_ENABLE=TRUE"
];

doCheck = runTests; # tests are inside parallel-crypto3-tests derivation

checkPhase = ''
cd parallel-crypto3 && ctest --verbose --output-on-failure -R && cd ..
# JUNIT file without explicit file name is generated after the name of the master test suite inside `CMAKE_CURRENT_SOURCE_DIR`
export BOOST_TEST_LOGGER=JUNIT:HRF
cd parallel-crypto3
ctest --verbose --output-on-failure -R
cd ..
mkdir -p ${placeholder "out"}/test-logs
find .. -type f -name '*_test.xml' -exec cp {} ${placeholder "out"}/test-logs \;
'';

shellHook = ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
BOOST_AUTO_TEST_SUITE(thread_pool_test_suite)

BOOST_AUTO_TEST_CASE(vector_multiplication_test) {
boost::unit_test::unit_test_log_t::instance().set_threshold_level( boost::unit_test::log_messages );
//boost::unit_test::framework::instance().set_report_level(boost::unit_test::log_silent);
size_t size = 131072;

std::vector<size_t> v(size);
Expand All @@ -55,7 +57,7 @@ BOOST_AUTO_TEST_CASE(vector_multiplication_test) {
}, nil::crypto3::ThreadPool::PoolLevel::HIGH));

for (std::size_t i = 0; i < size; ++i) {
BOOST_CHECK(v[i] == i * i);
BOOST_CHECK_EQUAL(v[i], i * i);
}
}

Expand Down
42 changes: 42 additions & 0 deletions parse_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging, json
from junitparser import JUnitXml
import glob, os
from opentelemetry import trace

undefined_behavior_sanitizer=os.environ['UndefinedBehaviorSanitizer']
address_sanitizer=os.environ['AddressSanitizer']
leak_sanitizer=os.environ['LeakSanitizer']

aggregated_test_results = JUnitXml();
for file in glob.glob("result/test-logs/*.xml"):
try:
aggregated_test_results.append(JUnitXml.fromfile(file))
except Exception as ex:
print("Error processing {}".format(file))
print(ex)

succeeded = aggregated_test_results.tests - \
aggregated_test_results.failures - \
aggregated_test_results.errors - \
aggregated_test_results.skipped

result = {
"tests" : aggregated_test_results.tests,
"failures" : aggregated_test_results.failures,
"errors" : aggregated_test_results.errors,
"skipped" : aggregated_test_results.skipped,
"succeeded" : succeeded,
"execution_time" : aggregated_test_results.time,
"undefined_behavior_sanitizer" : int(undefined_behavior_sanitizer),
"address_sanitizer" : int(address_sanitizer),
"leak_sanitizer" : int(leak_sanitizer),
}

print("Resulting JSON: {}".format(json.dumps(result)))

tracer = trace.get_tracer_provider().get_tracer(__name__)
with tracer.start_as_current_span("nightly_span"):
current_span = trace.get_current_span()
current_span.add_event("Nightly build finished")
logging.getLogger().error(json.dumps(result))

6 changes: 5 additions & 1 deletion proof-producer.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
gtest,
enableDebug ? false,
runTests ? false,
sanitize? false,
}:
let
inherit (lib) optional;
Expand All @@ -34,6 +35,7 @@ in stdenv.mkDerivation {
"-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
(if enableDebug then "-DCMAKE_BUILD_TYPE=Debug" else "-DCMAKE_BUILD_TYPE=Release")
(if runTests then "-DENABLE_TESTS=ON" else "-DENABLE_TESTS=OFF")
(if sanitize then "-DSANITIZE=ON" else "-DSANITIZE=OFF")
"-DPROOF_PRODUCER_ENABLE=TRUE"
"-G Ninja"
];
Expand All @@ -43,7 +45,9 @@ in stdenv.mkDerivation {
checkPhase = ''
# JUNIT file without explicit file name is generated after the name of the master test suite inside `CMAKE_CURRENT_SOURCE_DIR`
export BOOST_TEST_LOGGER=JUNIT:HRF
cd proof-producer && ctest --verbose --output-on-failure -R && cd ..
cd proof-producer
ctest --verbose --output-on-failure -R
cd ..
mkdir -p ${placeholder "out"}/test-logs
find .. -type f -name '*_test.xml' -exec cp {} ${placeholder "out"}/test-logs \;
'';
Expand Down
14 changes: 14 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
requests==2.32.2
opentelemetry-distro[otlp]==0.45b0
opentelemetry-instrumentation-requests==0.45b0
opentelemetry-util-http==0.45b0
opentelemetry-instrumentation==0.45b0
opentelemetry-semantic-conventions==0.45b0
opentelemetry-instrumentation==0.45b0
opentelemetry-semantic-conventions==0.45b0
opentelemetry-util-http==0.45b0
opentelemetry-instrumentation==0.45b0
opentelemetry-semantic-conventions==0.45b0
opentelemetry-util-http==0.45b0
opentelemetry-sdk
junitparser==3.2.0
Loading
Loading