github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/daemon/logger/copier_test.go (about)

     1  package logger
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  )
    13  
    14  type TestLoggerJSON struct {
    15  	*json.Encoder
    16  	mu    sync.Mutex
    17  	delay time.Duration
    18  }
    19  
    20  func (l *TestLoggerJSON) Log(m *Message) error {
    21  	if l.delay > 0 {
    22  		time.Sleep(l.delay)
    23  	}
    24  	l.mu.Lock()
    25  	defer l.mu.Unlock()
    26  	return l.Encode(m)
    27  }
    28  
    29  func (l *TestLoggerJSON) Close() error { return nil }
    30  
    31  func (l *TestLoggerJSON) Name() string { return "json" }
    32  
    33  func TestCopier(t *testing.T) {
    34  	stdoutLine := "Line that thinks that it is log line from docker stdout"
    35  	stderrLine := "Line that thinks that it is log line from docker stderr"
    36  	var stdout bytes.Buffer
    37  	var stderr bytes.Buffer
    38  	for i := 0; i < 30; i++ {
    39  		if _, err := stdout.WriteString(stdoutLine + "\n"); err != nil {
    40  			t.Fatal(err)
    41  		}
    42  		if _, err := stderr.WriteString(stderrLine + "\n"); err != nil {
    43  			t.Fatal(err)
    44  		}
    45  	}
    46  
    47  	var jsonBuf bytes.Buffer
    48  
    49  	jsonLog := &TestLoggerJSON{Encoder: json.NewEncoder(&jsonBuf)}
    50  
    51  	c := NewCopier(
    52  		map[string]io.Reader{
    53  			"stdout": &stdout,
    54  			"stderr": &stderr,
    55  		},
    56  		jsonLog)
    57  	c.Run()
    58  	wait := make(chan struct{})
    59  	go func() {
    60  		c.Wait()
    61  		close(wait)
    62  	}()
    63  	select {
    64  	case <-time.After(1 * time.Second):
    65  		t.Fatal("Copier failed to do its work in 1 second")
    66  	case <-wait:
    67  	}
    68  	dec := json.NewDecoder(&jsonBuf)
    69  	for {
    70  		var msg Message
    71  		if err := dec.Decode(&msg); err != nil {
    72  			if err == io.EOF {
    73  				break
    74  			}
    75  			t.Fatal(err)
    76  		}
    77  		if msg.Source != "stdout" && msg.Source != "stderr" {
    78  			t.Fatalf("Wrong Source: %q, should be %q or %q", msg.Source, "stdout", "stderr")
    79  		}
    80  		if msg.Source == "stdout" {
    81  			if string(msg.Line) != stdoutLine {
    82  				t.Fatalf("Wrong Line: %q, expected %q", msg.Line, stdoutLine)
    83  			}
    84  		}
    85  		if msg.Source == "stderr" {
    86  			if string(msg.Line) != stderrLine {
    87  				t.Fatalf("Wrong Line: %q, expected %q", msg.Line, stderrLine)
    88  			}
    89  		}
    90  	}
    91  }
    92  
    93  func TestCopierSlow(t *testing.T) {
    94  	stdoutLine := "Line that thinks that it is log line from docker stdout"
    95  	var stdout bytes.Buffer
    96  	for i := 0; i < 30; i++ {
    97  		if _, err := stdout.WriteString(stdoutLine + "\n"); err != nil {
    98  			t.Fatal(err)
    99  		}
   100  	}
   101  
   102  	var jsonBuf bytes.Buffer
   103  	//encoder := &encodeCloser{Encoder: json.NewEncoder(&jsonBuf)}
   104  	jsonLog := &TestLoggerJSON{Encoder: json.NewEncoder(&jsonBuf), delay: 100 * time.Millisecond}
   105  
   106  	c := NewCopier(map[string]io.Reader{"stdout": &stdout}, jsonLog)
   107  	c.Run()
   108  	wait := make(chan struct{})
   109  	go func() {
   110  		c.Wait()
   111  		close(wait)
   112  	}()
   113  	<-time.After(150 * time.Millisecond)
   114  	c.Close()
   115  	select {
   116  	case <-time.After(200 * time.Millisecond):
   117  		t.Fatalf("failed to exit in time after the copier is closed")
   118  	case <-wait:
   119  	}
   120  }
   121  
   122  type BenchmarkLoggerDummy struct {
   123  }
   124  
   125  func (l *BenchmarkLoggerDummy) Log(m *Message) error { return nil }
   126  
   127  func (l *BenchmarkLoggerDummy) Close() error { return nil }
   128  
   129  func (l *BenchmarkLoggerDummy) Name() string { return "dummy" }
   130  
   131  func BenchmarkCopier64(b *testing.B) {
   132  	benchmarkCopier(b, 1<<6)
   133  }
   134  func BenchmarkCopier128(b *testing.B) {
   135  	benchmarkCopier(b, 1<<7)
   136  }
   137  func BenchmarkCopier256(b *testing.B) {
   138  	benchmarkCopier(b, 1<<8)
   139  }
   140  func BenchmarkCopier512(b *testing.B) {
   141  	benchmarkCopier(b, 1<<9)
   142  }
   143  func BenchmarkCopier1K(b *testing.B) {
   144  	benchmarkCopier(b, 1<<10)
   145  }
   146  func BenchmarkCopier2K(b *testing.B) {
   147  	benchmarkCopier(b, 1<<11)
   148  }
   149  func BenchmarkCopier4K(b *testing.B) {
   150  	benchmarkCopier(b, 1<<12)
   151  }
   152  func BenchmarkCopier8K(b *testing.B) {
   153  	benchmarkCopier(b, 1<<13)
   154  }
   155  func BenchmarkCopier16K(b *testing.B) {
   156  	benchmarkCopier(b, 1<<14)
   157  }
   158  func BenchmarkCopier32K(b *testing.B) {
   159  	benchmarkCopier(b, 1<<15)
   160  }
   161  func BenchmarkCopier64K(b *testing.B) {
   162  	benchmarkCopier(b, 1<<16)
   163  }
   164  func BenchmarkCopier128K(b *testing.B) {
   165  	benchmarkCopier(b, 1<<17)
   166  }
   167  func BenchmarkCopier256K(b *testing.B) {
   168  	benchmarkCopier(b, 1<<18)
   169  }
   170  
   171  func piped(b *testing.B, iterations int, delay time.Duration, buf []byte) io.Reader {
   172  	r, w, err := os.Pipe()
   173  	if err != nil {
   174  		b.Fatal(err)
   175  		return nil
   176  	}
   177  	go func() {
   178  		for i := 0; i < iterations; i++ {
   179  			time.Sleep(delay)
   180  			if n, err := w.Write(buf); err != nil || n != len(buf) {
   181  				if err != nil {
   182  					b.Fatal(err)
   183  				}
   184  				b.Fatal(fmt.Errorf("short write"))
   185  			}
   186  		}
   187  		w.Close()
   188  	}()
   189  	return r
   190  }
   191  
   192  func benchmarkCopier(b *testing.B, length int) {
   193  	b.StopTimer()
   194  	buf := []byte{'A'}
   195  	for len(buf) < length {
   196  		buf = append(buf, buf...)
   197  	}
   198  	buf = append(buf[:length-1], []byte{'\n'}...)
   199  	b.StartTimer()
   200  	for i := 0; i < b.N; i++ {
   201  		c := NewCopier(
   202  			map[string]io.Reader{
   203  				"buffer": piped(b, 10, time.Nanosecond, buf),
   204  			},
   205  			&BenchmarkLoggerDummy{})
   206  		c.Run()
   207  		c.Wait()
   208  		c.Close()
   209  	}
   210  }