github.com/raychaser/docker@v1.5.0/engine/streams_test.go (about) 1 package engine 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "strings" 10 "testing" 11 ) 12 13 type sentinelWriteCloser struct { 14 calledWrite bool 15 calledClose bool 16 } 17 18 func (w *sentinelWriteCloser) Write(p []byte) (int, error) { 19 w.calledWrite = true 20 return len(p), nil 21 } 22 23 func (w *sentinelWriteCloser) Close() error { 24 w.calledClose = true 25 return nil 26 } 27 28 func TestOutputAddEnv(t *testing.T) { 29 input := "{\"foo\": \"bar\", \"answer_to_life_the_universe_and_everything\": 42}" 30 o := NewOutput() 31 result, err := o.AddEnv() 32 if err != nil { 33 t.Fatal(err) 34 } 35 o.Write([]byte(input)) 36 o.Close() 37 if v := result.Get("foo"); v != "bar" { 38 t.Errorf("Expected %v, got %v", "bar", v) 39 } 40 if v := result.GetInt("answer_to_life_the_universe_and_everything"); v != 42 { 41 t.Errorf("Expected %v, got %v", 42, v) 42 } 43 if v := result.Get("this-value-doesnt-exist"); v != "" { 44 t.Errorf("Expected %v, got %v", "", v) 45 } 46 } 47 48 func TestOutputAddClose(t *testing.T) { 49 o := NewOutput() 50 var s sentinelWriteCloser 51 o.Add(&s) 52 if err := o.Close(); err != nil { 53 t.Fatal(err) 54 } 55 // Write data after the output is closed. 56 // Write should succeed, but no destination should receive it. 57 if _, err := o.Write([]byte("foo bar")); err != nil { 58 t.Fatal(err) 59 } 60 if !s.calledClose { 61 t.Fatal("Output.Close() didn't close the destination") 62 } 63 } 64 65 func TestOutputAddPipe(t *testing.T) { 66 var testInputs = []string{ 67 "hello, world!", 68 "One\nTwo\nThree", 69 "", 70 "A line\nThen another nl-terminated line\n", 71 "A line followed by an empty line\n\n", 72 } 73 for _, input := range testInputs { 74 expectedOutput := input 75 o := NewOutput() 76 r, err := o.AddPipe() 77 if err != nil { 78 t.Fatal(err) 79 } 80 go func(o *Output) { 81 if n, err := o.Write([]byte(input)); err != nil { 82 t.Error(err) 83 } else if n != len(input) { 84 t.Errorf("Expected %d, got %d", len(input), n) 85 } 86 if err := o.Close(); err != nil { 87 t.Error(err) 88 } 89 }(o) 90 output, err := ioutil.ReadAll(r) 91 if err != nil { 92 t.Fatal(err) 93 } 94 if string(output) != expectedOutput { 95 t.Errorf("Last line is not stored as return string.\nExpected: '%s'\nGot: '%s'", expectedOutput, output) 96 } 97 } 98 } 99 100 func TestTail(t *testing.T) { 101 var tests = make(map[string][]string) 102 tests["hello, world!"] = []string{ 103 "", 104 "hello, world!", 105 "hello, world!", 106 "hello, world!", 107 } 108 tests["One\nTwo\nThree"] = []string{ 109 "", 110 "Three", 111 "Two\nThree", 112 "One\nTwo\nThree", 113 } 114 for input, outputs := range tests { 115 for n, expectedOutput := range outputs { 116 output := Tail(bytes.NewBufferString(input), n) 117 if output != expectedOutput { 118 t.Errorf("Tail n=%d returned wrong result.\nExpected: '%s'\nGot : '%s'", n, expectedOutput, output) 119 } 120 } 121 } 122 } 123 124 func lastLine(txt string) string { 125 scanner := bufio.NewScanner(strings.NewReader(txt)) 126 var lastLine string 127 for scanner.Scan() { 128 lastLine = scanner.Text() 129 } 130 return lastLine 131 } 132 133 func TestOutputAdd(t *testing.T) { 134 o := NewOutput() 135 b := &bytes.Buffer{} 136 o.Add(b) 137 input := "hello, world!" 138 if n, err := o.Write([]byte(input)); err != nil { 139 t.Fatal(err) 140 } else if n != len(input) { 141 t.Fatalf("Expected %d, got %d", len(input), n) 142 } 143 if output := b.String(); output != input { 144 t.Fatalf("Received wrong data from Add.\nExpected: '%s'\nGot: '%s'", input, output) 145 } 146 } 147 148 func TestOutputWriteError(t *testing.T) { 149 o := NewOutput() 150 buf := &bytes.Buffer{} 151 o.Add(buf) 152 r, w := io.Pipe() 153 input := "Hello there" 154 expectedErr := fmt.Errorf("This is an error") 155 r.CloseWithError(expectedErr) 156 o.Add(w) 157 n, err := o.Write([]byte(input)) 158 if err != expectedErr { 159 t.Fatalf("Output.Write() should return the first error encountered, if any") 160 } 161 if buf.String() != input { 162 t.Fatalf("Output.Write() should attempt write on all destinations, even after encountering an error") 163 } 164 if n != len(input) { 165 t.Fatalf("Output.Write() should return the size of the input if it successfully writes to at least one destination") 166 } 167 } 168 169 func TestInputAddEmpty(t *testing.T) { 170 i := NewInput() 171 var b bytes.Buffer 172 if err := i.Add(&b); err != nil { 173 t.Fatal(err) 174 } 175 data, err := ioutil.ReadAll(i) 176 if err != nil { 177 t.Fatal(err) 178 } 179 if len(data) > 0 { 180 t.Fatalf("Read from empty input shoul yield no data") 181 } 182 } 183 184 func TestInputAddTwo(t *testing.T) { 185 i := NewInput() 186 var b1 bytes.Buffer 187 // First add should succeed 188 if err := i.Add(&b1); err != nil { 189 t.Fatal(err) 190 } 191 var b2 bytes.Buffer 192 // Second add should fail 193 if err := i.Add(&b2); err == nil { 194 t.Fatalf("Adding a second source should return an error") 195 } 196 } 197 198 func TestInputAddNotEmpty(t *testing.T) { 199 i := NewInput() 200 b := bytes.NewBufferString("hello world\nabc") 201 expectedResult := b.String() 202 i.Add(b) 203 result, err := ioutil.ReadAll(i) 204 if err != nil { 205 t.Fatal(err) 206 } 207 if string(result) != expectedResult { 208 t.Fatalf("Expected: %v\nReceived: %v", expectedResult, result) 209 } 210 }