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  }