2023-01-27 21:37:20 +00:00
|
|
|
// Copyright (c) Tailscale Inc & AUTHORS
|
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
2022-07-07 19:54:04 +01:00
|
|
|
|
|
|
|
package tka
|
|
|
|
|
|
|
|
import (
|
2022-07-12 20:23:43 +01:00
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2022-07-07 19:54:04 +01:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
"golang.org/x/crypto/blake2s"
|
|
|
|
)
|
|
|
|
|
|
|
|
// randHash derives a fake blake2s hash from the test name
|
|
|
|
// and the given seed.
|
|
|
|
func randHash(t *testing.T, seed int64) [blake2s.Size]byte {
|
|
|
|
var out [blake2s.Size]byte
|
|
|
|
testingRand(t, seed).Read(out[:])
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImplementsChonk(t *testing.T) {
|
2022-07-12 20:23:43 +01:00
|
|
|
impls := []Chonk{&Mem{}, &FS{}}
|
2022-07-07 19:54:04 +01:00
|
|
|
t.Logf("chonks: %v", impls)
|
|
|
|
}
|
|
|
|
|
2022-07-12 20:23:43 +01:00
|
|
|
func TestTailchonk_ChildAUMs(t *testing.T) {
|
|
|
|
for _, chonk := range []Chonk{&Mem{}, &FS{base: t.TempDir()}} {
|
|
|
|
t.Run(fmt.Sprintf("%T", chonk), func(t *testing.T) {
|
|
|
|
parentHash := randHash(t, 1)
|
|
|
|
data := []AUM{
|
|
|
|
{
|
|
|
|
MessageKind: AUMRemoveKey,
|
|
|
|
KeyID: []byte{1, 2},
|
|
|
|
PrevAUMHash: parentHash[:],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
MessageKind: AUMRemoveKey,
|
|
|
|
KeyID: []byte{3, 4},
|
|
|
|
PrevAUMHash: parentHash[:],
|
|
|
|
},
|
|
|
|
}
|
2022-07-07 19:54:04 +01:00
|
|
|
|
2022-07-12 20:23:43 +01:00
|
|
|
if err := chonk.CommitVerifiedAUMs(data); err != nil {
|
|
|
|
t.Fatalf("CommitVerifiedAUMs failed: %v", err)
|
|
|
|
}
|
|
|
|
stored, err := chonk.ChildAUMs(parentHash)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("ChildAUMs failed: %v", err)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(data, stored); diff != "" {
|
|
|
|
t.Errorf("stored AUM differs (-want, +got):\n%s", diff)
|
2022-09-27 20:30:04 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTailchonk_AUMMissing(t *testing.T) {
|
|
|
|
for _, chonk := range []Chonk{&Mem{}, &FS{base: t.TempDir()}} {
|
|
|
|
t.Run(fmt.Sprintf("%T", chonk), func(t *testing.T) {
|
|
|
|
var notExists AUMHash
|
|
|
|
notExists[:][0] = 42
|
|
|
|
if _, err := chonk.AUM(notExists); err != os.ErrNotExist {
|
|
|
|
t.Errorf("chonk.AUM(notExists).err = %v, want %v", err, os.ErrNotExist)
|
2022-07-12 20:23:43 +01:00
|
|
|
}
|
|
|
|
})
|
2022-07-07 19:54:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTailchonkMem_Orphans(t *testing.T) {
|
|
|
|
chonk := Mem{}
|
|
|
|
|
|
|
|
parentHash := randHash(t, 1)
|
|
|
|
orphan := AUM{MessageKind: AUMNoOp}
|
|
|
|
aums := []AUM{
|
|
|
|
orphan,
|
|
|
|
// A parent is specified, so we shouldnt see it in GetOrphans()
|
|
|
|
{
|
|
|
|
MessageKind: AUMRemoveKey,
|
|
|
|
KeyID: []byte{3, 4},
|
|
|
|
PrevAUMHash: parentHash[:],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
if err := chonk.CommitVerifiedAUMs(aums); err != nil {
|
|
|
|
t.Fatalf("CommitVerifiedAUMs failed: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stored, err := chonk.Orphans()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Orphans failed: %v", err)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff([]AUM{orphan}, stored); diff != "" {
|
|
|
|
t.Errorf("stored AUM differs (-want, +got):\n%s", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-12 20:23:43 +01:00
|
|
|
func TestTailchonk_ReadChainFromHead(t *testing.T) {
|
|
|
|
for _, chonk := range []Chonk{&Mem{}, &FS{base: t.TempDir()}} {
|
2022-07-07 19:54:04 +01:00
|
|
|
|
2022-07-12 20:23:43 +01:00
|
|
|
t.Run(fmt.Sprintf("%T", chonk), func(t *testing.T) {
|
|
|
|
genesis := AUM{MessageKind: AUMRemoveKey, KeyID: []byte{1, 2}}
|
|
|
|
gHash := genesis.Hash()
|
|
|
|
intermediate := AUM{PrevAUMHash: gHash[:]}
|
|
|
|
iHash := intermediate.Hash()
|
|
|
|
leaf := AUM{PrevAUMHash: iHash[:]}
|
2022-07-07 19:54:04 +01:00
|
|
|
|
2022-07-12 20:23:43 +01:00
|
|
|
commitSet := []AUM{
|
|
|
|
genesis,
|
|
|
|
intermediate,
|
|
|
|
leaf,
|
|
|
|
}
|
|
|
|
if err := chonk.CommitVerifiedAUMs(commitSet); err != nil {
|
|
|
|
t.Fatalf("CommitVerifiedAUMs failed: %v", err)
|
|
|
|
}
|
|
|
|
// t.Logf("genesis hash = %X", genesis.Hash())
|
|
|
|
// t.Logf("intermediate hash = %X", intermediate.Hash())
|
|
|
|
// t.Logf("leaf hash = %X", leaf.Hash())
|
|
|
|
|
|
|
|
// Read the chain from the leaf backwards.
|
|
|
|
gotLeafs, err := chonk.Heads()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Heads failed: %v", err)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff([]AUM{leaf}, gotLeafs); diff != "" {
|
|
|
|
t.Fatalf("leaf AUM differs (-want, +got):\n%s", diff)
|
|
|
|
}
|
|
|
|
|
|
|
|
parent, _ := gotLeafs[0].Parent()
|
|
|
|
gotIntermediate, err := chonk.AUM(parent)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("AUM(<intermediate>) failed: %v", err)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(intermediate, gotIntermediate); diff != "" {
|
|
|
|
t.Errorf("intermediate AUM differs (-want, +got):\n%s", diff)
|
|
|
|
}
|
|
|
|
|
|
|
|
parent, _ = gotIntermediate.Parent()
|
|
|
|
gotGenesis, err := chonk.AUM(parent)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("AUM(<genesis>) failed: %v", err)
|
|
|
|
}
|
|
|
|
if diff := cmp.Diff(genesis, gotGenesis); diff != "" {
|
|
|
|
t.Errorf("genesis AUM differs (-want, +got):\n%s", diff)
|
|
|
|
}
|
|
|
|
})
|
2022-07-07 19:54:04 +01:00
|
|
|
}
|
2022-07-12 20:23:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestTailchonkFS_Commit(t *testing.T) {
|
|
|
|
chonk := &FS{base: t.TempDir()}
|
|
|
|
parentHash := randHash(t, 1)
|
|
|
|
aum := AUM{MessageKind: AUMNoOp, PrevAUMHash: parentHash[:]}
|
|
|
|
|
|
|
|
if err := chonk.CommitVerifiedAUMs([]AUM{aum}); err != nil {
|
|
|
|
t.Fatal(err)
|
2022-07-07 19:54:04 +01:00
|
|
|
}
|
|
|
|
|
2022-08-07 00:11:33 +01:00
|
|
|
dir, base := chonk.aumDir(aum.Hash())
|
2022-08-25 20:47:30 +01:00
|
|
|
if got, want := dir, filepath.Join(chonk.base, "PD"); got != want {
|
2022-08-07 00:11:33 +01:00
|
|
|
t.Errorf("aum dir=%s, want %s", got, want)
|
2022-07-12 20:23:43 +01:00
|
|
|
}
|
2022-08-25 20:47:30 +01:00
|
|
|
if want := "PD57DVP6GKC76OOZMXFFZUSOEFQXOLAVT7N2ZM5KB3HDIMCANF4A"; base != want {
|
2022-08-07 00:11:33 +01:00
|
|
|
t.Errorf("aum base=%s, want %s", base, want)
|
|
|
|
}
|
|
|
|
if _, err := os.Stat(filepath.Join(dir, base)); err != nil {
|
2022-07-12 20:23:43 +01:00
|
|
|
t.Errorf("stat of AUM file failed: %v", err)
|
2022-07-07 19:54:04 +01:00
|
|
|
}
|
2022-08-07 00:11:33 +01:00
|
|
|
if _, err := os.Stat(filepath.Join(chonk.base, "M7", "M7LL2NDB4NKCZIUPVS6RDM2GUOIMW6EEAFVBWMVCPUANQJPHT3SQ")); err != nil {
|
2022-07-12 20:23:43 +01:00
|
|
|
t.Errorf("stat of AUM parent failed: %v", err)
|
2022-07-07 19:54:04 +01:00
|
|
|
}
|
|
|
|
}
|