|
| 1 | +package audit |
| 2 | + |
| 3 | +import ( |
| 4 | + "testing" |
| 5 | + "time" |
| 6 | + |
| 7 | + "github.com/meridianhub/meridian/shared/platform/defaults" |
| 8 | + "github.com/stretchr/testify/assert" |
| 9 | +) |
| 10 | + |
| 11 | +// newTestWorker creates a Worker with nil db for unit testing option functions. |
| 12 | +// Do not call Start/Stop on this worker. |
| 13 | +func newTestWorker() *Worker { |
| 14 | + return &Worker{ |
| 15 | + batchSize: defaultBatchSize, |
| 16 | + pollInterval: defaultPollInterval, |
| 17 | + maxRetries: defaultMaxRetries, |
| 18 | + minPollInterval: defaultMinPollInterval, |
| 19 | + maxPollInterval: defaultMaxPollInterval, |
| 20 | + shutdown: make(chan struct{}), |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +func TestWithBatchSize(t *testing.T) { |
| 25 | + t.Run("positive value is applied", func(t *testing.T) { |
| 26 | + w := newTestWorker() |
| 27 | + WithBatchSize(50)(w) |
| 28 | + assert.Equal(t, 50, w.batchSize) |
| 29 | + }) |
| 30 | + |
| 31 | + t.Run("zero value is ignored", func(t *testing.T) { |
| 32 | + w := newTestWorker() |
| 33 | + WithBatchSize(0)(w) |
| 34 | + assert.Equal(t, defaultBatchSize, w.batchSize) |
| 35 | + }) |
| 36 | + |
| 37 | + t.Run("negative value is ignored", func(t *testing.T) { |
| 38 | + w := newTestWorker() |
| 39 | + WithBatchSize(-10)(w) |
| 40 | + assert.Equal(t, defaultBatchSize, w.batchSize) |
| 41 | + }) |
| 42 | +} |
| 43 | + |
| 44 | +func TestWithPollInterval(t *testing.T) { |
| 45 | + t.Run("positive duration is applied", func(t *testing.T) { |
| 46 | + w := newTestWorker() |
| 47 | + WithPollInterval(10 * time.Second)(w) |
| 48 | + assert.Equal(t, 10*time.Second, w.pollInterval) |
| 49 | + }) |
| 50 | + |
| 51 | + t.Run("zero duration is ignored", func(t *testing.T) { |
| 52 | + w := newTestWorker() |
| 53 | + WithPollInterval(0)(w) |
| 54 | + assert.Equal(t, defaultPollInterval, w.pollInterval) |
| 55 | + }) |
| 56 | + |
| 57 | + t.Run("negative duration is ignored", func(t *testing.T) { |
| 58 | + w := newTestWorker() |
| 59 | + WithPollInterval(-1 * time.Second)(w) |
| 60 | + assert.Equal(t, defaultPollInterval, w.pollInterval) |
| 61 | + }) |
| 62 | +} |
| 63 | + |
| 64 | +func TestWithMaxRetries(t *testing.T) { |
| 65 | + t.Run("positive value is applied", func(t *testing.T) { |
| 66 | + w := newTestWorker() |
| 67 | + WithMaxRetries(5)(w) |
| 68 | + assert.Equal(t, 5, w.maxRetries) |
| 69 | + }) |
| 70 | + |
| 71 | + t.Run("zero is accepted", func(t *testing.T) { |
| 72 | + w := newTestWorker() |
| 73 | + WithMaxRetries(0)(w) |
| 74 | + assert.Equal(t, 0, w.maxRetries) |
| 75 | + }) |
| 76 | + |
| 77 | + t.Run("negative value is ignored", func(t *testing.T) { |
| 78 | + w := newTestWorker() |
| 79 | + WithMaxRetries(-1)(w) |
| 80 | + assert.Equal(t, defaultMaxRetries, w.maxRetries) |
| 81 | + }) |
| 82 | +} |
| 83 | + |
| 84 | +func TestWithAdaptivePolling(t *testing.T) { |
| 85 | + t.Run("valid min and max are applied", func(t *testing.T) { |
| 86 | + w := newTestWorker() |
| 87 | + WithAdaptivePolling(100*time.Millisecond, 30*time.Second)(w) |
| 88 | + assert.True(t, w.adaptivePolling) |
| 89 | + assert.Equal(t, 100*time.Millisecond, w.minPollInterval) |
| 90 | + assert.Equal(t, 30*time.Second, w.maxPollInterval) |
| 91 | + }) |
| 92 | + |
| 93 | + t.Run("inverted min/max are swapped", func(t *testing.T) { |
| 94 | + w := newTestWorker() |
| 95 | + WithAdaptivePolling(30*time.Second, 100*time.Millisecond)(w) |
| 96 | + assert.True(t, w.adaptivePolling) |
| 97 | + assert.Equal(t, 100*time.Millisecond, w.minPollInterval) |
| 98 | + assert.Equal(t, 30*time.Second, w.maxPollInterval) |
| 99 | + }) |
| 100 | + |
| 101 | + t.Run("zero min interval is ignored", func(t *testing.T) { |
| 102 | + w := newTestWorker() |
| 103 | + WithAdaptivePolling(0, 30*time.Second)(w) |
| 104 | + assert.True(t, w.adaptivePolling) |
| 105 | + assert.Equal(t, defaultMinPollInterval, w.minPollInterval) |
| 106 | + assert.Equal(t, 30*time.Second, w.maxPollInterval) |
| 107 | + }) |
| 108 | + |
| 109 | + t.Run("zero max interval is ignored", func(t *testing.T) { |
| 110 | + w := newTestWorker() |
| 111 | + WithAdaptivePolling(100*time.Millisecond, 0)(w) |
| 112 | + assert.True(t, w.adaptivePolling) |
| 113 | + assert.Equal(t, 100*time.Millisecond, w.minPollInterval) |
| 114 | + assert.Equal(t, defaultMaxPollInterval, w.maxPollInterval) |
| 115 | + }) |
| 116 | +} |
| 117 | + |
| 118 | +func TestCalculateAdaptiveInterval(t *testing.T) { |
| 119 | + min := defaults.DefaultRetryDelay // 100ms |
| 120 | + max := defaults.DefaultRPCTimeout // 30s |
| 121 | + |
| 122 | + t.Run("work found resets to min interval", func(t *testing.T) { |
| 123 | + w := newTestWorker() |
| 124 | + w.minPollInterval = min |
| 125 | + w.maxPollInterval = max |
| 126 | + w.emptyPollCount = 5 // simulate previous idle state |
| 127 | + |
| 128 | + interval := w.calculateAdaptiveInterval(10) |
| 129 | + assert.Equal(t, min, interval) |
| 130 | + assert.Equal(t, 0, w.emptyPollCount) |
| 131 | + }) |
| 132 | + |
| 133 | + t.Run("no work increases interval exponentially", func(t *testing.T) { |
| 134 | + w := newTestWorker() |
| 135 | + w.minPollInterval = min |
| 136 | + w.maxPollInterval = max |
| 137 | + |
| 138 | + // First empty poll: emptyPollCount becomes 1, multiplier = 2^1 = 2 |
| 139 | + interval := w.calculateAdaptiveInterval(0) |
| 140 | + assert.Equal(t, 1, w.emptyPollCount) |
| 141 | + assert.Equal(t, 2*min, interval) |
| 142 | + |
| 143 | + // Second empty poll: emptyPollCount becomes 2, multiplier = 2^2 = 4 |
| 144 | + interval = w.calculateAdaptiveInterval(0) |
| 145 | + assert.Equal(t, 2, w.emptyPollCount) |
| 146 | + assert.Equal(t, 4*min, interval) |
| 147 | + }) |
| 148 | + |
| 149 | + t.Run("interval is capped at max", func(t *testing.T) { |
| 150 | + w := newTestWorker() |
| 151 | + w.minPollInterval = min |
| 152 | + w.maxPollInterval = 200 * time.Millisecond // very small max |
| 153 | + w.emptyPollCount = 20 // large count to exceed max |
| 154 | + |
| 155 | + interval := w.calculateAdaptiveInterval(0) |
| 156 | + assert.Equal(t, 200*time.Millisecond, interval) |
| 157 | + }) |
| 158 | +} |
0 commit comments