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