github.com/jbendotnet/noms@v0.0.0-20190904222105-c43e4293ea92/go/marshal/encode_test.go (about)

     1  // Copyright 2016 Attic Labs, Inc. All rights reserved.
     2  // Licensed under the Apache License, version 2.0:
     3  // http://www.apache.org/licenses/LICENSE-2.0
     4  
     5  package marshal
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"math"
    12  	"regexp"
    13  	"strings"
    14  	"testing"
    15  
    16  	"github.com/attic-labs/noms/go/types"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestEncode(tt *testing.T) {
    21  	vs := newTestValueStore()
    22  	defer vs.Close()
    23  
    24  	t := func(exp types.Value, v interface{}) {
    25  		actual, err := Marshal(vs, v)
    26  		assert.NoError(tt, err)
    27  		assert.True(tt, exp.Equals(actual))
    28  
    29  		// Encode again for fallthrough
    30  		actual2, err := Marshal(vs, actual)
    31  		assert.NoError(tt, err)
    32  		assert.True(tt, exp.Equals(actual2))
    33  	}
    34  
    35  	for _, n := range []float32{0, 42, 3.14159265359, math.MaxFloat32} {
    36  		t(types.Number(n), n)
    37  		t(types.Number(-n), -n)
    38  	}
    39  
    40  	for _, n := range []float64{0, 42, 3.14159265359, 9007199254740991, math.MaxFloat64} {
    41  		t(types.Number(n), n)
    42  		t(types.Number(-n), -n)
    43  	}
    44  
    45  	for _, n := range []int8{0, 42, math.MaxInt8} {
    46  		t(types.Number(n), n)
    47  		t(types.Number(-n), -n)
    48  	}
    49  
    50  	for _, n := range []int16{0, 42, math.MaxInt16} {
    51  		t(types.Number(n), n)
    52  		t(types.Number(-n), -n)
    53  	}
    54  
    55  	for _, n := range []int32{0, 42, math.MaxInt32} {
    56  		t(types.Number(n), n)
    57  		t(types.Number(-n), -n)
    58  	}
    59  
    60  	// int is at least int32
    61  	for _, n := range []int{0, 42, math.MaxInt32} {
    62  		t(types.Number(n), n)
    63  		t(types.Number(-n), -n)
    64  	}
    65  
    66  	for _, n := range []int64{0, 42, math.MaxInt64} {
    67  		t(types.Number(n), n)
    68  		t(types.Number(-n), -n)
    69  	}
    70  
    71  	for _, n := range []uint8{0, 42, math.MaxUint8} {
    72  		t(types.Number(n), n)
    73  	}
    74  
    75  	for _, n := range []uint16{0, 42, math.MaxUint16} {
    76  		t(types.Number(n), n)
    77  	}
    78  
    79  	for _, n := range []uint32{0, 42, math.MaxUint32} {
    80  		t(types.Number(n), n)
    81  	}
    82  
    83  	// uint is at least uint32
    84  	for _, n := range []uint{0, 42, math.MaxUint32} {
    85  		t(types.Number(n), n)
    86  	}
    87  
    88  	for _, n := range []uint64{0, 42, math.MaxUint64} {
    89  		t(types.Number(n), n)
    90  	}
    91  
    92  	t(types.Bool(true), true)
    93  	t(types.Bool(false), false)
    94  
    95  	for _, s := range []string{"", "s", "hello", "💩"} {
    96  		t(types.String(s), s)
    97  	}
    98  
    99  	t(types.NewList(vs, types.Number(42)), types.NewList(vs, types.Number(42)))
   100  	t(types.NewMap(vs, types.Number(42), types.String("hi")), types.NewMap(vs, types.Number(42), types.String("hi")))
   101  	t(types.NewSet(vs, types.String("bye")), types.NewSet(vs, types.String("bye")))
   102  	t(types.NewBlob(vs, bytes.NewBufferString("hello")), types.NewBlob(vs, bytes.NewBufferString("hello")))
   103  
   104  	type TestStruct struct {
   105  		Str string
   106  		Num float64
   107  	}
   108  	t(types.NewStruct("TestStruct", types.StructData{
   109  		"num": types.Number(42),
   110  		"str": types.String("Hello"),
   111  	}), TestStruct{Str: "Hello", Num: 42})
   112  	// Same again to test caching
   113  	t(types.NewStruct("TestStruct", types.StructData{
   114  		"num": types.Number(1),
   115  		"str": types.String("Bye"),
   116  	}), TestStruct{Str: "Bye", Num: 1})
   117  
   118  	anonStruct := struct {
   119  		B bool
   120  	}{
   121  		true,
   122  	}
   123  	t(types.NewStruct("", types.StructData{
   124  		"b": types.Bool(true),
   125  	}), anonStruct)
   126  
   127  	type TestNestedStruct struct {
   128  		A types.List
   129  		B TestStruct
   130  		C float64
   131  	}
   132  	t(types.NewStruct("TestNestedStruct", types.StructData{
   133  		"a": types.NewList(vs, types.String("hi")),
   134  		"b": types.NewStruct("TestStruct", types.StructData{
   135  			"str": types.String("bye"),
   136  			"num": types.Number(5678),
   137  		}),
   138  		"c": types.Number(1234),
   139  	}), TestNestedStruct{
   140  		A: types.NewList(vs, types.String("hi")),
   141  		B: TestStruct{
   142  			Str: "bye",
   143  			Num: 5678,
   144  		},
   145  		C: 1234,
   146  	})
   147  
   148  	type testStruct struct {
   149  		Str string
   150  		Num float64
   151  	}
   152  	t(types.NewStruct("TestStruct", types.StructData{
   153  		"num": types.Number(42),
   154  		"str": types.String("Hello"),
   155  	}), testStruct{Str: "Hello", Num: 42})
   156  }
   157  
   158  func assertEncodeErrorMessage(t *testing.T, v interface{}, expectedMessage string) {
   159  	vs := newTestValueStore()
   160  	defer vs.Close()
   161  
   162  	_, err := Marshal(vs, v)
   163  	assert.Error(t, err)
   164  	assert.Equal(t, expectedMessage, err.Error())
   165  }
   166  
   167  func TestInvalidTypes(t *testing.T) {
   168  	assertEncodeErrorMessage(t, make(chan int), "Type is not supported, type: chan int")
   169  	x := 42
   170  	assertEncodeErrorMessage(t, &x, "Type is not supported, type: *int")
   171  }
   172  
   173  func TestEncodeEmbeddedStructSkip(t *testing.T) {
   174  	assert := assert.New(t)
   175  
   176  	vs := newTestValueStore()
   177  	defer vs.Close()
   178  
   179  	type EmbeddedStruct struct {
   180  		X int
   181  	}
   182  	type TestStruct struct {
   183  		EmbeddedStruct `noms:"-"`
   184  		Y              int
   185  	}
   186  	s := TestStruct{EmbeddedStruct{1}, 2}
   187  	v, err := Marshal(vs, s)
   188  	assert.NoError(err)
   189  	assert.True(types.NewStruct("TestStruct", types.StructData{
   190  		"y": types.Number(2),
   191  	}).Equals(v))
   192  }
   193  
   194  func TestEncodeEmbeddedStructWithName(t *testing.T) {
   195  	assert := assert.New(t)
   196  
   197  	vs := newTestValueStore()
   198  	defer vs.Close()
   199  
   200  	type EmbeddedStruct struct {
   201  		X int
   202  	}
   203  	type TestStruct struct {
   204  		EmbeddedStruct `noms:"em"`
   205  		Y              int
   206  	}
   207  	s := TestStruct{EmbeddedStruct{1}, 2}
   208  	v, err := Marshal(vs, s)
   209  	assert.NoError(err)
   210  	assert.True(types.NewStruct("TestStruct", types.StructData{
   211  		"em": types.NewStruct("EmbeddedStruct", types.StructData{
   212  			"x": types.Number(1),
   213  		}),
   214  		"y": types.Number(2),
   215  	}).Equals(v))
   216  }
   217  
   218  func TestEncodeEmbeddedStruct(t *testing.T) {
   219  	assert := assert.New(t)
   220  
   221  	vs := newTestValueStore()
   222  	defer vs.Close()
   223  
   224  	type EmbeddedStruct struct {
   225  		X int
   226  	}
   227  	type TestStruct struct {
   228  		EmbeddedStruct
   229  	}
   230  	s := TestStruct{EmbeddedStruct{1}}
   231  	v, err := Marshal(vs, s)
   232  	assert.NoError(err)
   233  	assert.True(types.NewStruct("TestStruct", types.StructData{
   234  		"x": types.Number(1),
   235  	}).Equals(v))
   236  
   237  	type TestOuter struct {
   238  		A int
   239  		TestStruct
   240  		B int
   241  	}
   242  	s2 := TestOuter{0, TestStruct{EmbeddedStruct{1}}, 2}
   243  	v2, err := Marshal(vs, s2)
   244  	assert.NoError(err)
   245  	assert.True(types.NewStruct("TestOuter", types.StructData{
   246  		"a": types.Number(0),
   247  		"b": types.Number(2),
   248  		"x": types.Number(1),
   249  	}).Equals(v2))
   250  }
   251  
   252  func TestEncodeEmbeddedStructOriginal(t *testing.T) {
   253  	assert := assert.New(t)
   254  
   255  	vs := newTestValueStore()
   256  	defer vs.Close()
   257  
   258  	type EmbeddedStruct struct {
   259  		X int
   260  		O types.Struct `noms:",original"`
   261  		B bool
   262  	}
   263  	type TestStruct struct {
   264  		EmbeddedStruct
   265  	}
   266  	s := TestStruct{
   267  		EmbeddedStruct: EmbeddedStruct{
   268  			X: 1,
   269  			B: true,
   270  		},
   271  	}
   272  	v, err := Marshal(vs, s)
   273  	assert.NoError(err)
   274  	assert.True(types.NewStruct("TestStruct", types.StructData{
   275  		"b": types.Bool(true),
   276  		"x": types.Number(1),
   277  	}).Equals(v))
   278  }
   279  
   280  func TestEncodeNonExportedField(t *testing.T) {
   281  	type TestStruct struct {
   282  		x int
   283  	}
   284  	assertEncodeErrorMessage(t, TestStruct{1}, "Non exported fields are not supported, type: marshal.TestStruct")
   285  }
   286  
   287  func TestEncodeTaggingSkip(t *testing.T) {
   288  	assert := assert.New(t)
   289  
   290  	vs := newTestValueStore()
   291  	defer vs.Close()
   292  
   293  	type S struct {
   294  		Abc int `noms:"-"`
   295  		Def bool
   296  	}
   297  	s := S{42, true}
   298  	v, err := Marshal(vs, s)
   299  	assert.NoError(err)
   300  	assert.True(types.NewStruct("S", types.StructData{
   301  		"def": types.Bool(true),
   302  	}).Equals(v))
   303  }
   304  
   305  func TestEncodeNamedFields(t *testing.T) {
   306  	assert := assert.New(t)
   307  
   308  	vs := newTestValueStore()
   309  	defer vs.Close()
   310  
   311  	type S struct {
   312  		Aaa int  `noms:"a"`
   313  		Bbb bool `noms:"B"`
   314  		Ccc string
   315  	}
   316  	s := S{42, true, "Hi"}
   317  	v, err := Marshal(vs, s)
   318  	assert.NoError(err)
   319  	assert.True(types.NewStruct("S", types.StructData{
   320  		"a":   types.Number(42),
   321  		"B":   types.Bool(true),
   322  		"ccc": types.String("Hi"),
   323  	}).Equals(v))
   324  }
   325  
   326  func TestEncodeInvalidNamedFields(t *testing.T) {
   327  	type S struct {
   328  		A int `noms:"1a"`
   329  	}
   330  	assertEncodeErrorMessage(t, S{42}, "Invalid struct field name: 1a")
   331  }
   332  
   333  func TestEncodeOmitEmpty(t *testing.T) {
   334  	assert := assert.New(t)
   335  
   336  	vs := newTestValueStore()
   337  	defer vs.Close()
   338  
   339  	type S struct {
   340  		String  string  `noms:",omitempty"`
   341  		Bool    bool    `noms:",omitempty"`
   342  		Int     int     `noms:",omitempty"`
   343  		Int8    int8    `noms:",omitempty"`
   344  		Int16   int16   `noms:",omitempty"`
   345  		Int32   int32   `noms:",omitempty"`
   346  		Int64   int64   `noms:",omitempty"`
   347  		Uint    uint    `noms:",omitempty"`
   348  		Uint8   uint8   `noms:",omitempty"`
   349  		Uint16  uint16  `noms:",omitempty"`
   350  		Uint32  uint32  `noms:",omitempty"`
   351  		Uint64  uint64  `noms:",omitempty"`
   352  		Float32 float32 `noms:",omitempty"`
   353  		Float64 float64 `noms:",omitempty"`
   354  	}
   355  	s := S{
   356  		String:  "s",
   357  		Bool:    true,
   358  		Int:     1,
   359  		Int8:    1,
   360  		Int16:   1,
   361  		Int32:   1,
   362  		Int64:   1,
   363  		Uint:    1,
   364  		Uint8:   1,
   365  		Uint16:  1,
   366  		Uint32:  1,
   367  		Uint64:  1,
   368  		Float32: 1,
   369  		Float64: 1,
   370  	}
   371  	v, err := Marshal(vs, s)
   372  	assert.NoError(err)
   373  	assert.True(types.NewStruct("S", types.StructData{
   374  		"string":  types.String("s"),
   375  		"bool":    types.Bool(true),
   376  		"int":     types.Number(1),
   377  		"int8":    types.Number(1),
   378  		"int16":   types.Number(1),
   379  		"int32":   types.Number(1),
   380  		"int64":   types.Number(1),
   381  		"uint":    types.Number(1),
   382  		"uint8":   types.Number(1),
   383  		"uint16":  types.Number(1),
   384  		"uint32":  types.Number(1),
   385  		"uint64":  types.Number(1),
   386  		"float32": types.Number(1),
   387  		"float64": types.Number(1),
   388  	}).Equals(v))
   389  
   390  	s2 := S{
   391  		String:  "",
   392  		Bool:    false,
   393  		Int:     0,
   394  		Int8:    0,
   395  		Int16:   0,
   396  		Int32:   0,
   397  		Int64:   0,
   398  		Uint:    0,
   399  		Uint8:   0,
   400  		Uint16:  0,
   401  		Uint32:  0,
   402  		Uint64:  0,
   403  		Float32: 0,
   404  		Float64: 0,
   405  	}
   406  	v2, err := Marshal(vs, s2)
   407  	assert.NoError(err)
   408  	assert.True(types.NewStruct("S", types.StructData{}).Equals(v2))
   409  
   410  	type S2 struct {
   411  		Slice []int       `noms:",omitempty"`
   412  		Map   map[int]int `noms:",omitempty"`
   413  	}
   414  
   415  	s3 := S2{
   416  		Slice: []int{0},
   417  		Map:   map[int]int{0: 0},
   418  	}
   419  	v3, err := Marshal(vs, s3)
   420  	assert.NoError(err)
   421  	assert.True(types.NewStruct("S2", types.StructData{
   422  		"slice": types.NewList(vs, types.Number(0)),
   423  		"map":   types.NewMap(vs, types.Number(0), types.Number(0)),
   424  	}).Equals(v3))
   425  
   426  	s4 := S2{
   427  		Slice: []int{},
   428  		Map:   map[int]int{},
   429  	}
   430  	v4, err := Marshal(vs, s4)
   431  	assert.NoError(err)
   432  	assert.True(types.NewStruct("S2", types.StructData{}).Equals(v4))
   433  
   434  	s5 := S2{
   435  		Slice: nil,
   436  		Map:   nil,
   437  	}
   438  	v5, err := Marshal(vs, s5)
   439  	assert.NoError(err)
   440  	assert.True(types.NewStruct("S2", types.StructData{}).Equals(v5))
   441  
   442  	type S3 struct {
   443  		List  types.List  `noms:",omitempty"`
   444  		Value types.Value `noms:",omitempty"`
   445  	}
   446  	s6 := S3{
   447  		List:  types.NewList(vs),
   448  		Value: types.Number(0),
   449  	}
   450  	v6, err := Marshal(vs, s6)
   451  	assert.NoError(err)
   452  	assert.True(types.NewStruct("S3", types.StructData{
   453  		"list":  types.NewList(vs),
   454  		"value": types.Number(0),
   455  	}).Equals(v6))
   456  
   457  	s7 := S3{
   458  		List:  types.List{},
   459  		Value: nil,
   460  	}
   461  	v7, err := Marshal(vs, s7)
   462  	assert.NoError(err)
   463  	assert.True(types.NewStruct("S3", types.StructData{}).Equals(v7))
   464  
   465  	// Both name and omitempty
   466  	type S4 struct {
   467  		X int `noms:"y,omitempty"`
   468  	}
   469  	s8 := S4{
   470  		X: 1,
   471  	}
   472  	v8, err := Marshal(vs, s8)
   473  	assert.NoError(err)
   474  	assert.True(types.NewStruct("S4", types.StructData{
   475  		"y": types.Number(1),
   476  	}).Equals(v8))
   477  
   478  	s9 := S4{
   479  		X: 0,
   480  	}
   481  	v9, err := Marshal(vs, s9)
   482  	assert.NoError(err)
   483  	assert.True(types.NewStruct("S4", types.StructData{}).Equals(v9))
   484  }
   485  
   486  func ExampleMarshal() {
   487  	vs := newTestValueStore()
   488  	defer vs.Close()
   489  
   490  	type Person struct {
   491  		Given string
   492  		Male  bool
   493  	}
   494  	arya, err := Marshal(vs, Person{"Arya", false})
   495  	if err != nil {
   496  		fmt.Println(err)
   497  		return
   498  	}
   499  
   500  	fmt.Printf("Given: %s, Male: %t\n", arya.(types.Struct).Get("given").(types.String), arya.(types.Struct).Get("male").(types.Bool))
   501  	// Output: Given: Arya, Male: false
   502  }
   503  
   504  func TestEncodeSlice(t *testing.T) {
   505  	assert := assert.New(t)
   506  
   507  	vs := newTestValueStore()
   508  	defer vs.Close()
   509  
   510  	v, err := Marshal(vs, []string{"a", "b", "c"})
   511  	assert.NoError(err)
   512  	assert.True(types.NewList(vs, types.String("a"), types.String("b"), types.String("c")).Equals(v))
   513  }
   514  
   515  func TestEncodeArray(t *testing.T) {
   516  	assert := assert.New(t)
   517  
   518  	vs := newTestValueStore()
   519  	defer vs.Close()
   520  
   521  	v, err := Marshal(vs, [3]int{1, 2, 3})
   522  	assert.NoError(err)
   523  	assert.True(types.NewList(vs, types.Number(1), types.Number(2), types.Number(3)).Equals(v))
   524  }
   525  
   526  func TestEncodeStructWithSlice(t *testing.T) {
   527  	assert := assert.New(t)
   528  
   529  	vs := newTestValueStore()
   530  	defer vs.Close()
   531  
   532  	type S struct {
   533  		List []int
   534  	}
   535  	v, err := Marshal(vs, S{[]int{1, 2, 3}})
   536  	assert.NoError(err)
   537  	assert.True(types.NewStruct("S", types.StructData{
   538  		"list": types.NewList(vs, types.Number(1), types.Number(2), types.Number(3)),
   539  	}).Equals(v))
   540  }
   541  
   542  func TestEncodeStructWithArrayOfNomsValue(t *testing.T) {
   543  	assert := assert.New(t)
   544  
   545  	vs := newTestValueStore()
   546  	defer vs.Close()
   547  
   548  	type S struct {
   549  		List [1]types.Set
   550  	}
   551  	v, err := Marshal(vs, S{[1]types.Set{types.NewSet(vs, types.Bool(true))}})
   552  	assert.NoError(err)
   553  	assert.True(types.NewStruct("S", types.StructData{
   554  		"list": types.NewList(vs, types.NewSet(vs, types.Bool(true))),
   555  	}).Equals(v))
   556  }
   557  
   558  func TestEncodeNomsTypePtr(t *testing.T) {
   559  	assert := assert.New(t)
   560  
   561  	vs := newTestValueStore()
   562  	defer vs.Close()
   563  
   564  	testMarshal := func(g interface{}, expected types.Value) {
   565  		v, err := Marshal(vs, g)
   566  		assert.NoError(err)
   567  		assert.Equal(expected, v)
   568  	}
   569  
   570  	type S struct {
   571  		Type *types.Type
   572  	}
   573  
   574  	primitive := types.StringType
   575  	testMarshal(S{primitive}, types.NewStruct("S", types.StructData{"type": primitive}))
   576  
   577  	complex := types.MakeStructType("Complex",
   578  		types.StructField{
   579  			Name: "stuff",
   580  			Type: types.StringType,
   581  		},
   582  	)
   583  	testMarshal(S{complex}, types.NewStruct("S", types.StructData{"type": complex}))
   584  }
   585  
   586  func TestEncodeRecursive(t *testing.T) {
   587  	assert := assert.New(t)
   588  
   589  	vs := newTestValueStore()
   590  	defer vs.Close()
   591  
   592  	type Node struct {
   593  		Value    int
   594  		Children []Node
   595  	}
   596  	v, err := Marshal(vs, Node{
   597  		1, []Node{
   598  			{2, []Node{}},
   599  			{3, []Node(nil)},
   600  		},
   601  	})
   602  	assert.NoError(err)
   603  
   604  	typ := types.MakeStructType("Node",
   605  		types.StructField{
   606  			Name: "children",
   607  			Type: types.MakeListType(types.MakeCycleType("Node")),
   608  		},
   609  		types.StructField{
   610  			Name: "value",
   611  			Type: types.NumberType,
   612  		},
   613  	)
   614  	assert.True(typ.Equals(types.TypeOf(v)))
   615  
   616  	assert.True(types.NewStruct("Node", types.StructData{
   617  		"children": types.NewList(
   618  			vs,
   619  			types.NewStruct("Node", types.StructData{
   620  				"children": types.NewList(vs),
   621  				"value":    types.Number(2),
   622  			}),
   623  			types.NewStruct("Node", types.StructData{
   624  				"children": types.NewList(vs),
   625  				"value":    types.Number(3),
   626  			}),
   627  		),
   628  		"value": types.Number(1),
   629  	}).Equals(v))
   630  }
   631  
   632  func TestEncodeMap(t *testing.T) {
   633  	assert := assert.New(t)
   634  
   635  	vs := newTestValueStore()
   636  	defer vs.Close()
   637  
   638  	v, err := Marshal(vs, map[string]int{"a": 1, "b": 2, "c": 3})
   639  	assert.NoError(err)
   640  	assert.True(types.NewMap(
   641  		vs,
   642  		types.String("a"), types.Number(1),
   643  		types.String("b"), types.Number(2),
   644  		types.String("c"), types.Number(3)).Equals(v))
   645  
   646  	type S struct {
   647  		N string
   648  	}
   649  	v, err = Marshal(vs, map[S]bool{S{"Yes"}: true, S{"No"}: false})
   650  	assert.NoError(err)
   651  	assert.True(types.NewMap(
   652  		vs,
   653  		types.NewStruct("S", types.StructData{"n": types.String("Yes")}), types.Bool(true),
   654  		types.NewStruct("S", types.StructData{"n": types.String("No")}), types.Bool(false)).Equals(v))
   655  
   656  	v, err = Marshal(vs, map[string]int(nil))
   657  	assert.NoError(err)
   658  	assert.True(types.NewMap(vs).Equals(v))
   659  
   660  	v, err = Marshal(vs, map[string]int{})
   661  	assert.NoError(err)
   662  	assert.True(types.NewMap(vs).Equals(v))
   663  }
   664  
   665  func TestEncodeInterface(t *testing.T) {
   666  	assert := assert.New(t)
   667  
   668  	vs := newTestValueStore()
   669  	defer vs.Close()
   670  
   671  	var i interface{}
   672  	i = []string{"a", "b"}
   673  	v, err := Marshal(vs, i)
   674  	assert.NoError(err)
   675  	assert.True(types.NewList(vs, types.String("a"), types.String("b")).Equals(v))
   676  
   677  	i = map[interface{}]interface{}{"a": true, struct{ Name string }{"b"}: 42}
   678  	v, err = Marshal(vs, i)
   679  	assert.NoError(err)
   680  	assert.True(types.NewMap(
   681  		vs,
   682  		types.String("a"), types.Bool(true),
   683  		types.NewStruct("", types.StructData{"name": types.String("b")}), types.Number(42),
   684  	).Equals(v))
   685  }
   686  
   687  func TestEncodeSet(t *testing.T) {
   688  	assert := assert.New(t)
   689  
   690  	vs := newTestValueStore()
   691  	defer vs.Close()
   692  
   693  	v, err := Marshal(vs, struct {
   694  		A map[int]struct{} `noms:",set"`
   695  		B map[int]struct{}
   696  		C map[int]string      `noms:",set"`
   697  		D map[string]struct{} `noms:",set"`
   698  		E map[string]struct{}
   699  		F map[string]int `noms:",set"`
   700  		G []int          `noms:",set"`
   701  		H string         `noms:",set"`
   702  	}{
   703  		map[int]struct{}{0: {}, 1: {}, 2: {}},
   704  		map[int]struct{}{3: {}, 4: {}, 5: {}},
   705  		map[int]string{},
   706  		map[string]struct{}{"A": {}, "B": {}, "C": {}},
   707  		map[string]struct{}{"D": {}, "E": {}, "F": {}},
   708  		map[string]int{},
   709  		[]int{1, 2, 3},
   710  		"",
   711  	})
   712  	assert.NoError(err)
   713  	s, ok := v.(types.Struct)
   714  	assert.True(ok)
   715  
   716  	expect := map[string]types.NomsKind{
   717  		"a": types.SetKind,
   718  		"b": types.MapKind,
   719  		"c": types.MapKind,
   720  		"d": types.SetKind,
   721  		"e": types.MapKind,
   722  		"f": types.MapKind,
   723  		"g": types.SetKind,
   724  		"h": types.StringKind,
   725  	}
   726  	for fieldName, kind := range expect {
   727  		assert.Equal(kind, s.Get(fieldName).Kind())
   728  	}
   729  
   730  	// Test both the Set values are correct, and that the equivalent typed Map
   731  	// are correct in case the Set marshaling interferes with it.
   732  
   733  	a := s.Get("a").(types.Set)
   734  	assert.True(a.Has(types.Number(0)))
   735  	assert.True(a.Has(types.Number(1)))
   736  	assert.True(a.Has(types.Number(2)))
   737  
   738  	b := s.Get("b").(types.Map)
   739  	assert.True(b.Has(types.Number(3)))
   740  	assert.True(b.Has(types.Number(4)))
   741  	assert.True(b.Has(types.Number(5)))
   742  
   743  	d := s.Get("d").(types.Set)
   744  	assert.True(d.Has(types.String("A")))
   745  	assert.True(d.Has(types.String("B")))
   746  	assert.True(d.Has(types.String("C")))
   747  
   748  	e := s.Get("e").(types.Map)
   749  	assert.True(e.Has(types.String("D")))
   750  	assert.True(e.Has(types.String("E")))
   751  	assert.True(e.Has(types.String("F")))
   752  
   753  	g := s.Get("g").(types.Set)
   754  	assert.True(g.Has(types.Number(1)))
   755  	assert.True(g.Has(types.Number(2)))
   756  	assert.True(g.Has(types.Number(3)))
   757  }
   758  
   759  func TestEncodeOpt(t *testing.T) {
   760  	assert := assert.New(t)
   761  
   762  	vs := newTestValueStore()
   763  	defer vs.Close()
   764  
   765  	tc := []struct {
   766  		in        interface{}
   767  		opt       Opt
   768  		wantValue types.Value
   769  	}{
   770  		{
   771  			[]string{"a", "b"},
   772  			Opt{},
   773  			types.NewList(vs, types.String("a"), types.String("b")),
   774  		},
   775  		{
   776  			[]string{"a", "b"},
   777  			Opt{Set: true},
   778  			types.NewSet(vs, types.String("a"), types.String("b")),
   779  		},
   780  		{
   781  			map[string]struct{}{"a": struct{}{}, "b": struct{}{}},
   782  			Opt{},
   783  			types.NewMap(vs, types.String("a"), types.NewStruct("", nil), types.String("b"), types.NewStruct("", nil)),
   784  		},
   785  		{
   786  			map[string]struct{}{"a": struct{}{}, "b": struct{}{}},
   787  			Opt{Set: true},
   788  			types.NewSet(vs, types.String("a"), types.String("b")),
   789  		},
   790  	}
   791  
   792  	for _, t := range tc {
   793  		r, err := MarshalOpt(vs, t.in, t.opt)
   794  		assert.True(t.wantValue.Equals(r))
   795  		assert.Nil(err)
   796  	}
   797  }
   798  
   799  func TestEncodeSetWithTags(t *testing.T) {
   800  	assert := assert.New(t)
   801  
   802  	vs := newTestValueStore()
   803  	defer vs.Close()
   804  
   805  	v, err := Marshal(vs, struct {
   806  		A map[int]struct{} `noms:"foo,set"`
   807  		B map[int]struct{} `noms:",omitempty,set"`
   808  		C map[int]struct{} `noms:"bar,omitempty,set"`
   809  	}{
   810  		A: map[int]struct{}{0: {}, 1: {}},
   811  		C: map[int]struct{}{2: {}, 3: {}},
   812  	})
   813  	assert.NoError(err)
   814  	s, ok := v.(types.Struct)
   815  	assert.True(ok)
   816  
   817  	_, ok = s.MaybeGet("a")
   818  	assert.False(ok)
   819  	_, ok = s.MaybeGet("b")
   820  	assert.False(ok)
   821  	_, ok = s.MaybeGet("c")
   822  	assert.False(ok)
   823  
   824  	foo, ok := s.Get("foo").(types.Set)
   825  	assert.True(ok)
   826  	assert.True(types.NewSet(vs, types.Number(0), types.Number(1)).Equals(foo))
   827  
   828  	bar, ok := s.Get("bar").(types.Set)
   829  	assert.True(ok)
   830  	assert.True(types.NewSet(vs, types.Number(2), types.Number(3)).Equals(bar))
   831  }
   832  
   833  func TestInvalidTag(t *testing.T) {
   834  	vs := newTestValueStore()
   835  	defer vs.Close()
   836  
   837  	_, err := Marshal(vs, struct {
   838  		F string `noms:",omitEmpty"`
   839  	}{"F"})
   840  	assert.Error(t, err)
   841  	assert.Equal(t, `Unrecognized tag: omitEmpty`, err.Error())
   842  }
   843  
   844  func TestEncodeCanSkipUnexportedField(t *testing.T) {
   845  	assert := assert.New(t)
   846  
   847  	vs := newTestValueStore()
   848  	defer vs.Close()
   849  
   850  	type S struct {
   851  		Abc         int
   852  		notExported bool `noms:"-"`
   853  	}
   854  	s := S{42, true}
   855  	v, err := Marshal(vs, s)
   856  	assert.NoError(err)
   857  	assert.True(types.NewStruct("S", types.StructData{
   858  		"abc": types.Number(42),
   859  	}).Equals(v))
   860  }
   861  
   862  func TestEncodeOriginal(t *testing.T) {
   863  	assert := assert.New(t)
   864  
   865  	vs := newTestValueStore()
   866  	defer vs.Close()
   867  
   868  	type S struct {
   869  		Foo int          `noms:",omitempty"`
   870  		Bar types.Struct `noms:",original"`
   871  	}
   872  
   873  	var s S
   874  	var err error
   875  	var orig types.Struct
   876  
   877  	// New field value clobbers old field value
   878  	orig = types.NewStruct("S", types.StructData{
   879  		"foo": types.Number(42),
   880  	})
   881  	err = Unmarshal(orig, &s)
   882  	assert.NoError(err)
   883  	s.Foo = 43
   884  	assert.True(MustMarshal(vs, s).Equals(orig.Set("foo", types.Number(43))))
   885  
   886  	// New field extends old struct
   887  	orig = types.NewStruct("S", types.StructData{})
   888  	err = Unmarshal(orig, &s)
   889  	assert.NoError(err)
   890  	s.Foo = 43
   891  	assert.True(MustMarshal(vs, s).Equals(orig.Set("foo", types.Number(43))))
   892  
   893  	// Old struct name always used
   894  	orig = types.NewStruct("Q", types.StructData{})
   895  	err = Unmarshal(orig, &s)
   896  	assert.NoError(err)
   897  	s.Foo = 43
   898  	assert.True(MustMarshal(vs, s).Equals(orig.Set("foo", types.Number(43))))
   899  
   900  	// Field type of base are preserved
   901  	orig = types.NewStruct("S", types.StructData{
   902  		"foo": types.Number(42),
   903  	})
   904  	err = Unmarshal(orig, &s)
   905  	assert.NoError(err)
   906  	s.Foo = 43
   907  	out := MustMarshal(vs, s)
   908  	assert.True(out.Equals(orig.Set("foo", types.Number(43))))
   909  
   910  	st2 := types.MakeStructTypeFromFields("S", types.FieldMap{
   911  		"foo": types.NumberType,
   912  	})
   913  	assert.True(types.TypeOf(out).Equals(st2))
   914  
   915  	// It's OK to have an empty original field
   916  	s = S{
   917  		Foo: 42,
   918  	}
   919  	assert.True(MustMarshal(vs, s).Equals(
   920  		types.NewStruct("S", types.StructData{"foo": types.Number(float64(42))})))
   921  }
   922  
   923  func TestNomsTypes(t *testing.T) {
   924  	assert := assert.New(t)
   925  
   926  	vs := newTestValueStore()
   927  	defer vs.Close()
   928  
   929  	type S struct {
   930  		Blob   types.Blob
   931  		Bool   types.Bool
   932  		Number types.Number
   933  		String types.String
   934  		Type   *types.Type
   935  	}
   936  	s := S{
   937  		Blob:   types.NewBlob(vs),
   938  		Bool:   types.Bool(true),
   939  		Number: types.Number(42),
   940  		String: types.String("hi"),
   941  		Type:   types.NumberType,
   942  	}
   943  	assert.True(MustMarshal(vs, s).Equals(
   944  		types.NewStruct("S", types.StructData{
   945  			"blob":   types.NewBlob(vs),
   946  			"bool":   types.Bool(true),
   947  			"number": types.Number(42),
   948  			"string": types.String("hi"),
   949  			"type":   types.NumberType,
   950  		}),
   951  	))
   952  }
   953  
   954  type primitiveType int
   955  
   956  func (t primitiveType) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
   957  	return types.Number(int(t) + 1), nil
   958  }
   959  
   960  func TestMarshalerPrimitiveType(t *testing.T) {
   961  	assert := assert.New(t)
   962  
   963  	vs := newTestValueStore()
   964  	defer vs.Close()
   965  
   966  	u := primitiveType(42)
   967  	v := MustMarshal(vs, u)
   968  	assert.Equal(types.Number(43), v)
   969  }
   970  
   971  type primitiveSliceType []string
   972  
   973  func (u primitiveSliceType) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
   974  	return types.String(strings.Join(u, ",")), nil
   975  }
   976  
   977  func TestMarshalerPrimitiveSliceType(t *testing.T) {
   978  	assert := assert.New(t)
   979  
   980  	vs := newTestValueStore()
   981  	defer vs.Close()
   982  
   983  	u := primitiveSliceType([]string{"a", "b", "c"})
   984  	v := MustMarshal(vs, u)
   985  	assert.Equal(types.String("a,b,c"), v)
   986  }
   987  
   988  type primitiveMapType map[string]string
   989  
   990  func (u primitiveMapType) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
   991  	var vals types.ValueSlice
   992  	for k, v := range u {
   993  		vals = append(vals, types.String(k+","+v))
   994  	}
   995  	return types.NewSet(vrw, vals...), nil
   996  }
   997  
   998  func TestMarshalerPrimitiveMapType(t *testing.T) {
   999  	assert := assert.New(t)
  1000  
  1001  	vs := newTestValueStore()
  1002  	defer vs.Close()
  1003  
  1004  	u := primitiveMapType(map[string]string{
  1005  		"a": "foo",
  1006  		"b": "bar",
  1007  	})
  1008  	v := MustMarshal(vs, u)
  1009  	assert.True(types.NewSet(vs, types.String("a,foo"), types.String("b,bar")).Equals(v))
  1010  }
  1011  
  1012  type primitiveStructType struct {
  1013  	x, y int
  1014  }
  1015  
  1016  func (u primitiveStructType) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
  1017  	return types.Number(u.x + u.y), nil
  1018  }
  1019  
  1020  func TestMarshalerPrimitiveStructType(t *testing.T) {
  1021  	assert := assert.New(t)
  1022  
  1023  	vs := newTestValueStore()
  1024  	defer vs.Close()
  1025  
  1026  	u := primitiveStructType{1, 2}
  1027  	v := MustMarshal(vs, u)
  1028  	assert.Equal(types.Number(3), v)
  1029  }
  1030  
  1031  type builtinType regexp.Regexp
  1032  
  1033  func (u builtinType) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
  1034  	r := regexp.Regexp(u)
  1035  	return types.String(r.String()), nil
  1036  }
  1037  
  1038  func TestMarshalerBuiltinType(t *testing.T) {
  1039  	assert := assert.New(t)
  1040  
  1041  	vs := newTestValueStore()
  1042  	defer vs.Close()
  1043  
  1044  	s := "[a-z]+$"
  1045  	r := regexp.MustCompile(s)
  1046  	u := builtinType(*r)
  1047  	v := MustMarshal(vs, u)
  1048  	assert.Equal(types.String(s), v)
  1049  }
  1050  
  1051  type wrappedMarshalerType primitiveType
  1052  
  1053  func (u wrappedMarshalerType) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
  1054  	return types.Number(int(u) + 2), nil
  1055  }
  1056  
  1057  func TestMarshalerWrapperMarshalerType(t *testing.T) {
  1058  	assert := assert.New(t)
  1059  
  1060  	vs := newTestValueStore()
  1061  	defer vs.Close()
  1062  
  1063  	u := wrappedMarshalerType(primitiveType(42))
  1064  	v := MustMarshal(vs, u)
  1065  	assert.Equal(types.Number(44), v)
  1066  }
  1067  
  1068  type TestComplexStructType struct {
  1069  	P       primitiveType
  1070  	Ps      []primitiveType
  1071  	Pm      map[string]primitiveType
  1072  	Pslice  primitiveSliceType
  1073  	Pmap    primitiveMapType
  1074  	Pstruct primitiveStructType
  1075  	B       builtinType
  1076  }
  1077  
  1078  func TestMarshalerComplexStructType(t *testing.T) {
  1079  	assert := assert.New(t)
  1080  
  1081  	vs := newTestValueStore()
  1082  	defer vs.Close()
  1083  
  1084  	s := "foo|bar"
  1085  	r := regexp.MustCompile(s)
  1086  	u := TestComplexStructType{
  1087  		P:  42,
  1088  		Ps: []primitiveType{1, 2},
  1089  		Pm: map[string]primitiveType{
  1090  			"x": 100,
  1091  			"y": 101,
  1092  		},
  1093  		Pslice: primitiveSliceType{"a", "b", "c"},
  1094  		Pmap: primitiveMapType{
  1095  			"c": "123",
  1096  			"d": "456",
  1097  		},
  1098  		Pstruct: primitiveStructType{10, 20},
  1099  		B:       builtinType(*r),
  1100  	}
  1101  
  1102  	v := MustMarshal(vs, u)
  1103  
  1104  	assert.True(types.NewStruct("TestComplexStructType", types.StructData{
  1105  		"p":       types.Number(43),
  1106  		"ps":      types.NewList(vs, types.Number(2), types.Number(3)),
  1107  		"pm":      types.NewMap(vs, types.String("x"), types.Number(101), types.String("y"), types.Number(102)),
  1108  		"pslice":  types.String("a,b,c"),
  1109  		"pmap":    types.NewSet(vs, types.String("c,123"), types.String("d,456")),
  1110  		"pstruct": types.Number(30),
  1111  		"b":       types.String(s),
  1112  	}).Equals(v))
  1113  }
  1114  
  1115  type returnsMarshalerError struct {
  1116  	err error
  1117  }
  1118  
  1119  func (u returnsMarshalerError) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
  1120  	return nil, u.err
  1121  }
  1122  
  1123  type returnsMarshalerNil struct{}
  1124  
  1125  func (u returnsMarshalerNil) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
  1126  	return nil, nil
  1127  }
  1128  
  1129  type panicsMarshaler struct{}
  1130  
  1131  func (u panicsMarshaler) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
  1132  	panic("panic")
  1133  }
  1134  
  1135  func TestMarshalerErrors(t *testing.T) {
  1136  	assert := assert.New(t)
  1137  
  1138  	vs := newTestValueStore()
  1139  	defer vs.Close()
  1140  
  1141  	expErr := errors.New("expected error")
  1142  	m1 := returnsMarshalerError{expErr}
  1143  	_, actErr := Marshal(vs, m1)
  1144  	assert.Equal(expErr, actErr)
  1145  
  1146  	m2 := returnsMarshalerNil{}
  1147  	assert.Panics(func() { Marshal(vs, m2) })
  1148  
  1149  	m3 := panicsMarshaler{}
  1150  	assert.Panics(func() { Marshal(vs, m3) })
  1151  }
  1152  
  1153  type TestStructWithNameImpl struct {
  1154  	X int
  1155  }
  1156  
  1157  func (ts TestStructWithNameImpl) MarshalNomsStructName() string {
  1158  	return "A"
  1159  }
  1160  func TestMarshalStructName(t *testing.T) {
  1161  	assert := assert.New(t)
  1162  
  1163  	vs := newTestValueStore()
  1164  	defer vs.Close()
  1165  
  1166  	ts := TestStructWithNameImpl{
  1167  		X: 1,
  1168  	}
  1169  	v := MustMarshal(vs, ts)
  1170  	assert.True(types.NewStruct("A", types.StructData{
  1171  		"x": types.Number(1),
  1172  	}).Equals(v), types.EncodedValue(v))
  1173  }
  1174  
  1175  type TestStructWithNameImpl2 struct {
  1176  	X int
  1177  }
  1178  
  1179  func (ts TestStructWithNameImpl2) MarshalNomsStructName() string {
  1180  	return ""
  1181  }
  1182  func TestMarshalStructName2(t *testing.T) {
  1183  	assert := assert.New(t)
  1184  
  1185  	vs := newTestValueStore()
  1186  	defer vs.Close()
  1187  
  1188  	ts := TestStructWithNameImpl2{
  1189  		X: 1,
  1190  	}
  1191  	v := MustMarshal(vs, ts)
  1192  	assert.True(types.NewStruct("", types.StructData{
  1193  		"x": types.Number(1),
  1194  	}).Equals(v), types.EncodedValue(v))
  1195  }