blob: 1df3f125b76bd2ea36b3ba4f98c64649fb6ba110 [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 Bazanski5faa2fc2020-09-07 14:09:30 +020024)
25
Serge Bazanski12971d62020-11-17 12:12:58 +010026func testPayload(msg string) *LeveledPayload {
27 return &LeveledPayload{
28 messages: []string{msg},
29 timestamp: time.Now(),
30 severity: INFO,
31 file: "main.go",
32 line: 1337,
33 }
34}
35
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020036func TestJournalRetention(t *testing.T) {
37 j := newJournal()
38
39 for i := 0; i < 9000; i += 1 {
40 e := &entry{
41 origin: "main",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020042 leveled: testPayload(fmt.Sprintf("test %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020043 }
44 j.append(e)
45 }
46
47 entries := j.getEntries("main")
48 if want, got := 8192, len(entries); want != got {
49 t.Fatalf("wanted %d entries, got %d", want, got)
50 }
51 for i, entry := range entries {
52 want := fmt.Sprintf("test %d", (9000-8192)+i)
Serge Bazanski12971d62020-11-17 12:12:58 +010053 got := strings.Join(entry.leveled.messages, "\n")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020054 if want != got {
55 t.Fatalf("wanted entry %q, got %q", want, got)
56 }
57 }
58}
59
60func TestJournalQuota(t *testing.T) {
61 j := newJournal()
62
63 for i := 0; i < 9000; i += 1 {
64 j.append(&entry{
65 origin: "chatty",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020066 leveled: testPayload(fmt.Sprintf("chatty %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020067 })
68 if i%10 == 0 {
69 j.append(&entry{
70 origin: "solemn",
Serge Bazanski1bfa0c22020-10-14 16:45:07 +020071 leveled: testPayload(fmt.Sprintf("solemn %d", i)),
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020072 })
73 }
74 }
75
76 entries := j.getEntries("chatty")
77 if want, got := 8192, len(entries); want != got {
78 t.Fatalf("wanted %d chatty entries, got %d", want, got)
79 }
80 entries = j.getEntries("solemn")
81 if want, got := 900, len(entries); want != got {
82 t.Fatalf("wanted %d solemn entries, got %d", want, got)
83 }
84 entries = j.getEntries("absent")
85 if want, got := 0, len(entries); want != got {
86 t.Fatalf("wanted %d absent entries, got %d", want, got)
87 }
88
89 entries = j.scanEntries(filterAll())
90 if want, got := 8192+900, len(entries); want != got {
91 t.Fatalf("wanted %d total entries, got %d", want, got)
92 }
93 setMessages := make(map[string]bool)
94 for _, entry := range entries {
Serge Bazanski12971d62020-11-17 12:12:58 +010095 setMessages[strings.Join(entry.leveled.messages, "\n")] = true
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020096 }
97
98 for i := 0; i < 900; i += 1 {
99 want := fmt.Sprintf("solemn %d", i*10)
100 if !setMessages[want] {
101 t.Fatalf("could not find entry %q in journal", want)
102 }
103 }
104 for i := 0; i < 8192; i += 1 {
105 want := fmt.Sprintf("chatty %d", i+(9000-8192))
106 if !setMessages[want] {
107 t.Fatalf("could not find entry %q in journal", want)
108 }
109 }
110}
111
112func TestJournalSubtree(t *testing.T) {
113 j := newJournal()
Serge Bazanski1bfa0c22020-10-14 16:45:07 +0200114 j.append(&entry{origin: "a", leveled: testPayload("a")})
115 j.append(&entry{origin: "a.b", leveled: testPayload("a.b")})
116 j.append(&entry{origin: "a.b.c", leveled: testPayload("a.b.c")})
117 j.append(&entry{origin: "a.b.d", leveled: testPayload("a.b.d")})
118 j.append(&entry{origin: "e.f", leveled: testPayload("e.f")})
119 j.append(&entry{origin: "e.g", leveled: testPayload("e.g")})
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200120
121 expect := func(f filter, msgs ...string) string {
122 res := j.scanEntries(f)
123 set := make(map[string]bool)
124 for _, entry := range res {
Serge Bazanski12971d62020-11-17 12:12:58 +0100125 set[strings.Join(entry.leveled.messages, "\n")] = true
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200126 }
127
128 for _, want := range msgs {
129 if !set[want] {
130 return fmt.Sprintf("missing entry %q", want)
131 }
132 }
133 return ""
134 }
135
136 if res := expect(filterAll(), "a", "a.b", "a.b.c", "a.b.d", "e.f", "e.g"); res != "" {
137 t.Fatalf("All: %s", res)
138 }
139 if res := expect(filterSubtree("a"), "a", "a.b", "a.b.c", "a.b.d"); res != "" {
140 t.Fatalf("Subtree(a): %s", res)
141 }
142 if res := expect(filterSubtree("a.b"), "a.b", "a.b.c", "a.b.d"); res != "" {
143 t.Fatalf("Subtree(a.b): %s", res)
144 }
145 if res := expect(filterSubtree("e"), "e.f", "e.g"); res != "" {
146 t.Fatalf("Subtree(a.b): %s", res)
147 }
148}
Serge Bazanski367ee272023-03-16 17:50:39 +0100149
150func TestDN_Shorten(t *testing.T) {
151 for i, te := range []struct {
152 input string
153 maxLen int
154 want string
155 }{
156 {"root.role.controlplane.launcher.consensus.autopromoter", 20, "cplane autopromoter"},
157 {"networking.interfaces", 20, "net ifaces"},
158 {"hostsfile", 20, "hostsfile"},
159 {"root.dhcp-server", 20, "dhcp-server"},
160 {"root.role.kubernetes.run.kubernetes.apiserver", 20, "k8s apiserver"},
161 {"some.very.long.dn.that.cant.be.shortened", 20, "...cant be shortened"},
162 {"network.interfaces.dhcp", 20, "net ifaces dhcp"},
163 } {
164 got := DN(te.input).Shorten(MetropolisShortenDict, te.maxLen)
165 if len(got) > te.maxLen {
166 t.Errorf("case %d: output %q too long, got %d bytes, wanted %d", i, got, len(got), te.maxLen)
167 } else {
168 if te.want != got {
169 t.Errorf("case %d: wanted %q, got %q", i, te.want, got)
170 }
171 }
172 }
173}