gopkg.in/rethinkdb/rethinkdb-go.v6@v6.2.2/encoding/encoder_test.go (about) 1 package encoding 2 3 import ( 4 "errors" 5 "image" 6 "reflect" 7 "testing" 8 "time" 9 ) 10 11 var encodeExpected = map[string]interface{}{ 12 "Level0": int64(1), 13 "Level1b": int64(2), 14 "Level1c": int64(3), 15 "Level1a": int64(5), 16 "LEVEL1B": int64(6), 17 "e": map[string]interface{}{ 18 "Level1a": int64(8), 19 "Level1b": int64(9), 20 "Level1c": int64(10), 21 "Level1d": int64(11), 22 "x": int64(12), 23 }, 24 "Loop1": int64(13), 25 "Loop2": int64(14), 26 "X": int64(15), 27 "Y": int64(16), 28 "Z": int64(17), 29 } 30 31 func TestEncode(t *testing.T) { 32 // Top is defined in decoder_test.go 33 var in = Top{ 34 Level0: 1, 35 Embed0: Embed0{ 36 Level1b: 2, 37 Level1c: 3, 38 }, 39 Embed0a: &Embed0a{ 40 Level1a: 5, 41 Level1b: 6, 42 }, 43 Embed0b: &Embed0b{ 44 Level1a: 8, 45 Level1b: 9, 46 Level1c: 10, 47 Level1d: 11, 48 Level1e: 12, 49 }, 50 Loop: Loop{ 51 Loop1: 13, 52 Loop2: 14, 53 }, 54 Embed0p: Embed0p{ 55 Point: image.Point{X: 15, Y: 16}, 56 }, 57 Embed0q: Embed0q{ 58 Point: Point{Z: 17}, 59 }, 60 } 61 62 got, err := Encode(&in) 63 if err != nil { 64 t.Fatal(err) 65 } 66 if !reflect.DeepEqual(got, encodeExpected) { 67 t.Errorf(" got: %v\nwant: %v\n", got, encodeExpected) 68 } 69 } 70 71 type Optionals struct { 72 Sr string `rethinkdb:"sr"` 73 So string `rethinkdb:"so,omitempty"` 74 Sw string `rethinkdb:"-"` 75 76 Ir int `rethinkdb:"omitempty"` // actually named omitempty, not an option 77 Io int `rethinkdb:"io,omitempty"` 78 79 Tr time.Time `rethinkdb:"tr"` 80 To time.Time `rethinkdb:"to,omitempty"` 81 82 Slr []string `rethinkdb:"slr"` 83 Slo []string `rethinkdb:"slo,omitempty"` 84 85 Mr map[string]interface{} `rethinkdb:"mr"` 86 Mo map[string]interface{} `rethinkdb:",omitempty"` 87 } 88 89 var optionalsExpected = map[string]interface{}{ 90 "sr": "", 91 "omitempty": int64(0), 92 "tr": map[string]interface{}{"$reql_type$": "TIME", "epoch_time": 0, "timezone": "+00:00"}, 93 "slr": []interface{}(nil), 94 "mr": map[string]interface{}{}, 95 } 96 97 func TestOmitEmpty(t *testing.T) { 98 var o Optionals 99 o.Sw = "something" 100 o.Tr = time.Unix(0, 0).In(time.UTC) 101 o.Mr = map[string]interface{}{} 102 o.Mo = map[string]interface{}{} 103 104 got, err := Encode(&o) 105 if err != nil { 106 t.Fatal(err) 107 } 108 if !jsonEqual(got, optionalsExpected) { 109 t.Errorf("\ngot: %#v\nwant: %#v\n", got, optionalsExpected) 110 } 111 } 112 113 type IntType int 114 115 type MyStruct struct { 116 IntType 117 } 118 119 func TestAnonymousNonstruct(t *testing.T) { 120 var i IntType = 11 121 a := MyStruct{i} 122 var want = map[string]interface{}{"IntType": int64(11)} 123 124 got, err := Encode(a) 125 if err != nil { 126 t.Fatalf("Encode: %v", err) 127 } 128 if !reflect.DeepEqual(got, want) { 129 t.Errorf("got %v, want %v", got, want) 130 } 131 } 132 133 func TestEncodePointer(t *testing.T) { 134 v := Pointer{PPoint: &Point{Z: 1}, Point: Point{Z: 2}} 135 var want = map[string]interface{}{ 136 "PPoint": map[string]interface{}{"Z": int64(1)}, 137 "Point": map[string]interface{}{"Z": int64(2)}, 138 } 139 140 got, err := Encode(v) 141 if err != nil { 142 t.Fatalf("Encode: %v", err) 143 } 144 if !reflect.DeepEqual(got, want) { 145 t.Errorf("got %v, want %v", got, want) 146 } 147 } 148 149 func TestEncodeNilPointer(t *testing.T) { 150 v := Pointer{PPoint: nil, Point: Point{Z: 2}} 151 var want = map[string]interface{}{ 152 "PPoint": nil, 153 "Point": map[string]interface{}{"Z": int64(2)}, 154 } 155 156 got, err := Encode(v) 157 if err != nil { 158 t.Fatalf("Encode: %v", err) 159 } 160 if !reflect.DeepEqual(got, want) { 161 t.Errorf("got %v, want %v", got, want) 162 } 163 } 164 165 type BugA struct { 166 S string 167 } 168 169 type BugB struct { 170 BugA 171 S string 172 } 173 174 type BugC struct { 175 S string 176 } 177 178 // Legal Go: We never use the repeated embedded field (S). 179 type BugX struct { 180 A int 181 BugA 182 BugB 183 } 184 185 // Issue 5245. 186 func TestEmbeddedBug(t *testing.T) { 187 v := BugB{ 188 BugA{"A"}, 189 "B", 190 } 191 got, err := Encode(v) 192 if err != nil { 193 t.Fatal("Encode:", err) 194 } 195 want := map[string]interface{}{"S": "B"} 196 if !reflect.DeepEqual(got, want) { 197 t.Fatalf("Encode: got %v want %v", got, want) 198 } 199 // Now check that the duplicate field, S, does not appear. 200 x := BugX{ 201 A: 23, 202 } 203 got, err = Encode(x) 204 if err != nil { 205 t.Fatal("Encode:", err) 206 } 207 want = map[string]interface{}{"A": int64(23)} 208 if !reflect.DeepEqual(got, want) { 209 t.Fatalf("Encode: got %v want %v", got, want) 210 } 211 } 212 213 type BugD struct { // Same as BugA after tagging. 214 XXX string `rethinkdb:"S"` 215 } 216 217 // BugD's tagged S field should dominate BugA's. 218 type BugY struct { 219 BugA 220 BugD 221 } 222 223 // Test that a field with a tag dominates untagged fields. 224 func TestTaggedFieldDominates(t *testing.T) { 225 v := BugY{ 226 BugA{"BugA"}, 227 BugD{"BugD"}, 228 } 229 got, err := Encode(v) 230 if err != nil { 231 t.Fatal("Encode:", err) 232 } 233 want := map[string]interface{}{"S": "BugD"} 234 if !reflect.DeepEqual(got, want) { 235 t.Fatalf("Encode: got %v want %v", got, want) 236 } 237 } 238 239 // There are no tags here, so S should not appear. 240 type BugZ struct { 241 BugA 242 BugC 243 BugY // Contains a tagged S field through BugD; should not dominate. 244 } 245 246 func TestDuplicatedFieldDisappears(t *testing.T) { 247 v := BugZ{ 248 BugA{"BugA"}, 249 BugC{"BugC"}, 250 BugY{ 251 BugA{"nested BugA"}, 252 BugD{"nested BugD"}, 253 }, 254 } 255 got, err := Encode(v) 256 if err != nil { 257 t.Fatal("Encode:", err) 258 } 259 want := map[string]interface{}{} 260 if !reflect.DeepEqual(got, want) { 261 t.Fatalf("Encode: got %v want %v", got, want) 262 } 263 } 264 265 func TestEncodeMapIntKeys(t *testing.T) { 266 input := map[int]int{1: 1, 2: 2, 3: 3} 267 want := map[string]int{"1": 1, "2": 2, "3": 3} 268 269 out, err := Encode(input) 270 if err != nil { 271 t.Errorf("got error %v, expected nil", err) 272 } 273 if !jsonEqual(out, want) { 274 t.Errorf("got %q, want %q", out, want) 275 } 276 } 277 278 type RefA struct { 279 ID string `rethinkdb:"id,omitempty"` 280 B *RefB `rethinkdb:"b_id,reference" rethinkdb_ref:"id"` 281 } 282 283 type RefB struct { 284 ID string `rethinkdb:"id,omitempty"` 285 Name string `rethinkdb:"name"` 286 } 287 288 func TestReferenceField(t *testing.T) { 289 input := RefA{"1", &RefB{"2", "Name"}} 290 want := map[string]interface{}{"id": "1", "b_id": "2"} 291 292 out, err := Encode(input) 293 if err != nil { 294 t.Errorf("got error %v, expected nil", err) 295 } 296 if !jsonEqual(out, want) { 297 t.Errorf("got %q, want %q", out, want) 298 } 299 } 300 301 type RefC struct { 302 ID string `rethinkdb:"id,omitempty"` 303 B *RefB `rethinkdb:"b_id,reference" rethinkdb_ref:"b_id"` 304 } 305 306 func TestReferenceFieldMissing(t *testing.T) { 307 input := RefC{"1", &RefB{"2", "Name"}} 308 309 _, err := Encode(input) 310 if err == nil { 311 t.Errorf("expected non-nil error but got nil") 312 } 313 } 314 315 type RefD struct { 316 ID string `rethinkdb:"id,omitempty"` 317 B string `rethinkdb:"b_id,reference" rethinkdb_ref:"b_id"` 318 } 319 320 func TestReferenceFieldInvalid(t *testing.T) { 321 input := RefD{"1", "B"} 322 323 _, err := Encode(input) 324 if err == nil { 325 t.Errorf("expected non-nil error but got nil") 326 } 327 } 328 329 type RefE struct { 330 ID string `rethinkdb:"id,omitempty"` 331 FIDs *[]RefF `rethinkdb:"f_ids,reference" rethinkdb_ref:"id"` 332 } 333 334 type RefF struct { 335 ID string `rethinkdb:"id,omitempty"` 336 Name string `rethinkdb:"name"` 337 } 338 339 func TestReferenceFieldArray(t *testing.T) { 340 input := RefE{"1", &[]RefF{RefF{"2", "Name2"}, RefF{"3", "Name3"}}} 341 want := map[string]interface{}{"id": "1", "f_ids": []string{"2", "3"}} 342 343 out, err := Encode(input) 344 if err != nil { 345 t.Errorf("got error %v, expected nil", err) 346 } 347 if !jsonEqual(out, want) { 348 t.Errorf("got %q, want %q", out, want) 349 } 350 } 351 352 func TestEncodeBytes(t *testing.T) { 353 type BytesStruct struct { 354 A []byte 355 B [1]byte 356 } 357 358 input := BytesStruct{[]byte("A"), [1]byte{'B'}} 359 want := map[string]interface{}{ 360 "A": map[string]interface{}{"$reql_type$": "BINARY", "data": "QQ=="}, 361 "B": map[string]interface{}{"$reql_type$": "BINARY", "data": "Qg=="}, 362 } 363 364 out, err := Encode(input) 365 if err != nil { 366 t.Errorf("got error %v, expected nil", err) 367 } 368 if !jsonEqual(out, want) { 369 t.Errorf("got %q, want %q", out, want) 370 } 371 } 372 373 type Compound struct { 374 PartA string `rethinkdb:"id[0]"` 375 PartB string `rethinkdb:"id[1]"` 376 ErrA string `rethinkdb:"err_a[]"` 377 ErrB string `rethinkdb:"err_b["` 378 ErrC string `rethinkdb:"err_c]"` 379 } 380 381 func TestEncodeCompound(t *testing.T) { 382 input := Compound{"1", "2", "3", "4", "5"} 383 want := map[string]interface{}{"id": []string{"1", "2"}, "err_a[]": "3", "err_b[": "4", "err_c]": "5"} 384 385 out, err := Encode(input) 386 if err != nil { 387 t.Errorf("got error %v, expected nil", err) 388 } 389 if !jsonEqual(out, want) { 390 t.Errorf("got %q, want %q", out, want) 391 } 392 } 393 394 type CompoundRef struct { 395 PartA string `rethinkdb:"id[0]"` 396 PartB *RefB `rethinkdb:"id[1],reference" rethinkdb_ref:"id"` 397 } 398 399 func TestEncodeCompoundRef(t *testing.T) { 400 input := CompoundRef{"1", &RefB{"2", "Name"}} 401 want := map[string]interface{}{"id": []string{"1", "2"}} 402 403 out, err := Encode(input) 404 if err != nil { 405 t.Errorf("got error %v, expected nil", err) 406 } 407 if !jsonEqual(out, want) { 408 t.Errorf("got %q, want %q", out, want) 409 } 410 } 411 412 func TestEncodeNilSlice(t *testing.T) { 413 input := SliceStruct{} 414 want := map[string]interface{}{"X": []string(nil)} 415 416 out, err := Encode(input) 417 if err != nil { 418 t.Errorf("got error %v, expected nil", err) 419 } 420 if !jsonEqual(out, want) { 421 t.Errorf("got %q, want %q", out, want) 422 } 423 } 424 425 func TestEncodeCustomTypeEncodingValue(t *testing.T) { 426 type innerType struct { 427 Val int 428 } 429 430 outer := struct { 431 Inner innerType `rethinkdb:"inner"` 432 }{Inner: innerType{Val: 5}} 433 want := map[string]interface{}{ 434 "inner": map[string]interface{}{ 435 "someval": 5, 436 }, 437 } 438 439 SetTypeEncoding(reflect.TypeOf(innerType{}), 440 func(v interface{}) (interface{}, error) { 441 return map[string]interface{}{"someval": v.(innerType).Val}, nil 442 }, nil) 443 444 out, err := Encode(outer) 445 if err != nil { 446 t.Errorf("got error %v, expected nil", err) 447 } 448 if !jsonEqual(out, want) { 449 t.Errorf("got %q, want %q", out, want) 450 } 451 } 452 453 func TestEncodeCustomTypeEncodingPointer(t *testing.T) { 454 type innerType struct { 455 Val int 456 } 457 458 outer := struct { 459 Inner *innerType `rethinkdb:"inner"` 460 }{Inner: &innerType{Val: 5}} 461 want := map[string]interface{}{ 462 "inner": map[string]interface{}{ 463 "someval": 5, 464 }, 465 } 466 467 SetTypeEncoding(reflect.TypeOf((*innerType)(nil)), 468 func(v interface{}) (interface{}, error) { 469 return map[string]interface{}{"someval": v.(*innerType).Val}, nil 470 }, nil) 471 472 out, err := Encode(outer) 473 if err != nil { 474 t.Errorf("got error %v, expected nil", err) 475 } 476 if !jsonEqual(out, want) { 477 t.Errorf("got %q, want %q", out, want) 478 } 479 } 480 481 func TestEncodeCustomRootTypeEncodingValue(t *testing.T) { 482 type cType struct { 483 Val int 484 } 485 in := cType{Val: 5} 486 487 want := map[string]interface{}{ 488 "someval": 5, 489 } 490 491 SetTypeEncoding(reflect.TypeOf(cType{}), 492 func(v interface{}) (interface{}, error) { 493 return map[string]interface{}{"someval": v.(cType).Val}, nil 494 }, nil) 495 496 out, err := Encode(in) 497 if err != nil { 498 t.Errorf("got error %v, expected nil", err) 499 } 500 if !jsonEqual(out, want) { 501 t.Errorf("got %q, want %q", out, want) 502 } 503 } 504 505 func TestEncodeCustomRootTypeEncodingPointer(t *testing.T) { 506 type cType struct { 507 Val int 508 } 509 in := cType{Val: 5} 510 511 want := map[string]interface{}{ 512 "someval": 5, 513 } 514 515 SetTypeEncoding(reflect.TypeOf((*cType)(nil)), 516 func(v interface{}) (interface{}, error) { 517 return map[string]interface{}{"someval": v.(*cType).Val}, nil 518 }, nil) 519 520 out, err := Encode(&in) 521 if err != nil { 522 t.Errorf("got error %v, expected nil", err) 523 } 524 if !jsonEqual(out, want) { 525 t.Errorf("got %q, want %q", out, want) 526 } 527 } 528 529 func TestEncodeCustomRootTypeEncodingError(t *testing.T) { 530 type cType struct { 531 Val int 532 } 533 in := cType{Val: 5} 534 535 cerr := errors.New("encode error") 536 537 SetTypeEncoding(reflect.TypeOf((*cType)(nil)), 538 func(v interface{}) (interface{}, error) { 539 return nil, cerr 540 }, nil) 541 542 _, err := Encode(&in) 543 if err == nil { 544 t.Errorf("got nil error, expected %v", cerr) 545 } 546 if err != cerr { 547 t.Errorf("got %q, want %q", err, cerr) 548 } 549 }