github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/transport/ws/outbound_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package ws 8 9 import ( 10 "context" 11 "encoding/json" 12 "net/http" 13 "testing" 14 "time" 15 16 "github.com/google/uuid" 17 "github.com/stretchr/testify/require" 18 "nhooyr.io/websocket" 19 20 cryptoapi "github.com/hyperledger/aries-framework-go/pkg/crypto" 21 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 22 "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport" 23 mockpackager "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/packager" 24 ) 25 26 func TestClient(t *testing.T) { 27 t.Run("test outbound transport - accept", func(t *testing.T) { 28 outbound := NewOutbound() 29 require.NotNil(t, outbound) 30 31 require.True(t, outbound.Accept(webSocketScheme)) 32 require.False(t, outbound.Accept("http")) 33 }) 34 35 t.Run("test outbound transport - invalid url", func(t *testing.T) { 36 outbound := NewOutbound() 37 require.NotNil(t, outbound) 38 39 _, err := outbound.Send([]byte(""), prepareDestination("ws://invalid")) 40 require.Error(t, err) 41 require.Contains(t, err.Error(), "websocket client") 42 }) 43 44 t.Run("test outbound transport - success", func(t *testing.T) { 45 outbound := NewOutbound() 46 require.NotNil(t, outbound) 47 addr := startWebSocketServer(t, echo) 48 49 data := "hello" 50 resp, err := outbound.Send([]byte(data), prepareDestination("ws://"+addr)) 51 require.NoError(t, err) 52 require.Equal(t, "", resp) 53 }) 54 55 t.Run("test outbound transport - not a websocket server", func(t *testing.T) { 56 outbound := NewOutbound() 57 require.NotNil(t, outbound) 58 addr := startWebSocketServer(t, func(_ *testing.T, w http.ResponseWriter, r *http.Request) { 59 logger.Infof("inside http path") 60 }) 61 62 _, err := outbound.Send([]byte("ws-request"), prepareDestination("ws://"+addr)) 63 require.Error(t, err) 64 require.Contains(t, err.Error(), "websocket client") 65 }) 66 67 t.Run("test outbound transport pool success - no existing connections", func(t *testing.T) { 68 outbound := NewOutbound() 69 require.NotNil(t, outbound) 70 71 require.NoError(t, outbound.Start(&mockProvider{})) 72 73 addr := startWebSocketServer(t, echo) 74 75 data := "hello" 76 resp, err := outbound.Send([]byte(data), prepareDestination("ws://"+addr)) 77 require.NoError(t, err) 78 require.Equal(t, "", resp) 79 }) 80 81 t.Run("test outbound transport pool - accept recipients", func(t *testing.T) { 82 verKey := "XYZ" 83 recKey := []string{verKey} 84 85 outbound := NewOutbound() 86 require.NotNil(t, outbound) 87 88 require.NoError(t, outbound.Start(&mockProvider{ 89 &mockpackager.Packager{UnpackValue: &transport.Envelope{Message: []byte("data")}}, 90 }, 91 )) 92 93 addr := startWebSocketServer(t, echo) 94 95 resp, err := outbound.Send(createTransportDecRequest(t, decorator.TransportReturnRouteAll), 96 prepareDestinationWithTransport("ws://"+addr, decorator.TransportReturnRouteAll, recKey, nil)) 97 require.NoError(t, err) 98 require.Equal(t, "", resp) 99 100 // verify connection exists for the verKey 101 require.True(t, outbound.AcceptRecipient(recKey)) 102 103 // close the connection and verify 104 conn := outbound.pool.fetch(verKey) 105 require.NoError(t, conn.Close(websocket.StatusNormalClosure, "close conn")) 106 require.False(t, outbound.AcceptRecipient(recKey)) 107 108 // connection was remove in prev step 109 require.False(t, outbound.AcceptRecipient(recKey)) 110 }) 111 112 t.Run("test outbound transport pool - accept routing keys", func(t *testing.T) { 113 verKey := "XYZ" 114 routeKey := "ABC" 115 recKey := []string{verKey} 116 routingKeys := []string{routeKey} 117 118 outbound := NewOutbound() 119 require.NotNil(t, outbound) 120 121 require.NoError(t, outbound.Start(&mockProvider{ 122 &mockpackager.Packager{UnpackValue: &transport.Envelope{Message: []byte("data")}}, 123 }, 124 )) 125 126 addr := startWebSocketServer(t, echo) 127 128 des := prepareDestinationWithTransport("ws://"+addr, decorator.TransportReturnRouteAll, recKey, routingKeys) 129 130 data := "didcomm-message" 131 resp, err := outbound.Send([]byte(data), des) 132 require.NoError(t, err) 133 require.Equal(t, "", resp) 134 }) 135 136 t.Run("test outbound transport pool success - transport decorator", func(t *testing.T) { 137 outbound := NewOutbound() 138 require.NotNil(t, outbound) 139 140 require.NoError(t, outbound.Start(&mockProvider{ 141 &mockpackager.Packager{UnpackValue: &transport.Envelope{Message: []byte("data")}}, 142 }, 143 )) 144 145 addr := startWebSocketServer(t, echo) 146 147 resp, err := outbound.Send(createTransportDecRequest(t, decorator.TransportReturnRouteAll), 148 prepareDestinationWithTransport("ws://"+addr, decorator.TransportReturnRouteAll, nil, nil)) 149 require.NoError(t, err) 150 require.Equal(t, "", resp) 151 }) 152 153 t.Run("test outbound transport pool - transport decorator value none", func(t *testing.T) { 154 outbound := NewOutbound() 155 require.NotNil(t, outbound) 156 157 require.NoError(t, outbound.Start(&mockProvider{ 158 &mockpackager.Packager{UnpackValue: &transport.Envelope{Message: []byte("data")}}, 159 }, 160 )) 161 162 addr := startWebSocketServer(t, echo) 163 164 resp, err := outbound.Send(createTransportDecRequest(t, decorator.TransportReturnRouteNone), 165 prepareDestinationWithTransport("ws://"+addr, decorator.TransportReturnRouteNone, nil, nil)) 166 require.NoError(t, err) 167 require.Equal(t, "", resp) 168 }) 169 170 t.Run("test outbound transport - custom read limit for a single message", func(t *testing.T) { 171 outboundClient := NewOutbound(WithOutboundReadLimit(defaultReadLimit + 1)) 172 require.NotNil(t, outboundClient) 173 174 done := make(chan struct{}) 175 176 unpackMsg, err := json.Marshal(&decorator.Transport{ 177 ReturnRoute: &decorator.ReturnRoute{ 178 Value: decorator.TransportReturnRouteAll, 179 }, 180 }) 181 require.NoError(t, err) 182 183 fromKey, err := json.Marshal(&cryptoapi.PublicKey{KID: "keyID"}) 184 require.NoError(t, err) 185 186 transportProvider := &mockTransportProvider{ 187 frameworkID: uuid.New().String(), 188 packagerValue: &mockpackager.Packager{ 189 UnpackValue: &transport.Envelope{Message: unpackMsg, FromKey: fromKey}, 190 }, 191 executeInbound: func(envelope *transport.Envelope) error { 192 done <- struct{}{} 193 return nil 194 }, 195 } 196 197 addr := startWebSocketServer(t, func(t *testing.T, w http.ResponseWriter, r *http.Request) { 198 c, errAcc := Accept(w, r) 199 require.NoError(t, errAcc) 200 201 defer func() { 202 require.NoError(t, c.Close(websocket.StatusNormalClosure, "closing the connection")) 203 }() 204 205 bigMsg := make([]byte, defaultReadLimit+1) 206 207 errWrite := c.Write(context.Background(), websocket.MessageText, bigMsg) 208 require.NoError(t, errWrite) 209 }) 210 211 err = outboundClient.Start(transportProvider) 212 require.NoError(t, err) 213 214 resp, err := outboundClient.Send([]byte("data"), 215 prepareDestinationWithTransport("ws://"+addr, decorator.TransportReturnRouteAll, nil, nil)) 216 require.NoError(t, err) 217 require.Equal(t, "", resp) 218 219 select { 220 case <-done: 221 case <-time.After(3 * time.Second): 222 require.Fail(t, "inbound message handler was not called within given timeout") 223 } 224 }) 225 }