github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/bas/object_test.go (about) 1 package bas 2 3 import ( 4 "bytes" 5 "encoding/base64" 6 "fmt" 7 "math" 8 "math/rand" 9 "runtime" 10 "runtime/debug" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/coyove/nj/internal" 16 "github.com/coyove/nj/typ" 17 ) 18 19 func randString() string { 20 buf := make([]byte, 6) 21 rand.Read(buf) 22 return base64.StdEncoding.EncodeToString(buf) 23 } 24 25 func randInt(len, idx int) int { 26 buf := make([]byte, 6) 27 rand.Read(buf) 28 v := rand.Int() 29 if Int(v).HashCode()%uint32(len) == uint32(idx) { 30 return v 31 } 32 return randInt(len, idx) 33 } 34 35 func TestMapForeachDelete(t *testing.T) { 36 rand.Seed(time.Now().Unix()) 37 check := func(o *Map, idx int, k int, dist int32) { 38 i := o.items[idx] 39 if i.key.Int() != k || i.dist != dist { 40 t.Fatal(o.items, string(debug.Stack())) 41 } 42 } 43 44 o := newMap(1) 45 o.noresize = true 46 a := randInt(2, 1) 47 b := randInt(2, 1) 48 c := randInt(2, 1) 49 o.Set(Int(a), Int(a)) // [null, a+0] 50 o.Set(Int(b), Int(b)) // [b+1, a+0] 51 o.Delete(Int(a)) // [b+1, deleted+0] 52 if o.items[0].dist != 1 || !o.items[1].pDeleted { 53 t.Fatal(o.items) 54 } 55 o.Set(Int(a), Int(a)) // [a+1, b+0] 56 check(o, 0, a, 1) 57 check(o, 1, b, 0) 58 59 o.Delete(Int(a)) // [deleted+1, b+0] 60 o.Set(Int(c), Int(c)) // [c+1, b+0] 61 check(o, 0, c, 1) 62 check(o, 1, b, 0) 63 64 o = newMap(2) 65 o.noresize = true 66 a = randInt(4, 1) 67 b = randInt(4, 1) 68 c = randInt(4, 1) 69 d := randInt(4, 1) 70 o.Set(Int(a), Int(a)) 71 o.Set(Int(b), Int(b)) 72 o.Set(Int(c), Int(c)) 73 o.Set(Int(d), Int(d)) // [d+3, a+0, b+1, c+2] 74 check(o, 0, d, 3) 75 check(o, 1, a, 0) 76 check(o, 2, b, 1) 77 check(o, 3, c, 2) 78 79 o.Delete(Int(b)) // [d+3, a+0, deleted+1, c+2] 80 o.Set(Int(b), Int(b)) // [b+3, a+0, c+1, d+2] 81 check(o, 0, b, 3) 82 check(o, 1, a, 0) 83 check(o, 2, c, 1) 84 check(o, 3, d, 2) 85 86 o.Delete(Int(a)) 87 o.Delete(Int(c)) // [b+3, deleted+0, deleted+1, d+2] 88 loopCount := 0 89 o.Foreach(func(k Value, v *Value) bool { loopCount++; return true }) 90 if loopCount != 2 { 91 t.Fatal(loopCount, o.items) 92 } 93 for k, _ := o.FindNext(Nil); k != Nil; k, _ = o.FindNext(k) { 94 loopCount-- 95 } 96 if loopCount != 0 { 97 t.Fatal(o.items) 98 } 99 a = randInt(4, 2) 100 o.Set(Int(a), Int(a)) // [a+2, deleted+0, d+1, b+2] 101 check(o, 0, a, 2) 102 check(o, 2, d, 1) 103 check(o, 3, b, 2) 104 105 if x, _ := o.Get(Int(a)); x.Int() != a { 106 t.Fatal(o.items) 107 } 108 109 o = newMap(4) 110 o.noresize = true 111 a = randInt(8, 1) 112 b = randInt(8, 1) 113 c = randInt(8, 1) 114 d = randInt(8, 2) 115 e := randInt(8, 4) 116 o.Set(Int(a), Int(a)) 117 o.Set(Int(b), Int(b)) 118 o.Set(Int(c), Int(c)) 119 o.Set(Int(d), Int(d)) 120 o.Set(Int(e), Int(e)) // [nil, a+0, b+1, c+2, d+2, e+1, nil, nil] 121 check(o, 1, a, 0) 122 check(o, 2, b, 1) 123 check(o, 3, c, 2) 124 check(o, 4, d, 2) 125 check(o, 5, e, 1) 126 127 o.Delete(Int(b)) 128 o.Delete(Int(d)) // [nil, a+0, deleted+1, c+2, deleted+2, e+1, nil, nil] 129 if x, _ := o.Get(Int(b)); x != Nil { 130 t.Fatal(o.items) 131 } 132 if x, _ := o.Get(Int(c)); x != Int(c) { 133 t.Fatal(o.items) 134 } 135 o.Set(Int(d), Int(d)) // [nil, a+0, c+1, d+1, e+0, nil, nil, nil] 136 check(o, 1, a, 0) 137 check(o, 2, c, 1) 138 check(o, 3, d, 1) 139 check(o, 4, e, 0) 140 141 o.Delete(Int(e)) 142 o.Set(Int(e), Int(e)) 143 check(o, 1, a, 0) 144 check(o, 2, c, 1) 145 check(o, 3, d, 1) 146 check(o, 4, e, 0) 147 } 148 149 func BenchmarkRHMap10(b *testing.B) { benchmarkRHMap(b, 10) } 150 func BenchmarkGoMap10(b *testing.B) { benchmarkGoMap(b, 10) } 151 func BenchmarkRHMap20(b *testing.B) { benchmarkRHMap(b, 20) } 152 func BenchmarkGoMap20(b *testing.B) { benchmarkGoMap(b, 20) } 153 func BenchmarkRHMap50(b *testing.B) { benchmarkRHMap(b, 50) } 154 func BenchmarkGoMap50(b *testing.B) { benchmarkGoMap(b, 50) } 155 func BenchmarkRHMap5000(b *testing.B) { benchmarkRHMap(b, 5000) } 156 func BenchmarkGoMap5000(b *testing.B) { benchmarkGoMap(b, 5000) } 157 func BenchmarkRHMapUnc10(b *testing.B) { benchmarkRHMapUnconstrainted(b, 10) } 158 func BenchmarkGoMapUnc10(b *testing.B) { benchmarkGoMapUnconstrainted(b, 10) } 159 func BenchmarkRHMapUnc1000(b *testing.B) { benchmarkRHMapUnconstrainted(b, 1000) } 160 func BenchmarkGoMapUnc1000(b *testing.B) { benchmarkGoMapUnconstrainted(b, 1000) } 161 162 func benchmarkRHMap(b *testing.B, n int) { 163 rand.Seed(time.Now().Unix()) 164 m := newMap(n) 165 for i := 0; i < n; i++ { 166 m.Set(Int64(int64(i)), Int64(int64(i))) 167 } 168 for i := 0; i < b.N; i++ { 169 idx := rand.Intn(n) 170 if x, _ := m.Get(Int64(int64(idx))); x != Int64(int64(idx)) { 171 b.Fatal(idx, m) 172 } 173 } 174 } 175 176 func benchmarkRHMapUnconstrainted(b *testing.B, n int) { 177 rand.Seed(time.Now().Unix()) 178 m := newMap(1) 179 for i := 0; i < b.N; i++ { 180 for i := 0; i < n; i++ { 181 x := rand.Intn(n) 182 m.Set(Int64(int64(x)), Int64(int64(i))) 183 } 184 } 185 } 186 187 func benchmarkGoMap(b *testing.B, n int) { 188 rand.Seed(time.Now().Unix()) 189 m := map[int]int{} 190 for i := 0; i < n; i++ { 191 m[i] = i 192 } 193 for i := 0; i < b.N; i++ { 194 idx := rand.Intn(n) 195 if m[idx] == -1 { 196 b.Fatal(idx, m) 197 } 198 } 199 } 200 201 func benchmarkGoMapUnconstrainted(b *testing.B, n int) { 202 rand.Seed(time.Now().Unix()) 203 m := map[int]int{} 204 for i := 0; i < b.N; i++ { 205 for i := 0; i < n; i++ { 206 idx := rand.Intn(n) 207 m[idx] = i 208 } 209 } 210 } 211 212 func TestRHMap(t *testing.T) { 213 rand.Seed(time.Now().Unix()) 214 m := newMap(0) 215 m2 := map[int64]int64{} 216 counter := int64(0) 217 for i := 0; i < 1e6; i++ { 218 x := rand.Int63() 219 if x%2 == 0 { 220 x = counter 221 counter++ 222 } 223 m.Set(Int64(x), Int64(x)) 224 m2[x] = x 225 } 226 for k := range m2 { 227 delete(m2, k) 228 m.Delete(Int64(k)) 229 if rand.Intn(10000) == 0 { 230 break 231 } 232 } 233 234 fmt.Println(m.Len(), m.Cap(), len(m2)) 235 236 for k, v := range m2 { 237 if x, _ := m.Get(Int64(k)); x.Int64() != v { 238 m.Foreach(func(mk Value, mv *Value) bool { 239 if mk.Int64() == k { 240 t.Log(mk, *mv) 241 } 242 return true 243 }) 244 t.Fatal(x, k, v) 245 } 246 } 247 248 if m.Len() != len(m2) { 249 t.Fatal(m.Len(), len(m2)) 250 } 251 252 for k, v := m.FindNext(Nil); k != Nil; k, v = m.FindNext(k) { 253 if _, ok := m2[k.Int64()]; !ok { 254 t.Fatal(k, v, len(m2)) 255 } 256 delete(m2, k.Int64()) 257 } 258 if len(m2) != 0 { 259 t.Fatal(len(m2)) 260 } 261 262 m.Clear() 263 m.Set(Int64(0), Int64(0)) 264 m.Set(Int64(1), Int64(1)) 265 m.Set(Int64(2), Int64(2)) 266 267 for i := 4; i < 9; i++ { 268 m.Set(Int64(int64(i*i)), Int64(0)) 269 } 270 271 for k, v := m.FindNext(Nil); k != Nil; k, v = m.FindNext(k) { 272 fmt.Println(k, v) 273 } 274 } 275 276 func TestMapDistance(t *testing.T) { 277 test := func(sz int) { 278 o := newMap(sz) 279 for i := 0; i < sz; i++ { 280 o.Set(Int(randInt(sz, i)), Int(i)) 281 } 282 for _, i := range o.items { 283 if i.key != Nil { 284 if i.dist != 0 { 285 t.Fatal(o.items) 286 } 287 } 288 } 289 } 290 for i := 1; i < 16; i++ { 291 test(i) 292 } 293 test = func(sz int) { 294 o := newMap(sz / 2) 295 o.noresize = true 296 for i := 0; i < sz; i++ { 297 o.Set(Int(randInt(sz, i)), Int(i)) 298 } 299 for _, i := range o.items { 300 if i.dist != 0 { 301 t.Fatal(o.items) 302 } 303 } 304 } 305 for i := 2; i <= 16; i += 2 { 306 test(i) 307 } 308 } 309 310 func TestHashcodeDist(t *testing.T) { 311 rand.Seed(time.Now().Unix()) 312 for _, a := range []string{"a", "b", "c", "z", randString(), randString(), randString(), randString()} { 313 fmt.Println(Str(a).HashCode() % 32) 314 } 315 316 z := map[uint32]int{} 317 m := newMap(0) 318 rand.Seed(time.Now().Unix()) 319 for i := 0; i < 1e6; i++ { 320 v := Int64(int64(i)).HashCode() % 32 321 z[v]++ 322 m.Set(Int(i), Int(i)) 323 } 324 fmt.Println(z, m.density(), m.Cap()) 325 326 z = map[uint32]int{} 327 for i := 0; i < 1e6; i++ { 328 v := Int64(rand.Int63()).HashCode() % 32 329 z[v]++ 330 } 331 fmt.Println((z)) 332 333 z = map[uint32]int{} 334 for i := 0; i < 1e6; i++ { 335 v := Str(randString()).HashCode() % 32 336 z[v]++ 337 } 338 fmt.Println((z)) 339 340 z = map[uint32]int{} 341 m.Clear() 342 for i := 0; i < 1e6; i++ { 343 x := fmt.Sprintf("%016x", rand.Uint64()) 344 v := Str(x).HashCode() % 32 345 z[v]++ 346 m.Set(Str(x), Str(x)) 347 } 348 fmt.Println(z, m.density(), m.Cap()) 349 350 m = newMap(0) 351 for i := 0; i < 20; i++ { 352 m.Set(Int(i), Int(i)) 353 } 354 fmt.Println(m.DebugString()) 355 } 356 357 func BenchmarkStr(b *testing.B) { 358 for i := 0; i < b.N; i++ { 359 Str("\x00") 360 } 361 } 362 363 func BenchmarkStrHashCode(b *testing.B) { 364 x := Str(randString() + randString()) 365 for i := 0; i < b.N; i++ { 366 x.HashCode() 367 } 368 } 369 370 func BenchmarkContains(b *testing.B) { 371 m := newMap(0) 372 k2 := []Value{} 373 for i := 0; i < 1e3; i++ { 374 k := randString() 375 m.Set(Str(k), Int(0)) 376 k2 = append(k2, Str(randString())) 377 } 378 for i := 0; i < b.N; i++ { 379 if m.Contains(k2[rand.Intn(len(k2))]) { 380 b.Fatal() 381 } 382 } 383 } 384 385 func BenchmarkContainsNative(b *testing.B) { 386 k2 := []string{} 387 m := map[string]bool{} 388 for i := 0; i < 1e3; i++ { 389 k := randString() 390 m[k] = true 391 k2 = append(k2, randString()) 392 } 393 for i := 0; i < b.N; i++ { 394 if m[k2[rand.Intn(len(k2))]] { 395 b.Fatal() 396 } 397 } 398 } 399 400 func TestFalsyValue(t *testing.T) { 401 assert := func(b bool) { 402 if !b { 403 _, fn, ln, _ := runtime.Caller(1) 404 t.Fatal(fn, ln) 405 } 406 } 407 408 assert(Float64(0).IsFalse()) 409 assert(Float64(1 / math.Inf(-1)).IsFalse()) 410 assert(!Float64(math.NaN()).IsFalse()) 411 assert(!Bool(true).IsFalse()) 412 assert(Bool(false).IsFalse()) 413 assert(Str("").IsFalse()) 414 assert(Str("\x00").IsTrue()) 415 assert(Str("\x00\x00").IsTrue()) 416 assert(Str("\x00\x00\x00").IsTrue()) 417 assert(Str("\x00\x00\x00\x00").IsTrue()) 418 assert(Str("\x00\x00\x00\x00\x00").IsTrue()) 419 assert(Str(strings.Repeat("\x00", 6)).IsTrue()) 420 assert(Str(strings.Repeat("\x00", 7)).IsTrue()) 421 assert(Str(strings.Repeat("\x00", 8)).IsTrue()) 422 assert(Byte('a') == Str("a")) 423 assert(Rune('a') == Str("a")) 424 assert(Rune('\u263a') == Str("\u263a")) 425 assert(Rune('\U0001f60a') == Str("\U0001f60a")) 426 assert(Bytes(nil).IsTrue()) 427 assert(Bytes([]byte("")).IsTrue()) 428 assert(!ValueOf([]byte("")).IsFalse()) 429 assert(Str("\x00\x00\x00\x00\x00\x00\x00").Less(Str("\x00\x00\x00\x00\x00\x00\x00\x00"))) 430 assert(newArray().ToValue().IsArray()) 431 } 432 433 func TestFormat(t *testing.T) { 434 sprintf := func(format string, args ...interface{}) string { 435 p := &bytes.Buffer{} 436 internal.Fprintf(p, format, args...) 437 return p.String() 438 } 439 440 type payload struct { 441 f string 442 v interface{} 443 res string 444 } 445 446 payloads := []payload{ 447 {"%d", uint(12345), "12345"}, 448 {"%d", int(-12345), "-12345"}, 449 {"%d", ^uint8(0), "255"}, 450 {"%d", ^uint16(0), "65535"}, 451 {"%d", ^uint32(0), "4294967295"}, 452 {"%d", ^uint64(0), "18446744073709551615"}, 453 {"%d", int8(-1 << 7), "-128"}, 454 {"%d", int16(-1 << 15), "-32768"}, 455 {"%d", int32(-1 << 31), "-2147483648"}, 456 {"%d", int64(-1 << 63), "-9223372036854775808"}, 457 {"%.d", 0, ""}, 458 {"%.0d", 0, ""}, 459 {"%6.0d", 0, " "}, 460 {"%06.0d", 0, " "}, 461 {"% d", 12345, " 12345"}, 462 {"%+d", 12345, "+12345"}, 463 {"%+d", -12345, "-12345"}, 464 {"%b", 7, "111"}, 465 {"%b", -6, "-110"}, 466 {"%#b", 7, "0b111"}, 467 {"%#b", -6, "-0b110"}, 468 {"%b", ^uint32(0), "11111111111111111111111111111111"}, 469 {"%b", ^uint64(0), "1111111111111111111111111111111111111111111111111111111111111111"}, 470 {"%o", 01234, "1234"}, 471 {"%o", -01234, "-1234"}, 472 {"%#o", 01234, "01234"}, 473 {"%#o", -01234, "-01234"}, 474 {"%O", 01234, "0o1234"}, 475 {"%O", -01234, "-0o1234"}, 476 {"%o", ^uint32(0), "37777777777"}, 477 {"%o", ^uint64(0), "1777777777777777777777"}, 478 {"%#X", 0, "0X0"}, 479 {"%x", 0x12abcdef, "12abcdef"}, 480 {"%X", 0x12abcdef, "12ABCDEF"}, 481 {"%x", ^uint32(0), "ffffffff"}, 482 {"%X", ^uint64(0), "FFFFFFFFFFFFFFFF"}, 483 {"%.20b", 7, "00000000000000000111"}, 484 {"%10d", 12345, " 12345"}, 485 {"%10d", -12345, " -12345"}, 486 {"%+10d", 12345, " +12345"}, 487 {"%010d", 12345, "0000012345"}, 488 {"%010d", -12345, "-000012345"}, 489 {"%20.8d", 1234, " 00001234"}, 490 {"%20.8d", -1234, " -00001234"}, 491 {"%020.8d", 1234, " 00001234"}, 492 {"%020.8d", -1234, " -00001234"}, 493 {"%-20.8d", 1234, "00001234 "}, 494 {"%-20.8d", -1234, "-00001234 "}, 495 {"%-#20.8x", 0x1234abc, "0x01234abc "}, 496 {"%-#20.8X", 0x1234abc, "0X01234ABC "}, 497 {"%-#20.8o", 01234, "00001234 "}, 498 {"%+.3e", 0.0, "+0.000e+00"}, 499 {"%+.3e", 1.0, "+1.000e+00"}, 500 {"%+.3x", 0.0, "+0x0.000p+00"}, 501 {"%+.3x", 1.0, "+0x1.000p+00"}, 502 {"%+.3f", -1.0, "-1.000"}, 503 {"%+.3F", -1.0, "-1.000"}, 504 {"%+.3F", float32(-1.0), "-1.000"}, 505 {"%+07.2f", 1.0, "+001.00"}, 506 {"%+07.2f", -1.0, "-001.00"}, 507 {"%-07.2f", 1.0, "1.00 "}, 508 {"%-07.2f", -1.0, "-1.00 "}, 509 {"%+-07.2f", 1.0, "+1.00 "}, 510 {"%+-07.2f", -1.0, "-1.00 "}, 511 {"%-+07.2f", 1.0, "+1.00 "}, 512 {"%-+07.2f", -1.0, "-1.00 "}, 513 {"%+10.2f", +1.0, " +1.00"}, 514 {"%+10.2f", -1.0, " -1.00"}, 515 {"% .3E", -1.0, "-1.000E+00"}, 516 {"% .3e", 1.0, " 1.000e+00"}, 517 {"% .3X", -1.0, "-0X1.000P+00"}, 518 {"% .3x", 1.0, " 0x1.000p+00"}, 519 {"%+.3g", 0.0, "+0"}, 520 {"%+.3g", 1.0, "+1"}, 521 {"%+.3g", -1.0, "-1"}, 522 {"% .3g", -1.0, "-1"}, 523 {"% .3g", 1.0, " 1"}, 524 {"%b", float32(1.0), "8388608p-23"}, 525 {"%b", 1.0, "4503599627370496p-52"}, 526 // Test sharp flag used with floats. 527 {"%#g", 1e-323, "1.00000e-323"}, 528 {"%#g", -1.0, "-1.00000"}, 529 {"%#g", 1.1, "1.10000"}, 530 {"%#g", 123456.0, "123456."}, 531 {"%#g", 1234567.0, "1.234567e+06"}, 532 {"%#g", 1230000.0, "1.23000e+06"}, 533 {"%#g", 1000000.0, "1.00000e+06"}, 534 {"%#.0f", 1.0, "1."}, 535 {"%#.0e", 1.0, "1.e+00"}, 536 {"%#.0x", 1.0, "0x1.p+00"}, 537 {"%#.0g", 1.0, "1."}, 538 {"%#.0g", 1100000.0, "1.e+06"}, 539 {"%#.4f", 1.0, "1.0000"}, 540 {"%#.4e", 1.0, "1.0000e+00"}, 541 {"%#.4x", 1.0, "0x1.0000p+00"}, 542 {"%#.4g", 1.0, "1.000"}, 543 {"%#.4g", 100000.0, "1.000e+05"}, 544 {"%#.4g", 1.234, "1.234"}, 545 {"%#.4g", 0.1234, "0.1234"}, 546 {"%#.4g", 1.23, "1.230"}, 547 {"%#.4g", 0.123, "0.1230"}, 548 {"%#.4g", 1.2, "1.200"}, 549 {"%#.4g", 0.12, "0.1200"}, 550 {"%#.4g", 10.2, "10.20"}, 551 {"%#.4g", 0.0, "0.000"}, 552 {"%#.4g", 0.012, "0.01200"}, 553 {"%#.0f", 123.0, "123."}, 554 {"%#.0e", 123.0, "1.e+02"}, 555 {"%#.0x", 123.0, "0x1.p+07"}, 556 {"%#.0g", 123.0, "1.e+02"}, 557 {"%#.4f", 123.0, "123.0000"}, 558 {"%#.4e", 123.0, "1.2300e+02"}, 559 {"%#.4x", 123.0, "0x1.ec00p+06"}, 560 {"%#.4g", 123.0, "123.0"}, 561 {"%#.4g", 123000.0, "1.230e+05"}, 562 {"%#9.4g", 1.0, " 1.000"}, 563 // The sharp flag has no effect for binary float format. 564 {"%#b", 1.0, "4503599627370496p-52"}, 565 // Precision has no effect for binary float format. 566 {"%.4b", float32(1.0), "8388608p-23"}, 567 {"%.4b", -1.0, "-4503599627370496p-52"}, 568 // Test correct f.intbuf boundary checks. 569 // float infinites and NaNs 570 {"%f", math.Inf(1), "+Inf"}, 571 {"%.1f", math.Inf(-1), "-Inf"}, 572 {"% f", math.NaN(), " NaN"}, 573 {"%20f", math.Inf(1), " +Inf"}, 574 {"% 20F", math.Inf(1), " Inf"}, 575 {"% 20e", math.Inf(-1), " -Inf"}, 576 {"% 20x", math.Inf(-1), " -Inf"}, 577 {"%+20E", math.Inf(-1), " -Inf"}, 578 {"%+20X", math.Inf(-1), " -Inf"}, 579 {"% +20g", math.Inf(-1), " -Inf"}, 580 {"%+-20G", math.Inf(1), "+Inf "}, 581 {"%20e", math.NaN(), " NaN"}, 582 {"%20x", math.NaN(), " NaN"}, 583 {"% +20E", math.NaN(), " +NaN"}, 584 {"% +20X", math.NaN(), " +NaN"}, 585 {"% -20g", math.NaN(), " NaN "}, 586 {"%+-20G", math.NaN(), "+NaN "}, 587 // Zero padding does not apply to infinities and NaN. 588 {"%+020e", math.Inf(1), " +Inf"}, 589 {"%+020x", math.Inf(1), " +Inf"}, 590 {"%-020f", math.Inf(-1), "-Inf "}, 591 {"%-020E", math.NaN(), "NaN "}, 592 {"%-020X", math.NaN(), "NaN "}, 593 } 594 595 for _, p := range payloads { 596 if v := sprintf(p.f, p.v); v != p.res { 597 t.Fatal(p.f, p.v, "->", v, p.res) 598 } 599 } 600 } 601 602 func TestShape(t *testing.T) { 603 assertError := func(f bool, err error) { 604 if (err == nil) == f { 605 t.Fatal(err, string(debug.Stack())) 606 } 607 } 608 609 NewShape("") 610 // Shape(",") 611 // Shape("[") 612 // Shape("]") 613 // Shape("[,]") 614 615 assertError(false, NewShape("i")(Int(1))) 616 assertError(false, NewShape("n")(Int(1))) 617 assertError(false, NewShape("n")(Float64(1))) 618 assertError(false, NewShape("(i)")(Array(Int(1)))) 619 assertError(false, NewShape("(i i)")(Array(Int(1), Int(2)))) 620 assertError(false, NewShape("[i i]")(Array(Int(1), Int(2)))) 621 assertError(false, NewShape("[i i]")(Array(Int(1), Int(2), Int(3), Int(4)))) 622 assertError(false, NewShape("[i,i]")(Array())) 623 assertError(false, NewShape("(i,is)")(Array(Int(1), Int(2)))) 624 assertError(false, NewShape("(i,is)")(Array(Int(1), Str("2")))) 625 assertError(false, NewShape("([] is)")(Array(Array(Int(1)), Str("2")))) 626 assertError(false, NewShape("([@*int] is)")(Array(Array(NewNative(new(int)).ToValue()), Str("2")))) 627 assertError(false, NewShape("E")(Error(nil, fmt.Errorf("test")))) 628 assertError(false, NewShape("@error")(Error(nil, fmt.Errorf("test")))) 629 assertError(true, NewShape("[i]")(Array(Int(1), Float64(0.5)))) 630 assertError(false, NewShape("{} ")(NewObject(0).ToValue())) 631 632 o := NewObject(10) 633 o.Set(Int(1), Array()) 634 o.Set(Int(2), Array()) 635 assertError(false, NewShape("({i:[]} is)")(Array(o.ToValue(), Str("2")))) 636 637 o.Clear() 638 o.Set(Int(1), True) 639 o.Set(Int(2), Str("")) 640 assertError(false, NewShape("{}")(o.ToValue())) 641 assertError(false, NewShape("{i}")(o.ToValue())) 642 assertError(false, NewShape("{i v}")(o.ToValue())) 643 644 o.Clear() 645 assertError(false, NewShape("{i}")(o.ToValue())) 646 assertError(false, NewShape("<i,{}>")(o.ToValue())) 647 assertError(false, NewShape("<i,@object>")(o.ToValue())) 648 649 p := NewNamedObject("test", 0) 650 assertError(true, NewShape("@test")(o.ToValue())) 651 o.SetPrototype(p) 652 assertError(false, NewShape("@test")(o.ToValue())) 653 assertError(false, NewShape("@object")(o.ToValue())) 654 655 assertError(false, NewShape("R")(ValueOf(&bytes.Buffer{}))) 656 assertError(true, NewShape("C")(ValueOf(&bytes.Buffer{}))) 657 658 assertError(false, NewShape("<[],{}>")(o.ToValue())) 659 } 660 661 func BenchmarkShape(b *testing.B) { 662 v := Array(Int(1), Int(2)) 663 s := NewShape("[i,i]") 664 for i := 0; i < b.N; i++ { 665 s(v) 666 } 667 } 668 669 func BenchmarkShapeSimple(b *testing.B) { 670 v := Int(1) 671 for i := 0; i < b.N; i++ { 672 v.AssertShape("si", "") 673 } 674 } 675 676 func BenchmarkShapeType(b *testing.B) { 677 v := Int(1) 678 for i := 0; i < b.N; i++ { 679 switch v.Type() { 680 case typ.Number, typ.String: 681 v.AssertNumber("") 682 } 683 } 684 }