eintopf.info@v0.13.16/service/event/testutil/store.go (about)

     1  // Copyright (C) 2022 The Eintopf authors
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  
    16  package testutil
    17  
    18  import (
    19  	"context"
    20  	"reflect"
    21  	"testing"
    22  
    23  	"eintopf.info/internal/crud"
    24  	"eintopf.info/service/event"
    25  )
    26  
    27  type newStore func() (event.Storer, func(), error)
    28  
    29  // TestStore tests if a given event.Service acts as a event store.
    30  func TestStore(t *testing.T, newStore newStore) {
    31  	ctx := context.Background()
    32  	t.Helper()
    33  
    34  	t.Run("Create", func(tt *testing.T) {
    35  		store, cleanup, err := newStore()
    36  		if err != nil {
    37  			tt.Fatalf("Failed to create a new store: %s", err)
    38  		}
    39  		defer cleanup()
    40  
    41  		event, err := store.Create(ctx, &event.NewEvent{Name: "event1"})
    42  		if err != nil {
    43  			tt.Fatalf("expected store.Create to succeed. got %s", err.Error())
    44  		}
    45  		if event == nil {
    46  			tt.Fatalf("expected event not to be nil")
    47  		}
    48  	})
    49  
    50  	t.Run("CreateWithTags", func(tt *testing.T) {
    51  		store, cleanup, err := newStore()
    52  		if err != nil {
    53  			tt.Fatalf("Failed to create a new store: %s", err)
    54  		}
    55  		defer cleanup()
    56  
    57  		event, err := store.Create(ctx, &event.NewEvent{Name: "event1", Tags: []string{"foo", "bar"}})
    58  		if err != nil {
    59  			tt.Fatalf("expected store.Create to succeed. got %s", err.Error())
    60  		}
    61  		if event == nil {
    62  			tt.Fatalf("expected event not to be nil")
    63  		}
    64  	})
    65  
    66  	t.Run("CreateWithOwnedBy", func(tt *testing.T) {
    67  		store, cleanup, err := newStore()
    68  		if err != nil {
    69  			tt.Fatalf("Failed to create a new store: %s", err)
    70  		}
    71  		defer cleanup()
    72  
    73  		event, err := store.Create(ctx, &event.NewEvent{Name: "event1", OwnedBy: []string{"foo", "bar"}})
    74  		if err != nil {
    75  			tt.Fatalf("expected store.Create to succeed. got %s", err.Error())
    76  		}
    77  		if event == nil {
    78  			tt.Fatalf("expected event not to be nil")
    79  		}
    80  	})
    81  
    82  	t.Run("FindByIDNoMatch", func(tt *testing.T) {
    83  		store, cleanup, err := newStore()
    84  		if err != nil {
    85  			tt.Fatalf("Failed to create a new store: %s", err)
    86  		}
    87  		defer cleanup()
    88  
    89  		event, err := store.FindByID(ctx, "test")
    90  		if err != nil {
    91  			tt.Fatalf("expected store.FindByID to succeed. got %s", err.Error())
    92  		}
    93  		if event != nil {
    94  			tt.Fatalf("expected to event to be nil. got %v", event)
    95  		}
    96  	})
    97  
    98  	t.Run("FindByIDWithMatch", func(tt *testing.T) {
    99  		store, cleanup, err := newStore()
   100  		if err != nil {
   101  			tt.Fatalf("Failed to create a new store: %s", err)
   102  		}
   103  		defer cleanup()
   104  
   105  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event1"})
   106  		event, err := store.FindByID(ctx, event1.ID)
   107  		if err != nil {
   108  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   109  		}
   110  		if event.ID != event1.ID || event.Name != event1.Name {
   111  			tt.Fatalf("expected to find event1. got %v. want %v", event, event1)
   112  		}
   113  	})
   114  
   115  	t.Run("FindByIDWithTags", func(tt *testing.T) {
   116  		store, cleanup, err := newStore()
   117  		if err != nil {
   118  			tt.Fatalf("Failed to create a new store: %s", err)
   119  		}
   120  		defer cleanup()
   121  
   122  		event1, _ := store.Create(ctx, &event.NewEvent{
   123  			Name: "event1",
   124  			Tags: []string{"a", "b"},
   125  		})
   126  
   127  		event, err := store.FindByID(ctx, event1.ID)
   128  		if err != nil {
   129  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   130  		}
   131  		if event.ID != event1.ID || event.Name != event1.Name || !reflect.DeepEqual(event.Tags, event1.Tags) {
   132  			tt.Fatalf("expected to find event1. got %v. want %v", event, event1)
   133  		}
   134  	})
   135  
   136  	t.Run("FindByIDWithOwnedBy", func(tt *testing.T) {
   137  		store, cleanup, err := newStore()
   138  		if err != nil {
   139  			tt.Fatalf("Failed to create a new store: %s", err)
   140  		}
   141  		defer cleanup()
   142  
   143  		event1, _ := store.Create(ctx, &event.NewEvent{
   144  			Name:    "event1",
   145  			OwnedBy: []string{"a", "b"},
   146  		})
   147  
   148  		event, err := store.FindByID(ctx, event1.ID)
   149  		if err != nil {
   150  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   151  		}
   152  		if event.ID != event1.ID || event.Name != event1.Name || !reflect.DeepEqual(event.OwnedBy, event1.OwnedBy) {
   153  			tt.Fatalf("expected to find event1. got %v. want %v", event, event1)
   154  		}
   155  	})
   156  
   157  	t.Run("Find", func(tt *testing.T) {
   158  		store, cleanup, err := newStore()
   159  		if err != nil {
   160  			tt.Fatalf("Failed to create a new store: %s", err)
   161  		}
   162  		defer cleanup()
   163  
   164  		store.Create(ctx, &event.NewEvent{Name: "event1"})
   165  		store.Create(ctx, &event.NewEvent{Name: "event2"})
   166  		events, totalEvents, err := store.Find(ctx, nil)
   167  		if err != nil {
   168  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   169  		}
   170  		if len(events) != 2 {
   171  			tt.Fatalf("expected to recieve two events. got %d", len(events))
   172  		}
   173  		if totalEvents != 2 {
   174  			tt.Fatalf("expected to recieve a total of two events. got %d", totalEvents)
   175  		}
   176  	})
   177  
   178  	t.Run("FindTags", func(tt *testing.T) {
   179  		store, cleanup, err := newStore()
   180  		if err != nil {
   181  			tt.Fatalf("Failed to create a new store: %s", err)
   182  		}
   183  		defer cleanup()
   184  
   185  		event0, _ := store.Create(ctx, &event.NewEvent{Name: "event1", Tags: []string{"foo"}})
   186  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event2", Tags: []string{"bar", "foo"}})
   187  		events, _, err := store.Find(ctx, nil)
   188  		if err != nil {
   189  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   190  		}
   191  		if !reflect.DeepEqual(events[0].Tags, event0.Tags) {
   192  			tt.Fatalf("event0: tags are not the same: got %v, want %v", events[0].Tags, event0.Tags)
   193  		}
   194  		if !reflect.DeepEqual(events[1].Tags, event1.Tags) {
   195  			tt.Fatalf("event0: tags are not the same: got %v, want %v", events[1].Tags, event1.Tags)
   196  		}
   197  	})
   198  
   199  	t.Run("FindOwnedBy", func(tt *testing.T) {
   200  		store, cleanup, err := newStore()
   201  		if err != nil {
   202  			tt.Fatalf("Failed to create a new store: %s", err)
   203  		}
   204  		defer cleanup()
   205  
   206  		event0, _ := store.Create(ctx, &event.NewEvent{Name: "event1", OwnedBy: []string{"foo"}})
   207  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event2", OwnedBy: []string{"bar", "foo"}})
   208  		events, _, err := store.Find(ctx, nil)
   209  		if err != nil {
   210  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   211  		}
   212  		if !reflect.DeepEqual(events[0].OwnedBy, event0.OwnedBy) {
   213  			tt.Fatalf("event0: ownedBy are not the same: got %v, want %v", events[0].OwnedBy, event0.OwnedBy)
   214  		}
   215  		if !reflect.DeepEqual(events[1].OwnedBy, event1.OwnedBy) {
   216  			tt.Fatalf("event0: ownedBy are not the same: got %v, want %v", events[1].OwnedBy, event1.OwnedBy)
   217  		}
   218  	})
   219  
   220  	t.Run("FindFilter", func(tt *testing.T) {
   221  		store, cleanup, err := newStore()
   222  		if err != nil {
   223  			tt.Fatalf("Failed to create a new store: %s", err)
   224  		}
   225  		defer cleanup()
   226  
   227  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event1"})
   228  		store.Create(ctx, &event.NewEvent{Name: "event2"})
   229  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   230  			Filters: &event.FindFilters{Name: &event1.Name},
   231  		})
   232  		if err != nil {
   233  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   234  		}
   235  		if len(events) != 1 {
   236  			tt.Fatalf("expected to recieve one event. got %d", len(events))
   237  		}
   238  		if totalEvents != 1 {
   239  			tt.Fatalf("expected to recieve a total of one event. got %d", totalEvents)
   240  		}
   241  		if events[0].ID != event1.ID {
   242  			tt.Fatalf("expected to find event1. got %v. want %v", events[0], event1)
   243  		}
   244  	})
   245  
   246  	t.Run("FindFilterTags", func(tt *testing.T) {
   247  		store, cleanup, err := newStore()
   248  		if err != nil {
   249  			tt.Fatalf("Failed to create a new store: %s", err)
   250  		}
   251  		defer cleanup()
   252  
   253  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event1", Tags: []string{"foo"}})
   254  		store.Create(ctx, &event.NewEvent{Name: "event2"})
   255  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   256  			Filters: &event.FindFilters{Tags: []string{"foo"}},
   257  		})
   258  		if err != nil {
   259  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   260  		}
   261  		if len(events) != 1 {
   262  			tt.Fatalf("expected to recieve one event. got %d", len(events))
   263  		}
   264  		if totalEvents != 1 {
   265  			tt.Fatalf("expected to recieve a total of one event. got %d", totalEvents)
   266  		}
   267  		if events[0].ID != event1.ID {
   268  			tt.Fatalf("expected to find event1. got %v. want %v", events[0], event1)
   269  		}
   270  	})
   271  
   272  	t.Run("FindFilterOwnedBy", func(tt *testing.T) {
   273  		store, cleanup, err := newStore()
   274  		if err != nil {
   275  			tt.Fatalf("Failed to create a new store: %s", err)
   276  		}
   277  		defer cleanup()
   278  
   279  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event1", OwnedBy: []string{"foo"}})
   280  		store.Create(ctx, &event.NewEvent{Name: "event2"})
   281  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   282  			Filters: &event.FindFilters{OwnedBy: []string{"foo"}},
   283  		})
   284  		if err != nil {
   285  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   286  		}
   287  		if len(events) != 1 {
   288  			tt.Fatalf("expected to recieve one event. got %d", len(events))
   289  		}
   290  		if totalEvents != 1 {
   291  			tt.Fatalf("expected to recieve a total of one event. got %d", totalEvents)
   292  		}
   293  		if events[0].ID != event1.ID {
   294  			tt.Fatalf("expected to find event1. got %v. want %v", events[0], event1)
   295  		}
   296  	})
   297  
   298  	t.Run("FindFilterLikeName", func(tt *testing.T) {
   299  		store, cleanup, err := newStore()
   300  		if err != nil {
   301  			tt.Fatalf("Failed to create a new store: %s", err)
   302  		}
   303  		defer cleanup()
   304  
   305  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event1"})
   306  		store.Create(ctx, &event.NewEvent{Name: "event2"})
   307  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   308  			Filters: &event.FindFilters{LikeName: strptr("1")},
   309  		})
   310  		if err != nil {
   311  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   312  		}
   313  		if len(events) != 1 {
   314  			tt.Fatalf("expected to recieve one event. got %d", len(events))
   315  		}
   316  		if totalEvents != 1 {
   317  			tt.Fatalf("expected to recieve a total of one event. got %d", totalEvents)
   318  		}
   319  		if events[0].ID != event1.ID {
   320  			tt.Fatalf("expected to find event1. got %v. want %v", events[0], event1)
   321  		}
   322  	})
   323  
   324  	t.Run("CreateFindSortedASC", func(tt *testing.T) {
   325  		store, cleanup, err := newStore()
   326  		if err != nil {
   327  			tt.Fatalf("Failed to create a new store: %s", err)
   328  		}
   329  		defer cleanup()
   330  
   331  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "c event1"})
   332  		event2, _ := store.Create(ctx, &event.NewEvent{Name: "a event2"})
   333  		event3, _ := store.Create(ctx, &event.NewEvent{Name: "b event3"})
   334  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   335  			Sort:  "name",
   336  			Order: crud.OrderAsc,
   337  		})
   338  		if err != nil {
   339  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   340  		}
   341  		if len(events) != 3 {
   342  			tt.Fatalf("expected to find three event. got %d", len(events))
   343  		}
   344  		if totalEvents != 3 {
   345  			tt.Fatalf("expected to recieve a total of three events. got %d", totalEvents)
   346  		}
   347  		if events[0].ID != event2.ID {
   348  			tt.Fatalf("expected to event[0] to be event2 . got %v", events[0])
   349  		}
   350  		if events[1].ID != event3.ID {
   351  			tt.Fatalf("expected to event[1] to be event3 . got %v", events[1])
   352  		}
   353  		if events[2].ID != event1.ID {
   354  			tt.Fatalf("expected to event[2] to be event1 . got %v", events[2])
   355  		}
   356  	})
   357  
   358  	t.Run("CreateFindSortedDESC", func(tt *testing.T) {
   359  		store, cleanup, err := newStore()
   360  		if err != nil {
   361  			tt.Fatalf("Failed to create a new store: %s", err)
   362  		}
   363  		defer cleanup()
   364  
   365  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "c event1"})
   366  		event2, _ := store.Create(ctx, &event.NewEvent{Name: "a event2"})
   367  		event3, _ := store.Create(ctx, &event.NewEvent{Name: "b event3"})
   368  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   369  			Sort:  "name",
   370  			Order: crud.OrderDesc,
   371  		})
   372  		if err != nil {
   373  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   374  		}
   375  		if len(events) != 3 {
   376  			tt.Fatalf("expected to find three event. got %d", len(events))
   377  		}
   378  		if totalEvents != 3 {
   379  			tt.Fatalf("expected to recieve a total of three events. got %d", totalEvents)
   380  		}
   381  		if events[0].ID != event1.ID {
   382  			tt.Fatalf("expected to event[0] to be event1 . got %v", events[0])
   383  		}
   384  		if events[1].ID != event3.ID {
   385  			tt.Fatalf("expected to event[1] to be event3 . got %v", events[1])
   386  		}
   387  		if events[2].ID != event2.ID {
   388  			tt.Fatalf("expected to event[2] to be event2 . got %v", events[2])
   389  		}
   390  	})
   391  
   392  	t.Run("CreateFindPaginated", func(tt *testing.T) {
   393  		store, cleanup, err := newStore()
   394  		if err != nil {
   395  			tt.Fatalf("Failed to create a new store: %s", err)
   396  		}
   397  		defer cleanup()
   398  
   399  		store.Create(ctx, &event.NewEvent{Name: "event1"})
   400  		event2, _ := store.Create(ctx, &event.NewEvent{Name: "event2"})
   401  		store.Create(ctx, &event.NewEvent{Name: "event3"})
   402  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   403  			Limit:  1,
   404  			Offset: 1,
   405  			Sort:   "name",
   406  			Order:  "ASC",
   407  		})
   408  		if err != nil {
   409  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   410  		}
   411  		if len(events) != 1 {
   412  			tt.Fatalf("expected to find one event. got %d", len(events))
   413  		}
   414  		if totalEvents != 3 {
   415  			tt.Fatalf("expected to recieve a total of three events. got %d", totalEvents)
   416  		}
   417  		if events[0].ID != event2.ID || events[0].Name != event2.Name {
   418  			tt.Fatalf("expected to find event2. got %v. want %v", events[0], event2)
   419  		}
   420  	})
   421  
   422  	t.Run("CreateFindPaginatedAndSorted", func(tt *testing.T) {
   423  		store, cleanup, err := newStore()
   424  		if err != nil {
   425  			tt.Fatalf("Failed to create a new store: %s", err)
   426  		}
   427  		defer cleanup()
   428  
   429  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "c event1"})
   430  		store.Create(ctx, &event.NewEvent{Name: "a event2"})
   431  		store.Create(ctx, &event.NewEvent{Name: "b event3"})
   432  		events, totalEvents, err := store.Find(ctx, &crud.FindParams[event.FindFilters]{
   433  			Limit:  1,
   434  			Offset: 2,
   435  			Sort:   "name",
   436  			Order:  crud.OrderAsc,
   437  		})
   438  		if err != nil {
   439  			tt.Fatalf("expected store.Find to succeed. got %s", err.Error())
   440  		}
   441  		if len(events) != 1 {
   442  			tt.Fatalf("expected to find one event. got %d", len(events))
   443  		}
   444  		if totalEvents != 3 {
   445  			tt.Fatalf("expected to recieve a total of three events. got %d", totalEvents)
   446  		}
   447  		if events[0].ID != event1.ID {
   448  			tt.Fatalf("expected to event[0] to be event1 . got %v", events[0])
   449  		}
   450  	})
   451  
   452  	t.Run("Update", func(tt *testing.T) {
   453  		store, cleanup, err := newStore()
   454  		if err != nil {
   455  			tt.Fatalf("Failed to create a new store: %s", err)
   456  		}
   457  		defer cleanup()
   458  
   459  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event3"})
   460  		event1.Name = "event3.1"
   461  
   462  		_, err = store.Update(ctx, event1)
   463  		if err != nil {
   464  			tt.Fatalf("expected store.Update to succeed. got %s", err.Error())
   465  		}
   466  
   467  		event, err := store.FindByID(ctx, event1.ID)
   468  		if event.Name != "event3.1" {
   469  			tt.Fatalf("expected event.Name to be 'event3.1. got %s", event.Name)
   470  		}
   471  	})
   472  
   473  	t.Run("UpdateTags", func(tt *testing.T) {
   474  		store, cleanup, err := newStore()
   475  		if err != nil {
   476  			tt.Fatalf("Failed to create a new store: %s", err)
   477  		}
   478  		defer cleanup()
   479  
   480  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event3", Tags: []string{"foo", "bar"}})
   481  		event1.Tags = []string{"foz", "baz"}
   482  
   483  		_, err = store.Update(ctx, event1)
   484  		if err != nil {
   485  			tt.Fatalf("expected store.Update to succeed. got %s", err.Error())
   486  		}
   487  
   488  		event, err := store.FindByID(ctx, event1.ID)
   489  		if !reflect.DeepEqual(event.Tags, []string{"foz", "baz"}) {
   490  			tt.Fatalf("expected event.Tags to be ['foz', 'baz']. got %v", event.Tags)
   491  		}
   492  	})
   493  
   494  	t.Run("UpdateOwnedBy", func(tt *testing.T) {
   495  		store, cleanup, err := newStore()
   496  		if err != nil {
   497  			tt.Fatalf("Failed to create a new store: %s", err)
   498  		}
   499  		defer cleanup()
   500  
   501  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event3", OwnedBy: []string{"foo", "bar"}})
   502  		event1.OwnedBy = []string{"foz", "baz"}
   503  
   504  		_, err = store.Update(ctx, event1)
   505  		if err != nil {
   506  			tt.Fatalf("expected store.Update to succeed. got %s", err.Error())
   507  		}
   508  
   509  		event, err := store.FindByID(ctx, event1.ID)
   510  		if !reflect.DeepEqual(event.OwnedBy, []string{"foz", "baz"}) {
   511  			tt.Fatalf("expected event.OwnedBy to be ['foz', 'baz']. got %v", event.OwnedBy)
   512  		}
   513  	})
   514  
   515  	t.Run("Delete", func(tt *testing.T) {
   516  		store, cleanup, err := newStore()
   517  		if err != nil {
   518  			tt.Fatalf("Failed to create a new store: %s", err)
   519  		}
   520  		defer cleanup()
   521  
   522  		event1, _ := store.Create(ctx, &event.NewEvent{Name: "event1"})
   523  		err = store.Delete(ctx, event1.ID)
   524  		if err != nil {
   525  			tt.Fatalf("expected store.Delete to succeed. got %s", err.Error())
   526  		}
   527  		event, err := store.FindByID(ctx, event1.ID)
   528  		if event != nil {
   529  			tt.Fatal("expected event1 to be deleted")
   530  		}
   531  	})
   532  }
   533  
   534  func strptr(str string) *string { return &str }