Skip to content

Commit 0ebbd69

Browse files
committed
chore: add unit tests for various modules
1 parent ab4ca39 commit 0ebbd69

24 files changed

+3787
-5
lines changed

.golangci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ linters:
33
default: all
44
disable:
55
- depguard
6+
- paralleltest
67
- tagliatelle
78
- testpackage
89
settings:

internal/os/api/exit_code_test.go

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright 2026 New Relic Corporation. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package api
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestExitCodeErr_Error(t *testing.T) {
13+
tests := []struct {
14+
name string
15+
exitCode int
16+
expected string
17+
}{
18+
{
19+
name: "exit code 0",
20+
exitCode: 0,
21+
expected: "returned non zero exit: 0",
22+
},
23+
{
24+
name: "exit code 1",
25+
exitCode: 1,
26+
expected: "returned non zero exit: 1",
27+
},
28+
{
29+
name: "exit code 3 (restart)",
30+
exitCode: 3,
31+
expected: "returned non zero exit: 3",
32+
},
33+
{
34+
name: "negative exit code",
35+
exitCode: -1,
36+
expected: "returned non zero exit: -1",
37+
},
38+
{
39+
name: "large exit code",
40+
exitCode: 255,
41+
expected: "returned non zero exit: 255",
42+
},
43+
}
44+
45+
for _, tt := range tests {
46+
t.Run(tt.name, func(t *testing.T) {
47+
err := &ExitCodeErr{exitCode: tt.exitCode}
48+
assert.Equal(t, tt.expected, err.Error())
49+
})
50+
}
51+
}
52+
53+
func TestExitCodeErr_ExitCode(t *testing.T) {
54+
tests := []struct {
55+
name string
56+
exitCode int
57+
}{
58+
{
59+
name: "exit code success",
60+
exitCode: ExitCodeSuccess,
61+
},
62+
{
63+
name: "exit code error",
64+
exitCode: ExitCodeError,
65+
},
66+
{
67+
name: "exit code restart",
68+
exitCode: ExitCodeRestart,
69+
},
70+
{
71+
name: "custom exit code",
72+
exitCode: 42,
73+
},
74+
}
75+
76+
for _, tt := range tests {
77+
t.Run(tt.name, func(t *testing.T) {
78+
err := &ExitCodeErr{exitCode: tt.exitCode}
79+
assert.Equal(t, tt.exitCode, err.ExitCode())
80+
})
81+
}
82+
}
83+
84+
func TestNewExitCodeErr(t *testing.T) {
85+
tests := []struct {
86+
name string
87+
exitCode int
88+
}{
89+
{
90+
name: "create with success code",
91+
exitCode: ExitCodeSuccess,
92+
},
93+
{
94+
name: "create with error code",
95+
exitCode: ExitCodeError,
96+
},
97+
{
98+
name: "create with restart code",
99+
exitCode: ExitCodeRestart,
100+
},
101+
{
102+
name: "create with negative code",
103+
exitCode: -1,
104+
},
105+
}
106+
107+
for _, tt := range tests {
108+
t.Run(tt.name, func(t *testing.T) {
109+
err := NewExitCodeErr(tt.exitCode)
110+
assert.NotNil(t, err)
111+
assert.Equal(t, tt.exitCode, err.ExitCode())
112+
})
113+
}
114+
}
115+
116+
func TestExitCodeConstants(t *testing.T) {
117+
assert.Equal(t, 0, ExitCodeSuccess)
118+
assert.Equal(t, 1, ExitCodeError)
119+
assert.Equal(t, 3, ExitCodeRestart)
120+
}
121+
122+
func TestCheckExitCode_NilError(t *testing.T) {
123+
result := CheckExitCode(nil)
124+
assert.Equal(t, ExitCodeSuccess, result)
125+
}
126+
127+
func TestExitCodeErr_ImplementsError(_ *testing.T) {
128+
var _ error = (*ExitCodeErr)(nil)
129+
}

