chainsvrwscmds_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 // TestChainSvrWsCmds tests all of the chain server websocket-specific commands marshal and unmarshal into valid results
14 // include handling of optional fields being omitted in the marshalled command, while optional fields with defaults have
15 // the default assigned on unmarshalled commands.
16 func TestChainSvrWsCmds(t *testing.T) {
17 t.Parallel()
18 testID := 1
19 tests := []struct {
20 name string
21 newCmd func() (interface{}, error)
22 staticCmd func() interface{}
23 marshalled string
24 unmarshalled interface{}
25 }{
26 {
27 name: "authenticate",
28 newCmd: func() (interface{}, error) {
29 return btcjson.NewCmd("authenticate", "user", "pass")
30 },
31 staticCmd: func() interface{} {
32 return btcjson.NewAuthenticateCmd("user", "pass")
33 },
34 marshalled: `{"jsonrpc":"1.0","method":"authenticate","netparams":["user","pass"],"id":1}`,
35 unmarshalled: &btcjson.AuthenticateCmd{Username: "user", Passphrase: "pass"},
36 },
37 {
38 name: "notifyblocks",
39 newCmd: func() (interface{}, error) {
40 return btcjson.NewCmd("notifyblocks")
41 },
42 staticCmd: func() interface{} {
43 return btcjson.NewNotifyBlocksCmd()
44 },
45 marshalled: `{"jsonrpc":"1.0","method":"notifyblocks","netparams":[],"id":1}`,
46 unmarshalled: &btcjson.NotifyBlocksCmd{},
47 },
48 {
49 name: "stopnotifyblocks",
50 newCmd: func() (interface{}, error) {
51 return btcjson.NewCmd("stopnotifyblocks")
52 },
53 staticCmd: func() interface{} {
54 return btcjson.NewStopNotifyBlocksCmd()
55 },
56 marshalled: `{"jsonrpc":"1.0","method":"stopnotifyblocks","netparams":[],"id":1}`,
57 unmarshalled: &btcjson.StopNotifyBlocksCmd{},
58 },
59 {
60 name: "notifynewtransactions",
61 newCmd: func() (interface{}, error) {
62 return btcjson.NewCmd("notifynewtransactions")
63 },
64 staticCmd: func() interface{} {
65 return btcjson.NewNotifyNewTransactionsCmd(nil)
66 },
67 marshalled: `{"jsonrpc":"1.0","method":"notifynewtransactions","netparams":[],"id":1}`,
68 unmarshalled: &btcjson.NotifyNewTransactionsCmd{
69 Verbose: btcjson.Bool(false),
70 },
71 },
72 {
73 name: "notifynewtransactions optional",
74 newCmd: func() (interface{}, error) {
75 return btcjson.NewCmd("notifynewtransactions", true)
76 },
77 staticCmd: func() interface{} {
78 return btcjson.NewNotifyNewTransactionsCmd(btcjson.Bool(true))
79 },
80 marshalled: `{"jsonrpc":"1.0","method":"notifynewtransactions","netparams":[true],"id":1}`,
81 unmarshalled: &btcjson.NotifyNewTransactionsCmd{
82 Verbose: btcjson.Bool(true),
83 },
84 },
85 {
86 name: "stopnotifynewtransactions",
87 newCmd: func() (interface{}, error) {
88 return btcjson.NewCmd("stopnotifynewtransactions")
89 },
90 staticCmd: func() interface{} {
91 return btcjson.NewStopNotifyNewTransactionsCmd()
92 },
93 marshalled: `{"jsonrpc":"1.0","method":"stopnotifynewtransactions","netparams":[],"id":1}`,
94 unmarshalled: &btcjson.StopNotifyNewTransactionsCmd{},
95 },
96 {
97 name: "notifyreceived",
98 newCmd: func() (interface{}, error) {
99 return btcjson.NewCmd("notifyreceived", []string{"1Address"})
100 },
101 staticCmd: func() interface{} {
102 return btcjson.NewNotifyReceivedCmd([]string{"1Address"})
103 },
104 marshalled: `{"jsonrpc":"1.0","method":"notifyreceived","netparams":[["1Address"]],"id":1}`,
105 unmarshalled: &btcjson.NotifyReceivedCmd{
106 Addresses: []string{"1Address"},
107 },
108 },
109 {
110 name: "stopnotifyreceived",
111 newCmd: func() (interface{}, error) {
112 return btcjson.NewCmd("stopnotifyreceived", []string{"1Address"})
113 },
114 staticCmd: func() interface{} {
115 return btcjson.NewStopNotifyReceivedCmd([]string{"1Address"})
116 },
117 marshalled: `{"jsonrpc":"1.0","method":"stopnotifyreceived","netparams":[["1Address"]],"id":1}`,
118 unmarshalled: &btcjson.StopNotifyReceivedCmd{
119 Addresses: []string{"1Address"},
120 },
121 },
122 {
123 name: "notifyspent",
124 newCmd: func() (interface{}, error) {
125 return btcjson.NewCmd("notifyspent", `[{"hash":"123","index":0}]`)
126 },
127 staticCmd: func() interface{} {
128 ops := []btcjson.OutPoint{{Hash: "123", Index: 0}}
129 return btcjson.NewNotifySpentCmd(ops)
130 },
131 marshalled: `{"jsonrpc":"1.0","method":"notifyspent","netparams":[[{"hash":"123","index":0}]],"id":1}`,
132 unmarshalled: &btcjson.NotifySpentCmd{
133 OutPoints: []btcjson.OutPoint{{Hash: "123", Index: 0}},
134 },
135 },
136 {
137 name: "stopnotifyspent",
138 newCmd: func() (interface{}, error) {
139 return btcjson.NewCmd("stopnotifyspent", `[{"hash":"123","index":0}]`)
140 },
141 staticCmd: func() interface{} {
142 ops := []btcjson.OutPoint{{Hash: "123", Index: 0}}
143 return btcjson.NewStopNotifySpentCmd(ops)
144 },
145 marshalled: `{"jsonrpc":"1.0","method":"stopnotifyspent","netparams":[[{"hash":"123","index":0}]],"id":1}`,
146 unmarshalled: &btcjson.StopNotifySpentCmd{
147 OutPoints: []btcjson.OutPoint{{Hash: "123", Index: 0}},
148 },
149 },
150 {
151 name: "rescan",
152 newCmd: func() (interface{}, error) {
153 return btcjson.NewCmd("rescan", "123", `["1Address"]`,
154 `[{"hash":"0000000000000000000000000000000000000000000000000000000000000123","index":0}]`,
155 )
156 },
157 staticCmd: func() interface{} {
158 addrs := []string{"1Address"}
159 ops := []btcjson.OutPoint{{
160 Hash: "0000000000000000000000000000000000000000000000000000000000000123",
161 Index: 0,
162 },
163 }
164 return btcjson.NewRescanCmd("123", addrs, ops, nil)
165 },
166 marshalled: `{"jsonrpc":"1.0","method":"rescan","netparams":["123",["1Address"],[{"hash":"0000000000000000000000000000000000000000000000000000000000000123","index":0}]],"id":1}`,
167 unmarshalled: &btcjson.RescanCmd{
168 BeginBlock: "123",
169 Addresses: []string{"1Address"},
170 OutPoints: []btcjson.OutPoint{{Hash: "0000000000000000000000000000000000000000000000000000000000000123",
171 Index: 0,
172 },
173 },
174 EndBlock: nil,
175 },
176 },
177 {
178 name: "rescan optional",
179 newCmd: func() (interface{}, error) {
180 return btcjson.NewCmd("rescan", "123", `["1Address"]`, `[{"hash":"123","index":0}]`, "456")
181 },
182 staticCmd: func() interface{} {
183 addrs := []string{"1Address"}
184 ops := []btcjson.OutPoint{{Hash: "123", Index: 0}}
185 return btcjson.NewRescanCmd("123", addrs, ops, btcjson.String("456"))
186 },
187 marshalled: `{"jsonrpc":"1.0","method":"rescan","netparams":["123",["1Address"],[{"hash":"123","index":0}],"456"],"id":1}`,
188 unmarshalled: &btcjson.RescanCmd{
189 BeginBlock: "123",
190 Addresses: []string{"1Address"},
191 OutPoints: []btcjson.OutPoint{{Hash: "123", Index: 0}},
192 EndBlock: btcjson.String("456"),
193 },
194 },
195 {
196 name: "loadtxfilter",
197 newCmd: func() (interface{}, error) {
198 return btcjson.NewCmd("loadtxfilter", false, `["1Address"]`,
199 `[{"hash":"0000000000000000000000000000000000000000000000000000000000000123","index":0}]`,
200 )
201 },
202 staticCmd: func() interface{} {
203 addrs := []string{"1Address"}
204 ops := []btcjson.OutPoint{{
205 Hash: "0000000000000000000000000000000000000000000000000000000000000123",
206 Index: 0,
207 },
208 }
209 return btcjson.NewLoadTxFilterCmd(false, addrs, ops)
210 },
211 marshalled: `{"jsonrpc":"1.0","method":"loadtxfilter","netparams":[false,["1Address"],[{"hash":"0000000000000000000000000000000000000000000000000000000000000123","index":0}]],"id":1}`,
212 unmarshalled: &btcjson.LoadTxFilterCmd{
213 Reload: false,
214 Addresses: []string{"1Address"},
215 OutPoints: []btcjson.OutPoint{{Hash: "0000000000000000000000000000000000000000000000000000000000000123",
216 Index: 0,
217 },
218 },
219 },
220 },
221 {
222 name: "rescanblocks",
223 newCmd: func() (interface{}, error) {
224 return btcjson.NewCmd("rescanblocks",
225 `["0000000000000000000000000000000000000000000000000000000000000123"]`,
226 )
227 },
228 staticCmd: func() interface{} {
229 blockhashes := []string{"0000000000000000000000000000000000000000000000000000000000000123"}
230 return btcjson.NewRescanBlocksCmd(blockhashes)
231 },
232 marshalled: `{"jsonrpc":"1.0","method":"rescanblocks","netparams":[["0000000000000000000000000000000000000000000000000000000000000123"]],"id":1}`,
233 unmarshalled: &btcjson.RescanBlocksCmd{
234 BlockHashes: []string{"0000000000000000000000000000000000000000000000000000000000000123"},
235 },
236 },
237 }
238 t.Logf("Running %d tests", len(tests))
239 for i, test := range tests {
240 // Marshal the command as created by the new static command creation function.
241 marshalled, e := btcjson.MarshalCmd(testID, test.staticCmd())
242 if e != nil {
243 t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
244 test.name, e,
245 )
246 continue
247 }
248 if !bytes.Equal(marshalled, []byte(test.marshalled)) {
249 t.Errorf("Test #%d (%s) unexpected marshalled data - "+
250 "got %s, want %s", i, test.name, marshalled,
251 test.marshalled,
252 )
253 continue
254 }
255 // Ensure the command is created without error via the generic new command creation function.
256 cmd, e := test.newCmd()
257 if e != nil {
258 t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
259 i, test.name, e,
260 )
261 }
262 // Marshal the command as created by the generic new command creation function.
263 marshalled, e = btcjson.MarshalCmd(testID, cmd)
264 if e != nil {
265 t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
266 test.name, e,
267 )
268 continue
269 }
270 if !bytes.Equal(marshalled, []byte(test.marshalled)) {
271 t.Errorf("Test #%d (%s) unexpected marshalled data - "+
272 "got %s, want %s", i, test.name, marshalled,
273 test.marshalled,
274 )
275 continue
276 }
277 var request btcjson.Request
278 if e = json.Unmarshal(marshalled, &request); E.Chk(e) {
279 t.Errorf("Test #%d (%s) unexpected error while "+
280 "unmarshalling JSON-RPC request: %v", i,
281 test.name, e,
282 )
283 continue
284 }
285 cmd, e = btcjson.UnmarshalCmd(&request)
286 if e != nil {
287 t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
288 test.name, e,
289 )
290 continue
291 }
292 if !reflect.DeepEqual(cmd, test.unmarshalled) {
293 t.Errorf("Test #%d (%s) unexpected unmarshalled command "+
294 "- got %s, want %s", i, test.name,
295 fmt.Sprintf("(%T) %+[1]v", cmd),
296 fmt.Sprintf("(%T) %+[1]v\n", test.unmarshalled),
297 )
298 continue
299 }
300 }
301 }
302