blob: 826f2e70cd1217bd97b091a32ce6740d38af5f8f [file] [log] [blame]
Tim Windelschmidt6d33a432025-02-04 14:34:25 +01001// Copyright The Monogon Project Authors.
Serge Bazanski5faa2fc2020-09-07 14:09:30 +02002// SPDX-License-Identifier: Apache-2.0
Serge Bazanski5faa2fc2020-09-07 14:09:30 +02003
4package logtree
5
6import (
7 "fmt"
Serge Bazanski12971d62020-11-17 12:12:58 +01008 "strings"
Serge Bazanski5faa2fc2020-09-07 14:09:30 +02009 "testing"
Serge Bazanski12971d62020-11-17 12:12:58 +010010 "time"
Serge Bazanski3c5d0632024-09-12 10:49:12 +000011
12 "source.monogon.dev/go/logging"
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020013)
14
Serge Bazanski12971d62020-11-17 12:12:58 +010015func testPayload(msg string) *LeveledPayload {
16 return &LeveledPayload{
17 messages: []string{msg},
18 timestamp: time.Now(),
Serge Bazanski3c5d0632024-09-12 10:49:12 +000019 severity: logging.INFO,
Serge Bazanski12971d62020-11-17 12:12:58 +010020 file: "main.go",
21 line: 1337,
22 }
23}
24
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020025func TestJournalRetention(t *testing.T) {
26 j := newJournal()
27
28 for i := 0; i < 9000; i += 1 {
29 e := &entry{
30 origin: "main",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020031 leveled: testPayload(fmt.Sprintf("test %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020032 }
33 j.append(e)
34 }
35
Serge Bazanski8fab0142023-03-29 16:48:16 +020036 entries := j.getEntries(BacklogAllAvailable, "main")
Tim Windelschmidt9e964882025-07-22 01:06:21 +020037 if want, got := defaultDNQuota, len(entries); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020038 t.Fatalf("wanted %d entries, got %d", want, got)
39 }
40 for i, entry := range entries {
Tim Windelschmidt9e964882025-07-22 01:06:21 +020041 want := fmt.Sprintf("test %d", (9000-defaultDNQuota)+i)
Serge Bazanski12971d62020-11-17 12:12:58 +010042 got := strings.Join(entry.leveled.messages, "\n")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020043 if want != got {
44 t.Fatalf("wanted entry %q, got %q", want, got)
45 }
46 }
47}
48
49func TestJournalQuota(t *testing.T) {
50 j := newJournal()
51
52 for i := 0; i < 9000; i += 1 {
53 j.append(&entry{
54 origin: "chatty",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020055 leveled: testPayload(fmt.Sprintf("chatty %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020056 })
57 if i%10 == 0 {
58 j.append(&entry{
59 origin: "solemn",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020060 leveled: testPayload(fmt.Sprintf("solemn %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020061 })
62 }
63 }
64
Serge Bazanski8fab0142023-03-29 16:48:16 +020065 entries := j.getEntries(BacklogAllAvailable, "chatty")
Tim Windelschmidt9e964882025-07-22 01:06:21 +020066 if want, got := defaultDNQuota, len(entries); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020067 t.Fatalf("wanted %d chatty entries, got %d", want, got)
68 }
Serge Bazanski8fab0142023-03-29 16:48:16 +020069 entries = j.getEntries(BacklogAllAvailable, "solemn")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020070 if want, got := 900, len(entries); want != got {
71 t.Fatalf("wanted %d solemn entries, got %d", want, got)
72 }
Serge Bazanski8fab0142023-03-29 16:48:16 +020073 entries = j.getEntries(BacklogAllAvailable, "absent")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020074 if want, got := 0, len(entries); want != got {
75 t.Fatalf("wanted %d absent entries, got %d", want, got)
76 }
77
Serge Bazanski8fab0142023-03-29 16:48:16 +020078 entries = j.scanEntries(BacklogAllAvailable, filterAll())
Tim Windelschmidt9e964882025-07-22 01:06:21 +020079 if want, got := defaultDNQuota+900, len(entries); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020080 t.Fatalf("wanted %d total entries, got %d", want, got)
81 }
82 setMessages := make(map[string]bool)
83 for _, entry := range entries {
Serge Bazanski12971d62020-11-17 12:12:58 +010084 setMessages[strings.Join(entry.leveled.messages, "\n")] = true
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020085 }
86
87 for i := 0; i < 900; i += 1 {
88 want := fmt.Sprintf("solemn %d", i*10)
89 if !setMessages[want] {
90 t.Fatalf("could not find entry %q in journal", want)
91 }
92 }
Tim Windelschmidt9e964882025-07-22 01:06:21 +020093 for i := 0; i < defaultDNQuota; i += 1 {
94 want := fmt.Sprintf("chatty %d", i+(9000-defaultDNQuota))
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020095 if !setMessages[want] {
96 t.Fatalf("could not find entry %q in journal", want)
97 }
98 }
99}
100
101func TestJournalSubtree(t *testing.T) {
102 j := newJournal()
Serge Bazanski1bfa0c22020-10-14 16:45:07 +0200103 j.append(&entry{origin: "a", leveled: testPayload("a")})
104 j.append(&entry{origin: "a.b", leveled: testPayload("a.b")})
105 j.append(&entry{origin: "a.b.c", leveled: testPayload("a.b.c")})
106 j.append(&entry{origin: "a.b.d", leveled: testPayload("a.b.d")})
107 j.append(&entry{origin: "e.f", leveled: testPayload("e.f")})
108 j.append(&entry{origin: "e.g", leveled: testPayload("e.g")})
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200109
110 expect := func(f filter, msgs ...string) string {
Serge Bazanski8fab0142023-03-29 16:48:16 +0200111 res := j.scanEntries(BacklogAllAvailable, f)
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200112 set := make(map[string]bool)
113 for _, entry := range res {
Serge Bazanski12971d62020-11-17 12:12:58 +0100114 set[strings.Join(entry.leveled.messages, "\n")] = true
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200115 }
116
117 for _, want := range msgs {
118 if !set[want] {
119 return fmt.Sprintf("missing entry %q", want)
120 }
121 }
122 return ""
123 }
124
125 if res := expect(filterAll(), "a", "a.b", "a.b.c", "a.b.d", "e.f", "e.g"); res != "" {
126 t.Fatalf("All: %s", res)
127 }
128 if res := expect(filterSubtree("a"), "a", "a.b", "a.b.c", "a.b.d"); res != "" {
129 t.Fatalf("Subtree(a): %s", res)
130 }
131 if res := expect(filterSubtree("a.b"), "a.b", "a.b.c", "a.b.d"); res != "" {
132 t.Fatalf("Subtree(a.b): %s", res)
133 }
134 if res := expect(filterSubtree("e"), "e.f", "e.g"); res != "" {
135 t.Fatalf("Subtree(a.b): %s", res)
136 }
137}
Serge Bazanski367ee272023-03-16 17:50:39 +0100138
139func TestDN_Shorten(t *testing.T) {
140 for i, te := range []struct {
141 input string
142 maxLen int
143 want string
144 }{
145 {"root.role.controlplane.launcher.consensus.autopromoter", 20, "cplane autopromoter"},
146 {"networking.interfaces", 20, "net ifaces"},
147 {"hostsfile", 20, "hostsfile"},
148 {"root.dhcp-server", 20, "dhcp-server"},
149 {"root.role.kubernetes.run.kubernetes.apiserver", 20, "k8s apiserver"},
150 {"some.very.long.dn.that.cant.be.shortened", 20, "...cant be shortened"},
151 {"network.interfaces.dhcp", 20, "net ifaces dhcp"},
152 } {
153 got := DN(te.input).Shorten(MetropolisShortenDict, te.maxLen)
154 if len(got) > te.maxLen {
155 t.Errorf("case %d: output %q too long, got %d bytes, wanted %d", i, got, len(got), te.maxLen)
156 } else {
157 if te.want != got {
158 t.Errorf("case %d: wanted %q, got %q", i, te.want, got)
159 }
160 }
161 }
162}