github.com/wrgl/wrgl@v0.14.0/pkg/ref/sql/store_test.go (about) 1 package refsql 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/google/uuid" 9 _ "github.com/mattn/go-sqlite3" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 "github.com/wrgl/wrgl/pkg/ref" 13 refhelpers "github.com/wrgl/wrgl/pkg/ref/helpers" 14 "github.com/wrgl/wrgl/pkg/testutils" 15 ) 16 17 func TestStore(t *testing.T) { 18 db, cleanup := testutils.CreateSQLDB(t, CreateTableStmts) 19 defer cleanup() 20 s := NewStore(db) 21 22 sum := testutils.SecureRandomBytes(16) 23 require.NoError(t, s.Set("heads/alpha", sum)) 24 v, err := s.Get("heads/alpha") 25 require.NoError(t, err) 26 assert.Equal(t, sum, v) 27 28 rl1 := refhelpers.RandomReflog() 29 rl1.OldOID = nil 30 require.NoError(t, s.SetWithLog("heads/beta", rl1.NewOID, rl1)) 31 rl2 := refhelpers.RandomReflog() 32 rl2.OldOID = rl1.NewOID 33 require.NoError(t, s.SetWithLog("heads/beta", rl2.NewOID, rl2)) 34 v, err = s.Get("heads/beta") 35 require.NoError(t, err) 36 assert.Equal(t, rl2.NewOID, v) 37 38 refhelpers.AssertReflogReaderContains(t, s, "heads/beta", rl2, rl1) 39 40 require.NoError(t, s.Copy("heads/beta", "heads/beta-1")) 41 v, err = s.Get("heads/beta-1") 42 require.NoError(t, err) 43 assert.Equal(t, rl2.NewOID, v) 44 v, err = s.Get("heads/beta") 45 require.NoError(t, err) 46 assert.Equal(t, rl2.NewOID, v) 47 refhelpers.AssertReflogReaderContains(t, s, "heads/beta", rl2, rl1) 48 refhelpers.AssertReflogReaderContains(t, s, "heads/beta-1", rl2, rl1) 49 50 require.NoError(t, s.Rename("heads/beta", "heads/beta-2")) 51 v, err = s.Get("heads/beta-2") 52 require.NoError(t, err) 53 assert.Equal(t, rl2.NewOID, v) 54 _, err = s.Get("heads/beta") 55 assert.Equal(t, ref.ErrKeyNotFound, err) 56 refhelpers.AssertReflogReaderContains(t, s, "heads/beta-2", rl2, rl1) 57 _, err = s.LogReader("heads/beta") 58 assert.Error(t, err) 59 60 require.NoError(t, s.Set("tags/dec-2022", testutils.SecureRandomBytes(16))) 61 for i, c := range []struct { 62 Prefixes []string 63 NotPrefixes []string 64 Expected []string 65 }{ 66 {nil, nil, []string{"heads/alpha", "heads/beta-1", "heads/beta-2", "tags/dec-2022"}}, 67 {[]string{"heads/"}, nil, []string{"heads/alpha", "heads/beta-1", "heads/beta-2"}}, 68 {[]string{"heads/a", "heads/beta-1"}, nil, []string{"heads/alpha", "heads/beta-1"}}, 69 {nil, []string{"heads/"}, []string{"tags/dec-2022"}}, 70 {[]string{"heads/"}, []string{"heads/alpha"}, []string{"heads/beta-1", "heads/beta-2"}}, 71 {[]string{"heads/", "tags/"}, []string{"heads/alpha"}, []string{"heads/beta-1", "heads/beta-2", "tags/dec-2022"}}, 72 } { 73 keys, err := s.FilterKey(c.Prefixes, c.NotPrefixes) 74 require.NoError(t, err) 75 assert.Equal(t, c.Expected, keys, "case %d", i) 76 m, err := s.Filter(c.Prefixes, c.NotPrefixes) 77 require.NoError(t, err) 78 assert.Len(t, m, len(c.Expected), "case %d", i) 79 for _, r := range c.Expected { 80 assert.Contains(t, m, r, "case %d", i) 81 } 82 } 83 84 m, err := s.Filter([]string{"heads/"}, nil) 85 require.NoError(t, err) 86 assert.Equal(t, map[string][]byte{ 87 "heads/alpha": sum, 88 "heads/beta-1": rl2.NewOID, 89 "heads/beta-2": rl2.NewOID, 90 }, m) 91 m, err = s.Filter([]string{"heads/b"}, nil) 92 require.NoError(t, err) 93 assert.Equal(t, map[string][]byte{ 94 "heads/beta-1": rl2.NewOID, 95 "heads/beta-2": rl2.NewOID, 96 }, m) 97 98 require.NoError(t, s.Delete("heads/alpha")) 99 _, err = s.Get("heads/alpha") 100 assert.Equal(t, ref.ErrKeyNotFound, err) 101 102 require.NoError(t, s.Delete("heads/beta-1")) 103 _, err = s.Get("heads/beta-1") 104 assert.Equal(t, ref.ErrKeyNotFound, err) 105 _, err = s.LogReader("heads/beta-1") 106 assert.Error(t, err) 107 } 108 109 func TestCreateTransaction(t *testing.T) { 110 db, cleanup := testutils.CreateSQLDB(t, CreateTableStmts) 111 defer cleanup() 112 s := NewStore(db) 113 114 txid, err := s.NewTransaction(nil) 115 require.NoError(t, err) 116 117 tx, err := s.GetTransaction(*txid) 118 require.NoError(t, err) 119 assert.Equal(t, tx.ID, *txid) 120 assert.NotEmpty(t, tx.Begin) 121 assert.Equal(t, ref.TSInProgress, tx.Status) 122 assert.Empty(t, tx.End) 123 124 tx.End = time.Now() 125 tx.Status = ref.TSCommitted 126 require.NoError(t, s.UpdateTransaction(tx)) 127 tx2, err := s.GetTransaction(*txid) 128 require.NoError(t, err) 129 refhelpers.AssertTransactionEqual(t, tx, tx2) 130 131 txid2, err := s.NewTransaction(nil) 132 require.NoError(t, err) 133 require.NoError(t, s.DeleteTransaction(*txid2)) 134 135 txid3, err := s.NewTransaction(nil) 136 require.NoError(t, err) 137 txid4, err := s.NewTransaction(nil) 138 require.NoError(t, err) 139 140 time.Sleep(time.Second) 141 txid5, err := s.NewTransaction(nil) 142 require.NoError(t, err) 143 ids, err := s.GCTransactions(time.Second) 144 require.NoError(t, err) 145 assert.Equal(t, []uuid.UUID{*txid3, *txid4}, ids) 146 _, err = s.GetTransaction(*txid3) 147 assert.Error(t, err) 148 _, err = s.GetTransaction(*txid4) 149 assert.Error(t, err) 150 _, err = s.GetTransaction(*txid5) 151 require.NoError(t, err) 152 153 assert.Equal(t, fmt.Errorf("cannot discard committed transaction"), s.DeleteTransaction(*txid)) 154 } 155 156 func TestTransactionLog(t *testing.T) { 157 db, cleanup := testutils.CreateSQLDB(t, CreateTableStmts) 158 defer cleanup() 159 s := NewStore(db) 160 161 txid, err := s.NewTransaction(nil) 162 require.NoError(t, err) 163 164 rl1 := refhelpers.RandomReflog() 165 rl1.OldOID = nil 166 require.NoError(t, s.SetWithLog("heads/alpha", rl1.NewOID, rl1)) 167 168 rl2 := refhelpers.RandomReflog() 169 rl2.OldOID = rl1.NewOID 170 rl2.Txid = txid 171 require.NoError(t, s.SetWithLog("heads/alpha", rl2.NewOID, rl2)) 172 173 refhelpers.AssertLatestReflogEqual(t, s, "heads/alpha", rl2) 174 175 rl3 := refhelpers.RandomReflog() 176 rl3.OldOID = nil 177 rl3.Txid = txid 178 require.NoError(t, s.SetWithLog("heads/beta", rl3.NewOID, rl3)) 179 180 m, err := s.GetTransactionLogs(*txid) 181 require.NoError(t, err) 182 assert.Len(t, m, 2) 183 refhelpers.AssertReflogEqual(t, rl2, m["heads/alpha"]) 184 refhelpers.AssertReflogEqual(t, rl3, m["heads/beta"]) 185 } 186 187 func TestListTransactions(t *testing.T) { 188 db, cleanup := testutils.CreateSQLDB(t, CreateTableStmts) 189 defer cleanup() 190 s := NewStore(db) 191 192 txids := []*uuid.UUID{} 193 for i := 0; i < 4; i++ { 194 txid, err := s.NewTransaction(nil) 195 require.NoError(t, err) 196 txids = append(txids, txid) 197 } 198 199 txs := make([]*ref.Transaction, len(txids)) 200 for i, txid := range txids { 201 tx, err := s.GetTransaction(*txid) 202 require.NoError(t, err) 203 txs[i] = tx 204 } 205 206 txs[0].Status = ref.TSCommitted 207 txs[0].End = time.Now() 208 require.NoError(t, s.UpdateTransaction(txs[0])) 209 210 sl, err := s.ListTransactions(0, 10) 211 require.NoError(t, err) 212 refhelpers.AssertTransactionSliceEqual(t, []*ref.Transaction{ 213 txs[3], txs[2], txs[1], txs[0], 214 }, sl) 215 216 sl, err = s.ListTransactions(1, 2) 217 require.NoError(t, err) 218 refhelpers.AssertTransactionSliceEqual(t, []*ref.Transaction{txs[2], txs[1]}, sl) 219 } 220 221 func TestCreateTransactionFromExisting(t *testing.T) { 222 db, cleanup := testutils.CreateSQLDB(t, CreateTableStmts) 223 defer cleanup() 224 s := NewStore(db) 225 226 tx := &ref.Transaction{ 227 ID: uuid.New(), 228 Begin: time.Now().Add(-time.Hour), 229 Status: ref.TSInProgress, 230 End: time.Now(), 231 } 232 txid, err := s.NewTransaction(tx) 233 require.NoError(t, err) 234 assert.Equal(t, tx.ID, *txid) 235 tx2, err := s.GetTransaction(*txid) 236 require.NoError(t, err) 237 refhelpers.AssertTransactionEqual(t, tx, tx2) 238 }