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

     1  package plenccodec_test
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/google/go-cmp/cmp"
     8  	fuzz "github.com/google/gofuzz"
     9  	"github.com/philpearl/plenc"
    10  )
    11  
    12  func TestMap(t *testing.T) {
    13  	one := 1
    14  	two := 2
    15  
    16  	type mk struct {
    17  		A int `plenc:"1"`
    18  		B int `plenc:"2"`
    19  	}
    20  
    21  	type thing struct {
    22  		M map[string]string `plenc:"1"`
    23  		I int               `plenc:"2"`
    24  	}
    25  
    26  	tests := []struct {
    27  		name string
    28  		data interface{}
    29  	}{
    30  		{
    31  			name: "string,string",
    32  			data: map[string]string{
    33  				"hat": "hut",
    34  				"it":  "sit",
    35  			},
    36  		},
    37  		{
    38  			name: "string,string empty",
    39  			data: map[string]string{},
    40  		},
    41  		{
    42  			name: "string,string empty strings",
    43  			data: map[string]string{
    44  				"hat": "",
    45  				"it":  "",
    46  				"":    "elephant",
    47  			},
    48  		},
    49  		{
    50  			name: "string,int",
    51  			data: map[string]int{
    52  				"hat": 0,
    53  				"it":  32,
    54  			},
    55  		},
    56  		{
    57  			name: "string,*int",
    58  			data: map[string]*int{
    59  				"hat": nil,
    60  				"it":  &one,
    61  			},
    62  		},
    63  		{
    64  			name: "string,*int",
    65  			data: map[string]*int{
    66  				"hat": nil,
    67  				"it":  &one,
    68  				"at":  &two,
    69  			},
    70  		},
    71  		{
    72  			name: "string,*int just nil",
    73  			data: map[string]*int{
    74  				"hat": nil,
    75  			},
    76  		},
    77  		{
    78  			name: "float,*int",
    79  			data: map[float32]*int{
    80  				0:     nil,
    81  				1.001: &one,
    82  			},
    83  		},
    84  		{
    85  			name: "struct,*int",
    86  			data: map[mk]*int{
    87  				{A: 1, B: 7}: nil,
    88  				{A: 1, B: 3}: &one,
    89  			},
    90  		},
    91  		{
    92  			name: "nil map",
    93  			data: map[string]string(nil),
    94  		},
    95  		{
    96  			name: "map in struct nil",
    97  			data: thing{},
    98  		},
    99  		{
   100  			name: "map in struct empty",
   101  			data: thing{M: map[string]string{}},
   102  		},
   103  		{
   104  			name: "map in struct",
   105  			data: thing{
   106  				M: map[string]string{"A": "B"},
   107  			},
   108  		},
   109  		{
   110  			name: "map in struct with following",
   111  			data: thing{
   112  				M: map[string]string{"A": "B"},
   113  				I: 100,
   114  			},
   115  		},
   116  	}
   117  
   118  	for _, test := range tests {
   119  		t.Run(test.name, func(t *testing.T) {
   120  			data, err := plenc.Marshal(nil, test.data)
   121  			if err != nil {
   122  				t.Fatal(err)
   123  			}
   124  
   125  			mv := reflect.New(reflect.TypeOf(test.data))
   126  			if err := plenc.Unmarshal(data, mv.Interface()); err != nil {
   127  				t.Fatal(err)
   128  			}
   129  
   130  			if diff := cmp.Diff(test.data, mv.Elem().Interface()); diff != "" {
   131  				t.Fatalf("result differs: %s", diff)
   132  			}
   133  		})
   134  	}
   135  }
   136  
   137  func TestMapZero(t *testing.T) {
   138  	// This matches the behaviour of the standard json package, but is different
   139  	// to unmarshalling into a struct where the struct is always zeroed first
   140  	m := map[string]string{"hat": "pineapple"}
   141  	n := map[string]string{"cheese": "monkey"}
   142  	data, err := plenc.Marshal(nil, n)
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  	if err := plenc.Unmarshal(data, &m); err != nil {
   147  		t.Fatal(err)
   148  	}
   149  	if diff := cmp.Diff(map[string]string{
   150  		"hat":    "pineapple",
   151  		"cheese": "monkey",
   152  	}, m); diff != "" {
   153  		t.Fatal(diff)
   154  	}
   155  }
   156  
   157  func TestMapFuzz(t *testing.T) {
   158  	fz := fuzz.New()
   159  
   160  	for i := 0; i < 100; i++ {
   161  		var in, out map[string]string
   162  		fz.Fuzz(&in)
   163  
   164  		data, err := plenc.Marshal(nil, in)
   165  		if err != nil {
   166  			t.Fatal(err)
   167  		}
   168  
   169  		if err := plenc.Unmarshal(data, &out); err != nil {
   170  			t.Fatal(err)
   171  		}
   172  
   173  		if diff := cmp.Diff(in, out); diff != "" {
   174  			t.Fatalf("result differs (%d): %s", i, diff)
   175  		}
   176  	}
   177  }
   178  
   179  func BenchmarkMap(b *testing.B) {
   180  	m := map[string]string{
   181  		"AAA":  "AAA",
   182  		"AAA1": "AAA",
   183  		"AAA2": "AAA",
   184  		"AAA3": "AAA",
   185  		"AAA4": "AAA",
   186  		"AAA5": "AAA",
   187  		"AAA6": "AAA",
   188  		"AAA7": "AAA",
   189  	}
   190  
   191  	b.ResetTimer()
   192  	b.ReportAllocs()
   193  	var data []byte
   194  	var o map[string]string
   195  	for i := 0; i < b.N; i++ {
   196  		var err error
   197  		data, err = plenc.Marshal(data[:0], m)
   198  		if err != nil {
   199  			b.Fatal(err)
   200  		}
   201  		for k := range o {
   202  			delete(o, k)
   203  		}
   204  		if err := plenc.Unmarshal(data, &o); err != nil {
   205  			b.Fatal(err)
   206  		}
   207  	}
   208  }