-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathreconnection_test.go
151 lines (128 loc) · 4.14 KB
/
reconnection_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package client
import (
"context"
"os"
"sync/atomic"
"testing"
"time"
)
// TestReconnection verifies that the client automatically reconnects after a disconnect
func TestReconnection(t *testing.T) {
// Skip unless explicitly enabled
if os.Getenv("RUN_RECONNECTION_TEST") != "true" {
t.Skip("Skipping reconnection test. Set RUN_RECONNECTION_TEST=true to run")
}
apiKey := os.Getenv("FIBER_API_KEY")
if apiKey == "" {
t.Skip("FIBER_API_KEY environment variable not set")
}
target := "beta.fiberapi.io:8080"
// Simplified to only test reconnection behavior
testReconnection(t, target, apiKey)
}
// testReconnection is a helper function that tests reconnection behavior
func testReconnection(t *testing.T, target, apiKey string) {
t.Logf("========== CONNECTION SETUP ==========")
// Create configuration
config := NewConfig().SetIdleTimeout(10 * time.Second).SetHealthCheckInterval(10 * time.Second).SetLogLevel("debug")
// Create client
fiber := NewClientWithConfig(target, apiKey, config)
defer fiber.Close()
// Connect to the API
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
err := fiber.Connect(ctx)
if err != nil {
t.Fatalf("Failed to connect: %v", err)
}
// Create a channel for transactions
txs := make(chan *TransactionWithSender)
subDone := make(chan error, 1)
// Subscribe to new transactions
go func() {
err := fiber.SubscribeNewTxs(nil, txs)
subDone <- err
close(subDone)
}()
// Wait for initial data to confirm subscription is working
t.Log("Waiting for initial transactions before testing reconnection...")
initialRxCount := 0
initialWaitTimeout := time.After(15 * time.Second)
initialWait:
for {
select {
case <-initialWaitTimeout:
t.Fatal("Did not receive any initial transactions within timeout")
case tx, ok := <-txs:
if !ok {
t.Fatal("Transaction channel closed during initial wait")
}
initialRxCount++
t.Logf("Received initial tx %d: %s", initialRxCount, tx.Transaction.Hash())
if initialRxCount >= 1 {
t.Log("Received sufficient initial transactions")
break initialWait
}
case err := <-subDone:
t.Fatalf("Subscription ended during initial wait: %v", err)
}
}
// Record state before we simulate a disconnection
t.Logf("Current connection state before disconnect: %v", fiber.conn.GetState())
// Simulate a network interruption by forcibly closing the connection
t.Log("Simulating network interruption...")
disconnectTime := time.Now()
fiber.conn.Close()
// Now wait for transactions to appear after reconnection
t.Log("Waiting for reconnection...")
txAfterDisconnect := atomic.Int32{}
reconnected := false
var reconnectTime time.Time
waiting := true
reconnectTimeout := time.After(30 * time.Second)
for waiting {
select {
case <-reconnectTimeout:
t.Fatal("Did not reconnect within the expected timeout period")
case tx, ok := <-txs:
if !ok {
t.Log("Transaction channel was closed")
waiting = false
break
}
// Only count transactions received after a reasonable delay
timeSinceDisconnect := time.Since(disconnectTime)
if timeSinceDisconnect > 3*time.Second {
if !reconnected {
reconnected = true
reconnectTime = time.Now()
t.Logf("RECONNECTION DETECTED after %v - Transaction received after disconnect",
reconnectTime.Sub(disconnectTime))
t.Logf("Current connection state after reconnect: %v", fiber.conn.GetState())
}
// Log transaction hash
t.Logf("Post-reconnect tx: %s", tx.Transaction.Hash())
txAfterDisconnect.Add(1)
// If we've verified reconnection with multiple transactions, we can exit
if txAfterDisconnect.Load() >= 3 {
t.Logf("Successfully confirmed reconnection with %d transactions",
txAfterDisconnect.Load())
waiting = false
}
}
case <-time.After(500 * time.Millisecond):
// Poll interval
case err := <-subDone:
if err != nil {
t.Fatalf("Subscription ended with error: %v", err)
}
waiting = false
}
}
// Verify results
if !reconnected {
t.Errorf("Expected client to reconnect, but it did not")
} else {
t.Logf("SUCCESS: Client reconnected after %v", reconnectTime.Sub(disconnectTime))
}
}