package serial import ( "bytes" "crypto/sha256" "testing" ) // TestPutGetRoundTrip pins the 5-byte big-endian encoding: every byte position // matters because index keys are byte-compared by the sorted file. func TestPutGetRoundTrip(t *testing.T) { vals := []uint64{0, 1, 255, 256, 65535, 1 << 32, Max - 1, Max} for _, v := range vals { buf := []byte{:Len} Put(buf, v) if got := Get(buf); got != v { t.Fatalf("Get(Put(%d)) = %d", v, got) } } } func TestPutByteLayout(t *testing.T) { buf := []byte{:Len} Put(buf, 0x0102030405) want := []byte{0x01, 0x02, 0x03, 0x04, 0x05} if !bytes.Equal(buf, want) { t.Fatal("Put byte order") } Put(buf, 0) if !bytes.Equal(buf, []byte{0, 0, 0, 0, 0}) { t.Fatal("Put zero") } Put(buf, Max) if !bytes.Equal(buf, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) { t.Fatal("Put Max") } } func TestGetReadsEveryByte(t *testing.T) { // One bit per byte position: a decode that drops a shift reads wrong here. if Get([]byte{1, 0, 0, 0, 0}) != 1<<32 { t.Fatal("byte 0 shift") } if Get([]byte{0, 1, 0, 0, 0}) != 1<<24 { t.Fatal("byte 1 shift") } if Get([]byte{0, 0, 1, 0, 0}) != 1<<16 { t.Fatal("byte 2 shift") } if Get([]byte{0, 0, 0, 1, 0}) != 1<<8 { t.Fatal("byte 3 shift") } if Get([]byte{0, 0, 0, 0, 1}) != 1 { t.Fatal("byte 4 shift") } } func TestAppend(t *testing.T) { dst := Append([]byte("ab"), 0x0102030405) want := []byte("ab\x01\x02\x03\x04\x05") if !bytes.Equal(dst, want) { t.Fatalf("Append = %x", dst) } only := Append(nil, 0) if len(only) != Len { t.Fatalf("Append(nil) len = %d", len(only)) } if Get(only) != 0 { t.Fatal("Append(nil) value") } // Two appends stack. two := Append(Append(nil, 1), 2) if len(two) != 2*Len { t.Fatalf("two appends len = %d", len(two)) } if Get(two[:Len]) != 1 || Get(two[Len:]) != 2 { t.Fatal("two appends value") } } // TestHashHelpers pins length, determinism and the exact sha256 prefix, since // the engine compares these hashes as index keys. func TestHashHelpers(t *testing.T) { in := []byte("the quick brown fox") sum := sha256.Sum256(in) ih := IdHash(in) if len(ih) != HashLen { t.Fatalf("IdHash len = %d", len(ih)) } if !bytes.Equal(ih, sum[:HashLen]) { t.Fatal("IdHash is not the sha256 prefix") } if !bytes.Equal(IdHash(in), ih) { t.Fatal("IdHash not deterministic") } if bytes.Equal(IdHash(in), IdHash([]byte("the quick brown fo"))) { t.Fatal("IdHash collision on near input") } ph := PubHash(in) if len(ph) != HashLen || !bytes.Equal(ph, sum[:HashLen]) { t.Fatal("PubHash is not the sha256 prefix") } // Same input, same bytes: the three helpers are all truncated sha256. if !bytes.Equal(ph, ih) { t.Fatal("IdHash and PubHash differ for the same input") } ihash := Ident(in) if len(ihash) != HashLen || !bytes.Equal(ihash, sum[:HashLen]) { t.Fatal("Ident is not the sha256 prefix") } zeroSum := sha256.Sum256(nil) if !bytes.Equal(Ident(nil), zeroSum[:HashLen]) { t.Fatal("Ident(nil)") } if len(Ident(nil)) != HashLen { t.Fatal("Ident(nil) length") } } func TestTimestampRoundTrip(t *testing.T) { vals := []int64{0, 1, -1, 1700000000, 1 << 40, -1700000000} for _, v := range vals { buf := []byte{:8} PutTimestamp(buf, v) if got := GetTimestamp(buf); got != v { t.Fatalf("GetTimestamp(PutTimestamp(%d)) = %d", v, got) } } } func TestTimestampByteLayout(t *testing.T) { buf := []byte{:8} PutTimestamp(buf, 0x0102030405060708) want := []byte{1, 2, 3, 4, 5, 6, 7, 8} if !bytes.Equal(buf, want) { t.Fatalf("PutTimestamp = %x", buf) } // -1 is all ones, so a signed cast that clamps would fail here. PutTimestamp(buf, -1) if !bytes.Equal(buf, []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}) { t.Fatal("PutTimestamp(-1)") } } func TestAppendTimestamp(t *testing.T) { out := AppendTimestamp([]byte("x"), 0x0102030405060708) if len(out) != 9 { t.Fatalf("AppendTimestamp len = %d", len(out)) } if out[0] != 'x' { t.Fatal("AppendTimestamp clobbered dst") } if GetTimestamp(out[1:]) != 0x0102030405060708 { t.Fatal("AppendTimestamp payload") } } func TestKindRoundTrip(t *testing.T) { vals := []uint16{0, 1, 7, 255, 256, 30023, 65535} for _, v := range vals { buf := []byte{:2} PutKind(buf, v) if got := GetKind(buf); got != v { t.Fatalf("GetKind(PutKind(%d)) = %d", v, got) } } kbuf := []byte{:2} PutKind(kbuf, 0xABCD) if !bytes.Equal(kbuf, []byte{0xAB, 0xCD}) { t.Fatalf("PutKind = %x", kbuf) } } func TestAppendKind(t *testing.T) { out := AppendKind([]byte("k"), 7) if !bytes.Equal(out, []byte{'k', 0, 7}) { t.Fatalf("AppendKind = %x", out) } if len(AppendKind(nil, 0)) != 2 { t.Fatal("AppendKind(nil) length") } if GetKind(AppendKind(nil, 30023)) != 30023 { t.Fatal("AppendKind payload") } }