Skip to content

Commit c36f0c8

Browse files
committed
feat: add scheduler calls, mocks and unit tests on solana worker
1 parent 104f45c commit c36f0c8

7 files changed

Lines changed: 51 additions & 47 deletions

File tree

.mockery.yaml

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
1-
# Mockery configuration file
2-
3-
# All interfaces in a package are generated by default. You can set this to false in the config of
4-
# of each package to disable this behavior.
51
all: false
6-
with-expecter: true
7-
# The name of the mock file to be generated is the snake cased interface name.
8-
filename: "{{.InterfaceName | snakecase | lower}}.go"
9-
# Creates the mocks in a `mocks` dir inside the package containing the interfaces.
10-
dir: "{{.InterfaceDir}}/mocks"
11-
# The name of the mock struct is the interface name.
12-
mockname: "{{.InterfaceName}}"
13-
# Places the mock package in the same package as the interface.
14-
outpkg: "mocks"
2+
153
packages:
4+
github.com/smartcontractkit/timelock-worker/pkg/timelock:
5+
interfaces:
6+
Scheduler:
7+
config:
8+
dir: "./pkg/timelock"
9+
filename: "scheduler_mock.go"
10+
1611
github.com/ethereum/go-ethereum/accounts/abi/bind:
1712
interfaces:
1813
ContractBackend:
1914
config:
20-
# inpackage: false
21-
filename: "{{.InterfaceName | snakecase}}.go"
22-
# mockname: "{{.InterfaceName}}"
2315
dir: "./pkg/timelock/mocks"
16+
filename: "contract_backend.go"

