github.com/m3db/m3@v1.5.0/src/cluster/kv/mem/store_test.go (about)

     1  // Copyright (c) 2016 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package mem
    22  
    23  import (
    24  	"sync"
    25  	"testing"
    26  
    27  	"github.com/m3db/m3/src/cluster/generated/proto/kvtest"
    28  	"github.com/m3db/m3/src/cluster/kv"
    29  
    30  	"github.com/stretchr/testify/require"
    31  )
    32  
    33  func TestValue(t *testing.T) {
    34  	v1 := NewValue(1, &kvtest.Foo{
    35  		Msg: "1",
    36  	})
    37  
    38  	v2 := NewValue(2, &kvtest.Foo{
    39  		Msg: "2",
    40  	})
    41  
    42  	require.True(t, v2.IsNewer(v1))
    43  }
    44  
    45  func TestStore(t *testing.T) {
    46  	s := NewStore()
    47  
    48  	// Should start without a value
    49  	val, err := s.Get("foo")
    50  	require.Equal(t, kv.ErrNotFound, err)
    51  	require.Nil(t, val)
    52  
    53  	// Should be able to set to non-existent value
    54  	version, err := s.SetIfNotExists("foo", &kvtest.Foo{
    55  		Msg: "first",
    56  	})
    57  	require.NoError(t, err)
    58  	require.Equal(t, 1, version)
    59  
    60  	// And have that value stored
    61  	val, err = s.Get("foo")
    62  	require.NoError(t, err)
    63  	require.NotNil(t, val)
    64  	require.Equal(t, 1, val.Version())
    65  
    66  	var read kvtest.Foo
    67  	require.NoError(t, val.Unmarshal(&read))
    68  	require.Equal(t, "first", read.Msg)
    69  
    70  	// Should not be able to SetIfNotExists to that value again
    71  	_, err = s.SetIfNotExists("foo", &kvtest.Foo{
    72  		Msg: "update",
    73  	})
    74  	require.Equal(t, kv.ErrAlreadyExists, err)
    75  
    76  	read.Reset()
    77  	val, err = s.Get("foo")
    78  	require.NoError(t, err)
    79  	require.NotNil(t, val)
    80  	require.Equal(t, 1, val.Version())
    81  	require.NoError(t, val.Unmarshal(&read))
    82  	require.Equal(t, "first", read.Msg)
    83  
    84  	// Should be able to Set unconditionally and get a new version
    85  	version2, err := s.Set("foo", &kvtest.Foo{
    86  		Msg: "update",
    87  	})
    88  	require.NoError(t, err)
    89  	require.Equal(t, 2, version2)
    90  
    91  	read.Reset()
    92  	val, err = s.Get("foo")
    93  	require.NoError(t, err)
    94  	require.Equal(t, 2, val.Version())
    95  	require.NoError(t, val.Unmarshal(&read))
    96  	require.Equal(t, "update", read.Msg)
    97  
    98  	// Should not be able to set at an old version
    99  	_, err = s.CheckAndSet("foo", version, &kvtest.Foo{
   100  		Msg: "update2",
   101  	})
   102  	require.Equal(t, kv.ErrVersionMismatch, err)
   103  
   104  	read.Reset()
   105  	val, err = s.Get("foo")
   106  	require.NoError(t, err)
   107  	require.NotNil(t, val)
   108  	require.Equal(t, 2, val.Version())
   109  	require.NoError(t, val.Unmarshal(&read))
   110  	require.Equal(t, "update", read.Msg)
   111  
   112  	// Should be able to set at the specific version
   113  	version3, err := s.CheckAndSet("foo", val.Version(), &kvtest.Foo{
   114  		Msg: "update3",
   115  	})
   116  	require.NoError(t, err)
   117  	require.Equal(t, 3, version3)
   118  
   119  	read.Reset()
   120  	val, err = s.Get("foo")
   121  	require.NoError(t, err)
   122  	require.NotNil(t, val)
   123  	require.Equal(t, 3, val.Version())
   124  	require.NoError(t, val.Unmarshal(&read))
   125  	require.Equal(t, "update3", read.Msg)
   126  }
   127  
   128  func TestStoreWatch(t *testing.T) {
   129  	s := NewStore()
   130  
   131  	fooWatch1, err := s.Watch("foo")
   132  	require.NoError(t, err)
   133  	require.NotNil(t, fooWatch1)
   134  	require.Nil(t, fooWatch1.Get())
   135  
   136  	version, err := s.SetIfNotExists("foo", &kvtest.Foo{
   137  		Msg: "first",
   138  	})
   139  	require.NoError(t, err)
   140  	require.Equal(t, 1, version)
   141  
   142  	<-fooWatch1.C()
   143  	var foo kvtest.Foo
   144  	require.NoError(t, fooWatch1.Get().Unmarshal(&foo))
   145  	require.Equal(t, "first", foo.Msg)
   146  
   147  	fooWatch2, err := s.Watch("foo")
   148  	require.NoError(t, err)
   149  	<-fooWatch2.C()
   150  	require.NoError(t, fooWatch2.Get().Unmarshal(&foo))
   151  	require.Equal(t, "first", foo.Msg)
   152  
   153  	var wg sync.WaitGroup
   154  	wg.Add(2)
   155  
   156  	go func() {
   157  		defer wg.Done()
   158  		<-fooWatch1.C()
   159  		var foo kvtest.Foo
   160  		require.NoError(t, fooWatch1.Get().Unmarshal(&foo))
   161  		require.Equal(t, "second", foo.Msg)
   162  	}()
   163  
   164  	go func() {
   165  		defer wg.Done()
   166  		<-fooWatch2.C()
   167  		var foo kvtest.Foo
   168  		require.NoError(t, fooWatch2.Get().Unmarshal(&foo))
   169  		require.Equal(t, "second", foo.Msg)
   170  	}()
   171  
   172  	version, err = s.Set("foo", &kvtest.Foo{
   173  		Msg: "second",
   174  	})
   175  	require.NoError(t, err)
   176  	require.Equal(t, 2, version)
   177  	wg.Wait()
   178  
   179  	fooWatch1.Close()
   180  	version, err = s.Set("foo", &kvtest.Foo{
   181  		Msg: "third",
   182  	})
   183  	require.NoError(t, err)
   184  	require.Equal(t, 3, version)
   185  	require.NoError(t, fooWatch2.Get().Unmarshal(&foo))
   186  	require.Equal(t, "third", foo.Msg)
   187  }
   188  
   189  func TestFakeStoreErrors(t *testing.T) {
   190  	s := NewStore()
   191  
   192  	_, err := s.Set("foo", nil)
   193  	require.Error(t, err)
   194  
   195  	_, err = s.SetIfNotExists("foo", nil)
   196  	require.Error(t, err)
   197  
   198  	_, err = s.CheckAndSet("foo", 1, nil)
   199  	require.Error(t, err)
   200  
   201  	_, err = s.History("foo", -5, 0)
   202  	require.Error(t, err)
   203  
   204  	_, err = s.History("foo", 0, 10)
   205  	require.Error(t, err)
   206  
   207  	_, err = s.History("foo", 20, 10)
   208  	require.Error(t, err)
   209  }
   210  
   211  func TestHistory(t *testing.T) {
   212  	s := NewStore()
   213  
   214  	for i := 1; i <= 10; i++ {
   215  		_, err := s.Set("foo", &kvtest.Foo{
   216  			Msg: "bar1",
   217  		})
   218  		require.NoError(t, err)
   219  	}
   220  
   221  	vals, err := s.History("foo", 3, 7)
   222  	require.NoError(t, err)
   223  	require.Equal(t, 4, len(vals))
   224  	for i := 0; i < len(vals); i++ {
   225  		require.Equal(t, i+3, vals[i].Version())
   226  	}
   227  
   228  	vals, err = s.History("foo", 3, 3)
   229  	require.NoError(t, err)
   230  	require.Equal(t, 0, len(vals))
   231  
   232  	vals, err = s.History("foo", 13, 17)
   233  	require.NoError(t, err)
   234  	require.Equal(t, 0, len(vals))
   235  }
   236  
   237  func TestDelete(t *testing.T) {
   238  	s := NewStore()
   239  
   240  	_, err := s.Delete("foo")
   241  	require.Error(t, err)
   242  	require.Equal(t, kv.ErrNotFound, err)
   243  
   244  	s.Set("foo", &kvtest.Foo{
   245  		Msg: "bar1",
   246  	})
   247  
   248  	w, err := s.Watch("foo")
   249  	require.NoError(t, err)
   250  
   251  	<-w.C()
   252  	require.Equal(t, 1, w.Get().Version())
   253  
   254  	s.Set("foo", &kvtest.Foo{
   255  		Msg: "bar2",
   256  	})
   257  	<-w.C()
   258  	v := w.Get()
   259  	require.Equal(t, 2, v.Version())
   260  	val, err := s.Delete("foo")
   261  	require.NoError(t, err)
   262  	require.Equal(t, 2, val.Version())
   263  
   264  	var read kvtest.Foo
   265  	require.NoError(t, val.Unmarshal(&read))
   266  	require.Equal(t, "bar2", read.Msg)
   267  
   268  	<-w.C()
   269  	require.Nil(t, w.Get())
   270  
   271  	_, err = s.Get("foo")
   272  	require.Error(t, err)
   273  	require.Equal(t, kv.ErrNotFound, err)
   274  
   275  	s.Set("foo", &kvtest.Foo{
   276  		Msg: "after_delete_bar1",
   277  	})
   278  
   279  	<-w.C()
   280  	newValue := w.Get()
   281  	require.Equal(t, 1, newValue.Version())
   282  	require.True(t, newValue.IsNewer(v))
   283  }
   284  
   285  func TestTxn(t *testing.T) {
   286  	store := NewStore()
   287  
   288  	r, err := store.Commit(
   289  		[]kv.Condition{
   290  			kv.NewCondition().
   291  				SetCompareType(kv.CompareEqual).
   292  				SetTargetType(kv.TargetVersion).
   293  				SetKey("foo").
   294  				SetValue(0),
   295  			kv.NewCondition().
   296  				SetCompareType(kv.CompareEqual).
   297  				SetTargetType(kv.TargetVersion).
   298  				SetKey("key").
   299  				SetValue(0),
   300  		},
   301  		[]kv.Op{
   302  			kv.NewSetOp("key", &kvtest.Foo{Msg: "1"}),
   303  			kv.NewSetOp("foo", &kvtest.Foo{Msg: "1"}),
   304  		},
   305  	)
   306  	require.NoError(t, err)
   307  	require.Equal(t, 2, len(r.Responses()))
   308  	require.Equal(t, "key", r.Responses()[0].Key())
   309  	require.Equal(t, kv.OpSet, r.Responses()[0].Type())
   310  	require.Equal(t, 1, r.Responses()[0].Value())
   311  	require.Equal(t, "foo", r.Responses()[1].Key())
   312  	require.Equal(t, kv.OpSet, r.Responses()[1].Type())
   313  	require.Equal(t, 1, r.Responses()[1].Value())
   314  
   315  	_, err = store.Commit(
   316  		[]kv.Condition{
   317  			kv.NewCondition().
   318  				SetCompareType(kv.CompareEqual).
   319  				SetTargetType(kv.TargetVersion).
   320  				SetKey("foo").
   321  				SetValue(1),
   322  			kv.NewCondition().
   323  				SetCompareType(kv.CompareEqual).
   324  				SetTargetType(kv.TargetVersion).
   325  				SetKey("key").
   326  				SetValue(0),
   327  		},
   328  		[]kv.Op{
   329  			kv.NewSetOp("key", &kvtest.Foo{Msg: "1"}),
   330  			kv.NewSetOp("foo", &kvtest.Foo{Msg: "1"}),
   331  		},
   332  	)
   333  	require.Error(t, err)
   334  	require.Equal(t, kv.ErrConditionCheckFailed, err)
   335  }