The reference of competitive-verifier


Resolving dependencies

oj-resolve

oj-resolve subcommand reslove source code status by Online Judge Verification Helper.

Supported languages

Summary:

Language Available file extensions How to specify attributes Features (verify / bundle / doc) Example file
C++ .cpp .hpp // competitive-verifier: [KEY] [VALUE]
#define [KEY] [VALUE] (deprecated)
:heavy_check_mark: / :heavy_check_mark: / :heavy_check_mark: segment_tree.range_sum_query.cpp
Nim .nim # competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :heavy_check_mark: -
Python 3 .py # competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :heavy_check_mark: union_find.yosupo.py
Haskell .hs -- competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :warning: -
Ruby .rb # competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :warning: -
Go .go // competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :warning: helloworld_test.go
Java .java // competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :warning: HelloWorld_test.java
Rust .rs // competitive-verifier: [KEY] [VALUE] :heavy_check_mark: / :x: / :warning: itp1-1-a.rs

Settings for C++

You can specify compilers and options with writing config.toml as below. If there are no settings, oj-resolve automatically detects compilers (g++ and clang++ if exists) and use recommended options.

[[languages.cpp.environments]]
CXX = "g++"

[[languages.cpp.environments]]
CXX = "clang++"
CXXFLAGS = ["-std=c++17", "-Wall", "-g", "-fsanitize=undefined", "-D_GLIBCXX_DEBUG"]
  • If you use environments which ulimit doesn’t work on, and if you want to set CXXFLAGS by yourself, please be careful about the stack size.
  • The supported extensions are .cpp, .hpp, .cc, and .h. Please note that files with other extensions like .c .h++ and files without extensions are not recognized.

Settings for Nim

You can specify options and targets (e.g. c cpp) with writing config.toml as below. If there is no settings, oj-resolve automatically use recommended options similar to options on AtCoder.

[[languages.nim.environments]]
compile_to = "c"

[[languages.nim.environments]]
compile_to = "cpp"
NIMFLAGS = ["--warning:on", "--opt:none"]

Default

[[languages.nim.environments]]
compile_to = "cpp"
NIMFLAGS = ["-d:release", "--opt:speed"]

Settings for Python 3

There is no config now.

Settings for Rust

oj-verify uses root source files of binary targets or example targets (excluding targets which crate-type is specified) which have the PROBLEM attribute

You can customize the method to list depending files with languages.rust.list_dependencies_backend of config.toml.

  • kind = "none"

    This is the default behavoir. For each target, all .rs files in the target is treated as a block. The dependency relationship of files in each target are not analyzed.

    [languages.rust.list_dependencies_backend]
    kind = "none"
    
    • For a file which is a root source file of a target, the file depends all .rs files in its target and all depending local crates.
    • For a file which is not a root source file of any targets, the file depends all .rs files in its target.
  • kind = "cargo-udeps"

    This method is similar to kind = "none", but uses cargo-udeps in $PATH to narrow down dependencies. It computes the dependency relationship of files using the dependencies relationship between crates.

    [languages.rust.list_dependencies_backend]
    kind = "cargo-udeps"
    toolchain = "nightly-yyyy-mm-dd" # defaults to "nightly"
    

Settings for other languages

You can use languages other than above (e.g. AWK examples/awk/circle_test.awk). Please write commands to compile and execute in the config file config.toml (e.g. config.toml). execute field are required, and other fields are optional.

[languages.awk]
compile = "bash -c 'echo hello > {tempdir}/hello'"
execute = "env AWKPATH={basedir} awk -f {path}"
bundle = "false"
list_dependencies = "sed 's/^@include \"\\(.*\\)\"$/\\1/ ; t ; d' {path}"

Replacement

Config Actual
{basedir} The working directory.
{path} The relative path to {basedir} of the file to execute.
{dir} The relative path to {basedir} of the directory which contains file to execute.
{tempdir} The temporary directory.

Unit test settings

If you have unit tests, you can use UNITTEST attribute. helloworld_test.go

// competitive-verifier: UNITTEST GOTEST_RESULT

package main

import (
    "testing"
    "./helloworld"
)

func TestHelloWorld(t *testing.T) {
    want:= "Hello World"
    if got := helloworld.GetHelloWorld(); got != want {
        t.Errorf("helloworld.GetHelloWorld() = %v, want %v", got, want)
    }
}
      - name: go test
        id: go-unittest
        run: go test
        working-directory: examples/go
        continue-on-error: true
        env:
          GO111MODULE: "off"

      - name: oj-resolve
        uses: competitive-verifier/actions/oj-resolve@v2
        with:
          include: examples
          exclude: |
            src
            tests
          output-path: resolved.json
          config: examples/config.toml
        env:
          GOTEST_RESULT: ${{ steps.go-unittest.outcome == 'success' }}

