package index import ( "bytes" "testing" "git.smesh.lol/smesh/pkg/store/serial" ) func ixHash8(fill byte) (b []byte) { b = []byte{:serial.HashLen} for i := range b { b[i] = fill } return } func ixHash32(fill byte) (b []byte) { b = []byte{:32} for i := range b { b[i] = fill } return } // TestKeyLengthConstants ties each declared key length to the length the // builder actually produces. A drift between the two corrupts every fixed // width record read. func TestKeyLengthConstants(t *testing.T) { ih := ixHash8(0x11) ph := ixHash8(0x22) if len(MakeEid(ih, 9)) != EidKeyLen { t.Fatal("EidKeyLen") } if len(MakeEidPrefix(ih)) != 3+serial.HashLen { t.Fatal("MakeEidPrefix length") } if len(MakeSei(9)) != SeiKeyLen { t.Fatal("SeiKeyLen") } if len(MakeCA(7, 9)) != CAKeyLen { t.Fatal("CAKeyLen") } if len(MakeExp(7, 9)) != ExpKeyLen { t.Fatal("ExpKeyLen") } if len(MakeKC(7, 7, 9)) != KCKeyLen { t.Fatal("KCKeyLen") } if len(MakePC(ph, 7, 9)) != PCKeyLen { t.Fatal("PCKeyLen") } if len(MakeKPC(7, ph, 7, 9)) != KPCKeyLen { t.Fatal("KPCKeyLen") } if len(MakeTC('t', ph, 7, 9)) != TCKeyLen { t.Fatal("TCKeyLen") } if len(MakeTKC(7, 't', ph, 7, 9)) != TKCKeyLen { t.Fatal("TKCKeyLen") } if len(MakeTPC(ph, 't', ph, 7, 9)) != TPCKeyLen { t.Fatal("TPCKeyLen") } if len(MakeTKP(7, ph, 't', ph, 7, 9)) != TKPKeyLen { t.Fatal("TKPKeyLen") } if len(MakeWrd(ph, 9)) != WrdKeyLen { t.Fatal("WrdKeyLen") } if len(MakePks(ph, 9)) != PksKeyLen { t.Fatal("PksKeyLen") } if len(MakeSpk(9)) != SpkKeyLen { t.Fatal("SpkKeyLen") } if len(MakeSeiRec(9, ixHash32(3))) != SeiRecLen { t.Fatal("SeiRecLen") } if len(MakeSpkRec(9, ixHash32(4))) != SpkRecLen { t.Fatal("SpkRecLen") } if len(MakeFpc(9, ixHash32(5), ph, 7)) != FpcKeyLen { t.Fatal("FpcKeyLen") } if len(MakeEpg(1, 2, 7, 3)) != EpgKeyLen { t.Fatal("EpgKeyLen") } if len(MakePeg(1, 7, 3, 2)) != PegKeyLen { t.Fatal("PegKeyLen") } if len(MakeEeg(1, 2, 7, 3)) != EegKeyLen { t.Fatal("EegKeyLen") } if len(MakeGee(1, 7, 3, 2)) != GeeKeyLen { t.Fatal("GeeKeyLen") } if len(MakePpg(1, 2, 7, 3, 4)) != PpgKeyLen { t.Fatal("PpgKeyLen") } if len(MakeGpp(1, 7, 3, 2, 4)) != GppKeyLen { t.Fatal("GppKeyLen") } } func TestEidKeys(t *testing.T) { ih := ixHash8(0xAB) k := MakeEid(ih, 0x0102030405) if !bytes.Equal(k[:3], Eid[:]) { t.Fatalf("Eid prefix = %x", k[:3]) } if !bytes.Equal(k[3:3+serial.HashLen], ih) { t.Fatal("Eid hash field") } if serial.Get(k[3+serial.HashLen:]) != 0x0102030405 { t.Fatal("Eid serial field") } // The prefix is exactly the key with the serial stripped. p := MakeEidPrefix(ih) if len(p) != 3+serial.HashLen { t.Fatalf("EidPrefix len = %d", len(p)) } if !bytes.Equal(p, k[:3+serial.HashLen]) { t.Fatal("EidPrefix is not the key prefix") } if EidCmpLen != 3+serial.HashLen { t.Fatal("EidCmpLen must stop at the hash") } } func TestSeiKeys(t *testing.T) { k := MakeSei(0x0102030405) if !bytes.Equal(k[:3], Sei[:]) { t.Fatal("Sei prefix") } if serial.Get(k[3:]) != 0x0102030405 { t.Fatal("Sei serial") } id := ixHash32(0x7E) rec := MakeSeiRec(0x0102030405, id) if !bytes.Equal(rec[:SeiKeyLen], k) { t.Fatal("SeiRec key portion") } if !bytes.Equal(rec[SeiKeyLen:], id) { t.Fatal("SeiRec value portion") } } func TestOrderingKeys(t *testing.T) { ts := int64(1700000000) ser := uint64(0x0102030405) ca := MakeCA(ts, ser) if !bytes.Equal(ca[:3], CA[:]) { t.Fatal("CA prefix") } if serial.GetTimestamp(ca[3:11]) != ts { t.Fatal("CA timestamp") } if serial.Get(ca[11:]) != ser { t.Fatal("CA serial") } kc := MakeKC(30023, ts, ser) if !bytes.Equal(kc[:3], KC[:]) { t.Fatal("KC prefix") } if serial.GetKind(kc[3:5]) != 30023 { t.Fatal("KC kind") } if serial.GetTimestamp(kc[5:13]) != ts { t.Fatal("KC timestamp") } if serial.Get(kc[13:]) != ser { t.Fatal("KC serial") } ph := ixHash8(0x33) pc := MakePC(ph, ts, ser) if !bytes.Equal(pc[:3], PC[:]) { t.Fatal("PC prefix") } if !bytes.Equal(pc[3:3+serial.HashLen], ph) { t.Fatal("PC pubhash") } if serial.GetTimestamp(pc[3+serial.HashLen:3+serial.HashLen+8]) != ts { t.Fatal("PC timestamp") } if serial.Get(pc[3+serial.HashLen+8:]) != ser { t.Fatal("PC serial") } kpc := MakeKPC(7, ph, ts, ser) if !bytes.Equal(kpc[:3], KPC[:]) { t.Fatal("KPC prefix") } if serial.GetKind(kpc[3:5]) != 7 { t.Fatal("KPC kind") } if !bytes.Equal(kpc[5:5+serial.HashLen], ph) { t.Fatal("KPC pubhash") } if serial.GetTimestamp(kpc[5+serial.HashLen:5+serial.HashLen+8]) != ts { t.Fatal("KPC timestamp") } if serial.Get(kpc[5+serial.HashLen+8:]) != ser { t.Fatal("KPC serial") } } func TestTagKeys(t *testing.T) { ts := int64(1700000000) ser := uint64(0x0102030405) vh := ixHash8(0x44) ph := ixHash8(0x55) tc := MakeTC('t', vh, ts, ser) if !bytes.Equal(tc[:3], TC[:]) { t.Fatal("TC prefix") } if tc[3] != 't' { t.Fatal("TC tag key") } if !bytes.Equal(tc[4:4+serial.HashLen], vh) { t.Fatal("TC value hash") } if serial.GetTimestamp(tc[4+serial.HashLen:4+serial.HashLen+8]) != ts { t.Fatal("TC timestamp") } if serial.Get(tc[4+serial.HashLen+8:]) != ser { t.Fatal("TC serial") } tkc := MakeTKC(7, 'p', vh, ts, ser) if !bytes.Equal(tkc[:3], TKC[:]) { t.Fatal("TKC prefix") } if serial.GetKind(tkc[3:5]) != 7 { t.Fatal("TKC kind") } if tkc[5] != 'p' { t.Fatal("TKC tag key") } if !bytes.Equal(tkc[6:6+serial.HashLen], vh) { t.Fatal("TKC value hash") } if serial.GetTimestamp(tkc[6+serial.HashLen:6+serial.HashLen+8]) != ts { t.Fatal("TKC timestamp") } if serial.Get(tkc[6+serial.HashLen+8:]) != ser { t.Fatal("TKC serial") } tpc := MakeTPC(ph, 'e', vh, ts, ser) if !bytes.Equal(tpc[:3], TPC[:]) { t.Fatal("TPC prefix") } if !bytes.Equal(tpc[3:3+serial.HashLen], ph) { t.Fatal("TPC pubhash") } if tpc[3+serial.HashLen] != 'e' { t.Fatal("TPC tag key") } if !bytes.Equal(tpc[3+serial.HashLen+1:3+serial.HashLen+1+serial.HashLen], vh) { t.Fatal("TPC value hash") } if serial.GetTimestamp(tpc[3+serial.HashLen+1+serial.HashLen:3+serial.HashLen+1+serial.HashLen+8]) != ts { t.Fatal("TPC timestamp") } if serial.Get(tpc[3+serial.HashLen+1+serial.HashLen+8:]) != ser { t.Fatal("TPC serial") } tkp := MakeTKP(7, ph, 'e', vh, ts, ser) if !bytes.Equal(tkp[:3], TKP[:]) { t.Fatal("TKP prefix") } if serial.GetKind(tkp[3:5]) != 7 { t.Fatal("TKP kind") } if !bytes.Equal(tkp[5:5+serial.HashLen], ph) { t.Fatal("TKP pubhash") } if tkp[5+serial.HashLen] != 'e' { t.Fatal("TKP tag key") } if !bytes.Equal(tkp[5+serial.HashLen+1:5+serial.HashLen+1+serial.HashLen], vh) { t.Fatal("TKP value hash") } if serial.GetTimestamp(tkp[5+serial.HashLen+1+serial.HashLen:5+serial.HashLen+1+serial.HashLen+8]) != ts { t.Fatal("TKP timestamp") } if serial.Get(tkp[5+serial.HashLen+1+serial.HashLen+8:]) != ser { t.Fatal("TKP serial") } } func TestWordPubkeyExpFpcKeys(t *testing.T) { ph := ixHash8(0x66) ser := uint64(0x0102030405) ts := int64(1700000000) wrd := MakeWrd(ph, ser) if !bytes.Equal(wrd[:3], Wrd[:]) { t.Fatal("Wrd prefix") } if !bytes.Equal(wrd[3:3+serial.HashLen], ph) { t.Fatal("Wrd hash") } if serial.Get(wrd[3+serial.HashLen:]) != ser { t.Fatal("Wrd serial") } pks := MakePks(ph, ser) if !bytes.Equal(pks[:3], Pks[:]) { t.Fatal("Pks prefix") } if !bytes.Equal(pks[3:3+serial.HashLen], ph) { t.Fatal("Pks hash") } if serial.Get(pks[3+serial.HashLen:]) != ser { t.Fatal("Pks serial") } if PksCmpLen != 3+serial.HashLen { t.Fatal("PksCmpLen must stop at the hash") } spk := MakeSpk(ser) if !bytes.Equal(spk[:3], Spk[:]) { t.Fatal("Spk prefix") } if serial.Get(spk[3:]) != ser { t.Fatal("Spk serial") } pub := ixHash32(0x77) spkRec := MakeSpkRec(ser, pub) if !bytes.Equal(spkRec[:SpkKeyLen], spk) { t.Fatal("SpkRec key portion") } if !bytes.Equal(spkRec[SpkKeyLen:], pub) { t.Fatal("SpkRec value portion") } exp := MakeExp(ts, ser) if !bytes.Equal(exp[:3], Exp[:]) { t.Fatal("Exp prefix") } if serial.GetTimestamp(exp[3:11]) != ts { t.Fatal("Exp timestamp") } if serial.Get(exp[11:]) != ser { t.Fatal("Exp serial") } id := ixHash32(0x88) fpc := MakeFpc(ser, id, ph, ts) if !bytes.Equal(fpc[:3], Fpc[:]) { t.Fatal("Fpc prefix") } if serial.Get(fpc[3:3+serial.Len]) != ser { t.Fatal("Fpc serial") } if !bytes.Equal(fpc[3+serial.Len:3+serial.Len+32], id) { t.Fatal("Fpc full id") } if !bytes.Equal(fpc[3+serial.Len+32:3+serial.Len+32+serial.HashLen], ph) { t.Fatal("Fpc pubhash") } if serial.GetTimestamp(fpc[3+serial.Len+32+serial.HashLen:]) != ts { t.Fatal("Fpc timestamp") } if FpcCmpLen != 3+serial.Len { t.Fatal("FpcCmpLen must stop at the serial") } } func TestGraphKeys(t *testing.T) { ser := uint64(0x0102030405) ser2 := uint64(0x060708090A) epg := MakeEpg(ser, ser2, 7, DirPTagOut) if !bytes.Equal(epg[:3], Epg[:]) { t.Fatal("Epg prefix") } if serial.Get(epg[3:8]) != ser { t.Fatal("Epg event serial") } if serial.Get(epg[8:13]) != ser2 { t.Fatal("Epg pubkey serial") } if serial.GetKind(epg[13:15]) != 7 { t.Fatal("Epg kind") } if epg[15] != DirPTagOut { t.Fatal("Epg direction") } peg := MakePeg(ser2, 7, DirPTagIn, ser) if !bytes.Equal(peg[:3], Peg[:]) { t.Fatal("Peg prefix") } if serial.Get(peg[3:8]) != ser2 { t.Fatal("Peg pubkey serial") } if serial.GetKind(peg[8:10]) != 7 { t.Fatal("Peg kind") } if peg[10] != DirPTagIn { t.Fatal("Peg direction") } if serial.Get(peg[11:]) != ser { t.Fatal("Peg event serial") } eeg := MakeEeg(ser, ser2, 7, DirETagOut) if !bytes.Equal(eeg[:3], Eeg[:]) { t.Fatal("Eeg prefix") } if serial.Get(eeg[3:8]) != ser || serial.Get(eeg[8:13]) != ser2 { t.Fatal("Eeg serials") } if serial.GetKind(eeg[13:15]) != 7 || eeg[15] != DirETagOut { t.Fatal("Eeg kind/dir") } gee := MakeGee(ser2, 7, DirETagIn, ser) if !bytes.Equal(gee[:3], Gee[:]) { t.Fatal("Gee prefix") } if serial.Get(gee[3:8]) != ser2 { t.Fatal("Gee target serial") } if serial.GetKind(gee[8:10]) != 7 || gee[10] != DirETagIn { t.Fatal("Gee kind/dir") } if serial.Get(gee[11:]) != ser { t.Fatal("Gee source serial") } ppg := MakePpg(ser, ser2, 7, DirPKOut, 42) if !bytes.Equal(ppg[:3], Ppg[:]) { t.Fatal("Ppg prefix") } if serial.Get(ppg[3:8]) != ser || serial.Get(ppg[8:13]) != ser2 { t.Fatal("Ppg serials") } if serial.GetKind(ppg[13:15]) != 7 || ppg[15] != DirPKOut { t.Fatal("Ppg kind/dir") } if serial.Get(ppg[16:]) != 42 { t.Fatal("Ppg event serial") } gpp := MakeGpp(ser2, 7, DirPKIn, ser, 42) if !bytes.Equal(gpp[:3], Gpp[:]) { t.Fatal("Gpp prefix") } if serial.Get(gpp[3:8]) != ser2 { t.Fatal("Gpp target pk") } if serial.GetKind(gpp[8:10]) != 7 || gpp[10] != DirPKIn { t.Fatal("Gpp kind/dir") } if serial.Get(gpp[11:16]) != ser { t.Fatal("Gpp source pk") } if serial.Get(gpp[16:]) != 42 { t.Fatal("Gpp event serial") } } // TestEdgeDirections pins the numeric direction values: they are on-disk bytes, // so a renumbering silently changes the meaning of every stored edge. func TestEdgeDirections(t *testing.T) { if DirAuthor != 0 || DirPTagOut != 1 || DirPTagIn != 2 { t.Fatal("event-pubkey directions") } if DirETagOut != 0 || DirETagIn != 1 { t.Fatal("event-event directions") } if DirPKOut != 0 || DirPKIn != 1 { t.Fatal("pubkey-pubkey directions") } }