This project provides a set of tools for testing the correctness of solutions in coding competitions. Because scripts are all command-line interface (CLI), the project is independent of text editors/ IDEs. vscode and nvim are the recommended text editors.
This project is in the early stage of development, so there is a lot of room for improvement. Nevertheless, it is mature enough for casual coding competition.
- Clone the repo, run
nix build, then run./install.sh. - Create your workspace directory with sub directories:
- task
- archive
- output
- Create new task and solve problem
You can also run cpcli directly from the checkout without installing it:
nix run . -- --project-config=/path/to/project_config.toml --helpThis file should be named project_config.toml and placed directly at the top level of your workspace folder. root is optional; when omitted, cpcli uses the directory containing project_config.toml. ~ and relative paths are supported.
task_editor_exec = "cpcli_editor"
use_template_engine = false
[language_config]
default = "cpp"
[language_config.override]
[language_config.cpp]
compiler = "g++"
regular_flag = "-DLOCAL -O2 -std=c++17"
debug_flag = "-DLOCAL -Wall -Wshadow -std=c++17 -g -fsanitize=address -fsanitize=undefined -D_GLIBCXX_DEBUG"
use_precompiled_header = false
use_cache = true
include_dir = "include"
[language_config.cu]
compiler = "cpcli_cuda_compile"
runtime = "cpcli_cuda_run"
regular_flag = "-std=c++17 -O2 -lineinfo -Wno-deprecated-gpu-targets -gencode arch=compute_70,code=compute_70"
debug_flag = "-std=c++17 -O0 -g -lineinfo -Wno-deprecated-gpu-targets -gencode arch=compute_70,code=compute_70"
[language_config.py]
interpreter = "python3"CUDA tasks use solution.cu. When runtime is set, cpcli compiles a
solution.cuda-bin and creates ./solution as a launcher that passes the CUDA
binary to that runtime. This allows simulator or container backends without
changing the task runner.
The bundled cpcli_cuda_setup command extracts the matching CUDA headers and
libdevice into ~/.cache/cpcli/cuda-toolkit-12.8 for clangd/editor support.
<your workspace>
├── archive
│ ├── Archive
│ ├── AtCoder - ACL Beginner Contest
│ ├── TopCoder SRM #456
│ ├── Topcoder - TCO 2021 Regional Qualifier 1 DIV 1
│ ├── Topcoder 2021 Round 1B
│ ├── Topcoder Open Algo 2019
│ ├── Unsorted
│ └── vnoi.info
├── include
│ ├── genlib.hpp
│ ├── interactive.hpp
│ └── testlib.h
├── output
│ └── solution.cpp
├── project_config.toml
├── task
│ └── F - Keep Connect
│ ├── config.toml
│ └── solution.cpp
└── template
├── checker.template
├── gen.template
├── interactor.template
└── solution.template
Please take a look at the archive folder for more information.
$ cpcli_app --project-config=project_config.toml task --root-dir="/Users/cunbidun/competitive_programming/task/F - Keep Connect" --build| Num | Attribute | Type | Description | Default value |
|---|---|---|---|---|
| 1 | task_dir |
string |
Directory for storing current task | |
| 2 | output_dir |
string |
Compiled solution will be copy to this directory (so you know where to look for file for submission) | "" |
| 3 | template_dir |
string |
Directory for storing template (check the repo template folder for more info) |
"" |
| 4 | archive_dir |
string |
Directory for archiving completed task (check the repo archive folder for more info) |
"" |
| 6 | include_dir |
string |
Store libs here | |
| 5 | task_editor_exec |
string |
Executable frontend to edit task config.toml or config.json |
cpcli_editor |
| 7 | cpp_compile_flag |
string |
Cpp normal complier flag | "-DLOCAL -static -O2 -std=c++17" |
| 8 | cpp_debug_flag |
string |
Cpp debug flag | "-DLOCAL -Wall -Wshadow -std=c++17 -g -fsanitize=address -fsanitize=undefined -D_GLIBCXX_DEBUG" |
| 9 | use_precompiled_header |
bool |
use precompiled headers | true |
| 10 | use_cache |
bool |
Enable cache | true |
New task configs are written as config.toml. Existing flat config.json and old flat TOML keys are still accepted, but saving through the task editor writes the new sectioned TOML shape.
tests = [
{ enabled = true, has_expected_output = true, input = "1\n", output = "1\n" },
]
[problem]
name = "E. Trees of Tranquillity"
group = "Codeforces - Codeforces Round #722 (Div. 2)"
url = "https://codeforces.com/contest/1529/problem/E"
[run]
time_limit_ms = 3000
checker = "custom"
interactive = false
stop_on_first_failure = false
[display]
hide_accepted_tests = false
truncate_long_output = false
[generation]
enabled = true
test_count = 10
seed = ""
args = ""
expected_output_from_slow = trueCanonical task config keys:
| Attribute | Type | Description | Default value |
|---|---|---|---|
problem.name |
string |
Problem name or id. | "" |
problem.group |
string |
Contest/group name used for archive. | "" |
problem.url |
string |
Problem URL. | unset |
run.time_limit_ms |
int |
Time limit in milliseconds. | 10000 |
run.checker |
string |
Checker name. | token_checker |
run.interactive |
boolean |
Whether the task is interactive. | false |
run.stop_on_first_failure |
boolean |
Stop after WA, RTE, or TLE. | false |
display.hide_accepted_tests |
boolean |
Hide accepted test details. | true |
display.truncate_long_output |
boolean |
Truncate long input/output when printing. | false |
generation.enabled |
boolean |
Enable generated tests. | false |
generation.test_count |
int |
Number of generated tests. | 0 |
generation.seed |
string |
Generator seed. If empty, cpcli creates one. | "" |
generation.args |
string |
Extra arguments passed to gen after seed and count. |
"" |
generation.expected_output_from_slow |
boolean |
Use slow to produce expected output for generated tests. |
false |
tests[].enabled |
boolean |
Whether this sample test runs. | true |
tests[].has_expected_output |
boolean |
Whether output should be checked. |
derived from output |
tests[].input |
string |
Test input. | required |
tests[].output |
string |
Expected output. | optional |
Others checker included:
double_4: checking up to 4 decimals digitdouble_6: checking up to 6 decimals digitdouble_9: checking up to 9 decimals digittoken_checker: compare output files token by tokencustom: user's custom checker
The recommend text editor for developing this project is vscode
-
Enter the development environment and configure the project:
nix develop cmake -S . -B build -G Ninja -DBUILD_TESTING=ON -
Build the project. CMake writes
build/compile_commands.jsonfor editor tooling.cmake --build build
-
Run the tests:
ctest --test-dir build --output-on-failure
-
.vscodesetupCreate a
.vscodeat the top level directory of the repository.vscode ├── c_cpp_properties.json └── settings.jsonc_cpp_properties.jsoncontent:{ "configurations": [ { "name": "cpcli_app", "compileCommands": "${workspaceFolder}/build/compile_commands.json" } ], "version": 4 }
nix build
./install.sh
result/share/cpcli/task-editor/task-editor --root ~/competitive_programming/task/<task>cmake -S . -B build -G Ninja -DBUILD_TESTING=ON
cmake --build build
ctest --test-dir build --output-on-failureBuild with coverage instrumentation, then run the tests and generate the report:
cmake -S . -B build-coverage -G Ninja -DBUILD_TESTING=ON \
-DCMAKE_CXX_FLAGS="--coverage" -DCMAKE_EXE_LINKER_FLAGS="--coverage"
cmake --build build-coverage
ctest --test-dir build-coverage
lcov --capture --directory build-coverage --output-file coverage.info
genhtml coverage.info --output-directory coverage
open coverage/index.htmlMake sure to have sphinx and sphinx-rtd-theme installed
$ pip install -U sphinx sphinx-rtd-theme$ cd docs
$ make clean html
$ open build/html/index.html-
The project is heavily inspired by Egor Kulikov's idea-chelper.
-
Checkers and generators use Mike Mirzayanov's testlib
-
The precompiled header feature is inspired by Dushyant Singh's script Speed-Up-GCC-Compile-Time.