2020-10-14 13:42:00 +00:00
|
|
|
package origin
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/connection"
|
2020-11-25 06:55:13 +00:00
|
|
|
|
|
|
|
"github.com/rs/zerolog"
|
2020-10-14 13:42:00 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
type dynamicMockFetcher struct {
|
|
|
|
percentage int32
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (dmf *dynamicMockFetcher) fetch() connection.PercentageFetcher {
|
|
|
|
return func() (int32, error) {
|
|
|
|
if dmf.err != nil {
|
|
|
|
return 0, dmf.err
|
|
|
|
}
|
|
|
|
return dmf.percentage, nil
|
|
|
|
}
|
|
|
|
}
|
2021-02-05 00:07:49 +00:00
|
|
|
|
2020-10-14 13:42:00 +00:00
|
|
|
func TestWaitForBackoffFallback(t *testing.T) {
|
|
|
|
maxRetries := uint(3)
|
|
|
|
backoff := BackoffHandler{
|
|
|
|
MaxRetries: maxRetries,
|
|
|
|
BaseTime: time.Millisecond * 10,
|
|
|
|
}
|
2020-11-25 06:55:13 +00:00
|
|
|
log := zerolog.Nop()
|
2020-10-14 13:42:00 +00:00
|
|
|
resolveTTL := time.Duration(0)
|
|
|
|
namedTunnel := &connection.NamedTunnelConfig{
|
2020-11-23 21:36:16 +00:00
|
|
|
Credentials: connection.Credentials{
|
2020-10-14 13:42:00 +00:00
|
|
|
AccountTag: "test-account",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
mockFetcher := dynamicMockFetcher{
|
|
|
|
percentage: 0,
|
|
|
|
}
|
2021-01-21 15:23:18 +00:00
|
|
|
warpRoutingEnabled := false
|
2020-11-25 06:55:13 +00:00
|
|
|
protocolSelector, err := connection.NewProtocolSelector(
|
|
|
|
connection.HTTP2.String(),
|
2021-01-21 15:23:18 +00:00
|
|
|
warpRoutingEnabled,
|
2020-11-25 06:55:13 +00:00
|
|
|
namedTunnel,
|
|
|
|
mockFetcher.fetch(),
|
|
|
|
resolveTTL,
|
|
|
|
&log,
|
|
|
|
)
|
2020-10-14 13:42:00 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
initProtocol := protocolSelector.Current()
|
|
|
|
assert.Equal(t, connection.HTTP2, initProtocol)
|
|
|
|
|
2021-02-05 00:07:49 +00:00
|
|
|
protocolFallback := &protocolFallback{
|
2020-10-14 13:42:00 +00:00
|
|
|
backoff,
|
|
|
|
initProtocol,
|
|
|
|
false,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retry #0 and #1. At retry #2, we switch protocol, so the fallback loop has one more retry than this
|
|
|
|
for i := 0; i < int(maxRetries-1); i++ {
|
2021-02-05 00:07:49 +00:00
|
|
|
protocolFallback.BackoffTimer() // simulate retry
|
|
|
|
ok := selectNextProtocol(&log, protocolFallback, protocolSelector)
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.Equal(t, initProtocol, protocolFallback.protocol)
|
2020-10-14 13:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Retry fallback protocol
|
|
|
|
for i := 0; i < int(maxRetries); i++ {
|
2021-02-05 00:07:49 +00:00
|
|
|
protocolFallback.BackoffTimer() // simulate retry
|
|
|
|
ok := selectNextProtocol(&log, protocolFallback, protocolSelector)
|
|
|
|
assert.True(t, ok)
|
2020-10-14 13:42:00 +00:00
|
|
|
fallback, ok := protocolSelector.Fallback()
|
|
|
|
assert.True(t, ok)
|
2021-02-05 00:07:49 +00:00
|
|
|
assert.Equal(t, fallback, protocolFallback.protocol)
|
2020-10-14 13:42:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
currentGlobalProtocol := protocolSelector.Current()
|
|
|
|
assert.Equal(t, initProtocol, currentGlobalProtocol)
|
|
|
|
|
|
|
|
// No protocol to fallback, return error
|
2021-02-05 00:07:49 +00:00
|
|
|
protocolFallback.BackoffTimer() // simulate retry
|
|
|
|
ok := selectNextProtocol(&log, protocolFallback, protocolSelector)
|
|
|
|
assert.False(t, ok)
|
2020-10-14 13:42:00 +00:00
|
|
|
|
2021-02-05 00:07:49 +00:00
|
|
|
protocolFallback.reset()
|
|
|
|
protocolFallback.BackoffTimer() // simulate retry
|
|
|
|
ok = selectNextProtocol(&log, protocolFallback, protocolSelector)
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.Equal(t, initProtocol, protocolFallback.protocol)
|
2020-10-14 13:42:00 +00:00
|
|
|
}
|