github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/datastore/revisions/hlcrevision_test.go (about) 1 package revisions 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/shopspring/decimal" 8 "github.com/stretchr/testify/require" 9 ) 10 11 func TestNewForHLC(t *testing.T) { 12 tcs := []string{ 13 "1", 14 "2", 15 "42", 16 "1257894000000000000", 17 "-1", 18 "1.0000000023", 19 "1703283409994227985.0000000004", 20 "1703283409994227985.0000000040", 21 "1703283409994227985.0010000000", 22 } 23 24 for _, tc := range tcs { 25 t.Run(tc, func(t *testing.T) { 26 d, err := decimal.NewFromString(tc) 27 require.NoError(t, err) 28 29 rev, err := NewForHLC(d) 30 require.NoError(t, err) 31 require.Equal(t, tc, rev.String()) 32 }) 33 } 34 } 35 36 func TestTimestampNanoSec(t *testing.T) { 37 tcs := map[string]int64{ 38 "1": 1, 39 "2": 2, 40 "42": 42, 41 "1257894000000000000": 1257894000000000000, 42 "-1": -1, 43 "1.0000000023": 1, 44 "9223372036854775807.0000000002": 9223372036854775807, 45 "1703283409994227985.0000000004": 1703283409994227985, 46 "1703283409994227985.0000000040": 1703283409994227985, 47 } 48 49 for tc, nano := range tcs { 50 t.Run(tc, func(t *testing.T) { 51 rev, err := HLCRevisionFromString(tc) 52 require.NoError(t, err) 53 54 require.Equal(t, nano, rev.TimestampNanoSec()) 55 }) 56 } 57 } 58 59 func TestInexactFloat64(t *testing.T) { 60 tcs := map[string]float64{ 61 "1": 1, 62 "2": 2, 63 "42": 42, 64 "1257894000000000000": 1257894000000000000, 65 "-1": -1, 66 "1.0000000023": 1.0000000023, 67 "9223372036854775807.0000000002": 9223372036854775807.0000000002, 68 "1703283409994227985.0000000004": 1703283409994227985.0000000004, 69 "1703283409994227985.0000000040": 1703283409994227985.000000004, 70 "1703283409994227985.000000004": 1703283409994227985.000000004, 71 "1703283409994227985.0010": 1703283409994227985.001, 72 "1703283409994227985.0010000000": 1703283409994227985.001, 73 "1703283409994227985.001": 1703283409994227985.001, 74 } 75 76 for tc, floatValue := range tcs { 77 t.Run(tc, func(t *testing.T) { 78 rev, err := HLCRevisionFromString(tc) 79 require.NoError(t, err) 80 81 require.Equal(t, floatValue, rev.InexactFloat64()) 82 }) 83 } 84 } 85 86 func TestNewHLCForTime(t *testing.T) { 87 time := time.Now() 88 rev := NewForTime(time) 89 require.Equal(t, time.UnixNano(), rev.TimestampNanoSec()) 90 } 91 92 func TestHLCKeyEquals(t *testing.T) { 93 tcs := []struct { 94 left string 95 right string 96 isEqual bool 97 }{ 98 { 99 "1", "2", false, 100 }, 101 { 102 "2", "1", false, 103 }, 104 { 105 "2", "2", true, 106 }, 107 { 108 "1", "1.0000000005", false, 109 }, 110 { 111 "1.0000000001", "1.0000000001", true, 112 }, 113 { 114 "1.0000000001", "1", false, 115 }, 116 { 117 "1703283409994227985.0000000004", "1703283409994227985.0000000005", false, 118 }, 119 { 120 "1703283409994227985.0000000005", "1703283409994227985.0000000004", false, 121 }, 122 { 123 "1703283409994227985.0000000014", "1703283409994227985.0000000005", false, 124 }, 125 { 126 "1703283409994227985.0000000005", "1703283409994227985.0000000005", true, 127 }, 128 { 129 "1703283409994227985.0000000050", "1703283409994227985.0000000050", true, 130 }, 131 { 132 "1703283409994227985.0000000050", "1703283409994227985.0000000005", false, 133 }, 134 { 135 "1703283409994227985.000000005", "1703283409994227985.0000000050", true, 136 }, 137 } 138 139 for _, tc := range tcs { 140 t.Run(tc.left+"-"+tc.right, func(t *testing.T) { 141 left, err := HLCRevisionFromString(tc.left) 142 require.NoError(t, err) 143 144 right, err := HLCRevisionFromString(tc.right) 145 require.NoError(t, err) 146 147 lk := HLCKeyFunc(left) 148 rk := HLCKeyFunc(right) 149 150 require.Equal(t, tc.isEqual, lk == rk) 151 }) 152 } 153 } 154 155 func TestHLCKeyLessThanFunc(t *testing.T) { 156 tcs := []struct { 157 left string 158 right string 159 isLessThan bool 160 }{ 161 { 162 "1", "2", true, 163 }, 164 { 165 "2", "1", false, 166 }, 167 { 168 "2", "2", false, 169 }, 170 { 171 "1", "1.0000000005", true, 172 }, 173 { 174 "1.0000000001", "1.0000000001", false, 175 }, 176 { 177 "1.0000000001", "1", false, 178 }, 179 { 180 "1703283409994227985.0000000004", "1703283409994227985.0000000005", true, 181 }, 182 { 183 "1703283409994227985.0000000005", "1703283409994227985.0000000004", false, 184 }, 185 { 186 "1703283409994227985.0000000014", "1703283409994227985.0000000005", false, 187 }, 188 { 189 "1703283409994227985.0000000005", "1703283409994227985.0000000014", true, 190 }, 191 } 192 193 for _, tc := range tcs { 194 t.Run(tc.left+"-"+tc.right, func(t *testing.T) { 195 left, err := HLCRevisionFromString(tc.left) 196 require.NoError(t, err) 197 198 right, err := HLCRevisionFromString(tc.right) 199 require.NoError(t, err) 200 201 lk := HLCKeyFunc(left) 202 rk := HLCKeyFunc(right) 203 204 require.Equal(t, tc.isLessThan, HLCKeyLessThanFunc(lk, rk)) 205 }) 206 } 207 } 208 209 func BenchmarkHLCParsing(b *testing.B) { 210 tcs := []string{ 211 "1", 212 "2", 213 "42", 214 "1257894000000000000", 215 "-1", 216 "9223372036854775807.1000000025", 217 "1703283409994227985.0000000004", 218 } 219 220 for _, tc := range tcs { 221 b.Run(tc, func(b *testing.B) { 222 for i := 0; i < b.N; i++ { 223 _, err := HLCRevisionFromString(tc) 224 if err != nil { 225 b.Fatal(err) 226 } 227 } 228 }) 229 } 230 } 231 232 func BenchmarkHLCLessThan(b *testing.B) { 233 tcs := []struct { 234 left string 235 right string 236 }{ 237 { 238 "1", "2", 239 }, 240 { 241 "2", "1", 242 }, 243 { 244 "2", "2", 245 }, 246 { 247 "1703283409994227985.0000000004", "1703283409994227985.0000000005", 248 }, 249 { 250 "1703283409994227985.0000000005", "1703283409994227985.0000000004", 251 }, 252 } 253 254 for _, tc := range tcs { 255 b.Run(tc.left+"-"+tc.right, func(b *testing.B) { 256 left, err := HLCRevisionFromString(tc.left) 257 if err != nil { 258 b.Fatal(err) 259 } 260 261 right, err := HLCRevisionFromString(tc.right) 262 if err != nil { 263 b.Fatal(err) 264 } 265 266 b.ResetTimer() 267 left.LessThan(right) 268 }) 269 } 270 } 271 272 func BenchmarkHLCLessThanFunc(b *testing.B) { 273 tcs := []struct { 274 left string 275 right string 276 }{ 277 { 278 "1", "2", 279 }, 280 { 281 "2", "1", 282 }, 283 { 284 "2", "2", 285 }, 286 { 287 "1703283409994227985.0000000001", "1703283409994227985.0000000001", 288 }, 289 { 290 "1703283409994227985.0000000004", "1703283409994227985.0000000005", 291 }, 292 { 293 "1703283409994227985.0000000005", "1703283409994227985.0000000004", 294 }, 295 } 296 297 for _, tc := range tcs { 298 b.Run(tc.left+"-"+tc.right, func(b *testing.B) { 299 left, err := HLCRevisionFromString(tc.left) 300 if err != nil { 301 b.Fatal(err) 302 } 303 304 right, err := HLCRevisionFromString(tc.right) 305 if err != nil { 306 b.Fatal(err) 307 } 308 309 b.ResetTimer() 310 lk := HLCKeyFunc(left) 311 rk := HLCKeyFunc(right) 312 313 for i := 0; i < b.N; i++ { 314 HLCKeyLessThanFunc(lk, rk) 315 } 316 }) 317 } 318 }