OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / btcjson / cmdparse_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         "encoding/json"
9         "math"
10         "reflect"
11         "testing"
12
13         "github.com/btcsuite/btcd/btcjson"
14 )
15
16 // TestAssignField tests the assignField function handles supported combinations
17 // properly.
18 func TestAssignField(t *testing.T) {
19         t.Parallel()
20
21         tests := []struct {
22                 name     string
23                 dest     interface{}
24                 src      interface{}
25                 expected interface{}
26         }{
27                 {
28                         name:     "same types",
29                         dest:     int8(0),
30                         src:      int8(100),
31                         expected: int8(100),
32                 },
33                 {
34                         name: "same types - more source pointers",
35                         dest: int8(0),
36                         src: func() interface{} {
37                                 i := int8(100)
38                                 return &i
39                         }(),
40                         expected: int8(100),
41                 },
42                 {
43                         name: "same types - more dest pointers",
44                         dest: func() interface{} {
45                                 i := int8(0)
46                                 return &i
47                         }(),
48                         src:      int8(100),
49                         expected: int8(100),
50                 },
51                 {
52                         name: "convertible types - more source pointers",
53                         dest: int16(0),
54                         src: func() interface{} {
55                                 i := int8(100)
56                                 return &i
57                         }(),
58                         expected: int16(100),
59                 },
60                 {
61                         name: "convertible types - both pointers",
62                         dest: func() interface{} {
63                                 i := int8(0)
64                                 return &i
65                         }(),
66                         src: func() interface{} {
67                                 i := int16(100)
68                                 return &i
69                         }(),
70                         expected: int8(100),
71                 },
72                 {
73                         name:     "convertible types - int16 -> int8",
74                         dest:     int8(0),
75                         src:      int16(100),
76                         expected: int8(100),
77                 },
78                 {
79                         name:     "convertible types - int16 -> uint8",
80                         dest:     uint8(0),
81                         src:      int16(100),
82                         expected: uint8(100),
83                 },
84                 {
85                         name:     "convertible types - uint16 -> int8",
86                         dest:     int8(0),
87                         src:      uint16(100),
88                         expected: int8(100),
89                 },
90                 {
91                         name:     "convertible types - uint16 -> uint8",
92                         dest:     uint8(0),
93                         src:      uint16(100),
94                         expected: uint8(100),
95                 },
96                 {
97                         name:     "convertible types - float32 -> float64",
98                         dest:     float64(0),
99                         src:      float32(1.5),
100                         expected: float64(1.5),
101                 },
102                 {
103                         name:     "convertible types - float64 -> float32",
104                         dest:     float32(0),
105                         src:      float64(1.5),
106                         expected: float32(1.5),
107                 },
108                 {
109                         name:     "convertible types - string -> bool",
110                         dest:     false,
111                         src:      "true",
112                         expected: true,
113                 },
114                 {
115                         name:     "convertible types - string -> int8",
116                         dest:     int8(0),
117                         src:      "100",
118                         expected: int8(100),
119                 },
120                 {
121                         name:     "convertible types - string -> uint8",
122                         dest:     uint8(0),
123                         src:      "100",
124                         expected: uint8(100),
125                 },
126                 {
127                         name:     "convertible types - string -> float32",
128                         dest:     float32(0),
129                         src:      "1.5",
130                         expected: float32(1.5),
131                 },
132                 {
133                         name: "convertible types - typecase string -> string",
134                         dest: "",
135                         src: func() interface{} {
136                                 type foo string
137                                 return foo("foo")
138                         }(),
139                         expected: "foo",
140                 },
141                 {
142                         name:     "convertible types - string -> array",
143                         dest:     [2]string{},
144                         src:      `["test","test2"]`,
145                         expected: [2]string{"test", "test2"},
146                 },
147                 {
148                         name:     "convertible types - string -> slice",
149                         dest:     []string{},
150                         src:      `["test","test2"]`,
151                         expected: []string{"test", "test2"},
152                 },
153                 {
154                         name:     "convertible types - string -> struct",
155                         dest:     struct{ A int }{},
156                         src:      `{"A":100}`,
157                         expected: struct{ A int }{100},
158                 },
159                 {
160                         name:     "convertible types - string -> map",
161                         dest:     map[string]float64{},
162                         src:      `{"1Address":1.5}`,
163                         expected: map[string]float64{"1Address": 1.5},
164                 },
165         }
166
167         t.Logf("Running %d tests", len(tests))
168         for i, test := range tests {
169                 dst := reflect.New(reflect.TypeOf(test.dest)).Elem()
170                 src := reflect.ValueOf(test.src)
171                 err := btcjson.TstAssignField(1, "testField", dst, src)
172                 if err != nil {
173                         t.Errorf("Test #%d (%s) unexpected error: %v", i,
174                                 test.name, err)
175                         continue
176                 }
177
178                 // Inidirect through to the base types to ensure their values
179                 // are the same.
180                 for dst.Kind() == reflect.Ptr {
181                         dst = dst.Elem()
182                 }
183                 if !reflect.DeepEqual(dst.Interface(), test.expected) {
184                         t.Errorf("Test #%d (%s) unexpected value - got %v, "+
185                                 "want %v", i, test.name, dst.Interface(),
186                                 test.expected)
187                         continue
188                 }
189         }
190 }
191
192 // TestAssignFieldErrors tests the assignField function error paths.
193 func TestAssignFieldErrors(t *testing.T) {
194         t.Parallel()
195
196         tests := []struct {
197                 name string
198                 dest interface{}
199                 src  interface{}
200                 err  btcjson.Error
201         }{
202                 {
203                         name: "general incompatible int -> string",
204                         dest: string(0),
205                         src:  int(0),
206                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
207                 },
208                 {
209                         name: "overflow source int -> dest int",
210                         dest: int8(0),
211                         src:  int(128),
212                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
213                 },
214                 {
215                         name: "overflow source int -> dest uint",
216                         dest: uint8(0),
217                         src:  int(256),
218                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
219                 },
220                 {
221                         name: "int -> float",
222                         dest: float32(0),
223                         src:  int(256),
224                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
225                 },
226                 {
227                         name: "overflow source uint64 -> dest int64",
228                         dest: int64(0),
229                         src:  uint64(1 << 63),
230                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
231                 },
232                 {
233                         name: "overflow source uint -> dest int",
234                         dest: int8(0),
235                         src:  uint(128),
236                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
237                 },
238                 {
239                         name: "overflow source uint -> dest uint",
240                         dest: uint8(0),
241                         src:  uint(256),
242                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
243                 },
244                 {
245                         name: "uint -> float",
246                         dest: float32(0),
247                         src:  uint(256),
248                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
249                 },
250                 {
251                         name: "float -> int",
252                         dest: int(0),
253                         src:  float32(1.0),
254                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
255                 },
256                 {
257                         name: "overflow float64 -> float32",
258                         dest: float32(0),
259                         src:  float64(math.MaxFloat64),
260                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
261                 },
262                 {
263                         name: "invalid string -> bool",
264                         dest: true,
265                         src:  "foo",
266                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
267                 },
268                 {
269                         name: "invalid string -> int",
270                         dest: int8(0),
271                         src:  "foo",
272                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
273                 },
274                 {
275                         name: "overflow string -> int",
276                         dest: int8(0),
277                         src:  "128",
278                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
279                 },
280                 {
281                         name: "invalid string -> uint",
282                         dest: uint8(0),
283                         src:  "foo",
284                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
285                 },
286                 {
287                         name: "overflow string -> uint",
288                         dest: uint8(0),
289                         src:  "256",
290                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
291                 },
292                 {
293                         name: "invalid string -> float",
294                         dest: float32(0),
295                         src:  "foo",
296                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
297                 },
298                 {
299                         name: "overflow string -> float",
300                         dest: float32(0),
301                         src:  "1.7976931348623157e+308",
302                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
303                 },
304                 {
305                         name: "invalid string -> array",
306                         dest: [3]int{},
307                         src:  "foo",
308                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
309                 },
310                 {
311                         name: "invalid string -> slice",
312                         dest: []int{},
313                         src:  "foo",
314                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
315                 },
316                 {
317                         name: "invalid string -> struct",
318                         dest: struct{ A int }{},
319                         src:  "foo",
320                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
321                 },
322                 {
323                         name: "invalid string -> map",
324                         dest: map[string]int{},
325                         src:  "foo",
326                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
327                 },
328         }
329
330         t.Logf("Running %d tests", len(tests))
331         for i, test := range tests {
332                 dst := reflect.New(reflect.TypeOf(test.dest)).Elem()
333                 src := reflect.ValueOf(test.src)
334                 err := btcjson.TstAssignField(1, "testField", dst, src)
335                 if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
336                         t.Errorf("Test #%d (%s) wrong error - got %T (%[3]v), "+
337                                 "want %T", i, test.name, err, test.err)
338                         continue
339                 }
340                 gotErrorCode := err.(btcjson.Error).ErrorCode
341                 if gotErrorCode != test.err.ErrorCode {
342                         t.Errorf("Test #%d (%s) mismatched error code - got "+
343                                 "%v (%v), want %v", i, test.name, gotErrorCode,
344                                 err, test.err.ErrorCode)
345                         continue
346                 }
347         }
348 }
349
350 // TestNewCmdErrors ensures the error paths of NewCmd behave as expected.
351 func TestNewCmdErrors(t *testing.T) {
352         t.Parallel()
353
354         tests := []struct {
355                 name   string
356                 method string
357                 args   []interface{}
358                 err    btcjson.Error
359         }{
360                 {
361                         name:   "unregistered command",
362                         method: "boguscommand",
363                         args:   []interface{}{},
364                         err:    btcjson.Error{ErrorCode: btcjson.ErrUnregisteredMethod},
365                 },
366                 {
367                         name:   "too few parameters to command with required + optional",
368                         method: "getblock",
369                         args:   []interface{}{},
370                         err:    btcjson.Error{ErrorCode: btcjson.ErrNumParams},
371                 },
372                 {
373                         name:   "too many parameters to command with no optional",
374                         method: "getblockcount",
375                         args:   []interface{}{"123"},
376                         err:    btcjson.Error{ErrorCode: btcjson.ErrNumParams},
377                 },
378                 {
379                         name:   "incorrect parameter type",
380                         method: "getblock",
381                         args:   []interface{}{1},
382                         err:    btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
383                 },
384         }
385
386         t.Logf("Running %d tests", len(tests))
387         for i, test := range tests {
388                 _, err := btcjson.NewCmd(test.method, test.args...)
389                 if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
390                         t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+
391                                 "want %T", i, test.name, err, test.err)
392                         continue
393                 }
394                 gotErrorCode := err.(btcjson.Error).ErrorCode
395                 if gotErrorCode != test.err.ErrorCode {
396                         t.Errorf("Test #%d (%s) mismatched error code - got "+
397                                 "%v (%v), want %v", i, test.name, gotErrorCode,
398                                 err, test.err.ErrorCode)
399                         continue
400                 }
401         }
402 }
403
404 // TestMarshalCmdErrors  tests the error paths of the MarshalCmd function.
405 func TestMarshalCmdErrors(t *testing.T) {
406         t.Parallel()
407
408         tests := []struct {
409                 name string
410                 id   interface{}
411                 cmd  interface{}
412                 err  btcjson.Error
413         }{
414                 {
415                         name: "unregistered type",
416                         id:   1,
417                         cmd:  (*int)(nil),
418                         err:  btcjson.Error{ErrorCode: btcjson.ErrUnregisteredMethod},
419                 },
420                 {
421                         name: "nil instance of registered type",
422                         id:   1,
423                         cmd:  (*btcjson.GetBlockCmd)(nil),
424                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
425                 },
426                 {
427                         name: "nil instance of registered type",
428                         id:   []int{0, 1},
429                         cmd:  &btcjson.GetBlockCountCmd{},
430                         err:  btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
431                 },
432         }
433
434         t.Logf("Running %d tests", len(tests))
435         for i, test := range tests {
436                 _, err := btcjson.MarshalCmd(test.id, test.cmd)
437                 if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
438                         t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+
439                                 "want %T", i, test.name, err, test.err)
440                         continue
441                 }
442                 gotErrorCode := err.(btcjson.Error).ErrorCode
443                 if gotErrorCode != test.err.ErrorCode {
444                         t.Errorf("Test #%d (%s) mismatched error code - got "+
445                                 "%v (%v), want %v", i, test.name, gotErrorCode,
446                                 err, test.err.ErrorCode)
447                         continue
448                 }
449         }
450 }
451
452 // TestUnmarshalCmdErrors  tests the error paths of the UnmarshalCmd function.
453 func TestUnmarshalCmdErrors(t *testing.T) {
454         t.Parallel()
455
456         tests := []struct {
457                 name    string
458                 request btcjson.Request
459                 err     btcjson.Error
460         }{
461                 {
462                         name: "unregistered type",
463                         request: btcjson.Request{
464                                 Jsonrpc: "1.0",
465                                 Method:  "bogusmethod",
466                                 Params:  nil,
467                                 ID:      nil,
468                         },
469                         err: btcjson.Error{ErrorCode: btcjson.ErrUnregisteredMethod},
470                 },
471                 {
472                         name: "incorrect number of params",
473                         request: btcjson.Request{
474                                 Jsonrpc: "1.0",
475                                 Method:  "getblockcount",
476                                 Params:  []json.RawMessage{[]byte(`"bogusparam"`)},
477                                 ID:      nil,
478                         },
479                         err: btcjson.Error{ErrorCode: btcjson.ErrNumParams},
480                 },
481                 {
482                         name: "invalid type for a parameter",
483                         request: btcjson.Request{
484                                 Jsonrpc: "1.0",
485                                 Method:  "getblock",
486                                 Params:  []json.RawMessage{[]byte("1")},
487                                 ID:      nil,
488                         },
489                         err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
490                 },
491                 {
492                         name: "invalid JSON for a parameter",
493                         request: btcjson.Request{
494                                 Jsonrpc: "1.0",
495                                 Method:  "getblock",
496                                 Params:  []json.RawMessage{[]byte(`"1`)},
497                                 ID:      nil,
498                         },
499                         err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType},
500                 },
501         }
502
503         t.Logf("Running %d tests", len(tests))
504         for i, test := range tests {
505                 _, err := btcjson.UnmarshalCmd(&test.request)
506                 if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
507                         t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+
508                                 "want %T", i, test.name, err, test.err)
509                         continue
510                 }
511                 gotErrorCode := err.(btcjson.Error).ErrorCode
512                 if gotErrorCode != test.err.ErrorCode {
513                         t.Errorf("Test #%d (%s) mismatched error code - got "+
514                                 "%v (%v), want %v", i, test.name, gotErrorCode,
515                                 err, test.err.ErrorCode)
516                         continue
517                 }
518         }
519 }