aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/store/compat_test.go
blob: c8e7fa44b01cca9aa1f67f83557bc3bd59f89277 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package store_test

import (
	"log"
	"math/rand"
	"reflect"
	"slices"
	"testing"
	"time"

	"hakurei.app/container/check"
	"hakurei.app/hst"
	"hakurei.app/internal/store"
	"hakurei.app/message"
)

func TestMulti(t *testing.T) {
	s := store.NewMulti(message.NewMsg(log.New(log.Writer(), "multi: ", 0)), check.MustAbs(t.TempDir()))

	t.Run("list empty store", func(t *testing.T) {
		if identities, err := s.List(); err != nil {
			t.Fatalf("List: error = %v", err)
		} else if len(identities) != 0 {
			t.Fatalf("List: identities = %#v", identities)
		}
	})

	const (
		insertEntryChecked = iota
		insertEntryNoCheck
		insertEntryOtherApp

		tl
	)

	var tc [tl]hst.State
	for i := 0; i < tl; i++ {
		if err := hst.NewInstanceID(&tc[i].ID); err != nil {
			t.Fatalf("cannot create dummy state: %v", err)
		}
		tc[i].PID = rand.Int()
		tc[i].Config = hst.Template()
		tc[i].Time = time.Now()
	}

	do := func(identity int, f func(c store.Cursor)) {
		if ok, err := s.Do(identity, f); err != nil {
			t.Fatalf("Do: ok = %v, error = %v", ok, err)
		}
	}

	insert := func(i, identity int) {
		do(identity, func(c store.Cursor) {
			if err := c.Save(&tc[i]); err != nil {
				t.Fatalf("Save: error = %v", err)
			}
		})
	}

	check := func(i, identity int) {
		do(identity, func(c store.Cursor) {
			if entries, err := c.Load(); err != nil {
				t.Fatalf("Load: error = %v", err)
			} else if got, ok := entries[tc[i].ID]; !ok {
				t.Fatalf("Load: entry %s missing", &tc[i].ID)
			} else {
				got.Time = tc[i].Time
				if !reflect.DeepEqual(got, &tc[i]) {
					t.Fatalf("Load: entry %s got %#v, want %#v", &tc[i].ID, got, &tc[i])
				}
			}
		})
	}

	// insert entry checked
	insert(insertEntryChecked, 0)
	check(insertEntryChecked, 0)

	// insert entry unchecked
	insert(insertEntryNoCheck, 0)

	// insert entry different identity
	insert(insertEntryOtherApp, 1)
	check(insertEntryOtherApp, 1)

	// check previous insertion
	check(insertEntryNoCheck, 0)

	// list identities
	if identities, err := s.List(); err != nil {
		t.Fatalf("List: error = %v", err)
	} else {
		slices.Sort(identities)
		want := []int{0, 1}
		if !slices.Equal(identities, want) {
			t.Fatalf("List() = %#v, want %#v", identities, want)
		}
	}

	// join store
	if entries, err := store.Join(s); err != nil {
		t.Fatalf("Join: error = %v", err)
	} else if len(entries) != 3 {
		t.Fatalf("Join(s) = %#v", entries)
	}

	// clear identity 1
	do(1, func(c store.Cursor) {
		if err := c.Destroy(tc[insertEntryOtherApp].ID); err != nil {
			t.Fatalf("Destroy: error = %v", err)
		}
	})
	do(1, func(c store.Cursor) {
		if l, err := c.Len(); err != nil {
			t.Fatalf("Len: error = %v", err)
		} else if l != 0 {
			t.Fatalf("Len: %d, want 0", l)
		}
	})
}