github.com/git-lfs/git-lfs@v2.5.2+incompatible/tools/kv/keyvaluestore_test.go (about)

     1  package kv
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestStoreSimple(t *testing.T) {
    12  	tmpf, err := ioutil.TempFile("", "lfstest1")
    13  	assert.Nil(t, err)
    14  	filename := tmpf.Name()
    15  	defer os.Remove(filename)
    16  	tmpf.Close()
    17  
    18  	kvs, err := NewStore(filename)
    19  	assert.Nil(t, err)
    20  
    21  	// We'll include storing custom structs
    22  	type customData struct {
    23  		Val1 string
    24  		Val2 int
    25  	}
    26  	// Needed to store custom struct
    27  	RegisterTypeForStorage(&customData{})
    28  
    29  	kvs.Set("stringVal", "This is a string value")
    30  	kvs.Set("intVal", 3)
    31  	kvs.Set("floatVal", 3.142)
    32  	kvs.Set("structVal", &customData{"structTest", 20})
    33  
    34  	s := kvs.Get("stringVal")
    35  	assert.Equal(t, "This is a string value", s)
    36  	i := kvs.Get("intVal")
    37  	assert.Equal(t, 3, i)
    38  	f := kvs.Get("floatVal")
    39  	assert.Equal(t, 3.142, f)
    40  	c := kvs.Get("structVal")
    41  	assert.Equal(t, c, &customData{"structTest", 20})
    42  	n := kvs.Get("noValue")
    43  	assert.Nil(t, n)
    44  
    45  	kvs.Remove("stringVal")
    46  	s = kvs.Get("stringVal")
    47  	assert.Nil(t, s)
    48  	// Set the string value again before saving
    49  	kvs.Set("stringVal", "This is a string value")
    50  
    51  	err = kvs.Save()
    52  	assert.Nil(t, err)
    53  	kvs = nil
    54  
    55  	// Now confirm that we can read it all back
    56  	kvs2, err := NewStore(filename)
    57  	assert.Nil(t, err)
    58  	s = kvs2.Get("stringVal")
    59  	assert.Equal(t, "This is a string value", s)
    60  	i = kvs2.Get("intVal")
    61  	assert.Equal(t, 3, i)
    62  	f = kvs2.Get("floatVal")
    63  	assert.Equal(t, 3.142, f)
    64  	c = kvs2.Get("structVal")
    65  	assert.Equal(t, c, &customData{"structTest", 20})
    66  	n = kvs2.Get("noValue")
    67  	assert.Nil(t, n)
    68  
    69  	// Test remove all
    70  	kvs2.RemoveAll()
    71  	s = kvs2.Get("stringVal")
    72  	assert.Nil(t, s)
    73  	i = kvs2.Get("intVal")
    74  	assert.Nil(t, i)
    75  	f = kvs2.Get("floatVal")
    76  	assert.Nil(t, f)
    77  	c = kvs2.Get("structVal")
    78  	assert.Nil(t, c)
    79  
    80  	err = kvs2.Save()
    81  	assert.Nil(t, err)
    82  	kvs2 = nil
    83  
    84  	// Now confirm that we can read blank & get nothing
    85  	kvs, err = NewStore(filename)
    86  	kvs.Visit(func(k string, v interface{}) bool {
    87  		// Should not be called
    88  		assert.Fail(t, "Should be no entries")
    89  		return true
    90  	})
    91  
    92  }
    93  
    94  func TestStoreOptimisticConflict(t *testing.T) {
    95  	tmpf, err := ioutil.TempFile("", "lfstest2")
    96  	assert.Nil(t, err)
    97  	filename := tmpf.Name()
    98  	defer os.Remove(filename)
    99  	tmpf.Close()
   100  
   101  	kvs1, err := NewStore(filename)
   102  	assert.Nil(t, err)
   103  
   104  	kvs1.Set("key1", "value1")
   105  	kvs1.Set("key2", "value2")
   106  	kvs1.Set("key3", "value3")
   107  	err = kvs1.Save()
   108  	assert.Nil(t, err)
   109  
   110  	// Load second copy & modify
   111  	kvs2, err := NewStore(filename)
   112  	assert.Nil(t, err)
   113  	// New keys
   114  	kvs2.Set("key4", "value4_fromkvs2")
   115  	kvs2.Set("key5", "value5_fromkvs2")
   116  	// Modify a key too
   117  	kvs2.Set("key1", "value1_fromkvs2")
   118  	err = kvs2.Save()
   119  	assert.Nil(t, err)
   120  
   121  	// Now modify first copy & save; it should detect optimistic lock issue
   122  	// New item
   123  	kvs1.Set("key10", "value10")
   124  	// Overlapping item; since we save second this will overwrite one from kvs2
   125  	kvs1.Set("key4", "value4")
   126  	err = kvs1.Save()
   127  	assert.Nil(t, err)
   128  
   129  	// This should have merged changes from kvs2 in the process
   130  	v := kvs1.Get("key1")
   131  	assert.Equal(t, "value1_fromkvs2", v) // this one was modified by kvs2
   132  	v = kvs1.Get("key2")
   133  	assert.Equal(t, "value2", v)
   134  	v = kvs1.Get("key3")
   135  	assert.Equal(t, "value3", v)
   136  	v = kvs1.Get("key4")
   137  	assert.Equal(t, "value4", v) // we overwrote this so would not be merged
   138  	v = kvs1.Get("key5")
   139  	assert.Equal(t, "value5_fromkvs2", v)
   140  
   141  }
   142  
   143  func TestStoreReduceSize(t *testing.T) {
   144  	tmpf, err := ioutil.TempFile("", "lfstest3")
   145  	assert.Nil(t, err)
   146  	filename := tmpf.Name()
   147  	defer os.Remove(filename)
   148  	tmpf.Close()
   149  
   150  	kvs, err := NewStore(filename)
   151  	assert.Nil(t, err)
   152  
   153  	kvs.Set("key1", "I woke up in a Soho doorway")
   154  	kvs.Set("key2", "A policeman knew my name")
   155  	kvs.Set("key3", "He said 'You can go sleep at home tonight")
   156  	kvs.Set("key4", "If you can get up and walk away'")
   157  
   158  	assert.NotNil(t, kvs.Get("key1"))
   159  	assert.NotNil(t, kvs.Get("key2"))
   160  	assert.NotNil(t, kvs.Get("key3"))
   161  	assert.NotNil(t, kvs.Get("key4"))
   162  
   163  	assert.Nil(t, kvs.Save())
   164  
   165  	stat1, _ := os.Stat(filename)
   166  
   167  	// Remove all but 1 key & save smaller version
   168  	kvs.Remove("key2")
   169  	kvs.Remove("key3")
   170  	kvs.Remove("key4")
   171  	assert.Nil(t, kvs.Save())
   172  
   173  	// Now reload fresh & prove works
   174  	kvs = nil
   175  
   176  	kvs, err = NewStore(filename)
   177  	assert.Nil(t, err)
   178  	assert.NotNil(t, kvs.Get("key1"))
   179  	assert.Nil(t, kvs.Get("key2"))
   180  	assert.Nil(t, kvs.Get("key3"))
   181  	assert.Nil(t, kvs.Get("key4"))
   182  
   183  	stat2, _ := os.Stat(filename)
   184  
   185  	assert.True(t, stat2.Size() < stat1.Size(), "Size should have reduced, was %d now %d", stat1.Size(), stat2.Size())
   186  
   187  }