decred.org/dcrdex@v1.0.5/server/noderelay/noderelay_test.go (about) 1 //go:build live 2 3 package noderelay 4 5 import ( 6 "context" 7 "encoding/json" 8 "fmt" 9 "io" 10 "net" 11 "net/http" 12 "os" 13 "path/filepath" 14 "strings" 15 "testing" 16 "time" 17 18 "decred.org/dcrdex/client/comms" 19 "decred.org/dcrdex/dex" 20 ) 21 22 func TestNexus(t *testing.T) { 23 netAddr, _ := net.ResolveTCPAddr("tcp", "localhost:0") 24 l, _ := net.ListenTCP("tcp", netAddr) 25 addr := l.Addr().String() 26 l.Close() 27 _, port, err := net.SplitHostPort(addr) 28 if err != nil { 29 t.Fatalf("error splitting host and port from address %q", addr) 30 } 31 32 dir, err := os.MkdirTemp("", "") 33 if err != nil { 34 t.Fatalf("Error making temp dir: %v", err) 35 } 36 defer os.RemoveAll(dir) 37 38 relayID := "0xabcanything_you-want" 39 40 cfg := &NexusConfig{ 41 Port: port, 42 Dir: dir, 43 Key: filepath.Join(dir, "t.key"), 44 Cert: filepath.Join(dir, "t.cert"), 45 Logger: dex.StdOutLogger("T", dex.LevelDebug), 46 RelayIDs: []string{relayID}, 47 } 48 49 n, err := NewNexus(cfg) 50 if err != nil { 51 t.Fatalf("NewNexus error: %v", err) 52 } 53 54 certB, err := os.ReadFile(cfg.Cert) 55 if err != nil { 56 t.Fatalf("Error reading certificate file: %v", err) 57 } 58 59 ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 60 defer cancel() 61 if _, err = n.Connect(ctx); err != nil { 62 t.Fatalf("Start error: %v", err) 63 } 64 65 time.Sleep(2 * time.Second) 66 67 relayAddr, err := n.RelayAddr(relayID) 68 if err != nil { 69 t.Fatalf("RelayAddr error: %v", err) 70 } 71 72 firstRequest, firstResponse := "firstRequest", "firstResponse" 73 var rawHandlerErr error 74 75 var cl comms.WsConn 76 cl, err = comms.NewWsConn(&comms.WsCfg{ 77 URL: "wss://" + addr, 78 PingWait: 20 * time.Second, 79 Cert: certB, 80 ReconnectSync: func() { 81 cancel() 82 }, 83 ConnectEventFunc: func(s comms.ConnectionStatus) {}, 84 Logger: dex.StdOutLogger("CL", dex.LevelDebug), 85 RawHandler: func(b []byte) { 86 var req *RelayedMessage 87 if err := json.Unmarshal(b, &req); err != nil { 88 t.Fatalf("Error unmarshaling raw message: %v", err) 89 } 90 switch req.MessageID { 91 case 1: 92 if string(req.Body) != firstRequest { 93 rawHandlerErr = fmt.Errorf("first request had unexpected body %s != %s", string(req.Body), firstRequest) 94 cancel() 95 return 96 } 97 msgB, _ := json.Marshal(&RelayedMessage{ 98 MessageID: 1, 99 Body: []byte(firstResponse), 100 }) 101 if err := cl.SendRaw(msgB); err != nil { 102 rawHandlerErr = fmt.Errorf("Send error: %w", err) 103 cancel() 104 } 105 } 106 }, 107 }) 108 if err != nil { 109 t.Fatalf("NewWsConn error: %v", err) 110 } 111 112 cm := dex.NewConnectionMaster(cl) 113 if err := cm.ConnectOnce(ctx); err != nil { 114 t.Fatalf("ConnectOnce error: %v", err) 115 } 116 117 msgB, _ := json.Marshal(&RelayedMessage{ 118 MessageID: 0, // 0 is always the node ID 119 Body: []byte(relayID), 120 }) 121 122 cl.SendRaw(msgB) 123 124 select { 125 case <-n.WaitForSourceNodes(): 126 case <-ctx.Done(): 127 return 128 case <-time.After(time.Second * 5): 129 t.Fatal("timed out waiting for source nodes to connect") 130 } 131 132 // Now act like an asset backend and send a request through the relay node. 133 relayURL := "http://" + relayAddr 134 resp, err := http.DefaultClient.Post(relayURL, "application/json", strings.NewReader(firstRequest)) 135 if err != nil { 136 t.Fatalf("Post error: %v", err) 137 } 138 139 b, err := io.ReadAll(resp.Body) 140 resp.Body.Close() 141 if err != nil { 142 t.Fatalf("First response read error: %v", err) 143 } 144 respBody := strings.TrimSpace(string(b)) 145 if respBody != firstResponse { 146 t.Fatalf("wrong first response. %s != %s", string(b), firstResponse) 147 } 148 cancel() 149 cm.Wait() 150 n.wg.Wait() 151 152 if rawHandlerErr != nil { 153 t.Fatalf("Error generated in node source request handling: %v", rawHandlerErr) 154 } 155 fmt.Println("!!!!! Success !!!!!") 156 }