internal/os/fs/fs_test.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
// Copyright 2026 New Relic Corporation. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package fs
5+
6+
import (
7+
"os"
8+
"path/filepath"
9+
"regexp"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
)
15+
16+
func TestReadFirstLine(t *testing.T) {
17+
tests := []struct {
18+
name string
19+
content string
20+
expected string
21+
expectError bool
22+
}{
23+
{
24+
name: "single line",
25+
content: "Hello World",
26+
expected: "Hello World",
27+
expectError: false,
28+
},
29+
{
30+
name: "multiple lines returns first",
31+
content: "First Line\nSecond Line\nThird Line",
32+
expected: "First Line",
33+
expectError: false,
34+
},
35+
{
36+
name: "trims whitespace",
37+
content: " Trimmed Content \nSecond Line",
38+
expected: "Trimmed Content",
39+
expectError: false,
40+
},
41+
{
42+
name: "empty file",
43+
content: "",
44+
expected: "",
45+
expectError: false,
46+
},
47+
{
48+
name: "only newline",
49+
content: "\n",
50+
expected: "",
51+
expectError: false,
52+
},
53+
{
54+
name: "tabs and spaces",
55+
content: "\t Hello \t\nWorld",
56+
expected: "Hello",
57+
expectError: false,
58+
},
59+
}
60+
61+
for _, tt := range tests { //nolint:varnamelen
62+
t.Run(tt.name, func(t *testing.T) {
63+
tmpFile := createTempFile(t, tt.content)
64+
defer os.Remove(tmpFile)
65+
66+
result, err := ReadFirstLine(tmpFile)
67+
if tt.expectError {
68+
require.Error(t, err)
69+
} else {
70+
require.NoError(t, err)
71+
assert.Equal(t, tt.expected, result)
72+
}
73+
})
74+
}
75+
}
76+
77+
func TestReadFirstLine_FileNotFound(t *testing.T) {
78+
result, err := ReadFirstLine("/nonexistent/path/file.txt")
79+
require.Error(t, err)
80+
assert.Equal(t, "unknown", result)
81+
assert.Contains(t, err.Error(), "cannot open file")
82+
}
83+
84+
func TestReadFileFieldMatching(t *testing.T) {
85+
tests := []struct {
86+
name string
87+
content string
88+
pattern string
89+
expected string
90+
expectError bool
91+
}{
92+
{
93+
name: "match on first line",
94+
content: "VERSION=1.2.3\nNAME=test",
95+
pattern: `VERSION=(.+)`,
96+
expected: "1.2.3",
97+
expectError: false,
98+
},
99+
{
100+
name: "match on second line",
101+
content: "NAME=test\nVERSION=1.2.3",
102+
pattern: `VERSION=(.+)`,
103+
expected: "1.2.3",
104+
expectError: false,
105+
},
106+
{
107+
name: "match with quotes",
108+
content: `NAME="Ubuntu"\nVERSION="20.04"`,
109+
pattern: `NAME="([^"]+)"`,
110+
expected: "Ubuntu",
111+
expectError: false,
112+
},
113+
{
114+
name: "no match returns unknown",
115+
content: "FOO=bar\nBAZ=qux",
116+
pattern: `VERSION=(.+)`,
117+
expected: "unknown",
118+
expectError: false,
119+
},
120+
{
121+
name: "complex regex",
122+
content: "Red Hat Enterprise Linux release 8.4 (Ootpa)",
123+
pattern: `release (\d+\.\d+)`,
124+
expected: "8.4",
125+
expectError: false,
126+
},
127+
{
128+
name: "empty file returns unknown",
129+
content: "",
130+
pattern: `(.+)`,
131+
expected: "unknown",
132+
expectError: false,
133+
},
134+
}
135+
136+
for _, tt := range tests { //nolint:varnamelen
137+
t.Run(tt.name, func(t *testing.T) {
138+
tmpFile := createTempFile(t, tt.content)
139+
140+
defer os.Remove(tmpFile)
141+
142+
re := regexp.MustCompile(tt.pattern)
143+
144+
result, err := ReadFileFieldMatching(tmpFile, re)
145+
if tt.expectError {
146+
assert.Error(t, err)
147+
} else {
148+
// Note: err may still be nil even when result is "unknown"
149+
assert.Equal(t, tt.expected, result)
150+
}
151+
})
152+
}
153+
}
154+
155+
func TestReadFileFieldMatching_FileNotFound(t *testing.T) {
156+
re := regexp.MustCompile(`(.+)`)
157+
result, err := ReadFileFieldMatching("/nonexistent/path/file.txt", re)
158+
require.Error(t, err)
159+
assert.Equal(t, "unknown", result)
160+
assert.Contains(t, err.Error(), "cannot open file")
161+
}
162+
163+
func TestReadFileFieldMatching_MultipleCaptures(t *testing.T) {
164+
content := "VERSION_ID=8.4"
165+
166+
tmpFile := createTempFile(t, content)
167+
defer os.Remove(tmpFile)
168+
169+
// Pattern with multiple capture groups - should return first capture
170+
re := regexp.MustCompile(`VERSION_ID=(\d+)\.(\d+)`)
171+
result, err := ReadFileFieldMatching(tmpFile, re)
172+
require.NoError(t, err)
173+
assert.Equal(t, "8", result) // First capture group
174+
}
175+
176+
func TestReadFileFieldMatching_LinuxReleaseFiles(t *testing.T) {
177+
t.Run("os-release NAME", func(t *testing.T) {
178+
tmpFile := createTempFile(t, `NAME="Ubuntu"\nVERSION="20.04.3 LTS (Focal Fossa)"`)
179+
defer os.Remove(tmpFile)
180+
181+
re := regexp.MustCompile(`NAME="?([^"\n]+)"?`)
182+
result, err := ReadFileFieldMatching(tmpFile, re)
183+
require.NoError(t, err)
184+
assert.Equal(t, "Ubuntu", result)
185+
})
186+
187+
t.Run("centos-release", func(t *testing.T) {
188+
tmpFile := createTempFile(t, "CentOS Linux release 7.9.2009 (Core)")
189+
defer os.Remove(tmpFile)
190+
191+
re := regexp.MustCompile(`release (\d+\.\d+)`)
192+
result, err := ReadFileFieldMatching(tmpFile, re)
193+
require.NoError(t, err)
194+
assert.Equal(t, "7.9", result)
195+
})
196+
197+
t.Run("redhat-release", func(t *testing.T) {
198+
tmpFile := createTempFile(t, "Red Hat Enterprise Linux release 8.4 (Ootpa)")
199+
defer os.Remove(tmpFile)
200+
201+
re := regexp.MustCompile(`release (\d+\.\d+)`)
202+
result, err := ReadFileFieldMatching(tmpFile, re)
203+
require.NoError(t, err)
204+
assert.Equal(t, "8.4", result)
205+
})
206+
}
207+
208+
// createTempFile creates a temporary file with the given content and returns its path.
209+
func createTempFile(t *testing.T, content string) string {
210+
t.Helper()
211+
tmpDir := t.TempDir()
212+
tmpFile := filepath.Join(tmpDir, "testfile")
213+
err := os.WriteFile(tmpFile, []byte(content), 0o600)
214+
require.NoError(t, err)
215+
216+
return tmpFile
217+
}

0 commit comments

Comments
 (0)