chainsvrwsntfns_test.go raw
1 package btcjson_test
2
3 import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "reflect"
8 "testing"
9
10 "github.com/p9c/p9/pkg/btcjson"
11 )
12
13 // TestChainSvrWsNtfns tests all of the chain server websocket-specific notifications marshal and unmarshal into valid
14 // results include handling of optional fields being omitted in the marshalled command, while optional fields with
15 // defaults have the default assigned on unmarshalled commands.
16 func TestChainSvrWsNtfns(t *testing.T) {
17 t.Parallel()
18 tests := []struct {
19 name string
20 newNtfn func() (interface{}, error)
21 staticNtfn func() interface{}
22 marshalled string
23 unmarshalled interface{}
24 }{
25 {
26 name: "blockconnected",
27 newNtfn: func() (interface{}, error) {
28 return btcjson.NewCmd("blockconnected", "123", 100000, 123456789)
29 },
30 staticNtfn: func() interface{} {
31 return btcjson.NewBlockConnectedNtfn("123", 100000, 123456789)
32 },
33 marshalled: `{"jsonrpc":"1.0","method":"blockconnected","netparams":["123",100000,123456789],"id":null}`,
34 unmarshalled: &btcjson.BlockConnectedNtfn{
35 Hash: "123",
36 Height: 100000,
37 Time: 123456789,
38 },
39 },
40 {
41 name: "blockdisconnected",
42 newNtfn: func() (interface{}, error) {
43 return btcjson.NewCmd("blockdisconnected", "123", 100000, 123456789)
44 },
45 staticNtfn: func() interface{} {
46 return btcjson.NewBlockDisconnectedNtfn("123", 100000, 123456789)
47 },
48 marshalled: `{"jsonrpc":"1.0","method":"blockdisconnected","netparams":["123",100000,123456789],"id":null}`,
49 unmarshalled: &btcjson.BlockDisconnectedNtfn{
50 Hash: "123",
51 Height: 100000,
52 Time: 123456789,
53 },
54 },
55 {
56 name: "filteredblockconnected",
57 newNtfn: func() (interface{}, error) {
58 return btcjson.NewCmd("filteredblockconnected", 100000, "header", []string{"tx0", "tx1"})
59 },
60 staticNtfn: func() interface{} {
61 return btcjson.NewFilteredBlockConnectedNtfn(100000, "header", []string{"tx0", "tx1"})
62 },
63 marshalled: `{"jsonrpc":"1.0","method":"filteredblockconnected","netparams":[100000,"header",["tx0","tx1"]],"id":null}`,
64 unmarshalled: &btcjson.FilteredBlockConnectedNtfn{
65 Height: 100000,
66 Header: "header",
67 SubscribedTxs: []string{"tx0", "tx1"},
68 },
69 },
70 {
71 name: "filteredblockdisconnected",
72 newNtfn: func() (interface{}, error) {
73 return btcjson.NewCmd("filteredblockdisconnected", 100000, "header")
74 },
75 staticNtfn: func() interface{} {
76 return btcjson.NewFilteredBlockDisconnectedNtfn(100000, "header")
77 },
78 marshalled: `{"jsonrpc":"1.0","method":"filteredblockdisconnected","netparams":[100000,"header"],"id":null}`,
79 unmarshalled: &btcjson.FilteredBlockDisconnectedNtfn{
80 Height: 100000,
81 Header: "header",
82 },
83 },
84 {
85 name: "recvtx",
86 newNtfn: func() (interface{}, error) {
87 return btcjson.NewCmd("recvtx", "001122", `{"height":100000,"hash":"123","index":0,"time":12345678}`)
88 },
89 staticNtfn: func() interface{} {
90 blockDetails := btcjson.BlockDetails{
91 Height: 100000,
92 Hash: "123",
93 Index: 0,
94 Time: 12345678,
95 }
96 return btcjson.NewRecvTxNtfn("001122", &blockDetails)
97 },
98 marshalled: `{"jsonrpc":"1.0","method":"recvtx","netparams":["001122",{"height":100000,"hash":"123","index":0,"time":12345678}],"id":null}`,
99 unmarshalled: &btcjson.RecvTxNtfn{
100 HexTx: "001122",
101 Block: &btcjson.BlockDetails{
102 Height: 100000,
103 Hash: "123",
104 Index: 0,
105 Time: 12345678,
106 },
107 },
108 },
109 {
110 name: "redeemingtx",
111 newNtfn: func() (interface{}, error) {
112 return btcjson.NewCmd("redeemingtx", "001122",
113 `{"height":100000,"hash":"123","index":0,"time":12345678}`,
114 )
115 },
116 staticNtfn: func() interface{} {
117 blockDetails := btcjson.BlockDetails{
118 Height: 100000,
119 Hash: "123",
120 Index: 0,
121 Time: 12345678,
122 }
123 return btcjson.NewRedeemingTxNtfn("001122", &blockDetails)
124 },
125 marshalled: `{"jsonrpc":"1.0","method":"redeemingtx","netparams":["001122",{"height":100000,"hash":"123","index":0,"time":12345678}],"id":null}`,
126 unmarshalled: &btcjson.RedeemingTxNtfn{
127 HexTx: "001122",
128 Block: &btcjson.BlockDetails{
129 Height: 100000,
130 Hash: "123",
131 Index: 0,
132 Time: 12345678,
133 },
134 },
135 },
136 {
137 name: "rescanfinished",
138 newNtfn: func() (interface{}, error) {
139 return btcjson.NewCmd("rescanfinished", "123", 100000, 12345678)
140 },
141 staticNtfn: func() interface{} {
142 return btcjson.NewRescanFinishedNtfn("123", 100000, 12345678)
143 },
144 marshalled: `{"jsonrpc":"1.0","method":"rescanfinished","netparams":["123",100000,12345678],"id":null}`,
145 unmarshalled: &btcjson.RescanFinishedNtfn{
146 Hash: "123",
147 Height: 100000,
148 Time: 12345678,
149 },
150 },
151 {
152 name: "rescanprogress",
153 newNtfn: func() (interface{}, error) {
154 return btcjson.NewCmd("rescanprogress", "123", 100000, 12345678)
155 },
156 staticNtfn: func() interface{} {
157 return btcjson.NewRescanProgressNtfn("123", 100000, 12345678)
158 },
159 marshalled: `{"jsonrpc":"1.0","method":"rescanprogress","netparams":["123",100000,12345678],"id":null}`,
160 unmarshalled: &btcjson.RescanProgressNtfn{
161 Hash: "123",
162 Height: 100000,
163 Time: 12345678,
164 },
165 },
166 {
167 name: "txaccepted",
168 newNtfn: func() (interface{}, error) {
169 return btcjson.NewCmd("txaccepted", "123", 1.5)
170 },
171 staticNtfn: func() interface{} {
172 return btcjson.NewTxAcceptedNtfn("123", 1.5)
173 },
174 marshalled: `{"jsonrpc":"1.0","method":"txaccepted","netparams":["123",1.5],"id":null}`,
175 unmarshalled: &btcjson.TxAcceptedNtfn{
176 TxID: "123",
177 Amount: 1.5,
178 },
179 },
180 {
181 name: "txacceptedverbose",
182 newNtfn: func() (interface{}, error) {
183 return btcjson.NewCmd("txacceptedverbose",
184 `{"hex":"001122","txid":"123","version":1,"locktime":4294967295,"vin":null,"vout":null,"confirmations":0}`,
185 )
186 },
187 staticNtfn: func() interface{} {
188 txResult := btcjson.TxRawResult{
189 Hex: "001122",
190 Txid: "123",
191 Version: 1,
192 LockTime: 4294967295,
193 Vin: nil,
194 Vout: nil,
195 Confirmations: 0,
196 }
197 return btcjson.NewTxAcceptedVerboseNtfn(txResult)
198 },
199 marshalled: `{"jsonrpc":"1.0","method":"txacceptedverbose","netparams":[{"hex":"001122","txid":"123","version":1,"locktime":4294967295,"vin":null,"vout":null}],"id":null}`,
200 unmarshalled: &btcjson.TxAcceptedVerboseNtfn{
201 RawTx: btcjson.TxRawResult{
202 Hex: "001122",
203 Txid: "123",
204 Version: 1,
205 LockTime: 4294967295,
206 Vin: nil,
207 Vout: nil,
208 Confirmations: 0,
209 },
210 },
211 },
212 {
213 name: "relevanttxaccepted",
214 newNtfn: func() (interface{}, error) {
215 return btcjson.NewCmd("relevanttxaccepted", "001122")
216 },
217 staticNtfn: func() interface{} {
218 return btcjson.NewRelevantTxAcceptedNtfn("001122")
219 },
220 marshalled: `{"jsonrpc":"1.0","method":"relevanttxaccepted","netparams":["001122"],"id":null}`,
221 unmarshalled: &btcjson.RelevantTxAcceptedNtfn{
222 Transaction: "001122",
223 },
224 },
225 }
226 t.Logf("Running %d tests", len(tests))
227 for i, test := range tests {
228 // Marshal the notification as created by the new static creation function. The ID is nil for notifications.
229 marshalled, e := btcjson.MarshalCmd(nil, test.staticNtfn())
230 if e != nil {
231 t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
232 test.name, e,
233 )
234 continue
235 }
236 if !bytes.Equal(marshalled, []byte(test.marshalled)) {
237 t.Errorf("Test #%d (%s) unexpected marshalled data - "+
238 "got %s, want %s", i, test.name, marshalled,
239 test.marshalled,
240 )
241 continue
242 }
243 // Ensure the notification is created without error via the generic new notification creation function.
244 cmd, e := test.newNtfn()
245 if e != nil {
246 t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
247 i, test.name, e,
248 )
249 }
250 // Marshal the notification as created by the generic new notification creation function. The ID is nil for
251 // notifications.
252 marshalled, e = btcjson.MarshalCmd(nil, cmd)
253 if e != nil {
254 t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
255 test.name, e,
256 )
257 continue
258 }
259 if !bytes.Equal(marshalled, []byte(test.marshalled)) {
260 t.Errorf("Test #%d (%s) unexpected marshalled data - "+
261 "got %s, want %s", i, test.name, marshalled,
262 test.marshalled,
263 )
264 continue
265 }
266 var request btcjson.Request
267 if e = json.Unmarshal(marshalled, &request); E.Chk(e) {
268 t.Errorf("Test #%d (%s) unexpected error while "+
269 "unmarshalling JSON-RPC request: %v", i,
270 test.name, e,
271 )
272 continue
273 }
274 cmd, e = btcjson.UnmarshalCmd(&request)
275 if e != nil {
276 t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
277 test.name, e,
278 )
279 continue
280 }
281 if !reflect.DeepEqual(cmd, test.unmarshalled) {
282 t.Errorf("Test #%d (%s) unexpected unmarshalled command "+
283 "- got %s, want %s", i, test.name,
284 fmt.Sprintf("(%T) %+[1]v", cmd),
285 fmt.Sprintf("(%T) %+[1]v\n", test.unmarshalled),
286 )
287 continue
288 }
289 }
290 }
291