gomcp/internal/transport/p2p/ws_transport_test.go

139 lines
3.5 KiB
Go

// Copyright 2026 Syntrex Lab. All rights reserved.
// Use of this source code is governed by an Apache-2.0 license
// that can be found in the LICENSE file.
package transport
import (
"context"
"encoding/json"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/syntrex-lab/gomcp/internal/domain/peer"
)
func TestWSTransport_StartStop(t *testing.T) {
reg := peer.NewRegistry("test-node", 5*time.Minute)
cfg := WSConfig{Port: 0, Host: "localhost", Enabled: true}
tr := NewWSTransport(cfg, reg)
// Port 0 → use default 9741, but we override with listener.
err := tr.Start()
require.NoError(t, err)
addr := tr.Addr()
assert.NotEmpty(t, addr)
err = tr.Stop()
assert.NoError(t, err)
}
func TestWSTransport_Ping(t *testing.T) {
reg := peer.NewRegistry("ping-node", 5*time.Minute)
cfg := WSConfig{Port: 0, Host: "localhost"}
tr := NewWSTransport(cfg, reg)
require.NoError(t, tr.Start())
defer tr.Stop()
ctx := context.Background()
peerID, err := tr.Ping(ctx, tr.Addr())
require.NoError(t, err)
assert.Equal(t, reg.SelfID(), peerID)
}
func TestWSTransport_SyncPayload(t *testing.T) {
reg := peer.NewRegistry("sync-node", 5*time.Minute)
cfg := WSConfig{Port: 0}
tr := NewWSTransport(cfg, reg)
done := make(chan peer.SyncPayload, 1)
tr.OnSync(func(p peer.SyncPayload) error {
done <- p
return nil
})
require.NoError(t, tr.Start())
defer tr.Stop()
payload := peer.SyncPayload{
FromPeerID: "remote-1",
GenomeHash: "abc123",
Facts: []peer.SyncFact{
{ID: "f1", Content: "test fact", Level: 0, IsGene: false},
},
SyncedAt: time.Now(),
}
ctx := context.Background()
err := tr.SendSync(ctx, tr.Addr(), payload)
require.NoError(t, err)
received := <-done
assert.Equal(t, "remote-1", received.FromPeerID)
assert.Equal(t, "abc123", received.GenomeHash)
assert.Len(t, received.Facts, 1)
assert.Equal(t, "test fact", received.Facts[0].Content)
}
func TestWSTransport_DeltaSync(t *testing.T) {
reg := peer.NewRegistry("delta-node", 5*time.Minute)
cfg := WSConfig{Port: 0}
tr := NewWSTransport(cfg, reg)
require.NoError(t, tr.Start())
defer tr.Stop()
ctx := context.Background()
req := peer.DeltaSyncRequest{
FromPeerID: reg.SelfID(),
GenomeHash: "test_hash",
Since: time.Now().Add(-1 * time.Hour),
MaxBatch: 10,
}
resp, err := tr.SendDeltaSync(ctx, tr.Addr(), req)
require.NoError(t, err)
assert.NotNil(t, resp)
assert.Equal(t, reg.SelfID(), resp.FromPeerID)
assert.False(t, resp.HasMore)
}
func TestFilterFactsSince(t *testing.T) {
now := time.Now()
facts := []peer.SyncFact{
{ID: "old", Content: "old fact", CreatedAt: now.Add(-2 * time.Hour)},
{ID: "new1", Content: "new fact 1", CreatedAt: now.Add(-30 * time.Minute)},
{ID: "new2", Content: "new fact 2", CreatedAt: now.Add(-10 * time.Minute)},
}
// Filter since 1 hour ago.
filtered, hasMore := peer.FilterFactsSince(facts, now.Add(-1*time.Hour), 100)
assert.Len(t, filtered, 2)
assert.False(t, hasMore)
assert.Equal(t, "new1", filtered[0].ID)
assert.Equal(t, "new2", filtered[1].ID)
// Filter with small batch.
filtered, hasMore = peer.FilterFactsSince(facts, now.Add(-1*time.Hour), 1)
assert.Len(t, filtered, 1)
assert.True(t, hasMore)
}
func TestMessage_JSON(t *testing.T) {
msg := Message{
Type: "ping",
From: "node-1",
SentAt: time.Now(),
}
data, err := json.Marshal(msg)
require.NoError(t, err)
var decoded Message
require.NoError(t, json.Unmarshal(data, &decoded))
assert.Equal(t, "ping", decoded.Type)
assert.Equal(t, "node-1", decoded.From)
}