github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/model/model_test.go (about)

     1  package model
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"sort"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/gofrs/uuid"
    11  	fs "github.com/tickoalcantara12/micro/v3/service/store/file"
    12  )
    13  
    14  type User struct {
    15  	ID      string `json:"id"`
    16  	Age     int    `json:"age"`
    17  	HasPet  bool   `json:"hasPet"`
    18  	Created int64  `json:"created"`
    19  	Tag     string `json:"tag"`
    20  	Updated int64  `json:"updated"`
    21  }
    22  
    23  func TestQueryEqualsByID(t *testing.T) {
    24  	table := New(User{}, &Options{
    25  		Store:     fs.NewStore(),
    26  		Namespace: uuid.Must(uuid.NewV4()).String(),
    27  	})
    28  
    29  	err := table.Create(User{
    30  		ID:  "1",
    31  		Age: 12,
    32  	})
    33  	if err != nil {
    34  		t.Fatal(err)
    35  	}
    36  	err = table.Create(User{
    37  		ID:  "2",
    38  		Age: 25,
    39  	})
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	users := []User{}
    44  	q := QueryEquals("ID", "1")
    45  	q.Order.Type = OrderTypeUnordered
    46  	err = table.Read(q, &users)
    47  	if err != nil {
    48  		t.Fatal(err)
    49  	}
    50  	if len(users) != 1 {
    51  		t.Fatal(users)
    52  	}
    53  }
    54  
    55  type User1 struct {
    56  	Id      string `json:"id"`
    57  	Age     int    `json:"age"`
    58  	HasPet  bool   `json:"hasPet"`
    59  	Created int64  `json:"created"`
    60  	Tag     string `json:"tag"`
    61  	Updated int64  `json:"updated"`
    62  }
    63  
    64  func TestQueryEqualsLowerCaseID(t *testing.T) {
    65  	table := New(&User1{}, &Options{
    66  		Store:     fs.NewStore(),
    67  		Namespace: uuid.Must(uuid.NewV4()).String(),
    68  	})
    69  
    70  	// pointer insert
    71  	err := table.Create(&User1{
    72  		Id:  "1",
    73  		Age: 12,
    74  	})
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	err = table.Create(User1{
    79  		Id:  "2",
    80  		Age: 25,
    81  	})
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  	users := []User1{}
    86  	q := QueryEquals("Id", "1")
    87  	q.Order.Type = OrderTypeUnordered
    88  	err = table.Read(q, &users)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	if len(users) != 1 {
    93  		t.Fatal(users)
    94  	}
    95  }
    96  
    97  func TestQueryEqualsMismatchIDCapitalization(t *testing.T) {
    98  	table := New(&User1{}, &Options{
    99  		Store:     fs.NewStore(),
   100  		Namespace: uuid.Must(uuid.NewV4()).String(),
   101  	})
   102  
   103  	// pointer insert
   104  	err := table.Create(&User1{
   105  		Id:  "1",
   106  		Age: 12,
   107  	})
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	err = table.Create(User1{
   112  		Id:  "2",
   113  		Age: 25,
   114  	})
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	users := []User1{}
   119  	q := QueryEquals("id", "1")
   120  	q.Order.Type = OrderTypeUnordered
   121  	err = table.Read(q, &users)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	if len(users) != 1 {
   126  		t.Fatal(users)
   127  	}
   128  }
   129  
   130  func TestQueryEqualsByIDMap(t *testing.T) {
   131  	m := map[string]interface{}{
   132  		"ID":      "id",
   133  		"age":     1,
   134  		"hasPet":  true,
   135  		"created": 1,
   136  		"tag":     "tag",
   137  		"updated": 1,
   138  	}
   139  	table := New(m, &Options{
   140  		Store:     fs.NewStore(),
   141  		Namespace: uuid.Must(uuid.NewV4()).String(),
   142  	})
   143  
   144  	err := table.Create(map[string]interface{}{
   145  		"ID":  "1",
   146  		"Age": 12,
   147  	})
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	err = table.Create(map[string]interface{}{
   152  		"ID":  "2",
   153  		"Age": 25,
   154  	})
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	users := []map[string]interface{}{}
   159  	q := QueryEquals("ID", "1")
   160  	q.Order.Type = OrderTypeUnordered
   161  	err = table.Read(q, &users)
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	if len(users) != 1 {
   166  		t.Fatal(users)
   167  	}
   168  }
   169  
   170  func TestQueryEqualsByIDMapNoSchemaWithIndexes(t *testing.T) {
   171  	m := map[string]interface{}{}
   172  	table := New(m, &Options{
   173  		Store:     fs.NewStore(),
   174  		Namespace: uuid.Must(uuid.NewV4()).String(),
   175  		Indexes:   []Index{ByEquality("Age")},
   176  	})
   177  
   178  	err := table.Create(map[string]interface{}{
   179  		"ID":  "1",
   180  		"Age": 12,
   181  	})
   182  	if err != nil {
   183  		t.Fatal(err)
   184  	}
   185  	err = table.Create(map[string]interface{}{
   186  		"ID":  "2",
   187  		"Age": 25,
   188  	})
   189  	if err != nil {
   190  		t.Fatal(err)
   191  	}
   192  	users := []map[string]interface{}{}
   193  	q := QueryEquals("ID", "1")
   194  	q.Order.Type = OrderTypeUnordered
   195  	err = table.Read(q, &users)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	if len(users) != 1 {
   200  		t.Fatal(users)
   201  	}
   202  }
   203  
   204  func TestListAllMap(t *testing.T) {
   205  	m := map[string]interface{}{
   206  		"ID":      "id",
   207  		"age":     1,
   208  		"hasPet":  true,
   209  		"created": 1,
   210  		"tag":     "tag",
   211  		"updated": 1,
   212  	}
   213  	table := New(m, &Options{
   214  		Store:     fs.NewStore(),
   215  		Namespace: uuid.Must(uuid.NewV4()).String(),
   216  	})
   217  
   218  	err := table.Create(map[string]interface{}{
   219  		"ID":  "1",
   220  		"Age": 12,
   221  	})
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  	err = table.Create(map[string]interface{}{
   226  		"ID":  "2",
   227  		"Age": 25,
   228  	})
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  	users := []map[string]interface{}{}
   233  	q := QueryAll()
   234  	err = table.Read(q, &users)
   235  	if err != nil {
   236  		t.Fatal(err)
   237  	}
   238  	if len(users) != 2 {
   239  		t.Fatal(users)
   240  	}
   241  }
   242  
   243  func TestListAllMapCutomID(t *testing.T) {
   244  	m := map[string]interface{}{
   245  		"name":    "id",
   246  		"age":     1,
   247  		"hasPet":  true,
   248  		"created": 1,
   249  		"tag":     "tag",
   250  		"updated": 1,
   251  	}
   252  	table := New(m, &Options{
   253  		Store:     fs.NewStore(),
   254  		Key:       "name",
   255  		Namespace: uuid.Must(uuid.NewV4()).String(),
   256  	})
   257  
   258  	err := table.Create(map[string]interface{}{
   259  		"name": "1",
   260  		"age":  12,
   261  	})
   262  	if err != nil {
   263  		t.Fatal(err)
   264  	}
   265  	err = table.Create(map[string]interface{}{
   266  		"name": "2",
   267  		"age":  25,
   268  	})
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	users := []map[string]interface{}{}
   273  	q := QueryAll()
   274  	err = table.Read(q, &users)
   275  	if err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	if len(users) != 2 {
   279  		t.Fatal(users)
   280  	}
   281  }
   282  
   283  func TestListLimitMap(t *testing.T) {
   284  	ageAsc := ByEquality("age")
   285  	ageAsc.Order.Type = OrderTypeAsc
   286  
   287  	ageDesc := ByEquality("age")
   288  	ageDesc.Order.Type = OrderTypeDesc
   289  
   290  	m := map[string]interface{}{
   291  		"ID":      "id",
   292  		"age":     1,
   293  		"hasPet":  true,
   294  		"created": 1,
   295  		"tag":     "tag",
   296  		"updated": 1,
   297  	}
   298  	table := New(m, &Options{
   299  		Store:     fs.NewStore(),
   300  		Indexes:   []Index{ageAsc, ageDesc},
   301  		Namespace: uuid.Must(uuid.NewV4()).String(),
   302  	})
   303  
   304  	err := table.Create(map[string]interface{}{
   305  		"ID":  "1",
   306  		"age": 12,
   307  	})
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  	err = table.Create(map[string]interface{}{
   312  		"ID":  "2",
   313  		"age": 25,
   314  	})
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	err = table.Create(map[string]interface{}{
   319  		"ID":  "3",
   320  		"age": 35,
   321  	})
   322  	if err != nil {
   323  		t.Fatal(err)
   324  	}
   325  	users := []map[string]interface{}{}
   326  	q := QueryAll()
   327  	q.Limit = 1
   328  	err = table.Read(q, &users)
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  	if len(users) != 1 {
   333  		t.Fatal(users)
   334  	}
   335  
   336  	q = ageDesc.ToQuery(nil)
   337  	q.Limit = 1
   338  	err = table.Read(q, &users)
   339  	if err != nil {
   340  		t.Fatal(err)
   341  	}
   342  	if len(users) != 1 {
   343  		t.Fatal(users)
   344  	}
   345  	if users[0]["age"].(float64) != 35 {
   346  		t.Fatal(users[0])
   347  	}
   348  
   349  	q = ageAsc.ToQuery(nil)
   350  	q.Limit = 1
   351  	err = table.Read(q, &users)
   352  	if err != nil {
   353  		t.Fatal(err)
   354  	}
   355  	if len(users) != 1 {
   356  		t.Fatal(users)
   357  	}
   358  	if users[0]["age"].(float64) != 12 {
   359  		t.Fatal(users[0])
   360  	}
   361  }
   362  
   363  // TestNewModel tests the creation using NewModel and Register
   364  func TestNewModel(t *testing.T) {
   365  	// create a new model
   366  	table := NewModel(
   367  		WithStore(fs.NewStore()),
   368  		WithNamespace(uuid.Must(uuid.NewV4()).String()),
   369  	)
   370  
   371  	// register the instance
   372  	table.Register(User{})
   373  
   374  	err := table.Create(User{
   375  		ID:  "1",
   376  		Age: 12,
   377  	})
   378  	if err != nil {
   379  		t.Fatal(err)
   380  	}
   381  	err = table.Create(User{
   382  		ID:  "2",
   383  		Age: 25,
   384  	})
   385  	if err != nil {
   386  		t.Fatal(err)
   387  	}
   388  	users := []User{}
   389  	q := QueryEquals("ID", "1")
   390  	q.Order.Type = OrderTypeUnordered
   391  	err = table.Read(q, &users)
   392  	if err != nil {
   393  		t.Fatal(err)
   394  	}
   395  	if len(users) != 1 {
   396  		t.Fatal(users)
   397  	}
   398  }
   399  
   400  func TestRead(t *testing.T) {
   401  	table := New(User{}, &Options{
   402  		Store:     fs.NewStore(),
   403  		Indexes:   []Index{ByEquality("age")},
   404  		Namespace: uuid.Must(uuid.NewV4()).String(),
   405  	})
   406  	user := User{}
   407  	// intentionally querying Age to test case tolerance
   408  	err := table.Read(QueryEquals("Age", 25), &user)
   409  	if err != ErrorNotFound {
   410  		t.Fatal(err)
   411  	}
   412  
   413  	// test pointer create
   414  	err = table.Create(&User{
   415  		ID:  "1",
   416  		Age: 25,
   417  	})
   418  	if err != nil {
   419  		t.Fatal(err)
   420  	}
   421  
   422  	err = table.Read(QueryEquals("age", 25), &user)
   423  	if err != nil {
   424  		t.Fatal(err)
   425  	}
   426  	if user.ID != "1" {
   427  		t.Fatal(user)
   428  	}
   429  
   430  	err = table.Create(User{
   431  		ID:  "2",
   432  		Age: 25,
   433  	})
   434  	if err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	err = table.Read(QueryEquals("age", 25), &user)
   439  	if err == ErrorMultipleRecordsFound {
   440  		t.Fatal(err)
   441  	}
   442  }
   443  
   444  func TestQueryEquals(t *testing.T) {
   445  	table := New(User{}, &Options{
   446  		Store:     fs.NewStore(),
   447  		Indexes:   []Index{ByEquality("age")},
   448  		Namespace: uuid.Must(uuid.NewV4()).String(),
   449  	})
   450  
   451  	err := table.Create(User{
   452  		ID:  "1",
   453  		Age: 12,
   454  	})
   455  	if err != nil {
   456  		t.Fatal(err)
   457  	}
   458  	err = table.Create(User{
   459  		ID:  "2",
   460  		Age: 25,
   461  	})
   462  	if err != nil {
   463  		t.Fatal(err)
   464  	}
   465  	err = table.Create(User{
   466  		ID:  "3",
   467  		Age: 12,
   468  	})
   469  	if err != nil {
   470  		t.Fatal(err)
   471  	}
   472  	users := []User{}
   473  	err = table.Read(QueryEquals("age", 12), &users)
   474  	if err != nil {
   475  		t.Fatal(err)
   476  	}
   477  	if len(users) != 2 {
   478  		t.Fatal(users)
   479  	}
   480  }
   481  
   482  func reverse(ss []string) {
   483  	last := len(ss) - 1
   484  	for i := 0; i < len(ss)/2; i++ {
   485  		ss[i], ss[last-i] = ss[last-i], ss[i]
   486  	}
   487  }
   488  
   489  func TestOrderingStrings(t *testing.T) {
   490  	type caze struct {
   491  		tags    []string
   492  		reverse bool
   493  	}
   494  	cazes := []caze{
   495  		{
   496  			tags:    []string{"2", "1"},
   497  			reverse: false,
   498  		},
   499  		{
   500  			tags:    []string{"2", "1"},
   501  			reverse: true,
   502  		},
   503  		{
   504  
   505  			tags:    []string{"abcd", "abcde", "abcdf"},
   506  			reverse: false,
   507  		},
   508  		{
   509  			tags:    []string{"abcd", "abcde", "abcdf"},
   510  			reverse: true,
   511  		},
   512  		{
   513  			tags:    []string{"2", "abcd", "abcde", "abcdf", "1"},
   514  			reverse: false,
   515  		},
   516  		{
   517  			tags:    []string{"2", "abcd", "abcde", "abcdf", "1"},
   518  			reverse: true,
   519  		},
   520  	}
   521  	for _, c := range cazes {
   522  		tagIndex := ByEquality("tag")
   523  		if c.reverse {
   524  			tagIndex.Order.Type = OrderTypeDesc
   525  		}
   526  		tagIndex.StringOrderPadLength = 12
   527  		table := New(User{}, &Options{
   528  			Store:     fs.NewStore(),
   529  			Indexes:   []Index{tagIndex},
   530  			Namespace: uuid.Must(uuid.NewV4()).String(),
   531  		})
   532  		for _, key := range c.tags {
   533  			err := table.Create(User{
   534  				ID:  uuid.Must(uuid.NewV4()).String(),
   535  				Tag: key,
   536  			})
   537  			if err != nil {
   538  				t.Fatal(err)
   539  			}
   540  		}
   541  		users := []User{}
   542  		q := QueryEquals("tag", nil)
   543  		if c.reverse {
   544  			q.Order.Type = OrderTypeDesc
   545  		}
   546  		err := table.Read(q, &users)
   547  		if err != nil {
   548  			t.Fatal(err)
   549  		}
   550  
   551  		tags := sort.StringSlice(c.tags)
   552  		sort.Sort(tags)
   553  		if c.reverse {
   554  			reverse(tags)
   555  		}
   556  		if len(tags) != len(users) {
   557  			t.Fatal(tags, users)
   558  		}
   559  		for i, key := range tags {
   560  			if users[i].Tag != key {
   561  				userTags := []string{}
   562  				for _, v := range users {
   563  					userTags = append(userTags, v.Tag)
   564  				}
   565  				t.Fatalf("Should be %v, got %v, is reverse: %v", tags, userTags, c.reverse)
   566  			}
   567  		}
   568  	}
   569  
   570  }
   571  
   572  func reverseInt(is []int) {
   573  	last := len(is) - 1
   574  	for i := 0; i < len(is)/2; i++ {
   575  		is[i], is[last-i] = is[last-i], is[i]
   576  	}
   577  }
   578  
   579  func TestOrderingNumbers(t *testing.T) {
   580  	type caze struct {
   581  		dates   []int
   582  		reverse bool
   583  	}
   584  	cazes := []caze{
   585  		{
   586  			dates:   []int{20, 30},
   587  			reverse: false,
   588  		},
   589  		{
   590  			dates:   []int{20, 30},
   591  			reverse: true,
   592  		},
   593  	}
   594  	for _, c := range cazes {
   595  		createdIndex := ByEquality("created")
   596  		if c.reverse {
   597  			createdIndex.Order.Type = OrderTypeDesc
   598  		}
   599  		table := New(User{}, &Options{
   600  			Store:     fs.NewStore(),
   601  			Indexes:   []Index{createdIndex},
   602  			Namespace: uuid.Must(uuid.NewV4()).String(),
   603  		})
   604  		for _, key := range c.dates {
   605  			err := table.Create(User{
   606  				ID:      uuid.Must(uuid.NewV4()).String(),
   607  				Created: int64(key),
   608  			})
   609  			if err != nil {
   610  				t.Fatal(err)
   611  			}
   612  		}
   613  		users := []User{}
   614  		q := QueryEquals("created", nil)
   615  		if c.reverse {
   616  			q.Order.Type = OrderTypeDesc
   617  		}
   618  		err := table.Read(q, &users)
   619  		if err != nil {
   620  			t.Fatal(err)
   621  		}
   622  
   623  		dates := sort.IntSlice(c.dates)
   624  		sort.Sort(dates)
   625  		if c.reverse {
   626  			reverseInt([]int(dates))
   627  		}
   628  		if len(users) != len(dates) {
   629  			t.Fatalf("Expected %v, got %v", len(dates), len(users))
   630  		}
   631  		for i, date := range dates {
   632  			if users[i].Created != int64(date) {
   633  				userDates := []int{}
   634  				for _, v := range users {
   635  					userDates = append(userDates, int(v.Created))
   636  				}
   637  				t.Fatalf("Should be %v, got %v, is reverse: %v", dates, userDates, c.reverse)
   638  			}
   639  		}
   640  	}
   641  
   642  }
   643  
   644  func TestStaleIndexRemoval(t *testing.T) {
   645  	tagIndex := ByEquality("tag")
   646  	table := New(User{}, &Options{
   647  		Store:     fs.NewStore(),
   648  		Indexes:   []Index{tagIndex},
   649  		Namespace: uuid.Must(uuid.NewV4()).String(),
   650  	})
   651  	err := table.Create(User{
   652  		ID:  "1",
   653  		Tag: "hi-there",
   654  	})
   655  	if err != nil {
   656  		t.Fatal(err)
   657  	}
   658  	err = table.Create(User{
   659  		ID:  "1",
   660  		Tag: "hello-there",
   661  	})
   662  	if err != nil {
   663  		t.Fatal(err)
   664  	}
   665  	res := []User{}
   666  	err = table.Read(QueryEquals("tag", nil), &res)
   667  	if err != nil {
   668  		t.Fatal(err)
   669  	}
   670  	if len(res) > 1 {
   671  		t.Fatal(res)
   672  	}
   673  }
   674  
   675  func TestUniqueIndex(t *testing.T) {
   676  	tagIndex := ByEquality("tag")
   677  	tagIndex.Unique = true
   678  	table := New(User{}, &Options{
   679  		Store:     fs.NewStore(),
   680  		Indexes:   []Index{tagIndex},
   681  		Namespace: uuid.Must(uuid.NewV4()).String(),
   682  	})
   683  	err := table.Create(User{
   684  		ID:  "1",
   685  		Tag: "hi-there",
   686  	})
   687  	if err != nil {
   688  		t.Fatal(err)
   689  	}
   690  	err = table.Create(User{
   691  		ID:  "2",
   692  		Tag: "hello-there",
   693  	})
   694  	if err != nil {
   695  		t.Fatal(err)
   696  	}
   697  	err = table.Create(User{
   698  		ID:  "3",
   699  		Tag: "hi-there",
   700  	})
   701  	if err == nil {
   702  		t.Fatal("Create shoud fail with duplicate tag error because the index is unique")
   703  	}
   704  }
   705  
   706  type Tag struct {
   707  	Slug string `json:"slug"`
   708  	Age  int    `json:"age"`
   709  	Type string `json:"type"`
   710  }
   711  
   712  func TestNonIDKeys(t *testing.T) {
   713  	table := New(Tag{}, &Options{
   714  		Store:     fs.NewStore(),
   715  		Key:       "slug",
   716  		Namespace: uuid.Must(uuid.NewV4()).String(),
   717  	})
   718  
   719  	err := table.Create(Tag{
   720  		Slug: "1",
   721  		Age:  12,
   722  	})
   723  	if err != nil {
   724  		t.Fatal(err)
   725  	}
   726  	err = table.Create(Tag{
   727  		Slug: "2",
   728  		Age:  25,
   729  	})
   730  	if err != nil {
   731  		t.Fatal(err)
   732  	}
   733  	users := []User{}
   734  	q := QueryEquals("slug", "1")
   735  	q.Order.Type = OrderTypeUnordered
   736  	err = table.Read(q, &users)
   737  	if err != nil {
   738  		t.Fatal(err)
   739  	}
   740  	if len(users) != 1 {
   741  		t.Fatal(users)
   742  	}
   743  }
   744  
   745  // This might be an almost duplicate test, I used it to try reproduce an issue
   746  // Leaving this here for now as we dont have enough tests anyway.
   747  func TestReadByString(t *testing.T) {
   748  	typeIndex := ByEquality("type")
   749  
   750  	table := New(Tag{}, &Options{
   751  		Key:       "slug",
   752  		Store:     fs.NewStore(),
   753  		Indexes:   []Index{typeIndex},
   754  		Debug:     false,
   755  		Namespace: uuid.Must(uuid.NewV4()).String(),
   756  	})
   757  
   758  	err := table.Create(Tag{
   759  		Slug: "1",
   760  		Type: "post-tag",
   761  	})
   762  	if err != nil {
   763  		t.Fatal(err)
   764  	}
   765  	err = table.Create(Tag{
   766  		Slug: "2",
   767  		Type: "post-tag",
   768  	})
   769  	if err != nil {
   770  		t.Fatal(err)
   771  	}
   772  	tags := []Tag{}
   773  	q := QueryEquals("type", "post-tag")
   774  	err = table.Read(q, &tags)
   775  	if err != nil {
   776  		t.Fatal(err)
   777  	}
   778  	if len(tags) != 2 {
   779  		t.Fatal(tags)
   780  	}
   781  }
   782  
   783  func TestOderByDifferentFieldThanFilterField(t *testing.T) {
   784  	typeIndex := ByEquality("type")
   785  	typeIndex.Order = Order{
   786  		Type:      OrderTypeDesc,
   787  		FieldName: "age",
   788  	}
   789  
   790  	table := New(Tag{}, &Options{
   791  		Key:       "slug",
   792  		Store:     fs.NewStore(),
   793  		Indexes:   []Index{typeIndex},
   794  		Namespace: uuid.Must(uuid.NewV4()).String(),
   795  		Debug:     false,
   796  	})
   797  
   798  	err := table.Create(Tag{
   799  		Slug: "1",
   800  		Type: "post-tag",
   801  		Age:  15,
   802  	})
   803  	if err != nil {
   804  		t.Fatal(err)
   805  	}
   806  	err = table.Create(Tag{
   807  		Slug: "2",
   808  		Type: "post-tag",
   809  		Age:  25,
   810  	})
   811  	if err != nil {
   812  		t.Fatal(err)
   813  	}
   814  	err = table.Create(Tag{
   815  		Slug: "3",
   816  		Type: "other-tag",
   817  		Age:  30,
   818  	})
   819  	if err != nil {
   820  		t.Fatal(err)
   821  	}
   822  	tags := []Tag{}
   823  	err = table.Read(typeIndex.ToQuery("post-tag"), &tags)
   824  	if err != nil {
   825  		t.Fatal(err)
   826  	}
   827  	if len(tags) != 2 {
   828  		t.Fatal(tags)
   829  	}
   830  	if tags[0].Age != 25 {
   831  		t.Fatal(tags)
   832  	}
   833  	if tags[1].Age != 15 {
   834  		t.Fatal(tags)
   835  	}
   836  
   837  	err = table.Read(typeIndex.ToQuery(nil), &tags)
   838  	if err != nil {
   839  		t.Fatal(err)
   840  	}
   841  	if len(tags) != 3 {
   842  		t.Fatal(tags)
   843  	}
   844  }
   845  
   846  func TestDeleteIndexCleanup(t *testing.T) {
   847  	slugIndex := ByEquality("slug")
   848  	slugIndex.Order.Type = OrderTypeUnordered
   849  
   850  	typeIndex := ByEquality("type")
   851  
   852  	table := New(Tag{}, &Options{
   853  		Key:       "slug",
   854  		Store:     fs.NewStore(),
   855  		Indexes:   []Index{typeIndex},
   856  		Namespace: uuid.Must(uuid.NewV4()).String(),
   857  		Debug:     false,
   858  	})
   859  
   860  	err := table.Create(Tag{
   861  		Slug: "1",
   862  		Type: "post-tag",
   863  	})
   864  	if err != nil {
   865  		t.Fatal(err)
   866  	}
   867  	err = table.Create(Tag{
   868  		Slug: "2",
   869  		Type: "post-tag",
   870  	})
   871  	if err != nil {
   872  		t.Fatal(err)
   873  	}
   874  	tags := []Tag{}
   875  	q := QueryEquals("type", "post-tag")
   876  	err = table.Read(q, &tags)
   877  	if err != nil {
   878  		t.Fatal(err)
   879  	}
   880  	if len(tags) != 2 {
   881  		t.Fatal(tags)
   882  	}
   883  
   884  	err = table.Delete(slugIndex.ToQuery("1"))
   885  	if err != nil {
   886  		t.Fatal(err)
   887  	}
   888  
   889  	q = QueryEquals("type", "post-tag")
   890  	err = table.Read(q, &tags)
   891  	if err != nil {
   892  		t.Fatal(err)
   893  	}
   894  	if len(tags) != 1 {
   895  		t.Fatal(tags)
   896  	}
   897  }
   898  
   899  func TestDeleteByUnmatchingIndex(t *testing.T) {
   900  	table := New(User{}, &Options{
   901  		Store:     fs.NewStore(),
   902  		Namespace: uuid.Must(uuid.NewV4()).String(),
   903  		Debug:     false,
   904  	})
   905  
   906  	err := table.Create(User{
   907  		ID:  "1",
   908  		Age: 20,
   909  	})
   910  	if err != nil {
   911  		t.Fatal(err)
   912  	}
   913  	err = table.Create(User{
   914  		ID:  "2",
   915  		Age: 30,
   916  	})
   917  	if err != nil {
   918  		t.Fatal(err)
   919  	}
   920  
   921  	err = table.Delete(QueryEquals("ID", "1"))
   922  	if err != nil {
   923  		t.Fatal(err)
   924  	}
   925  	t.Run("Test read by unspecified index", func(t *testing.T) {
   926  		users := []User{}
   927  		err = table.Read(QueryEquals("ID", "1"), &users)
   928  		if err != nil {
   929  			t.Fatal(err)
   930  		}
   931  		if len(users) != 0 {
   932  			t.Fatal(users)
   933  		}
   934  		err = table.Read(QueryEquals("ID", "2"), &users)
   935  		if err != nil {
   936  			t.Fatal(err)
   937  		}
   938  		if len(users) != 1 {
   939  			t.Fatal(users)
   940  		}
   941  	})
   942  }
   943  
   944  func TestDeleteByUnmatchingIndexMap(t *testing.T) {
   945  	table := New(map[string]interface{}{}, &Options{
   946  		Store:     fs.NewStore(),
   947  		Namespace: uuid.Must(uuid.NewV4()).String(),
   948  		Debug:     false,
   949  	})
   950  
   951  	err := table.Create(map[string]interface{}{
   952  		"ID":  "1",
   953  		"Age": 20,
   954  	})
   955  	if err != nil {
   956  		t.Fatal(err)
   957  	}
   958  	err = table.Create(map[string]interface{}{
   959  		"ID":  "2",
   960  		"Age": 30,
   961  	})
   962  	if err != nil {
   963  		t.Fatal(err)
   964  	}
   965  
   966  	err = table.Delete(QueryEquals("ID", "1"))
   967  	if err != nil {
   968  		t.Fatal(err)
   969  	}
   970  	t.Run("Test read by unspecified index", func(t *testing.T) {
   971  		users := []map[string]interface{}{}
   972  		err = table.Read(QueryEquals("ID", "1"), &users)
   973  		if err != nil {
   974  			t.Fatal(err)
   975  		}
   976  		if len(users) != 0 {
   977  			t.Fatal(users)
   978  		}
   979  		err = table.Read(QueryEquals("ID", "2"), &users)
   980  		if err != nil {
   981  			t.Fatal(err)
   982  		}
   983  		if len(users) != 1 {
   984  			t.Fatal(users)
   985  		}
   986  	})
   987  }
   988  
   989  func TestUpdateDeleteIndexMaintenance(t *testing.T) {
   990  	updIndex := ByEquality("updated")
   991  	updIndex.Order.Type = OrderTypeDesc
   992  
   993  	table := New(User{}, &Options{
   994  		Store:     fs.NewStore(),
   995  		Indexes:   []Index{updIndex},
   996  		Namespace: uuid.Must(uuid.NewV4()).String(),
   997  		Debug:     false,
   998  	})
   999  
  1000  	err := table.Create(User{
  1001  		ID:      "1",
  1002  		Age:     12,
  1003  		Updated: 5000,
  1004  	})
  1005  	if err != nil {
  1006  		t.Fatal(err)
  1007  	}
  1008  
  1009  	err = table.Create(User{
  1010  		ID:      "2",
  1011  		Age:     25,
  1012  		Updated: 5001,
  1013  	})
  1014  	if err != nil {
  1015  		t.Fatal(err)
  1016  	}
  1017  	users := []User{}
  1018  	q := updIndex.ToQuery(nil)
  1019  	err = table.Read(q, &users)
  1020  	if err != nil {
  1021  		t.Fatal(err)
  1022  	}
  1023  	if len(users) != 2 {
  1024  		t.Fatal(users)
  1025  	}
  1026  	if users[0].ID != "2" || users[1].ID != "1" {
  1027  		t.Fatal(users)
  1028  	}
  1029  
  1030  	err = table.Create(User{
  1031  		ID:      "1",
  1032  		Age:     12,
  1033  		Updated: 5002,
  1034  	})
  1035  	if err != nil {
  1036  		t.Fatal(err)
  1037  	}
  1038  
  1039  	err = table.Read(q, &users)
  1040  	if err != nil {
  1041  		t.Fatal(err)
  1042  	}
  1043  	if len(users) != 2 {
  1044  		t.Fatal(users)
  1045  	}
  1046  	if users[0].ID != "1" || users[1].ID != "2" {
  1047  		t.Fatal(users)
  1048  	}
  1049  }
  1050  
  1051  func TestUpdateDeleteIndexMaintenanceMap(t *testing.T) {
  1052  	updIndex := ByEquality("Updated")
  1053  	updIndex.Order.Type = OrderTypeDesc
  1054  
  1055  	table := New(map[string]interface{}{}, &Options{
  1056  		Store:     fs.NewStore(),
  1057  		Indexes:   []Index{updIndex},
  1058  		Namespace: uuid.Must(uuid.NewV4()).String(),
  1059  		Debug:     false,
  1060  	})
  1061  
  1062  	err := table.Create(map[string]interface{}{
  1063  		"ID":      "1",
  1064  		"Age":     "12",
  1065  		"Updated": "5000",
  1066  	})
  1067  	if err != nil {
  1068  		t.Fatal(err)
  1069  	}
  1070  
  1071  	err = table.Create(map[string]interface{}{
  1072  		"ID":      "2",
  1073  		"Age":     "25",
  1074  		"Updated": "5001",
  1075  	})
  1076  	if err != nil {
  1077  		t.Fatal(err)
  1078  	}
  1079  	users := []map[string]interface{}{}
  1080  	q := updIndex.ToQuery(nil)
  1081  	err = table.Read(q, &users)
  1082  	if err != nil {
  1083  		t.Fatal(err)
  1084  	}
  1085  	if len(users) != 2 {
  1086  		t.Fatal(users)
  1087  	}
  1088  	if users[0]["ID"] != "2" || users[1]["ID"] != "1" {
  1089  		t.Fatal(users)
  1090  	}
  1091  
  1092  	err = table.Create(map[string]interface{}{
  1093  		"ID":      "1",
  1094  		"Age":     "12",
  1095  		"Updated": "5002",
  1096  	})
  1097  	if err != nil {
  1098  		t.Fatal(err)
  1099  	}
  1100  
  1101  	err = table.Read(q, &users)
  1102  	if err != nil {
  1103  		t.Fatal(err)
  1104  	}
  1105  	if len(users) != 2 {
  1106  		t.Fatal(users)
  1107  	}
  1108  	if users[0]["ID"] != "1" || users[1]["ID"] != "2" {
  1109  		t.Fatal(users)
  1110  	}
  1111  }
  1112  
  1113  type TypeTest struct {
  1114  	ID  string `json:"ID"`
  1115  	F32 float32
  1116  	F64 float64
  1117  	I   int
  1118  	I32 int32
  1119  	I64 int64
  1120  	S   string
  1121  	B   bool
  1122  }
  1123  
  1124  // Test aimed specifically to test all types
  1125  func TestAllCombos(t *testing.T) {
  1126  	// go over all filter + order combos
  1127  	// for equality indexing
  1128  
  1129  	v := reflect.ValueOf(TypeTest{})
  1130  	for filterFieldI := 0; filterFieldI < v.NumField(); filterFieldI++ {
  1131  		filterField := v.Field(filterFieldI)
  1132  		for orderFieldI := 0; orderFieldI < v.NumField(); orderFieldI++ {
  1133  			orderField := v.Field(orderFieldI)
  1134  
  1135  			filterFieldName := v.Type().Field(filterFieldI).Name
  1136  			orderFieldName := v.Type().Field(orderFieldI).Name
  1137  			if filterFieldName == "ID" || orderFieldName == "ID" {
  1138  				continue
  1139  			}
  1140  			if filterFieldName == orderFieldName {
  1141  				continue
  1142  			}
  1143  
  1144  			t.Run(fmt.Sprintf("Filter by %v, order by %v ASC", filterField.Type().Name(), orderField.Type().Name()), func(t *testing.T) {
  1145  				index := ByEquality(filterFieldName)
  1146  				index.Order.Type = OrderTypeAsc
  1147  				index.Order.FieldName = orderFieldName
  1148  
  1149  				table := New(TypeTest{}, &Options{
  1150  					Store:     fs.NewStore(),
  1151  					Indexes:   []Index{index},
  1152  					Namespace: uuid.Must(uuid.NewV4()).String(),
  1153  					Debug:     false,
  1154  				})
  1155  
  1156  				small := TypeTest{
  1157  					ID: "1",
  1158  				}
  1159  				v1 := getExampleValue(table.(*model).getFieldValue(small, orderFieldName), 1)
  1160  				table.(*model).setFieldValue(&small, orderFieldName, v1)
  1161  
  1162  				large := TypeTest{
  1163  					ID: "2",
  1164  				}
  1165  				v2 := getExampleValue(table.(*model).getFieldValue(large, orderFieldName), 2)
  1166  				table.(*model).setFieldValue(&large, orderFieldName, v2)
  1167  
  1168  				err := table.Create(small)
  1169  				if err != nil {
  1170  					t.Fatal(err)
  1171  				}
  1172  				err = table.Create(large)
  1173  				if err != nil {
  1174  					t.Fatal(err)
  1175  				}
  1176  				results := []TypeTest{}
  1177  				err = table.Read(QueryEquals(filterFieldName, nil), &results)
  1178  				if err != nil {
  1179  					t.Fatal(err)
  1180  				}
  1181  				if len(results) < 2 {
  1182  					t.Fatal(results)
  1183  				}
  1184  				if results[0].ID != "1" || results[1].ID != "2" {
  1185  					t.Fatal("Results:", results, results[0].ID, results[1].ID)
  1186  				}
  1187  			})
  1188  			t.Run(fmt.Sprintf("Filter by %v, order by %v DESC", filterField.Type().Name(), orderField.Type().Name()), func(t *testing.T) {
  1189  				index := ByEquality(filterFieldName)
  1190  				index.Order.Type = OrderTypeDesc
  1191  				index.Order.FieldName = orderFieldName
  1192  
  1193  				table := New(TypeTest{}, &Options{
  1194  					Store:     fs.NewStore(),
  1195  					Indexes:   []Index{index},
  1196  					Namespace: uuid.Must(uuid.NewV4()).String(),
  1197  					Debug:     false,
  1198  				})
  1199  
  1200  				small := TypeTest{
  1201  					ID: "1",
  1202  				}
  1203  				v1 := getExampleValue(table.(*model).getFieldValue(small, orderFieldName), 1)
  1204  				table.(*model).setFieldValue(&small, orderFieldName, v1)
  1205  
  1206  				large := TypeTest{
  1207  					ID: "2",
  1208  				}
  1209  				v2 := getExampleValue(table.(*model).getFieldValue(large, orderFieldName), 2)
  1210  				table.(*model).setFieldValue(&large, orderFieldName, v2)
  1211  
  1212  				err := table.Create(small)
  1213  				if err != nil {
  1214  					t.Fatal(err)
  1215  				}
  1216  				err = table.Create(large)
  1217  				if err != nil {
  1218  					t.Fatal(err)
  1219  				}
  1220  				results := []TypeTest{}
  1221  				err = table.Read(index.ToQuery(nil), &results)
  1222  				if err != nil {
  1223  					t.Fatal(err)
  1224  				}
  1225  				if len(results) < 2 {
  1226  					t.Fatal(results)
  1227  				}
  1228  				if results[0].ID != "2" || results[1].ID != "1" {
  1229  					t.Fatal("Results:", results, results[0].ID, results[1].ID)
  1230  				}
  1231  			})
  1232  		}
  1233  	}
  1234  }
  1235  
  1236  // returns an example value generated
  1237  // nth = each successive number should cause this
  1238  // function to return a "bigger value" for each type
  1239  func getExampleValue(i interface{}, nth int) interface{} {
  1240  	switch v := i.(type) {
  1241  	case string:
  1242  		return strings.Repeat("a", nth)
  1243  	case bool:
  1244  		if nth == 1 {
  1245  			return false
  1246  		}
  1247  		return true
  1248  	case float32:
  1249  		return v + float32(nth) + .1
  1250  	case float64:
  1251  		return v + float64(nth) + 0.1
  1252  	case int:
  1253  		return v + nth
  1254  	case int32:
  1255  		return v + int32(nth)
  1256  	case int64:
  1257  		return v + int64(nth)
  1258  	}
  1259  	return nil
  1260  }