Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
d860163
TTCN-3 test-execution runtime (interpreter + ntt exec) and ETSI confo…
rafael2knokia Jun 23, 2026
0d4c645
Scope unqualified getreply/catch to the enclosing call signature
rafael2knokia Jul 6, 2026
a936de5
Add opt-in real-scheduler mode for concurrent PTC send/receive loops
rafael2knokia Jul 6, 2026
640c29f
conformance: record match provenance and a real-execution metric
rafael2knokia Jul 7, 2026
c2eb656
conformance: SemanticsProfile umbrella + differential harness
rafael2knokia Jul 7, 2026
4656fa8
interpreter: strict-profile snapshot alt evaluator (no verdict heuris…
rafael2knokia Jul 7, 2026
efb92f0
interpreter: strict-profile connection-topology send routing
rafael2knokia Jul 7, 2026
07f889d
interpreter/conformance: cancellable execution (bound strict runs)
rafael2knokia Jul 7, 2026
0dbc599
interpreter: deterministic (virtual) clock for strict runs
rafael2knokia Jul 7, 2026
3b23eb2
interpreter: strict connection routing for procedure comm
rafael2knokia Jul 7, 2026
ab0f6fa
interpreter: run single-port finite responders at start under strict
rafael2knokia Jul 7, 2026
e828ad3
interpreter: strict procedure-payload matching (honour templates)
rafael2knokia Jul 7, 2026
7c6abfa
interpreter: strict routing for port-array connected endpoints
rafael2knokia Jul 8, 2026
0ddab65
interpreter: run concurrent PTCs for blocking procedure calls under s…
rafael2knokia Jul 9, 2026
5c22db7
interpreter: evaluate boolean guards in the strict alt snapshot
rafael2knokia Jul 10, 2026
e031d79
runtime: add discrete-event quiescence scheduler (unwired foundation)
rafael2knokia Jul 10, 2026
7123eb4
interpreter: wire the quiescence scheduler (gated off pending proc-re…
rafael2knokia Jul 10, 2026
424212a
interpreter: fix procedure-comm redirect + multi-client broadcast (st…
rafael2knokia Jul 10, 2026
612286e
runtime: replace the quiescence barrier with a deterministic cooperat…
rafael2knokia Jul 11, 2026
e78965a
Strict interleave: snapshot take-each-branch-once semantics
rafael2knokia Jul 14, 2026
ef0d812
Strict alt: advance deterministic clock for timers inside altstep guards
rafael2knokia Jul 14, 2026
a3eee4b
Strict: measure modelled PTC completion against the virtual clock
rafael2knokia Jul 14, 2026
ab785f1
Strict teardown: stop remaining PTCs before joining them
rafael2knokia Jul 14, 2026
bc89877
Coop scheduler: correct component lifecycle (blocking done, stoppable…
rafael2knokia Jul 15, 2026
3cf1b62
Enable the cooperative scheduler for strict execution
rafael2knokia Jul 15, 2026
c66e0b6
Coop fork model: fork all comm PTCs; match positional record template…
rafael2knokia Jul 15, 2026
3bf3fc7
exec: add --deterministic mode (opt-in discrete-event scheduler)
rafael2knokia Jul 16, 2026
cb90798
Strict: don't pre-populate sender redirect under the scheduler (C1)
rafael2knokia Jul 16, 2026
37e4616
Strict: model the blocking-call timeout as a virtual timer (C3)
rafael2knokia Jul 16, 2026
c0bc337
Strict: fan out any-port receive over the component's own ports
rafael2knokia Jul 16, 2026
8391c45
Strict: detect a fired default by an actual match, not a verdict change
rafael2knokia Jul 16, 2026
ba31744
Strict: T.running tracks the virtual clock, not just the wall clock
rafael2knokia Jul 17, 2026
8bd6c0e
Semantic: reject permutation() on a set-of target (ETSI B.1.3.3)
rafael2knokia Jul 17, 2026
ad72225
Semantic: resolve named signature templates in the Sig:tmplRef form
rafael2knokia Jul 17, 2026
7d250bf
Refresh conformance baseline: 97.26% -> 97.30% (4790 -> 4792)
rafael2knokia Jul 17, 2026
4c3459d
Strict: multicast call routing + selective deferred-responder replay
rafael2knokia Jul 17, 2026
2d7ff29
Make the strict discrete-event engine the default
rafael2knokia Jul 20, 2026
20d47ad
Strict: dynamic any-timer resolution + route direct altsteps to strict
rafael2knokia Jul 27, 2026
57c0bf9
Strict: run activated defaults on the strict evaluator (non-blocking)
rafael2knokia Jul 27, 2026
05383b6
Docs: refresh remaining-work for the strict engine
rafael2knokia Jul 28, 2026
c74cd66
Strict: interleave handles activated defaults; honour @nodefault
rafael2knokia Aug 3, 2026
e9b4134
Strict: gate altstep bodies on the profile, not the scheduler
rafael2knokia Aug 3, 2026
f921fdb
Strict: run blocking interleave bodies on the snapshot evaluator
rafael2knokia Aug 3, 2026
dc6848f
Make the strict profile the library default
rafael2knokia Aug 3, 2026
7d1d297
Remove the approximate engine's CLI surface
rafael2knokia Aug 3, 2026
c96c76f
Delete the approximate alt evaluator
rafael2knokia Aug 3, 2026
6b0013d
Delete the SemanticsProfile toggle
rafael2knokia Aug 3, 2026
6582c55
Docs: one engine, and an honest real-execution ceiling
rafael2knokia Aug 3, 2026
9aa7ede
Drop a test comment describing the removed RealScheduler option
rafael2knokia Aug 3, 2026
881f7ed
Execute the module control part as a program (ETSI 26)
rafael2knokia Aug 3, 2026
3fc6492
Value and template reference semantics (ETSI 6.2, 15.6.5, 15.11, 16.1.2)
rafael2knokia Aug 4, 2026
bb71b87
Enumerated values take precedence over a clashing local definition
rafael2knokia Aug 4, 2026
450ced9
Record why the undeclared-verdict coercion cannot be removed yet
rafael2knokia Aug 4, 2026
193667e
Implement the object cast and `of` type test (ETSI 5.1.2.5, 5.1.2.6)
rafael2knokia Aug 4, 2026
9766521
Defaults unwind their caller: stop, and break, in an altstep (ETSI 20…
rafael2knokia Aug 4, 2026
6df43e2
Bind external functions through a registry (ETSI 16.1.3)
rafael2knokia Aug 4, 2026
6031223
encvalue_o / decvalue_o for bitstrings, records and short input (Anne…
rafael2knokia Aug 4, 2026
7b673d4
Docs: the executed-but-wrong slice, and what it measured
rafael2knokia Aug 4, 2026
44f7d74
The baseline is a measurement, not a high-water mark
rafael2knokia Aug 10, 2026
13c20eb
A scheduler deadlock is an error, not a shrug (4813 -> 4769)
rafael2knokia Aug 10, 2026
d146a60
An undeclared verdict stays none (4769 -> 4744)
rafael2knokia Aug 10, 2026
f5101ec
Record why a stopped alive component cannot be restarted
rafael2knokia Aug 10, 2026
61aa7b5
Procedure responder bodies run for real (4744 -> 4747)
rafael2knokia Aug 10, 2026
305c328
Docs: what the conformance numbers evidence, and what they did not
rafael2knokia Aug 10, 2026
bee893c
An injected message reaches a driver-bound PTC
rafael2knokia Aug 18, 2026
82019c8
Real-clock t.read and exec --live for driving a live SUT
rafael2knokia Aug 19, 2026
51be360
A built-in TCP test port reaches a live endpoint over the network
rafael2knokia Aug 19, 2026
d8b4b64
An alt takes its snapshot, so a mid-round arrival can't jump the queue
rafael2knokia Aug 19, 2026
85ed13b
Performance profiling: per-port latency and throughput on a live run
rafael2knokia Aug 19, 2026
f34989d
Wire the built-in TCP port from a .cfg, no user Go code
rafael2knokia Aug 19, 2026
a1db11d
Docs: live testing and performance profiling
rafael2knokia Aug 19, 2026
918387a
TCP port: octetstring payloads over length-prefix framing
rafael2knokia Aug 20, 2026
dfc7b9b
interleave takes its snapshot too
rafael2knokia Aug 20, 2026
887a48b
Per-component TCP port addresses from a .cfg
rafael2knokia Aug 20, 2026
03397a2
all component.done blocks, so a PTC's verdict is not lost
rafael2knokia Aug 20, 2026
9d05328
Route proc/message `to <component>` to only the addressed component
rafael2knokia Aug 20, 2026
f504ce6
Docs: record the built-in TCP port, live exec and profiling in the ma…
rafael2knokia Aug 21, 2026
a7c9526
Add a CHANGELOG; credit the article that inspired live testing + prof…
rafael2knokia Aug 21, 2026
d8c817f
Docs: cite the ICT Express article in full
rafael2knokia Aug 21, 2026
58237d3
Make the boolean-guard alt test deterministic (fix a Windows CI flake)
rafael2knokia Aug 21, 2026
49163cd
A runnable live-testing example, and metrics in the HTML report
rafael2knokia Sep 8, 2026
5192e1d
ntt exec exits non-zero on a failing suite; fix invalid docs snippets
rafael2knokia Sep 8, 2026
672516a
Test per-component port addresses at cluster scale
rafael2knokia Sep 9, 2026
4539c0a
A built-in HTTP test port for driving a REST service under test
rafael2knokia Sep 9, 2026
c79b8d3
TLS and mutual TLS for the HTTP test port
rafael2knokia Sep 9, 2026
909a6bb
A value redirect initialises its target for the clause body
rafael2knokia Sep 9, 2026
39ce594
A transport failure is its own inbound type, with a matchable reason
rafael2knokia Sep 9, 2026
7de156c
Classify a dropped connection as `reset`; report every verdict's reason
rafael2knokia Sep 9, 2026
785205b
Classify Winsock errors: the Windows CI job was red
rafael2knokia Sep 9, 2026
d2d1693
A bare procedure guard respects the alt snapshot too
rafael2knokia Sep 9, 2026
6a7077e
Unit-test the transport classifier; fix the Windows unreachable phrasing
rafael2knokia Sep 9, 2026
3579d59
Docs: scope the decvalue gap, and why the port leaves JSON alone
rafael2knokia Sep 9, 2026
e3d9810
Docs: an ending is a value, not a silence
rafael2knokia Sep 9, 2026
1bf6016
Docs: record where we fail our own ending-is-a-value test
rafael2knokia Sep 9, 2026
3a86556
The TCP port reports a peer hang-up instead of going quiet
rafael2knokia Sep 9, 2026
2978736
Docs: list report_disconnect in the .cfg parameter table
rafael2knokia Sep 9, 2026
9093deb
Wait on an event, not a snapshot, in the per-component scale test
rafael2knokia Sep 9, 2026
c1c091e
Docs: warn that concurrent HTTP requests cannot be correlated
rafael2knokia Sep 10, 2026
63ce69c
An oversize response is reported, not silently truncated
rafael2knokia Sep 10, 2026
0a34687
Test that a TCP connection does not outlive its testcase
rafael2knokia Sep 10, 2026
fd9cb28
Wait on the close event in the lifetime test, not a sleep loop
rafael2knokia Sep 10, 2026
30cf716
Wait on an event in the per-component PTC test too
rafael2knokia Sep 10, 2026
104b0e4
Docs: correct three claims that no longer match the code
rafael2knokia Sep 14, 2026
da9efd0
Record: a PTC body that waits on a timer is skipped under --live
rafael2knokia Sep 14, 2026
d1e99ab
Fork a PTC on the real clock whenever its body does port communication
rafael2knokia Sep 14, 2026
abe3738
Correct the §1y attribution; record a lost-verdict gap under --live
rafael2knokia Sep 14, 2026
f2c777c
Make comp.done block on the real clock, so a PTC's verdict survives it
rafael2knokia Sep 14, 2026
062ff83
Ship a runnable HTTPS/JSON example
rafael2knokia Sep 14, 2026
b228da3
Honour `to <component>` on the real clock instead of broadcasting
rafael2knokia Sep 14, 2026
328df21
Don't require a positive minimum latency on a coarse clock
rafael2knokia Sep 14, 2026
d00c228
Detect a fired default, and answer comp.done as a value, on both clocks
rafael2knokia Sep 14, 2026
5ff3487
Restore a comment in the vendored corpus to its upstream wording
rafael2knokia Sep 15, 2026
6405254
Record which upstream revision the vendored corpus is
rafael2knokia Sep 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
47 changes: 45 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,33 @@ on:

jobs:
test:
# Run the same suite on Linux, macOS, and Windows. Windows uses
# backslash as its path separator and is case-insensitive for file
# names, both of which used to trip up path-handling tests until
# the cleanup tracked in issue #629.
name: Tests
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
# The TTCN-3 conformance test suite under
# testdata/ttcn3-conformance-tests/ has paths > 260 chars,
# which trips Windows' MAX_PATH limit during checkout. This
# config must run BEFORE actions/checkout so the clone itself
# can write the long paths.
- name: Enable Git long paths (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: git config --system core.longpaths true
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Test
run: go test -race -v ./...
run: go test -race ./...

lint:
name: Linting
Expand All @@ -31,3 +48,29 @@ jobs:
uses: golangci/golangci-lint-action@v6
with:
version: v1.60

conformance:
# The ntt-Titan roadmap makes the ETSI conformance pass-rate the
# always-on regression gate: a commit that drops the rate by more
# than --regress fails CI. The "real" gate measures verdicts: each
# file in the suite has an @verdict annotation; a file matches when
# the interpreter's actual outcome equals the annotation. The
# baseline lives in testdata/conformance-baseline.json and is
# refreshed whenever a milestone deliberately moves the rate up.
name: ETSI conformance pass-rate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: stable
- name: Build ntt
run: go build -o /tmp/ntt .
- name: Run conformance suite
run: |
/tmp/ntt conformance \
--baseline testdata/conformance-baseline.json \
--regress 0.5 \
--timeout 4s \
--jobs 4 \
testdata/ttcn3-conformance-tests
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@

# Build directory
bin/*
_output/

# Developer-local cabicgo build shim. The file links a developer's
# checkout of a downstream test-suite repo into a custom ntt binary;
# the path is hardcoded so the file is kept out of the main repo.
main_timesync_ports.go

# Test binary, build with `go test -c`
*.test
Expand All @@ -19,3 +25,7 @@ bin/*
# VS code
.vscode/*
.devcontainer/**

# CLI tooling artifacts
.antigravitycli/
cursor-context.txt
121 changes: 121 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Changelog

All notable changes to this project are documented here.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Releases before 0.24.0 predate this file; see the
[git tags](https://github.com/nokia/ntt/tags) and GitHub releases for their history.

## [0.24.0] - unreleased

Live testing and performance profiling: the same strict TTCN-3 engine can now
drive a real system under test over the network and measure how it behaves —
functional testing *and* profiling on one engine, with the deterministic
conformance path untouched. It realizes the approach from Peuster et al.,
["Joint testing and profiling of microservice-based network services using
TTCN-3"](https://doi.org/10.1016/j.icte.2019.02.001) (ICT Express, 2019): a
single functional test doubles as a performance probe. See
[docs/live-testing-and-profiling.md](docs/live-testing-and-profiling.md).

### Added

- **`ntt exec --live`** — run the strict engine on the real clock with real
concurrency, so timers pace real I/O against a live SUT. The virtual-clock
default (reproducible, deterministic) is unchanged; bound a live run with
`--timeout`.
- **Real-clock `t.read`** — measures actual wall-clock elapsed under `--live`,
so a testcase can time an operation (`t.start; <request/response>; t.read`).
Virtual-clock semantics (ETSI 23.4) are unchanged.
- **Built-in TCP test port** (`runtime/port/tcpport`) — bind a TTCN-3 message
port to a live TCP endpoint with no user C code and no cgo. Newline framing
(charstring) or length-prefix framing (octetstring, binary-safe). A peer
hang-up mid-test is reported rather than left as a silence a suite cannot
distinguish from a slow answer: always as a stderr warning, and — opt-in via
`report_disconnect` — as an inbound `Disconnected` value it can match on.
- **Config-driven test ports** — declare the TCP port in a `.cfg`
`[TESTPORT_PARAMETERS]` block (`transport := "tcp"`, `host`/`port` or
`address`, `dial_timeout`, `framing`); no Go code required. A `*`
(any-component) entry supplies defaults that a specific-component entry
inherits and overrides, so one port name can reach different SUTs on
different components.
- **Performance profiling** — `ntt exec --profile` captures per-port send /
receive counts, send→receive round-trip latency (min / p50 / p90 / p99) and
throughput. Report it as a table with `--format=profile`, as a metrics
section in `--format=json`, or as a **Performance profile** table in the
self-contained `--format=html` report (handy as a CI artefact).
- **Built-in HTTP test port** (`runtime/port/httpport`) — drive a REST service
with no user code: `map` binds a base URL, `p.send` issues the request, and
the response arrives at `p.receive` as a `{status, body}` record. Wired from
a `.cfg` with `transport := "http"`, supports per-component base URLs, and
surfaces a failed request as a separate `TransportError` inbound type with
a machine-matchable `reason` (`refused`, `unreachable`, `timeout`, `dns`,
`tls`, `other`, `reset`, `oversize`) plus a `detail` string for logging — so a suite can branch
on "the pod is restarting" versus "the pod is wedged" instead of
substring-matching an error message, and a failure is never a silent
timeout. A 4xx/5xx stays an ordinary response.
- **TLS and mutual TLS for the HTTP port** — an `https://` base URL verifies
against the system roots by default, or against a supplied `ca_cert`;
`client_cert` + `client_key` enable mTLS, and `server_name` overrides SNI
when dialling by IP. Certificate files are read at map time, so a bad path
fails the map operation naming the file. `insecure_skip_verify` is
supported for self-signed test endpoints and warns on stderr each run.
No gRPC.
- **Runnable example** — [`examples/live-testing/`](examples/live-testing/):
a TTCN-3 module plus `.cfg` that drive a real TCP SUT and report its
latency, with a copy-pasteable stand-in server. Exercised by CI so it
cannot rot.

### Changed

- **A `setverdict` reason is reported for every verdict, not just fail and
error.** `setverdict(inconc, "why")` lost its message even though CI counts
inconc as a failure, and `setverdict(pass, "label")` lost it too. The reason
is also no longer rendered as a quoted TTCN-3 literal, so a JUnit
`<failure message="...">` now reads as written.
- **`ntt exec` exits non-zero when the suite does not pass.** It previously
exited `0` even for a failing suite, so a CI pipeline treated red as green.
Severity follows the JUnit mapping already used by the reports: `inconc`,
`fail` and `error` exit non-zero; `pass` and `none` exit `0`. The report
itself is written first and is byte-identical — only the exit status
changed.
- **`all component.done` / `.killed` now block** (ETSI 21.3.7/21.3.8) instead
of answering a non-blocking snapshot, so a forked PTC's body actually runs
and its verdict is recorded — a failing PTC can no longer leave the testcase
`pass`. **On the default (virtual-clock, cooperative-scheduler) path only.**
Under `--live` the parking helper has no scheduler to park on, so `.done`
still answers a snapshot and a testcase that forks PTCs will not wait for
them; teardown then stops them, possibly before they have done anything.
Wait on an event instead — have each worker report over a connected port
and receive those reports. Tracked as
[remaining-work §1y](docs/conformance/remaining-work.md).
- Conformance baseline moved **4747 → 4754 (96.53%)**, net **+7 with zero
per-file regressions**. The baseline is a measurement, not a high-water
mark; the `--regress` gate is the ratchet.

### Fixed

- An injected message now reaches a **driver-bound PTC** — an external test
port's inbound traffic is delivered to a PTC's `receive`, not just the MTC's.
- **`alt` and `interleave` take a per-round snapshot** (ETSI 20.2): a message
arriving mid-evaluation can no longer let a later catch-all clause jump ahead
of an earlier, more specific one — the race a live socket exposed.
- **`p.send(...) to c`, `p.reply(...) to c` and `p.raise(...) to c`** unicast to
only the addressed component(s) instead of broadcasting to every connected
peer, so a sibling PTC no longer receives a value or catches an exception
meant for another.
- A **bare** `p.getreply` / `p.getcall` / `p.catch` guard reads the running
PTC's own per-component queue, so a reply/exception routed to it is no longer
invisible to the PTC's own `catch`.
- **Documentation defects found by running the docs through `ntt check`.**
The getting-started walkthrough used an invalid `package.yml` field
(`source_dir` instead of `sources`), a testcase with `runs on system`
(`system` is a keyword, not a component type), and showed `ntt exec` output
that the tool never produced; `cabi-ports.md` used the keyword `port` as a
record field name; and the `t.read` stopwatch snippet started a timer with
no default duration (invalid per ETSI 12). Every TTCN-3 snippet in the docs
now passes `ntt check`, and the walkthrough was replayed verbatim to confirm
its commands and output.

[0.24.0]: https://github.com/nokia/ntt/compare/v0.23.2...ntt-titan
Loading
Loading