package link import ( "bytes" "testing" "time" "git.quad4.io/Networks/Reticulum-Go/pkg/common" "git.quad4.io/Networks/Reticulum-Go/pkg/destination" "git.quad4.io/Networks/Reticulum-Go/pkg/identity" "git.quad4.io/Networks/Reticulum-Go/pkg/packet" ) type mockTransport struct { sentPackets []*packet.Packet } func (m *mockTransport) SendPacket(pkt *packet.Packet) error { m.sentPackets = append(m.sentPackets, pkt) return nil } func (m *mockTransport) RegisterLink(linkID []byte, link interface{}) { } func (m *mockTransport) GetConfig() *common.ReticulumConfig { return &common.ReticulumConfig{} } func (m *mockTransport) GetInterfaces() map[string]common.NetworkInterface { return make(map[string]common.NetworkInterface) } func (m *mockTransport) RegisterDestination(hash []byte, dest interface{}) { } type mockInterface struct { name string } func (m *mockInterface) GetName() string { return m.name } func (m *mockInterface) Start() error { return nil } func (m *mockInterface) Stop() error { return nil } func (m *mockInterface) Send(data []byte, address string) error { return nil } func (m *mockInterface) ProcessIncoming(data []byte) error { return nil } func (m *mockInterface) SetPacketCallback(cb func([]byte, common.NetworkInterface)) { } func (m *mockInterface) GetType() string { return "mock" } func (m *mockInterface) GetMTU() int { return 500 } func (m *mockInterface) Detach() { } func (m *mockInterface) Enable() { } func (m *mockInterface) Disable() { } func (m *mockInterface) IsEnabled() bool { return true } func (m *mockInterface) IsOnline() bool { return true } func (m *mockInterface) IsDetached() bool { return false } func (m *mockInterface) GetPacketCallback() func([]byte, common.NetworkInterface) { return nil } func (m *mockInterface) GetConn() interface{} { return nil } func (m *mockInterface) ProcessOutgoing(data []byte) ([]byte, error) { return data, nil } func (m *mockInterface) SendPathRequest(destHash []byte) error { return nil } func (m *mockInterface) SendLinkPacket(data []byte) error { return nil } func (m *mockInterface) GetBandwidthAvailable() float64 { return 1.0 } func TestLinkRequestResponse(t *testing.T) { serverIdent, err := identity.New() if err != nil { t.Fatalf("Failed to create server identity: %v", err) } clientIdent, err := identity.New() if err != nil { t.Fatalf("Failed to create client identity: %v", err) } mockTrans := &mockTransport{ sentPackets: make([]*packet.Packet, 0), } serverDest, err := destination.New(serverIdent, destination.IN, destination.SINGLE, "testapp", mockTrans, "server") if err != nil { t.Fatalf("Failed to create server destination: %v", err) } expectedResponse := []byte("response data") testPath := "/test/path" err = serverDest.RegisterRequestHandler(testPath, func(path string, data []byte, requestID []byte, linkID []byte, remoteIdentity *identity.Identity, requestedAt int64) []byte { if path != testPath { t.Errorf("Expected path %s, got %s", testPath, path) } return expectedResponse }, destination.ALLOW_ALL, nil) if err != nil { t.Fatalf("Failed to register request handler: %v", err) } // Test the handler is registered correctly pathHash := identity.TruncatedHash([]byte(testPath)) handler := serverDest.GetRequestHandler(pathHash) if handler == nil { t.Fatal("Handler not found after registration") } // Call the handler testLinkID := make([]byte, 16) result := handler(pathHash, []byte("test data"), []byte("request-id"), testLinkID, clientIdent, time.Now()) if result == nil { t.Fatal("Handler returned nil") } responseBytes, ok := result.([]byte) if !ok { t.Fatalf("Handler returned unexpected type: %T", result) } if !bytes.Equal(responseBytes, expectedResponse) { t.Errorf("Expected response %q, got %q", expectedResponse, responseBytes) } } func TestLinkRequestHandlerNotFound(t *testing.T) { serverIdent, _ := identity.New() mockTrans := &mockTransport{sentPackets: make([]*packet.Packet, 0)} serverDest, _ := destination.New(serverIdent, destination.IN, destination.SINGLE, "testapp", mockTrans, "server") nonExistentPath := "/does/not/exist" pathHash := identity.TruncatedHash([]byte(nonExistentPath)) handler := serverDest.GetRequestHandler(pathHash) if handler != nil { t.Error("Expected no handler for non-existent path, but found one") } } func TestLinkResponseHandling(t *testing.T) { // This test verifies the basic structure for response handling // Full integration testing would require a proper transport setup requestID := []byte("test-request-id-") responseData := []byte("response payload") receipt := &RequestReceipt{ requestID: requestID, status: STATUS_PENDING, } // Verify initial state if receipt.status != STATUS_PENDING { t.Errorf("Expected initial status PENDING, got %d", receipt.status) } // Simulate setting response receipt.response = responseData receipt.status = STATUS_ACTIVE if !bytes.Equal(receipt.response, responseData) { t.Errorf("Expected response %q, got %q", responseData, receipt.response) } if receipt.status != STATUS_ACTIVE { t.Errorf("Expected status ACTIVE after response, got %d", receipt.status) } }