Stress Testing is a tool for competitive programming and algorithm development. It checks your C++ solution against a brute-force solution on random tests, and stops at the first input where they disagree, crash, or run out of time.
- Modular C++ test generators for numbers, arrays, strings and graphs
- Clear reports for Wrong Answer, Time Limit Exceeded and Runtime Error, with the input, both outputs, stderr, the crash signal and the first differing line
- Every test has a seed, so a failing test can be replayed with
--seed --sanitizebuilds with AddressSanitizer and UBSan to catch overflow and out-of-bounds bugs--epsfor floating-point answers, and an optionalcpp/checker.cppfor problems with more than one valid answer- Recompiles only when a source file changes
- Cross-platform: macOS, Linux and Windows
- Python 3.9+
- GCC (
g++). The templates include<bits/stdc++.h>, which only GCC ships. Set theCXXenvironment variable to use another compiler. - CMake (optional, only for building inside an IDE)
-
macOS: Pre-installed, or install via Homebrew:
brew install python3
-
Linux (Debian/Ubuntu):
sudo apt update && sudo apt install python3 python3-pip -
Windows: Download Python and add it to PATH.
-
macOS: Apple's
g++is really Clang, so install GCC from Homebrew. The script picks the newestg++-<version>on your PATH.brew install gcc
-
Linux (Debian/Ubuntu):
sudo apt update && sudo apt install build-essential g++ -
Windows: Install MinGW-w64 or use WSL. MinGW has no sanitizers, so
--sanitizeneeds WSL.
-
macOS:
brew install cmake
-
Linux:
sudo apt install cmake
-
Windows: Download CMake and add it to PATH.
git clone https://github.com/7oSkaaa/stress_testing.git
cd stress_testingπ¦ Stress_Testing
βββ π CMakeLists.txt
βββ π README.md
βββ π stress_testing.py
βββ ποΈ cpp/
β βββ π correct.cpp
β βββ π generator.cpp
β βββ π test.cpp
β βββ π checker.cpp (optional)
β βββ ποΈ generators/
β βββ π generator_arrays.h
β βββ π generator_graphs.h
β βββ π generator_numbers.h
β βββ π generator_strings.h
β βββ π generator_utils.h
βββ ποΈ src/
β βββ π __init__.py
β βββ ποΈ utils/
β βββ π __init__.py
β βββ π cpp_compiler.py
β βββ π terminal_colors.py
βββ ποΈ bin/ (generated: compiled programs)
βββ ποΈ data/ (generated: the last failing test)
- Place your brute-force solution in
cpp/correct.cpp. - Place your optimized solution in
cpp/test.cpp. - Edit
cpp/generator.cppto generate tests with the generators fromcpp/generators/.
The script passes a seed as the generator's first argument. Seed the random engine from it, so the script can replay a failing test:
#include <bits/stdc++.h>
#include "generators/generator_numbers.h"
#include "generators/generator_arrays.h"
#include "generators/generator_strings.h"
#include "generators/generator_graphs.h"
#include "generators/generator_utils.h"
int main(int argc, char* argv[]) {
std::mt19937_64 rng(argc > 1 ? std::stoull(argv[1]) : std::chrono::steady_clock::now().time_since_epoch().count());
int n = gen_numbers::random<int>(5, 15, rng);
auto arr = gen_arrays::random<int>(n, 1, 100, rng);
gen_utils::print(arr);
auto s = gen_strings::random(n, gen_strings::CaseType::Lower, rng);
std::cout << s << '\n';
auto tree = gen_graphs::tree(n, rng);
gen_utils::print(tree);
return 0;
}Keep tests small. The brute force has to finish on every one of them.
python stress_testing.py --tests 100 --time 2--tests N: number of tests.0keeps running until a test fails. If you leave it out, the script asks.--time S: time limit fortest.cppin seconds. The generator and the brute force getmax(10, 5 Γ S)seconds, because they are allowed to be slow. If you leave it out, the script asks.--seed N: run only the test generated from seedN. A failure prints the full command for you.--eps E: accept numbers whose absolute or relative error is at mostE.--sanitize: build with-fsanitize=address,undefined. Programs run a few times slower, so raise--timeif needed. Memory leaks are not reported, since unfreed memory is normal in contest code. SetASAN_OPTIONSyourself to change that.
The programs compile with -std=c++17 -O2 into bin/. The script exits with code 0 when every test passes and 1 on a failure or a compile error.
While tests pass, a single line updates in place with the test count and the slowest test.cpp run so far. At the first failure the script prints:
- the status (
WRONG ANSWER,TIME LIMIT EXCEEDEDorRUNTIME ERROR), the program that failed, and how it ended: a signal such asSIGSEGVon Linux and macOS, or a crash name such asACCESS_VIOLATIONorSTACK_OVERFLOWon Windows - the input, the expected output and your output, with the first differing line highlighted
- the stderr of the program that failed
- the command that reruns this exact test
The failing test is also saved to data/input.txt, data/correct_output.txt and data/test_output.txt.
Colors turn off when the output is not a terminal or when the NO_COLOR environment variable is set. Set FORCE_COLOR to keep them in an IDE run window that shows colors but is not a terminal.
When cpp/checker.cpp exists, it decides each verdict instead of the token comparison. It is called with the same arguments as a testlib checker, so testlib checkers work unchanged:
checker <input file> <your output file> <expected output file>
Exit code 0 means accepted. Any other exit code is a Wrong Answer, and whatever the checker prints is shown as the reason. For example, this checker accepts any answer that is at least the expected one:
#include <bits/stdc++.h>
int main(int argc, char* argv[]) {
std::ifstream out(argv[2]), ans(argv[3]);
long double yours, expected;
if (!(out >> yours)) { std::cout << "no output"; return 1; }
ans >> expected;
if (yours < expected) { std::cout << std::fixed << "expected at least " << expected << ", got " << yours; return 1; }
return 0;
}cmake -S . -B build
cmake --build buildThis builds generator, test, correct and checker (if present) into build/ for use inside an IDE. The Python script does not use it.
CMake must use GCC, and stops with a message if the compiler has no <bits/stdc++.h>. CMake picks Apple Clang on macOS and Visual Studio on Windows by default, so choose GCC there. Delete build/ first if a previous configure used another compiler:
cmake -S . -B build -DCMAKE_CXX_COMPILER=g++-16 # macOS, use your Homebrew GCC version
cmake -S . -B build -G "MinGW Makefiles" # Windows with MinGWIn CLion, select a GCC toolchain under Settings, Build, Execution, Deployment, Toolchains.
random < T > (T l, T r, rng): Random integer in [l, r].random_range < T > (T l, T r, int count, rng): Vector of random integers in [l, r].random_exclude < T > (T l, T r, set < T > exclude, rng): Random integer in [l, r] not in exclude.random_range_exclude < T > (T l, T r, int count, set < T > exclude, rng): Vector of random integers not in exclude.random_weighted < T > (vector < T > values, vector < double > weights, rng): Random value from values with custom weights.random_real < T > (T l, T r, rng): Random floating-point in [l, r].random_real_exclude < T > (T l, T r, T excl_l, T excl_r, rng): Random real in [l, r] excluding [excl_l, excl_r].
random < T > (int len, T l, T r, rng, unique, sorted): Random array of length len in [l, r]. Withunique, len must be at most r - l + 1.permutation < T > (int n, rng): Random permutation of 1..n.matrix < T > (int rows, int cols, T l, T r, rng, unique_rows, sorted_rows): 2D array.pairs < T > (int len, T l1, T r1, T l2, T r2, rng, ordered): Vector of pairs.subset < T > (T l, T r, int k, rng, sorted): Unique subset of size k from [l, r].random_with_sum < T > (int len, T sum, T min_val, T max_val, rng): Random array with exactly the given sum, each element in [min_val, max_val].partition < T > (T sum, int k, T min_val, T max_val, rng): Same asrandom_with_sumwith the arguments in a different order.arithmetic_progression < T > (int len, T start, T step): Arithmetic progression.geometric_progression < T > (int len, T start, T ratio): Geometric progression.constant_array < T > (int len, T value): Array with all elements equal.bit_array < T > (int len, double prob_one, rng): Bit array (0/1) with probability for 1s.shuffled < T > (vector < T > v, rng): Shuffled copy of v.strictly_increasing < T > (int len, T start, T step_min, T step_max, rng): Strictly increasing array.strictly_decreasing < T > (int len, T start, T step_min, T step_max, rng): Strictly decreasing array.
random (int len, CaseType, rng, char l, char r): Random string of letters in [l, r], in the given case.palindrome (int len, CaseType, rng, char l, char r): Palindrome string.random_alphanum (int len, bool letters, bool digits, CaseType, rng): Alphanumeric string.random_custom (int len, string alphabet, rng): String from custom alphabet.random_strings (int count, int len, CaseType, rng): Vector of random strings.palindromes (int count, int len, CaseType, rng): Vector of palindromes.
Edge lists come out shuffled. Functions that cannot build the requested graph stop with a failed assert.
tree (int n, rng): Random tree (edges).simple_graph (int n, int m, rng): Connected graph without self-loops or multi-edges, n - 1 <= m <= n(n - 1)/2.weighted_graph (int n, int m, int min_w, int max_w, rng): Weightedsimple_graph.directed_graph (int n, int m, rng): Directed graph without self-loops or multi-edges.dag (int n, int m, rng): Directed acyclic graph.bipartite (int n1, int n2, int m, rng): Bipartite graph.star (int n, rng, int center): Star graph.cycle (int n, rng): Cycle graph, n >= 3.complete (int n): Complete graph.regular (int n, int d, rng): Random simple d-regular graph, for any d < n with nΒ·d even.tree_with_diameter (int n, int diameter, rng): Tree with exactly the given diameter (capped at n - 1).chain_tree (int n): Chain tree (path).
print (const vector < T > &v): Print vector.print (const vector < pair < T, U > > &v): Print vector of pairs.print (const vector < vector < T > > &mat): Print 2D vector.print (const vector < tuple < Args... > > &v): Print vector of tuples.print (const T &val): Print single value.print (const vector < string > &v): Print vector of strings.
- Set the compiler with the
CXXenvironment variable. Otherwise the script usesg++, or on macOS the newestg++-<version>it finds. - The project is modular and easy to extend for your own needs.