github.com/bitfinexcom/bitfinex-api-go@v0.0.0-20210608095005-9e0b26f200fb/tests/integration/v2/live_websocket_public_test.go (about) 1 package tests 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "sync" 8 "testing" 9 "time" 10 11 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/book" 12 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/candle" 13 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/common" 14 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/ticker" 15 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/trade" 16 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/tradeexecution" 17 "github.com/bitfinexcom/bitfinex-api-go/pkg/models/tradeexecutionupdate" 18 "github.com/bitfinexcom/bitfinex-api-go/v2" 19 "github.com/bitfinexcom/bitfinex-api-go/v2/websocket" 20 ) 21 22 // wait2 will wait for at least "count" messages on channel "ch" within time "t", or return an error 23 func wait2(ch <-chan interface{}, count int, bc <-chan error, t time.Duration) error { 24 c := make(chan interface{}) 25 go func() { 26 <-ch 27 close(c) 28 }() 29 select { 30 case <-bc: 31 return fmt.Errorf("transport closed while waiting") 32 case <-c: 33 return nil // normal 34 case <-time.After(t): 35 return fmt.Errorf("timed out waiting") 36 } 37 } 38 39 func wait(wg *sync.WaitGroup, bc <-chan error, to time.Duration) error { 40 c := make(chan struct{}) 41 go func() { 42 defer close(c) 43 wg.Wait() 44 }() 45 select { 46 case <-bc: 47 return fmt.Errorf("websocket closed while waiting") // timed out 48 case <-c: 49 return nil // completed normally 50 case <-time.After(to): 51 return fmt.Errorf("timed out waiting") // timed out 52 } 53 } 54 55 func TestPublicTicker(t *testing.T) { 56 c := websocket.New() 57 58 err := c.Connect() 59 if err != nil { 60 t.Fatal("Error connecting to web socket : ", err) 61 } 62 defer c.Close() 63 64 subs := make(chan interface{}, 10) 65 unsubs := make(chan interface{}, 10) 66 infos := make(chan interface{}, 10) 67 tick := make(chan interface{}, 100) 68 69 errch := make(chan error) 70 go func() { 71 // nolint:megacheck 72 for { 73 select { 74 case msg := <-c.Listen(): 75 if msg == nil { 76 return 77 } 78 log.Printf("recv msg: %#v", msg) 79 switch m := msg.(type) { 80 case error: 81 errch <- msg.(error) 82 case *websocket.UnsubscribeEvent: 83 unsubs <- m 84 case *websocket.SubscribeEvent: 85 subs <- m 86 case *websocket.InfoEvent: 87 infos <- m 88 case *ticker.Snapshot: 89 tick <- m 90 case *ticker.Ticker: 91 tick <- m 92 default: 93 t.Logf("test recv: %#v", msg) 94 } 95 } 96 } 97 }() 98 99 ctx, cxl := context.WithTimeout(context.Background(), time.Second*5) 100 defer cxl() 101 id, err := c.SubscribeTicker(ctx, common.TradingPrefix+bitfinex.BTCUSD) 102 if err != nil { 103 t.Fatal(err) 104 } 105 106 if err := wait2(tick, 1, errch, 2*time.Second); err != nil { 107 t.Fatalf("failed to receive ticker message from websocket: %s", err) 108 } 109 110 err = c.Unsubscribe(ctx, id) 111 if err != nil { 112 t.Fatal(err) 113 } 114 115 if err := wait2(unsubs, 1, errch, 2*time.Second); err != nil { 116 t.Errorf("failed to receive unsubscribe message from websocket: %s", err) 117 } 118 } 119 120 func TestPublicTrades(t *testing.T) { 121 c := websocket.New() 122 wg := sync.WaitGroup{} 123 wg.Add(3) // 1. Info with version, 2. Subscription event, 3. 3 x data message 124 125 err := c.Connect() 126 if err != nil { 127 t.Fatal("Error connecting to web socket : ", err) 128 } 129 defer c.Close() 130 131 subs := make(chan interface{}, 10) 132 unsubs := make(chan interface{}, 10) 133 infos := make(chan interface{}, 10) 134 trades := make(chan interface{}, 100) 135 136 errch := make(chan error) 137 go func() { 138 // nolint:megacheck 139 for { 140 select { 141 case msg := <-c.Listen(): 142 if msg == nil { 143 return 144 } 145 log.Printf("recv msg: %#v", msg) 146 switch m := msg.(type) { 147 case error: 148 errch <- msg.(error) 149 case *websocket.UnsubscribeEvent: 150 unsubs <- m 151 case *websocket.SubscribeEvent: 152 subs <- m 153 case *websocket.InfoEvent: 154 infos <- m 155 case *tradeexecutionupdate.Snapshot: 156 trades <- m 157 case *trade.Trade: 158 trades <- m 159 case *tradeexecutionupdate.TradeExecutionUpdate: 160 trades <- m 161 case *tradeexecution.TradeExecution: 162 trades <- m 163 case *trade.Snapshot: 164 trades <- m 165 default: 166 t.Logf("test recv: %#v", msg) 167 } 168 } 169 } 170 }() 171 172 ctx, cxl := context.WithTimeout(context.Background(), time.Second*5) 173 defer cxl() 174 id, err := c.SubscribeTrades(ctx, common.TradingPrefix+bitfinex.BTCUSD) 175 if err != nil { 176 t.Fatal(err) 177 } 178 179 if err := wait2(trades, 1, errch, 2*time.Second); err != nil { 180 t.Errorf("failed to receive trade message from websocket: %s", err) 181 } 182 183 err = c.Unsubscribe(ctx, id) 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 if err := wait2(unsubs, 1, errch, 2*time.Second); err != nil { 189 t.Errorf("failed to receive unsubscribe message from websocket: %s", err) 190 } 191 } 192 193 func TestPublicBooks(t *testing.T) { 194 c := websocket.New() 195 wg := sync.WaitGroup{} 196 wg.Add(3) // 1. Info with version, 2. Subscription event, 3. data message 197 198 err := c.Connect() 199 if err != nil { 200 t.Fatal("Error connecting to web socket : ", err) 201 } 202 defer c.Close() 203 204 subs := make(chan interface{}, 10) 205 unsubs := make(chan interface{}, 10) 206 infos := make(chan interface{}, 10) 207 books := make(chan interface{}, 100) 208 209 errch := make(chan error) 210 go func() { 211 // nolint:megacheck 212 for { 213 select { 214 case msg := <-c.Listen(): 215 if msg == nil { 216 return 217 } 218 log.Printf("recv msg: %#v", msg) 219 switch m := msg.(type) { 220 case error: 221 errch <- msg.(error) 222 case *websocket.UnsubscribeEvent: 223 unsubs <- m 224 case *websocket.SubscribeEvent: 225 subs <- m 226 case *websocket.InfoEvent: 227 infos <- m 228 case *book.Snapshot: 229 books <- m 230 case *book.Book: 231 books <- m 232 default: 233 t.Logf("test recv: %#v", msg) 234 } 235 } 236 } 237 }() 238 239 ctx, cxl := context.WithTimeout(context.Background(), time.Second*5) 240 defer cxl() 241 id, err := c.SubscribeBook(ctx, common.TradingPrefix+bitfinex.BTCUSD, common.Precision0, common.FrequencyRealtime, 1) 242 if err != nil { 243 t.Fatal(err) 244 } 245 246 if err := wait2(books, 1, errch, 5*time.Second); err != nil { 247 t.Fatalf("failed to receive book update message from websocket: %s", err) 248 } 249 250 err = c.Unsubscribe(ctx, id) 251 if err != nil { 252 t.Fatal(err) 253 } 254 255 if err := wait2(unsubs, 1, errch, 5*time.Second); err != nil { 256 t.Errorf("failed to receive unsubscribe message from websocket: %s", err) 257 } 258 } 259 260 func TestPublicCandles(t *testing.T) { 261 c := websocket.New() 262 wg := sync.WaitGroup{} 263 wg.Add(3) // 1. Info with version, 2. Subscription event, 3. data message 264 265 err := c.Connect() 266 if err != nil { 267 t.Fatal("Error connecting to web socket : ", err) 268 } 269 defer c.Close() 270 271 subs := make(chan interface{}, 10) 272 unsubs := make(chan interface{}, 10) 273 infos := make(chan interface{}, 10) 274 candles := make(chan interface{}, 100) 275 276 errch := make(chan error) 277 go func() { 278 // nolint:megacheck 279 for { 280 select { 281 case msg := <-c.Listen(): 282 if msg == nil { 283 return 284 } 285 log.Printf("recv msg: %#v", msg) 286 switch m := msg.(type) { 287 case error: 288 errch <- msg.(error) 289 case *websocket.UnsubscribeEvent: 290 unsubs <- m 291 case *websocket.SubscribeEvent: 292 subs <- m 293 case *websocket.InfoEvent: 294 infos <- m 295 case *candle.Candle: 296 candles <- m 297 case *candle.Snapshot: 298 candles <- m 299 default: 300 t.Logf("test recv: %#v", msg) 301 } 302 } 303 } 304 }() 305 306 ctx, cxl := context.WithTimeout(context.Background(), time.Second*5) 307 defer cxl() 308 id, err := c.SubscribeCandles(ctx, common.TradingPrefix+bitfinex.BTCUSD, common.OneMonth) 309 if err != nil { 310 t.Fatal(err) 311 } 312 313 if err := wait2(candles, 1, errch, 2*time.Second); err != nil { 314 t.Errorf("failed to receive a candle message from websocket: %s", err) 315 } 316 317 err = c.Unsubscribe(ctx, id) 318 if err != nil { 319 t.Fatal(err) 320 } 321 322 if err := wait2(unsubs, 1, errch, 2*time.Second); err != nil { 323 t.Errorf("failed to receive an unsubscribe message from websocket: %s", err) 324 } 325 }