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>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user