bbe88b0f70
Idle → Starting → Active → Failed lifecycle. bringUp resolves upstream IP, installs the driver (idempotent), runs initial procscan, opens redirector listener, builds filter + opens WinDivert handle, then spawns the diverter reader and 2-second procscan ticker. On every outbound TCP packet from a target PID: record (src_port → real_target) mapping, rewrite dst to 127.0.0.1:listener_port, re-inject. Loopback listener picks up the connection, looks up the original target, and SOCKS5-tunnels. P2.1 scope: no Reconnecting state, no panic recovery, no UDP forwarding. Those land in P2.2/P2.3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
31 lines
755 B
Go
31 lines
755 B
Go
package engine
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestStatusTransitions_Valid(t *testing.T) {
|
|
cases := []struct {
|
|
from Status
|
|
to Status
|
|
ok bool
|
|
}{
|
|
{StatusIdle, StatusStarting, true},
|
|
{StatusStarting, StatusActive, true},
|
|
{StatusStarting, StatusFailed, true},
|
|
{StatusActive, StatusIdle, true}, // user clicked Stop
|
|
{StatusActive, StatusFailed, true}, // crash
|
|
{StatusFailed, StatusStarting, true}, // user clicked Retry
|
|
// Invalid transitions
|
|
{StatusIdle, StatusActive, false},
|
|
{StatusIdle, StatusFailed, false},
|
|
{StatusActive, StatusStarting, false},
|
|
}
|
|
for _, c := range cases {
|
|
got := isValidTransition(c.from, c.to)
|
|
assert.Equalf(t, c.ok, got, "%s → %s", c.from, c.to)
|
|
}
|
|
}
|