github.com/philpearl/plenc@v0.0.15/plenccodec/struct_test.go (about)

     1  package plenccodec_test
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/google/go-cmp/cmp"
     9  	"github.com/philpearl/plenc"
    10  	"github.com/philpearl/plenc/plenccodec"
    11  )
    12  
    13  func TestFieldRemoval(t *testing.T) {
    14  	type S1 struct {
    15  		A int     `plenc:"1"`
    16  		B int     `plenc:"2"`
    17  		C string  `plenc:"3"`
    18  		D float32 `plenc:"4"`
    19  		E float64 `plenc:"5"`
    20  	}
    21  	type S2 struct {
    22  		B int `plenc:"2"`
    23  	}
    24  
    25  	in := S1{A: 1, B: 2, C: "3", D: 4, E: 5}
    26  	data, err := plenc.Marshal(nil, &in)
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	var out S2
    32  	if err := plenc.Unmarshal(data, &out); err != nil {
    33  		t.Fatal(err)
    34  	}
    35  
    36  	if out.B != 2 {
    37  		t.Fatalf("Unmarshal unexpected value for B. %d", out.B)
    38  	}
    39  }
    40  
    41  func TestRecursiveStruct(t *testing.T) {
    42  	type s0 struct {
    43  		A []s0 `plenc:"1"`
    44  		B int  `plenc:"2"`
    45  	}
    46  
    47  	a := s0{
    48  		A: []s0{{A: []s0{{B: 1}}}, {A: []s0{{B: 1}}, B: 3}},
    49  	}
    50  
    51  	data, err := plenc.Marshal(nil, &a)
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  
    56  	var out s0
    57  	if err := plenc.Unmarshal(data, &out); err != nil {
    58  		t.Fatal(err)
    59  	}
    60  
    61  	if diff := cmp.Diff(a, out); diff != "" {
    62  		t.Fatalf("Not as expected. %s\n%x", diff, data)
    63  	}
    64  }
    65  
    66  func TestSliceStructPtr(t *testing.T) {
    67  	type S2 struct {
    68  		A int `plenc:"1"`
    69  	}
    70  	type S1 struct {
    71  		A []*S2 `plenc:"1"`
    72  	}
    73  
    74  	tests := []S1{
    75  		{},
    76  		{A: []*S2{
    77  			{A: 1},
    78  			{A: 2},
    79  		}},
    80  		{A: []*S2{
    81  			{A: 1},
    82  			{},
    83  			{A: 2},
    84  		}},
    85  	}
    86  
    87  	/*
    88  		00001011
    89  		0b 03
    90  		  02 0802
    91  		  00
    92  		  02 0804
    93  	*/
    94  	for _, test := range tests {
    95  		t.Run(fmt.Sprintf("%#v", test), func(t *testing.T) {
    96  			data, err := plenc.Marshal(nil, &test)
    97  			if err != nil {
    98  				t.Fatal(err)
    99  			}
   100  
   101  			var out S1
   102  			if err := plenc.Unmarshal(data, &out); err != nil {
   103  				t.Fatal(err)
   104  			}
   105  
   106  			if diff := cmp.Diff(test, out); diff != "" {
   107  				t.Fatalf("Not as expected. %s\n%x", diff, data)
   108  			}
   109  		})
   110  	}
   111  }
   112  
   113  func TestSliceStructPtrNil(t *testing.T) {
   114  	type S2 struct {
   115  		A int `plenc:"1"`
   116  	}
   117  	type S1 struct {
   118  		A []*S2 `plenc:"1"`
   119  	}
   120  
   121  	in := S1{A: []*S2{
   122  		{A: 1},
   123  		nil,
   124  		{A: 2},
   125  	}}
   126  
   127  	exp := S1{A: []*S2{
   128  		{A: 1},
   129  		{},
   130  		{A: 2},
   131  	}}
   132  
   133  	data, err := plenc.Marshal(nil, &in)
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  
   138  	var out S1
   139  	if err := plenc.Unmarshal(data, &out); err != nil {
   140  		t.Fatal(err)
   141  	}
   142  
   143  	if diff := cmp.Diff(exp, out); diff != "" {
   144  		t.Fatalf("Not as expected. %s\n%x", diff, data)
   145  	}
   146  }
   147  
   148  func TestZeroReuseSlice(t *testing.T) {
   149  	type s1 struct {
   150  		A int `plenc:"1"`
   151  		B int `plenc:"2"`
   152  	}
   153  	v := []s1{{A: 1}, {A: 2}}
   154  	v = v[:0]
   155  
   156  	w := []s1{{B: 3}, {B: 4}}
   157  	data, err := plenc.Marshal(nil, w)
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  
   162  	if err := plenc.Unmarshal(data, &v); err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	if diff := cmp.Diff(w, v); diff != "" {
   166  		t.Fatal(diff)
   167  	}
   168  }
   169  
   170  func TestZeroReuse(t *testing.T) {
   171  	type s1 struct {
   172  		A int `plenc:"1"`
   173  		B int `plenc:"2"`
   174  	}
   175  	v := s1{A: 37, B: 42}
   176  
   177  	w := s1{A: 0, B: 3}
   178  	data, err := plenc.Marshal(nil, w)
   179  	if err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	// We expect this to update v and not zero fields that aren't in the output.
   184  	// Note that plenc is implicitly omitempty for some field types, so zero
   185  	// ints in the data we're unmarshalling won't overwrite anything.
   186  	if err := plenc.Unmarshal(data, &v); err != nil {
   187  		t.Fatal(err)
   188  	}
   189  	if diff := cmp.Diff(s1{A: 37, B: 3}, v); diff != "" {
   190  		t.Fatal(diff)
   191  	}
   192  }
   193  
   194  func TestStructDescriptor(t *testing.T) {
   195  	type s2 struct {
   196  		A string `plenc:"1"`
   197  	}
   198  	type s1 struct {
   199  		A int `plenc:"1,flat"`
   200  		B int `plenc:"2"`
   201  		C s2  `plenc:"3"`
   202  	}
   203  
   204  	c, err := plenc.CodecForType(reflect.TypeOf(s1{}))
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  
   209  	if diff := cmp.Diff(plenccodec.Descriptor{
   210  		TypeName: "s1",
   211  		Type:     plenccodec.FieldTypeStruct,
   212  		Elements: []plenccodec.Descriptor{
   213  			{Index: 1, Name: "A", Type: plenccodec.FieldTypeFlatInt},
   214  			{Index: 2, Name: "B", Type: plenccodec.FieldTypeInt},
   215  			{
   216  				Index:    3,
   217  				Name:     "C",
   218  				Type:     plenccodec.FieldTypeStruct,
   219  				TypeName: "s2",
   220  				Elements: []plenccodec.Descriptor{
   221  					{Index: 1, Name: "A", Type: plenccodec.FieldTypeString},
   222  				},
   223  			},
   224  		},
   225  	}, c.Descriptor()); diff != "" {
   226  		t.Fatal(diff)
   227  	}
   228  }