This commit is contained in:
nnbcccscdscdsc
2026-03-23 20:18:53 +08:00
commit 4824675244
28 changed files with 5569 additions and 0 deletions

View File

@@ -0,0 +1,188 @@
//go:build linux
package peer
import (
"net"
"strings"
"sync"
"testing"
"omnisocketgo/cmd/internal/latencylog"
"omnisocketgo/cmd/internal/protocol"
"omnisocketgo/cmd/internal/server"
)
func TestClientsExchangeMessagesWithLinuxTimestamps(t *testing.T) {
hub := server.NewHub()
serverAddr, cleanup := startRealHubServer(t, hub)
defer cleanup()
peerALogger := &recordingLogger{}
peerA, err := Dial(serverAddr, "peer-a", WithLogger(peerALogger))
if err != nil {
t.Fatalf("Dial(peer-a) error = %v", err)
}
defer func() { _ = peerA.Close() }()
peerBLogger := &recordingLogger{}
peerB, err := Dial(serverAddr, "peer-b", WithLogger(peerBLogger))
if err != nil {
t.Fatalf("Dial(peer-b) error = %v", err)
}
defer func() { _ = peerB.Close() }()
inboxDir := t.TempDir()
waitFor(t, func() bool { return hub.HasPeer("peer-a") && hub.HasPeer("peer-b") }, "both peers to be registered")
if err := peerA.SendText("peer-b", "hello"); err != nil {
t.Fatalf("SendText() error = %v", err)
}
textMsg, err := peerB.Receive()
if err != nil {
t.Fatalf("peerB.Receive(text) error = %v", err)
}
if _, err := peerB.PersistMessage(textMsg, inboxDir); err != nil {
t.Fatalf("peerB.PersistMessage(text) error = %v", err)
}
if err := peerA.SendFile("peer-b", "payload.bin", []byte{0x01, 0x02, 0x03}); err != nil {
t.Fatalf("SendFile() error = %v", err)
}
fileMsg, err := peerB.Receive()
if err != nil {
t.Fatalf("peerB.Receive(file) error = %v", err)
}
if _, err := peerB.PersistMessage(fileMsg, inboxDir); err != nil {
t.Fatalf("peerB.PersistMessage(file) error = %v", err)
}
waitFor(t, func() bool { return hasMessageEvents(peerALogger.Events(), 1, latencylog.EventAAppPrepBegin, latencylog.EventATXSched, latencylog.EventATXSoftware) }, "peer-a text kernel timestamps")
waitFor(t, func() bool { return hasMessageEvents(peerALogger.Events(), 2, latencylog.EventAAppPrepBegin, latencylog.EventATXSched, latencylog.EventATXSoftware) }, "peer-a file kernel timestamps")
waitFor(t, func() bool { return hasMessageEvents(peerBLogger.Events(), 1, latencylog.EventBRXSoftware, latencylog.EventBAppRecv, latencylog.EventBPersistBegin, latencylog.EventBPersistEnd) }, "peer-b text receive timestamps")
waitFor(t, func() bool { return hasMessageEvents(peerBLogger.Events(), 2, latencylog.EventBRXSoftware, latencylog.EventBAppRecv, latencylog.EventBPersistBegin, latencylog.EventBPersistEnd) }, "peer-b file receive timestamps")
}
func startRealHubServer(t *testing.T, hub *server.Hub) (string, func()) {
t.Helper()
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("net.Listen() error = %v", err)
}
var (
wg sync.WaitGroup
stop = make(chan struct{})
errOnce sync.Once
)
wg.Add(1)
go func() {
defer wg.Done()
for {
conn, acceptErr := listener.Accept()
if acceptErr != nil {
select {
case <-stop:
return
default:
}
if strings.Contains(acceptErr.Error(), "closed") {
return
}
t.Errorf("listener.Accept() error = %v", acceptErr)
return
}
wg.Add(1)
go func(rawConn net.Conn) {
defer wg.Done()
if serveErr := hub.ServeConn(rawConn); serveErr != nil && !isExpectedHubServeExit(serveErr) {
errOnce.Do(func() {
t.Logf("hub.ServeConn() ended with %v", serveErr)
})
}
}(conn)
}
}()
cleanup := func() {
close(stop)
_ = listener.Close()
wg.Wait()
}
return listener.Addr().String(), cleanup
}
func hasMessageEvents(events []latencylog.Event, messageID uint64, wantEvents ...string) bool {
seen := make(map[string]bool, len(wantEvents))
for _, event := range events {
if event.MessageID != messageID {
continue
}
if event.TsUnixNano <= 0 {
return false
}
seen[event.Event] = true
}
for _, wantEvent := range wantEvents {
if !seen[wantEvent] {
return false
}
}
return true
}
func isExpectedHubServeExit(err error) bool {
if err == nil {
return true
}
message := err.Error()
return strings.Contains(message, "closed") || strings.Contains(message, "protocol: read frame: EOF")
}
func TestLinuxTimestampedReceivePreservesBusinessMessageShape(t *testing.T) {
hub := server.NewHub()
serverAddr, cleanup := startRealHubServer(t, hub)
defer cleanup()
peerA, err := Dial(serverAddr, "peer-a")
if err != nil {
t.Fatalf("Dial(peer-a) error = %v", err)
}
defer func() { _ = peerA.Close() }()
peerB, err := Dial(serverAddr, "peer-b")
if err != nil {
t.Fatalf("Dial(peer-b) error = %v", err)
}
defer func() { _ = peerB.Close() }()
waitFor(t, func() bool { return hub.HasPeer("peer-a") && hub.HasPeer("peer-b") }, "both peers to be registered")
want := protocol.Message{
Type: protocol.MessageTypeFile,
ID: 1,
From: "peer-a",
To: "peer-b",
FileName: "payload.bin",
Body: []byte{0xde, 0xad, 0xbe, 0xef},
}
if err := peerA.SendFile(want.To, want.FileName, want.Body); err != nil {
t.Fatalf("SendFile() error = %v", err)
}
got, err := peerB.Receive()
if err != nil {
t.Fatalf("peerB.Receive() error = %v", err)
}
if got.Type != want.Type || got.ID != want.ID || got.From != want.From || got.To != want.To || got.FileName != want.FileName || string(got.Body) != string(want.Body) {
t.Fatalf("received message mismatch: got %+v want %+v", got, want)
}
}