blob: 0190f0468fd2e87f2288adb8484b557b92b90eeb [file] [log] [blame]
Lorenz Brunf8da2e72022-06-14 12:39:32 +02001package pstore
2
3import (
4 "fmt"
5 "testing"
6 "testing/fstest"
7 "time"
8)
9
10func TestParseHeader(t *testing.T) {
11 var cases = []struct {
12 input string
13 expectedOut *pstoreDmesgHeader
14 }{
15 {"Panic#2 Part30", &pstoreDmesgHeader{"Panic", 2, 30}},
16 {"Oops#1 Part5", &pstoreDmesgHeader{"Oops", 1, 5}},
17 // Random kernel output that is similar, but definitely not a dump header
18 {"<4>[2501503.489317] Oops: 0010 [#1] SMP NOPTI", nil},
19 }
20 for i, c := range cases {
21 t.Run(fmt.Sprintf("Test#%d", i+1), func(t *testing.T) {
22 out, err := parseDmesgHeader(c.input)
23 switch {
24 case err != nil && c.expectedOut != nil:
25 t.Errorf("Failed parsing %q: %v", c.input, err)
26 case err == nil && c.expectedOut == nil:
27 t.Errorf("Successfully parsed %q, expected error", c.input)
28 case err != nil && c.expectedOut == nil:
29 case err == nil && c.expectedOut != nil:
30 if out.Part != c.expectedOut.Part {
31 t.Errorf("Expected part to be %d, got %d", c.expectedOut.Part, out.Part)
32 }
33 if out.Counter != c.expectedOut.Counter {
34 t.Errorf("Expected counter to be %d, got %d", c.expectedOut.Counter, out.Counter)
35 }
36 if out.Reason != c.expectedOut.Reason {
37 t.Errorf("Expected reason to be %q, got %q", c.expectedOut.Reason, out.Reason)
38 }
39 }
40 })
41 }
42}
43
44func TestGetKmsgDumps(t *testing.T) {
45 testTime1 := time.Date(2022, 06, 13, 1, 2, 3, 4, time.UTC)
46 testTime2 := time.Date(2020, 06, 13, 1, 2, 3, 4, time.UTC)
47 testTime3 := time.Date(2010, 06, 13, 1, 2, 3, 4, time.UTC)
48 cases := []struct {
49 name string
50 inputFS fstest.MapFS
51 expectErr bool
52 expectedDumps []KmsgDump
53 }{
54 {"EmptyPstore", map[string]*fstest.MapFile{}, false, []KmsgDump{}},
55 {"SingleDumpSingleFile", map[string]*fstest.MapFile{
56 "dmesg-efi-165467917816002": {ModTime: testTime1, Data: []byte("Panic#2 Part1\ntest1\ntest2")},
57 "yolo-efi-165467917816002": {ModTime: testTime1, Data: []byte("something totally unrelated")},
58 }, false, []KmsgDump{{
59 Reason: "Panic",
60 OccurredAt: testTime1,
61 Counter: 2,
62 Lines: []string{
63 "test1",
64 "test2",
65 },
66 }}},
67 {"SingleDumpMultipleFiles", map[string]*fstest.MapFile{
68 "dmesg-efi-165467917816002": {ModTime: testTime1, Data: []byte("Panic#2 Part1\ntest2\ntest3")},
69 "dmesg-efi-165467917817002": {ModTime: testTime2, Data: []byte("Panic#2 Part2\ntest1")},
70 }, false, []KmsgDump{{
71 Reason: "Panic",
72 OccurredAt: testTime1,
73 Counter: 2,
74 Lines: []string{
75 "test1",
76 "test2",
77 "test3",
78 },
79 }}},
80 {"MultipleDumpsMultipleFiles", map[string]*fstest.MapFile{
81 "dmesg-efi-165467917816002": {ModTime: testTime1, Data: []byte("Panic#2 Part1\ntest2\ntest3")},
82 "dmesg-efi-165467917817002": {ModTime: testTime2, Data: []byte("Panic#2 Part2\ntest1")},
83 "dmesg-efi-265467917816002": {ModTime: testTime3, Data: []byte("Oops#1 Part1\noops3")},
84 "dmesg-efi-265467917817002": {ModTime: testTime2, Data: []byte("Oops#1 Part2\noops1\noops2")},
85 }, false, []KmsgDump{{
86 Reason: "Panic",
87 OccurredAt: testTime1,
88 Counter: 2,
89 Lines: []string{
90 "test1",
91 "test2",
92 "test3",
93 },
94 }, {
95 Reason: "Oops",
96 OccurredAt: testTime3,
97 Counter: 1,
98 Lines: []string{
99 "oops1",
100 "oops2",
101 "oops3",
102 },
103 }}},
104 }
105 for _, c := range cases {
106 t.Run(c.name, func(t *testing.T) {
107 dumps, err := getKmsgDumpsFromFS(c.inputFS)
108 switch {
109 case err == nil && c.expectErr:
110 t.Error("Expected error, but got none")
111 return
112 case err != nil && !c.expectErr:
113 t.Errorf("Got unexpected error: %v", err)
114 return
115 case err != nil && c.expectErr:
116 // Got expected error
117 return
118 case err == nil && !c.expectErr:
119 if len(dumps) != len(c.expectedDumps) {
120 t.Fatalf("Expected %d dumps, got %d", len(c.expectedDumps), len(dumps))
121 }
122 for i, dump := range dumps {
123 if dump.OccurredAt != c.expectedDumps[i].OccurredAt {
124 t.Errorf("Dump %d expected to have occurred at %v, got %v", i, c.expectedDumps[i].OccurredAt, dump.OccurredAt)
125 }
126 if dump.Reason != c.expectedDumps[i].Reason {
127 t.Errorf("Expected reason in dump %d to be %v, got %v", i, c.expectedDumps[i].Reason, dump.Reason)
128 }
129 if dump.Counter != c.expectedDumps[i].Counter {
130 t.Errorf("Expected counter in dump %d to be %d, got %d", i, c.expectedDumps[i].Counter, dump.Counter)
131 }
132 if len(dump.Lines) != len(c.expectedDumps[i].Lines) {
133 t.Errorf("Expected number of lines in dump %d to be %d, got %d", i, len(c.expectedDumps[i].Lines), len(dump.Lines))
134 }
135 for j := range dump.Lines {
136 if dump.Lines[j] != c.expectedDumps[i].Lines[j] {
137 t.Errorf("Expected line %d in dump %d to be %q, got %q", i, j, c.expectedDumps[i].Lines[j], dump.Lines[j])
138 }
139 }
140 }
141 }
142 })
143 }
144}