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  }