github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/zedtoken/zedtoken_test.go (about)

     1  package zedtoken
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
     8  	"github.com/shopspring/decimal"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/authzed/spicedb/internal/datastore/revisions"
    12  	"github.com/authzed/spicedb/pkg/datastore"
    13  )
    14  
    15  var encodeRevisionTests = []datastore.Revision{
    16  	revisions.NewForTransactionID(1),
    17  	revisions.NewForTransactionID(2),
    18  	revisions.NewForTransactionID(4),
    19  	revisions.NewForTransactionID(8),
    20  	revisions.NewForTransactionID(16),
    21  	revisions.NewForTransactionID(128),
    22  	revisions.NewForTransactionID(256),
    23  	revisions.NewForTransactionID(1621538189028928000),
    24  }
    25  
    26  func mustHLC(str string) datastore.Revision {
    27  	rev, err := revisions.HLCRevisionFromString(str)
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  	return rev
    32  }
    33  
    34  var encodeHLCRevisionTests = []datastore.Revision{
    35  	mustHLC("1235"),
    36  	mustHLC("1234.0000000001"),
    37  }
    38  
    39  func TestZedTokenEncode(t *testing.T) {
    40  	for _, rev := range encodeRevisionTests {
    41  		rev := rev
    42  		t.Run(rev.String(), func(t *testing.T) {
    43  			require := require.New(t)
    44  			encoded, err := NewFromRevision(rev)
    45  			require.NoError(err)
    46  
    47  			decoded, err := DecodeRevision(encoded, revisions.CommonDecoder{
    48  				Kind: revisions.TransactionID,
    49  			})
    50  			require.NoError(err)
    51  			require.True(rev.Equal(decoded))
    52  		})
    53  	}
    54  }
    55  
    56  func TestZedTokenEncodeHLC(t *testing.T) {
    57  	for _, rev := range encodeHLCRevisionTests {
    58  		rev := rev
    59  		t.Run(rev.String(), func(t *testing.T) {
    60  			require := require.New(t)
    61  			encoded, err := NewFromRevision(rev)
    62  			require.NoError(err)
    63  
    64  			decoded, err := DecodeRevision(encoded, revisions.CommonDecoder{
    65  				Kind: revisions.HybridLogicalClock,
    66  			})
    67  			require.NoError(err)
    68  			require.True(rev.Equal(decoded))
    69  		})
    70  	}
    71  }
    72  
    73  var decodeTests = []struct {
    74  	format           string
    75  	token            string
    76  	expectedRevision datastore.Revision
    77  	expectError      bool
    78  }{
    79  	{
    80  		format:           "invalid",
    81  		token:            "abc",
    82  		expectedRevision: datastore.NoRevision,
    83  		expectError:      true,
    84  	},
    85  	{
    86  		format:           "V1 Zookie",
    87  		token:            "CAESAA==",
    88  		expectedRevision: revisions.NewForTransactionID(0),
    89  		expectError:      false,
    90  	},
    91  	{
    92  		format:           "V1 Zookie",
    93  		token:            "CAESAggB",
    94  		expectedRevision: revisions.NewForTransactionID(1),
    95  		expectError:      false,
    96  	},
    97  	{
    98  		format:           "V1 Zookie",
    99  		token:            "CAESAggC",
   100  		expectedRevision: revisions.NewForTransactionID(2),
   101  		expectError:      false,
   102  	},
   103  	{
   104  		format:           "V1 Zookie",
   105  		token:            "CAESAwiAAg==",
   106  		expectedRevision: revisions.NewForTransactionID(256),
   107  		expectError:      false,
   108  	},
   109  	{
   110  		format:           "V1 Zookie",
   111  		token:            "CAIaAwoBMA==",
   112  		expectedRevision: revisions.NewForTransactionID(0),
   113  		expectError:      false,
   114  	},
   115  	{
   116  		format:           "V1 ZedToken",
   117  		token:            "CAIaAwoBMQ==",
   118  		expectedRevision: revisions.NewForTransactionID(1),
   119  		expectError:      false,
   120  	},
   121  	{
   122  		format:           "V1 ZedToken",
   123  		token:            "CAIaAwoBMg==",
   124  		expectedRevision: revisions.NewForTransactionID(2),
   125  		expectError:      false,
   126  	},
   127  	{
   128  		format:           "V1 ZedToken",
   129  		token:            "CAIaAwoBNA==",
   130  		expectedRevision: revisions.NewForTransactionID(4),
   131  		expectError:      false,
   132  	},
   133  }
   134  
   135  func TestDecode(t *testing.T) {
   136  	for _, testCase := range decodeTests {
   137  		testCase := testCase
   138  		testName := fmt.Sprintf("%s(%s)=>%s", testCase.format, testCase.token, testCase.expectedRevision)
   139  		t.Run(testName, func(t *testing.T) {
   140  			require := require.New(t)
   141  
   142  			decoded, err := DecodeRevision(&v1.ZedToken{
   143  				Token: testCase.token,
   144  			}, revisions.CommonDecoder{
   145  				Kind: revisions.TransactionID,
   146  			})
   147  			if testCase.expectError {
   148  				require.Error(err)
   149  			} else {
   150  				require.NoError(err)
   151  				require.True(
   152  					testCase.expectedRevision.Equal(decoded),
   153  					"%s != %s",
   154  					testCase.expectedRevision,
   155  					decoded,
   156  				)
   157  			}
   158  		})
   159  	}
   160  }
   161  
   162  var hlcDecodeTests = []struct {
   163  	format           string
   164  	token            string
   165  	expectedRevision datastore.Revision
   166  	expectError      bool
   167  }{
   168  	{
   169  		format: "V1 ZedToken",
   170  		token:  "CAIaFQoTMTYyMTUzODE4OTAyODkyODAwMA==",
   171  		expectedRevision: func() datastore.Revision {
   172  			r, err := revisions.NewForHLC(decimal.NewFromInt(1621538189028928000))
   173  			if err != nil {
   174  				panic(err)
   175  			}
   176  			return r
   177  		}(),
   178  		expectError: false,
   179  	},
   180  	{
   181  		format: "V1 ZedToken",
   182  		token:  "GiAKHjE2OTM1NDA5NDAzNzMwNDU3MjcuMDAwMDAwMDAwMQ==",
   183  		expectedRevision: (func() datastore.Revision {
   184  			v, err := decimal.NewFromString("1693540940373045727.0000000001")
   185  			if err != nil {
   186  				panic(err)
   187  			}
   188  
   189  			r, err := revisions.NewForHLC(v)
   190  			if err != nil {
   191  				panic(err)
   192  			}
   193  
   194  			return r
   195  		})(),
   196  		expectError: false,
   197  	},
   198  }
   199  
   200  func TestHLCDecode(t *testing.T) {
   201  	for _, testCase := range hlcDecodeTests {
   202  		testCase := testCase
   203  		testName := fmt.Sprintf("%s(%s)=>%s", testCase.format, testCase.token, testCase.expectedRevision)
   204  		t.Run(testName, func(t *testing.T) {
   205  			require := require.New(t)
   206  
   207  			decoded, err := DecodeRevision(&v1.ZedToken{
   208  				Token: testCase.token,
   209  			}, revisions.CommonDecoder{
   210  				Kind: revisions.HybridLogicalClock,
   211  			})
   212  			if testCase.expectError {
   213  				require.Error(err)
   214  			} else {
   215  				require.NoError(err)
   216  				require.True(
   217  					testCase.expectedRevision.Equal(decoded),
   218  					"%s != %s",
   219  					testCase.expectedRevision,
   220  					decoded,
   221  				)
   222  			}
   223  		})
   224  	}
   225  }