1- // new_worker_solana_test.go
21package timelock
32
43import (
@@ -14,220 +13,202 @@ import (
1413)
1514
1615func 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
217202func 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