|
4 | 4 | "testing" |
5 | 5 | "time" |
6 | 6 |
|
| 7 | + "github.com/lucas-clemente/quic-go" |
7 | 8 | "github.com/rs/zerolog" |
8 | 9 | "github.com/stretchr/testify/assert" |
9 | 10 |
|
@@ -53,48 +54,71 @@ func TestWaitForBackoffFallback(t *testing.T) { |
53 | 54 | initProtocol := protocolSelector.Current() |
54 | 55 | assert.Equal(t, connection.HTTP2, initProtocol) |
55 | 56 |
|
56 | | - protocolFallback := &protocolFallback{ |
| 57 | + protoFallback := &protocolFallback{ |
57 | 58 | backoff, |
58 | 59 | initProtocol, |
59 | 60 | false, |
60 | 61 | } |
61 | 62 |
|
62 | 63 | // Retry #0 and #1. At retry #2, we switch protocol, so the fallback loop has one more retry than this |
63 | 64 | for i := 0; i < int(maxRetries-1); i++ { |
64 | | - protocolFallback.BackoffTimer() // simulate retry |
65 | | - ok := selectNextProtocol(&log, protocolFallback, protocolSelector, false) |
| 65 | + protoFallback.BackoffTimer() // simulate retry |
| 66 | + ok := selectNextProtocol(&log, protoFallback, protocolSelector, nil) |
66 | 67 | assert.True(t, ok) |
67 | | - assert.Equal(t, initProtocol, protocolFallback.protocol) |
| 68 | + assert.Equal(t, initProtocol, protoFallback.protocol) |
68 | 69 | } |
69 | 70 |
|
70 | 71 | // Retry fallback protocol |
71 | 72 | for i := 0; i < int(maxRetries); i++ { |
72 | | - protocolFallback.BackoffTimer() // simulate retry |
73 | | - ok := selectNextProtocol(&log, protocolFallback, protocolSelector, false) |
| 73 | + protoFallback.BackoffTimer() // simulate retry |
| 74 | + ok := selectNextProtocol(&log, protoFallback, protocolSelector, nil) |
74 | 75 | assert.True(t, ok) |
75 | 76 | fallback, ok := protocolSelector.Fallback() |
76 | 77 | assert.True(t, ok) |
77 | | - assert.Equal(t, fallback, protocolFallback.protocol) |
| 78 | + assert.Equal(t, fallback, protoFallback.protocol) |
78 | 79 | } |
79 | 80 |
|
80 | 81 | currentGlobalProtocol := protocolSelector.Current() |
81 | 82 | assert.Equal(t, initProtocol, currentGlobalProtocol) |
82 | 83 |
|
83 | 84 | // No protocol to fallback, return error |
84 | | - protocolFallback.BackoffTimer() // simulate retry |
85 | | - ok := selectNextProtocol(&log, protocolFallback, protocolSelector, false) |
| 85 | + protoFallback.BackoffTimer() // simulate retry |
| 86 | + ok := selectNextProtocol(&log, protoFallback, protocolSelector, nil) |
86 | 87 | assert.False(t, ok) |
87 | 88 |
|
88 | | - protocolFallback.reset() |
89 | | - protocolFallback.BackoffTimer() // simulate retry |
90 | | - ok = selectNextProtocol(&log, protocolFallback, protocolSelector, false) |
| 89 | + protoFallback.reset() |
| 90 | + protoFallback.BackoffTimer() // simulate retry |
| 91 | + ok = selectNextProtocol(&log, protoFallback, protocolSelector, nil) |
91 | 92 | assert.True(t, ok) |
92 | | - assert.Equal(t, initProtocol, protocolFallback.protocol) |
| 93 | + assert.Equal(t, initProtocol, protoFallback.protocol) |
93 | 94 |
|
94 | | - protocolFallback.reset() |
95 | | - protocolFallback.BackoffTimer() // simulate retry |
96 | | - ok = selectNextProtocol(&log, protocolFallback, protocolSelector, true) |
| 95 | + protoFallback.reset() |
| 96 | + protoFallback.BackoffTimer() // simulate retry |
| 97 | + ok = selectNextProtocol(&log, protoFallback, protocolSelector, &quic.IdleTimeoutError{}) |
97 | 98 | // Check that we get a true after the first try itself when this flag is true. This allows us to immediately |
98 | | - // switch protocols. |
| 99 | + // switch protocols when there is a fallback. |
99 | 100 | assert.True(t, ok) |
| 101 | + |
| 102 | + // But if there is no fallback available, then we exhaust the retries despite the type of error. |
| 103 | + // The reason why there's no fallback available is because we pick a specific protocol instead of letting it be auto. |
| 104 | + protocolSelector, err = connection.NewProtocolSelector( |
| 105 | + "quic", |
| 106 | + warpRoutingEnabled, |
| 107 | + namedTunnel, |
| 108 | + mockFetcher.fetch(), |
| 109 | + resolveTTL, |
| 110 | + &log, |
| 111 | + ) |
| 112 | + assert.NoError(t, err) |
| 113 | + protoFallback = &protocolFallback{backoff, protocolSelector.Current(), false} |
| 114 | + for i := 0; i < int(maxRetries-1); i++ { |
| 115 | + protoFallback.BackoffTimer() // simulate retry |
| 116 | + ok := selectNextProtocol(&log, protoFallback, protocolSelector, &quic.IdleTimeoutError{}) |
| 117 | + assert.True(t, ok) |
| 118 | + assert.Equal(t, connection.QUIC, protoFallback.protocol) |
| 119 | + } |
| 120 | + // And finally it fails as it should, with no fallback. |
| 121 | + protoFallback.BackoffTimer() |
| 122 | + ok = selectNextProtocol(&log, protoFallback, protocolSelector, &quic.IdleTimeoutError{}) |
| 123 | + assert.False(t, ok) |
100 | 124 | } |
0 commit comments