+package alamo
+
+import (
+ "context"
+ "errors"
+ "testing"
+ "testing/synctest"
+ "time"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestGatewaySharesSixSecondRequestStartInterval(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ client := &fakeGateway{states: []State{testState()}}
+ gateway := &gateway{client: client}
+ _, err := gateway.status(t.Context())
+ require.NoError(t, err)
+
+ _, err = gateway.action(t.Context(), testMAC, Action{})
+ require.NoError(t, err)
+
+ _, err = gateway.status(t.Context())
+ require.NoError(t, err)
+ require.Len(t, client.starts, 3)
+ require.Equal(t, 6*time.Second, client.starts[1].Sub(client.starts[0]))
+ require.Equal(t, 6*time.Second, client.starts[2].Sub(client.starts[1]))
+ })
+}
+
+func TestGatewayDoesNotSpendAnotherIntervalAfterSlowRequests(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ client := &fakeGateway{
+ states: []State{testState()},
+ delay: 4 * time.Second,
+ }
+ gateway := &gateway{client: client}
+ _, err := gateway.status(t.Context())
+ require.NoError(t, err)
+
+ _, err = gateway.status(t.Context())
+ require.NoError(t, err)
+ require.Equal(t, 6*time.Second, client.starts[1].Sub(client.starts[0]))
+ })
+}
+
+func TestGatewayExpiryAndCancellationStopRateWaitWithoutIO(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ client := &fakeGateway{states: []State{testState()}}
+ gateway := &gateway{client: client}
+ _, err := gateway.status(t.Context())
+ require.NoError(t, err)
+
+ ctx, cancel := context.WithTimeout(t.Context(), time.Second)
+ defer cancel()
+
+ _, err = gateway.action(ctx, testMAC, Action{})
+ require.ErrorIs(t, err, context.DeadlineExceeded)
+
+ ctx, cancel = context.WithCancel(t.Context())
+ cancel()
+
+ _, err = gateway.status(ctx)
+ require.ErrorIs(t, err, context.Canceled)
+ require.Len(t, client.starts, 1)
+ })
+}
+
+func TestGatewayBoundsFakeClientOperationsAndReturnsFailures(t *testing.T) {
+ synctest.Test(t, func(t *testing.T) {
+ client := &fakeGateway{delay: time.Minute}
+ gateway := &gateway{client: client}
+ _, err := gateway.status(t.Context())
+ require.ErrorIs(t, err, context.DeadlineExceeded)
+
+ _, err = gateway.action(t.Context(), testMAC, Action{})
+ require.ErrorIs(t, err, context.DeadlineExceeded)
+
+ client.delay = 0
+ client.err = errors.New("gateway unavailable")
+ _, err = gateway.status(t.Context())
+ require.ErrorIs(t, err, client.err)
+
+ _, err = gateway.action(t.Context(), testMAC, Action{})
+ require.ErrorIs(t, err, client.err)
+ })
+}