157 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package dht
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	libp2p "github.com/libp2p/go-libp2p"
 | |
| 	dhtmode "github.com/libp2p/go-libp2p-kad-dht"
 | |
| 	"github.com/libp2p/go-libp2p/core/test"
 | |
| )
 | |
| 
 | |
| type harness struct {
 | |
| 	ctx  context.Context
 | |
| 	host libp2pHost
 | |
| 	dht  *LibP2PDHT
 | |
| }
 | |
| 
 | |
| type libp2pHost interface {
 | |
| 	Close() error
 | |
| }
 | |
| 
 | |
| func newHarness(t *testing.T, opts ...Option) *harness {
 | |
| 	t.Helper()
 | |
| 
 | |
| 	ctx, cancel := context.WithCancel(context.Background())
 | |
| 
 | |
| 	host, err := libp2p.New(libp2p.ListenAddrStrings("/ip4/127.0.0.1/tcp/0"))
 | |
| 	if err != nil {
 | |
| 		cancel()
 | |
| 		t.Fatalf("failed to create libp2p host: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	options := append([]Option{WithAutoBootstrap(false)}, opts...)
 | |
| 	d, err := NewLibP2PDHT(ctx, host, options...)
 | |
| 	if err != nil {
 | |
| 		host.Close()
 | |
| 		cancel()
 | |
| 		t.Fatalf("failed to create DHT: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	t.Cleanup(func() {
 | |
| 		d.Close()
 | |
| 		host.Close()
 | |
| 		cancel()
 | |
| 	})
 | |
| 
 | |
| 	return &harness{ctx: ctx, host: host, dht: d}
 | |
| }
 | |
| 
 | |
| func TestDefaultConfig(t *testing.T) {
 | |
| 	cfg := DefaultConfig()
 | |
| 
 | |
| 	if cfg.ProtocolPrefix != "/CHORUS" {
 | |
| 		t.Fatalf("expected protocol prefix '/CHORUS', got %s", cfg.ProtocolPrefix)
 | |
| 	}
 | |
| 
 | |
| 	if cfg.BootstrapTimeout != 30*time.Second {
 | |
| 		t.Fatalf("expected bootstrap timeout 30s, got %v", cfg.BootstrapTimeout)
 | |
| 	}
 | |
| 
 | |
| 	if cfg.Mode != dhtmode.ModeAuto {
 | |
| 		t.Fatalf("expected mode auto, got %v", cfg.Mode)
 | |
| 	}
 | |
| 
 | |
| 	if !cfg.AutoBootstrap {
 | |
| 		t.Fatal("expected auto bootstrap to be enabled")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestWithOptionsOverridesDefaults(t *testing.T) {
 | |
| 	h := newHarness(t,
 | |
| 		WithProtocolPrefix("/custom"),
 | |
| 		WithDiscoveryInterval(2*time.Minute),
 | |
| 		WithBootstrapTimeout(45*time.Second),
 | |
| 		WithMode(dhtmode.ModeClient),
 | |
| 		WithAutoBootstrap(true),
 | |
| 	)
 | |
| 
 | |
| 	cfg := h.dht.config
 | |
| 
 | |
| 	if cfg.ProtocolPrefix != "/custom" {
 | |
| 		t.Fatalf("expected protocol prefix '/custom', got %s", cfg.ProtocolPrefix)
 | |
| 	}
 | |
| 
 | |
| 	if cfg.DiscoveryInterval != 2*time.Minute {
 | |
| 		t.Fatalf("expected discovery interval 2m, got %v", cfg.DiscoveryInterval)
 | |
| 	}
 | |
| 
 | |
| 	if cfg.BootstrapTimeout != 45*time.Second {
 | |
| 		t.Fatalf("expected bootstrap timeout 45s, got %v", cfg.BootstrapTimeout)
 | |
| 	}
 | |
| 
 | |
| 	if cfg.Mode != dhtmode.ModeClient {
 | |
| 		t.Fatalf("expected mode client, got %v", cfg.Mode)
 | |
| 	}
 | |
| 
 | |
| 	if !cfg.AutoBootstrap {
 | |
| 		t.Fatal("expected auto bootstrap to remain enabled")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestProvideRequiresBootstrap(t *testing.T) {
 | |
| 	h := newHarness(t)
 | |
| 
 | |
| 	err := h.dht.Provide(h.ctx, "key")
 | |
| 	if err == nil {
 | |
| 		t.Fatal("expected Provide to fail when not bootstrapped")
 | |
| 	}
 | |
| 
 | |
| 	if !strings.Contains(err.Error(), "not bootstrapped") {
 | |
| 		t.Fatalf("expected error to indicate bootstrap requirement, got %v", err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestRegisterPeer(t *testing.T) {
 | |
| 	h := newHarness(t)
 | |
| 
 | |
| 	peerID := test.RandPeerIDFatal(t)
 | |
| 
 | |
| 	h.dht.RegisterPeer(peerID, "apollo", "platform", []string{"go"})
 | |
| 
 | |
| 	peers := h.dht.GetKnownPeers()
 | |
| 
 | |
| 	info, ok := peers[peerID]
 | |
| 	if !ok {
 | |
| 		t.Fatalf("expected peer to be tracked")
 | |
| 	}
 | |
| 
 | |
| 	if info.Agent != "apollo" {
 | |
| 		t.Fatalf("expected agent apollo, got %s", info.Agent)
 | |
| 	}
 | |
| 
 | |
| 	if info.Role != "platform" {
 | |
| 		t.Fatalf("expected role platform, got %s", info.Role)
 | |
| 	}
 | |
| 
 | |
| 	if len(info.Capabilities) != 1 || info.Capabilities[0] != "go" {
 | |
| 		t.Fatalf("expected capability go, got %v", info.Capabilities)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestGetStatsProvidesUptime(t *testing.T) {
 | |
| 	h := newHarness(t)
 | |
| 
 | |
| 	stats := h.dht.GetStats()
 | |
| 
 | |
| 	if stats.TotalPeers != 0 {
 | |
| 		t.Fatalf("expected zero peers, got %d", stats.TotalPeers)
 | |
| 	}
 | |
| 
 | |
| 	if stats.Uptime < 0 {
 | |
| 		t.Fatalf("expected non-negative uptime, got %v", stats.Uptime)
 | |
| 	}
 | |
| }
 | 
