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  }