.tool-versions

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
golang 1.24.3
22
golangci-lint 1.64.8
33
task 3.40.0
4-
mockery 2.50.0
4+
mockery 3.3.2

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/gagliardetto/binary v0.8.0
1212
github.com/gagliardetto/solana-go v1.12.0
1313
github.com/google/go-cmp v0.7.0
14+
github.com/mr-tron/base58 v1.2.0
1415
github.com/prometheus/client_golang v1.21.1
1516
github.com/samber/lo v1.47.0
1617
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240917103524-56f1a8d2cd4b
@@ -129,7 +130,6 @@ require (
129130
github.com/modern-go/reflect2 v1.0.2 // indirect
130131
github.com/morikuni/aec v1.0.0 // indirect
131132
github.com/mostynb/zstdpool-freelist v0.0.0-20201229113212-927304c0c3b1 // indirect
132-
github.com/mr-tron/base58 v1.2.0 // indirect
133133
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
134134
github.com/olekukonko/tablewriter v0.0.5 // indirect
135135
github.com/opencontainers/go-digest v1.0.0 // indirect

pkg/timelock/scheduler_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ func newTestScheduler() *scheduler {
200200
return newScheduler(10*time.Second, logger, execFn)
201201
}
202202

203+
// newMockScheduler returns a mock Scheduler with assertion tracking setup
204+
func newMockScheduler(t *testing.T) *MockScheduler {
205+
mockScheduler := NewMockScheduler(t)
206+
207+
// Example: you can preset mock behavior here if needed
208+
// mockScheduler.On("runScheduler", mock.Anything).Return(make(chan struct{}))
209+
210+
return mockScheduler
211+
}
212+
203213
// generateOpKeys generates a slice of operation keys from a slice of strings.
204214
func generateOpKeys(t *testing.T, in []string) [][32]byte {
205215
t.Helper()

pkg/timelock/worker_solana.go

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,10 @@ func NewTimelockWorkerSolana(
100100
}
101101

102102
if dryRun {
103-
tWorker.scheduler = nil // TODO: add solana nopScheduler implementation
103+
tWorker.scheduler = newNopScheduler(logger)
104104
} else {
105-
tWorker.scheduler = nil // TODO: add solana Scheduler implementation
105+
tWorker.scheduler = newScheduler(time.Duration(pollPeriod)*time.Second, logger, func(context.Context, []TimelockCallScheduled) {})
106106
}
107-
108107
return tWorker, nil
109108
}
110109

@@ -117,7 +116,7 @@ func (w *WorkerSolana) Listen(ctx context.Context) error {
117116
w.startLog()
118117

119118
// Run the scheduler to add/del operations in a thread-safe way.
120-
//schedulingDone = w.scheduler.runScheduler(ctxwc)
119+
schedulingDone := w.scheduler.runScheduler(ctxwc)
121120

122121
//// Retrieve logs asynchronously.
123122
pollDone, txCh := w.pollNewTransactions(ctxwc)
@@ -136,14 +135,14 @@ func (w *WorkerSolana) Listen(ctx context.Context) error {
136135

137136
w.logger.Info("shutting down timelock-worker")
138137
w.logger.Info("dumping operation store")
139-
// TODO: re-add when scheduler is implemented
140-
//w.scheduler.dumpOperationStore(time.Now)
138+
139+
w.scheduler.dumpOperationStore(time.Now)
141140

142141
// Wait for all goroutines to finish.
143142
shutdownCtx, cancel := context.WithTimeout(context.Background(), time.Second*5)
144143
defer cancel()
145144

146-
<-isclosed.All(shutdownCtx, pollDone, procDone) //nolint:contextcheck
145+
<-isclosed.All(shutdownCtx, schedulingDone, pollDone, procDone) //nolint:contextcheck
147146

148147
return nil
149148
}
@@ -341,8 +340,7 @@ func (w *WorkerSolana) handleEventCancelled(_ context.Context, event SolanaTimel
341340
w.logger.With(operationID, fmt.Sprintf("%x", event.ID)).
342341
Infow("event received, cancelling operation", "event type", eventCancelled)
343342

344-
// TODO: add scheduler call once scheduler is implemented
345-
//w.scheduler.delFromScheduler(event.ID)
343+
w.scheduler.delFromScheduler(event.ID)
346344
}
347345

348346
// handleEventExecuted checks if the operation is done and deletes it from the scheduler if it is.
@@ -357,8 +355,8 @@ func (w *WorkerSolana) handleEventExecuted(ctx context.Context, event SolanaTime
357355
}
358356
if isDone {
359357
logger.Infow("event received, deleting operation from scheduler", "event type ", eventCallExecuted)
360-
// TODO: add scheduler call once scheduler is implemented
361-
//w.scheduler.delFromScheduler(event.ID)
358+
359+
w.scheduler.delFromScheduler(event.ID)
362360
} else {
363361
logger.Warn("operation not done; skipping deletion from scheduler")
364362
}
@@ -384,8 +382,7 @@ func (w *WorkerSolana) handleEventScheduled(ctx context.Context, event SolanaTim
384382

385383
if isOp {
386384
logger.Infow("event received", "event type", eventCallScheduled)
387-
// TODO: add scheduler call once scheduler is implemented
388-
// w.scheduler.addToScheduler(cs)
385+
w.scheduler.addToScheduler(&solanaTimelockCallScheduled{callScheduledEvent: event})
389386
} else {
390387
logger.Warn("invalid operation")
391388
}

pkg/timelock/worker_solana_test.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,43 +194,46 @@ func TestPollNewSignatures(t *testing.T) {
194194

195195
func TestHandleEventCancelled(t *testing.T) {
196196
id := [32]byte{1, 2, 3}
197-
197+
s := newMockScheduler(t)
198198
worker := &WorkerSolana{
199-
logger: testLogger,
199+
logger: testLogger,
200+
scheduler: s,
200201
}
201-
202+
s.On("delFromScheduler", mock.Anything).Return(nil)
202203
worker.handleEventCancelled(context.Background(), SolanaTimelockCallCancelledEvent{ID: id})
203-
// TODO: once scheduler is added we can assert expectation from a mock scheduler here.
204204
}
205205

206206
func TestHandleEventExecuted_Done(t *testing.T) {
207207
id := [32]byte{4, 5, 6}
208208
mockInsp := new(mocks.TimelockInspector)
209209
mockInsp.On("IsOperationDone", mock.Anything, "some.addr", id).Return(true, nil)
210-
210+
s := newMockScheduler(t)
211211
worker := &WorkerSolana{
212212
timelockFullAddress: "some.addr",
213213
inspector: mockInsp,
214+
scheduler: s,
214215
logger: testLogger,
215216
}
217+
s.On("delFromScheduler", mock.Anything).Return(nil)
216218
event := SolanaTimelockCallExecutedEvent{ID: id, Target: solana.PublicKey{}}
217219
err := worker.handleEventExecuted(context.Background(), event)
218220
require.NoError(t, err)
219221
mockInsp.AssertExpectations(t)
220-
// TODO: once scheduler is added we can assert expectation from a mock scheduler here.
221222
}
222223

223224
func TestHandleEventScheduled_IsOp(t *testing.T) {
224225
id := [32]byte{7, 8, 9}
225226
mockInsp := new(mocks.TimelockInspector)
226227
mockInsp.On("IsOperationDone", mock.Anything, "some.addr", id).Return(false, nil)
227228
mockInsp.On("IsOperation", mock.Anything, "some.addr", id).Return(true, nil)
228-
229+
s := newMockScheduler(t)
229230
worker := &WorkerSolana{
230231
timelockFullAddress: "some.addr",
231232
inspector: mockInsp,
233+
scheduler: s,
232234
logger: testLogger,
233235
}
236+
s.On("addToScheduler", mock.Anything).Return(nil)
234237
event := SolanaTimelockCallScheduledEvent{ID: id, Target: solana.PublicKey{}}
235238
err := worker.handleEventScheduled(context.Background(), event)
236239
require.NoError(t, err)
@@ -245,6 +248,7 @@ func TestHandleEventScheduled_OperationDone(t *testing.T) {
245248
worker := &WorkerSolana{
246249
timelockFullAddress: "some.addr",
247250
inspector: mockInsp,
251+
scheduler: newMockScheduler(t),
248252
logger: testLogger,
249253
}
250254
event := SolanaTimelockCallScheduledEvent{ID: id, Target: solana.PublicKey{}}
@@ -261,13 +265,13 @@ func TestHandleEventExecuted_NotDone(t *testing.T) {
261265
worker := &WorkerSolana{
262266
timelockFullAddress: "some.addr",
263267
inspector: mockInsp,
268+
scheduler: newMockScheduler(t),
264269
logger: testLogger,
265270
}
266271
event := SolanaTimelockCallExecutedEvent{ID: id, Target: solana.PublicKey{}}
267272
err := worker.handleEventExecuted(context.Background(), event)
268273
require.NoError(t, err)
269274
mockInsp.AssertExpectations(t)
270-
// TODO: once scheduler is added we can assert expectation from a mock scheduler here.
271275
}
272276

273277
func TestHandleEventScheduled_IsOp_Error(t *testing.T) {
@@ -279,6 +283,7 @@ func TestHandleEventScheduled_IsOp_Error(t *testing.T) {
279283
worker := &WorkerSolana{
280284
timelockFullAddress: "some.addr",
281285
inspector: mockInsp,
286+
scheduler: newMockScheduler(t),
282287
logger: testLogger,
283288
}
284289
event := SolanaTimelockCallScheduledEvent{ID: id, Target: solana.PublicKey{}}
@@ -293,9 +298,9 @@ func TestHandleEventExecuted_Error(t *testing.T) {
293298
worker := &WorkerSolana{
294299
timelockFullAddress: "some.addr",
295300
inspector: mockInsp,
301+
scheduler: newMockScheduler(t),
296302
logger: testLogger,
297303
}
298304
event := SolanaTimelockCallExecutedEvent{ID: id, Target: solana.PublicKey{}}
299305
require.ErrorContains(t, worker.handleEventExecuted(context.Background(), event), "timelock.isOperationDone call failed")
300-
// TODO: once scheduler is added we can assert expectation from a mock scheduler here.
301306
}

tests/integration/solana/worker_test.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,11 @@ func (s *solanaIntegrationTestSuite) TestTimelockWorkerListen() {
5454
assert.Equal(collect, logEntries[3].Message, "\tPoll Period")
5555
assert.Equal(collect, logEntries[4].Message, "\tEvent Listener Poll Period")
5656
assert.Equal(collect, logEntries[5].Message, "\tEvent Listener Poll #Logs")
57-
assert.Equal(collect, logEntries[6].Message, "starting pollNewTransactions")
58-
assert.Contains(collect, logEntries[7].Message, "new pollNewTransactions")
59-
assert.Equal(collect, logEntries[8].Message, "found new signatures")
60-
assert.Contains(collect, logEntries[9].Message, "found event scheduled:")
61-
assert.Contains(collect, logEntries[10].Message, "event received")
62-
assert.Contains(collect, logEntries[10].Context[3].Key, "event type")
63-
assert.Contains(collect, logEntries[10].Context[3].String, "CallScheduled")
57+
assert.Equal(collect, logEntries[6].Message, "nop.runScheduler")
58+
assert.Equal(collect, logEntries[7].Message, "starting pollNewTransactions")
59+
assert.Contains(collect, logEntries[8].Message, "new pollNewTransactions")
60+
assert.Equal(collect, logEntries[9].Message, "found new signatures")
61+
assert.Contains(collect, logEntries[10].Message, "found event scheduled:")
62+
assert.Contains(collect, logEntries[11].Message, "event received")
6463
}, 20*time.Second, 200*time.Millisecond)
6564
}

0 commit comments

Comments
 (0)