Skip to the content.

Testing and CI

The project verifies equivalent behavior at two levels:

  1. one shared set of domain cases executed by every language-specific runner
  2. one process-level parity suite that compares observable command-line behavior across Java, C++ and Python

Shared contract cases

The file tests/cases.tsv is the language-neutral source of truth.

It contains seven valid and twenty-three invalid IPv4/CIDR examples. Valid cases define the complete expected result. Invalid cases define the exact validation category and message.

The contract covers:

The oversized numeric cases prevent a parser difference: Java and C++ use fixed-width integers, while Python supports arbitrary-precision integers. Every implementation performs the same bounded decimal text comparison before conversion.

The combined-error cases verify that, after exactly one / separator is found, empty IPv4 and prefix components are checked before either component is parsed in detail.

Language-specific tests

Language Test runner Contract scope CLI smoke scope
Java 21 java/test/SubnetCalculatorTest.java Executes the command-line program and checks all shared result fields, errors and exit codes valid direct call, invalid direct call, help and incorrect usage
C++20 cpp/tests/subnet_test.cpp with CTest Calls the calculation module and checks every structured result field and exception message CMake script executes the built CLI for the same four modes
Python 3.12 python/test_subnet_calculator.py Uses unittest for every shared calculation and validation case subprocess checks for the same four modes

No external test framework is required.

Cross-language parity

tests/cross_language_parity.py executes the three real command-line implementations and records:

(return code, stdout bytes, stderr bytes)

The current parity suite contains nine direct cases and two interactive cases. It covers:

On Linux, all nine direct cases and both interactive cases require complete byte-for-byte equality across Java, C++ and Python.

On Windows, all ASCII-safe direct cases and both interactive cases also require complete byte-for-byte equality. The two non-ASCII command-line argument cases are checked semantically per implementation: identical exit code, identical error category, empty standard output and the expected direct-mode format hint. This boundary is explicit because the Windows Java launcher may replace a command-line character that is not representable in its native launcher encoding before main(String[]) receives the argument.

The C++ executable uses a wide-character Windows entry point and converts command-line arguments to UTF-8. The parity-only Java launcher configures UTF-8 standard streams. Child-process streams are captured as bytes so the test harness does not impose an incorrect decoder on platform-native output.

A failed parity run writes parity-diagnostics.txt. GitHub Actions uploads that file as a temporary diagnostic artifact on Windows failures; successful runs remove it.

Local commands

Java

javac -d java/out java/src/SubnetCalculator.java java/test/SubnetCalculatorTest.java java/test/Utf8JavaLauncher.java
java -cp java/out SubnetCalculatorTest tests/cases.tsv

C++

cmake -S cpp -B cpp/build -DBUILD_TESTING=ON
cmake --build cpp/build --config Release
ctest --test-dir cpp/build --build-config Release --output-on-failure

Python

python -m unittest discover -s python -p "test_*.py" -v

Cross-language parity

After Java and C++ have been built:

python tests/cross_language_parity.py

On Windows, py -3.12 can replace python.

GitHub Actions

The workflow under .github/workflows/ci.yml runs on pull requests, pushes to main and manual dispatches.

It exposes five independent checks:

The workflow uses read-only repository permissions, cancels superseded runs and applies a ten-minute timeout to every job. Keeping the checks separate makes failures easy to locate and verifies both the Linux toolchain and the Windows execution boundary.