github.com/niubaoshu/goutils@v0.0.0-20180828035119-e8e576f66c2b/deepclone_test.go (about) 1 package goutils 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 "time" 8 "unsafe" 9 ) 10 11 // just basic is this working stuff 12 func TestSimple(t *testing.T) { 13 Strings := []string{"a", "b", "c"} 14 cpyS := DeepClone(Strings).([]string) 15 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyS)).Data { 16 t.Error("[]string: expected SliceHeader data pointers to point to different locations, they didn't") 17 goto CopyBools 18 } 19 if len(cpyS) != len(Strings) { 20 t.Errorf("[]string: len was %d; want %d", len(cpyS), len(Strings)) 21 goto CopyBools 22 } 23 for i, v := range Strings { 24 if v != cpyS[i] { 25 t.Errorf("[]string: got %v at index %d of the copy; want %v", cpyS[i], i, v) 26 } 27 } 28 29 CopyBools: 30 Bools := []bool{true, true, false, false} 31 cpyB := DeepClone(Bools).([]bool) 32 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyB)).Data { 33 t.Error("[]bool: expected SliceHeader data pointers to point to different locations, they didn't") 34 goto CopyBytes 35 } 36 if len(cpyB) != len(Bools) { 37 t.Errorf("[]bool: len was %d; want %d", len(cpyB), len(Bools)) 38 goto CopyBytes 39 } 40 for i, v := range Bools { 41 if v != cpyB[i] { 42 t.Errorf("[]bool: got %v at index %d of the copy; want %v", cpyB[i], i, v) 43 } 44 } 45 46 CopyBytes: 47 Bytes := []byte("hello") 48 cpyBt := DeepClone(Bytes).([]byte) 49 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyBt)).Data { 50 t.Error("[]byte: expected SliceHeader data pointers to point to different locations, they didn't") 51 goto CopyInts 52 } 53 if len(cpyBt) != len(Bytes) { 54 t.Errorf("[]byte: len was %d; want %d", len(cpyBt), len(Bytes)) 55 goto CopyInts 56 } 57 for i, v := range Bytes { 58 if v != cpyBt[i] { 59 t.Errorf("[]byte: got %v at index %d of the copy; want %v", cpyBt[i], i, v) 60 } 61 } 62 63 CopyInts: 64 Ints := []int{42} 65 cpyI := DeepClone(Ints).([]int) 66 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyI)).Data { 67 t.Error("[]int: expected SliceHeader data pointers to point to different locations, they didn't") 68 goto CopyUints 69 } 70 if len(cpyI) != len(Ints) { 71 t.Errorf("[]int: len was %d; want %d", len(cpyI), len(Ints)) 72 goto CopyUints 73 } 74 for i, v := range Ints { 75 if v != cpyI[i] { 76 t.Errorf("[]int: got %v at index %d of the copy; want %v", cpyI[i], i, v) 77 } 78 } 79 80 CopyUints: 81 Uints := []uint{1, 2, 3, 4, 5} 82 cpyU := DeepClone(Uints).([]uint) 83 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyU)).Data { 84 t.Error("[]: expected SliceHeader data pointers to point to different locations, they didn't") 85 goto CopyFloat32s 86 } 87 if len(cpyU) != len(Uints) { 88 t.Errorf("[]uint: len was %d; want %d", len(cpyU), len(Uints)) 89 goto CopyFloat32s 90 } 91 for i, v := range Uints { 92 if v != cpyU[i] { 93 t.Errorf("[]uint: got %v at index %d of the copy; want %v", cpyU[i], i, v) 94 } 95 } 96 97 CopyFloat32s: 98 Float32s := []float32{3.14} 99 cpyF := DeepClone(Float32s).([]float32) 100 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyF)).Data { 101 t.Error("[]float32: expected SliceHeader data pointers to point to different locations, they didn't") 102 goto CopyInterfaces 103 } 104 if len(cpyF) != len(Float32s) { 105 t.Errorf("[]float32: len was %d; want %d", len(cpyF), len(Float32s)) 106 goto CopyInterfaces 107 } 108 for i, v := range Float32s { 109 if v != cpyF[i] { 110 t.Errorf("[]float32: got %v at index %d of the copy; want %v", cpyF[i], i, v) 111 } 112 } 113 114 CopyInterfaces: 115 Interfaces := []interface{}{"a", 42, true, 4.32} 116 cpyIf := DeepClone(Interfaces).([]interface{}) 117 if (*reflect.SliceHeader)(unsafe.Pointer(&Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyIf)).Data { 118 t.Error("[]interfaces: expected SliceHeader data pointers to point to different locations, they didn't") 119 return 120 } 121 if len(cpyIf) != len(Interfaces) { 122 t.Errorf("[]interface{}: len was %d; want %d", len(cpyIf), len(Interfaces)) 123 return 124 } 125 for i, v := range Interfaces { 126 if v != cpyIf[i] { 127 t.Errorf("[]interface{}: got %v at index %d of the copy; want %v", cpyIf[i], i, v) 128 } 129 } 130 } 131 132 type Basics struct { 133 String string 134 Strings []string 135 StringArr [4]string 136 Bool bool 137 Bools []bool 138 Byte byte 139 Bytes []byte 140 Int int 141 Ints []int 142 Int8 int8 143 Int8s []int8 144 Int16 int16 145 Int16s []int16 146 Int32 int32 147 Int32s []int32 148 Int64 int64 149 Int64s []int64 150 Uint uint 151 Uints []uint 152 Uint8 uint8 153 Uint8s []uint8 154 Uint16 uint16 155 Uint16s []uint16 156 Uint32 uint32 157 Uint32s []uint32 158 Uint64 uint64 159 Uint64s []uint64 160 Float32 float32 161 Float32s []float32 162 Float64 float64 163 Float64s []float64 164 Complex64 complex64 165 Complex64s []complex64 166 Complex128 complex128 167 Complex128s []complex128 168 Interface interface{} 169 Interfaces []interface{} 170 } 171 172 // These tests test that all supported basic types are copied correctly. This 173 // is done by copying a struct with fields of most of the basic types as []T. 174 func TestMostTypes(t *testing.T) { 175 test := Basics{ 176 String: "kimchi", 177 Strings: []string{"uni", "ika"}, 178 StringArr: [4]string{"malort", "barenjager", "fernet", "salmiakki"}, 179 Bool: true, 180 Bools: []bool{true, false, true}, 181 Byte: 'z', 182 Bytes: []byte("abc"), 183 Int: 42, 184 Ints: []int{0, 1, 3, 4}, 185 Int8: 8, 186 Int8s: []int8{8, 9, 10}, 187 Int16: 16, 188 Int16s: []int16{16, 17, 18, 19}, 189 Int32: 32, 190 Int32s: []int32{32, 33}, 191 Int64: 64, 192 Int64s: []int64{64}, 193 Uint: 420, 194 Uints: []uint{11, 12, 13}, 195 Uint8: 81, 196 Uint8s: []uint8{81, 82}, 197 Uint16: 160, 198 Uint16s: []uint16{160, 161, 162, 163, 164}, 199 Uint32: 320, 200 Uint32s: []uint32{320, 321}, 201 Uint64: 640, 202 Uint64s: []uint64{6400, 6401, 6402, 6403}, 203 Float32: 32.32, 204 Float32s: []float32{32.32, 33}, 205 Float64: 64.1, 206 Float64s: []float64{64, 65, 66}, 207 Complex64: complex64(-64 + 12i), 208 Complex64s: []complex64{complex64(-65 + 11i), complex64(66 + 10i)}, 209 Complex128: complex128(-128 + 12i), 210 Complex128s: []complex128{complex128(-128 + 11i), complex128(129 + 10i)}, 211 Interfaces: []interface{}{42, true, "pan-galactic"}, 212 } 213 214 cpy := DeepClone(test).(Basics) 215 216 // see if they point to the same location 217 if fmt.Sprintf("%p", &cpy) == fmt.Sprintf("%p", &test) { 218 t.Error("address of copy was the same as original; they should be different") 219 return 220 } 221 222 // Go through each field and check to see it got copied properly 223 if cpy.String != test.String { 224 t.Errorf("String: got %v; want %v", cpy.String, test.String) 225 } 226 227 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Strings)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Strings)).Data { 228 t.Error("Strings: address of copy was the same as original; they should be different") 229 goto StringArr 230 } 231 232 if len(cpy.Strings) != len(test.Strings) { 233 t.Errorf("Strings: len was %d; want %d", len(cpy.Strings), len(test.Strings)) 234 goto StringArr 235 } 236 for i, v := range test.Strings { 237 if v != cpy.Strings[i] { 238 t.Errorf("Strings: got %v at index %d of the copy; want %v", cpy.Strings[i], i, v) 239 } 240 } 241 242 StringArr: 243 if unsafe.Pointer(&test.StringArr) == unsafe.Pointer(&cpy.StringArr) { 244 t.Error("StringArr: address of copy was the same as original; they should be different") 245 goto Bools 246 } 247 for i, v := range test.StringArr { 248 if v != cpy.StringArr[i] { 249 t.Errorf("StringArr: got %v at index %d of the copy; want %v", cpy.StringArr[i], i, v) 250 } 251 } 252 253 Bools: 254 if cpy.Bool != test.Bool { 255 t.Errorf("Bool: got %v; want %v", cpy.Bool, test.Bool) 256 } 257 258 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Bools)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Bools)).Data { 259 t.Error("Bools: address of copy was the same as original; they should be different") 260 goto Bytes 261 } 262 if len(cpy.Bools) != len(test.Bools) { 263 t.Errorf("Bools: len was %d; want %d", len(cpy.Bools), len(test.Bools)) 264 goto Bytes 265 } 266 for i, v := range test.Bools { 267 if v != cpy.Bools[i] { 268 t.Errorf("Bools: got %v at index %d of the copy; want %v", cpy.Bools[i], i, v) 269 } 270 } 271 272 Bytes: 273 if cpy.Byte != test.Byte { 274 t.Errorf("Byte: got %v; want %v", cpy.Byte, test.Byte) 275 } 276 277 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Bytes)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Bytes)).Data { 278 t.Error("Bytes: address of copy was the same as original; they should be different") 279 goto Ints 280 } 281 if len(cpy.Bytes) != len(test.Bytes) { 282 t.Errorf("Bytes: len was %d; want %d", len(cpy.Bytes), len(test.Bytes)) 283 goto Ints 284 } 285 for i, v := range test.Bytes { 286 if v != cpy.Bytes[i] { 287 t.Errorf("Bytes: got %v at index %d of the copy; want %v", cpy.Bytes[i], i, v) 288 } 289 } 290 291 Ints: 292 if cpy.Int != test.Int { 293 t.Errorf("Int: got %v; want %v", cpy.Int, test.Int) 294 } 295 296 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Ints)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Ints)).Data { 297 t.Error("Ints: address of copy was the same as original; they should be different") 298 goto Int8s 299 } 300 if len(cpy.Ints) != len(test.Ints) { 301 t.Errorf("Ints: len was %d; want %d", len(cpy.Ints), len(test.Ints)) 302 goto Int8s 303 } 304 for i, v := range test.Ints { 305 if v != cpy.Ints[i] { 306 t.Errorf("Ints: got %v at index %d of the copy; want %v", cpy.Ints[i], i, v) 307 } 308 } 309 310 Int8s: 311 if cpy.Int8 != test.Int8 { 312 t.Errorf("Int8: got %v; want %v", cpy.Int8, test.Int8) 313 } 314 315 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Int8s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Int8s)).Data { 316 t.Error("Int8s: address of copy was the same as original; they should be different") 317 goto Int16s 318 } 319 if len(cpy.Int8s) != len(test.Int8s) { 320 t.Errorf("Int8s: len was %d; want %d", len(cpy.Int8s), len(test.Int8s)) 321 goto Int16s 322 } 323 for i, v := range test.Int8s { 324 if v != cpy.Int8s[i] { 325 t.Errorf("Int8s: got %v at index %d of the copy; want %v", cpy.Int8s[i], i, v) 326 } 327 } 328 329 Int16s: 330 if cpy.Int16 != test.Int16 { 331 t.Errorf("Int16: got %v; want %v", cpy.Int16, test.Int16) 332 } 333 334 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Int16s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Int16s)).Data { 335 t.Error("Int16s: address of copy was the same as original; they should be different") 336 goto Int32s 337 } 338 if len(cpy.Int16s) != len(test.Int16s) { 339 t.Errorf("Int16s: len was %d; want %d", len(cpy.Int16s), len(test.Int16s)) 340 goto Int32s 341 } 342 for i, v := range test.Int16s { 343 if v != cpy.Int16s[i] { 344 t.Errorf("Int16s: got %v at index %d of the copy; want %v", cpy.Int16s[i], i, v) 345 } 346 } 347 348 Int32s: 349 if cpy.Int32 != test.Int32 { 350 t.Errorf("Int32: got %v; want %v", cpy.Int32, test.Int32) 351 } 352 353 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Int32s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Int32s)).Data { 354 t.Error("Int32s: address of copy was the same as original; they should be different") 355 goto Int64s 356 } 357 if len(cpy.Int32s) != len(test.Int32s) { 358 t.Errorf("Int32s: len was %d; want %d", len(cpy.Int32s), len(test.Int32s)) 359 goto Int64s 360 } 361 for i, v := range test.Int32s { 362 if v != cpy.Int32s[i] { 363 t.Errorf("Int32s: got %v at index %d of the copy; want %v", cpy.Int32s[i], i, v) 364 } 365 } 366 367 Int64s: 368 if cpy.Int64 != test.Int64 { 369 t.Errorf("Int64: got %v; want %v", cpy.Int64, test.Int64) 370 } 371 372 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Int64s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Int64s)).Data { 373 t.Error("Int64s: address of copy was the same as original; they should be different") 374 goto Uints 375 } 376 if len(cpy.Int64s) != len(test.Int64s) { 377 t.Errorf("Int64s: len was %d; want %d", len(cpy.Int64s), len(test.Int64s)) 378 goto Uints 379 } 380 for i, v := range test.Int64s { 381 if v != cpy.Int64s[i] { 382 t.Errorf("Int64s: got %v at index %d of the copy; want %v", cpy.Int64s[i], i, v) 383 } 384 } 385 386 Uints: 387 if cpy.Uint != test.Uint { 388 t.Errorf("Uint: got %v; want %v", cpy.Uint, test.Uint) 389 } 390 391 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Uints)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Uints)).Data { 392 t.Error("Uints: address of copy was the same as original; they should be different") 393 goto Uint8s 394 } 395 if len(cpy.Uints) != len(test.Uints) { 396 t.Errorf("Uints: len was %d; want %d", len(cpy.Uints), len(test.Uints)) 397 goto Uint8s 398 } 399 for i, v := range test.Uints { 400 if v != cpy.Uints[i] { 401 t.Errorf("Uints: got %v at index %d of the copy; want %v", cpy.Uints[i], i, v) 402 } 403 } 404 405 Uint8s: 406 if cpy.Uint8 != test.Uint8 { 407 t.Errorf("Uint8: got %v; want %v", cpy.Uint8, test.Uint8) 408 } 409 410 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Uint8s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Uint8s)).Data { 411 t.Error("Uint8s: address of copy was the same as original; they should be different") 412 goto Uint16s 413 } 414 if len(cpy.Uint8s) != len(test.Uint8s) { 415 t.Errorf("Uint8s: len was %d; want %d", len(cpy.Uint8s), len(test.Uint8s)) 416 goto Uint16s 417 } 418 for i, v := range test.Uint8s { 419 if v != cpy.Uint8s[i] { 420 t.Errorf("Uint8s: got %v at index %d of the copy; want %v", cpy.Uint8s[i], i, v) 421 } 422 } 423 424 Uint16s: 425 if cpy.Uint16 != test.Uint16 { 426 t.Errorf("Uint16: got %v; want %v", cpy.Uint16, test.Uint16) 427 } 428 429 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Uint16s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Uint16s)).Data { 430 t.Error("Uint16s: address of copy was the same as original; they should be different") 431 goto Uint32s 432 } 433 if len(cpy.Uint16s) != len(test.Uint16s) { 434 t.Errorf("Uint16s: len was %d; want %d", len(cpy.Uint16s), len(test.Uint16s)) 435 goto Uint32s 436 } 437 for i, v := range test.Uint16s { 438 if v != cpy.Uint16s[i] { 439 t.Errorf("Uint16s: got %v at index %d of the copy; want %v", cpy.Uint16s[i], i, v) 440 } 441 } 442 443 Uint32s: 444 if cpy.Uint32 != test.Uint32 { 445 t.Errorf("Uint32: got %v; want %v", cpy.Uint32, test.Uint32) 446 } 447 448 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Uint32s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Uint32s)).Data { 449 t.Error("Uint32s: address of copy was the same as original; they should be different") 450 goto Uint64s 451 } 452 if len(cpy.Uint32s) != len(test.Uint32s) { 453 t.Errorf("Uint32s: len was %d; want %d", len(cpy.Uint32s), len(test.Uint32s)) 454 goto Uint64s 455 } 456 for i, v := range test.Uint32s { 457 if v != cpy.Uint32s[i] { 458 t.Errorf("Uint32s: got %v at index %d of the copy; want %v", cpy.Uint32s[i], i, v) 459 } 460 } 461 462 Uint64s: 463 if cpy.Uint64 != test.Uint64 { 464 t.Errorf("Uint64: got %v; want %v", cpy.Uint64, test.Uint64) 465 } 466 467 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Uint64s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Uint64s)).Data { 468 t.Error("Uint64s: address of copy was the same as original; they should be different") 469 goto Float32s 470 } 471 if len(cpy.Uint64s) != len(test.Uint64s) { 472 t.Errorf("Uint64s: len was %d; want %d", len(cpy.Uint64s), len(test.Uint64s)) 473 goto Float32s 474 } 475 for i, v := range test.Uint64s { 476 if v != cpy.Uint64s[i] { 477 t.Errorf("Uint64s: got %v at index %d of the copy; want %v", cpy.Uint64s[i], i, v) 478 } 479 } 480 481 Float32s: 482 if cpy.Float32 != test.Float32 { 483 t.Errorf("Float32: got %v; want %v", cpy.Float32, test.Float32) 484 } 485 486 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Float32s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Float32s)).Data { 487 t.Error("Float32s: address of copy was the same as original; they should be different") 488 goto Float64s 489 } 490 if len(cpy.Float32s) != len(test.Float32s) { 491 t.Errorf("Float32s: len was %d; want %d", len(cpy.Float32s), len(test.Float32s)) 492 goto Float64s 493 } 494 for i, v := range test.Float32s { 495 if v != cpy.Float32s[i] { 496 t.Errorf("Float32s: got %v at index %d of the copy; want %v", cpy.Float32s[i], i, v) 497 } 498 } 499 500 Float64s: 501 if cpy.Float64 != test.Float64 { 502 t.Errorf("Float64: got %v; want %v", cpy.Float64, test.Float64) 503 } 504 505 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Float64s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Float64s)).Data { 506 t.Error("Float64s: address of copy was the same as original; they should be different") 507 goto Complex64s 508 } 509 if len(cpy.Float64s) != len(test.Float64s) { 510 t.Errorf("Float64s: len was %d; want %d", len(cpy.Float64s), len(test.Float64s)) 511 goto Complex64s 512 } 513 for i, v := range test.Float64s { 514 if v != cpy.Float64s[i] { 515 t.Errorf("Float64s: got %v at index %d of the copy; want %v", cpy.Float64s[i], i, v) 516 } 517 } 518 519 Complex64s: 520 if cpy.Complex64 != test.Complex64 { 521 t.Errorf("Complex64: got %v; want %v", cpy.Complex64, test.Complex64) 522 } 523 524 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Complex64s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Complex64s)).Data { 525 t.Error("Complex64s: address of copy was the same as original; they should be different") 526 goto Complex128s 527 } 528 if len(cpy.Complex64s) != len(test.Complex64s) { 529 t.Errorf("Complex64s: len was %d; want %d", len(cpy.Complex64s), len(test.Complex64s)) 530 goto Complex128s 531 } 532 for i, v := range test.Complex64s { 533 if v != cpy.Complex64s[i] { 534 t.Errorf("Complex64s: got %v at index %d of the copy; want %v", cpy.Complex64s[i], i, v) 535 } 536 } 537 538 Complex128s: 539 if cpy.Complex128 != test.Complex128 { 540 t.Errorf("Complex128s: got %v; want %v", cpy.Complex128s, test.Complex128s) 541 } 542 543 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Complex128s)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Complex128s)).Data { 544 t.Error("Complex128s: address of copy was the same as original; they should be different") 545 goto Interfaces 546 } 547 if len(cpy.Complex128s) != len(test.Complex128s) { 548 t.Errorf("Complex128s: len was %d; want %d", len(cpy.Complex128s), len(test.Complex128s)) 549 goto Interfaces 550 } 551 for i, v := range test.Complex128s { 552 if v != cpy.Complex128s[i] { 553 t.Errorf("Complex128s: got %v at index %d of the copy; want %v", cpy.Complex128s[i], i, v) 554 } 555 } 556 557 Interfaces: 558 if cpy.Interface != test.Interface { 559 t.Errorf("Interface: got %v; want %v", cpy.Interface, test.Interface) 560 } 561 562 if (*reflect.SliceHeader)(unsafe.Pointer(&test.Interfaces)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.Interfaces)).Data { 563 t.Error("Interfaces: address of copy was the same as original; they should be different") 564 return 565 } 566 if len(cpy.Interfaces) != len(test.Interfaces) { 567 t.Errorf("Interfaces: len was %d; want %d", len(cpy.Interfaces), len(test.Interfaces)) 568 return 569 } 570 for i, v := range test.Interfaces { 571 if v != cpy.Interfaces[i] { 572 t.Errorf("Interfaces: got %v at index %d of the copy; want %v", cpy.Interfaces[i], i, v) 573 } 574 } 575 } 576 577 // not meant to be exhaustive 578 func TestComplexSlices(t *testing.T) { 579 orig3Int := [][][]int{[][]int{[]int{1, 2, 3}, []int{11, 22, 33}}, [][]int{[]int{7, 8, 9}, []int{66, 77, 88, 99}}} 580 cpyI := DeepClone(orig3Int).([][][]int) 581 if (*reflect.SliceHeader)(unsafe.Pointer(&orig3Int)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyI)).Data { 582 t.Error("[][][]int: address of copy was the same as original; they should be different") 583 return 584 } 585 if len(orig3Int) != len(cpyI) { 586 t.Errorf("[][][]int: len of copy was %d; want %d", len(cpyI), len(orig3Int)) 587 goto sliceMap 588 } 589 for i, v := range orig3Int { 590 if len(v) != len(cpyI[i]) { 591 t.Errorf("[][][]int: len of element %d was %d; want %d", i, len(cpyI[i]), len(v)) 592 continue 593 } 594 for j, vv := range v { 595 if len(vv) != len(cpyI[i][j]) { 596 t.Errorf("[][][]int: len of element %d:%d was %d, want %d", i, j, len(cpyI[i][j]), len(vv)) 597 continue 598 } 599 for k, vvv := range vv { 600 if vvv != cpyI[i][j][k] { 601 t.Errorf("[][][]int: element %d:%d:%d was %d, want %d", i, j, k, cpyI[i][j][k], vvv) 602 } 603 } 604 } 605 606 } 607 608 sliceMap: 609 slMap := []map[int]string{map[int]string{0: "a", 1: "b"}, map[int]string{10: "k", 11: "l", 12: "m"}} 610 cpyM := DeepClone(slMap).([]map[int]string) 611 if (*reflect.SliceHeader)(unsafe.Pointer(&slMap)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpyM)).Data { 612 t.Error("[]map[int]string: address of copy was the same as original; they should be different") 613 } 614 if len(slMap) != len(cpyM) { 615 t.Errorf("[]map[int]string: len of copy was %d; want %d", len(cpyM), len(slMap)) 616 goto done 617 } 618 for i, v := range slMap { 619 if len(v) != len(cpyM[i]) { 620 t.Errorf("[]map[int]string: len of element %d was %d; want %d", i, len(cpyM[i]), len(v)) 621 continue 622 } 623 for k, vv := range v { 624 val, ok := cpyM[i][k] 625 if !ok { 626 t.Errorf("[]map[int]string: element %d was expected to have a value at key %d, it didn't", i, k) 627 continue 628 } 629 if val != vv { 630 t.Errorf("[]map[int]string: element %d, key %d: got %s, want %s", i, k, val, vv) 631 } 632 } 633 } 634 done: 635 } 636 637 type A struct { 638 Int int 639 String string 640 UintSl []uint 641 NilSl []string 642 Map map[string]int 643 MapB map[string]*B 644 SliceB []B 645 B 646 T time.Time 647 } 648 649 type B struct { 650 Vals []string 651 } 652 653 var AStruct = A{ 654 Int: 42, 655 String: "Konichiwa", 656 UintSl: []uint{0, 1, 2, 3}, 657 Map: map[string]int{"a": 1, "b": 2}, 658 MapB: map[string]*B{ 659 "hi": &B{Vals: []string{"hello", "bonjour"}}, 660 "bye": &B{Vals: []string{"good-bye", "au revoir"}}, 661 }, 662 SliceB: []B{ 663 B{Vals: []string{"Ciao", "Aloha"}}, 664 }, 665 B: B{Vals: []string{"42"}}, 666 T: time.Now(), 667 } 668 669 func TestStructA(t *testing.T) { 670 cpy := DeepClone(AStruct).(A) 671 if &cpy == &AStruct { 672 t.Error("expected copy to have a different address than the original; it was the same") 673 return 674 } 675 if cpy.Int != AStruct.Int { 676 t.Errorf("A.Int: got %v, want %v", cpy.Int, AStruct.Int) 677 } 678 if cpy.String != AStruct.String { 679 t.Errorf("A.String: got %v; want %v", cpy.String, AStruct.String) 680 } 681 if (*reflect.SliceHeader)(unsafe.Pointer(&cpy.UintSl)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&AStruct.UintSl)).Data { 682 t.Error("A.Uintsl: expected the copies address to be different; it wasn't") 683 goto NilSl 684 } 685 if len(cpy.UintSl) != len(AStruct.UintSl) { 686 t.Errorf("A.UintSl: got len of %d, want %d", len(cpy.UintSl), len(AStruct.UintSl)) 687 goto NilSl 688 } 689 for i, v := range AStruct.UintSl { 690 if cpy.UintSl[i] != v { 691 t.Errorf("A.UintSl %d: got %d, want %d", i, cpy.UintSl[i], v) 692 } 693 } 694 695 NilSl: 696 if cpy.NilSl != nil { 697 t.Error("A.NilSl: expected slice to be nil, it wasn't") 698 } 699 700 if *(*uintptr)(unsafe.Pointer(&cpy.Map)) == *(*uintptr)(unsafe.Pointer(&AStruct.Map)) { 701 t.Error("A.Map: expected the copy's address to be different; it wasn't") 702 goto AMapB 703 } 704 if len(cpy.Map) != len(AStruct.Map) { 705 t.Errorf("A.Map: got len of %d, want %d", len(cpy.Map), len(AStruct.Map)) 706 goto AMapB 707 } 708 for k, v := range AStruct.Map { 709 val, ok := cpy.Map[k] 710 if !ok { 711 t.Errorf("A.Map: expected the key %s to exist in the copy, it didn't", k) 712 continue 713 } 714 if val != v { 715 t.Errorf("A.Map[%s]: got %d, want %d", k, val, v) 716 } 717 } 718 719 AMapB: 720 if *(*uintptr)(unsafe.Pointer(&cpy.MapB)) == *(*uintptr)(unsafe.Pointer(&AStruct.MapB)) { 721 t.Error("A.MapB: expected the copy's address to be different; it wasn't") 722 goto ASliceB 723 } 724 if len(cpy.MapB) != len(AStruct.MapB) { 725 t.Errorf("A.MapB: got len of %d, want %d", len(cpy.MapB), len(AStruct.MapB)) 726 goto ASliceB 727 } 728 for k, v := range AStruct.MapB { 729 val, ok := cpy.MapB[k] 730 if !ok { 731 t.Errorf("A.MapB: expected the key %s to exist in the copy, it didn't", k) 732 continue 733 } 734 if unsafe.Pointer(val) == unsafe.Pointer(v) { 735 t.Errorf("A.MapB[%s]: expected the addresses of the values to be different; they weren't", k) 736 continue 737 } 738 // the slice headers should point to different data 739 if (*reflect.SliceHeader)(unsafe.Pointer(&v.Vals)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&val.Vals)).Data { 740 t.Errorf("%s: expected B's SliceHeaders to point to different Data locations; they did not.", k) 741 continue 742 } 743 for i, vv := range v.Vals { 744 if vv != val.Vals[i] { 745 t.Errorf("A.MapB[%s].Vals[%d]: got %s want %s", k, i, vv, val.Vals[i]) 746 } 747 } 748 } 749 750 ASliceB: 751 if (*reflect.SliceHeader)(unsafe.Pointer(&AStruct.SliceB)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.SliceB)).Data { 752 t.Error("A.SliceB: expected the copy's address to be different; it wasn't") 753 goto B 754 } 755 756 if len(AStruct.SliceB) != len(cpy.SliceB) { 757 t.Errorf("A.SliceB: got length of %d; want %d", len(cpy.SliceB), len(AStruct.SliceB)) 758 goto B 759 } 760 761 for i := range AStruct.SliceB { 762 if unsafe.Pointer(&AStruct.SliceB[i]) == unsafe.Pointer(&cpy.SliceB[i]) { 763 t.Errorf("A.SliceB[%d]: expected them to have different addresses, they didn't", i) 764 continue 765 } 766 if (*reflect.SliceHeader)(unsafe.Pointer(&AStruct.SliceB[i].Vals)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.SliceB[i].Vals)).Data { 767 t.Errorf("A.SliceB[%d]: expected B.Vals SliceHeader.Data to point to different locations; they did not", i) 768 continue 769 } 770 if len(AStruct.SliceB[i].Vals) != len(cpy.SliceB[i].Vals) { 771 t.Errorf("A.SliceB[%d]: expected B's vals to have the same length, they didn't", i) 772 continue 773 } 774 for j, val := range AStruct.SliceB[i].Vals { 775 if val != cpy.SliceB[i].Vals[j] { 776 t.Errorf("A.SliceB[%d].Vals[%d]: got %v; want %v", i, j, cpy.SliceB[i].Vals[j], val) 777 } 778 } 779 } 780 B: 781 if unsafe.Pointer(&AStruct.B) == unsafe.Pointer(&cpy.B) { 782 t.Error("A.B: expected them to have different addresses, they didn't") 783 goto T 784 } 785 if (*reflect.SliceHeader)(unsafe.Pointer(&AStruct.B.Vals)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&cpy.B.Vals)).Data { 786 t.Error("A.B.Vals: expected the SliceHeaders.Data to point to different locations; they didn't") 787 goto T 788 } 789 if len(AStruct.B.Vals) != len(cpy.B.Vals) { 790 t.Error("A.B.Vals: expected their lengths to be the same, they weren't") 791 goto T 792 } 793 for i, v := range AStruct.B.Vals { 794 if v != cpy.B.Vals[i] { 795 t.Errorf("A.B.Vals[%d]: got %s want %s", i, cpy.B.Vals[i], v) 796 } 797 } 798 T: 799 if fmt.Sprintf("%p", &AStruct.T) == fmt.Sprintf("%p", &cpy.T) { 800 t.Error("A.T: expected them to have different addresses, they didn't") 801 return 802 } 803 if !AStruct.T.Equal(cpy.T) { 804 t.Errorf("A.T: got %v, want %v", cpy.T, AStruct.T) 805 } 806 } 807 808 type Unexported struct { 809 A string 810 B int 811 aa string 812 bb int 813 } 814 815 func TestUnexportedFields(t *testing.T) { 816 u := &Unexported{ 817 A: "A", 818 B: 42, 819 aa: "aa", 820 bb: 42, 821 } 822 cpy := DeepClone(u).(*Unexported) 823 if cpy == u { 824 t.Error("expected addresses to be different, they weren't") 825 return 826 } 827 if u.A != cpy.A { 828 t.Errorf("Unexported.A: got %s want %s", cpy.A, u.A) 829 } 830 if u.B != cpy.B { 831 t.Errorf("Unexported.A: got %d want %d", cpy.B, u.B) 832 } 833 if cpy.aa != u.aa { 834 t.Errorf("Unexported.aa: got %s want %s ", cpy.aa, u.aa) 835 } 836 if cpy.bb != u.bb { 837 t.Errorf("Unexported.bb: got %d want %d", cpy.bb, u.bb) 838 } 839 } 840 841 // Note: this test will fail until https://github.com/golang/go/issues/15716 is 842 // fixed and the version it is part of gets released. 843 type T struct { 844 time.Time 845 } 846 847 func TestTimeDeepClone(t *testing.T) { 848 tests := []struct { 849 Y int 850 M time.Month 851 D int 852 h int 853 m int 854 s int 855 nsec int 856 TZ string 857 }{ 858 {2016, time.July, 4, 23, 11, 33, 3000, "America/New_York"}, 859 {2015, time.October, 31, 9, 44, 23, 45935, "UTC"}, 860 {2014, time.May, 5, 22, 01, 50, 219300, "Europe/Prague"}, 861 } 862 863 for i, test := range tests { 864 l, err := time.LoadLocation(test.TZ) 865 if err != nil { 866 t.Errorf("%d: unexpected error: %s", i, err) 867 continue 868 } 869 var x T 870 x.Time = time.Date(test.Y, test.M, test.D, test.h, test.m, test.s, test.nsec, l) 871 c := DeepClone(x).(T) 872 873 if !x.Time.Equal(c.Time) { 874 t.Errorf("%d: time: got %v; want %v", i, &c, &x) 875 continue 876 } 877 878 if fmt.Sprintf("%p", &c) == fmt.Sprintf("%p", &x) { 879 t.Errorf("%d: expected the copy to have a different address than the original value; they were the same: %p %p", i, &c, &x) 880 continue 881 } 882 if x.UnixNano() != c.UnixNano() { 883 t.Errorf("%d: nanotime: got %v; want %v", i, c.UnixNano(), x.UnixNano()) 884 continue 885 } 886 if x.Location().String() != c.Location().String() { 887 t.Errorf("%d: location: got %q; want %q", i, c.Location(), x.Location()) 888 } 889 } 890 } 891 892 func TestPointerToStruct(t *testing.T) { 893 type Foo struct { 894 Bar int 895 } 896 897 f := &Foo{Bar: 42} 898 cpy := DeepClone(f) 899 if f == cpy { 900 t.Errorf("expected copy to point to a different location: orig: %p; copy: %p", f, cpy) 901 } 902 if !reflect.DeepEqual(f, cpy) { 903 t.Errorf("expected the copy to be equal to the original (except for memory location); it wasn't: got %#v; want %#v", f, cpy) 904 } 905 } 906 907 func TestIssue9(t *testing.T) { 908 // simple pointer copy 909 x := 42 910 testA := map[string]*int{ 911 "a": nil, 912 "b": &x, 913 } 914 copyA := DeepClone(testA).(map[string]*int) 915 if unsafe.Pointer(&testA) == unsafe.Pointer(©A) { 916 t.Fatalf("expected the map pointers to be different: testA: %v\tcopyA: %v", unsafe.Pointer(&testA), unsafe.Pointer(©A)) 917 } 918 if !reflect.DeepEqual(testA, copyA) { 919 t.Errorf("got %#v; want %#v", copyA, testA) 920 } 921 if testA["b"] == copyA["b"] { 922 t.Errorf("entries for 'b' pointed to the same address: %v; expected them to point to different addresses", testA["b"]) 923 } 924 925 // map copy 926 type Foo struct { 927 Alpha string 928 } 929 930 type Bar struct { 931 Beta string 932 Gamma int 933 Delta *Foo 934 } 935 936 type Biz struct { 937 Epsilon map[int]*Bar 938 } 939 940 testB := Biz{ 941 Epsilon: map[int]*Bar{ 942 0: &Bar{}, 943 1: &Bar{ 944 Beta: "don't panic", 945 Gamma: 42, 946 Delta: nil, 947 }, 948 2: &Bar{ 949 Beta: "sudo make me a sandwich.", 950 Gamma: 11, 951 Delta: &Foo{ 952 Alpha: "okay.", 953 }, 954 }, 955 }, 956 } 957 958 copyB := DeepClone(testB).(Biz) 959 if !reflect.DeepEqual(testB, copyB) { 960 t.Errorf("got %#v; want %#v", copyB, testB) 961 return 962 } 963 964 // check that the maps point to different locations 965 if unsafe.Pointer(&testB.Epsilon) == unsafe.Pointer(©B.Epsilon) { 966 t.Fatalf("expected the map pointers to be different; they weren't: testB: %v\tcopyB: %v", unsafe.Pointer(&testB.Epsilon), unsafe.Pointer(©B.Epsilon)) 967 } 968 969 for k, v := range testB.Epsilon { 970 if v == nil && copyB.Epsilon[k] == nil { 971 continue 972 } 973 if v == nil && copyB.Epsilon[k] != nil { 974 t.Errorf("%d: expected copy of a nil entry to be nil; it wasn't: %#v", copyB.Epsilon[k]) 975 continue 976 } 977 if v == copyB.Epsilon[k] { 978 t.Errorf("entries for '%d' pointed to the same address: %v; expected them to point to different addresses", v) 979 continue 980 } 981 if v.Beta != copyB.Epsilon[k].Beta { 982 t.Errorf("%d.Beta: got %q; want %q", copyB.Epsilon[k].Beta, v.Beta) 983 } 984 if v.Gamma != copyB.Epsilon[k].Gamma { 985 t.Errorf("%d.Gamma: got %d; want %d", copyB.Epsilon[k].Gamma, v.Gamma) 986 } 987 if v.Delta == nil && copyB.Epsilon[k].Delta == nil { 988 continue 989 } 990 if v.Delta == nil && copyB.Epsilon[k].Delta != nil { 991 t.Errorf("%d.Delta: got %#v; want nil", copyB.Epsilon[k].Delta) 992 } 993 if v.Delta == copyB.Epsilon[k].Delta { 994 t.Errorf("%d.Delta: expected the pointers to be different, they were the same: %v", k, v.Delta) 995 continue 996 } 997 if v.Delta.Alpha != copyB.Epsilon[k].Delta.Alpha { 998 t.Errorf("%d.Delta.Foo: got %q; want %q", v.Delta.Alpha, copyB.Epsilon[k].Delta.Alpha) 999 } 1000 } 1001 1002 // test that map keys are deep copied 1003 testC := map[*Foo][]string{ 1004 &Foo{Alpha: "Henry Dorsett Case"}: []string{ 1005 "Cutter", 1006 }, 1007 &Foo{Alpha: "Molly Millions"}: []string{ 1008 "Rose Kolodny", 1009 "Cat Mother", 1010 "Steppin' Razor", 1011 }, 1012 } 1013 1014 copyC := DeepClone(testC).(map[*Foo][]string) 1015 if unsafe.Pointer(&testC) == unsafe.Pointer(©C) { 1016 t.Fatalf("expected the map pointers to be different; they weren't: testB: %v\tcopyB: %v", unsafe.Pointer(&testB.Epsilon), unsafe.Pointer(©B.Epsilon)) 1017 } 1018 1019 // make sure the lengths are the same 1020 if len(testC) != len(copyC) { 1021 t.Fatalf("got len %d; want %d", len(copyC), len(testC)) 1022 } 1023 1024 // check that everything was deep copied: since the key is a pointer, we check to 1025 // see if the pointers are different but the values being pointed to are the same. 1026 for k, v := range testC { 1027 for kk, vv := range copyC { 1028 if *kk == *k { 1029 if kk == k { 1030 t.Errorf("key pointers should be different: orig: %p; copy: %p", k, kk) 1031 } 1032 // check that the slices are the same but different 1033 if !reflect.DeepEqual(v, vv) { 1034 t.Errorf("expected slice contents to be the same; they weren't: orig: %v; copy: %v", v, vv) 1035 } 1036 1037 if (*reflect.SliceHeader)(unsafe.Pointer(&v)).Data == (*reflect.SliceHeader)(unsafe.Pointer(&vv)).Data { 1038 t.Error("expected the SliceHeaders.Data to point to different locations; they didn't: %v", (*reflect.SliceHeader)(unsafe.Pointer(&v)).Data) 1039 } 1040 break 1041 } 1042 } 1043 } 1044 1045 type Bizz struct { 1046 *Foo 1047 } 1048 1049 testD := map[Bizz]string{ 1050 Bizz{&Foo{"Neuromancer"}}: "Rio", 1051 Bizz{&Foo{"Wintermute"}}: "Berne", 1052 } 1053 copyD := DeepClone(testD).(map[Bizz]string) 1054 if len(copyD) != len(testD) { 1055 t.Fatalf("copy had %d elements; expected %d", len(copyD), len(testD)) 1056 } 1057 1058 for k, v := range testD { 1059 var found bool 1060 for kk, vv := range copyD { 1061 if reflect.DeepEqual(k, kk) { 1062 found = true 1063 // check that Foo points to different locations 1064 if unsafe.Pointer(k.Foo) == unsafe.Pointer(kk.Foo) { 1065 t.Errorf("Expected Foo to point to different locations; they didn't: orig: %p; copy %p", k.Foo, kk.Foo) 1066 break 1067 } 1068 if *k.Foo != *kk.Foo { 1069 t.Errorf("Expected copy of the key's Foo field to have the same value as the original, it wasn't: orig: %#v; copy: %#v", k.Foo, kk.Foo) 1070 } 1071 if v != vv { 1072 t.Errorf("Expected the values to be the same; the weren't: got %v; want %v", vv, v) 1073 } 1074 } 1075 } 1076 if !found { 1077 t.Errorf("expected key %v to exist in the copy; it didn't", k) 1078 } 1079 } 1080 }