specify in the unit test file executed by the main function

If you have unit tests executed by the main function like C++, you can use STANDALONE attribute. bit_minus_random_test.cpp

// competitive-verifier: STANDALONE
#include <iostream>
#include <cassert>
#include <random>
#include "examples/cpp/bit_minus.hpp"
using namespace std;

int main()
{
    mt19937 rnd(random_device{}());
    for (size_t i = 0; i < 100000; i++)
    {
        auto num = rnd();
        cout << num << " " << bit_minus(num) << endl;
        assert(-(int64_t)num == bit_minus(num));
    }
    return 0;
}

csharp-resolver: C# settings

Use https://github.com/competitive-verifier/csharp-resolver.

Automating the verification

Supported judging platforms

Name Remarks
Library Checker  
Aizu Online Judge  
yukicoder You must set the YUKICODER_TOKEN environment variable. See 「ログインしてないと使えない機能をAPIとして使いたい」 in ヘルプ - yukicoder and Creating and using encrypted secrets - GitHub Help.

Other judging platforms do not currently publish the test cases in usable forms, and so are not currently supported.

Available macro definitions

Macro name Description Remarks
PROBLEM specify the URL of the problem to submit  
LOCALCASE specify the path of the test cases  
ERROR specify the absolute or relative error to be considered as correct  
TLE specify the TLE time in seconds  
STANDALONE specify in the unit test file executed by the main function  
UNITTEST specify the environment variable which represents unit test status  
TITLE specify the title of source  
DISPLAY specify the document output mode visible, no-index, hidden, never

PROBLEM

By specifying the URL of a supported service, oj-resolve will collect this as a test executable file.

// competitive-verifier: PROBLEM https://judge.yosupo.jp/problem/aplusb
#include <iostream>
using namespace std;

int main()
{
    long a, b;
    cin >> a >> b;
    cout << a + b << endl;
    return 0;
}

LOCALCASE

By specifying a directory, oj-resolve will collect this as a test executable file.

// competitive-verifier: LOCALCASE ./local_aplusb_cases
#include <iostream>
using namespace std;

int main()
{
    long a, b;
    cin >> a >> b;
    cout << a + b << endl;
    return 0;
}

Each test case consists of an input file named {name}.in and an output file named {name}.out. Subdirectories are searched recursively 1.

ERROR, TLE

Specifies the tolerance and execution time limit values to be used when running PROBLEM or LOCALCASE.

STANDALONE

oj-resolve will collect this as a test executable file. Whether a test has succeeded is determined by checking if the exit status code is 0. This is useful in environments like C++, where unit tests are executed within the main function.

UNITTEST

When running oj-resolve, it is considered successful if the specified environment variable exists; otherwise, it is considered a failure.

This is useful in environments like Go, where unit tests are executed outside of the main function.

See: #unittest-settings

TITLE

Specify the title of source.

DISPLAY

Specify the document output mode.

  • visible (default): Generate and display the document.
  • no-index: Generate the document, but do not show it on the index page. It will still appear in dependency lists such as “Depends on”.
  • hidden: Generate the document, but do not show it on the index page or in dependency lists such as “Depends on”.
  • never: Do not generate the document.

Generating Documentation

Embedding Markdown to pages for source codes

Markdown files in the repository are automatically recognized. When the documentation_of field in Front Matter specifies a source code file, the content of Markdown file is inserted into the generated document page of specified code.

For example, to add description to a document of a file path/to/segment_tree.hpp, make a Markdown file like foo/bar.md and write as the following in the file.

---
title: Segment Tree
documentation_of: ./path/to/segment_tree.hpp
---

## Description

In this file, ...

The documentation_of accepts either a relative or an absolute path1.

Embedding Markdown to the top page

Please make the file .competitive-verifier/docs/index.md and write Markdown there.

Local execution

Executing following commands, you can see generated documents locally at http://localhost:4000/.

$ bundle config set --local path .vendor/bundle
$ bundle install
$ bundle exec jekyll serve

To do this, Ruby’s Bundler is required. If you are using Ubuntu, you can install this with sudo apt install ruby-bundler.

Others

  • The file .competitive-verifier/docs/_config.yml is copied into the target directory with some modification.
  • Files under the directory .competitive-verifier/docs/static/ are copied into the target directory directly.
  • For compatibility, you can use .verify-helper/ instead of .competitive-verifier/. (deprecated)

Footnote

  1. Strings starting with ./ or ../ are treated as paths relative to the current file. Strings starting with // are treated as paths relative to the project’s root directory. The path should use / as directory separator be case-sensitive.  2