github.com/bartle-stripe/trillian@v1.2.1/storage/types_test.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package storage 16 17 import ( 18 "bytes" 19 "fmt" 20 "math/big" 21 "strconv" 22 "testing" 23 24 "github.com/google/trillian/testonly" 25 ) 26 27 var h2b = testonly.MustHexDecode 28 29 func TestMaskLeft(t *testing.T) { 30 for _, tc := range []struct { 31 index []byte 32 depth int 33 want []byte 34 }{ 35 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 0, want: h2b("0000000000000000000000000000000000000000")}, 36 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 1, want: h2b("8000000000000000000000000000000000000000")}, 37 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 2, want: h2b("C000000000000000000000000000000000000000")}, 38 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 3, want: h2b("E000000000000000000000000000000000000000")}, 39 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 4, want: h2b("F000000000000000000000000000000000000000")}, 40 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 5, want: h2b("F800000000000000000000000000000000000000")}, 41 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 6, want: h2b("FC00000000000000000000000000000000000000")}, 42 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 7, want: h2b("FE00000000000000000000000000000000000000")}, 43 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 8, want: h2b("FF00000000000000000000000000000000000000")}, 44 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 9, want: h2b("FF80000000000000000000000000000000000000")}, 45 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 10, want: h2b("FFC0000000000000000000000000000000000000")}, 46 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 159, want: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE")}, 47 {index: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), depth: 160, want: h2b("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")}, 48 {index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 1, want: h2b("0000000000000000000000000000000000000000")}, 49 {index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 17, want: h2b("0001000000000000000000000000000000000000")}, 50 {index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 159, want: h2b("000102030405060708090A0B0C0D0E0F10111212")}, 51 {index: h2b("000102030405060708090A0B0C0D0E0F10111213"), depth: 160, want: h2b("000102030405060708090A0B0C0D0E0F10111213")}, 52 } { 53 nID := NewNodeIDFromHash(tc.index) 54 if got, want := nID.MaskLeft(tc.depth).Path, tc.want; !bytes.Equal(got, want) { 55 t.Errorf("maskIndex(%x, %v): %x, want %x", tc.index, tc.depth, got, want) 56 } 57 } 58 } 59 60 func TestNewNodeIDFromBigInt(t *testing.T) { 61 for _, tc := range []struct { 62 depth int 63 index *big.Int 64 totalDepth int 65 wantPath []byte 66 wantDepth int 67 }{ 68 {256, new(big.Int).SetBytes(h2b("00")), 256, h2b("0000000000000000000000000000000000000000000000000000000000000000"), 256}, 69 {256, new(big.Int).SetBytes(h2b("01")), 256, h2b("0000000000000000000000000000000000000000000000000000000000000001"), 256}, 70 {8, new(big.Int).SetBytes(h2b("4100000000000000000000000000000000000000000000000000000000000000")), 256, 71 h2b("4100000000000000000000000000000000000000000000000000000000000000"), 8}, 72 } { 73 n := NewNodeIDFromBigInt(tc.depth, tc.index, tc.totalDepth) 74 if got, want := n.Path, tc.wantPath; !bytes.Equal(got, want) { 75 t.Errorf("NewNodeIDFromBigInt(%v, %x, %v): %x, want %x", 76 tc.depth, tc.index.Bytes(), tc.totalDepth, got, want) 77 } 78 if got, want := n.PrefixLenBits, tc.wantDepth; got != want { 79 t.Errorf("NewNodeIDFromBigInt(%v, %x, %v): depth %v, want %v", 80 tc.depth, tc.index.Bytes(), tc.totalDepth, got, want) 81 } 82 } 83 } 84 85 func TestSplit(t *testing.T) { 86 for _, tc := range []struct { 87 inPath []byte 88 inPathLenBits int 89 splitBytes, suffixBits int 90 outPrefix []byte 91 outSuffixBits int 92 outSuffix []byte 93 unusedBytes int 94 }{ 95 {h2b("1234567f"), 32, 3, 8, h2b("123456"), 8, h2b("7f"), 0}, 96 {h2b("123456ff"), 29, 3, 8, h2b("123456"), 5, h2b("f8"), 0}, 97 {h2b("123456ff"), 25, 3, 8, h2b("123456"), 1, h2b("80"), 0}, 98 {h2b("12345678"), 16, 1, 8, h2b("12"), 8, h2b("34"), 2}, 99 {h2b("12345678"), 9, 1, 8, h2b("12"), 1, h2b("00"), 2}, 100 {h2b("12345678"), 8, 0, 8, h2b(""), 8, h2b("12"), 3}, 101 {h2b("12345678"), 7, 0, 8, h2b(""), 7, h2b("12"), 3}, 102 {h2b("12345678"), 0, 0, 8, h2b(""), 0, h2b("00"), 3}, 103 {h2b("70"), 2, 0, 8, h2b(""), 2, h2b("40"), 0}, 104 {h2b("70"), 3, 0, 8, h2b(""), 3, h2b("60"), 0}, 105 {h2b("70"), 4, 0, 8, h2b(""), 4, h2b("70"), 0}, 106 {h2b("70"), 5, 0, 8, h2b(""), 5, h2b("70"), 0}, 107 {h2b("0003"), 16, 1, 8, h2b("00"), 8, h2b("03"), 0}, 108 {h2b("0003"), 15, 1, 8, h2b("00"), 7, h2b("02"), 0}, 109 {h2b("0001000000000000"), 16, 1, 8, h2b("00"), 8, h2b("01"), 6}, 110 {h2b("0100000000000000"), 8, 0, 8, h2b(""), 8, h2b("01"), 7}, 111 // Map subtree scenarios 112 {h2b("0100000000000000"), 16, 0, 16, h2b(""), 16, h2b("0100"), 6}, 113 {h2b("0100000000000000"), 32, 0, 32, h2b(""), 32, h2b("01000000"), 4}, 114 {h2b("0000000000000000000000000000000000000000000000000000000000000001"), 256, 10, 176, h2b("00000000000000000000"), 176, h2b("00000000000000000000000000000000000000000001"), 0}, 115 } { 116 n := NewNodeIDFromHash(tc.inPath) 117 n.PrefixLenBits = tc.inPathLenBits 118 119 p, s := n.Split(tc.splitBytes, tc.suffixBits) 120 if got, want := p, tc.outPrefix; !bytes.Equal(got, want) { 121 t.Errorf("%d, %x.Split(%v, %v): prefix %x, want %x", 122 tc.inPathLenBits, tc.inPath, tc.splitBytes, tc.suffixBits, got, want) 123 continue 124 } 125 if got, want := int(s.Bits), tc.outSuffixBits; got != want { 126 t.Errorf("%d, %x.Split(%v, %v): suffix.Bits %v, want %d", 127 tc.inPathLenBits, tc.inPath, tc.splitBytes, tc.suffixBits, got, want) 128 continue 129 } 130 if got, want := s.Path, tc.outSuffix; !bytes.Equal(got, want) { 131 t.Errorf("%d, %x.Split(%v, %v).Path: %x, want %x", 132 tc.inPathLenBits, tc.inPath, tc.splitBytes, tc.suffixBits, got, want) 133 continue 134 } 135 136 newNode := NewNodeIDFromPrefixSuffix(p, s, len(tc.inPath)*8) 137 want := []byte{} 138 want = append(want, tc.outPrefix...) 139 want = append(want, tc.outSuffix...) 140 want = append(want, make([]byte, tc.unusedBytes)...) 141 if got, want := newNode.Path, want; !bytes.Equal(got, want) { 142 t.Errorf("NewNodeIDFromPrefix(%x, %v).Path: %x, want %x", p, s, got, want) 143 } 144 if got, want := newNode.PrefixLenBits, n.PrefixLenBits; got != want { 145 t.Errorf("NewNodeIDFromPrefix(%x, %v).PrefixLenBits: %x, want %x", p, s, got, want) 146 } 147 } 148 } 149 150 func TestNewNodeIDFromPrefix(t *testing.T) { 151 for _, tc := range []struct { 152 prefix []byte 153 depth int 154 index int64 155 subDepth int 156 totalDepth int 157 wantPath []byte 158 wantDepth int 159 }{ 160 {prefix: h2b(""), depth: 8, index: 0, subDepth: 8, totalDepth: 64, wantPath: h2b("0000000000000000"), wantDepth: 8}, 161 {prefix: h2b(""), depth: 8, index: 1, subDepth: 8, totalDepth: 64, wantPath: h2b("0100000000000000"), wantDepth: 8}, 162 {prefix: h2b("00"), depth: 7, index: 1, subDepth: 8, totalDepth: 64, wantPath: h2b("0002000000000000"), wantDepth: 15}, 163 {prefix: h2b("00"), depth: 8, index: 1, subDepth: 8, totalDepth: 64, wantPath: h2b("0001000000000000"), wantDepth: 16}, 164 {prefix: h2b("00"), depth: 16, index: 257, subDepth: 16, totalDepth: 64, wantPath: h2b("0001010000000000"), wantDepth: 24}, 165 {prefix: h2b("12345678"), depth: 8, index: 1, subDepth: 8, totalDepth: 64, wantPath: h2b("1234567801000000"), wantDepth: 40}, 166 } { 167 n := NewNodeIDFromPrefix(tc.prefix, tc.depth, tc.index, tc.subDepth, tc.totalDepth) 168 if got, want := n.Path, tc.wantPath; !bytes.Equal(got, want) { 169 t.Errorf("NewNodeIDFromPrefix(%x, %v, %v, %v, %v).Path: %x, want %x", 170 tc.prefix, tc.depth, tc.index, tc.subDepth, tc.totalDepth, got, want) 171 } 172 if got, want := n.PrefixLenBits, tc.wantDepth; got != want { 173 t.Errorf("NewNodeIDFromPrefix(%x, %v, %v, %v, %v).Depth: %v, want %v", 174 tc.prefix, tc.depth, tc.index, tc.subDepth, tc.totalDepth, got, want) 175 } 176 } 177 } 178 179 func TestNewNodeIDWithPrefix(t *testing.T) { 180 for _, tc := range []struct { 181 input uint64 182 inputLen int 183 pathLen int 184 maxLen int 185 want []byte 186 }{ 187 {input: h26("00"), inputLen: 0, pathLen: 0, maxLen: 64, want: h2b("0000000000000000")}, 188 {input: h26("12345678"), inputLen: 32, pathLen: 32, maxLen: 64, want: h2b("1234567800000000")}, 189 // top 15 bits of 0x345678 are: 0101 0110 0111 1000 190 {input: h26("345678"), inputLen: 15, pathLen: 16, maxLen: 24, want: h2b("acf000")}, 191 } { 192 n := NewNodeIDWithPrefix(tc.input, tc.inputLen, tc.pathLen, tc.maxLen) 193 if got, want := n.Path, tc.want; !bytes.Equal(got, want) { 194 t.Errorf("NewNodeIDWithPrefix(%x, %v, %v, %v).Path: %x, want %x", 195 tc.input, tc.inputLen, tc.pathLen, tc.maxLen, got, want) 196 } 197 } 198 } 199 200 func TestNewNodeIDForTreeCoords(t *testing.T) { 201 for _, v := range []struct { 202 height int64 203 index int64 204 maxBits int 205 shouldFail bool 206 want string 207 }{ 208 {0, 0x00, 8, false, "00000000"}, 209 {0, 0x01, 8, false, "00000001"}, 210 {1, 0x01, 8, false, "0000001"}, 211 {0, 0x01, 16, false, "0000000000000001"}, 212 {2, 0x04, 8, false, "000100"}, 213 {8, 0x01, 16, false, "00000001"}, 214 {0, 0x80, 8, false, "10000000"}, 215 {0, 0x01, 64, false, "0000000000000000000000000000000000000000000000000000000000000001"}, 216 {63, 0x01, 64, false, "1"}, 217 {63, 0x02, 64, true, "index of 0x02 is too large for given height"}, 218 } { 219 n, err := NewNodeIDForTreeCoords(v.height, v.index, v.maxBits) 220 221 if got, want := err != nil, v.shouldFail; got != want { 222 t.Errorf("NewNodeIDForTreeCoords(%d, %x, %d): %v, want failure: %v", 223 v.height, v.index, v.maxBits, err, want) 224 continue 225 } 226 if err != nil { 227 continue 228 } 229 if got, want := n.String(), v.want; got != want { 230 t.Errorf("NewNodeIDForTreeCoords(%d, %x, %d).String(): '%v', want '%v'", 231 v.height, v.index, v.maxBits, got, want) 232 } 233 } 234 } 235 236 func TestSetBit(t *testing.T) { 237 for _, tc := range []struct { 238 n NodeID 239 i int 240 b uint 241 want []byte 242 }{ 243 { 244 n: NewNodeIDWithPrefix(h26("00"), 0, 64, 64), 245 i: 27, b: 1, 246 want: h2b("0000000008000000"), 247 }, 248 { 249 n: NewNodeIDWithPrefix(h26("00"), 0, 56, 64), 250 i: 0, b: 1, 251 want: h2b("0000000000000001"), 252 }, 253 { 254 n: NewNodeIDWithPrefix(h26("00"), 0, 64, 64), 255 i: 27, b: 0, 256 want: h2b("0000000000000000"), 257 }, 258 } { 259 n := tc.n 260 n.SetBit(tc.i, tc.b) 261 if got, want := n.Path, tc.want; !bytes.Equal(got, want) { 262 t.Errorf("%x.SetBit(%v,%v): %v, want %v", tc.n.Path, tc.i, tc.b, got, want) 263 } 264 } 265 } 266 267 func TestFlipBit(t *testing.T) { 268 for _, tc := range []struct { 269 index []byte 270 i int 271 want []byte 272 }{ 273 {index: h2b("00"), i: 0, want: h2b("01")}, 274 {index: h2b("00"), i: 7, want: h2b("80")}, 275 {index: h2b("000b"), i: 0, want: h2b("000a")}, 276 {index: h2b("000b"), i: 1, want: h2b("0009")}, 277 {index: h2b("000b"), i: 2, want: h2b("000f")}, 278 {index: h2b("000b"), i: 3, want: h2b("0003")}, 279 {index: h2b("0001"), i: 0, want: h2b("0000")}, 280 {index: h2b("8000"), i: 15, want: h2b("0000")}, 281 {index: h2b("0000000000000001"), i: 0, want: h2b("0000000000000000")}, 282 {index: h2b("0000000000010000"), i: 16, want: h2b("0000000000000000")}, 283 {index: h2b("8000000000000000"), i: 63, want: h2b("0000000000000000")}, 284 } { 285 nID := NewNodeIDFromHash(tc.index) 286 if got, want := nID.FlipRightBit(tc.i).Path, tc.want; !bytes.Equal(got, want) { 287 t.Errorf("flipBit(%x, %d): %x, want %x", tc.index, tc.i, got, want) 288 } 289 } 290 } 291 292 func TestBit(t *testing.T) { 293 for _, tc := range []struct { 294 n NodeID 295 want string 296 }{ 297 { 298 // Every 3rd bit is 1. 299 n: NewNodeIDWithPrefix(h26("9249"), 16, 16, 16), 300 want: "1001001001001001", 301 }, 302 { 303 n: NewNodeIDWithPrefix(h26("0055"), 16, 16, 24), 304 want: "000000000101010100000000", 305 }, 306 { 307 n: NewNodeIDWithPrefix(h26("f2"), 8, 0, 24), 308 want: "111100100000000000000000", 309 }, 310 { 311 n: NewNodeIDWithPrefix(h26("01"), 1, 8, 24), 312 want: "100000000000000000000000", 313 }, 314 } { 315 for i, c := range tc.want { 316 height := len(tc.want) - 1 - i // Count from right to left. 317 if got, want := tc.n.Bit(height), uint(c-'0'); got != want { 318 t.Errorf("%v.Bit(%v): %x, want %v", tc.n.String(), height, got, want) 319 } 320 } 321 } 322 } 323 324 func TestString(t *testing.T) { 325 for i, tc := range []struct { 326 n NodeID 327 want string 328 }{ 329 { 330 n: NewEmptyNodeID(32), 331 want: "", 332 }, 333 { 334 n: NewNodeIDWithPrefix(h26("345678"), 24, 32, 32), 335 want: "00110100010101100111100000000000", 336 }, 337 { 338 n: NewNodeIDWithPrefix(h26("12345678"), 32, 32, 64), 339 want: "00010010001101000101011001111000", 340 }, 341 { 342 n: NewNodeIDWithPrefix(h26("345678"), 15, 16, 24), 343 want: fmt.Sprintf("%016b", (0x345678<<1)&0xfffd), 344 }, 345 { 346 n: NewNodeIDWithPrefix(h26("1234"), 15, 16, 16), 347 want: "0010010001101000", 348 }, 349 { 350 n: NewNodeIDWithPrefix(h26("f2"), 8, 8, 24), 351 want: "11110010", 352 }, 353 { 354 n: NewNodeIDWithPrefix(h26("1234"), 16, 16, 16), 355 want: "0001001000110100", 356 }, 357 } { 358 if got, want := tc.n.String(), tc.want; got != want { 359 t.Errorf("%v: String(): %v, want '%v'", i, got, want) 360 } 361 } 362 } 363 364 func TestSiblings(t *testing.T) { 365 for _, tc := range []struct { 366 input uint64 367 inputLen int 368 pathLen int 369 maxLen int 370 want []string 371 }{ 372 { 373 input: h26("abe4"), 374 inputLen: 16, 375 pathLen: 16, 376 maxLen: 16, 377 want: []string{"1010101111100101", 378 "101010111110011", 379 "10101011111000", 380 "1010101111101", 381 "101010111111", 382 "10101011110", 383 "1010101110", 384 "101010110", 385 "10101010", 386 "1010100", 387 "101011", 388 "10100", 389 "1011", 390 "100", 391 "11", 392 "0"}, 393 }, 394 } { 395 n := NewNodeIDWithPrefix(tc.input, tc.inputLen, tc.pathLen, tc.maxLen) 396 sibs := n.Siblings() 397 if got, want := len(sibs), len(tc.want); got != want { 398 t.Errorf("Got %d siblings, want %d", got, want) 399 continue 400 } 401 402 for i, s := range sibs { 403 if got, want := s.String(), tc.want[i]; got != want { 404 t.Errorf("sibling %d: %v, want %v", i, got, want) 405 } 406 } 407 } 408 } 409 410 func TestNodeEquivalent(t *testing.T) { 411 l := 16 412 na := NewNodeIDWithPrefix(h26("1234"), l, l, l) 413 for _, tc := range []struct { 414 n1, n2 NodeID 415 want bool 416 }{ 417 { 418 // Self is Equal 419 n1: na, 420 n2: na, 421 want: true, 422 }, 423 { 424 // Equal 425 n1: NewNodeIDWithPrefix(h26("1234"), l, l, l), 426 n2: NewNodeIDWithPrefix(h26("1234"), l, l, l), 427 want: true, 428 }, 429 { 430 // Different PrefixLen 431 n1: NewNodeIDWithPrefix(h26("123f"), l, l, l), 432 n2: NewNodeIDWithPrefix(h26("123f"), l-1, l, l), 433 want: false, 434 }, 435 { 436 // Different IDLen 437 n1: NewNodeIDWithPrefix(h26("1234"), l, l, l), 438 n2: NewNodeIDWithPrefix(h26("1234"), l, l+8, l+8), 439 want: false, 440 }, 441 { 442 // Different Prefix 443 n1: NewNodeIDWithPrefix(h26("1234"), l, l, l), 444 n2: NewNodeIDWithPrefix(h26("5432"), l, l, l), 445 want: false, 446 }, 447 { 448 // Different max len, but that's ok because the prefixes are identical 449 n1: NewNodeIDWithPrefix(h26("1234"), l, l, l), 450 n2: NewNodeIDWithPrefix(h26("1234"), l, l, l*2), 451 want: true, 452 }, 453 } { 454 if got, want := tc.n1.Equivalent(tc.n2), tc.want; got != want { 455 t.Errorf("Equivalent(%v, %v): %v, want %v", 456 tc.n1, tc.n2, got, want) 457 } 458 } 459 } 460 461 // It's important to have confidence in the CoordString output as it's used in debugging 462 func TestCoordString(t *testing.T) { 463 // Test some roundtrips for various depths and indices 464 for d := 0; d < 37; d++ { 465 for i := 0; i < 117; i++ { 466 n, err := NewNodeIDForTreeCoords(int64(d), int64(i), 64) 467 if err != nil { 468 t.Fatal(err) 469 } 470 if got, want := n.CoordString(), fmt.Sprintf("[d:%d, i:%d]", d, i); got != want { 471 t.Errorf("n.CoordString() got: %v, want: %v", got, want) 472 } 473 } 474 } 475 } 476 477 // h26 converts a hex string into an uint64. 478 func h26(h string) uint64 { 479 i, err := strconv.ParseUint(h, 16, 64) 480 if err != nil { 481 panic(err) 482 } 483 return i 484 }