OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / go-wire / reflect_test.go
1 package wire
2
3 import (
4         "bytes"
5         "encoding/hex"
6         "fmt"
7         "reflect"
8         "testing"
9         "time"
10
11         "github.com/stretchr/testify/assert"
12
13         cmn "github.com/tendermint/tmlibs/common"
14 )
15
16 type SimpleStruct struct {
17         String string
18         Bytes  []byte
19         Time   time.Time
20 }
21
22 type Animal interface{}
23
24 // Implements Animal
25 type Cat struct {
26         SimpleStruct
27 }
28
29 // Implements Animal
30 type Dog struct {
31         SimpleStruct
32 }
33
34 // Implements Animal
35 type Snake []byte
36
37 // Implements Animal
38 type Viper struct {
39         Bytes []byte
40 }
41
42 var _ = RegisterInterface(
43         struct{ Animal }{},
44         ConcreteType{Cat{}, 0x01},
45         ConcreteType{Dog{}, 0x02},
46         ConcreteType{Snake{}, 0x03},
47         ConcreteType{&Viper{}, 0x04},
48 )
49
50 func TestTime(t *testing.T) {
51
52         // panic trying to encode times before 1970
53         panicCases := []time.Time{
54                 time.Time{},
55                 time.Unix(-10, 0),
56                 time.Unix(0, -10),
57         }
58         for _, c := range panicCases {
59                 n, err := new(int), new(error)
60                 buf := new(bytes.Buffer)
61                 assert.Panics(t, func() { WriteBinary(c, buf, n, err) }, "expected WriteBinary to panic on times before 1970")
62         }
63
64         // ensure we can encode/decode a recent time
65         now := time.Now()
66         n, err := new(int), new(error)
67         buf := new(bytes.Buffer)
68         WriteBinary(now, buf, n, err)
69
70         var thisTime time.Time
71         thisTime = ReadBinary(thisTime, buf, 0, new(int), new(error)).(time.Time)
72         if !thisTime.Truncate(time.Millisecond).Equal(now.Truncate(time.Millisecond)) {
73                 t.Fatalf("times dont match. got %v, expected %v", thisTime, now)
74         }
75
76         // error trying to decode bad times
77         errorCases := []struct {
78                 thisTime time.Time
79                 err      error
80         }{
81                 {time.Time{}, ErrBinaryReadInvalidTimeNegative},
82                 {time.Unix(-10, 0), ErrBinaryReadInvalidTimeNegative},
83                 {time.Unix(0, -10), ErrBinaryReadInvalidTimeNegative},
84
85                 {time.Unix(0, 10), ErrBinaryReadInvalidTimeSubMillisecond},
86                 {time.Unix(1, 10), ErrBinaryReadInvalidTimeSubMillisecond},
87         }
88         for _, c := range errorCases {
89                 n, err := new(int), new(error)
90                 buf := new(bytes.Buffer)
91                 timeNano := c.thisTime.UnixNano()
92                 WriteInt64(timeNano, buf, n, err)
93                 var thisTime time.Time
94                 thisTime = ReadBinary(thisTime, buf, 0, n, err).(time.Time)
95                 assert.Equal(t, *err, c.err, "expected ReadBinary to throw an error")
96                 assert.Equal(t, thisTime, time.Time{}, "expected ReadBinary to return default time")
97         }
98 }
99
100 func TestEncodeDecode(t *testing.T) {
101         cat := &Cat{SimpleStruct{String: "cat", Time: time.Now()}}
102
103         n, err := new(int), new(error)
104         buf := new(bytes.Buffer)
105         WriteBinary(cat, buf, n, err)
106         if *err != nil {
107                 t.Fatalf("writeBinary:: failed to encode Cat: %v", *err)
108         }
109
110         cat2 := new(Cat)
111         n, err = new(int), new(error)
112         cat2 = ReadBinary(cat2, buf, 0, n, err).(*Cat)
113         if *err != nil {
114                 t.Fatalf("unexpected err: %v", *err)
115         }
116
117         // NOTE: this fails because []byte{} != []byte(nil)
118         //      assert.Equal(t, cat, cat2, "expected cats to match")
119 }
120
121 func TestUnexportedEmbeddedTypes(t *testing.T) {
122         type unexportedReceiver struct {
123                 animal Animal
124         }
125
126         type exportedReceiver struct {
127                 Animal Animal
128         }
129
130         now := time.Now().Truncate(time.Millisecond)
131         origCat := Cat{SimpleStruct{String: "cat", Time: now}}
132         exportedCat := exportedReceiver{origCat} // this is what we encode
133         writeCat := func() *bytes.Buffer {
134                 n, err := new(int), new(error)
135                 buf := new(bytes.Buffer)
136                 WriteBinary(exportedCat, buf, n, err)
137                 if *err != nil {
138                         t.Errorf("writeBinary:: failed to encode Cat: %v", *err)
139                 }
140                 return buf
141         }
142
143         // try to read into unexportedReceiver (should fail)
144         buf := writeCat()
145         n, err := new(int), new(error)
146         unexp := ReadBinary(unexportedReceiver{}, buf, 0, n, err).(unexportedReceiver)
147         if *err != nil {
148                 t.Fatalf("unexpected err: %v", *err)
149         }
150         returnCat, ok := unexp.animal.(Cat)
151         if ok {
152                 t.Fatalf("unexpectedly parsed out the Cat type")
153         }
154
155         // try to read into exportedReceiver (should pass)
156         buf = writeCat()
157         n, err = new(int), new(error)
158         exp := ReadBinary(exportedReceiver{}, buf, 0, n, err).(exportedReceiver)
159         if *err != nil {
160                 t.Fatalf("unexpected err: %v", *err)
161         }
162         returnCat, ok = exp.Animal.(Cat)
163         if !ok {
164                 t.Fatalf("expected to be able to parse out the Cat type; rrecv: %#v", exp.Animal)
165         }
166
167         _ = returnCat
168         // NOTE: this fails because []byte{} != []byte(nil)
169         //      assert.Equal(t, origCat, returnCat, fmt.Sprintf("cats dont match"))
170
171 }
172
173 // TODO: add assertions here ...
174 func TestAnimalInterface(t *testing.T) {
175         var foo Animal
176
177         // Type of pointer to Animal
178         rt := reflect.TypeOf(&foo)
179         fmt.Printf("rt: %v\n", rt)
180
181         // Type of Animal itself.
182         // NOTE: normally this is acquired through other means
183         // like introspecting on method signatures, or struct fields.
184         rte := rt.Elem()
185         fmt.Printf("rte: %v\n", rte)
186
187         // Get a new pointer to the interface
188         // NOTE: calling .Interface() is to get the actual value,
189         // instead of reflection values.
190         ptr := reflect.New(rte).Interface()
191         fmt.Printf("ptr: %v", ptr)
192
193         // Make a binary byteslice that represents a *snake.
194         foo = Snake([]byte("snake"))
195         snakeBytes := BinaryBytes(foo)
196         snakeReader := bytes.NewReader(snakeBytes)
197
198         // Now you can read it.
199         n, err := new(int), new(error)
200         it := ReadBinary(foo, snakeReader, 0, n, err).(Animal)
201         fmt.Println(it, reflect.TypeOf(it))
202 }
203
204 //-------------------------------------
205
206 type Constructor func() interface{}
207 type Instantiator func() (o interface{}, ptr interface{})
208 type Validator func(o interface{}, t *testing.T)
209
210 type TestCase struct {
211         Constructor
212         Instantiator
213         Validator
214 }
215
216 //-------------------------------------
217
218 func constructBasic() interface{} {
219         cat := Cat{
220                 SimpleStruct{
221                         String: "String",
222                         Bytes:  []byte("Bytes"),
223                         Time:   time.Unix(123, 456789999),
224                 },
225         }
226         return cat
227 }
228
229 func instantiateBasic() (interface{}, interface{}) {
230         return Cat{}, &Cat{}
231 }
232
233 func validateBasic(o interface{}, t *testing.T) {
234         cat := o.(Cat)
235         if cat.String != "String" {
236                 t.Errorf("Expected cat.String == 'String', got %v", cat.String)
237         }
238         if string(cat.Bytes) != "Bytes" {
239                 t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
240         }
241         if cat.Time.UnixNano() != 123456000000 { // Only milliseconds
242                 t.Errorf("Expected cat.Time.UnixNano() == 123456000000, got %v", cat.Time.UnixNano())
243         }
244 }
245
246 //-------------------------------------
247
248 type NilTestStruct struct {
249         IntPtr *int
250         CatPtr *Cat
251         Animal Animal
252 }
253
254 func constructNilTestStruct() interface{} {
255         return NilTestStruct{}
256 }
257
258 func instantiateNilTestStruct() (interface{}, interface{}) {
259         return NilTestStruct{}, &NilTestStruct{}
260 }
261
262 func validateNilTestStruct(o interface{}, t *testing.T) {
263         nts := o.(NilTestStruct)
264         if nts.IntPtr != nil {
265                 t.Errorf("Expected nts.IntPtr to be nil, got %v", nts.IntPtr)
266         }
267         if nts.CatPtr != nil {
268                 t.Errorf("Expected nts.CatPtr to be nil, got %v", nts.CatPtr)
269         }
270         if nts.Animal != nil {
271                 t.Errorf("Expected nts.Animal to be nil, got %v", nts.Animal)
272         }
273 }
274
275 //-------------------------------------
276
277 type ComplexStruct struct {
278         Name   string
279         Animal Animal
280 }
281
282 func constructComplex() interface{} {
283         c := ComplexStruct{
284                 Name:   "Complex",
285                 Animal: constructBasic(),
286         }
287         return c
288 }
289
290 func instantiateComplex() (interface{}, interface{}) {
291         return ComplexStruct{}, &ComplexStruct{}
292 }
293
294 func validateComplex(o interface{}, t *testing.T) {
295         c2 := o.(ComplexStruct)
296         if cat, ok := c2.Animal.(Cat); ok {
297                 validateBasic(cat, t)
298         } else {
299                 t.Errorf("Expected c2.Animal to be of type cat, got %v", reflect.ValueOf(c2.Animal).Elem().Type())
300         }
301 }
302
303 //-------------------------------------
304
305 type ComplexStruct2 struct {
306         Cat    Cat
307         Dog    *Dog
308         Snake  Snake
309         Snake2 *Snake
310         Viper  Viper
311         Viper2 *Viper
312 }
313
314 func constructComplex2() interface{} {
315         snake_ := Snake([]byte("hiss"))
316         snakePtr_ := &snake_
317
318         c := ComplexStruct2{
319                 Cat: Cat{
320                         SimpleStruct{
321                                 String: "String",
322                                 Bytes:  []byte("Bytes"),
323                                 Time:   time.Now(),
324                         },
325                 },
326                 Dog: &Dog{
327                         SimpleStruct{
328                                 String: "Woof",
329                                 Bytes:  []byte("Bark"),
330                                 Time:   time.Now(),
331                         },
332                 },
333                 Snake:  Snake([]byte("hiss")),
334                 Snake2: snakePtr_,
335                 Viper:  Viper{Bytes: []byte("hizz")},
336                 Viper2: &Viper{Bytes: []byte("hizz")},
337         }
338         return c
339 }
340
341 func instantiateComplex2() (interface{}, interface{}) {
342         return ComplexStruct2{}, &ComplexStruct2{}
343 }
344
345 func validateComplex2(o interface{}, t *testing.T) {
346         c2 := o.(ComplexStruct2)
347         cat := c2.Cat
348         if cat.String != "String" {
349                 t.Errorf("Expected cat.String == 'String', got %v", cat.String)
350         }
351         if string(cat.Bytes) != "Bytes" {
352                 t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
353         }
354
355         dog := c2.Dog
356         if dog.String != "Woof" {
357                 t.Errorf("Expected dog.String == 'Woof', got %v", dog.String)
358         }
359         if string(dog.Bytes) != "Bark" {
360                 t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes)
361         }
362
363         snake := c2.Snake
364         if string(snake) != "hiss" {
365                 t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake))
366         }
367
368         snake2 := c2.Snake2
369         if string(*snake2) != "hiss" {
370                 t.Errorf("Expected string(snake2) == 'hiss', got %v", string(*snake2))
371         }
372
373         viper := c2.Viper
374         if string(viper.Bytes) != "hizz" {
375                 t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes))
376         }
377
378         viper2 := c2.Viper2
379         if string(viper2.Bytes) != "hizz" {
380                 t.Errorf("Expected string(viper2.Bytes) == 'hizz', got %v", string(viper2.Bytes))
381         }
382 }
383
384 //-------------------------------------
385
386 type ComplexStructArray struct {
387         Animals []Animal
388         Bytes   [5]byte
389         Ints    [5]int
390         Array   SimpleArray
391 }
392
393 func constructComplexArray() interface{} {
394         c := ComplexStructArray{
395                 Animals: []Animal{
396                         Cat{
397                                 SimpleStruct{
398                                         String: "String",
399                                         Bytes:  []byte("Bytes"),
400                                         Time:   time.Now(),
401                                 },
402                         },
403                         Dog{
404                                 SimpleStruct{
405                                         String: "Woof",
406                                         Bytes:  []byte("Bark"),
407                                         Time:   time.Now(),
408                                 },
409                         },
410                         Snake([]byte("hiss")),
411                         &Viper{
412                                 Bytes: []byte("hizz"),
413                         },
414                 },
415                 Bytes: [5]byte{1, 10, 50, 100, 200},
416                 Ints:  [5]int{1, 2, 3, 4, 5},
417                 Array: SimpleArray([5]byte{1, 10, 50, 100, 200}),
418         }
419         return c
420 }
421
422 func instantiateComplexArray() (interface{}, interface{}) {
423         return ComplexStructArray{}, &ComplexStructArray{}
424 }
425
426 func validateComplexArray(o interface{}, t *testing.T) {
427         c2 := o.(ComplexStructArray)
428         if cat, ok := c2.Animals[0].(Cat); ok {
429                 if cat.String != "String" {
430                         t.Errorf("Expected cat.String == 'String', got %v", cat.String)
431                 }
432                 if string(cat.Bytes) != "Bytes" {
433                         t.Errorf("Expected cat.Bytes == 'Bytes', got %X", cat.Bytes)
434                 }
435         } else {
436                 t.Errorf("Expected c2.Animals[0] to be of type cat, got %v", reflect.ValueOf(c2.Animals[0]).Elem().Type())
437         }
438
439         if dog, ok := c2.Animals[1].(Dog); ok {
440                 if dog.String != "Woof" {
441                         t.Errorf("Expected dog.String == 'Woof', got %v", dog.String)
442                 }
443                 if string(dog.Bytes) != "Bark" {
444                         t.Errorf("Expected dog.Bytes == 'Bark', got %X", dog.Bytes)
445                 }
446         } else {
447                 t.Errorf("Expected c2.Animals[1] to be of type dog, got %v", reflect.ValueOf(c2.Animals[1]).Elem().Type())
448         }
449
450         if snake, ok := c2.Animals[2].(Snake); ok {
451                 if string(snake) != "hiss" {
452                         t.Errorf("Expected string(snake) == 'hiss', got %v", string(snake))
453                 }
454         } else {
455                 t.Errorf("Expected c2.Animals[2] to be of type Snake, got %v", reflect.ValueOf(c2.Animals[2]).Elem().Type())
456         }
457
458         if viper, ok := c2.Animals[3].(*Viper); ok {
459                 if string(viper.Bytes) != "hizz" {
460                         t.Errorf("Expected string(viper.Bytes) == 'hizz', got %v", string(viper.Bytes))
461                 }
462         } else {
463                 t.Errorf("Expected c2.Animals[3] to be of type *Viper, got %v", reflect.ValueOf(c2.Animals[3]).Elem().Type())
464         }
465 }
466
467 //-----------------------------------------------------------------------------
468
469 var testCases = []TestCase{}
470
471 func init() {
472         testCases = append(testCases, TestCase{constructBasic, instantiateBasic, validateBasic})
473         testCases = append(testCases, TestCase{constructComplex, instantiateComplex, validateComplex})
474         testCases = append(testCases, TestCase{constructComplex2, instantiateComplex2, validateComplex2})
475         testCases = append(testCases, TestCase{constructComplexArray, instantiateComplexArray, validateComplexArray})
476         testCases = append(testCases, TestCase{constructNilTestStruct, instantiateNilTestStruct, validateNilTestStruct})
477 }
478
479 func TestBinary(t *testing.T) {
480
481         for i, testCase := range testCases {
482
483                 t.Log(fmt.Sprintf("Running test case %v", i))
484
485                 // Construct an object
486                 o := testCase.Constructor()
487
488                 // Write the object
489                 data := BinaryBytes(o)
490                 t.Logf("Binary: %X", data)
491
492                 instance, instancePtr := testCase.Instantiator()
493
494                 // Read onto a struct
495                 n, err := new(int), new(error)
496                 res := ReadBinary(instance, bytes.NewReader(data), 0, n, err)
497                 if *err != nil {
498                         t.Fatalf("Failed to read into instance: %v", *err)
499                 }
500
501                 // Validate object
502                 testCase.Validator(res, t)
503
504                 // Read onto a pointer
505                 n, err = new(int), new(error)
506                 res = ReadBinaryPtr(instancePtr, bytes.NewReader(data), 0, n, err)
507                 if *err != nil {
508                         t.Fatalf("Failed to read into instance: %v", *err)
509                 }
510                 if res != instancePtr {
511                         t.Errorf("Expected pointer to pass through")
512                 }
513
514                 // Validate object
515                 testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t)
516
517                 // Read with len(data)-1 limit should fail.
518                 instance, _ = testCase.Instantiator()
519                 n, err = new(int), new(error)
520                 ReadBinary(instance, bytes.NewReader(data), len(data)-1, n, err)
521                 if *err != ErrBinaryReadOverflow {
522                         t.Fatalf("Expected ErrBinaryReadOverflow")
523                 }
524
525                 // Read with len(data) limit should succeed.
526                 instance, _ = testCase.Instantiator()
527                 n, err = new(int), new(error)
528                 ReadBinary(instance, bytes.NewReader(data), len(data), n, err)
529                 if *err != nil {
530                         t.Fatalf("Failed to read instance with sufficient limit: %v", (*err).Error(), *n, len(data), reflect.TypeOf(instance))
531                 }
532         }
533
534 }
535
536 func TestJSON(t *testing.T) {
537
538         for i, testCase := range testCases {
539
540                 t.Log(fmt.Sprintf("Running test case %v", i))
541
542                 // Construct an object
543                 o := testCase.Constructor()
544
545                 // Write the object
546                 data := JSONBytes(o)
547                 t.Logf("JSON: %v", string(data))
548
549                 instance, instancePtr := testCase.Instantiator()
550
551                 // Read onto a struct
552                 err := new(error)
553                 res := ReadJSON(instance, data, err)
554                 if *err != nil {
555                         t.Fatalf("Failed to read cat: %v", *err)
556                 }
557
558                 // Validate object
559                 testCase.Validator(res, t)
560
561                 // Read onto a pointer
562                 res = ReadJSON(instancePtr, data, err)
563                 if *err != nil {
564                         t.Fatalf("Failed to read cat: %v", *err)
565                 }
566
567                 if res != instancePtr {
568                         t.Errorf("Expected pointer to pass through")
569                 }
570
571                 // Validate object
572                 testCase.Validator(reflect.ValueOf(res).Elem().Interface(), t)
573         }
574
575 }
576
577 //------------------------------------------------------------------------------
578
579 type Foo struct {
580         FieldA string `json:"fieldA"` // json field name is "fieldA"
581         FieldB string // json field name is "FieldB"
582         fieldC string // not exported, not serialized.
583         FieldD string `json:",omitempty"`  // omit if empty
584         FieldE string `json:",omitempty"`  // omit if empty (but won't be)
585         FieldF string `json:"F,omitempty"` // its name is "F", omit if empty
586         FieldG string `json:"G,omitempty"` // its name is "F", omit if empty (but won't be)
587 }
588
589 func TestJSONFieldNames(t *testing.T) {
590         for i := 0; i < 20; i++ { // Try to ensure deterministic success.
591                 foo := Foo{
592                         FieldA: "a",
593                         FieldB: "b",
594                         fieldC: "c",
595                         FieldD: "",  // omit because empty
596                         FieldE: "e", // no omit, not empty
597                         FieldF: "",  // omit because empty
598                         FieldG: "g", // no omit, not empty
599                 }
600                 stringified := string(JSONBytes(foo))
601                 expected := `{"fieldA":"a","FieldB":"b","FieldE":"e","G":"g"}`
602                 if stringified != expected {
603                         t.Fatalf("JSONFieldNames error: expected %v, got %v",
604                                 expected, stringified)
605                 }
606         }
607 }
608
609 //------------------------------------------------------------------------------
610
611 func TestBadAlloc(t *testing.T) {
612         n, err := new(int), new(error)
613         instance := new([]byte)
614         data := cmn.RandBytes(100 * 1024)
615         b := new(bytes.Buffer)
616         // this slice of data claims to be much bigger than it really is
617         WriteUvarint(uint(1<<32-1), b, n, err)
618         b.Write(data)
619         res := ReadBinary(instance, b, 0, n, err)
620         fmt.Println(res, *err)
621 }
622
623 //------------------------------------------------------------------------------
624
625 type SimpleArray [5]byte
626
627 func TestSimpleArray(t *testing.T) {
628         var foo SimpleArray
629
630         // Type of pointer to array
631         rt := reflect.TypeOf(&foo)
632         fmt.Printf("rt: %v\n", rt) // *binary.SimpleArray
633
634         // Type of array itself.
635         // NOTE: normally this is acquired through other means
636         // like introspecting on method signatures, or struct fields.
637         rte := rt.Elem()
638         fmt.Printf("rte: %v\n", rte) // binary.SimpleArray
639
640         // Get a new pointer to the array
641         // NOTE: calling .Interface() is to get the actual value,
642         // instead of reflection values.
643         ptr := reflect.New(rte).Interface()
644         fmt.Printf("ptr: %v\n", ptr) // &[0 0 0 0 0]
645
646         // Make a simple int aray
647         fooArray := SimpleArray([5]byte{1, 10, 50, 100, 200})
648         fooBytes := BinaryBytes(fooArray)
649         fooReader := bytes.NewReader(fooBytes)
650
651         // Now you can read it.
652         n, err := new(int), new(error)
653         it := ReadBinary(foo, fooReader, 0, n, err).(SimpleArray)
654
655         if !bytes.Equal(it[:], fooArray[:]) {
656                 t.Errorf("Expected %v but got %v", fooArray, it)
657         }
658 }
659
660 //--------------------------------------------------------------------------------
661
662 func TestNilPointerInterface(t *testing.T) {
663
664         type MyInterface interface{}
665         type MyConcreteStruct1 struct{}
666         type MyConcreteStruct2 struct{}
667
668         RegisterInterface(
669                 struct{ MyInterface }{},
670                 ConcreteType{&MyConcreteStruct1{}, 0x01},
671                 ConcreteType{&MyConcreteStruct2{}, 0x02},
672         )
673
674         type MyStruct struct {
675                 MyInterface
676         }
677
678         myStruct := MyStruct{(*MyConcreteStruct1)(nil)}
679         buf, n, err := new(bytes.Buffer), int(0), error(nil)
680         WriteBinary(myStruct, buf, &n, &err)
681         if err == nil {
682                 t.Error("Expected error in writing nil pointer interface")
683         }
684
685         myStruct = MyStruct{&MyConcreteStruct1{}}
686         buf, n, err = new(bytes.Buffer), int(0), error(nil)
687         WriteBinary(myStruct, buf, &n, &err)
688         if err != nil {
689                 t.Error("Unexpected error", err)
690         }
691
692 }
693
694 //--------------------------------------------------------------------------------
695
696 func TestMultipleInterfaces(t *testing.T) {
697
698         type MyInterface1 interface{}
699         type MyInterface2 interface{}
700         type Struct1 struct{}
701         type Struct2 struct{}
702
703         RegisterInterface(
704                 struct{ MyInterface1 }{},
705                 ConcreteType{&Struct1{}, 0x01},
706                 ConcreteType{&Struct2{}, 0x02},
707                 ConcreteType{Struct1{}, 0x03},
708                 ConcreteType{Struct2{}, 0x04},
709         )
710         RegisterInterface(
711                 struct{ MyInterface2 }{},
712                 ConcreteType{&Struct1{}, 0x11},
713                 ConcreteType{&Struct2{}, 0x12},
714                 ConcreteType{Struct1{}, 0x13},
715                 ConcreteType{Struct2{}, 0x14},
716         )
717
718         type MyStruct struct {
719                 F1 []MyInterface1
720                 F2 []MyInterface2
721         }
722
723         myStruct := MyStruct{
724                 F1: []MyInterface1{
725                         nil,
726                         &Struct1{},
727                         &Struct2{},
728                         Struct1{},
729                         Struct2{},
730                 },
731                 F2: []MyInterface2{
732                         nil,
733                         &Struct1{},
734                         &Struct2{},
735                         Struct1{},
736                         Struct2{},
737                 },
738         }
739         buf, n, err := new(bytes.Buffer), int(0), error(nil)
740         WriteBinary(myStruct, buf, &n, &err)
741         if err != nil {
742                 t.Error("Unexpected error", err)
743         }
744         if hexStr := hex.EncodeToString(buf.Bytes()); hexStr !=
745                 "0105"+"0001020304"+"0105"+"0011121314" {
746                 t.Error("Unexpected binary bytes", hexStr)
747         }
748
749         // Now, read
750
751         myStruct2 := MyStruct{}
752         ReadBinaryPtr(&myStruct2, buf, 0, &n, &err)
753         if err != nil {
754                 t.Error("Unexpected error", err)
755         }
756
757         if len(myStruct2.F1) != 5 {
758                 t.Error("Expected F1 to have 5 items")
759         }
760         if myStruct2.F1[0] != nil {
761                 t.Error("Expected F1[0] to be nil")
762         }
763         if _, ok := (myStruct2.F1[1]).(*Struct1); !ok {
764                 t.Error("Expected F1[1] to be of type *Struct1")
765         }
766         if s, _ := (myStruct2.F1[1]).(*Struct1); s == nil {
767                 t.Error("Expected F1[1] to be of type *Struct1 but not nil")
768         }
769         if _, ok := (myStruct2.F1[2]).(*Struct2); !ok {
770                 t.Error("Expected F1[2] to be of type *Struct2")
771         }
772         if s, _ := (myStruct2.F1[2]).(*Struct2); s == nil {
773                 t.Error("Expected F1[2] to be of type *Struct2 but not nil")
774         }
775         if _, ok := (myStruct2.F1[3]).(Struct1); !ok {
776                 t.Error("Expected F1[3] to be of type Struct1")
777         }
778         if _, ok := (myStruct2.F1[4]).(Struct2); !ok {
779                 t.Error("Expected F1[4] to be of type Struct2")
780         }
781         if myStruct2.F2[0] != nil {
782                 t.Error("Expected F2[0] to be nil")
783         }
784         if _, ok := (myStruct2.F2[1]).(*Struct1); !ok {
785                 t.Error("Expected F2[1] to be of type *Struct1")
786         }
787         if s, _ := (myStruct2.F2[1]).(*Struct1); s == nil {
788                 t.Error("Expected F2[1] to be of type *Struct1 but not nil")
789         }
790         if _, ok := (myStruct2.F2[2]).(*Struct2); !ok {
791                 t.Error("Expected F2[2] to be of type *Struct2")
792         }
793         if s, _ := (myStruct2.F2[2]).(*Struct2); s == nil {
794                 t.Error("Expected F2[2] to be of type *Struct2 but not nil")
795         }
796         if _, ok := (myStruct2.F2[3]).(Struct1); !ok {
797                 t.Error("Expected F2[3] to be of type Struct1")
798         }
799         if _, ok := (myStruct2.F2[4]).(Struct2); !ok {
800                 t.Error("Expected F2[4] to be of type Struct2")
801         }
802
803 }
804
805 //--------------------------------------------------------------------------------
806
807 func TestPointers(t *testing.T) {
808
809         type Struct1 struct {
810                 Foo int
811         }
812
813         type MyStruct struct {
814                 F1 *Struct1
815                 F2 *Struct1
816         }
817
818         myStruct := MyStruct{
819                 F1: nil,
820                 F2: &Struct1{8},
821         }
822         buf, n, err := new(bytes.Buffer), int(0), error(nil)
823         WriteBinary(myStruct, buf, &n, &err)
824         if err != nil {
825                 t.Error("Unexpected error", err)
826         }
827         if hexStr := hex.EncodeToString(buf.Bytes()); hexStr !=
828                 "00"+"010108" {
829                 t.Error("Unexpected binary bytes", hexStr)
830         }
831
832         // Now, read
833
834         myStruct2 := MyStruct{}
835         ReadBinaryPtr(&myStruct2, buf, 0, &n, &err)
836         if err != nil {
837                 t.Error("Unexpected error", err)
838         }
839
840         if myStruct2.F1 != nil {
841                 t.Error("Expected F1 to be nil")
842         }
843         if myStruct2.F2.Foo != 8 {
844                 t.Error("Expected F2.Foo to be 8")
845         }
846
847 }
848
849 //--------------------------------------------------------------------------------
850
851 func TestUnsafe(t *testing.T) {
852
853         type Struct1 struct {
854                 Foo float64
855         }
856
857         type Struct2 struct {
858                 Foo float64 `wire:"unsafe"`
859         }
860
861         myStruct := Struct1{5.32}
862         myStruct2 := Struct2{5.32}
863         buf, n, err := new(bytes.Buffer), int(0), error(nil)
864         WriteBinary(myStruct, buf, &n, &err)
865         if err == nil {
866                 t.Error("Expected error due to float without `unsafe`")
867         }
868
869         buf, n, err = new(bytes.Buffer), int(0), error(nil)
870         WriteBinary(myStruct2, buf, &n, &err)
871         if err != nil {
872                 t.Error("Unexpected error", err)
873         }
874
875         var s Struct2
876         n, err = int(0), error(nil)
877         ReadBinaryPtr(&s, buf, 0, &n, &err)
878         if err != nil {
879                 t.Error("Unexpected error", err)
880         }
881
882         if s.Foo != myStruct2.Foo {
883                 t.Error("Expected float values to be the same. Got", s.Foo, "expected", myStruct2.Foo)
884         }
885
886 }
887
888 //--------------------------------------------------------------------------------
889
890 func TestUnwrap(t *testing.T) {
891
892         type Result interface{}
893         type ConcreteResult struct{ A int }
894         RegisterInterface(
895                 struct{ Result }{},
896                 ConcreteType{&ConcreteResult{}, 0x01},
897         )
898
899         type Struct1 struct {
900                 Result Result `json:"unwrap"`
901                 other  string // this should be ignored, it is unexported
902                 Other  string `json:"-"` // this should also be ignored
903         }
904
905         myStruct := Struct1{Result: &ConcreteResult{5}}
906         buf, n, err := new(bytes.Buffer), int(0), error(nil)
907         WriteJSON(myStruct, buf, &n, &err)
908         if err != nil {
909                 t.Error("Unexpected error", err)
910         }
911         jsonBytes := buf.Bytes()
912         if string(jsonBytes) != `[1,{"A":5}]` {
913                 t.Error("Unexpected jsonBytes", string(jsonBytes))
914         }
915
916         var s Struct1
917         err = error(nil)
918         ReadJSON(&s, jsonBytes, &err)
919         if err != nil {
920                 t.Error("Unexpected error", err)
921         }
922
923         sConcrete, ok := s.Result.(*ConcreteResult)
924         if !ok {
925                 t.Error("Expected struct result to be of type ConcreteResult. Got", reflect.TypeOf(s.Result))
926         }
927
928         got := sConcrete.A
929         expected := myStruct.Result.(*ConcreteResult).A
930         if got != expected {
931                 t.Error("Expected values to match. Got", got, "expected", expected)
932         }
933
934 }