Skip to content

Commit 7314a49

Browse files
authored
CI: ensure tests don't alter the repository (#3616)
1 parent 983c5c3 commit 7314a49

22 files changed

+91
-75
lines changed

.github/workflows/go-tests.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,18 @@ jobs:
181181
- name: Unit tests
182182
run: |
183183
go install gotest.tools/[email protected]
184+
# make the repo read-only, with the exception of coverage output
185+
touch coverage.out
186+
chmod -R a-w .
187+
chmod u+w coverage.out
184188
make testcover
189+
# ignore changes to codecov.yml
190+
if [[ $(git status --porcelain -- . ":(exclude).github/codecov.yml") ]]; then
191+
echo "Error: Unit tests should not create or alter files inside the repository. Please use the appropriate testing helpers or otherwise temporary locations."
192+
git diff --name-only
193+
exit 1
194+
fi
195+
chmod -R u+w .
185196
186197
# check if some component stubs are missing
187198
- name: "Build profile: minimal"

pkg/acquisition/acquisition_test.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func (f *MockSource) StreamingAcquisition(context.Context, chan types.Event, *to
6868
func (f *MockSource) CanRun() error { return nil }
6969
func (f *MockSource) GetMetrics() []prometheus.Collector { return nil }
7070
func (f *MockSource) GetAggregMetrics() []prometheus.Collector { return nil }
71-
func (f *MockSource) Dump() interface{} { return f }
71+
func (f *MockSource) Dump() any { return f }
7272
func (f *MockSource) GetName() string { return "mock" }
7373
func (f *MockSource) ConfigureByDSN(string, map[string]string, *log.Entry, string) error {
7474
return errors.New("not supported")
@@ -236,57 +236,57 @@ func TestLoadAcquisitionFromFile(t *testing.T) {
236236
{
237237
TestName: "invalid_yaml_file",
238238
Config: csconfig.CrowdsecServiceCfg{
239-
AcquisitionFiles: []string{"test_files/badyaml.yaml"},
239+
AcquisitionFiles: []string{"testdata/badyaml.yaml"},
240240
},
241-
ExpectedError: "failed to parse test_files/badyaml.yaml: yaml: unmarshal errors",
241+
ExpectedError: "failed to parse testdata/badyaml.yaml: yaml: unmarshal errors",
242242
ExpectedLen: 0,
243243
},
244244
{
245245
TestName: "invalid_empty_yaml",
246246
Config: csconfig.CrowdsecServiceCfg{
247-
AcquisitionFiles: []string{"test_files/emptyitem.yaml"},
247+
AcquisitionFiles: []string{"testdata/emptyitem.yaml"},
248248
},
249249
ExpectedLen: 0,
250250
},
251251
{
252252
TestName: "basic_valid",
253253
Config: csconfig.CrowdsecServiceCfg{
254-
AcquisitionFiles: []string{"test_files/basic_filemode.yaml"},
254+
AcquisitionFiles: []string{"testdata/basic_filemode.yaml"},
255255
},
256256
ExpectedLen: 2,
257257
},
258258
{
259259
TestName: "missing_labels",
260260
Config: csconfig.CrowdsecServiceCfg{
261-
AcquisitionFiles: []string{"test_files/missing_labels.yaml"},
261+
AcquisitionFiles: []string{"testdata/missing_labels.yaml"},
262262
},
263-
ExpectedError: "missing labels in test_files/missing_labels.yaml",
263+
ExpectedError: "missing labels in testdata/missing_labels.yaml",
264264
},
265265
{
266266
TestName: "backward_compat",
267267
Config: csconfig.CrowdsecServiceCfg{
268-
AcquisitionFiles: []string{"test_files/backward_compat.yaml"},
268+
AcquisitionFiles: []string{"testdata/backward_compat.yaml"},
269269
},
270270
ExpectedLen: 2,
271271
},
272272
{
273273
TestName: "bad_type",
274274
Config: csconfig.CrowdsecServiceCfg{
275-
AcquisitionFiles: []string{"test_files/bad_source.yaml"},
275+
AcquisitionFiles: []string{"testdata/bad_source.yaml"},
276276
},
277-
ExpectedError: "in file test_files/bad_source.yaml (position 0) - unknown data source does_not_exist",
277+
ExpectedError: "in file testdata/bad_source.yaml (position 0) - unknown data source does_not_exist",
278278
},
279279
{
280280
TestName: "invalid_filetype_config",
281281
Config: csconfig.CrowdsecServiceCfg{
282-
AcquisitionFiles: []string{"test_files/bad_filetype.yaml"},
282+
AcquisitionFiles: []string{"testdata/bad_filetype.yaml"},
283283
},
284-
ExpectedError: "while configuring datasource of type file from test_files/bad_filetype.yaml",
284+
ExpectedError: "while configuring datasource of type file from testdata/bad_filetype.yaml",
285285
},
286286
{
287287
TestName: "from_env",
288288
Config: csconfig.CrowdsecServiceCfg{
289-
AcquisitionFiles: []string{"test_files/env.yaml"},
289+
AcquisitionFiles: []string{"testdata/env.yaml"},
290290
},
291291
ExpectedLen: 1,
292292
},
@@ -356,7 +356,7 @@ func (f *MockCat) StreamingAcquisition(context.Context, chan types.Event, *tomb.
356356
func (f *MockCat) CanRun() error { return nil }
357357
func (f *MockCat) GetMetrics() []prometheus.Collector { return nil }
358358
func (f *MockCat) GetAggregMetrics() []prometheus.Collector { return nil }
359-
func (f *MockCat) Dump() interface{} { return f }
359+
func (f *MockCat) Dump() any { return f }
360360
func (f *MockCat) ConfigureByDSN(string, map[string]string, *log.Entry, string) error {
361361
return errors.New("not supported")
362362
}
@@ -403,7 +403,7 @@ func (f *MockTail) StreamingAcquisition(ctx context.Context, out chan types.Even
403403
func (f *MockTail) CanRun() error { return nil }
404404
func (f *MockTail) GetMetrics() []prometheus.Collector { return nil }
405405
func (f *MockTail) GetAggregMetrics() []prometheus.Collector { return nil }
406-
func (f *MockTail) Dump() interface{} { return f }
406+
func (f *MockTail) Dump() any { return f }
407407
func (f *MockTail) ConfigureByDSN(string, map[string]string, *log.Entry, string) error {
408408
return errors.New("not supported")
409409
}
@@ -538,7 +538,7 @@ func (f *MockSourceByDSN) StreamingAcquisition(context.Context, chan types.Event
538538
func (f *MockSourceByDSN) CanRun() error { return nil }
539539
func (f *MockSourceByDSN) GetMetrics() []prometheus.Collector { return nil }
540540
func (f *MockSourceByDSN) GetAggregMetrics() []prometheus.Collector { return nil }
541-
func (f *MockSourceByDSN) Dump() interface{} { return f }
541+
func (f *MockSourceByDSN) Dump() any { return f }
542542
func (f *MockSourceByDSN) GetName() string { return "mockdsn" }
543543
func (f *MockSourceByDSN) ConfigureByDSN(dsn string, labels map[string]string, logger *log.Entry, uuid string) error {
544544
dsn = strings.TrimPrefix(dsn, "mockdsn://")

pkg/acquisition/modules/file/file_test.go

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ func TestConfigureDSN(t *testing.T) {
103103

104104
func TestOneShot(t *testing.T) {
105105
ctx := t.Context()
106+
tmpDir := t.TempDir()
107+
deletedFile := filepath.Join(tmpDir, "test_delete.log")
106108

107109
permDeniedFile := "/etc/shadow"
108110
permDeniedError := "failed opening /etc/shadow: open /etc/shadow: permission denied"
@@ -166,40 +168,40 @@ filename: /do/not/exist`,
166168
name: "test.log",
167169
config: `
168170
mode: cat
169-
filename: test_files/test.log`,
171+
filename: testdata/test.log`,
170172
expectedLines: 5,
171173
logLevel: log.WarnLevel,
172174
},
173175
{
174176
name: "test.log.gz",
175177
config: `
176178
mode: cat
177-
filename: test_files/test.log.gz`,
179+
filename: testdata/test.log.gz`,
178180
expectedLines: 5,
179181
logLevel: log.WarnLevel,
180182
},
181183
{
182184
name: "unexpected end of gzip stream",
183185
config: `
184186
mode: cat
185-
filename: test_files/bad.gz`,
186-
expectedErr: "failed to read gz test_files/bad.gz: unexpected EOF",
187+
filename: testdata/bad.gz`,
188+
expectedErr: "failed to read gz testdata/bad.gz: unexpected EOF",
187189
expectedLines: 0,
188190
logLevel: log.WarnLevel,
189191
},
190192
{
191193
name: "deleted file",
192-
config: `
194+
config: fmt.Sprintf(`
193195
mode: cat
194-
filename: test_files/test_delete.log`,
196+
filename: %s`, deletedFile),
195197
setup: func() {
196-
f, _ := os.Create("test_files/test_delete.log")
198+
f, _ := os.Create(deletedFile)
197199
f.Close()
198200
},
199201
afterConfigure: func() {
200-
os.Remove("test_files/test_delete.log")
202+
os.Remove(deletedFile)
201203
},
202-
expectedErr: "could not stat file test_files/test_delete.log",
204+
expectedErr: "could not stat file " + deletedFile,
203205
},
204206
}
205207

@@ -252,14 +254,14 @@ func TestLiveAcquisition(t *testing.T) {
252254
ctx := t.Context()
253255
permDeniedFile := "/etc/shadow"
254256
permDeniedError := "unable to read /etc/shadow : open /etc/shadow: permission denied"
255-
testPattern := "test_files/*.log"
257+
tmpDir := t.TempDir()
258+
testPattern := filepath.Join(tmpDir, "*.log")
256259

257260
if runtime.GOOS == "windows" {
258261
// Technically, this is not a permission denied error, but we just want to test what happens
259262
// if we do not have access to the file
260263
permDeniedFile = `C:\Windows\System32\config\SAM`
261264
permDeniedError = `unable to read C:\Windows\System32\config\SAM : open C:\Windows\System32\config\SAM: The process cannot access the file because it is being used by another process`
262-
testPattern = `test_files\*.log`
263265
}
264266

265267
tests := []struct {
@@ -320,10 +322,10 @@ force_inotify: true`, testPattern),
320322
logLevel: log.DebugLevel,
321323
name: "GlobInotify",
322324
afterConfigure: func() {
323-
f, _ := os.Create("test_files/a.log")
325+
f, _ := os.Create(filepath.Join(tmpDir, "a.log"))
324326
f.Close()
325327
time.Sleep(1 * time.Second)
326-
os.Remove("test_files/a.log")
328+
os.Remove(f.Name())
327329
},
328330
},
329331
{
@@ -336,18 +338,18 @@ force_inotify: true`, testPattern),
336338
logLevel: log.DebugLevel,
337339
name: "GlobInotifyChmod",
338340
afterConfigure: func() {
339-
f, err := os.Create("test_files/a.log")
341+
f, err := os.Create(filepath.Join(tmpDir, "a.log"))
340342
require.NoError(t, err)
341343
err = f.Close()
342344
require.NoError(t, err)
343345
time.Sleep(1 * time.Second)
344-
err = os.Chmod("test_files/a.log", 0o000)
346+
err = os.Chmod(f.Name(), 0o000)
345347
require.NoError(t, err)
346348
},
347349
teardown: func() {
348-
err := os.Chmod("test_files/a.log", 0o644)
350+
err := os.Chmod(filepath.Join(tmpDir, "a.log"), 0o644)
349351
require.NoError(t, err)
350-
err = os.Remove("test_files/a.log")
352+
err = os.Remove(filepath.Join(tmpDir, "a.log"))
351353
require.NoError(t, err)
352354
},
353355
},
@@ -361,11 +363,11 @@ force_inotify: true`, testPattern),
361363
logLevel: log.DebugLevel,
362364
name: "InotifyMkDir",
363365
afterConfigure: func() {
364-
err := os.Mkdir("test_files/pouet/", 0o700)
366+
err := os.Mkdir(filepath.Join(tmpDir, "pouet"), 0o700)
365367
require.NoError(t, err)
366368
},
367369
teardown: func() {
368-
os.Remove("test_files/pouet/")
370+
os.Remove(filepath.Join(tmpDir, "pouet"))
369371
},
370372
},
371373
}
@@ -398,6 +400,7 @@ force_inotify: true`, testPattern),
398400
if tc.expectedLines != 0 {
399401
var stopReading bool
400402
defer func() { stopReading = true }()
403+
401404
go func() {
402405
for {
403406
select {
@@ -419,7 +422,7 @@ force_inotify: true`, testPattern),
419422

420423
if tc.expectedLines != 0 {
421424
// f.IsTailing is path delimiter sensitive
422-
streamLogFile := filepath.Join("test_files", "stream.log")
425+
streamLogFile := filepath.Join(tmpDir, "stream.log")
423426

424427
fd, err := os.Create(streamLogFile)
425428
require.NoError(t, err, "could not create test file")
@@ -435,6 +438,7 @@ force_inotify: true`, testPattern),
435438
time.Sleep(50 * time.Millisecond)
436439
continue
437440
}
441+
438442
waitingForTail = false
439443
}
440444
}
@@ -475,7 +479,7 @@ force_inotify: true`, testPattern),
475479
}
476480

477481
func TestExclusion(t *testing.T) {
478-
config := `filenames: ["test_files/*.log*"]
482+
config := `filenames: ["testdata/*.log*"]
479483
exclude_regexps: ["\\.gz$"]`
480484
logger, hook := test.NewNullLogger()
481485
// logger.SetLevel(ts.logLevel)
@@ -487,7 +491,7 @@ exclude_regexps: ["\\.gz$"]`
487491

488492
require.NotNil(t, hook.LastEntry())
489493
assert.Contains(t, hook.LastEntry().Message, `Skipping file: matches exclude regex "\\.gz`)
490-
assert.Equal(t, filepath.Join("test_files", "test.log.gz"), hook.LastEntry().Data["file"])
494+
assert.Equal(t, filepath.Join("testdata", "test.log.gz"), hook.LastEntry().Data["file"])
491495
hook.Reset()
492496
}
493497

File renamed without changes.
File renamed without changes.
File renamed without changes.

pkg/acquisition/modules/journalctl/journalctl_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,7 @@ journalctl_filter:
280280

281281
func TestMain(m *testing.M) {
282282
if os.Getenv("USE_SYSTEM_JOURNALCTL") == "" {
283-
currentDir, _ := os.Getwd()
284-
fullPath := filepath.Join(currentDir, "test_files")
283+
fullPath, _ := filepath.Abs("./testdata")
285284
os.Setenv("PATH", fullPath+":"+os.Getenv("PATH"))
286285
}
287286

pkg/acquisition/modules/journalctl/test_files/journalctl renamed to pkg/acquisition/modules/journalctl/testdata/journalctl

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@ import argparse
44
import time
55
import sys
66

7+
78
class CustomParser(argparse.ArgumentParser):
8-
#small hack to make argparse errors the same as journalctl
9+
# small hack to make argparse errors the same as journalctl
910
def error(self, message):
1011
if 'unrecognized arguments:' in message:
11-
sys.stderr.write("journalctl: invalid option -- '_'\n")
12-
sys.stderr.flush()
13-
exit(1)
12+
_ = sys.stderr.write("journalctl: invalid option -- '_'\n")
1413
else:
15-
sys.stderr.write(message)
16-
sys.stderr.flush()
17-
exit(1)
14+
_ = sys.stderr.write(message)
15+
_ = sys.stderr.flush()
16+
exit(1)
17+
1818

1919
LOGS = """-- Logs begin at Fri 2019-07-26 17:13:13 CEST, end at Mon 2020-11-23 09:17:34 CET. --
2020
Nov 22 11:22:19 zeroed sshd[1480]: Invalid user wqeqwe from 127.0.0.1 port 55818
@@ -32,14 +32,14 @@ Nov 22 11:23:27 zeroed sshd[1791]: Invalid user wqeqwe5 from 127.0.0.1 port 5583
3232
Nov 22 11:23:27 zeroed sshd[1791]: Failed password for invalid user wqeqwe5 from 127.0.0.1 port 55834 ssh2"""
3333

3434
parser = CustomParser()
35-
parser.add_argument('filter', metavar='FILTER', type=str, nargs='?')
36-
parser.add_argument('-n', dest='n', type=int)
37-
parser.add_argument('--follow', dest='follow', action='store_true', default=False)
35+
_ = parser.add_argument('filter', metavar='FILTER', type=str, nargs='?')
36+
_ = parser.add_argument('-n', dest='n', type=int)
37+
_ = parser.add_argument('--follow', dest='follow', action='store_true', default=False)
3838

3939
args = parser.parse_args()
4040

4141
for line in LOGS.split('\n'):
4242
print(line)
4343

4444
if args.follow:
45-
time.sleep(9999)
45+
time.sleep(9999)
File renamed without changes.

pkg/acquisition/modules/wineventlog/wineventlog_windows_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,18 +258,18 @@ func TestOneShotAcquisition(t *testing.T) {
258258
},
259259
{
260260
name: "existing file",
261-
dsn: `wineventlog://test_files/Setup.evtx`,
261+
dsn: `wineventlog://testdata/Setup.evtx`,
262262
expectedCount: 24,
263263
expectedErr: "",
264264
},
265265
{
266266
name: "filter on event_id",
267-
dsn: `wineventlog://test_files/Setup.evtx?event_id=2`,
267+
dsn: `wineventlog://testdata/Setup.evtx?event_id=2`,
268268
expectedCount: 1,
269269
},
270270
{
271271
name: "filter on event_id",
272-
dsn: `wineventlog://test_files/Setup.evtx?event_id=2&event_id=3`,
272+
dsn: `wineventlog://testdata/Setup.evtx?event_id=2&event_id=3`,
273273
expectedCount: 24,
274274
},
275275
}

0 commit comments

Comments
 (0)