Skip to content

Instantly share code, notes, and snippets.

@cpuguy83
Created August 15, 2018 19:16
Show Gist options
  • Save cpuguy83/e538793de18c762608358ee0eaddc197 to your computer and use it in GitHub Desktop.
Save cpuguy83/e538793de18c762608358ee0eaddc197 to your computer and use it in GitHub Desktop.
package loggerutils
import (
"io"
"io/ioutil"
"os"
"sync/atomic"
"testing"
"time"
"github.com/docker/docker/daemon/logger"
"gotest.tools/assert"
)
func TestFollowLogsProducerGone(t *testing.T) {
lw := logger.NewLogWatcher()
f, err := ioutil.TempFile("", t.Name())
assert.NilError(t, err)
defer os.Remove(f.Name())
defer f.Close()
var closed int32
closeLogger := func() {
f.Close()
atomic.StoreInt32(&closed, 1)
lw.ProducerGone()
}
var readAfterClose int
makeDecoder := func(rdr io.Reader) func() (*logger.Message, error) {
return func() (*logger.Message, error) {
if atomic.LoadInt32(&closed) == 1 {
// simulate extra messages to send after the logger is closed
if readAfterClose > 2 {
return nil, io.EOF
}
readAfterClose++
}
return &logger.Message{}, nil
}
}
var since, until time.Time
followLogsDone := make(chan struct{})
go func() {
followLogs(f, lw, make(chan interface{}), makeDecoder, since, until)
close(followLogsDone)
}()
select {
case <-lw.Msg:
case err := <-lw.Err:
assert.NilError(t, err)
case <-followLogsDone:
t.Fatal("follow logs finished unexpectedly")
case <-time.After(60 * time.Second):
t.Fatal("timeout waiting for log message")
}
closeLogger()
// should get two more log messages
for i := 0; i < 2; i++ {
select {
case <-lw.Msg:
case err := <-lw.Err:
assert.NilError(t, err)
case <-followLogsDone:
t.Fatal("follow logs should not be done")
case <-time.After(60 * time.Second):
t.Fatal("timeout waiting for log messages")
}
}
select {
case <-followLogsDone:
case <-time.After(60 * time.Second):
t.Fatal("timeout waiting for followLogs to finish")
}
select {
case <-lw.WatchConsumerGone():
t.Fatal("consumer should not have exited")
default:
}
}
func TestFollowLogsConsumerGone(t *testing.T) {
lw := logger.NewLogWatcher()
f, err := ioutil.TempFile("", t.Name())
assert.NilError(t, err)
defer os.Remove(f.Name())
defer f.Close()
makeDecoder := func(rdr io.Reader) func() (*logger.Message, error) {
return func() (*logger.Message, error) {
return &logger.Message{}, nil
}
}
followLogsDone := make(chan struct{})
var since, until time.Time
go func() {
followLogs(f, lw, make(chan interface{}), makeDecoder, since, until)
close(followLogsDone)
}()
select {
case <-lw.Msg:
case err := <-lw.Err:
assert.NilError(t, err)
case <-followLogsDone:
t.Fatal("follow logs finished unexpectedly")
case <-time.After(60 * time.Second):
t.Fatal("timeout waiting for log message")
}
lw.ConsumerGone()
select {
case <-followLogsDone:
case <-time.After(60 * time.Second):
t.Fatal("timeout waiting for follow logs to finish")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment