github.com/jbendotnet/noms@v0.0.0-20190904222105-c43e4293ea92/go/marshal/encode_type_test.go (about) 1 // Copyright 2017 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 "errors" 9 "fmt" 10 "reflect" 11 "testing" 12 13 "github.com/attic-labs/noms/go/nomdl" 14 "github.com/attic-labs/noms/go/types" 15 "github.com/stretchr/testify/assert" 16 ) 17 18 func TestMarshalTypeType(tt *testing.T) { 19 t := func(exp *types.Type, ptr interface{}) { 20 p := reflect.ValueOf(ptr) 21 assert.NotEqual(tt, reflect.Ptr, p.Type().Kind()) 22 actual, err := MarshalType(p.Interface()) 23 assert.NoError(tt, err) 24 assert.NotNil(tt, actual, "%#v", p.Interface()) 25 assert.True(tt, exp.Equals(actual)) 26 } 27 28 t(types.NumberType, float32(0)) 29 t(types.NumberType, float64(0)) 30 t(types.NumberType, int(0)) 31 t(types.NumberType, int16(0)) 32 t(types.NumberType, int32(0)) 33 t(types.NumberType, int64(0)) 34 t(types.NumberType, int8(0)) 35 t(types.NumberType, uint(0)) 36 t(types.NumberType, uint16(0)) 37 t(types.NumberType, uint32(0)) 38 t(types.NumberType, uint64(0)) 39 t(types.NumberType, uint8(0)) 40 41 t(types.BoolType, true) 42 t(types.StringType, "hi") 43 44 var l []int 45 t(types.MakeListType(types.NumberType), l) 46 47 var m map[uint32]string 48 t(types.MakeMapType(types.NumberType, types.StringType), m) 49 50 t(types.MakeListType(types.ValueType), types.List{}) 51 t(types.MakeSetType(types.ValueType), types.Set{}) 52 t(types.MakeMapType(types.ValueType, types.ValueType), types.Map{}) 53 t(types.MakeRefType(types.ValueType), types.Ref{}) 54 55 type TestStruct struct { 56 Str string 57 Num float64 58 } 59 var str TestStruct 60 t(types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 61 "str": types.StringType, 62 "num": types.NumberType, 63 }), str) 64 65 // Same again to test caching 66 t(types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 67 "str": types.StringType, 68 "num": types.NumberType, 69 }), str) 70 71 anonStruct := struct { 72 B bool 73 }{ 74 true, 75 } 76 t(types.MakeStructTypeFromFields("", types.FieldMap{ 77 "b": types.BoolType, 78 }), anonStruct) 79 80 type TestNestedStruct struct { 81 A []int16 82 B TestStruct 83 C float64 84 } 85 var nestedStruct TestNestedStruct 86 t(types.MakeStructTypeFromFields("TestNestedStruct", types.FieldMap{ 87 "a": types.MakeListType(types.NumberType), 88 "b": types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 89 "str": types.StringType, 90 "num": types.NumberType, 91 }), 92 "c": types.NumberType, 93 }), nestedStruct) 94 95 type testStruct struct { 96 Str string 97 Num float64 98 } 99 var ts testStruct 100 t(types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 101 "str": types.StringType, 102 "num": types.NumberType, 103 }), ts) 104 } 105 106 // 107 func assertMarshalTypeErrorMessage(t *testing.T, v interface{}, expectedMessage string) { 108 _, err := MarshalType(v) 109 assert.Error(t, err) 110 assert.Equal(t, expectedMessage, err.Error()) 111 } 112 113 func TestMarshalTypeInvalidTypes(t *testing.T) { 114 assertMarshalTypeErrorMessage(t, make(chan int), "Type is not supported, type: chan int") 115 } 116 117 func TestMarshalTypeEmbeddedStruct(t *testing.T) { 118 assert := assert.New(t) 119 120 type EmbeddedStruct struct { 121 B bool 122 } 123 type TestStruct struct { 124 EmbeddedStruct 125 A int 126 } 127 128 var s TestStruct 129 typ := MustMarshalType(s) 130 131 assert.True(types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 132 "a": types.NumberType, 133 "b": types.BoolType, 134 }).Equals(typ)) 135 } 136 137 func TestMarshalTypeEmbeddedStructSkip(t *testing.T) { 138 assert := assert.New(t) 139 140 type EmbeddedStruct struct { 141 B bool 142 } 143 type TestStruct struct { 144 EmbeddedStruct `noms:"-"` 145 A int 146 } 147 148 var s TestStruct 149 typ := MustMarshalType(s) 150 151 assert.True(types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 152 "a": types.NumberType, 153 }).Equals(typ)) 154 } 155 156 func TestMarshalTypeEmbeddedStructNamed(t *testing.T) { 157 assert := assert.New(t) 158 159 type EmbeddedStruct struct { 160 B bool 161 } 162 type TestStruct struct { 163 EmbeddedStruct `noms:"em"` 164 A int 165 } 166 167 var s TestStruct 168 typ := MustMarshalType(s) 169 170 assert.True(types.MakeStructTypeFromFields("TestStruct", types.FieldMap{ 171 "a": types.NumberType, 172 "em": types.MakeStructTypeFromFields("EmbeddedStruct", types.FieldMap{ 173 "b": types.BoolType, 174 }), 175 }).Equals(typ)) 176 } 177 178 func TestMarshalTypeEncodeNonExportedField(t *testing.T) { 179 type TestStruct struct { 180 x int 181 } 182 assertMarshalTypeErrorMessage(t, TestStruct{1}, "Non exported fields are not supported, type: marshal.TestStruct") 183 } 184 185 func TestMarshalTypeEncodeTaggingSkip(t *testing.T) { 186 assert := assert.New(t) 187 188 type S struct { 189 Abc int `noms:"-"` 190 Def bool 191 } 192 var s S 193 typ, err := MarshalType(s) 194 assert.NoError(err) 195 assert.True(types.MakeStructTypeFromFields("S", types.FieldMap{ 196 "def": types.BoolType, 197 }).Equals(typ)) 198 } 199 200 func TestMarshalTypeNamedFields(t *testing.T) { 201 assert := assert.New(t) 202 203 type S struct { 204 Aaa int `noms:"a"` 205 Bbb bool `noms:"B"` 206 Ccc string 207 } 208 var s S 209 typ, err := MarshalType(s) 210 assert.NoError(err) 211 assert.True(types.MakeStructTypeFromFields("S", types.FieldMap{ 212 "a": types.NumberType, 213 "B": types.BoolType, 214 "ccc": types.StringType, 215 }).Equals(typ)) 216 } 217 218 func TestMarshalTypeInvalidNamedFields(t *testing.T) { 219 type S struct { 220 A int `noms:"1a"` 221 } 222 var s S 223 assertMarshalTypeErrorMessage(t, s, "Invalid struct field name: 1a") 224 } 225 226 func TestMarshalTypeOmitEmpty(t *testing.T) { 227 assert := assert.New(t) 228 229 type S struct { 230 String string `noms:",omitempty"` 231 } 232 var s S 233 typ, err := MarshalType(s) 234 assert.NoError(err) 235 assert.True(types.MakeStructType("S", types.StructField{Name: "string", Type: types.StringType, Optional: true}).Equals(typ)) 236 } 237 238 func ExampleMarshalType() { 239 240 type Person struct { 241 Given string 242 Female bool 243 } 244 var person Person 245 personNomsType, err := MarshalType(person) 246 if err != nil { 247 fmt.Println(err) 248 return 249 } 250 251 fmt.Println(personNomsType.Describe()) 252 // Output: Struct Person { 253 // female: Bool, 254 // given: String, 255 // } 256 } 257 258 func TestMarshalTypeSlice(t *testing.T) { 259 assert := assert.New(t) 260 261 s := []string{"a", "b", "c"} 262 typ, err := MarshalType(s) 263 assert.NoError(err) 264 assert.True(types.MakeListType(types.StringType).Equals(typ)) 265 } 266 267 func TestMarshalTypeArray(t *testing.T) { 268 assert := assert.New(t) 269 270 a := [3]int{1, 2, 3} 271 typ, err := MarshalType(a) 272 assert.NoError(err) 273 assert.True(types.MakeListType(types.NumberType).Equals(typ)) 274 } 275 276 func TestMarshalTypeStructWithSlice(t *testing.T) { 277 assert := assert.New(t) 278 279 type S struct { 280 List []int 281 } 282 var s S 283 typ, err := MarshalType(s) 284 assert.NoError(err) 285 assert.True(types.MakeStructTypeFromFields("S", types.FieldMap{ 286 "list": types.MakeListType(types.NumberType), 287 }).Equals(typ)) 288 } 289 290 func TestMarshalTypeRecursive(t *testing.T) { 291 assert := assert.New(t) 292 293 type Node struct { 294 Value int 295 Children []Node 296 } 297 var n Node 298 typ, err := MarshalType(n) 299 assert.NoError(err) 300 301 typ2 := types.MakeStructType("Node", 302 types.StructField{ 303 Name: "children", 304 Type: types.MakeListType(types.MakeCycleType("Node")), 305 }, 306 types.StructField{ 307 Name: "value", 308 Type: types.NumberType, 309 }, 310 ) 311 assert.True(typ2.Equals(typ)) 312 } 313 314 func TestMarshalTypeMap(t *testing.T) { 315 assert := assert.New(t) 316 317 var m map[string]int 318 typ, err := MarshalType(m) 319 assert.NoError(err) 320 assert.True(types.MakeMapType(types.StringType, types.NumberType).Equals(typ)) 321 322 type S struct { 323 N string 324 } 325 326 var m2 map[S]bool 327 typ, err = MarshalType(m2) 328 assert.NoError(err) 329 assert.True(types.MakeMapType( 330 types.MakeStructTypeFromFields("S", types.FieldMap{ 331 "n": types.StringType, 332 }), 333 types.BoolType).Equals(typ)) 334 } 335 336 func TestMarshalTypeSet(t *testing.T) { 337 assert := assert.New(t) 338 339 type S struct { 340 A map[int]struct{} `noms:",set"` 341 B map[int]struct{} 342 C map[int]string `noms:",set"` 343 D map[string]struct{} `noms:",set"` 344 E map[string]struct{} 345 F map[string]int `noms:",set"` 346 G []int `noms:",set"` 347 H string `noms:",set"` 348 } 349 var s S 350 typ, err := MarshalType(s) 351 assert.NoError(err) 352 353 emptyStructType := types.MakeStructTypeFromFields("", types.FieldMap{}) 354 355 assert.True(types.MakeStructTypeFromFields("S", types.FieldMap{ 356 "a": types.MakeSetType(types.NumberType), 357 "b": types.MakeMapType(types.NumberType, emptyStructType), 358 "c": types.MakeMapType(types.NumberType, types.StringType), 359 "d": types.MakeSetType(types.StringType), 360 "e": types.MakeMapType(types.StringType, emptyStructType), 361 "f": types.MakeMapType(types.StringType, types.NumberType), 362 "g": types.MakeSetType(types.NumberType), 363 "h": types.StringType, 364 }).Equals(typ)) 365 } 366 367 func TestEncodeTypeOpt(t *testing.T) { 368 assert := assert.New(t) 369 370 tc := []struct { 371 in interface{} 372 opt Opt 373 wantType *types.Type 374 }{ 375 { 376 []string{}, 377 Opt{}, 378 types.MakeListType(types.StringType), 379 }, 380 { 381 []string{}, 382 Opt{Set: true}, 383 types.MakeSetType(types.StringType), 384 }, 385 { 386 map[string]struct{}{}, 387 Opt{}, 388 types.MakeMapType(types.StringType, types.MakeStructType("")), 389 }, 390 { 391 map[string]struct{}{}, 392 Opt{Set: true}, 393 types.MakeSetType(types.StringType), 394 }, 395 } 396 397 for _, t := range tc { 398 r, err := MarshalTypeOpt(t.in, t.opt) 399 assert.True(t.wantType.Equals(r)) 400 assert.Nil(err) 401 } 402 } 403 404 func TestMarshalTypeSetWithTags(t *testing.T) { 405 assert := assert.New(t) 406 407 type S struct { 408 A map[int]struct{} `noms:"foo,set"` 409 B map[int]struct{} `noms:",omitempty,set"` 410 C map[int]struct{} `noms:"bar,omitempty,set"` 411 } 412 413 var s S 414 typ, err := MarshalType(s) 415 assert.NoError(err) 416 assert.True(types.MakeStructType("S", 417 types.StructField{Name: "foo", Type: types.MakeSetType(types.NumberType), Optional: false}, 418 types.StructField{Name: "b", Type: types.MakeSetType(types.NumberType), Optional: true}, 419 types.StructField{Name: "bar", Type: types.MakeSetType(types.NumberType), Optional: true}, 420 ).Equals(typ)) 421 } 422 423 func TestMarshalTypeInvalidTag(t *testing.T) { 424 425 type S struct { 426 F string `noms:",omitEmpty"` 427 } 428 var s S 429 _, err := MarshalType(s) 430 assert.Error(t, err) 431 assert.Equal(t, `Unrecognized tag: omitEmpty`, err.Error()) 432 } 433 434 func TestMarshalTypeCanSkipUnexportedField(t *testing.T) { 435 assert := assert.New(t) 436 437 type S struct { 438 Abc int 439 notExported bool `noms:"-"` 440 } 441 var s S 442 typ, err := MarshalType(s) 443 assert.NoError(err) 444 assert.True(types.MakeStructTypeFromFields("S", types.FieldMap{ 445 "abc": types.NumberType, 446 }).Equals(typ)) 447 } 448 449 func TestMarshalTypeOriginal(t *testing.T) { 450 assert := assert.New(t) 451 452 type S struct { 453 Foo int `noms:",omitempty"` 454 Bar types.Struct `noms:",original"` 455 } 456 457 var s S 458 typ, err := MarshalType(s) 459 assert.NoError(err) 460 assert.True(types.MakeStructType("S", 461 types.StructField{Name: "foo", Type: types.NumberType, Optional: true}, 462 ).Equals(typ)) 463 } 464 465 func TestMarshalTypeNomsTypes(t *testing.T) { 466 assert := assert.New(t) 467 468 type S struct { 469 Blob types.Blob 470 Bool types.Bool 471 Number types.Number 472 String types.String 473 Type *types.Type 474 } 475 var s S 476 assert.True(MustMarshalType(s).Equals( 477 types.MakeStructTypeFromFields("S", types.FieldMap{ 478 "blob": types.BlobType, 479 "bool": types.BoolType, 480 "number": types.NumberType, 481 "string": types.StringType, 482 "type": types.TypeType, 483 }), 484 )) 485 } 486 487 func (t primitiveType) MarshalNomsType() (*types.Type, error) { 488 return types.NumberType, nil 489 } 490 491 func TestTypeMarshalerPrimitiveType(t *testing.T) { 492 assert := assert.New(t) 493 494 var u primitiveType 495 typ := MustMarshalType(u) 496 assert.Equal(types.NumberType, typ) 497 } 498 499 func (u primitiveSliceType) MarshalNomsType() (*types.Type, error) { 500 return types.StringType, nil 501 } 502 503 func TestTypeMarshalerPrimitiveSliceType(t *testing.T) { 504 assert := assert.New(t) 505 506 var u primitiveSliceType 507 typ := MustMarshalType(u) 508 assert.Equal(types.StringType, typ) 509 } 510 511 func (u primitiveMapType) MarshalNomsType() (*types.Type, error) { 512 return types.MakeSetType(types.StringType), nil 513 } 514 515 func TestTypeMarshalerPrimitiveMapType(t *testing.T) { 516 assert := assert.New(t) 517 518 var u primitiveMapType 519 typ := MustMarshalType(u) 520 assert.Equal(types.MakeSetType(types.StringType), typ) 521 } 522 523 func TestTypeMarshalerPrimitiveStructTypeNoMarshalNomsType(t *testing.T) { 524 assert := assert.New(t) 525 526 var u primitiveStructType 527 _, err := MarshalType(u) 528 assert.Error(err) 529 assert.Equal("Cannot marshal type which implements marshal.Marshaler, perhaps implement marshal.TypeMarshaler for marshal.primitiveStructType", err.Error()) 530 } 531 532 func (u builtinType) MarshalNomsType() (*types.Type, error) { 533 return types.StringType, nil 534 } 535 536 func TestTypeMarshalerBuiltinType(t *testing.T) { 537 assert := assert.New(t) 538 539 var u builtinType 540 typ := MustMarshalType(u) 541 assert.Equal(types.StringType, typ) 542 } 543 544 func (u wrappedMarshalerType) MarshalNomsType() (*types.Type, error) { 545 return types.NumberType, nil 546 } 547 548 func TestTypeMarshalerWrapperMarshalerType(t *testing.T) { 549 assert := assert.New(t) 550 551 var u wrappedMarshalerType 552 typ := MustMarshalType(u) 553 assert.Equal(types.NumberType, typ) 554 } 555 556 func (u returnsMarshalerError) MarshalNomsType() (*types.Type, error) { 557 return nil, errors.New("expected error") 558 } 559 560 func (u returnsMarshalerNil) MarshalNomsType() (*types.Type, error) { 561 return nil, nil 562 } 563 564 func (u panicsMarshaler) MarshalNomsType() (*types.Type, error) { 565 panic("panic") 566 } 567 568 func TestTypeMarshalerErrors(t *testing.T) { 569 assert := assert.New(t) 570 571 expErr := errors.New("expected error") 572 var m1 returnsMarshalerError 573 _, actErr := MarshalType(m1) 574 assert.Equal(expErr, actErr) 575 576 var m2 returnsMarshalerNil 577 assert.Panics(func() { MarshalType(m2) }) 578 579 var m3 panicsMarshaler 580 assert.Panics(func() { MarshalType(m3) }) 581 } 582 583 func TestMarshalTypeStructName(t *testing.T) { 584 assert := assert.New(t) 585 586 var ts TestStructWithNameImpl 587 typ := MustMarshalType(ts) 588 assert.True(types.MakeStructType("A", types.StructField{Name: "x", Type: types.NumberType, Optional: false}).Equals(typ), typ.Describe()) 589 } 590 591 func TestMarshalTypeStructName2(t *testing.T) { 592 assert := assert.New(t) 593 594 var ts TestStructWithNameImpl2 595 typ := MustMarshalType(ts) 596 assert.True(types.MakeStructType("", types.StructField{Name: "x", Type: types.NumberType, Optional: false}).Equals(typ), typ.Describe()) 597 } 598 599 type OutPhoto struct { 600 Faces []OutFace `noms:",set"` 601 SomeOtherFacesSet []OutFace `noms:",set"` 602 } 603 604 type OutFace struct { 605 Blob types.Ref 606 } 607 608 func (f OutFace) MarshalNomsStructName() string { 609 return "Face" 610 } 611 612 func TestMarshalTypeOutface(t *testing.T) { 613 614 typ := MustMarshalType(OutPhoto{}) 615 expectedType := nomdl.MustParseType(`Struct OutPhoto { 616 faces: Set<Struct Face { 617 blob: Ref<Value>, 618 }>, 619 someOtherFacesSet: Set<Cycle<Face>>, 620 }`) 621 assert.True(t, typ.Equals(expectedType)) 622 }