serial_test.mx raw

   1  package serial
   2  
   3  import (
   4  	"bytes"
   5  	"crypto/sha256"
   6  	"testing"
   7  )
   8  
   9  // TestPutGetRoundTrip pins the 5-byte big-endian encoding: every byte position
  10  // matters because index keys are byte-compared by the sorted file.
  11  func TestPutGetRoundTrip(t *testing.T) {
  12  	vals := []uint64{0, 1, 255, 256, 65535, 1 << 32, Max - 1, Max}
  13  	for _, v := range vals {
  14  		buf := []byte{:Len}
  15  		Put(buf, v)
  16  		if got := Get(buf); got != v {
  17  			t.Fatalf("Get(Put(%d)) = %d", v, got)
  18  		}
  19  	}
  20  }
  21  
  22  func TestPutByteLayout(t *testing.T) {
  23  	buf := []byte{:Len}
  24  	Put(buf, 0x0102030405)
  25  	want := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
  26  	if !bytes.Equal(buf, want) {
  27  		t.Fatal("Put byte order")
  28  	}
  29  	Put(buf, 0)
  30  	if !bytes.Equal(buf, []byte{0, 0, 0, 0, 0}) {
  31  		t.Fatal("Put zero")
  32  	}
  33  	Put(buf, Max)
  34  	if !bytes.Equal(buf, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) {
  35  		t.Fatal("Put Max")
  36  	}
  37  }
  38  
  39  func TestGetReadsEveryByte(t *testing.T) {
  40  	// One bit per byte position: a decode that drops a shift reads wrong here.
  41  	if Get([]byte{1, 0, 0, 0, 0}) != 1<<32 {
  42  		t.Fatal("byte 0 shift")
  43  	}
  44  	if Get([]byte{0, 1, 0, 0, 0}) != 1<<24 {
  45  		t.Fatal("byte 1 shift")
  46  	}
  47  	if Get([]byte{0, 0, 1, 0, 0}) != 1<<16 {
  48  		t.Fatal("byte 2 shift")
  49  	}
  50  	if Get([]byte{0, 0, 0, 1, 0}) != 1<<8 {
  51  		t.Fatal("byte 3 shift")
  52  	}
  53  	if Get([]byte{0, 0, 0, 0, 1}) != 1 {
  54  		t.Fatal("byte 4 shift")
  55  	}
  56  }
  57  
  58  func TestAppend(t *testing.T) {
  59  	dst := Append([]byte("ab"), 0x0102030405)
  60  	want := []byte("ab\x01\x02\x03\x04\x05")
  61  	if !bytes.Equal(dst, want) {
  62  		t.Fatalf("Append = %x", dst)
  63  	}
  64  	only := Append(nil, 0)
  65  	if len(only) != Len {
  66  		t.Fatalf("Append(nil) len = %d", len(only))
  67  	}
  68  	if Get(only) != 0 {
  69  		t.Fatal("Append(nil) value")
  70  	}
  71  	// Two appends stack.
  72  	two := Append(Append(nil, 1), 2)
  73  	if len(two) != 2*Len {
  74  		t.Fatalf("two appends len = %d", len(two))
  75  	}
  76  	if Get(two[:Len]) != 1 || Get(two[Len:]) != 2 {
  77  		t.Fatal("two appends value")
  78  	}
  79  }
  80  
  81  // TestHashHelpers pins length, determinism and the exact sha256 prefix, since
  82  // the engine compares these hashes as index keys.
  83  func TestHashHelpers(t *testing.T) {
  84  	in := []byte("the quick brown fox")
  85  	sum := sha256.Sum256(in)
  86  
  87  	ih := IdHash(in)
  88  	if len(ih) != HashLen {
  89  		t.Fatalf("IdHash len = %d", len(ih))
  90  	}
  91  	if !bytes.Equal(ih, sum[:HashLen]) {
  92  		t.Fatal("IdHash is not the sha256 prefix")
  93  	}
  94  	if !bytes.Equal(IdHash(in), ih) {
  95  		t.Fatal("IdHash not deterministic")
  96  	}
  97  	if bytes.Equal(IdHash(in), IdHash([]byte("the quick brown fo"))) {
  98  		t.Fatal("IdHash collision on near input")
  99  	}
 100  
 101  	ph := PubHash(in)
 102  	if len(ph) != HashLen || !bytes.Equal(ph, sum[:HashLen]) {
 103  		t.Fatal("PubHash is not the sha256 prefix")
 104  	}
 105  	// Same input, same bytes: the three helpers are all truncated sha256.
 106  	if !bytes.Equal(ph, ih) {
 107  		t.Fatal("IdHash and PubHash differ for the same input")
 108  	}
 109  
 110  	ihash := Ident(in)
 111  	if len(ihash) != HashLen || !bytes.Equal(ihash, sum[:HashLen]) {
 112  		t.Fatal("Ident is not the sha256 prefix")
 113  	}
 114  	zeroSum := sha256.Sum256(nil)
 115  	if !bytes.Equal(Ident(nil), zeroSum[:HashLen]) {
 116  		t.Fatal("Ident(nil)")
 117  	}
 118  	if len(Ident(nil)) != HashLen {
 119  		t.Fatal("Ident(nil) length")
 120  	}
 121  }
 122  
 123  func TestTimestampRoundTrip(t *testing.T) {
 124  	vals := []int64{0, 1, -1, 1700000000, 1 << 40, -1700000000}
 125  	for _, v := range vals {
 126  		buf := []byte{:8}
 127  		PutTimestamp(buf, v)
 128  		if got := GetTimestamp(buf); got != v {
 129  			t.Fatalf("GetTimestamp(PutTimestamp(%d)) = %d", v, got)
 130  		}
 131  	}
 132  }
 133  
 134  func TestTimestampByteLayout(t *testing.T) {
 135  	buf := []byte{:8}
 136  	PutTimestamp(buf, 0x0102030405060708)
 137  	want := []byte{1, 2, 3, 4, 5, 6, 7, 8}
 138  	if !bytes.Equal(buf, want) {
 139  		t.Fatalf("PutTimestamp = %x", buf)
 140  	}
 141  	// -1 is all ones, so a signed cast that clamps would fail here.
 142  	PutTimestamp(buf, -1)
 143  	if !bytes.Equal(buf, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) {
 144  		t.Fatal("PutTimestamp(-1)")
 145  	}
 146  }
 147  
 148  func TestAppendTimestamp(t *testing.T) {
 149  	out := AppendTimestamp([]byte("x"), 0x0102030405060708)
 150  	if len(out) != 9 {
 151  		t.Fatalf("AppendTimestamp len = %d", len(out))
 152  	}
 153  	if out[0] != 'x' {
 154  		t.Fatal("AppendTimestamp clobbered dst")
 155  	}
 156  	if GetTimestamp(out[1:]) != 0x0102030405060708 {
 157  		t.Fatal("AppendTimestamp payload")
 158  	}
 159  }
 160  
 161  func TestKindRoundTrip(t *testing.T) {
 162  	vals := []uint16{0, 1, 7, 255, 256, 30023, 65535}
 163  	for _, v := range vals {
 164  		buf := []byte{:2}
 165  		PutKind(buf, v)
 166  		if got := GetKind(buf); got != v {
 167  			t.Fatalf("GetKind(PutKind(%d)) = %d", v, got)
 168  		}
 169  	}
 170  	kbuf := []byte{:2}
 171  	PutKind(kbuf, 0xABCD)
 172  	if !bytes.Equal(kbuf, []byte{0xAB, 0xCD}) {
 173  		t.Fatalf("PutKind = %x", kbuf)
 174  	}
 175  }
 176  
 177  func TestAppendKind(t *testing.T) {
 178  	out := AppendKind([]byte("k"), 7)
 179  	if !bytes.Equal(out, []byte{'k', 0, 7}) {
 180  		t.Fatalf("AppendKind = %x", out)
 181  	}
 182  	if len(AppendKind(nil, 0)) != 2 {
 183  		t.Fatal("AppendKind(nil) length")
 184  	}
 185  	if GetKind(AppendKind(nil, 30023)) != 30023 {
 186  		t.Fatal("AppendKind payload")
 187  	}
 188  }
 189