github.com/adowair/kvdb@v0.0.0-20231101174258-ceca93b03596/kv/ops_test.go (about)

     1  package kv_test
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/adowair/kvdb/kv"
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  // testcase runs as a subtest of the top-level test in this file. Each
    14  // testcase consists of a series of operations to be executed. The returns
    15  // from each operation are compared to some expected values.
    16  type testcase struct {
    17  	name  string
    18  	steps []step
    19  }
    20  
    21  // step encapsulates the run of a single command, its expected outputs
    22  // and the assertion that its outputs match the expectation.
    23  type step struct {
    24  	run func(*testing.T, *expReturns)
    25  	expReturns
    26  }
    27  
    28  // expReturns encapsulates possible returns for any operation. All fields
    29  // are optional depending on the operation being tested, except for `expError`.
    30  type expReturns struct {
    31  	err      error
    32  	value    string
    33  	firstSet time.Time
    34  	lastSet  time.Time
    35  }
    36  
    37  var (
    38  	time0 = time.Unix(0, 0)
    39  	time1 = time.Unix(1, 0)
    40  )
    41  
    42  func testGet(key string) func(*testing.T, *expReturns) {
    43  	return func(t *testing.T, r *expReturns) {
    44  		value, err := kv.Get(key)
    45  		assert.ErrorIs(t, err, r.err)
    46  		assert.Equal(t, r.value, value)
    47  	}
    48  }
    49  
    50  func testSet(key, val string, now time.Time) func(*testing.T, *expReturns) {
    51  	return func(t *testing.T, r *expReturns) {
    52  		err := kv.Set(key, val, now)
    53  		assert.ErrorIs(t, err, r.err)
    54  	}
    55  }
    56  
    57  func testTimestamp(key string) func(*testing.T, *expReturns) {
    58  	return func(t *testing.T, r *expReturns) {
    59  		firstSet, lastSet, err := kv.Timestamps(key)
    60  		assert.ErrorIs(t, err, r.err)
    61  		assert.Equal(t, r.firstSet, firstSet, "firstSet")
    62  		assert.Equal(t, r.lastSet, lastSet, "lastSet")
    63  	}
    64  }
    65  
    66  func testDelete(key string) func(*testing.T, *expReturns) {
    67  	return func(t *testing.T, r *expReturns) {
    68  		err := kv.Delete(key)
    69  		assert.ErrorIs(t, err, r.err)
    70  	}
    71  }
    72  
    73  func TestKVOps(t *testing.T) {
    74  	for _, tc := range []testcase{
    75  		{
    76  			name: "TestGetNotExist",
    77  			steps: []step{
    78  				{
    79  					run:        testGet("a"),
    80  					expReturns: expReturns{err: kv.ErrNotExist},
    81  				},
    82  			},
    83  		},
    84  		{
    85  			name: "TestDoubleGetNotExist",
    86  			steps: []step{
    87  				{
    88  					run:        testGet("a"),
    89  					expReturns: expReturns{err: kv.ErrNotExist},
    90  				},
    91  				{
    92  					run:        testGet("b"),
    93  					expReturns: expReturns{err: kv.ErrNotExist},
    94  				},
    95  			},
    96  		},
    97  		{
    98  			name: "TestSetGet",
    99  			steps: []step{
   100  				{
   101  					run:        testSet("a", "12", time0),
   102  					expReturns: expReturns{err: nil},
   103  				},
   104  				{
   105  					run:        testGet("a"),
   106  					expReturns: expReturns{err: nil, value: "12"},
   107  				},
   108  				{
   109  					run:        testSet("b", "13", time0),
   110  					expReturns: expReturns{err: nil},
   111  				},
   112  				{
   113  					run:        testGet("b"),
   114  					expReturns: expReturns{err: nil, value: "13"},
   115  				},
   116  				{
   117  					run:        testSet("a", "14", time1),
   118  					expReturns: expReturns{err: nil},
   119  				},
   120  				{
   121  					run:        testGet("a"),
   122  					expReturns: expReturns{err: nil, value: "14"},
   123  				},
   124  			},
   125  		},
   126  		{
   127  			name: "TestSetTS",
   128  			steps: []step{
   129  				{
   130  					run:        testSet("a", "12", time0),
   131  					expReturns: expReturns{err: nil},
   132  				},
   133  				{
   134  					run:        testTimestamp("a"),
   135  					expReturns: expReturns{err: nil, firstSet: time0, lastSet: time0},
   136  				},
   137  				{
   138  					run:        testSet("b", "13", time1),
   139  					expReturns: expReturns{err: nil},
   140  				},
   141  				{
   142  					run:        testTimestamp("b"),
   143  					expReturns: expReturns{err: nil, firstSet: time1, lastSet: time1},
   144  				},
   145  				{
   146  					run:        testSet("a", "13", time1),
   147  					expReturns: expReturns{err: nil},
   148  				},
   149  				{
   150  					run:        testTimestamp("a"),
   151  					expReturns: expReturns{err: nil, firstSet: time0, lastSet: time1},
   152  				},
   153  			},
   154  		},
   155  		{
   156  			name: "TestDeleteTS",
   157  			steps: []step{
   158  				{
   159  					run:        testSet("a", "12", time0),
   160  					expReturns: expReturns{err: nil},
   161  				},
   162  				{
   163  					run:        testDelete("a"),
   164  					expReturns: expReturns{err: nil},
   165  				},
   166  				{
   167  					run:        testTimestamp("a"),
   168  					expReturns: expReturns{err: kv.ErrNotExist},
   169  				},
   170  			},
   171  		},
   172  		{
   173  			name: "TestDeleteGet",
   174  			steps: []step{
   175  				{
   176  					run:        testSet("a", "12", time0),
   177  					expReturns: expReturns{err: nil},
   178  				},
   179  				{
   180  					run:        testDelete("a"),
   181  					expReturns: expReturns{err: nil},
   182  				},
   183  				{
   184  					run:        testGet("a"),
   185  					expReturns: expReturns{err: kv.ErrNotExist},
   186  				},
   187  			},
   188  		},
   189  	} {
   190  		t.Run(tc.name, func(t *testing.T) {
   191  			dir := t.TempDir()
   192  			assert.NoError(t, os.Chdir(dir))
   193  			for i, step := range tc.steps {
   194  				t.Run(fmt.Sprintf("TestStep%d", i), func(t *testing.T) {
   195  					step.run(t, &step.expReturns)
   196  				})
   197  			}
   198  		})
   199  	}
   200  }