github.com/ravendb/ravendb-go-client@v0.0.0-20240229102137-4474ee7aa0fa/tests/go1_test.go (about) 1 package tests 2 3 import ( 4 "fmt" 5 "reflect" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/ravendb/ravendb-go-client/examples/northwind" 11 12 ravendb "github.com/ravendb/ravendb-go-client" 13 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func assertIllegalArgumentError(t *testing.T, err error, s ...string) { 18 assert.Error(t, err) 19 if err != nil { 20 _, ok := err.(*ravendb.IllegalArgumentError) 21 if !ok { 22 assert.True(t, ok, "expected error of type *ravendb.IllegalArgumentError, got %T", err) 23 return 24 } 25 if len(s) > 0 { 26 panicIf(len(s) > 1, "only 0 or 1 strings are expected as s") 27 assert.Equal(t, s[0], err.Error()) 28 } 29 } 30 } 31 32 func assertIllegalStateError(t *testing.T, err error, s ...string) { 33 assert.Error(t, err) 34 if err != nil { 35 _, ok := err.(*ravendb.IllegalStateError) 36 if !ok { 37 assert.True(t, ok, "expected error of type *ravendb.IllegalStateError, got %T", err) 38 return 39 } 40 if len(s) > 0 { 41 panicIf(len(s) > 1, "only 0 or 1 strings are expected as s") 42 assert.Equal(t, s[0], err.Error()) 43 } 44 } 45 } 46 47 func goTest(t *testing.T, driver *RavenTestDriver) { 48 logTestName() 49 50 var err error 51 store := driver.getDocumentStoreMust(t) 52 defer store.Close() 53 54 session := openSessionMust(t, store) 55 user := User{} 56 57 // check validation of arguments to Store and Delete 58 59 { 60 // can't store/delete etc. nil 61 var v interface{} 62 err = session.Store(v) 63 assertIllegalArgumentError(t, err, "entity can't be nil") 64 err = session.StoreWithID(v, "users/1") 65 assertIllegalArgumentError(t, err) 66 err = session.Delete(v) 67 assertIllegalArgumentError(t, err) 68 _, err = session.GetMetadataFor(v) 69 assertIllegalArgumentError(t, err) 70 _, err = session.GetChangeVectorFor(v) 71 assertIllegalArgumentError(t, err) 72 _, err = session.GetLastModifiedFor(v) 73 assertIllegalArgumentError(t, err) 74 _, err = session.HasChanged(v) 75 assertIllegalArgumentError(t, err) 76 err = session.Evict(v) 77 assertIllegalArgumentError(t, err) 78 err = session.Advanced().Patch(v, "foo", 1) 79 assertIllegalArgumentError(t, err) 80 err = session.Advanced().Increment(v, "foo", 1) 81 assertIllegalArgumentError(t, err) 82 err = session.Advanced().PatchArray(v, "foo", nil) 83 assertIllegalArgumentError(t, err) 84 err = session.Refresh(v) 85 assertIllegalArgumentError(t, err) 86 } 87 88 { 89 // can't store/delete etc. nil pointer 90 var v *User 91 err = session.Store(v) 92 assertIllegalArgumentError(t, err, "entity of type *tests.User can't be nil") 93 err = session.StoreWithID(v, "users/1") 94 assertIllegalArgumentError(t, err) 95 err = session.Delete(v) 96 assertIllegalArgumentError(t, err) 97 _, err = session.GetMetadataFor(v) 98 assertIllegalArgumentError(t, err) 99 _, err = session.GetChangeVectorFor(v) 100 assertIllegalArgumentError(t, err) 101 _, err = session.GetLastModifiedFor(v) 102 assertIllegalArgumentError(t, err) 103 _, err = session.HasChanged(v) 104 assertIllegalArgumentError(t, err) 105 err = session.Evict(v) 106 assertIllegalArgumentError(t, err) 107 err = session.Advanced().Patch(v, "foo", 1) 108 assertIllegalArgumentError(t, err) 109 err = session.Advanced().Increment(v, "foo", 1) 110 assertIllegalArgumentError(t, err) 111 err = session.Advanced().PatchArray(v, "foo", nil) 112 assertIllegalArgumentError(t, err) 113 err = session.Refresh(v) 114 assertIllegalArgumentError(t, err) 115 } 116 117 { 118 // can't store/delete etc. struct 119 v := user 120 err = session.Store(v) 121 assertIllegalArgumentError(t, err, "entity can't be of type tests.User, try passing *tests.User") 122 err = session.StoreWithID(v, "users/1") 123 assertIllegalArgumentError(t, err) 124 err = session.Delete(v) 125 assertIllegalArgumentError(t, err) 126 _, err = session.GetMetadataFor(v) 127 assertIllegalArgumentError(t, err) 128 _, err = session.GetChangeVectorFor(v) 129 assertIllegalArgumentError(t, err) 130 _, err = session.GetLastModifiedFor(v) 131 assertIllegalArgumentError(t, err) 132 _, err = session.HasChanged(v) 133 assertIllegalArgumentError(t, err) 134 err = session.Evict(v) 135 assertIllegalArgumentError(t, err) 136 err = session.Advanced().Patch(v, "foo", 1) 137 assertIllegalArgumentError(t, err) 138 err = session.Advanced().Increment(v, "foo", 1) 139 assertIllegalArgumentError(t, err) 140 err = session.Advanced().PatchArray(v, "foo", nil) 141 assertIllegalArgumentError(t, err) 142 err = session.Refresh(v) 143 assertIllegalArgumentError(t, err) 144 } 145 146 { 147 // can't store/delete etc. **struct (double pointer values) 148 ptrUser := &user 149 v := &ptrUser 150 err = session.Store(v) 151 assertIllegalArgumentError(t, err, "entity can't be of type **tests.User, try passing *tests.User") 152 err = session.StoreWithID(v, "users/1") 153 assertIllegalArgumentError(t, err) 154 err = session.Delete(v) 155 assertIllegalArgumentError(t, err) 156 _, err = session.GetMetadataFor(v) 157 assertIllegalArgumentError(t, err) 158 _, err = session.GetChangeVectorFor(v) 159 assertIllegalArgumentError(t, err) 160 _, err = session.GetLastModifiedFor(v) 161 assertIllegalArgumentError(t, err) 162 _, err = session.HasChanged(v) 163 assertIllegalArgumentError(t, err) 164 err = session.Evict(v) 165 assertIllegalArgumentError(t, err) 166 err = session.Advanced().Patch(v, "foo", 1) 167 assertIllegalArgumentError(t, err) 168 err = session.Advanced().Increment(v, "foo", 1) 169 assertIllegalArgumentError(t, err) 170 err = session.Advanced().PatchArray(v, "foo", nil) 171 assertIllegalArgumentError(t, err) 172 err = session.Refresh(v) 173 assertIllegalArgumentError(t, err) 174 } 175 176 { 177 // can't store/delete etc. a map 178 var v map[string]interface{} 179 err = session.Store(v) 180 assertIllegalArgumentError(t, err, "entity can't be of type map[string]interface {}, try passing *map[string]interface {}") 181 err = session.StoreWithID(v, "users/1") 182 assertIllegalArgumentError(t, err) 183 err = session.Delete(v) 184 assertIllegalArgumentError(t, err) 185 _, err = session.GetMetadataFor(v) 186 assertIllegalArgumentError(t, err) 187 _, err = session.GetChangeVectorFor(v) 188 assertIllegalArgumentError(t, err) 189 _, err = session.GetLastModifiedFor(v) 190 assertIllegalArgumentError(t, err) 191 _, err = session.HasChanged(v) 192 assertIllegalArgumentError(t, err) 193 err = session.Evict(v) 194 assertIllegalArgumentError(t, err) 195 err = session.Advanced().Patch(v, "foo", 1) 196 assertIllegalArgumentError(t, err) 197 err = session.Advanced().Increment(v, "foo", 1) 198 assertIllegalArgumentError(t, err) 199 err = session.Advanced().PatchArray(v, "foo", nil) 200 assertIllegalArgumentError(t, err) 201 err = session.Refresh(v) 202 assertIllegalArgumentError(t, err) 203 } 204 205 { 206 v := &User{} // dummy value that only has to pass type check 207 adv := session.Advanced() 208 209 err = adv.Increment(v, "", 1) 210 assertIllegalArgumentError(t, err, "path can't be empty string") 211 err = adv.Increment(v, "foo", nil) 212 assertIllegalArgumentError(t, err, "valueToAdd can't be nil") 213 214 err = adv.IncrementByID("", "foo", 1) 215 assertIllegalArgumentError(t, err, "id can't be empty string") 216 err = adv.IncrementByID("id", "", 1) 217 assertIllegalArgumentError(t, err, "path can't be empty string") 218 err = adv.IncrementByID("id", "foo", nil) 219 assertIllegalArgumentError(t, err, "valueToAdd can't be nil") 220 221 err = adv.Patch(v, "", 1) 222 assertIllegalArgumentError(t, err, "path can't be empty string") 223 err = adv.Patch(v, "foo", nil) 224 assertIllegalArgumentError(t, err, "value can't be nil") 225 226 err = adv.PatchByID("", "foo", 1) 227 assertIllegalArgumentError(t, err, "id can't be empty string") 228 err = adv.PatchByID("id", "", 1) 229 assertIllegalArgumentError(t, err, "path can't be empty string") 230 err = adv.PatchByID("id", "foo", nil) 231 assertIllegalArgumentError(t, err, "value can't be nil") 232 233 err = adv.PatchArray(v, "", nil) 234 assertIllegalArgumentError(t, err, "pathToArray can't be empty string") 235 err = adv.PatchArray(v, "foo", nil) 236 assertIllegalArgumentError(t, err, "arrayAdder can't be nil") 237 238 err = adv.PatchArrayByID("", "foo", nil) 239 assertIllegalArgumentError(t, err, "id can't be empty string") 240 err = adv.PatchArrayByID("id", "", nil) 241 assertIllegalArgumentError(t, err, "pathToArray can't be empty string") 242 err = adv.PatchArrayByID("id", "foo", nil) 243 assertIllegalArgumentError(t, err, "arrayAdder can't be nil") 244 } 245 246 { 247 _, err = session.Exists("") 248 assertIllegalArgumentError(t, err, "id cannot be empty string") 249 } 250 251 session.Close() 252 } 253 254 func goStore(t *testing.T, session *ravendb.DocumentSession) []*User { 255 logTestName() 256 257 var err error 258 var res []*User 259 { 260 names := []string{"John", "Mary", "Paul"} 261 for _, name := range names { 262 u := &User{} 263 u.setName(name) 264 err := session.Store(u) 265 assert.NoError(t, err) 266 res = append(res, u) 267 } 268 err = session.SaveChanges() 269 assert.NoError(t, err) 270 session.Close() 271 } 272 return res 273 } 274 275 func goTestGetLastModifiedForAndChanges(t *testing.T, driver *RavenTestDriver) { 276 logTestName() 277 278 var err error 279 var changed, hasChanges bool 280 281 store := driver.getDocumentStoreMust(t) 282 defer store.Close() 283 284 var users []*User 285 var lastModifiedFirst *time.Time 286 { 287 session := openSessionMust(t, store) 288 users = goStore(t, session) 289 lastModifiedFirst, err = session.GetLastModifiedFor(users[0]) 290 assert.NoError(t, err) 291 assert.NotNil(t, lastModifiedFirst) 292 session.Close() 293 } 294 295 { 296 session := openSessionMust(t, store) 297 298 // test HasChanges() 299 hasChanges = session.HasChanges() 300 assert.False(t, hasChanges) 301 302 var u *User 303 id := users[0].ID 304 err = session.Load(&u, id) 305 assert.NoError(t, err) 306 assert.Equal(t, id, u.ID) 307 lastModified, err := session.GetLastModifiedFor(u) 308 assert.NoError(t, err) 309 assert.Equal(t, *lastModifiedFirst, *lastModified) 310 311 changed, err = session.HasChanged(u) 312 assert.NoError(t, err) 313 assert.False(t, changed) 314 315 // check last modified changes after modification 316 u.Age = 5 317 err = session.Store(u) 318 assert.NoError(t, err) 319 320 changed, err = session.HasChanged(u) 321 assert.NoError(t, err) 322 assert.True(t, changed) 323 324 hasChanges = session.HasChanges() 325 assert.True(t, hasChanges) 326 327 err = session.SaveChanges() 328 assert.NoError(t, err) 329 330 lastModified, err = session.GetLastModifiedFor(u) 331 assert.NoError(t, err) 332 diff := (*lastModified).Sub(*lastModifiedFirst) 333 assert.True(t, diff > 0) 334 335 session.Close() 336 } 337 338 { 339 // test HasChanged() detects deletion 340 session := openSessionMust(t, store) 341 var u *User 342 id := users[0].ID 343 err = session.Load(&u, id) 344 assert.NoError(t, err) 345 346 err = session.Delete(u) 347 assert.NoError(t, err) 348 349 /* 350 // TODO: should deleted items be reported as changed? 351 changed, err = session.HasChanged(u) 352 assert.NoError(t, err) 353 assert.True(t, changed) 354 */ 355 356 hasChanges = session.HasChanges() 357 assert.True(t, hasChanges) 358 359 // Evict undoes deletion so we shouldn't have changes 360 err = session.Evict(u) 361 assert.NoError(t, err) 362 363 changed, err = session.HasChanged(u) 364 assert.NoError(t, err) 365 assert.False(t, changed) 366 367 hasChanges = session.HasChanges() 368 assert.False(t, hasChanges) 369 } 370 } 371 372 func goTestListeners(t *testing.T, driver *RavenTestDriver) { 373 logTestName() 374 375 var err error 376 377 store := driver.getDocumentStoreMust(t) 378 defer store.Close() 379 380 nBeforeStoreCalledCount := 0 381 beforeStore := func(event *ravendb.BeforeStoreEventArgs) { 382 _, ok := event.Entity.(*User) 383 assert.True(t, ok) 384 nBeforeStoreCalledCount++ 385 } 386 beforeStoreID := store.AddBeforeStoreListener(beforeStore) 387 388 nAfterSaveChangesCalledCount := 0 389 afterSaveChanges := func(event *ravendb.AfterSaveChangesEventArgs) { 390 _, ok := event.Entity.(*User) 391 assert.True(t, ok) 392 nAfterSaveChangesCalledCount++ 393 } 394 afterSaveChangesID := store.AddAfterSaveChangesListener(afterSaveChanges) 395 396 nBeforeDeleteCalledCount := 0 397 beforeDelete := func(event *ravendb.BeforeDeleteEventArgs) { 398 u, ok := event.Entity.(*User) 399 assert.True(t, ok) 400 assert.Equal(t, "users/1-A", u.ID) 401 nBeforeDeleteCalledCount++ 402 } 403 beforeDeleteID := store.AddBeforeDeleteListener(beforeDelete) 404 405 nBeforeQueryCalledCount := 0 406 beforeQuery := func(event *ravendb.BeforeQueryEventArgs) { 407 nBeforeQueryCalledCount++ 408 } 409 beforeQueryID := store.AddBeforeQueryListener(beforeQuery) 410 411 { 412 assert.Equal(t, 0, nBeforeStoreCalledCount) 413 assert.Equal(t, 0, nAfterSaveChangesCalledCount) 414 session := openSessionMust(t, store) 415 users := goStore(t, session) 416 session.Close() 417 assert.Equal(t, len(users), nBeforeStoreCalledCount) 418 assert.Equal(t, len(users), nAfterSaveChangesCalledCount) 419 } 420 421 { 422 assert.Equal(t, 0, nBeforeDeleteCalledCount) 423 session := openSessionMust(t, store) 424 var u *User 425 err = session.Load(&u, "users/1-A") 426 assert.NoError(t, err) 427 err = session.Delete(u) 428 assert.NoError(t, err) 429 err = session.SaveChanges() 430 assert.NoError(t, err) 431 session.Close() 432 assert.Equal(t, 1, nBeforeDeleteCalledCount) 433 } 434 435 { 436 assert.Equal(t, 0, nBeforeQueryCalledCount) 437 session := openSessionMust(t, store) 438 tp := reflect.TypeOf(&User{}) 439 q := session.QueryCollectionForType(tp) 440 var users []*User 441 err = q.GetResults(&users) 442 assert.NoError(t, err) 443 assert.Equal(t, 2, len(users)) 444 session.Close() 445 assert.Equal(t, 1, nBeforeQueryCalledCount) 446 } 447 448 store.RemoveBeforeStoreListener(beforeStoreID) 449 store.RemoveAfterSaveChangesListener(afterSaveChangesID) 450 store.RemoveBeforeDeleteListener(beforeDeleteID) 451 store.RemoveBeforeQueryListener(beforeQueryID) 452 453 { 454 // verify those listeners were removed 455 nBeforeStoreCalledCountPrev := nBeforeStoreCalledCount 456 nAfterSaveChangesCalledCountPrev := nAfterSaveChangesCalledCount 457 nBeforeDeleteCalledCountPrev := nBeforeDeleteCalledCount 458 nBeforeQueryCalledCountPrev := nBeforeQueryCalledCount 459 460 session := openSessionMust(t, store) 461 462 var users []*User 463 q := session.QueryCollectionForType(userType) 464 err = q.GetResults(&users) 465 assert.NoError(t, err) 466 assert.Equal(t, 2, len(users)) 467 assert.Equal(t, nBeforeQueryCalledCountPrev, nBeforeQueryCalledCount) 468 469 u := &User{} 470 err = session.Store(u) 471 assert.NoError(t, err) 472 err = session.DeleteByID("users/2-A", "") 473 assert.NoError(t, err) 474 err = session.SaveChanges() 475 assert.NoError(t, err) 476 session.Close() 477 478 assert.Equal(t, nBeforeStoreCalledCountPrev, nBeforeStoreCalledCount) 479 assert.Equal(t, nAfterSaveChangesCalledCountPrev, nAfterSaveChangesCalledCount) 480 assert.Equal(t, nBeforeDeleteCalledCountPrev, nBeforeDeleteCalledCount) 481 } 482 483 { 484 // test that Refresh() only works if entity is in session 485 session := openSessionMust(t, store) 486 var u *User 487 err = session.Load(&u, "users/3-A") 488 assert.NoError(t, err) 489 assert.NotNil(t, u) 490 err = session.Refresh(u) 491 assert.NoError(t, err) 492 493 err = session.Refresh(u) 494 assert.NoError(t, err) 495 496 for i := 0; err == nil && i < 32; i++ { 497 err = session.Refresh(u) 498 } 499 assertIllegalStateError(t, err, "exceeded max number of requests per session of 32") 500 501 session.Close() 502 } 503 504 { 505 // check Load() does proper argument validation 506 session := openSessionMust(t, store) 507 508 var v *User 509 err = session.Load(&v, "") 510 assertIllegalArgumentError(t, err, "id cannot be empty string") 511 512 err = session.Load(nil, "id") 513 assertIllegalArgumentError(t, err, "result can't be nil") 514 515 err = session.Load(User{}, "id") 516 assertIllegalArgumentError(t, err, "result can't be of type tests.User, try passing **tests.User") 517 518 err = session.Load(&User{}, "id") 519 assertIllegalArgumentError(t, err, "result can't be of type *tests.User, try passing **tests.User") 520 521 err = session.Load([]*User{}, "id") 522 assertIllegalArgumentError(t, err, "result can't be of type []*tests.User") 523 524 err = session.Load(&[]*User{}, "id") 525 assertIllegalArgumentError(t, err, "result can't be of type *[]*tests.User") 526 527 var n int 528 err = session.Load(n, "id") 529 assertIllegalArgumentError(t, err, "result can't be of type int") 530 err = session.Load(&n, "id") 531 assertIllegalArgumentError(t, err, "result can't be of type *int") 532 nPtr := &n 533 err = session.Load(&nPtr, "id") 534 assertIllegalArgumentError(t, err, "result can't be of type **int") 535 536 session.Close() 537 } 538 539 { 540 // check LoadMulti() does proper argument validation 541 session := openSessionMust(t, store) 542 543 var v map[string]*User 544 err = session.LoadMulti(v, nil) 545 assertIllegalArgumentError(t, err, "ids cannot be empty array") 546 err = session.LoadMulti(&v, []string{}) 547 assertIllegalArgumentError(t, err, "ids cannot be empty array") 548 549 err = session.LoadMulti(User{}, []string{"id"}) 550 assertIllegalArgumentError(t, err, "results can't be of type tests.User, must be map[string]<type>") 551 552 err = session.LoadMulti(&User{}, []string{"id"}) 553 assertIllegalArgumentError(t, err, "results can't be of type *tests.User, must be map[string]<type>") 554 555 err = session.LoadMulti(map[int]*User{}, []string{"id"}) 556 assertIllegalArgumentError(t, err, "results can't be of type map[int]*tests.User, must be map[string]<type>") 557 558 err = session.LoadMulti(map[string]int{}, []string{"id"}) 559 assertIllegalArgumentError(t, err, "results can't be of type map[string]int, must be map[string]<type>") 560 561 err = session.LoadMulti(map[string]*int{}, []string{"id"}) 562 assertIllegalArgumentError(t, err, "results can't be of type map[string]*int, must be map[string]<type>") 563 564 err = session.LoadMulti(map[string]User{}, []string{"id"}) 565 assertIllegalArgumentError(t, err, "results can't be of type map[string]tests.User, must be map[string]<type>") 566 567 err = session.LoadMulti(v, []string{"id"}) 568 assertIllegalArgumentError(t, err, "results can't be a nil map") 569 570 session.Close() 571 } 572 573 } 574 575 // TODO: this must be more comprehensive. Need to test all APIs. 576 func goTestStoreMap(t *testing.T, driver *RavenTestDriver) { 577 logTestName() 578 579 var err error 580 581 store := driver.getDocumentStoreMust(t) 582 defer store.Close() 583 584 { 585 session := openSessionMust(t, store) 586 m := map[string]interface{}{ 587 "foo": 5, 588 "bar": true, 589 "nullVal": nil, 590 "strVal": "a string", 591 } 592 err = session.StoreWithID(&m, "maps/1") 593 assert.NoError(t, err) 594 595 m2 := map[string]interface{}{ 596 "foo": 8, 597 "strVal": "more string", 598 } 599 err = session.Store(&m2) 600 assert.NoError(t, err) 601 602 err = session.SaveChanges() 603 assert.NoError(t, err) 604 605 meta, err := session.GetMetadataFor(m) 606 assertIllegalArgumentError(t, err, "instance can't be of type map[string]interface {}, try passing *map[string]interface {}") 607 assert.Nil(t, meta) 608 609 meta, err = session.GetMetadataFor(&m) 610 assert.NoError(t, err) 611 assert.NotNil(t, meta) 612 613 session.Close() 614 } 615 616 { 617 session := openSessionMust(t, store) 618 var mp *map[string]interface{} 619 err = session.Load(&mp, "maps/1") 620 assert.NoError(t, err) 621 m := *mp 622 assert.Equal(t, float64(5), m["foo"]) 623 assert.Equal(t, "a string", m["strVal"]) 624 625 session.Close() 626 } 627 } 628 629 func goTestFindCollectionName(t *testing.T) { 630 logTestName() 631 632 findCollectionName := func(entity interface{}) string { 633 if _, ok := entity.(*User); ok { 634 return "my users" 635 } 636 return ravendb.GetCollectionNameDefault(entity) 637 } 638 c := ravendb.NewDocumentConventions() 639 c.FindCollectionName = findCollectionName 640 name := c.GetCollectionName(&Employee{}) 641 assert.Equal(t, name, "Employees") 642 643 name = c.GetCollectionName(&User{}) 644 assert.Equal(t, name, "my users") 645 } 646 647 // test that insertion order of bulk_docs (BatchOperation / BatchCommand) 648 func goTestBatchCommandOrder(t *testing.T, driver *RavenTestDriver) { 649 logTestName() 650 651 var err error 652 store := driver.getDocumentStoreMust(t) 653 defer store.Close() 654 655 // delete to trigger a code path that uses deferred commands 656 // this is very sensitive to how code is structured: deleted 657 // commands are gathered first in random order and put 658 // commands are in insertion order 659 nUsers := 10 660 { 661 session := openSessionMust(t, store) 662 663 ids := []string{"users/5"} 664 for i := 1; i <= nUsers; i++ { 665 u := &User{ 666 Age: i, 667 } 668 u.setName(fmt.Sprintf("Name %d", i)) 669 id := fmt.Sprintf("users/%d", i) 670 err = session.StoreWithID(u, id) 671 assert.NoError(t, err) 672 if i == 5 { 673 err = session.Delete(u) 674 assert.NoError(t, err) 675 } else { 676 ids = append(ids, id) 677 } 678 } 679 commandsData, err := session.ForTestsSaveChangesGetCommands() 680 assert.NoError(t, err) 681 assert.Equal(t, len(commandsData), nUsers) 682 for i, cmdData := range commandsData { 683 var id string 684 switch d := cmdData.(type) { 685 case *ravendb.PutCommandDataWithJSON: 686 id = d.ID 687 case *ravendb.DeleteCommandData: 688 id = d.ID 689 } 690 expID := ids[i] 691 assert.Equal(t, expID, id) 692 assert.Equal(t, expID, id) 693 } 694 695 session.Close() 696 } 697 } 698 699 // test that we get a meaningful error for server exceptions sent as JSON response 700 // https://github.com/ravendb/ravendb-go-client/issues/147 701 func goTestInvalidIndexDefinition(t *testing.T, driver *RavenTestDriver) { 702 logTestName() 703 704 restore := disableLogFailedRequests() 705 defer restore() 706 707 var err error 708 store := driver.getDocumentStoreMust(t) 709 defer store.Close() 710 711 indexName := "Song/TextData" 712 index := ravendb.NewIndexCreationTask(indexName) 713 714 index.Map = ` 715 from song in docs.Songs 716 select { 717 SongData = new { 718 song.Artist, 719 song.Title, 720 song.Tags, 721 song.TrackId 722 } 723 } 724 ` 725 index.Index("SongData", ravendb.FieldIndexingSearch) 726 727 err = index.Execute(store, nil, "") 728 assert.Error(t, err) 729 _, ok := err.(*ravendb.IndexCompilationError) 730 assert.True(t, ok) 731 } 732 733 // increasing code coverage of bulk_insert_operation.go 734 func goTestBulkInsertCoverage(t *testing.T, driver *RavenTestDriver) { 735 logTestName() 736 737 var err error 738 store := driver.getDocumentStoreMust(t) 739 740 var orphanedInsert *ravendb.BulkInsertOperation 741 742 defer func() { 743 restore := disableLogFailedRequests() 744 store.Close() 745 err = orphanedInsert.Close() 746 assert.Error(t, err) 747 restore() 748 }() 749 750 { 751 752 bulkInsert := store.BulkInsert("") 753 o := &FooBar{ 754 Name: "John Doe", 755 } 756 // trigger BulkInsertOperation.escapeID 757 err = bulkInsert.StoreWithID(o, `FooBars/my-"-\id`, nil) 758 assert.NoError(t, err) 759 err = bulkInsert.Close() 760 assert.NoError(t, err) 761 } 762 763 { 764 bulkInsert := store.BulkInsert("") 765 o := &FooBar{ 766 Name: "John Doe", 767 } 768 err = bulkInsert.StoreWithID(o, ``, nil) 769 assert.Error(t, err) 770 err = bulkInsert.Close() 771 assert.NoError(t, err) 772 } 773 774 { 775 bulkInsert := store.BulkInsert("") 776 o := &FooBar{ 777 Name: "John Doe", 778 } 779 err = bulkInsert.StoreWithID(o, ``, nil) 780 assert.Error(t, err) 781 err = bulkInsert.Close() 782 assert.NoError(t, err) 783 } 784 785 { 786 bulkInsert := store.BulkInsert("") 787 o := &FooBar{ 788 Name: "John Doe", 789 } 790 // trigger a path in BulkInsertOperation.Store() that takes ID from metadata 791 m := map[string]interface{}{ 792 ravendb.MetadataID: "FooBars/id-frommeta", 793 } 794 meta := ravendb.NewMetadataAsDictionaryWithMetadata(m) 795 id, err := bulkInsert.Store(o, meta) 796 assert.Equal(t, "FooBars/id-frommeta", id) 797 assert.NoError(t, err) 798 err = bulkInsert.Close() 799 assert.NoError(t, err) 800 } 801 802 { 803 bulkInsert := store.BulkInsert("") 804 err = bulkInsert.Close() 805 assert.NoError(t, err) 806 } 807 808 { 809 orphanedInsert = store.BulkInsert("") 810 o := &FooBar{ 811 Name: "John Doe", 812 } 813 _, err = orphanedInsert.Store(o, nil) 814 assert.NoError(t, err) 815 } 816 817 { 818 // try to trigger concurrency check 819 bulkInsert := store.BulkInsert("") 820 var wg sync.WaitGroup 821 for i := 0; i < 5; i++ { 822 wg.Add(1) 823 go func() { 824 o := &FooBar{ 825 Name: "John Doe", 826 } 827 _, _ = bulkInsert.Store(o, nil) 828 wg.Done() 829 }() 830 } 831 wg.Wait() 832 833 err = bulkInsert.Close() 834 assert.NoError(t, err) 835 } 836 837 { 838 // trigger operationID == -1 code path in Abort 839 bulkInsert := store.BulkInsert("") 840 err = bulkInsert.Abort() 841 assert.NoError(t, err) 842 err = bulkInsert.Close() 843 assert.NoError(t, err) 844 } 845 846 } 847 848 // increasing code coverage of raw_document_query.go 849 func goTestRawQueryCoverage(t *testing.T, driver *RavenTestDriver) { 850 logTestName() 851 852 var err error 853 store := driver.getDocumentStoreMust(t) 854 createNorthwindDatabase(t, driver, store) 855 856 { 857 session := openSessionMust(t, store) 858 859 rawQuery := `from employees where FirstName == $p0` 860 q := session.RawQuery(rawQuery) 861 q = q.AddParameter("p0", "Anne") 862 assert.NoError(t, q.Err()) 863 // adding the same parameter twice generates an error 864 q = q.AddParameter("p0", "Anne") 865 assert.Error(t, q.Err()) 866 q = q.AddParameter("p0", "Anne") 867 assert.Error(t, q.Err()) 868 // trigger early error check 869 q = q.UsingDefaultOperator(ravendb.QueryOperatorAnd) 870 assert.Error(t, q.Err()) 871 872 // exercise error path in Any() 873 _, _ = q.Any() 874 875 session.Close() 876 } 877 878 { 879 restore := disableLogFailedRequests() 880 session := openSessionMust(t, store) 881 rawQuery := `from employees where FirstName == $p0` 882 q := session.RawQuery(rawQuery) 883 // a no-op but exercises the code path 884 q = q.UsingDefaultOperator(ravendb.QueryOperatorOr) 885 886 var results []*northwind.Employee 887 err = q.GetResults(&results) 888 assert.Error(t, err) 889 _, ok := err.(*ravendb.InvalidQueryError) 890 assert.True(t, ok) 891 892 session.Close() 893 restore() 894 } 895 896 { 897 session := openSessionMust(t, store) 898 899 rawQuery := `from employees where FirstName == $p0` 900 q := session.RawQuery(rawQuery) 901 q = q.AddParameter("p0", "Anne") 902 903 _, err = q.Any() 904 assert.NoError(t, err) 905 906 session.Close() 907 } 908 909 { 910 session := openSessionMust(t, store) 911 912 rawQuery := `from employees where FirstName == $p0` 913 q := session.RawQuery(rawQuery) 914 q = q.AddParameter("p0", "Anne") 915 q = q.WaitForNonStaleResultsWithTimeout(time.Second * 15) 916 q = q.WaitForNonStaleResults() 917 q = q.NoTracking() 918 q = q.NoCaching() 919 var stats *ravendb.QueryStatistics 920 q = q.Statistics(&stats) 921 922 nAfterQueryCalled := 0 923 afterQueryExecuted := func(r *ravendb.QueryResult) { 924 nAfterQueryCalled++ 925 } 926 927 afterQueryExecutedIdx := q.AddAfterQueryExecutedListener(afterQueryExecuted) 928 q = q.RemoveAfterQueryExecutedListener(afterQueryExecutedIdx) 929 930 afterQueryExecutedIdx1 := q.AddAfterQueryExecutedListener(afterQueryExecuted) 931 afterQueryExecutedIdx2 := q.AddAfterQueryExecutedListener(afterQueryExecuted) 932 933 nBeforeQueryCalled := 0 934 beforeQueryCalled := func(r *ravendb.IndexQuery) { 935 nBeforeQueryCalled++ 936 } 937 938 beforeQueryExecutedIdx := q.AddBeforeQueryExecutedListener(beforeQueryCalled) 939 q = q.RemoveBeforeQueryExecutedListener(beforeQueryExecutedIdx) 940 941 beforeQueryExecutedIdx1 := q.AddBeforeQueryExecutedListener(beforeQueryCalled) 942 beforeQueryExecutedIdx2 := q.AddBeforeQueryExecutedListener(beforeQueryCalled) 943 944 afterStreamExecuted := func(map[string]interface{}) { 945 // no-op 946 } 947 afterStreamExecutedIdx := q.AddAfterStreamExecutedListener(afterStreamExecuted) 948 949 var results []*northwind.Employee 950 err = q.GetResults(&results) 951 assert.NoError(t, err) 952 953 q = q.RemoveAfterQueryExecutedListener(afterQueryExecutedIdx1) 954 q = q.RemoveAfterQueryExecutedListener(afterQueryExecutedIdx2) 955 956 q = q.RemoveBeforeQueryExecutedListener(beforeQueryExecutedIdx1) 957 q = q.RemoveBeforeQueryExecutedListener(beforeQueryExecutedIdx2) 958 959 q = q.RemoveAfterStreamExecutedListener(afterStreamExecutedIdx) 960 assert.Equal(t, 2, nAfterQueryCalled) 961 assert.Equal(t, 2, nBeforeQueryCalled) 962 assert.NotNil(t, stats) 963 964 session.Close() 965 } 966 } 967 968 // increase code coverage in abstract_document_query.go etc. 969 func goTestQueryCoverage(t *testing.T, driver *RavenTestDriver) { 970 logTestName() 971 972 var err error 973 store := driver.getDocumentStoreMust(t) 974 createNorthwindDatabase(t, driver, store) 975 976 { 977 session := openSessionMust(t, store) 978 q := session.QueryCollection("empoloyees") 979 q = q.Distinct() 980 _, err = q.Any() 981 assert.NoError(t, err) 982 session.Close() 983 } 984 985 { 986 session := openSessionMust(t, store) 987 q := session.QueryCollection("empoloyees") 988 // trigger error condition in distinct() 989 q = q.Distinct() 990 q = q.Distinct() 991 assert.Error(t, q.Err()) 992 993 q = session.QueryCollection("empoloyees") 994 q = q.Where("LastName", "asd", "me") 995 assert.Error(t, q.Err()) 996 session.Close() 997 } 998 999 { 1000 session := openSessionMust(t, store) 1001 q := session.QueryCollection("empoloyees") 1002 q = q.Where("FirstName", "!=", "zzz") 1003 q = q.Where("FirstName", "<", "Zorro") 1004 q = q.Where("FirstName", "<=", "Zorro") 1005 q = q.Where("FirstName", ">", "Aha") 1006 q = q.Where("FirstName", ">=", "Aha") 1007 q = q.RandomOrderingWithSeed("") 1008 1009 var results []*northwind.Employee 1010 err = q.GetResults(&results) 1011 assert.NoError(t, err) 1012 1013 session.Close() 1014 } 1015 1016 } 1017 1018 func goTestLazyCoverage(t *testing.T, driver *RavenTestDriver) { 1019 var err error 1020 store := driver.getDocumentStoreMust(t) 1021 defer store.Close() 1022 1023 { 1024 session := openSessionMust(t, store) 1025 for i := 1; i <= 2; i++ { 1026 company := &Company{ 1027 ID: fmt.Sprintf("companies/%d", i), 1028 } 1029 err = session.StoreWithID(company, company.ID) 1030 assert.NoError(t, err) 1031 } 1032 1033 err = session.SaveChanges() 1034 assert.NoError(t, err) 1035 1036 session.Close() 1037 } 1038 1039 { 1040 session := openSessionMust(t, store) 1041 1042 user := User5{ 1043 Name: "Ayende", 1044 } 1045 err = session.Store(&user) 1046 assert.NoError(t, err) 1047 1048 partner := User5{ 1049 PartnerID: "user5s/1-A", 1050 } 1051 err = session.Store(&partner) 1052 assert.NoError(t, err) 1053 1054 err = session.SaveChanges() 1055 assert.NoError(t, err) 1056 1057 session.Close() 1058 } 1059 1060 { 1061 session := openSessionMust(t, store) 1062 1063 fn1 := func() { 1064 // no-op 1065 } 1066 1067 var company1Ref *Company 1068 1069 query := session.Advanced().Lazily() 1070 // returns error on empty id 1071 lazy, err := query.LoadWithEval("", fn1, &company1Ref) 1072 assert.Error(t, err) 1073 assert.Nil(t, lazy) 1074 1075 // returns error on empty ids 1076 lazy, err = query.LoadMulti(nil) 1077 assert.Error(t, err) 1078 assert.Nil(t, lazy) 1079 1080 // returns error on empty ids 1081 lazy, err = query.LoadMultiWithEval(nil, fn1, nil) 1082 assert.Error(t, err) 1083 assert.Nil(t, lazy) 1084 1085 var c *Company 1086 err = session.Load(&c, "companies/1") 1087 assert.NoError(t, err) 1088 assert.Equal(t, c.ID, "companies/1") 1089 1090 // trigger o.delegate.IsLoaded(id) code path in LoadWithEval 1091 { 1092 query := session.Advanced().Lazily() 1093 lazy, err := query.LoadWithEval("companies/1", fn1, &company1Ref) 1094 assert.NoError(t, err) 1095 1096 var c1 *Company 1097 err = lazy.GetValue(&c1) 1098 assert.NoError(t, err) 1099 assert.Equal(t, c.ID, "companies/1") 1100 } 1101 1102 { 1103 session := openSessionMust(t, store) 1104 1105 advanced := session.Advanced() 1106 _, err = advanced.Lazily().Load("user5s/2-A") 1107 assert.NoError(t, err) 1108 _, err = advanced.Lazily().Load("user5s/1-A") 1109 assert.NoError(t, err) 1110 1111 _, err = advanced.Eagerly().ExecuteAllPendingLazyOperations() 1112 assert.NoError(t, err) 1113 1114 oldCount := advanced.GetNumberOfRequests() 1115 1116 resultLazy, err := advanced.Lazily().Include("PartnerId").Load("user5s/2-A") 1117 assert.NoError(t, err) 1118 var user *User 1119 err = resultLazy.GetValue(&user) 1120 assert.NoError(t, err) 1121 assert.NotNil(t, user) 1122 assert.Equal(t, user.ID, "user5s/2-A") 1123 1124 newCount := advanced.GetNumberOfRequests() 1125 assert.Equal(t, newCount, oldCount) 1126 1127 session.Close() 1128 } 1129 1130 session.Close() 1131 } 1132 1133 { 1134 session := openSessionMust(t, store) 1135 1136 advanced := session.Advanced() 1137 1138 { 1139 // empty id returns an error 1140 resultLazy, err := advanced.Lazily().Include("PartnerId").Load("") 1141 assert.Error(t, err) 1142 assert.Nil(t, resultLazy) 1143 } 1144 1145 { 1146 // empty ids returns an error 1147 resultLazy, err := advanced.Lazily().Include("PartnerId").LoadMulti(nil) 1148 assert.Error(t, err) 1149 assert.Nil(t, resultLazy) 1150 1151 resultLazy, err = advanced.Lazily().Include("PartnerId").LoadMulti([]string{}) 1152 assert.Error(t, err) 1153 assert.Nil(t, resultLazy) 1154 } 1155 1156 { 1157 resultLazy, err := advanced.Lazily().Include("PartnerId").LoadMulti([]string{"user5s/2-A", "user5s/1-A"}) 1158 assert.NoError(t, err) 1159 err = resultLazy.GetValue(nil) 1160 assert.Error(t, err) 1161 } 1162 1163 { 1164 resultLazy, err := advanced.Lazily().Include("PartnerId").LoadMulti([]string{"user5s/2-A", "user5s/1-A"}) 1165 assert.NoError(t, err) 1166 results := map[string]*User5{} 1167 err = resultLazy.GetValue(results) 1168 assert.NoError(t, err) 1169 assert.Equal(t, 2, len(results)) 1170 } 1171 1172 { 1173 resultLazy, err := advanced.Lazily().Include("PartnerId").LoadMulti([]string{"user5s/2-A", "user5s/1-A"}) 1174 assert.NoError(t, err) 1175 results := map[string]*User{} 1176 // trying to get a mismatched type. has User5, we're trying to get User 1177 err = resultLazy.GetValue(results) 1178 assert.Error(t, err) 1179 assert.Equal(t, len(results), 0) 1180 } 1181 1182 session.Close() 1183 } 1184 1185 } 1186 1187 func TestGo1(t *testing.T) { 1188 driver := createTestDriver(t) 1189 destroy := func() { destroyDriver(t, driver) } 1190 defer recoverTest(t, destroy) 1191 1192 if false { 1193 goTestStoreMap(t, driver) 1194 goTest(t, driver) 1195 goTestGetLastModifiedForAndChanges(t, driver) 1196 goTestListeners(t, driver) 1197 goTestFindCollectionName(t) 1198 goTestBatchCommandOrder(t, driver) 1199 goTestInvalidIndexDefinition(t, driver) 1200 goTestBulkInsertCoverage(t, driver) 1201 goTestRawQueryCoverage(t, driver) 1202 goTestQueryCoverage(t, driver) 1203 } 1204 goTestLazyCoverage(t, driver) 1205 }