github.com/tidwall/tile38@v0.0.0-20230521152930-0144ca6883f3/internal/collection/collection_test.go (about) 1 package collection 2 3 import ( 4 "fmt" 5 "math/rand" 6 "reflect" 7 "strconv" 8 "testing" 9 "time" 10 11 "github.com/tidwall/geojson" 12 "github.com/tidwall/geojson/geometry" 13 "github.com/tidwall/gjson" 14 "github.com/tidwall/tile38/internal/field" 15 "github.com/tidwall/tile38/internal/object" 16 ) 17 18 func PO(x, y float64) *geojson.Point { 19 return geojson.NewPoint(geometry.Point{X: x, Y: y}) 20 } 21 22 func init() { 23 seed := time.Now().UnixNano() 24 println(seed) 25 rand.Seed(seed) 26 } 27 28 func expect(t testing.TB, expect bool) { 29 t.Helper() 30 if !expect { 31 t.Fatal("not what you expected") 32 } 33 } 34 35 func bounds(c *Collection) geometry.Rect { 36 minX, minY, maxX, maxY := c.Bounds() 37 return geometry.Rect{ 38 Min: geometry.Point{X: minX, Y: minY}, 39 Max: geometry.Point{X: maxX, Y: maxY}, 40 } 41 } 42 43 func TestCollectionNewCollection(t *testing.T) { 44 const numItems = 10000 45 objs := make(map[string]geojson.Object) 46 c := New() 47 for i := 0; i < numItems; i++ { 48 id := strconv.FormatInt(int64(i), 10) 49 obj := PO(rand.Float64()*360-180, rand.Float64()*180-90) 50 objs[id] = obj 51 c.Set(object.New(id, obj, 0, field.List{})) 52 } 53 count := 0 54 bbox := geometry.Rect{ 55 Min: geometry.Point{X: -180, Y: -90}, 56 Max: geometry.Point{X: 180, Y: 90}, 57 } 58 c.geoSearch(bbox, func(o *object.Object) bool { 59 count++ 60 return true 61 }) 62 if count != len(objs) { 63 t.Fatalf("count = %d, expect %d", count, len(objs)) 64 } 65 count = c.Count() 66 if count != len(objs) { 67 t.Fatalf("c.Count() = %d, expect %d", count, len(objs)) 68 } 69 testCollectionVerifyContents(t, c, objs) 70 } 71 72 func toFields(fNames, fValues []string) field.List { 73 var fields field.List 74 for i := 0; i < len(fNames); i++ { 75 fields = fields.Set(field.Make(fNames[i], fValues[i])) 76 } 77 return fields 78 } 79 80 func TestCollectionSet(t *testing.T) { 81 t.Run("AddString", func(t *testing.T) { 82 c := New() 83 str1 := String("hello") 84 old := c.Set(object.New("str", str1, 0, field.List{})) 85 expect(t, old == nil) 86 }) 87 t.Run("UpdateString", func(t *testing.T) { 88 c := New() 89 str1 := String("hello") 90 str2 := String("world") 91 old := c.Set(object.New("str", str1, 0, field.List{})) 92 expect(t, old == nil) 93 old = c.Set(object.New("str", str2, 0, field.List{})) 94 expect(t, old.Geo() == str1) 95 }) 96 t.Run("AddPoint", func(t *testing.T) { 97 c := New() 98 point1 := PO(-112.1, 33.1) 99 old := c.Set(object.New("point", point1, 0, field.List{})) 100 expect(t, old == nil) 101 }) 102 t.Run("UpdatePoint", func(t *testing.T) { 103 c := New() 104 point1 := PO(-112.1, 33.1) 105 point2 := PO(-112.2, 33.2) 106 old := c.Set(object.New("point", point1, 0, field.List{})) 107 expect(t, old == nil) 108 old = c.Set(object.New("point", point2, 0, field.List{})) 109 expect(t, old.Geo().Center() == point1.Base()) 110 }) 111 t.Run("Fields", func(t *testing.T) { 112 c := New() 113 str1 := String("hello") 114 115 fNames := []string{"a", "b", "c"} 116 fValues := []string{"1", "2", "3"} 117 fields1 := toFields(fNames, fValues) 118 old := c.Set(object.New("str", str1, 0, fields1)) 119 expect(t, old == nil) 120 121 str2 := String("hello") 122 123 fNames = []string{"d", "e", "f"} 124 fValues = []string{"4", "5", "6"} 125 fields2 := toFields(fNames, fValues) 126 127 old = c.Set(object.New("str", str2, 0, fields2)) 128 expect(t, old.Geo() == str1) 129 expect(t, reflect.DeepEqual(old.Fields(), fields1)) 130 131 fNames = []string{"a", "b", "c", "d", "e", "f"} 132 fValues = []string{"7", "8", "9", "10", "11", "12"} 133 fields3 := toFields(fNames, fValues) 134 old = c.Set(object.New("str", str1, 0, fields3)) 135 expect(t, old.Geo() == str2) 136 expect(t, reflect.DeepEqual(old.Fields(), fields2)) 137 }) 138 t.Run("Delete", func(t *testing.T) { 139 c := New() 140 141 c.Set(object.New("1", String("1"), 0, field.List{})) 142 c.Set(object.New("2", String("2"), 0, field.List{})) 143 c.Set(object.New("3", PO(1, 2), 0, field.List{})) 144 145 expect(t, c.Count() == 3) 146 expect(t, c.StringCount() == 2) 147 expect(t, c.PointCount() == 1) 148 expect(t, bounds(c) == geometry.Rect{ 149 Min: geometry.Point{X: 1, Y: 2}, 150 Max: geometry.Point{X: 1, Y: 2}}) 151 var prev *object.Object 152 153 prev = c.Delete("2") 154 expect(t, prev.Geo().String() == "2") 155 expect(t, c.Count() == 2) 156 expect(t, c.StringCount() == 1) 157 expect(t, c.PointCount() == 1) 158 159 prev = c.Delete("1") 160 expect(t, prev.Geo().String() == "1") 161 expect(t, c.Count() == 1) 162 expect(t, c.StringCount() == 0) 163 expect(t, c.PointCount() == 1) 164 165 prev = c.Delete("3") 166 expect(t, prev.Geo().String() == `{"type":"Point","coordinates":[1,2]}`) 167 expect(t, c.Count() == 0) 168 expect(t, c.StringCount() == 0) 169 expect(t, c.PointCount() == 0) 170 prev = c.Delete("3") 171 expect(t, prev == nil) 172 expect(t, c.Count() == 0) 173 expect(t, bounds(c) == geometry.Rect{}) 174 expect(t, c.Get("3") == nil) 175 }) 176 } 177 178 func fieldValueAt(fields field.List, index int) string { 179 if index < 0 || index >= fields.Len() { 180 panic("out of bounds") 181 } 182 var retval string 183 var i int 184 fields.Scan(func(f field.Field) bool { 185 if i == index { 186 retval = f.Value().Data() 187 } 188 i++ 189 return true 190 }) 191 return retval 192 } 193 194 func TestCollectionScan(t *testing.T) { 195 N := 256 196 c := New() 197 for _, i := range rand.Perm(N) { 198 id := fmt.Sprintf("%04d", i) 199 c.Set(object.New(id, String(id), 0, makeFields( 200 field.Make("ex", id), 201 ))) 202 } 203 var n int 204 var prevID string 205 c.Scan(false, nil, nil, func(o *object.Object) bool { 206 if n > 0 { 207 expect(t, o.ID() > prevID) 208 } 209 expect(t, o.ID() == fieldValueAt(o.Fields(), 0)) 210 n++ 211 prevID = o.ID() 212 return true 213 }) 214 expect(t, n == c.Count()) 215 n = 0 216 c.Scan(true, nil, nil, func(o *object.Object) bool { 217 if n > 0 { 218 expect(t, o.ID() < prevID) 219 } 220 expect(t, o.ID() == fieldValueAt(o.Fields(), 0)) 221 n++ 222 prevID = o.ID() 223 return true 224 }) 225 expect(t, n == c.Count()) 226 227 n = 0 228 c.ScanRange("0060", "0070", false, nil, nil, 229 func(o *object.Object) bool { 230 if n > 0 { 231 expect(t, o.ID() > prevID) 232 } 233 expect(t, o.ID() == fieldValueAt(o.Fields(), 0)) 234 n++ 235 prevID = o.ID() 236 return true 237 }) 238 expect(t, n == 10) 239 240 n = 0 241 c.ScanRange("0070", "0060", true, nil, nil, 242 func(o *object.Object) bool { 243 if n > 0 { 244 expect(t, o.ID() < prevID) 245 } 246 expect(t, o.ID() == fieldValueAt(o.Fields(), 0)) 247 n++ 248 prevID = o.ID() 249 return true 250 }) 251 expect(t, n == 10) 252 253 n = 0 254 c.ScanGreaterOrEqual("0070", true, nil, nil, 255 func(o *object.Object) bool { 256 if n > 0 { 257 expect(t, o.ID() < prevID) 258 } 259 expect(t, o.ID() == fieldValueAt(o.Fields(), 0)) 260 n++ 261 prevID = o.ID() 262 return true 263 }) 264 expect(t, n == 71) 265 266 n = 0 267 c.ScanGreaterOrEqual("0070", false, nil, nil, 268 func(o *object.Object) bool { 269 if n > 0 { 270 expect(t, o.ID() > prevID) 271 } 272 expect(t, o.ID() == fieldValueAt(o.Fields(), 0)) 273 n++ 274 prevID = o.ID() 275 return true 276 }) 277 expect(t, n == c.Count()-70) 278 279 } 280 281 func makeFields(entries ...field.Field) field.List { 282 var fields field.List 283 for _, f := range entries { 284 fields = fields.Set(f) 285 } 286 return fields 287 } 288 289 func TestCollectionSearch(t *testing.T) { 290 N := 256 291 c := New() 292 for i, j := range rand.Perm(N) { 293 id := fmt.Sprintf("%04d", j) 294 ex := fmt.Sprintf("%04d", i) 295 c.Set(object.New(id, String(ex), 296 0, makeFields( 297 field.Make("i", ex), 298 field.Make("j", id), 299 ))) 300 } 301 var n int 302 var prevValue string 303 c.SearchValues(false, nil, nil, func(o *object.Object) bool { 304 if n > 0 { 305 expect(t, o.Geo().String() > prevValue) 306 } 307 expect(t, o.ID() == fieldValueAt(o.Fields(), 1)) 308 n++ 309 prevValue = o.Geo().String() 310 return true 311 }) 312 expect(t, n == c.Count()) 313 n = 0 314 c.SearchValues(true, nil, nil, func(o *object.Object) bool { 315 if n > 0 { 316 expect(t, o.Geo().String() < prevValue) 317 } 318 expect(t, o.ID() == fieldValueAt(o.Fields(), 1)) 319 n++ 320 prevValue = o.Geo().String() 321 return true 322 }) 323 expect(t, n == c.Count()) 324 325 n = 0 326 c.SearchValuesRange("0060", "0070", false, nil, nil, 327 func(o *object.Object) bool { 328 if n > 0 { 329 expect(t, o.Geo().String() > prevValue) 330 } 331 expect(t, o.ID() == fieldValueAt(o.Fields(), 1)) 332 n++ 333 prevValue = o.Geo().String() 334 return true 335 }) 336 expect(t, n == 10) 337 338 n = 0 339 c.SearchValuesRange("0070", "0060", true, nil, nil, 340 func(o *object.Object) bool { 341 if n > 0 { 342 expect(t, o.Geo().String() < prevValue) 343 } 344 expect(t, o.ID() == fieldValueAt(o.Fields(), 1)) 345 n++ 346 prevValue = o.Geo().String() 347 return true 348 }) 349 expect(t, n == 10) 350 } 351 352 func TestCollectionWeight(t *testing.T) { 353 c := New() 354 c.Set(object.New("1", String("1"), 0, field.List{})) 355 expect(t, c.TotalWeight() > 0) 356 c.Delete("1") 357 expect(t, c.TotalWeight() == 0) 358 c.Set(object.New("1", String("1"), 0, 359 toFields( 360 []string{"a", "b", "c"}, 361 []string{"1", "2", "3"}, 362 ), 363 )) 364 expect(t, c.TotalWeight() > 0) 365 c.Delete("1") 366 expect(t, c.TotalWeight() == 0) 367 c.Set(object.New("1", String("1"), 0, 368 toFields( 369 []string{"a", "b", "c"}, 370 []string{"1", "2", "3"}, 371 ), 372 )) 373 c.Set(object.New("2", String("2"), 0, 374 toFields( 375 []string{"d", "e", "f"}, 376 []string{"4", "5", "6"}, 377 ), 378 )) 379 c.Set(object.New("1", String("1"), 0, 380 toFields( 381 []string{"d", "e", "f"}, 382 []string{"4", "5", "6"}, 383 ), 384 )) 385 c.Delete("1") 386 c.Delete("2") 387 expect(t, c.TotalWeight() == 0) 388 } 389 390 func TestSpatialSearch(t *testing.T) { 391 json := ` 392 {"type":"FeatureCollection","features":[ 393 {"type":"Feature","id":"p1","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Point","coordinates":[-71.4743041992187,42.51867517417283]}}, 394 {"type":"Feature","id":"p2","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Point","coordinates":[-71.4056396484375,42.50197174319114]}}, 395 {"type":"Feature","id":"p3","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Point","coordinates":[-71.4619445800781,42.49437779897246]}}, 396 {"type":"Feature","id":"p4","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Point","coordinates":[-71.4337921142578,42.53891577257117]}}, 397 {"type":"Feature","id":"r1","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Polygon","coordinates":[[[-71.4279556274414,42.48804880765346],[-71.37439727783203,42.48804880765346],[-71.37439727783203,42.52322988064187],[-71.4279556274414,42.52322988064187],[-71.4279556274414,42.48804880765346]]]}}, 398 {"type":"Feature","id":"r2","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Polygon","coordinates":[[[-71.4825439453125,42.53588010092859],[-71.45027160644531,42.53588010092859],[-71.45027160644531,42.55839115400447],[-71.4825439453125,42.55839115400447],[-71.4825439453125,42.53588010092859]]]}}, 399 {"type":"Feature","id":"r3","properties":{"marker-color":"#962d28","stroke":"#962d28","fill":"#962d28"},"geometry":{"type":"Polygon","coordinates": [[[-71.4111328125,42.53512115995963],[-71.3833236694336,42.53512115995963],[-71.3833236694336,42.54953946116446],[-71.4111328125,42.54953946116446],[-71.4111328125,42.53512115995963]]]}}, 400 {"type":"Feature","id":"q1","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-71.55258178710938,42.51361399979923],[-71.42074584960938,42.51361399979923],[-71.42074584960938,42.59100512331456],[-71.55258178710938,42.59100512331456],[-71.55258178710938,42.51361399979923]]]}}, 401 {"type":"Feature","id":"q2","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-71.52992248535156,42.48121277771616],[-71.36375427246092,42.48121277771616],[-71.36375427246092,42.57786045892046],[-71.52992248535156,42.57786045892046],[-71.52992248535156,42.48121277771616]]]}}, 402 {"type":"Feature","id":"q3","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-71.49490356445312,42.56673588590953],[-71.52236938476562,42.47462922809497],[-71.42898559570312,42.464499337722344],[-71.43241882324219,42.522217752342236],[-71.37954711914061,42.56420729713456],[-71.49490356445312,42.56673588590953]]]}}, 403 {"type":"Feature","id":"q4","properties":{},"geometry":{"type":"Point","coordinates": [-71.46366119384766,42.54043355305221]}} 404 ]} 405 ` 406 p1, _ := geojson.Parse(gjson.Get(json, `features.#[id=="p1"]`).Raw, nil) 407 p2, _ := geojson.Parse(gjson.Get(json, `features.#[id=="p2"]`).Raw, nil) 408 p3, _ := geojson.Parse(gjson.Get(json, `features.#[id=="p3"]`).Raw, nil) 409 p4, _ := geojson.Parse(gjson.Get(json, `features.#[id=="p4"]`).Raw, nil) 410 r1, _ := geojson.Parse(gjson.Get(json, `features.#[id=="r1"]`).Raw, nil) 411 r2, _ := geojson.Parse(gjson.Get(json, `features.#[id=="r2"]`).Raw, nil) 412 r3, _ := geojson.Parse(gjson.Get(json, `features.#[id=="r3"]`).Raw, nil) 413 q1, _ := geojson.Parse(gjson.Get(json, `features.#[id=="q1"]`).Raw, nil) 414 q2, _ := geojson.Parse(gjson.Get(json, `features.#[id=="q2"]`).Raw, nil) 415 q3, _ := geojson.Parse(gjson.Get(json, `features.#[id=="q3"]`).Raw, nil) 416 q4, _ := geojson.Parse(gjson.Get(json, `features.#[id=="q4"]`).Raw, nil) 417 418 c := New() 419 c.Set(object.New("p1", p1, 0, field.List{})) 420 c.Set(object.New("p2", p2, 0, field.List{})) 421 c.Set(object.New("p3", p3, 0, field.List{})) 422 c.Set(object.New("p4", p4, 0, field.List{})) 423 c.Set(object.New("r1", r1, 0, field.List{})) 424 c.Set(object.New("r2", r2, 0, field.List{})) 425 c.Set(object.New("r3", r3, 0, field.List{})) 426 427 var n int 428 429 n = 0 430 c.Within(q1, 0, nil, nil, func(o *object.Object) bool { 431 n++ 432 return true 433 }) 434 expect(t, n == 3) 435 436 n = 0 437 c.Within(q2, 0, nil, nil, func(o *object.Object) bool { 438 n++ 439 return true 440 }) 441 expect(t, n == 7) 442 443 n = 0 444 c.Within(q3, 0, nil, nil, func(o *object.Object) bool { 445 n++ 446 return true 447 }) 448 expect(t, n == 4) 449 450 n = 0 451 c.Intersects(q1, 0, nil, nil, func(o *object.Object) bool { 452 n++ 453 return true 454 }) 455 expect(t, n == 4) 456 457 n = 0 458 c.Intersects(q2, 0, nil, nil, func(o *object.Object) bool { 459 n++ 460 return true 461 }) 462 expect(t, n == 7) 463 464 n = 0 465 c.Intersects(q3, 0, nil, nil, func(o *object.Object) bool { 466 n++ 467 return true 468 }) 469 expect(t, n == 5) 470 471 n = 0 472 c.Intersects(q3, 0, nil, nil, func(o *object.Object) bool { 473 n++ 474 return n <= 1 475 }) 476 expect(t, n == 2) 477 478 var items []geojson.Object 479 exitems := []geojson.Object{ 480 r2, p4, p1, r1, r3, p3, p2, 481 } 482 483 lastDist := float64(-1) 484 distsMonotonic := true 485 c.Nearby(q4, nil, nil, func(o *object.Object, dist float64) bool { 486 if dist < lastDist { 487 distsMonotonic = false 488 } 489 items = append(items, o.Geo()) 490 return true 491 }) 492 expect(t, len(items) == 7) 493 expect(t, distsMonotonic) 494 expect(t, reflect.DeepEqual(items, exitems)) 495 } 496 497 func TestCollectionSparse(t *testing.T) { 498 rect := geojson.NewRect(geometry.Rect{ 499 Min: geometry.Point{X: -71.598930, Y: 42.4586739}, 500 Max: geometry.Point{X: -71.37302, Y: 42.607937}, 501 }) 502 N := 10000 503 c := New() 504 r := rect.Rect() 505 for i := 0; i < N; i++ { 506 x := (r.Max.X-r.Min.X)*rand.Float64() + r.Min.X 507 y := (r.Max.Y-r.Min.Y)*rand.Float64() + r.Min.Y 508 point := PO(x, y) 509 c.Set(object.New(fmt.Sprintf("%d", i), point, 0, field.List{})) 510 } 511 var n int 512 n = 0 513 c.Within(rect, 1, nil, nil, func(o *object.Object) bool { 514 n++ 515 return true 516 }) 517 expect(t, n == 4) 518 519 n = 0 520 c.Within(rect, 2, nil, nil, func(o *object.Object) bool { 521 n++ 522 return true 523 }) 524 expect(t, n == 16) 525 526 n = 0 527 c.Within(rect, 3, nil, nil, func(o *object.Object) bool { 528 n++ 529 return true 530 }) 531 expect(t, n == 64) 532 533 n = 0 534 c.Within(rect, 3, nil, nil, func(o *object.Object) bool { 535 n++ 536 return n <= 30 537 }) 538 expect(t, n == 31) 539 540 n = 0 541 c.Intersects(rect, 3, nil, nil, func(o *object.Object) bool { 542 n++ 543 return true 544 }) 545 expect(t, n == 64) 546 547 n = 0 548 c.Intersects(rect, 3, nil, nil, func(o *object.Object) bool { 549 n++ 550 return n <= 30 551 }) 552 expect(t, n == 31) 553 554 } 555 556 func testCollectionVerifyContents(t *testing.T, c *Collection, objs map[string]geojson.Object) { 557 for id, o2 := range objs { 558 o := c.Get(id) 559 if o == nil { 560 t.Fatalf("ok[%s] = false, expect true", id) 561 } 562 j1 := string(o.Geo().AppendJSON(nil)) 563 j2 := string(o2.AppendJSON(nil)) 564 if j1 != j2 { 565 t.Fatalf("j1 == %s, expect %s", j1, j2) 566 } 567 } 568 } 569 570 func TestManyCollections(t *testing.T) { 571 colsM := make(map[string]*Collection) 572 cols := 100 573 objs := 1000 574 k := 0 575 for i := 0; i < cols; i++ { 576 key := strconv.FormatInt(int64(i), 10) 577 for j := 0; j < objs; j++ { 578 id := strconv.FormatInt(int64(j), 10) 579 p := geometry.Point{ 580 X: rand.Float64()*360 - 180, 581 Y: rand.Float64()*180 - 90, 582 } 583 obj := geojson.Object(PO(p.X, p.Y)) 584 col, ok := colsM[key] 585 if !ok { 586 col = New() 587 colsM[key] = col 588 } 589 col.Set(object.New(id, obj, 0, field.List{})) 590 k++ 591 } 592 } 593 594 col := colsM["13"] 595 //println(col.Count()) 596 bbox := geometry.Rect{ 597 Min: geometry.Point{X: -180, Y: 30}, 598 Max: geometry.Point{X: 34, Y: 100}, 599 } 600 col.geoSearch(bbox, func(o *object.Object) bool { 601 //println(id) 602 return true 603 }) 604 } 605 606 type testPointItem struct { 607 id string 608 object geojson.Object 609 fields field.List 610 } 611 612 func makeBenchFields(nFields int) field.List { 613 var fields field.List 614 for i := 0; i < nFields; i++ { 615 key := fmt.Sprintf("%d", i) 616 val := key 617 fields = fields.Set(field.Make(key, val)) 618 } 619 return fields 620 } 621 622 func BenchmarkInsert_Fields(t *testing.B) { 623 benchmarkInsert(t, 1) 624 } 625 626 func BenchmarkInsert_NoFields(t *testing.B) { 627 benchmarkInsert(t, 0) 628 } 629 630 func benchmarkInsert(t *testing.B, nFields int) { 631 rand.Seed(time.Now().UnixNano()) 632 items := make([]testPointItem, t.N) 633 for i := 0; i < t.N; i++ { 634 items[i] = testPointItem{ 635 fmt.Sprintf("%d", i), 636 PO(rand.Float64()*360-180, rand.Float64()*180-90), 637 makeBenchFields(nFields), 638 } 639 } 640 col := New() 641 t.ResetTimer() 642 for i := 0; i < t.N; i++ { 643 col.Set(object.New(items[i].id, items[i].object, 0, items[i].fields)) 644 } 645 } 646 647 func BenchmarkReplace_Fields(t *testing.B) { 648 benchmarkReplace(t, 1) 649 } 650 651 func BenchmarkReplace_NoFields(t *testing.B) { 652 benchmarkReplace(t, 0) 653 } 654 655 func benchmarkReplace(t *testing.B, nFields int) { 656 rand.Seed(time.Now().UnixNano()) 657 items := make([]testPointItem, t.N) 658 for i := 0; i < t.N; i++ { 659 items[i] = testPointItem{ 660 fmt.Sprintf("%d", i), 661 PO(rand.Float64()*360-180, rand.Float64()*180-90), 662 makeBenchFields(nFields), 663 } 664 } 665 col := New() 666 for i := 0; i < t.N; i++ { 667 col.Set(object.New(items[i].id, items[i].object, 0, items[i].fields)) 668 } 669 t.ResetTimer() 670 for _, i := range rand.Perm(t.N) { 671 o := col.Set(object.New(items[i].id, items[i].object, 0, field.List{})) 672 if o.Geo() != items[i].object { 673 t.Fatal("shoot!") 674 } 675 } 676 } 677 678 func BenchmarkGet_Fields(t *testing.B) { 679 benchmarkGet(t, 1) 680 } 681 682 func BenchmarkGet_NoFields(t *testing.B) { 683 benchmarkGet(t, 0) 684 } 685 686 func benchmarkGet(t *testing.B, nFields int) { 687 rand.Seed(time.Now().UnixNano()) 688 items := make([]testPointItem, t.N) 689 for i := 0; i < t.N; i++ { 690 items[i] = testPointItem{ 691 fmt.Sprintf("%d", i), 692 PO(rand.Float64()*360-180, rand.Float64()*180-90), 693 makeBenchFields(nFields), 694 } 695 } 696 col := New() 697 for i := 0; i < t.N; i++ { 698 col.Set(object.New(items[i].id, items[i].object, 0, items[i].fields)) 699 } 700 t.ResetTimer() 701 for _, i := range rand.Perm(t.N) { 702 o := col.Get(items[i].id) 703 if o.Geo() != items[i].object { 704 t.Fatal("shoot!") 705 } 706 } 707 } 708 709 func BenchmarkRemove_Fields(t *testing.B) { 710 benchmarkRemove(t, 1) 711 } 712 713 func BenchmarkRemove_NoFields(t *testing.B) { 714 benchmarkRemove(t, 0) 715 } 716 717 func benchmarkRemove(t *testing.B, nFields int) { 718 rand.Seed(time.Now().UnixNano()) 719 items := make([]testPointItem, t.N) 720 for i := 0; i < t.N; i++ { 721 items[i] = testPointItem{ 722 fmt.Sprintf("%d", i), 723 PO(rand.Float64()*360-180, rand.Float64()*180-90), 724 makeBenchFields(nFields), 725 } 726 } 727 col := New() 728 for i := 0; i < t.N; i++ { 729 col.Set(object.New(items[i].id, items[i].object, 0, items[i].fields)) 730 } 731 t.ResetTimer() 732 for _, i := range rand.Perm(t.N) { 733 prev := col.Delete(items[i].id) 734 if prev.Geo() != items[i].object { 735 t.Fatal("shoot!") 736 } 737 } 738 } 739 740 func BenchmarkScan_Fields(t *testing.B) { 741 benchmarkScan(t, 1) 742 } 743 744 func BenchmarkScan_NoFields(t *testing.B) { 745 benchmarkScan(t, 0) 746 } 747 748 func benchmarkScan(t *testing.B, nFields int) { 749 rand.Seed(time.Now().UnixNano()) 750 items := make([]testPointItem, t.N) 751 for i := 0; i < t.N; i++ { 752 items[i] = testPointItem{ 753 fmt.Sprintf("%d", i), 754 PO(rand.Float64()*360-180, rand.Float64()*180-90), 755 makeBenchFields(nFields), 756 } 757 } 758 col := New() 759 for i := 0; i < t.N; i++ { 760 col.Set(object.New(items[i].id, items[i].object, 0, items[i].fields)) 761 } 762 t.ResetTimer() 763 for i := 0; i < t.N; i++ { 764 var scanIteration int 765 col.Scan(true, nil, nil, func(o *object.Object) bool { 766 scanIteration++ 767 return scanIteration <= 500 768 }) 769 } 770 }