OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / btcjson / chainsvrcmds_test.go
1 // Copyright (c) 2014 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package btcjson_test
6
7 import (
8         "bytes"
9         "encoding/json"
10         "fmt"
11         "reflect"
12         "testing"
13
14         "github.com/btcsuite/btcd/btcjson"
15 )
16
17 // TestChainSvrCmds tests all of the chain server commands marshal and unmarshal
18 // into valid results include handling of optional fields being omitted in the
19 // marshalled command, while optional fields with defaults have the default
20 // assigned on unmarshalled commands.
21 func TestChainSvrCmds(t *testing.T) {
22         t.Parallel()
23
24         testID := int(1)
25         tests := []struct {
26                 name         string
27                 newCmd       func() (interface{}, error)
28                 staticCmd    func() interface{}
29                 marshalled   string
30                 unmarshalled interface{}
31         }{
32                 {
33                         name: "addnode",
34                         newCmd: func() (interface{}, error) {
35                                 return btcjson.NewCmd("addnode", "127.0.0.1", btcjson.ANRemove)
36                         },
37                         staticCmd: func() interface{} {
38                                 return btcjson.NewAddNodeCmd("127.0.0.1", btcjson.ANRemove)
39                         },
40                         marshalled:   `{"jsonrpc":"1.0","method":"addnode","params":["127.0.0.1","remove"],"id":1}`,
41                         unmarshalled: &btcjson.AddNodeCmd{Addr: "127.0.0.1", SubCmd: btcjson.ANRemove},
42                 },
43                 {
44                         name: "createrawtransaction",
45                         newCmd: func() (interface{}, error) {
46                                 return btcjson.NewCmd("createrawtransaction", `[{"txid":"123","vout":1}]`,
47                                         `{"456":0.0123}`)
48                         },
49                         staticCmd: func() interface{} {
50                                 txInputs := []btcjson.TransactionInput{
51                                         {Txid: "123", Vout: 1},
52                                 }
53                                 amounts := map[string]float64{"456": .0123}
54                                 return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, nil)
55                         },
56                         marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123}],"id":1}`,
57                         unmarshalled: &btcjson.CreateRawTransactionCmd{
58                                 Inputs:  []btcjson.TransactionInput{{Txid: "123", Vout: 1}},
59                                 Amounts: map[string]float64{"456": .0123},
60                         },
61                 },
62                 {
63                         name: "createrawtransaction optional",
64                         newCmd: func() (interface{}, error) {
65                                 return btcjson.NewCmd("createrawtransaction", `[{"txid":"123","vout":1}]`,
66                                         `{"456":0.0123}`, int64(12312333333))
67                         },
68                         staticCmd: func() interface{} {
69                                 txInputs := []btcjson.TransactionInput{
70                                         {Txid: "123", Vout: 1},
71                                 }
72                                 amounts := map[string]float64{"456": .0123}
73                                 return btcjson.NewCreateRawTransactionCmd(txInputs, amounts, btcjson.Int64(12312333333))
74                         },
75                         marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[{"txid":"123","vout":1}],{"456":0.0123},12312333333],"id":1}`,
76                         unmarshalled: &btcjson.CreateRawTransactionCmd{
77                                 Inputs:   []btcjson.TransactionInput{{Txid: "123", Vout: 1}},
78                                 Amounts:  map[string]float64{"456": .0123},
79                                 LockTime: btcjson.Int64(12312333333),
80                         },
81                 },
82
83                 {
84                         name: "decoderawtransaction",
85                         newCmd: func() (interface{}, error) {
86                                 return btcjson.NewCmd("decoderawtransaction", "123")
87                         },
88                         staticCmd: func() interface{} {
89                                 return btcjson.NewDecodeRawTransactionCmd("123")
90                         },
91                         marshalled:   `{"jsonrpc":"1.0","method":"decoderawtransaction","params":["123"],"id":1}`,
92                         unmarshalled: &btcjson.DecodeRawTransactionCmd{HexTx: "123"},
93                 },
94                 {
95                         name: "decodescript",
96                         newCmd: func() (interface{}, error) {
97                                 return btcjson.NewCmd("decodescript", "00")
98                         },
99                         staticCmd: func() interface{} {
100                                 return btcjson.NewDecodeScriptCmd("00")
101                         },
102                         marshalled:   `{"jsonrpc":"1.0","method":"decodescript","params":["00"],"id":1}`,
103                         unmarshalled: &btcjson.DecodeScriptCmd{HexScript: "00"},
104                 },
105                 {
106                         name: "getaddednodeinfo",
107                         newCmd: func() (interface{}, error) {
108                                 return btcjson.NewCmd("getaddednodeinfo", true)
109                         },
110                         staticCmd: func() interface{} {
111                                 return btcjson.NewGetAddedNodeInfoCmd(true, nil)
112                         },
113                         marshalled:   `{"jsonrpc":"1.0","method":"getaddednodeinfo","params":[true],"id":1}`,
114                         unmarshalled: &btcjson.GetAddedNodeInfoCmd{DNS: true, Node: nil},
115                 },
116                 {
117                         name: "getaddednodeinfo optional",
118                         newCmd: func() (interface{}, error) {
119                                 return btcjson.NewCmd("getaddednodeinfo", true, "127.0.0.1")
120                         },
121                         staticCmd: func() interface{} {
122                                 return btcjson.NewGetAddedNodeInfoCmd(true, btcjson.String("127.0.0.1"))
123                         },
124                         marshalled: `{"jsonrpc":"1.0","method":"getaddednodeinfo","params":[true,"127.0.0.1"],"id":1}`,
125                         unmarshalled: &btcjson.GetAddedNodeInfoCmd{
126                                 DNS:  true,
127                                 Node: btcjson.String("127.0.0.1"),
128                         },
129                 },
130                 {
131                         name: "getbestblockhash",
132                         newCmd: func() (interface{}, error) {
133                                 return btcjson.NewCmd("getbestblockhash")
134                         },
135                         staticCmd: func() interface{} {
136                                 return btcjson.NewGetBestBlockHashCmd()
137                         },
138                         marshalled:   `{"jsonrpc":"1.0","method":"getbestblockhash","params":[],"id":1}`,
139                         unmarshalled: &btcjson.GetBestBlockHashCmd{},
140                 },
141                 {
142                         name: "getblock",
143                         newCmd: func() (interface{}, error) {
144                                 return btcjson.NewCmd("getblock", "123")
145                         },
146                         staticCmd: func() interface{} {
147                                 return btcjson.NewGetBlockCmd("123", nil, nil)
148                         },
149                         marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123"],"id":1}`,
150                         unmarshalled: &btcjson.GetBlockCmd{
151                                 Hash:      "123",
152                                 Verbose:   btcjson.Bool(true),
153                                 VerboseTx: btcjson.Bool(false),
154                         },
155                 },
156                 {
157                         name: "getblock required optional1",
158                         newCmd: func() (interface{}, error) {
159                                 // Intentionally use a source param that is
160                                 // more pointers than the destination to
161                                 // exercise that path.
162                                 verbosePtr := btcjson.Bool(true)
163                                 return btcjson.NewCmd("getblock", "123", &verbosePtr)
164                         },
165                         staticCmd: func() interface{} {
166                                 return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), nil)
167                         },
168                         marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",true],"id":1}`,
169                         unmarshalled: &btcjson.GetBlockCmd{
170                                 Hash:      "123",
171                                 Verbose:   btcjson.Bool(true),
172                                 VerboseTx: btcjson.Bool(false),
173                         },
174                 },
175                 {
176                         name: "getblock required optional2",
177                         newCmd: func() (interface{}, error) {
178                                 return btcjson.NewCmd("getblock", "123", true, true)
179                         },
180                         staticCmd: func() interface{} {
181                                 return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), btcjson.Bool(true))
182                         },
183                         marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",true,true],"id":1}`,
184                         unmarshalled: &btcjson.GetBlockCmd{
185                                 Hash:      "123",
186                                 Verbose:   btcjson.Bool(true),
187                                 VerboseTx: btcjson.Bool(true),
188                         },
189                 },
190                 {
191                         name: "getblockchaininfo",
192                         newCmd: func() (interface{}, error) {
193                                 return btcjson.NewCmd("getblockchaininfo")
194                         },
195                         staticCmd: func() interface{} {
196                                 return btcjson.NewGetBlockChainInfoCmd()
197                         },
198                         marshalled:   `{"jsonrpc":"1.0","method":"getblockchaininfo","params":[],"id":1}`,
199                         unmarshalled: &btcjson.GetBlockChainInfoCmd{},
200                 },
201                 {
202                         name: "getblockcount",
203                         newCmd: func() (interface{}, error) {
204                                 return btcjson.NewCmd("getblockcount")
205                         },
206                         staticCmd: func() interface{} {
207                                 return btcjson.NewGetBlockCountCmd()
208                         },
209                         marshalled:   `{"jsonrpc":"1.0","method":"getblockcount","params":[],"id":1}`,
210                         unmarshalled: &btcjson.GetBlockCountCmd{},
211                 },
212                 {
213                         name: "getblockhash",
214                         newCmd: func() (interface{}, error) {
215                                 return btcjson.NewCmd("getblockhash", 123)
216                         },
217                         staticCmd: func() interface{} {
218                                 return btcjson.NewGetBlockHashCmd(123)
219                         },
220                         marshalled:   `{"jsonrpc":"1.0","method":"getblockhash","params":[123],"id":1}`,
221                         unmarshalled: &btcjson.GetBlockHashCmd{Index: 123},
222                 },
223                 {
224                         name: "getblockheader",
225                         newCmd: func() (interface{}, error) {
226                                 return btcjson.NewCmd("getblockheader", "123")
227                         },
228                         staticCmd: func() interface{} {
229                                 return btcjson.NewGetBlockHeaderCmd("123", nil)
230                         },
231                         marshalled: `{"jsonrpc":"1.0","method":"getblockheader","params":["123"],"id":1}`,
232                         unmarshalled: &btcjson.GetBlockHeaderCmd{
233                                 Hash:    "123",
234                                 Verbose: btcjson.Bool(true),
235                         },
236                 },
237                 {
238                         name: "getblocktemplate",
239                         newCmd: func() (interface{}, error) {
240                                 return btcjson.NewCmd("getblocktemplate")
241                         },
242                         staticCmd: func() interface{} {
243                                 return btcjson.NewGetBlockTemplateCmd(nil)
244                         },
245                         marshalled:   `{"jsonrpc":"1.0","method":"getblocktemplate","params":[],"id":1}`,
246                         unmarshalled: &btcjson.GetBlockTemplateCmd{Request: nil},
247                 },
248                 {
249                         name: "getblocktemplate optional - template request",
250                         newCmd: func() (interface{}, error) {
251                                 return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"]}`)
252                         },
253                         staticCmd: func() interface{} {
254                                 template := btcjson.TemplateRequest{
255                                         Mode:         "template",
256                                         Capabilities: []string{"longpoll", "coinbasetxn"},
257                                 }
258                                 return btcjson.NewGetBlockTemplateCmd(&template)
259                         },
260                         marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"]}],"id":1}`,
261                         unmarshalled: &btcjson.GetBlockTemplateCmd{
262                                 Request: &btcjson.TemplateRequest{
263                                         Mode:         "template",
264                                         Capabilities: []string{"longpoll", "coinbasetxn"},
265                                 },
266                         },
267                 },
268                 {
269                         name: "getblocktemplate optional - template request with tweaks",
270                         newCmd: func() (interface{}, error) {
271                                 return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":2}`)
272                         },
273                         staticCmd: func() interface{} {
274                                 template := btcjson.TemplateRequest{
275                                         Mode:         "template",
276                                         Capabilities: []string{"longpoll", "coinbasetxn"},
277                                         SigOpLimit:   500,
278                                         SizeLimit:    100000000,
279                                         MaxVersion:   2,
280                                 }
281                                 return btcjson.NewGetBlockTemplateCmd(&template)
282                         },
283                         marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":500,"sizelimit":100000000,"maxversion":2}],"id":1}`,
284                         unmarshalled: &btcjson.GetBlockTemplateCmd{
285                                 Request: &btcjson.TemplateRequest{
286                                         Mode:         "template",
287                                         Capabilities: []string{"longpoll", "coinbasetxn"},
288                                         SigOpLimit:   int64(500),
289                                         SizeLimit:    int64(100000000),
290                                         MaxVersion:   2,
291                                 },
292                         },
293                 },
294                 {
295                         name: "getblocktemplate optional - template request with tweaks 2",
296                         newCmd: func() (interface{}, error) {
297                                 return btcjson.NewCmd("getblocktemplate", `{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":2}`)
298                         },
299                         staticCmd: func() interface{} {
300                                 template := btcjson.TemplateRequest{
301                                         Mode:         "template",
302                                         Capabilities: []string{"longpoll", "coinbasetxn"},
303                                         SigOpLimit:   true,
304                                         SizeLimit:    100000000,
305                                         MaxVersion:   2,
306                                 }
307                                 return btcjson.NewGetBlockTemplateCmd(&template)
308                         },
309                         marshalled: `{"jsonrpc":"1.0","method":"getblocktemplate","params":[{"mode":"template","capabilities":["longpoll","coinbasetxn"],"sigoplimit":true,"sizelimit":100000000,"maxversion":2}],"id":1}`,
310                         unmarshalled: &btcjson.GetBlockTemplateCmd{
311                                 Request: &btcjson.TemplateRequest{
312                                         Mode:         "template",
313                                         Capabilities: []string{"longpoll", "coinbasetxn"},
314                                         SigOpLimit:   true,
315                                         SizeLimit:    int64(100000000),
316                                         MaxVersion:   2,
317                                 },
318                         },
319                 },
320                 {
321                         name: "getchaintips",
322                         newCmd: func() (interface{}, error) {
323                                 return btcjson.NewCmd("getchaintips")
324                         },
325                         staticCmd: func() interface{} {
326                                 return btcjson.NewGetChainTipsCmd()
327                         },
328                         marshalled:   `{"jsonrpc":"1.0","method":"getchaintips","params":[],"id":1}`,
329                         unmarshalled: &btcjson.GetChainTipsCmd{},
330                 },
331                 {
332                         name: "getconnectioncount",
333                         newCmd: func() (interface{}, error) {
334                                 return btcjson.NewCmd("getconnectioncount")
335                         },
336                         staticCmd: func() interface{} {
337                                 return btcjson.NewGetConnectionCountCmd()
338                         },
339                         marshalled:   `{"jsonrpc":"1.0","method":"getconnectioncount","params":[],"id":1}`,
340                         unmarshalled: &btcjson.GetConnectionCountCmd{},
341                 },
342                 {
343                         name: "getdifficulty",
344                         newCmd: func() (interface{}, error) {
345                                 return btcjson.NewCmd("getdifficulty")
346                         },
347                         staticCmd: func() interface{} {
348                                 return btcjson.NewGetDifficultyCmd()
349                         },
350                         marshalled:   `{"jsonrpc":"1.0","method":"getdifficulty","params":[],"id":1}`,
351                         unmarshalled: &btcjson.GetDifficultyCmd{},
352                 },
353                 {
354                         name: "getgenerate",
355                         newCmd: func() (interface{}, error) {
356                                 return btcjson.NewCmd("getgenerate")
357                         },
358                         staticCmd: func() interface{} {
359                                 return btcjson.NewGetGenerateCmd()
360                         },
361                         marshalled:   `{"jsonrpc":"1.0","method":"getgenerate","params":[],"id":1}`,
362                         unmarshalled: &btcjson.GetGenerateCmd{},
363                 },
364                 {
365                         name: "gethashespersec",
366                         newCmd: func() (interface{}, error) {
367                                 return btcjson.NewCmd("gethashespersec")
368                         },
369                         staticCmd: func() interface{} {
370                                 return btcjson.NewGetHashesPerSecCmd()
371                         },
372                         marshalled:   `{"jsonrpc":"1.0","method":"gethashespersec","params":[],"id":1}`,
373                         unmarshalled: &btcjson.GetHashesPerSecCmd{},
374                 },
375                 {
376                         name: "getinfo",
377                         newCmd: func() (interface{}, error) {
378                                 return btcjson.NewCmd("getinfo")
379                         },
380                         staticCmd: func() interface{} {
381                                 return btcjson.NewGetInfoCmd()
382                         },
383                         marshalled:   `{"jsonrpc":"1.0","method":"getinfo","params":[],"id":1}`,
384                         unmarshalled: &btcjson.GetInfoCmd{},
385                 },
386                 {
387                         name: "getmempoolentry",
388                         newCmd: func() (interface{}, error) {
389                                 return btcjson.NewCmd("getmempoolentry", "txhash")
390                         },
391                         staticCmd: func() interface{} {
392                                 return btcjson.NewGetMempoolEntryCmd("txhash")
393                         },
394                         marshalled: `{"jsonrpc":"1.0","method":"getmempoolentry","params":["txhash"],"id":1}`,
395                         unmarshalled: &btcjson.GetMempoolEntryCmd{
396                                 TxID: "txhash",
397                         },
398                 },
399                 {
400                         name: "getmempoolinfo",
401                         newCmd: func() (interface{}, error) {
402                                 return btcjson.NewCmd("getmempoolinfo")
403                         },
404                         staticCmd: func() interface{} {
405                                 return btcjson.NewGetMempoolInfoCmd()
406                         },
407                         marshalled:   `{"jsonrpc":"1.0","method":"getmempoolinfo","params":[],"id":1}`,
408                         unmarshalled: &btcjson.GetMempoolInfoCmd{},
409                 },
410                 {
411                         name: "getmininginfo",
412                         newCmd: func() (interface{}, error) {
413                                 return btcjson.NewCmd("getmininginfo")
414                         },
415                         staticCmd: func() interface{} {
416                                 return btcjson.NewGetMiningInfoCmd()
417                         },
418                         marshalled:   `{"jsonrpc":"1.0","method":"getmininginfo","params":[],"id":1}`,
419                         unmarshalled: &btcjson.GetMiningInfoCmd{},
420                 },
421                 {
422                         name: "getnetworkinfo",
423                         newCmd: func() (interface{}, error) {
424                                 return btcjson.NewCmd("getnetworkinfo")
425                         },
426                         staticCmd: func() interface{} {
427                                 return btcjson.NewGetNetworkInfoCmd()
428                         },
429                         marshalled:   `{"jsonrpc":"1.0","method":"getnetworkinfo","params":[],"id":1}`,
430                         unmarshalled: &btcjson.GetNetworkInfoCmd{},
431                 },
432                 {
433                         name: "getnettotals",
434                         newCmd: func() (interface{}, error) {
435                                 return btcjson.NewCmd("getnettotals")
436                         },
437                         staticCmd: func() interface{} {
438                                 return btcjson.NewGetNetTotalsCmd()
439                         },
440                         marshalled:   `{"jsonrpc":"1.0","method":"getnettotals","params":[],"id":1}`,
441                         unmarshalled: &btcjson.GetNetTotalsCmd{},
442                 },
443                 {
444                         name: "getnetworkhashps",
445                         newCmd: func() (interface{}, error) {
446                                 return btcjson.NewCmd("getnetworkhashps")
447                         },
448                         staticCmd: func() interface{} {
449                                 return btcjson.NewGetNetworkHashPSCmd(nil, nil)
450                         },
451                         marshalled: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[],"id":1}`,
452                         unmarshalled: &btcjson.GetNetworkHashPSCmd{
453                                 Blocks: btcjson.Int(120),
454                                 Height: btcjson.Int(-1),
455                         },
456                 },
457                 {
458                         name: "getnetworkhashps optional1",
459                         newCmd: func() (interface{}, error) {
460                                 return btcjson.NewCmd("getnetworkhashps", 200)
461                         },
462                         staticCmd: func() interface{} {
463                                 return btcjson.NewGetNetworkHashPSCmd(btcjson.Int(200), nil)
464                         },
465                         marshalled: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[200],"id":1}`,
466                         unmarshalled: &btcjson.GetNetworkHashPSCmd{
467                                 Blocks: btcjson.Int(200),
468                                 Height: btcjson.Int(-1),
469                         },
470                 },
471                 {
472                         name: "getnetworkhashps optional2",
473                         newCmd: func() (interface{}, error) {
474                                 return btcjson.NewCmd("getnetworkhashps", 200, 123)
475                         },
476                         staticCmd: func() interface{} {
477                                 return btcjson.NewGetNetworkHashPSCmd(btcjson.Int(200), btcjson.Int(123))
478                         },
479                         marshalled: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[200,123],"id":1}`,
480                         unmarshalled: &btcjson.GetNetworkHashPSCmd{
481                                 Blocks: btcjson.Int(200),
482                                 Height: btcjson.Int(123),
483                         },
484                 },
485                 {
486                         name: "getpeerinfo",
487                         newCmd: func() (interface{}, error) {
488                                 return btcjson.NewCmd("getpeerinfo")
489                         },
490                         staticCmd: func() interface{} {
491                                 return btcjson.NewGetPeerInfoCmd()
492                         },
493                         marshalled:   `{"jsonrpc":"1.0","method":"getpeerinfo","params":[],"id":1}`,
494                         unmarshalled: &btcjson.GetPeerInfoCmd{},
495                 },
496                 {
497                         name: "getrawmempool",
498                         newCmd: func() (interface{}, error) {
499                                 return btcjson.NewCmd("getrawmempool")
500                         },
501                         staticCmd: func() interface{} {
502                                 return btcjson.NewGetRawMempoolCmd(nil)
503                         },
504                         marshalled: `{"jsonrpc":"1.0","method":"getrawmempool","params":[],"id":1}`,
505                         unmarshalled: &btcjson.GetRawMempoolCmd{
506                                 Verbose: btcjson.Bool(false),
507                         },
508                 },
509                 {
510                         name: "getrawmempool optional",
511                         newCmd: func() (interface{}, error) {
512                                 return btcjson.NewCmd("getrawmempool", false)
513                         },
514                         staticCmd: func() interface{} {
515                                 return btcjson.NewGetRawMempoolCmd(btcjson.Bool(false))
516                         },
517                         marshalled: `{"jsonrpc":"1.0","method":"getrawmempool","params":[false],"id":1}`,
518                         unmarshalled: &btcjson.GetRawMempoolCmd{
519                                 Verbose: btcjson.Bool(false),
520                         },
521                 },
522                 {
523                         name: "getrawtransaction",
524                         newCmd: func() (interface{}, error) {
525                                 return btcjson.NewCmd("getrawtransaction", "123")
526                         },
527                         staticCmd: func() interface{} {
528                                 return btcjson.NewGetRawTransactionCmd("123", nil)
529                         },
530                         marshalled: `{"jsonrpc":"1.0","method":"getrawtransaction","params":["123"],"id":1}`,
531                         unmarshalled: &btcjson.GetRawTransactionCmd{
532                                 Txid:    "123",
533                                 Verbose: btcjson.Int(0),
534                         },
535                 },
536                 {
537                         name: "getrawtransaction optional",
538                         newCmd: func() (interface{}, error) {
539                                 return btcjson.NewCmd("getrawtransaction", "123", 1)
540                         },
541                         staticCmd: func() interface{} {
542                                 return btcjson.NewGetRawTransactionCmd("123", btcjson.Int(1))
543                         },
544                         marshalled: `{"jsonrpc":"1.0","method":"getrawtransaction","params":["123",1],"id":1}`,
545                         unmarshalled: &btcjson.GetRawTransactionCmd{
546                                 Txid:    "123",
547                                 Verbose: btcjson.Int(1),
548                         },
549                 },
550                 {
551                         name: "gettxout",
552                         newCmd: func() (interface{}, error) {
553                                 return btcjson.NewCmd("gettxout", "123", 1)
554                         },
555                         staticCmd: func() interface{} {
556                                 return btcjson.NewGetTxOutCmd("123", 1, nil)
557                         },
558                         marshalled: `{"jsonrpc":"1.0","method":"gettxout","params":["123",1],"id":1}`,
559                         unmarshalled: &btcjson.GetTxOutCmd{
560                                 Txid:           "123",
561                                 Vout:           1,
562                                 IncludeMempool: btcjson.Bool(true),
563                         },
564                 },
565                 {
566                         name: "gettxout optional",
567                         newCmd: func() (interface{}, error) {
568                                 return btcjson.NewCmd("gettxout", "123", 1, true)
569                         },
570                         staticCmd: func() interface{} {
571                                 return btcjson.NewGetTxOutCmd("123", 1, btcjson.Bool(true))
572                         },
573                         marshalled: `{"jsonrpc":"1.0","method":"gettxout","params":["123",1,true],"id":1}`,
574                         unmarshalled: &btcjson.GetTxOutCmd{
575                                 Txid:           "123",
576                                 Vout:           1,
577                                 IncludeMempool: btcjson.Bool(true),
578                         },
579                 },
580                 {
581                         name: "gettxoutproof",
582                         newCmd: func() (interface{}, error) {
583                                 return btcjson.NewCmd("gettxoutproof", []string{"123", "456"})
584                         },
585                         staticCmd: func() interface{} {
586                                 return btcjson.NewGetTxOutProofCmd([]string{"123", "456"}, nil)
587                         },
588                         marshalled: `{"jsonrpc":"1.0","method":"gettxoutproof","params":[["123","456"]],"id":1}`,
589                         unmarshalled: &btcjson.GetTxOutProofCmd{
590                                 TxIDs: []string{"123", "456"},
591                         },
592                 },
593                 {
594                         name: "gettxoutproof optional",
595                         newCmd: func() (interface{}, error) {
596                                 return btcjson.NewCmd("gettxoutproof", []string{"123", "456"},
597                                         btcjson.String("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"))
598                         },
599                         staticCmd: func() interface{} {
600                                 return btcjson.NewGetTxOutProofCmd([]string{"123", "456"},
601                                         btcjson.String("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"))
602                         },
603                         marshalled: `{"jsonrpc":"1.0","method":"gettxoutproof","params":[["123","456"],` +
604                                 `"000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"],"id":1}`,
605                         unmarshalled: &btcjson.GetTxOutProofCmd{
606                                 TxIDs:     []string{"123", "456"},
607                                 BlockHash: btcjson.String("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"),
608                         },
609                 },
610                 {
611                         name: "gettxoutsetinfo",
612                         newCmd: func() (interface{}, error) {
613                                 return btcjson.NewCmd("gettxoutsetinfo")
614                         },
615                         staticCmd: func() interface{} {
616                                 return btcjson.NewGetTxOutSetInfoCmd()
617                         },
618                         marshalled:   `{"jsonrpc":"1.0","method":"gettxoutsetinfo","params":[],"id":1}`,
619                         unmarshalled: &btcjson.GetTxOutSetInfoCmd{},
620                 },
621                 {
622                         name: "getwork",
623                         newCmd: func() (interface{}, error) {
624                                 return btcjson.NewCmd("getwork")
625                         },
626                         staticCmd: func() interface{} {
627                                 return btcjson.NewGetWorkCmd(nil)
628                         },
629                         marshalled: `{"jsonrpc":"1.0","method":"getwork","params":[],"id":1}`,
630                         unmarshalled: &btcjson.GetWorkCmd{
631                                 Data: nil,
632                         },
633                 },
634                 {
635                         name: "getwork optional",
636                         newCmd: func() (interface{}, error) {
637                                 return btcjson.NewCmd("getwork", "00112233")
638                         },
639                         staticCmd: func() interface{} {
640                                 return btcjson.NewGetWorkCmd(btcjson.String("00112233"))
641                         },
642                         marshalled: `{"jsonrpc":"1.0","method":"getwork","params":["00112233"],"id":1}`,
643                         unmarshalled: &btcjson.GetWorkCmd{
644                                 Data: btcjson.String("00112233"),
645                         },
646                 },
647                 {
648                         name: "help",
649                         newCmd: func() (interface{}, error) {
650                                 return btcjson.NewCmd("help")
651                         },
652                         staticCmd: func() interface{} {
653                                 return btcjson.NewHelpCmd(nil)
654                         },
655                         marshalled: `{"jsonrpc":"1.0","method":"help","params":[],"id":1}`,
656                         unmarshalled: &btcjson.HelpCmd{
657                                 Command: nil,
658                         },
659                 },
660                 {
661                         name: "help optional",
662                         newCmd: func() (interface{}, error) {
663                                 return btcjson.NewCmd("help", "getblock")
664                         },
665                         staticCmd: func() interface{} {
666                                 return btcjson.NewHelpCmd(btcjson.String("getblock"))
667                         },
668                         marshalled: `{"jsonrpc":"1.0","method":"help","params":["getblock"],"id":1}`,
669                         unmarshalled: &btcjson.HelpCmd{
670                                 Command: btcjson.String("getblock"),
671                         },
672                 },
673                 {
674                         name: "invalidateblock",
675                         newCmd: func() (interface{}, error) {
676                                 return btcjson.NewCmd("invalidateblock", "123")
677                         },
678                         staticCmd: func() interface{} {
679                                 return btcjson.NewInvalidateBlockCmd("123")
680                         },
681                         marshalled: `{"jsonrpc":"1.0","method":"invalidateblock","params":["123"],"id":1}`,
682                         unmarshalled: &btcjson.InvalidateBlockCmd{
683                                 BlockHash: "123",
684                         },
685                 },
686                 {
687                         name: "ping",
688                         newCmd: func() (interface{}, error) {
689                                 return btcjson.NewCmd("ping")
690                         },
691                         staticCmd: func() interface{} {
692                                 return btcjson.NewPingCmd()
693                         },
694                         marshalled:   `{"jsonrpc":"1.0","method":"ping","params":[],"id":1}`,
695                         unmarshalled: &btcjson.PingCmd{},
696                 },
697                 {
698                         name: "preciousblock",
699                         newCmd: func() (interface{}, error) {
700                                 return btcjson.NewCmd("preciousblock", "0123")
701                         },
702                         staticCmd: func() interface{} {
703                                 return btcjson.NewPreciousBlockCmd("0123")
704                         },
705                         marshalled: `{"jsonrpc":"1.0","method":"preciousblock","params":["0123"],"id":1}`,
706                         unmarshalled: &btcjson.PreciousBlockCmd{
707                                 BlockHash: "0123",
708                         },
709                 },
710                 {
711                         name: "reconsiderblock",
712                         newCmd: func() (interface{}, error) {
713                                 return btcjson.NewCmd("reconsiderblock", "123")
714                         },
715                         staticCmd: func() interface{} {
716                                 return btcjson.NewReconsiderBlockCmd("123")
717                         },
718                         marshalled: `{"jsonrpc":"1.0","method":"reconsiderblock","params":["123"],"id":1}`,
719                         unmarshalled: &btcjson.ReconsiderBlockCmd{
720                                 BlockHash: "123",
721                         },
722                 },
723                 {
724                         name: "searchrawtransactions",
725                         newCmd: func() (interface{}, error) {
726                                 return btcjson.NewCmd("searchrawtransactions", "1Address")
727                         },
728                         staticCmd: func() interface{} {
729                                 return btcjson.NewSearchRawTransactionsCmd("1Address", nil, nil, nil, nil, nil, nil)
730                         },
731                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address"],"id":1}`,
732                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
733                                 Address:     "1Address",
734                                 Verbose:     btcjson.Int(1),
735                                 Skip:        btcjson.Int(0),
736                                 Count:       btcjson.Int(100),
737                                 VinExtra:    btcjson.Int(0),
738                                 Reverse:     btcjson.Bool(false),
739                                 FilterAddrs: nil,
740                         },
741                 },
742                 {
743                         name: "searchrawtransactions",
744                         newCmd: func() (interface{}, error) {
745                                 return btcjson.NewCmd("searchrawtransactions", "1Address", 0)
746                         },
747                         staticCmd: func() interface{} {
748                                 return btcjson.NewSearchRawTransactionsCmd("1Address",
749                                         btcjson.Int(0), nil, nil, nil, nil, nil)
750                         },
751                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0],"id":1}`,
752                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
753                                 Address:     "1Address",
754                                 Verbose:     btcjson.Int(0),
755                                 Skip:        btcjson.Int(0),
756                                 Count:       btcjson.Int(100),
757                                 VinExtra:    btcjson.Int(0),
758                                 Reverse:     btcjson.Bool(false),
759                                 FilterAddrs: nil,
760                         },
761                 },
762                 {
763                         name: "searchrawtransactions",
764                         newCmd: func() (interface{}, error) {
765                                 return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5)
766                         },
767                         staticCmd: func() interface{} {
768                                 return btcjson.NewSearchRawTransactionsCmd("1Address",
769                                         btcjson.Int(0), btcjson.Int(5), nil, nil, nil, nil)
770                         },
771                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5],"id":1}`,
772                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
773                                 Address:     "1Address",
774                                 Verbose:     btcjson.Int(0),
775                                 Skip:        btcjson.Int(5),
776                                 Count:       btcjson.Int(100),
777                                 VinExtra:    btcjson.Int(0),
778                                 Reverse:     btcjson.Bool(false),
779                                 FilterAddrs: nil,
780                         },
781                 },
782                 {
783                         name: "searchrawtransactions",
784                         newCmd: func() (interface{}, error) {
785                                 return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10)
786                         },
787                         staticCmd: func() interface{} {
788                                 return btcjson.NewSearchRawTransactionsCmd("1Address",
789                                         btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), nil, nil, nil)
790                         },
791                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10],"id":1}`,
792                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
793                                 Address:     "1Address",
794                                 Verbose:     btcjson.Int(0),
795                                 Skip:        btcjson.Int(5),
796                                 Count:       btcjson.Int(10),
797                                 VinExtra:    btcjson.Int(0),
798                                 Reverse:     btcjson.Bool(false),
799                                 FilterAddrs: nil,
800                         },
801                 },
802                 {
803                         name: "searchrawtransactions",
804                         newCmd: func() (interface{}, error) {
805                                 return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10, 1)
806                         },
807                         staticCmd: func() interface{} {
808                                 return btcjson.NewSearchRawTransactionsCmd("1Address",
809                                         btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), nil, nil)
810                         },
811                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1],"id":1}`,
812                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
813                                 Address:     "1Address",
814                                 Verbose:     btcjson.Int(0),
815                                 Skip:        btcjson.Int(5),
816                                 Count:       btcjson.Int(10),
817                                 VinExtra:    btcjson.Int(1),
818                                 Reverse:     btcjson.Bool(false),
819                                 FilterAddrs: nil,
820                         },
821                 },
822                 {
823                         name: "searchrawtransactions",
824                         newCmd: func() (interface{}, error) {
825                                 return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10, 1, true)
826                         },
827                         staticCmd: func() interface{} {
828                                 return btcjson.NewSearchRawTransactionsCmd("1Address",
829                                         btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), btcjson.Bool(true), nil)
830                         },
831                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true],"id":1}`,
832                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
833                                 Address:     "1Address",
834                                 Verbose:     btcjson.Int(0),
835                                 Skip:        btcjson.Int(5),
836                                 Count:       btcjson.Int(10),
837                                 VinExtra:    btcjson.Int(1),
838                                 Reverse:     btcjson.Bool(true),
839                                 FilterAddrs: nil,
840                         },
841                 },
842                 {
843                         name: "searchrawtransactions",
844                         newCmd: func() (interface{}, error) {
845                                 return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10, 1, true, []string{"1Address"})
846                         },
847                         staticCmd: func() interface{} {
848                                 return btcjson.NewSearchRawTransactionsCmd("1Address",
849                                         btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), btcjson.Int(1), btcjson.Bool(true), &[]string{"1Address"})
850                         },
851                         marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,1,true,["1Address"]],"id":1}`,
852                         unmarshalled: &btcjson.SearchRawTransactionsCmd{
853                                 Address:     "1Address",
854                                 Verbose:     btcjson.Int(0),
855                                 Skip:        btcjson.Int(5),
856                                 Count:       btcjson.Int(10),
857                                 VinExtra:    btcjson.Int(1),
858                                 Reverse:     btcjson.Bool(true),
859                                 FilterAddrs: &[]string{"1Address"},
860                         },
861                 },
862                 {
863                         name: "sendrawtransaction",
864                         newCmd: func() (interface{}, error) {
865                                 return btcjson.NewCmd("sendrawtransaction", "1122")
866                         },
867                         staticCmd: func() interface{} {
868                                 return btcjson.NewSendRawTransactionCmd("1122", nil)
869                         },
870                         marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122"],"id":1}`,
871                         unmarshalled: &btcjson.SendRawTransactionCmd{
872                                 HexTx:         "1122",
873                                 AllowHighFees: btcjson.Bool(false),
874                         },
875                 },
876                 {
877                         name: "sendrawtransaction optional",
878                         newCmd: func() (interface{}, error) {
879                                 return btcjson.NewCmd("sendrawtransaction", "1122", false)
880                         },
881                         staticCmd: func() interface{} {
882                                 return btcjson.NewSendRawTransactionCmd("1122", btcjson.Bool(false))
883                         },
884                         marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122",false],"id":1}`,
885                         unmarshalled: &btcjson.SendRawTransactionCmd{
886                                 HexTx:         "1122",
887                                 AllowHighFees: btcjson.Bool(false),
888                         },
889                 },
890                 {
891                         name: "setgenerate",
892                         newCmd: func() (interface{}, error) {
893                                 return btcjson.NewCmd("setgenerate", true)
894                         },
895                         staticCmd: func() interface{} {
896                                 return btcjson.NewSetGenerateCmd(true, nil)
897                         },
898                         marshalled: `{"jsonrpc":"1.0","method":"setgenerate","params":[true],"id":1}`,
899                         unmarshalled: &btcjson.SetGenerateCmd{
900                                 Generate:     true,
901                                 GenProcLimit: btcjson.Int(-1),
902                         },
903                 },
904                 {
905                         name: "setgenerate optional",
906                         newCmd: func() (interface{}, error) {
907                                 return btcjson.NewCmd("setgenerate", true, 6)
908                         },
909                         staticCmd: func() interface{} {
910                                 return btcjson.NewSetGenerateCmd(true, btcjson.Int(6))
911                         },
912                         marshalled: `{"jsonrpc":"1.0","method":"setgenerate","params":[true,6],"id":1}`,
913                         unmarshalled: &btcjson.SetGenerateCmd{
914                                 Generate:     true,
915                                 GenProcLimit: btcjson.Int(6),
916                         },
917                 },
918                 {
919                         name: "stop",
920                         newCmd: func() (interface{}, error) {
921                                 return btcjson.NewCmd("stop")
922                         },
923                         staticCmd: func() interface{} {
924                                 return btcjson.NewStopCmd()
925                         },
926                         marshalled:   `{"jsonrpc":"1.0","method":"stop","params":[],"id":1}`,
927                         unmarshalled: &btcjson.StopCmd{},
928                 },
929                 {
930                         name: "submitblock",
931                         newCmd: func() (interface{}, error) {
932                                 return btcjson.NewCmd("submitblock", "112233")
933                         },
934                         staticCmd: func() interface{} {
935                                 return btcjson.NewSubmitBlockCmd("112233", nil)
936                         },
937                         marshalled: `{"jsonrpc":"1.0","method":"submitblock","params":["112233"],"id":1}`,
938                         unmarshalled: &btcjson.SubmitBlockCmd{
939                                 HexBlock: "112233",
940                                 Options:  nil,
941                         },
942                 },
943                 {
944                         name: "submitblock optional",
945                         newCmd: func() (interface{}, error) {
946                                 return btcjson.NewCmd("submitblock", "112233", `{"workid":"12345"}`)
947                         },
948                         staticCmd: func() interface{} {
949                                 options := btcjson.SubmitBlockOptions{
950                                         WorkID: "12345",
951                                 }
952                                 return btcjson.NewSubmitBlockCmd("112233", &options)
953                         },
954                         marshalled: `{"jsonrpc":"1.0","method":"submitblock","params":["112233",{"workid":"12345"}],"id":1}`,
955                         unmarshalled: &btcjson.SubmitBlockCmd{
956                                 HexBlock: "112233",
957                                 Options: &btcjson.SubmitBlockOptions{
958                                         WorkID: "12345",
959                                 },
960                         },
961                 },
962                 {
963                         name: "uptime",
964                         newCmd: func() (interface{}, error) {
965                                 return btcjson.NewCmd("uptime")
966                         },
967                         staticCmd: func() interface{} {
968                                 return btcjson.NewUptimeCmd()
969                         },
970                         marshalled:   `{"jsonrpc":"1.0","method":"uptime","params":[],"id":1}`,
971                         unmarshalled: &btcjson.UptimeCmd{},
972                 },
973                 {
974                         name: "validateaddress",
975                         newCmd: func() (interface{}, error) {
976                                 return btcjson.NewCmd("validateaddress", "1Address")
977                         },
978                         staticCmd: func() interface{} {
979                                 return btcjson.NewValidateAddressCmd("1Address")
980                         },
981                         marshalled: `{"jsonrpc":"1.0","method":"validateaddress","params":["1Address"],"id":1}`,
982                         unmarshalled: &btcjson.ValidateAddressCmd{
983                                 Address: "1Address",
984                         },
985                 },
986                 {
987                         name: "verifychain",
988                         newCmd: func() (interface{}, error) {
989                                 return btcjson.NewCmd("verifychain")
990                         },
991                         staticCmd: func() interface{} {
992                                 return btcjson.NewVerifyChainCmd(nil, nil)
993                         },
994                         marshalled: `{"jsonrpc":"1.0","method":"verifychain","params":[],"id":1}`,
995                         unmarshalled: &btcjson.VerifyChainCmd{
996                                 CheckLevel: btcjson.Int32(3),
997                                 CheckDepth: btcjson.Int32(288),
998                         },
999                 },
1000                 {
1001                         name: "verifychain optional1",
1002                         newCmd: func() (interface{}, error) {
1003                                 return btcjson.NewCmd("verifychain", 2)
1004                         },
1005                         staticCmd: func() interface{} {
1006                                 return btcjson.NewVerifyChainCmd(btcjson.Int32(2), nil)
1007                         },
1008                         marshalled: `{"jsonrpc":"1.0","method":"verifychain","params":[2],"id":1}`,
1009                         unmarshalled: &btcjson.VerifyChainCmd{
1010                                 CheckLevel: btcjson.Int32(2),
1011                                 CheckDepth: btcjson.Int32(288),
1012                         },
1013                 },
1014                 {
1015                         name: "verifychain optional2",
1016                         newCmd: func() (interface{}, error) {
1017                                 return btcjson.NewCmd("verifychain", 2, 500)
1018                         },
1019                         staticCmd: func() interface{} {
1020                                 return btcjson.NewVerifyChainCmd(btcjson.Int32(2), btcjson.Int32(500))
1021                         },
1022                         marshalled: `{"jsonrpc":"1.0","method":"verifychain","params":[2,500],"id":1}`,
1023                         unmarshalled: &btcjson.VerifyChainCmd{
1024                                 CheckLevel: btcjson.Int32(2),
1025                                 CheckDepth: btcjson.Int32(500),
1026                         },
1027                 },
1028                 {
1029                         name: "verifymessage",
1030                         newCmd: func() (interface{}, error) {
1031                                 return btcjson.NewCmd("verifymessage", "1Address", "301234", "test")
1032                         },
1033                         staticCmd: func() interface{} {
1034                                 return btcjson.NewVerifyMessageCmd("1Address", "301234", "test")
1035                         },
1036                         marshalled: `{"jsonrpc":"1.0","method":"verifymessage","params":["1Address","301234","test"],"id":1}`,
1037                         unmarshalled: &btcjson.VerifyMessageCmd{
1038                                 Address:   "1Address",
1039                                 Signature: "301234",
1040                                 Message:   "test",
1041                         },
1042                 },
1043                 {
1044                         name: "verifytxoutproof",
1045                         newCmd: func() (interface{}, error) {
1046                                 return btcjson.NewCmd("verifytxoutproof", "test")
1047                         },
1048                         staticCmd: func() interface{} {
1049                                 return btcjson.NewVerifyTxOutProofCmd("test")
1050                         },
1051                         marshalled: `{"jsonrpc":"1.0","method":"verifytxoutproof","params":["test"],"id":1}`,
1052                         unmarshalled: &btcjson.VerifyTxOutProofCmd{
1053                                 Proof: "test",
1054                         },
1055                 },
1056         }
1057
1058         t.Logf("Running %d tests", len(tests))
1059         for i, test := range tests {
1060                 // Marshal the command as created by the new static command
1061                 // creation function.
1062                 marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd())
1063                 if err != nil {
1064                         t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
1065                                 test.name, err)
1066                         continue
1067                 }
1068
1069                 if !bytes.Equal(marshalled, []byte(test.marshalled)) {
1070                         t.Errorf("Test #%d (%s) unexpected marshalled data - "+
1071                                 "got %s, want %s", i, test.name, marshalled,
1072                                 test.marshalled)
1073                         t.Errorf("\n%s\n%s", marshalled, test.marshalled)
1074                         continue
1075                 }
1076
1077                 // Ensure the command is created without error via the generic
1078                 // new command creation function.
1079                 cmd, err := test.newCmd()
1080                 if err != nil {
1081                         t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
1082                                 i, test.name, err)
1083                 }
1084
1085                 // Marshal the command as created by the generic new command
1086                 // creation function.
1087                 marshalled, err = btcjson.MarshalCmd(testID, cmd)
1088                 if err != nil {
1089                         t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
1090                                 test.name, err)
1091                         continue
1092                 }
1093
1094                 if !bytes.Equal(marshalled, []byte(test.marshalled)) {
1095                         t.Errorf("Test #%d (%s) unexpected marshalled data - "+
1096                                 "got %s, want %s", i, test.name, marshalled,
1097                                 test.marshalled)
1098                         continue
1099                 }
1100
1101                 var request btcjson.Request
1102                 if err := json.Unmarshal(marshalled, &request); err != nil {
1103                         t.Errorf("Test #%d (%s) unexpected error while "+
1104                                 "unmarshalling JSON-RPC request: %v", i,
1105                                 test.name, err)
1106                         continue
1107                 }
1108
1109                 cmd, err = btcjson.UnmarshalCmd(&request)
1110                 if err != nil {
1111                         t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
1112                                 test.name, err)
1113                         continue
1114                 }
1115
1116                 if !reflect.DeepEqual(cmd, test.unmarshalled) {
1117                         t.Errorf("Test #%d (%s) unexpected unmarshalled command "+
1118                                 "- got %s, want %s", i, test.name,
1119                                 fmt.Sprintf("(%T) %+[1]v", cmd),
1120                                 fmt.Sprintf("(%T) %+[1]v\n", test.unmarshalled))
1121                         continue
1122                 }
1123         }
1124 }
1125
1126 // TestChainSvrCmdErrors ensures any errors that occur in the command during
1127 // custom mashal and unmarshal are as expected.
1128 func TestChainSvrCmdErrors(t *testing.T) {
1129         t.Parallel()
1130
1131         tests := []struct {
1132                 name       string
1133                 result     interface{}
1134                 marshalled string
1135                 err        error
1136         }{
1137                 {
1138                         name:       "template request with invalid type",
1139                         result:     &btcjson.TemplateRequest{},
1140                         marshalled: `{"mode":1}`,
1141                         err:        &json.UnmarshalTypeError{},
1142                 },
1143                 {
1144                         name:       "invalid template request sigoplimit field",
1145                         result:     &btcjson.TemplateRequest{},
1146                         marshalled: `{"sigoplimit":"invalid"}`,
1147                         err:        btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
1148                 },
1149                 {
1150                         name:       "invalid template request sizelimit field",
1151                         result:     &btcjson.TemplateRequest{},
1152                         marshalled: `{"sizelimit":"invalid"}`,
1153                         err:        btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
1154                 },
1155         }
1156
1157         t.Logf("Running %d tests", len(tests))
1158         for i, test := range tests {
1159                 err := json.Unmarshal([]byte(test.marshalled), &test.result)
1160                 if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
1161                         t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+
1162                                 "want %T", i, test.name, err, test.err)
1163                         continue
1164                 }
1165
1166                 if terr, ok := test.err.(btcjson.Error); ok {
1167                         gotErrorCode := err.(btcjson.Error).ErrorCode
1168                         if gotErrorCode != terr.ErrorCode {
1169                                 t.Errorf("Test #%d (%s) mismatched error code "+
1170                                         "- got %v (%v), want %v", i, test.name,
1171                                         gotErrorCode, terr, terr.ErrorCode)
1172                                 continue
1173                         }
1174                 }
1175         }
1176 }