trainlog/docs/tests.md

4.5 KiB

Tests and Validation

1. Principle

A feature is not complete without relevant validation.

The exchange validator is executable specification during the format gates.

2. Canonical exchange validation

Run:

python tools/validate_json.py

The command validates:

  • examples/session-v1.json;
  • all tests/fixtures/valid/*.json as valid;
  • all tests/fixtures/invalid/*.json as invalid.

A negative fixture passes only when Trainlog rejects it.

3. Validation layers

A v1 document must pass:

  1. JSON Schema validation;
  2. Trainlog semantic validation.

Schema handles shape, enumerations, and primitive ranges.

Semantic validation handles cross-object and normalized rules.

4. Gate 1 semantic coverage

The canonical validator checks:

  • unique exercise_id;
  • normalized exercise-name uniqueness;
  • explicit timestamp offsets;
  • end time later than start time;
  • exact catalog/reference set equality;
  • one workout entry per exercise;
  • catalog tracking mode matching target;
  • catalog tracking mode matching actual sets;
  • load-mode/weight consistency;
  • non-blank notes.

5. Positive fixture coverage

Gate 1 includes:

  • mixed loaded repetition + timed session;
  • active session without ended_at;
  • planned exercise with zero actual sets;
  • bodyweight exercise with zero-repetition failed attempt;
  • assistance load;
  • completely interrupted session with zero exercises.

6. Negative fixture coverage

Gate 1 includes rejection of:

  • duplicate exercise IDs;
  • duplicate normalized exercise names;
  • duplicate workout exercise entries;
  • end timestamp before start;
  • missing timestamp offset;
  • target/actual tracking mismatch;
  • target containing both repetitions and duration;
  • unknown exercise reference;
  • unknown JSON field;
  • catalog tracking-mode mismatch;
  • load_mode=none carrying weight;
  • loaded target missing weight;
  • loaded actual set missing weight;
  • unreferenced catalog entries;
  • blank session notes;
  • blank exercise notes;
  • negative actual repetitions.

7. Gate 2 compiled validation

The normal Meson suite currently covers:

database
catalog
session_detail
duration
body_metrics
bodyviz
exercise_performance
session_type_schema
session_edit
body_observation_edit

The session-edit test verifies transactional child replacement without changing the parent session identity. The body-observation edit test verifies stable observation identity while metric values and notes are updated.

Schema validation includes the v1 -> v2 session_type migration.

8. C validation

Current pre-push validation includes:

  • normal strict-warning build;
  • the complete Meson test suite;
  • git diff --check;
  • frozen JSON v1 validators.

ASan/UBSan is run for meaningful implementation checkpoints before declaring a gate complete.

9. Pre-push checklist

Before every meaningful push:

  1. run python tools/validate_json.py;
  2. run python tools/validate_import_contract.py;
  3. run meson compile -C build;
  4. run meson test -C build --print-errorlogs;
  5. run sanitizers when relevant;
  6. run git diff --check;
  7. inspect git status --short;
  8. review documentation changes.

10. Catalog reconciliation contract

Before the C17 importer exists, Gate 1 defines local catalog merge behavior through an executable Python specification.

Run:

python tools/validate_import_contract.py

Canonical cases cover:

  • exact existing exercise reuse;
  • same identity with renamed display text;
  • same identity with incompatible tracking mode;
  • different identities with equivalent normalized names;
  • new unique exercise creation.

The full Gate 1 validation command is:

python tools/validate_json.py
python tools/validate_import_contract.py
git diff --check

11. USB/MTP transport validation

The compiled suite now contains:

usb
mtp

The usb test covers API validation, physical-device enumeration invariants, and rejection of duplicated USB interface children.

The mtp test covers bounded API argument validation for storage, folder, upload, listing, and download entry points.

Hardware probes additionally validate the real device path:

trainlog-usb-probe
trainlog-mtp-probe
trainlog-mtp-exchange-probe
trainlog-mtp-roundtrip-probe

Physical checkpoint result:

MTP devices: 1
ROUNDTRIP=PASS Trainlog/trainlog-probe.txt

The hardware probe is intentionally separate from the normal automated test suite because CI is not expected to have a connected unlocked Android MTP device.