moby--moby/daemon/logger/jsonfilelog/read_test.go

155 lines
3.6 KiB
Go

package jsonfilelog // import "github.com/docker/docker/daemon/logger/jsonfilelog"
import (
"bytes"
"encoding/json"
"io"
"testing"
"time"
"github.com/docker/docker/daemon/logger"
"gotest.tools/v3/assert"
"gotest.tools/v3/fs"
)
func BenchmarkJSONFileLoggerReadLogs(b *testing.B) {
tmp := fs.NewDir(b, "bench-jsonfilelog")
defer tmp.Remove()
jsonlogger, err := New(logger.Info{
ContainerID: "a7317399f3f857173c6179d44823594f8294678dea9999662e5c625b5a1c7657",
LogPath: tmp.Join("container.log"),
Config: map[string]string{
"labels": "first,second",
},
ContainerLabels: map[string]string{
"first": "label_value",
"second": "label_foo",
},
})
assert.NilError(b, err)
defer jsonlogger.Close()
msg := &logger.Message{
Line: []byte("Line that thinks that it is log line from docker\n"),
Source: "stderr",
Timestamp: time.Now().UTC(),
}
buf := bytes.NewBuffer(nil)
assert.NilError(b, marshalMessage(msg, nil, buf))
b.SetBytes(int64(buf.Len()))
b.ResetTimer()
chError := make(chan error, b.N+1)
go func() {
for i := 0; i < b.N; i++ {
chError <- jsonlogger.Log(msg)
}
chError <- jsonlogger.Close()
}()
lw := jsonlogger.(*JSONFileLogger).ReadLogs(logger.ReadConfig{Follow: true})
for {
select {
case <-lw.Msg:
case <-lw.WatchProducerGone():
return
case err := <-chError:
if err != nil {
b.Fatal(err)
}
}
}
}
func TestEncodeDecode(t *testing.T) {
t.Parallel()
m1 := &logger.Message{Line: []byte("hello 1"), Timestamp: time.Now(), Source: "stdout"}
m2 := &logger.Message{Line: []byte("hello 2"), Timestamp: time.Now(), Source: "stdout"}
m3 := &logger.Message{Line: []byte("hello 3"), Timestamp: time.Now(), Source: "stdout"}
buf := bytes.NewBuffer(nil)
assert.Assert(t, marshalMessage(m1, nil, buf))
assert.Assert(t, marshalMessage(m2, nil, buf))
assert.Assert(t, marshalMessage(m3, nil, buf))
dec := decodeFunc(buf)
defer dec.Close()
msg, err := dec.Decode()
assert.NilError(t, err)
assert.Assert(t, string(msg.Line) == "hello 1\n", string(msg.Line))
msg, err = dec.Decode()
assert.NilError(t, err)
assert.Assert(t, string(msg.Line) == "hello 2\n")
msg, err = dec.Decode()
assert.NilError(t, err)
assert.Assert(t, string(msg.Line) == "hello 3\n")
_, err = dec.Decode()
assert.Assert(t, err == io.EOF)
}
func TestUnexpectedEOF(t *testing.T) {
buf := bytes.NewBuffer(nil)
msg1 := &logger.Message{Timestamp: time.Now(), Line: []byte("hello1")}
msg2 := &logger.Message{Timestamp: time.Now(), Line: []byte("hello2")}
err := marshalMessage(msg1, json.RawMessage{}, buf)
assert.NilError(t, err)
err = marshalMessage(msg2, json.RawMessage{}, buf)
assert.NilError(t, err)
r := &readerWithErr{
err: io.EOF,
after: buf.Len() / 4,
r: buf,
}
dec := &decoder{rdr: r, maxRetry: 1}
_, err = dec.Decode()
assert.Error(t, err, io.ErrUnexpectedEOF.Error())
// again just to check
_, err = dec.Decode()
assert.Error(t, err, io.ErrUnexpectedEOF.Error())
// reset the error
// from here all reads should succeed until we get EOF on the underlying reader
r.err = nil
msg, err := dec.Decode()
assert.NilError(t, err)
assert.Equal(t, string(msg1.Line)+"\n", string(msg.Line))
msg, err = dec.Decode()
assert.NilError(t, err)
assert.Equal(t, string(msg2.Line)+"\n", string(msg.Line))
_, err = dec.Decode()
assert.Error(t, err, io.EOF.Error())
}
type readerWithErr struct {
err error
after int
r io.Reader
read int
}
func (r *readerWithErr) Read(p []byte) (int, error) {
if r.err != nil && r.read > r.after {
return 0, r.err
}
n, err := r.r.Read(p[:1])
if n > 0 {
r.read += n
}
return n, err
}