Files
mdg-filius/packages/core/test/scenarios/tcp-routed-loss.scenario.json
julian.kiedaischandClaude Opus 5.5 12849b1535 feat(core): TCP in the simulation core
engine.ts ports Swift's "Java-compatible TCP sockets" in one piece, since
half a state machine could not be checked: server and client sockets (a
free port from Java's random numbers on their own seed), the three-way
handshake with its result (connected, invalid socket, unreachable, timed
out), segments of 1460 bytes, messages up to the push, a timeout of
3 × 2.5 s with at most three attempts, closing through every Java state
including TIME_WAIT (2.5 s), sequence numbers modulo 2^32.

Three scenarios match the Swift engine trace for trace: a LAN with data
over three segments, closing from both ends, a closed port and an
unreachable host; two networks through a router with a firewall rule,
data lost until the connection closes, and an accepted socket that does
not hold the port of its closed listener; CLOSING, reached by a lost FIN.
The engine delivers a FIN within the same close, so both ends close at
once only with packet loss; an empty message does not arrive in Swift (it
does not advance the sequence number), nor here.

Swift's four TCP engine tests are ported, with tests for stopping, a
foreign SYN+ACK at a listener and the flag names. 17 mutation probes, 16
caught; the other (delivered, not waited, not connected gives unreachable)
cannot be reached through Swift's engine, which never sends a reset and
always acknowledges correctly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:03:16 +00:00

167 lines
3.8 KiB
JSON

{
"seed": 32,
"nodes": [
{
"id": "00000000-0000-0000-0000-000000000201",
"kind": "pc",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000211",
"label": "eth0"
}
]
},
{
"id": "00000000-0000-0000-0000-000000000202",
"kind": "router",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000221",
"label": "rt1"
},
{
"id": "00000000-0000-0000-0000-000000000222",
"label": "rt2"
}
]
},
{
"id": "00000000-0000-0000-0000-000000000203",
"kind": "pc",
"ports": [
{
"id": "00000000-0000-0000-0000-000000000213",
"label": "eth0"
}
]
}
],
"links": [
{
"id": "00000000-0000-0000-0000-00000000F004",
"sourceNode": "00000000-0000-0000-0000-000000000201",
"sourcePort": "00000000-0000-0000-0000-000000000211",
"targetNode": "00000000-0000-0000-0000-000000000202",
"targetPort": "00000000-0000-0000-0000-000000000221"
},
{
"id": "00000000-0000-0000-0000-00000000F005",
"sourceNode": "00000000-0000-0000-0000-000000000202",
"sourcePort": "00000000-0000-0000-0000-000000000222",
"targetNode": "00000000-0000-0000-0000-000000000203",
"targetPort": "00000000-0000-0000-0000-000000000213"
}
],
"devices": {
"00000000-0000-0000-0000-000000000201": {
"ip": "10.0.0.2",
"mask": "255.255.255.0",
"gateway": "10.0.0.1"
},
"00000000-0000-0000-0000-000000000202": {
"ip": "10.0.0.1",
"mask": "255.255.255.0"
},
"00000000-0000-0000-0000-000000000203": {
"ip": "20.0.0.2",
"mask": "255.255.255.0",
"gateway": "20.0.0.1"
}
},
"interfaces": [
{
"node": "00000000-0000-0000-0000-000000000202",
"port": "00000000-0000-0000-0000-000000000221",
"ip": "10.0.0.1",
"mask": "255.255.255.0"
},
{
"node": "00000000-0000-0000-0000-000000000202",
"port": "00000000-0000-0000-0000-000000000222",
"ip": "20.0.0.1",
"mask": "255.255.255.0"
}
],
"steps": [
{
"op": "openTcpServer",
"node": "00000000-0000-0000-0000-000000000203",
"port": 80
},
{
"op": "openTcpServer",
"node": "00000000-0000-0000-0000-000000000203",
"port": 81
},
{
"op": "openTcpClient",
"node": "00000000-0000-0000-0000-000000000201",
"target": "20.0.0.2",
"port": 80
},
{
"op": "connectTcp",
"socket": "00000000-0000-0000-0000-000000000003"
},
{
"op": "sendTcp",
"socket": "00000000-0000-0000-0000-000000000003",
"payload": "durch den Router"
},
{
"op": "receiveTcp",
"socket": "00000000-0000-0000-0000-000000000004"
},
{
"op": "openTcpClient",
"node": "00000000-0000-0000-0000-000000000201",
"target": "20.0.0.2",
"port": 81
},
{
"op": "connectTcp",
"socket": "00000000-0000-0000-0000-000000000005"
},
{
"op": "packetLoss",
"enabled": true
},
{
"op": "sendTcp",
"socket": "00000000-0000-0000-0000-000000000003",
"payload": "verloren"
},
{
"op": "packetLoss",
"enabled": false
},
{
"op": "sendTcp",
"socket": "00000000-0000-0000-0000-000000000003",
"payload": "zu spaet"
},
{
"op": "closeSocket",
"socket": "00000000-0000-0000-0000-000000000001"
},
{
"op": "openTcpServer",
"node": "00000000-0000-0000-0000-000000000203",
"port": 80
}
],
"firewalls": {
"00000000-0000-0000-0000-000000000202": {
"active": true,
"defaultPolicy": "accept",
"rules": [
{
"protocol": "tcp",
"port": 81,
"action": "drop"
}
]
}
}
}