//go:build linux && cgo && !static_build && journald // +build linux,cgo,!static_build,journald package journald // import "github.com/docker/docker/daemon/logger/journald" import ( "testing" "time" "github.com/coreos/go-systemd/v22/journal" "gotest.tools/v3/assert" "github.com/docker/docker/daemon/logger" "github.com/docker/docker/daemon/logger/journald/internal/fake" "github.com/docker/docker/daemon/logger/loggertest" ) func TestLogRead(t *testing.T) { r := loggertest.Reader{ Factory: func(t *testing.T, info logger.Info) func(*testing.T) logger.Logger { journalDir := t.TempDir() // Fill the journal with irrelevant events which the // LogReader needs to filter out. rotatedJournal := fake.NewT(t, journalDir+"/rotated.journal") rotatedJournal.AssignEventTimestampFromSyslogTimestamp = true l, err := new(logger.Info{ ContainerID: "wrongone0001", ContainerName: "fake", }) assert.NilError(t, err) l.sendToJournal = rotatedJournal.Send assert.NilError(t, l.Log(&logger.Message{Source: "stdout", Timestamp: time.Now().Add(-1 * 30 * time.Minute), Line: []byte("stdout of a different container in a rotated journal file")})) assert.NilError(t, l.Log(&logger.Message{Source: "stderr", Timestamp: time.Now().Add(-1 * 30 * time.Minute), Line: []byte("stderr of a different container in a rotated journal file")})) assert.NilError(t, rotatedJournal.Send("a log message from a totally different process in a rotated journal", journal.PriInfo, nil)) activeJournal := fake.NewT(t, journalDir+"/fake.journal") activeJournal.AssignEventTimestampFromSyslogTimestamp = true l, err = new(logger.Info{ ContainerID: "wrongone0002", ContainerName: "fake", }) assert.NilError(t, err) l.sendToJournal = activeJournal.Send assert.NilError(t, l.Log(&logger.Message{Source: "stdout", Timestamp: time.Now().Add(-1 * 30 * time.Minute), Line: []byte("stdout of a different container in the active journal file")})) assert.NilError(t, l.Log(&logger.Message{Source: "stderr", Timestamp: time.Now().Add(-1 * 30 * time.Minute), Line: []byte("stderr of a different container in the active journal file")})) assert.NilError(t, rotatedJournal.Send("a log message from a totally different process in the active journal", journal.PriInfo, nil)) return func(t *testing.T) logger.Logger { s := make(chan sendit, 100) t.Cleanup(func() { close(s) }) go func() { for m := range s { <-m.after activeJournal.Send(m.message, m.priority, m.vars) if m.sent != nil { close(m.sent) } } }() l, err := new(info) assert.NilError(t, err) l.journalReadDir = journalDir sl := &syncLogger{journald: l} l.sendToJournal = func(message string, priority journal.Priority, vars map[string]string) error { sent := make(chan struct{}) s <- sendit{ message: message, priority: priority, vars: vars, after: time.After(150 * time.Millisecond), sent: sent, } sl.waitOn = sent return nil } l.readSyncTimeout = 3 * time.Second return sl } }, } t.Run("Tail", r.TestTail) t.Run("Follow", r.TestFollow) } type sendit struct { message string priority journal.Priority vars map[string]string after <-chan time.Time sent chan<- struct{} } type syncLogger struct { *journald waitOn <-chan struct{} } func (l *syncLogger) Sync() error { if l.waitOn != nil { <-l.waitOn } return nil }