github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/datastore/revisions/commonrevision_test.go (about)

     1  package revisions
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  var kinds = map[RevisionKind]bool{Timestamp: false, TransactionID: false, HybridLogicalClock: true}
    11  
    12  func TestRevisionEqual(t *testing.T) {
    13  	tcs := []struct {
    14  		left    string
    15  		right   string
    16  		isEqual bool
    17  	}{
    18  		{
    19  			"1",
    20  			"2",
    21  			false,
    22  		},
    23  		{
    24  			"2",
    25  			"1",
    26  			false,
    27  		},
    28  		{
    29  			"1",
    30  			"1",
    31  			true,
    32  		},
    33  		{
    34  			"1.0000000004",
    35  			"1",
    36  			false,
    37  		},
    38  		{
    39  			"1",
    40  			"1.0000000004",
    41  			false,
    42  		},
    43  		{
    44  			"1.0000000004",
    45  			"1.0000000004",
    46  			true,
    47  		},
    48  	}
    49  
    50  	for _, tc := range tcs {
    51  		t.Run(tc.left+"-"+tc.right, func(t *testing.T) {
    52  			for kind, supportsDecimals := range kinds {
    53  				t.Run(string(kind), func(t *testing.T) {
    54  					if !supportsDecimals && strings.Contains(tc.left, ".") {
    55  						return
    56  					}
    57  
    58  					if !supportsDecimals && strings.Contains(tc.right, ".") {
    59  						return
    60  					}
    61  
    62  					parser := RevisionParser(kind)
    63  
    64  					leftRev, err := parser(tc.left)
    65  					require.NoError(t, err)
    66  
    67  					rightRev, err := parser(tc.right)
    68  					require.NoError(t, err)
    69  
    70  					require.Equal(t, tc.isEqual, leftRev.Equal(rightRev))
    71  					require.Equal(t, tc.isEqual, rightRev.Equal(leftRev))
    72  				})
    73  			}
    74  		})
    75  	}
    76  }
    77  
    78  func TestRevisionComparison(t *testing.T) {
    79  	tcs := []struct {
    80  		left              string
    81  		right             string
    82  		isLeftGreaterThan bool
    83  	}{
    84  		{
    85  			"1",
    86  			"2",
    87  			false,
    88  		},
    89  		{
    90  			"2",
    91  			"1",
    92  			true,
    93  		},
    94  		{
    95  			"1",
    96  			"1",
    97  			false,
    98  		},
    99  		{
   100  			"1.0000000004",
   101  			"1",
   102  			true,
   103  		},
   104  		{
   105  			"1",
   106  			"1.0000000004",
   107  			false,
   108  		},
   109  		{
   110  			"1.0000000004",
   111  			"1.0000000004",
   112  			false,
   113  		},
   114  	}
   115  
   116  	for _, tc := range tcs {
   117  		t.Run(tc.left+"-"+tc.right, func(t *testing.T) {
   118  			for kind, supportsDecimals := range kinds {
   119  				t.Run(string(kind), func(t *testing.T) {
   120  					if !supportsDecimals && strings.Contains(tc.left, ".") {
   121  						return
   122  					}
   123  
   124  					if !supportsDecimals && strings.Contains(tc.right, ".") {
   125  						return
   126  					}
   127  
   128  					parser := RevisionParser(kind)
   129  
   130  					leftRev, err := parser(tc.left)
   131  					require.NoError(t, err)
   132  
   133  					rightRev, err := parser(tc.right)
   134  					require.NoError(t, err)
   135  
   136  					if leftRev.Equal(rightRev) {
   137  						require.False(t, tc.isLeftGreaterThan)
   138  						return
   139  					}
   140  
   141  					require.Equal(t, tc.isLeftGreaterThan, leftRev.GreaterThan(rightRev))
   142  					require.Equal(t, !tc.isLeftGreaterThan, !leftRev.GreaterThan(rightRev))
   143  
   144  					require.Equal(t, !tc.isLeftGreaterThan, leftRev.LessThan(rightRev))
   145  					require.Equal(t, tc.isLeftGreaterThan, !leftRev.LessThan(rightRev))
   146  				})
   147  			}
   148  		})
   149  	}
   150  }
   151  
   152  func TestRevisionBidirectionalParsing(t *testing.T) {
   153  	tcs := []string{
   154  		"1", "2", "42", "192747564535", "1.0000000004", "1.0000000002", "1.0000000042", "-1235",
   155  	}
   156  
   157  	for _, tc := range tcs {
   158  		t.Run(tc, func(t *testing.T) {
   159  			for kind := range kinds {
   160  				t.Run(string(kind), func(t *testing.T) {
   161  					parser := RevisionParser(kind)
   162  					parsed, err := parser(tc)
   163  					if err != nil {
   164  						return
   165  					}
   166  
   167  					require.Equal(t, tc, parsed.String())
   168  				})
   169  			}
   170  		})
   171  	}
   172  }
   173  
   174  func TestTimestampRevisionParsing(t *testing.T) {
   175  	tcs := map[string]bool{
   176  		"1":                   false,
   177  		"2":                   false,
   178  		"42":                  false,
   179  		"1257894000000000000": false,
   180  		"-1":                  false,
   181  		"1.0000000004":        true,
   182  	}
   183  
   184  	for tc, expectError := range tcs {
   185  		t.Run(tc, func(t *testing.T) {
   186  			parser := RevisionParser(Timestamp)
   187  			parsed, err := parser(tc)
   188  			if expectError {
   189  				require.Error(t, err)
   190  				return
   191  			}
   192  
   193  			require.NoError(t, err)
   194  			require.Equal(t, tc, parsed.String())
   195  		})
   196  	}
   197  }
   198  
   199  func TestTransactionIDRevisionParsing(t *testing.T) {
   200  	tcs := map[string]bool{
   201  		"1":                   false,
   202  		"2":                   false,
   203  		"42":                  false,
   204  		"1257894000000000000": false,
   205  		"-1":                  true,
   206  		"1.0000000004":        true,
   207  	}
   208  
   209  	for tc, expectError := range tcs {
   210  		t.Run(tc, func(t *testing.T) {
   211  			parser := RevisionParser(TransactionID)
   212  			parsed, err := parser(tc)
   213  			if expectError {
   214  				require.Error(t, err)
   215  				return
   216  			}
   217  
   218  			require.NoError(t, err)
   219  			require.Equal(t, tc, parsed.String())
   220  		})
   221  	}
   222  }
   223  
   224  func TestHLCRevisionParsing(t *testing.T) {
   225  	tcs := map[string]bool{
   226  		"1":                              false,
   227  		"2":                              false,
   228  		"42":                             false,
   229  		"1257894000000000000":            false,
   230  		"-1":                             false,
   231  		"1.0000000004":                   false,
   232  		"9223372036854775807.0000000004": false,
   233  	}
   234  
   235  	for tc, expectError := range tcs {
   236  		t.Run(tc, func(t *testing.T) {
   237  			parser := RevisionParser(HybridLogicalClock)
   238  			parsed, err := parser(tc)
   239  			if expectError {
   240  				require.Error(t, err)
   241  				return
   242  			}
   243  
   244  			require.NoError(t, err)
   245  			require.Equal(t, tc, parsed.String())
   246  		})
   247  	}
   248  }