1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
//go:build !nosystemd && linux
// +build !nosystemd,linux
package main
import (
"context"
"os"
"testing"
"time"
"github.com/coreos/go-systemd/v22/sdjournal"
"github.com/stretchr/testify/assert"
)
func TestNewSystemdLogSource(t *testing.T) {
j := &fakeSystemdJournal{}
src, err := NewSystemdLogSource(j, "apath", "aunit", "aslice")
if err != nil {
t.Fatalf("NewSystemdLogSource failed: %v", err)
}
assert.Equal(t, []string{"_SYSTEMD_SLICE=aslice"}, j.addMatchCalls, "A match should be added for slice.")
assert.Equal(t, 1, j.seekTailCalls, "A call to SeekTail should be made.")
assert.Equal(t, 0, len(j.waitCalls), "No call to Wait should be made yet.")
if err := src.Close(); err != nil {
t.Fatalf("Close failed: %v", err)
}
assert.Equal(t, 1, j.closeCalls, "A call to Close should be made.")
}
func TestSystemdLogSource_Path(t *testing.T) {
j := &fakeSystemdJournal{}
src, err := NewSystemdLogSource(j, "apath", "aunit", "aslice")
if err != nil {
t.Fatalf("NewSystemdLogSource failed: %v", err)
}
defer src.Close()
assert.Equal(t, "apath", src.Path(), "Path should be set by New.")
}
func TestSystemdLogSource_Read(t *testing.T) {
ctx := context.Background()
j := &fakeSystemdJournal{
getEntryValues: []sdjournal.JournalEntry{
{
Fields: map[string]string{
"_HOSTNAME": "ahost",
"SYSLOG_IDENTIFIER": "anid",
"_PID": "123",
"MESSAGE": "aline",
},
RealtimeTimestamp: 1234567890000000,
},
},
nextValues: []uint64{1},
}
src, err := NewSystemdLogSource(j, "apath", "aunit", "aslice")
if err != nil {
t.Fatalf("NewSystemdLogSource failed: %v", err)
}
defer src.Close()
s, err := src.Read(ctx)
if err != nil {
t.Fatalf("Read failed: %v", err)
}
assert.Equal(t, []time.Duration{10 * time.Second}, j.waitCalls, "A Wait call should be made")
assert.Equal(t, 2, j.seekTailCalls, "Two seekTail calls expected")
assert.Equal(t, []uint64{1}, j.previousSkipCalls, "One previousSkipCall expected.")
assert.Equal(t, "Feb 13 23:31:30 ahost anid[123]: aline", s, "Read should get data from the journal entry.")
}
func TestSystemdLogSource_ReadEOF(t *testing.T) {
ctx := context.Background()
j := &fakeSystemdJournal{
nextValues: []uint64{0},
}
src, err := NewSystemdLogSource(j, "apath", "aunit", "aslice")
if err != nil {
t.Fatalf("NewSystemdLogSource failed: %v", err)
}
defer src.Close()
_, err = src.Read(ctx)
assert.Equal(t, SystemdNoMoreEntries, err, "Should interpret Next 0 as no more entries.")
}
func TestMain(m *testing.M) {
// We compare Unix timestamps to date strings, so make it deterministic.
os.Setenv("TZ", "UTC")
timeNow = func() time.Time { return time.Date(2009, 2, 13, 23, 31, 30, 0, time.UTC) }
defer func() {
timeNow = time.Now
}()
os.Exit(m.Run())
}
type fakeSystemdJournal struct {
getEntryError error
nextError error
getEntryValues []sdjournal.JournalEntry
nextValues []uint64
addMatchCalls []string
previousSkipCalls []uint64
waitCalls []time.Duration
closeCalls int
seekTailCalls int
}
func (j *fakeSystemdJournal) AddMatch(match string) error {
j.addMatchCalls = append(j.addMatchCalls, match)
return nil
}
func (j *fakeSystemdJournal) Close() error {
j.closeCalls++
return nil
}
func (j *fakeSystemdJournal) GetEntry() (*sdjournal.JournalEntry, error) {
if len(j.getEntryValues) == 0 {
return nil, j.getEntryError
}
e := j.getEntryValues[0]
j.getEntryValues = j.getEntryValues[1:]
return &e, nil
}
func (j *fakeSystemdJournal) Next() (uint64, error) {
if len(j.nextValues) == 0 {
return 0, j.nextError
}
v := j.nextValues[0]
j.nextValues = j.nextValues[1:]
return v, nil
}
func (j *fakeSystemdJournal) SeekTail() error {
j.seekTailCalls++
return nil
}
func (j *fakeSystemdJournal) PreviousSkip(skip uint64) (uint64, error) {
j.previousSkipCalls = append(j.previousSkipCalls, skip)
return skip, nil
}
func (j *fakeSystemdJournal) Wait(timeout time.Duration) int {
j.waitCalls = append(j.waitCalls, timeout)
if len(j.waitCalls) == 1 {
// first wait call
return sdjournal.SD_JOURNAL_INVALIDATE
}
return sdjournal.SD_JOURNAL_APPEND
}
|