Skip to content

Commit 36777da

Browse files
committed
fix: refactor unit tests
1 parent e7dec7c commit 36777da

1 file changed

Lines changed: 144 additions & 176 deletions

File tree

pkg/timelock/worker_solana_test.go

Lines changed: 144 additions & 176 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// new_worker_solana_test.go
21
package timelock
32

43
import (
@@ -14,220 +13,202 @@ import (
1413
)
1514

1615
func TestNewTimelockWorkerSolana(t *testing.T) {
17-
// Prepare one valid keypair for tests
16+
// prepare keypair
1817
priv, err := solana.NewRandomPrivateKey()
1918
require.NoError(t, err)
2019
privStr := priv.String()
2120
pubStr := priv.PublicKey().String()
2221

23-
// Dummy callProxyAddress (unused in constructor)
24-
callProxy := pubStr
25-
// fromBlock is unused by NewTimelockWorkerSolana; just pass zero
2622
fromBlock := big.NewInt(0)
27-
2823
logger := zap.NewNop().Sugar()
2924

3025
tests := []struct {
31-
name string
32-
nodeURL string
33-
timelockAddress string
34-
callProxyAddress string
35-
privateKey string
36-
fromBlock *big.Int
37-
pollPeriod int64
38-
listenerPollPeriod int64
39-
pollSize uint64
40-
dryRun bool
41-
wantErr bool
42-
errContainsSubstring string
26+
name string
27+
nodeURL string
28+
timelockAddress string
29+
privateKey string
30+
fromBlock *big.Int
31+
pollPeriod int64
32+
listenerPoll int64
33+
pollSize uint64
34+
dryRun bool
35+
errContains string
36+
want func(t *testing.T, w *WorkerSolana, err error)
4337
}{
38+
// happy path
4439
{
45-
name: "invalid URL syntax",
46-
nodeURL: "://not-a-url",
47-
timelockAddress: pubStr,
48-
callProxyAddress: callProxy,
49-
privateKey: privStr,
50-
fromBlock: fromBlock,
51-
pollPeriod: 1,
52-
listenerPollPeriod: 1,
53-
pollSize: 1,
54-
dryRun: true,
55-
wantErr: true,
56-
errContainsSubstring: "parse \"://not-a-url\"",
57-
},
58-
{
59-
name: "unsupported scheme",
60-
nodeURL: "ftp://example.com",
61-
timelockAddress: pubStr,
62-
callProxyAddress: callProxy,
63-
privateKey: privStr,
64-
fromBlock: fromBlock,
65-
pollPeriod: 1,
66-
listenerPollPeriod: 1,
67-
pollSize: 1,
68-
dryRun: false,
69-
wantErr: true,
70-
errContainsSubstring: "invalid node URL",
40+
name: "valid HTTP",
41+
nodeURL: "https://example.com",
42+
timelockAddress: pubStr,
43+
privateKey: privStr,
44+
fromBlock: fromBlock,
45+
pollPeriod: 5,
46+
listenerPoll: 5,
47+
pollSize: 10,
48+
dryRun: true,
49+
want: func(t *testing.T, w *WorkerSolana, err error) {
50+
require.NoError(t, err)
51+
require.NotNil(t, w)
52+
require.Equal(t, int64(5), w.pollPeriod)
53+
require.Equal(t, int64(5), w.listenerPollPeriod)
54+
require.Equal(t, uint64(10), w.pollSize)
55+
require.True(t, w.dryRun)
56+
expectedPk, _ := solana.PublicKeyFromBase58(pubStr)
57+
require.True(t, expectedPk.Equals(w.timelockProgramKey))
58+
require.Equal(t, privStr, w.privateKey.String())
59+
require.Nil(t, w.scheduler)
60+
},
7161
},
62+
// error cases
7263
{
73-
name: "invalid timelock address",
74-
nodeURL: "http://example.com",
75-
timelockAddress: "notBase58",
76-
callProxyAddress: callProxy,
77-
privateKey: privStr,
78-
fromBlock: fromBlock,
79-
pollPeriod: 1,
80-
listenerPollPeriod: 1,
81-
pollSize: 1,
82-
dryRun: false,
83-
wantErr: true,
84-
errContainsSubstring: "timelock addresses provided is not valid",
64+
name: "invalid URL syntax",
65+
nodeURL: "://bad",
66+
timelockAddress: pubStr,
67+
privateKey: privStr,
68+
fromBlock: fromBlock,
69+
pollPeriod: 1,
70+
listenerPoll: 1,
71+
pollSize: 1,
72+
dryRun: false,
73+
errContains: "parse \"://bad\"",
74+
want: func(t *testing.T, w *WorkerSolana, err error) {
75+
require.Error(t, err)
76+
require.Contains(t, err.Error(), "parse \"://bad\": missing protocol scheme")
77+
require.Nil(t, w)
78+
},
8579
},
8680
{
87-
name: "negative pollPeriod",
88-
nodeURL: "http://example.com",
89-
timelockAddress: pubStr,
90-
callProxyAddress: callProxy,
91-
privateKey: privStr,
92-
fromBlock: fromBlock,
93-
pollPeriod: 0,
94-
listenerPollPeriod: 1,
95-
pollSize: 1,
96-
dryRun: false,
97-
wantErr: true,
98-
errContainsSubstring: "poll-period must be a positive non-zero integer",
81+
name: "unsupported scheme",
82+
nodeURL: "ftp://example.com",
83+
timelockAddress: pubStr,
84+
privateKey: privStr,
85+
fromBlock: fromBlock,
86+
pollPeriod: 1,
87+
listenerPoll: 1,
88+
pollSize: 1,
89+
dryRun: false,
90+
errContains: "invalid node URL",
91+
want: func(t *testing.T, w *WorkerSolana, err error) {
92+
require.Error(t, err)
93+
require.Contains(t, err.Error(), "invalid node URL")
94+
require.Nil(t, w)
95+
},
9996
},
10097
{
101-
name: "zero listenerPollPeriod on HTTP",
102-
nodeURL: "https://example.com",
103-
timelockAddress: pubStr,
104-
callProxyAddress: callProxy,
105-
privateKey: privStr,
106-
fromBlock: fromBlock,
107-
pollPeriod: 1,
108-
listenerPollPeriod: 0,
109-
pollSize: 1,
110-
dryRun: false,
111-
wantErr: true,
112-
errContainsSubstring: "event-listener-poll-period must be a positive non-zero integer",
98+
name: "invalid timelock address",
99+
nodeURL: "http://example.com",
100+
timelockAddress: "notBase58",
101+
privateKey: privStr,
102+
fromBlock: fromBlock,
103+
pollPeriod: 1,
104+
listenerPoll: 1,
105+
pollSize: 1,
106+
dryRun: false,
107+
errContains: "timelock addresses provided is not valid",
108+
want: func(t *testing.T, w *WorkerSolana, err error) {
109+
require.Error(t, err)
110+
require.Contains(t, err.Error(), "timelock addresses provided is not valid")
111+
require.Nil(t, w)
112+
},
113113
},
114114
{
115-
name: "zero pollSize on HTTP",
116-
nodeURL: "http://example.com",
117-
timelockAddress: pubStr,
118-
callProxyAddress: callProxy,
119-
privateKey: privStr,
120-
fromBlock: fromBlock,
121-
pollPeriod: 1,
122-
listenerPollPeriod: 1,
123-
pollSize: 0,
124-
dryRun: false,
125-
wantErr: true,
126-
errContainsSubstring: "event-listener-poll-size must be a positive non-zero integer",
115+
name: "negative pollPeriod",
116+
nodeURL: "http://example.com",
117+
timelockAddress: pubStr,
118+
privateKey: privStr,
119+
fromBlock: fromBlock,
120+
pollPeriod: 0,
121+
listenerPoll: 1,
122+
pollSize: 1,
123+
dryRun: false,
124+
errContains: "poll-period must be a positive non-zero integer",
125+
want: func(t *testing.T, w *WorkerSolana, err error) {
126+
require.Error(t, err)
127+
require.Contains(t, err.Error(), "poll-period must be a positive non-zero integer")
128+
require.Nil(t, w)
129+
},
127130
},
128131
{
129-
name: "valid HTTP parameters",
130-
nodeURL: "https://example.com",
131-
timelockAddress: pubStr,
132-
callProxyAddress: callProxy,
133-
privateKey: privStr,
134-
fromBlock: fromBlock,
135-
pollPeriod: 5,
136-
listenerPollPeriod: 5,
137-
pollSize: 10,
138-
dryRun: true,
139-
wantErr: false,
132+
name: "zero listenerPoll on HTTP",
133+
nodeURL: "https://example.com",
134+
timelockAddress: pubStr,
135+
privateKey: privStr,
136+
fromBlock: fromBlock,
137+
pollPeriod: 1,
138+
listenerPoll: 0,
139+
pollSize: 1,
140+
dryRun: false,
141+
errContains: "event-listener-poll-period must be a positive non-zero integer",
142+
want: func(t *testing.T, w *WorkerSolana, err error) {
143+
require.Error(t, err)
144+
require.Contains(t, err.Error(), "event-listener-poll-period must be a positive non-zero integer")
145+
require.Nil(t, w)
146+
},
140147
},
141148
{
142-
name: "valid WS parameters ignore HTTP-only checks",
143-
nodeURL: "ws://example.com",
144-
timelockAddress: pubStr,
145-
callProxyAddress: callProxy,
146-
privateKey: privStr,
147-
fromBlock: fromBlock,
148-
pollPeriod: 2,
149-
listenerPollPeriod: 0,
150-
pollSize: 0,
151-
dryRun: false,
152-
wantErr: false,
149+
name: "zero pollSize on HTTP",
150+
nodeURL: "http://example.com",
151+
timelockAddress: pubStr,
152+
privateKey: privStr,
153+
fromBlock: fromBlock,
154+
pollPeriod: 1,
155+
listenerPoll: 1,
156+
pollSize: 0,
157+
dryRun: false,
158+
errContains: "event-listener-poll-size must be a positive non-zero integer",
159+
want: func(t *testing.T, w *WorkerSolana, err error) {
160+
require.Error(t, err)
161+
require.Contains(t, err.Error(), "event-listener-poll-size must be a positive non-zero integer")
162+
require.Nil(t, w)
163+
},
153164
},
154165
{
155-
name: "invalid private key",
156-
nodeURL: "http://example.com",
157-
timelockAddress: pubStr,
158-
callProxyAddress: callProxy,
159-
privateKey: "notBase58",
160-
fromBlock: fromBlock,
161-
pollPeriod: 1,
162-
listenerPollPeriod: 1,
163-
pollSize: 1,
164-
dryRun: false,
165-
wantErr: true,
166-
errContainsSubstring: "the provided private key is not valid",
166+
name: "invalid private key",
167+
nodeURL: "http://example.com",
168+
timelockAddress: pubStr,
169+
privateKey: "notBase58",
170+
fromBlock: fromBlock,
171+
pollPeriod: 1,
172+
listenerPoll: 1,
173+
pollSize: 1,
174+
dryRun: false,
175+
errContains: "the provided private key is not valid",
176+
want: func(t *testing.T, w *WorkerSolana, err error) {
177+
require.Error(t, err)
178+
require.Contains(t, err.Error(), "the provided private key is not valid")
179+
require.Nil(t, w)
180+
},
167181
},
168182
}
169183

170184
for _, tc := range tests {
171-
tc := tc // capture range variable
172185
t.Run(tc.name, func(t *testing.T) {
173186
w, err := NewTimelockWorkerSolana(
174187
tc.nodeURL,
175188
tc.timelockAddress,
176-
tc.callProxyAddress,
177189
tc.privateKey,
178190
tc.fromBlock,
179191
tc.pollPeriod,
180-
tc.listenerPollPeriod,
192+
tc.listenerPoll,
181193
tc.pollSize,
182194
tc.dryRun,
183195
logger,
184196
)
185-
if tc.wantErr {
186-
require.Error(t, err)
187-
if tc.errContainsSubstring != "" {
188-
require.Contains(t, err.Error(), tc.errContainsSubstring)
189-
}
190-
require.Nil(t, w)
191-
return
192-
}
193-
194-
require.NoError(t, err)
195-
require.NotNil(t, w)
196-
197-
// verify fields were set correctly
198-
require.Equal(t, tc.pollPeriod, w.pollPeriod)
199-
require.Equal(t, tc.listenerPollPeriod, w.listenerPollPeriod)
200-
require.Equal(t, tc.pollSize, w.pollSize)
201-
require.Equal(t, tc.dryRun, w.dryRun)
202-
203-
// timelockProgramKey should parse back to the same PublicKey
204-
expectedPk, pkErr := solana.PublicKeyFromBase58(tc.timelockAddress)
205-
require.NoError(t, pkErr)
206-
require.True(t, expectedPk.Equals(w.timelockProgramKey))
207-
208-
// privateKey should round-trip through Base58
209-
require.Equal(t, privStr, w.privateKey.String())
210-
211-
// scheduler is still nil (TODO)
212-
require.Nil(t, w.scheduler)
197+
tc.want(t, w, err)
213198
})
214199
}
215200
}
216201

217202
func TestListen_PanicAndLogs(t *testing.T) {
218-
// set up an observer to capture logs at Info level
219203
core, recorded := observer.New(zap.InfoLevel)
220204
logger := zap.New(core).Sugar()
221205

222-
// dummy solana client and key
223206
client := rpc.New("http://example.com")
224207
programKey, err := solana.PublicKeyFromBase58("11111111111111111111111111111111")
225208
require.NoError(t, err)
226209
priv, err := solana.NewRandomPrivateKey()
227210
require.NoError(t, err)
228211

229-
// build WorkerSolana with fake scheduler
230-
231212
w := &WorkerSolana{
232213
solanaClient: client,
233214
timelockProgramKey: programKey,
@@ -240,28 +221,15 @@ func TestListen_PanicAndLogs(t *testing.T) {
240221
lastSignature: nil,
241222
}
242223

243-
// Calling Listen should panic for now
244-
// TODO: remove once log polling and scheduler are implemented
245224
require.Panics(t, func() {
246225
_ = w.Listen(context.Background())
247226
})
248227

249-
// Inspect captured logs
250228
logs := recorded.All()
251-
require.GreaterOrEqual(t, len(logs), 5, "expected at least 5 log entries")
252-
253-
// 1st log: worker start
229+
require.GreaterOrEqual(t, len(logs), 5)
254230
require.Equal(t, "timelock-worker started [solana]", logs[0].Message)
255-
256-
// 2nd log: program address line
257231
require.Contains(t, logs[1].Message, w.timelockProgramKey.String())
258-
259-
// 3rd log: solana account address
260-
require.Contains(t, logs[2].Message, "solana account address:")
261-
262-
// 4th log: poll period
232+
require.Contains(t, logs[2].Message, "Solana account address:")
263233
require.Contains(t, logs[3].Message, "Poll Period:")
264-
265-
// 5th log: listener poll period or poll size
266234
require.Contains(t, logs[4].Message, "Event Listener Poll Period:")
267235
}

0 commit comments

Comments
 (0)