blob: d2957327362e491dd06797af62178a07357802c2 [file] [log] [blame]
Serge Bazanski5faa2fc2020-09-07 14:09:30 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package logtree
18
19import (
20 "fmt"
Serge Bazanski12971d62020-11-17 12:12:58 +010021 "strings"
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020022 "testing"
Serge Bazanski12971d62020-11-17 12:12:58 +010023 "time"
Serge Bazanski3c5d0632024-09-12 10:49:12 +000024
25 "source.monogon.dev/go/logging"
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020026)
27
Serge Bazanski12971d62020-11-17 12:12:58 +010028func testPayload(msg string) *LeveledPayload {
29 return &LeveledPayload{
30 messages: []string{msg},
31 timestamp: time.Now(),
Serge Bazanski3c5d0632024-09-12 10:49:12 +000032 severity: logging.INFO,
Serge Bazanski12971d62020-11-17 12:12:58 +010033 file: "main.go",
34 line: 1337,
35 }
36}
37
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020038func TestJournalRetention(t *testing.T) {
39 j := newJournal()
40
41 for i := 0; i < 9000; i += 1 {
42 e := &entry{
43 origin: "main",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020044 leveled: testPayload(fmt.Sprintf("test %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020045 }
46 j.append(e)
47 }
48
Serge Bazanski8fab0142023-03-29 16:48:16 +020049 entries := j.getEntries(BacklogAllAvailable, "main")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020050 if want, got := 8192, len(entries); want != got {
51 t.Fatalf("wanted %d entries, got %d", want, got)
52 }
53 for i, entry := range entries {
54 want := fmt.Sprintf("test %d", (9000-8192)+i)
Serge Bazanski12971d62020-11-17 12:12:58 +010055 got := strings.Join(entry.leveled.messages, "\n")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020056 if want != got {
57 t.Fatalf("wanted entry %q, got %q", want, got)
58 }
59 }
60}
61
62func TestJournalQuota(t *testing.T) {
63 j := newJournal()
64
65 for i := 0; i < 9000; i += 1 {
66 j.append(&entry{
67 origin: "chatty",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020068 leveled: testPayload(fmt.Sprintf("chatty %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020069 })
70 if i%10 == 0 {
71 j.append(&entry{
72 origin: "solemn",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020073 leveled: testPayload(fmt.Sprintf("solemn %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020074 })
75 }
76 }
77
Serge Bazanski8fab0142023-03-29 16:48:16 +020078 entries := j.getEntries(BacklogAllAvailable, "chatty")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020079 if want, got := 8192, len(entries); want != got {
80 t.Fatalf("wanted %d chatty entries, got %d", want, got)
81 }
Serge Bazanski8fab0142023-03-29 16:48:16 +020082 entries = j.getEntries(BacklogAllAvailable, "solemn")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020083 if want, got := 900, len(entries); want != got {
84 t.Fatalf("wanted %d solemn entries, got %d", want, got)
85 }
Serge Bazanski8fab0142023-03-29 16:48:16 +020086 entries = j.getEntries(BacklogAllAvailable, "absent")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020087 if want, got := 0, len(entries); want != got {
88 t.Fatalf("wanted %d absent entries, got %d", want, got)
89 }
90
Serge Bazanski8fab0142023-03-29 16:48:16 +020091 entries = j.scanEntries(BacklogAllAvailable, filterAll())
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020092 if want, got := 8192+900, len(entries); want != got {
93 t.Fatalf("wanted %d total entries, got %d", want, got)
94 }
95 setMessages := make(map[string]bool)
96 for _, entry := range entries {
Serge Bazanski12971d62020-11-17 12:12:58 +010097 setMessages[strings.Join(entry.leveled.messages, "\n")] = true
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020098 }
99
100 for i := 0; i < 900; i += 1 {
101 want := fmt.Sprintf("solemn %d", i*10)
102 if !setMessages[want] {
103 t.Fatalf("could not find entry %q in journal", want)
104 }
105 }
106 for i := 0; i < 8192; i += 1 {
107 want := fmt.Sprintf("chatty %d", i+(9000-8192))
108 if !setMessages[want] {
109 t.Fatalf("could not find entry %q in journal", want)
110 }
111 }
112}
113
114func TestJournalSubtree(t *testing.T) {
115 j := newJournal()
Serge Bazanski1bfa0c22020-10-14 16:45:07 +0200116 j.append(&entry{origin: "a", leveled: testPayload("a")})
117 j.append(&entry{origin: "a.b", leveled: testPayload("a.b")})
118 j.append(&entry{origin: "a.b.c", leveled: testPayload("a.b.c")})
119 j.append(&entry{origin: "a.b.d", leveled: testPayload("a.b.d")})
120 j.append(&entry{origin: "e.f", leveled: testPayload("e.f")})
121 j.append(&entry{origin: "e.g", leveled: testPayload("e.g")})
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200122
123 expect := func(f filter, msgs ...string) string {
Serge Bazanski8fab0142023-03-29 16:48:16 +0200124 res := j.scanEntries(BacklogAllAvailable, f)
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200125 set := make(map[string]bool)
126 for _, entry := range res {
Serge Bazanski12971d62020-11-17 12:12:58 +0100127 set[strings.Join(entry.leveled.messages, "\n")] = true
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200128 }
129
130 for _, want := range msgs {
131 if !set[want] {
132 return fmt.Sprintf("missing entry %q", want)
133 }
134 }
135 return ""
136 }
137
138 if res := expect(filterAll(), "a", "a.b", "a.b.c", "a.b.d", "e.f", "e.g"); res != "" {
139 t.Fatalf("All: %s", res)
140 }
141 if res := expect(filterSubtree("a"), "a", "a.b", "a.b.c", "a.b.d"); res != "" {
142 t.Fatalf("Subtree(a): %s", res)
143 }
144 if res := expect(filterSubtree("a.b"), "a.b", "a.b.c", "a.b.d"); res != "" {
145 t.Fatalf("Subtree(a.b): %s", res)
146 }
147 if res := expect(filterSubtree("e"), "e.f", "e.g"); res != "" {
148 t.Fatalf("Subtree(a.b): %s", res)
149 }
150}
Serge Bazanski367ee272023-03-16 17:50:39 +0100151
152func TestDN_Shorten(t *testing.T) {
153 for i, te := range []struct {
154 input string
155 maxLen int
156 want string
157 }{
158 {"root.role.controlplane.launcher.consensus.autopromoter", 20, "cplane autopromoter"},
159 {"networking.interfaces", 20, "net ifaces"},
160 {"hostsfile", 20, "hostsfile"},
161 {"root.dhcp-server", 20, "dhcp-server"},
162 {"root.role.kubernetes.run.kubernetes.apiserver", 20, "k8s apiserver"},
163 {"some.very.long.dn.that.cant.be.shortened", 20, "...cant be shortened"},
164 {"network.interfaces.dhcp", 20, "net ifaces dhcp"},
165 } {
166 got := DN(te.input).Shorten(MetropolisShortenDict, te.maxLen)
167 if len(got) > te.maxLen {
168 t.Errorf("case %d: output %q too long, got %d bytes, wanted %d", i, got, len(got), te.maxLen)
169 } else {
170 if te.want != got {
171 t.Errorf("case %d: wanted %q, got %q", i, te.want, got)
172 }
173 }
174 }
175}