Signed-off-by: Alexandr Morozov <lk4d4math@gmail.com>
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "bufio" |
|
| 4 | 5 |
"fmt" |
| 5 | 6 |
"io/ioutil" |
| 6 | 7 |
"os" |
| ... | ... |
@@ -12,6 +13,7 @@ import ( |
| 12 | 12 |
"strings" |
| 13 | 13 |
"sync" |
| 14 | 14 |
"testing" |
| 15 |
+ "time" |
|
| 15 | 16 |
|
| 16 | 17 |
"github.com/docker/docker/pkg/mount" |
| 17 | 18 |
"github.com/docker/docker/pkg/networkfs/resolvconf" |
| ... | ... |
@@ -1492,3 +1494,58 @@ func TestRunWorkdirExistsAndIsFile(t *testing.T) {
|
| 1492 | 1492 |
} |
| 1493 | 1493 |
logDone("run - error on existing file for workdir")
|
| 1494 | 1494 |
} |
| 1495 |
+ |
|
| 1496 |
+func TestRunExitOnStdinClose(t *testing.T) {
|
|
| 1497 |
+ name := "testrunexitonstdinclose" |
|
| 1498 |
+ defer deleteAllContainers() |
|
| 1499 |
+ runCmd := exec.Command(dockerBinary, "run", "--name", name, "-i", "busybox", "/bin/cat") |
|
| 1500 |
+ |
|
| 1501 |
+ stdin, err := runCmd.StdinPipe() |
|
| 1502 |
+ if err != nil {
|
|
| 1503 |
+ t.Fatal(err) |
|
| 1504 |
+ } |
|
| 1505 |
+ stdout, err := runCmd.StdoutPipe() |
|
| 1506 |
+ if err != nil {
|
|
| 1507 |
+ t.Fatal(err) |
|
| 1508 |
+ } |
|
| 1509 |
+ |
|
| 1510 |
+ if err := runCmd.Start(); err != nil {
|
|
| 1511 |
+ t.Fatal(err) |
|
| 1512 |
+ } |
|
| 1513 |
+ if _, err := stdin.Write([]byte("hello\n")); err != nil {
|
|
| 1514 |
+ t.Fatal(err) |
|
| 1515 |
+ } |
|
| 1516 |
+ |
|
| 1517 |
+ r := bufio.NewReader(stdout) |
|
| 1518 |
+ line, err := r.ReadString('\n')
|
|
| 1519 |
+ if err != nil {
|
|
| 1520 |
+ t.Fatal(err) |
|
| 1521 |
+ } |
|
| 1522 |
+ line = strings.TrimSpace(line) |
|
| 1523 |
+ if line != "hello" {
|
|
| 1524 |
+ t.Fatalf("Output should be 'hello', got '%q'", line)
|
|
| 1525 |
+ } |
|
| 1526 |
+ if err := stdin.Close(); err != nil {
|
|
| 1527 |
+ t.Fatal(err) |
|
| 1528 |
+ } |
|
| 1529 |
+ finish := make(chan struct{})
|
|
| 1530 |
+ go func() {
|
|
| 1531 |
+ if err := runCmd.Wait(); err != nil {
|
|
| 1532 |
+ t.Fatal(err) |
|
| 1533 |
+ } |
|
| 1534 |
+ close(finish) |
|
| 1535 |
+ }() |
|
| 1536 |
+ select {
|
|
| 1537 |
+ case <-finish: |
|
| 1538 |
+ case <-time.After(1 * time.Second): |
|
| 1539 |
+ t.Fatal("docker run failed to exit on stdin close")
|
|
| 1540 |
+ } |
|
| 1541 |
+ state, err := inspectField(name, "State.Running") |
|
| 1542 |
+ if err != nil {
|
|
| 1543 |
+ t.Fatal(err) |
|
| 1544 |
+ } |
|
| 1545 |
+ if state != "false" {
|
|
| 1546 |
+ t.Fatal("Container must be stopped after stdin closing")
|
|
| 1547 |
+ } |
|
| 1548 |
+ logDone("run - exit on stdin closing")
|
|
| 1549 |
+} |
| ... | ... |
@@ -113,57 +113,6 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error |
| 113 | 113 |
return nil |
| 114 | 114 |
} |
| 115 | 115 |
|
| 116 |
-func TestRunExit(t *testing.T) {
|
|
| 117 |
- stdin, stdinPipe := io.Pipe() |
|
| 118 |
- stdout, stdoutPipe := io.Pipe() |
|
| 119 |
- |
|
| 120 |
- cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil) |
|
| 121 |
- defer cleanup(globalEngine, t) |
|
| 122 |
- |
|
| 123 |
- c1 := make(chan struct{})
|
|
| 124 |
- go func() {
|
|
| 125 |
- cli.CmdRun("-i", unitTestImageID, "/bin/cat")
|
|
| 126 |
- close(c1) |
|
| 127 |
- }() |
|
| 128 |
- |
|
| 129 |
- setTimeout(t, "Read/Write assertion timed out", 2*time.Second, func() {
|
|
| 130 |
- if err := assertPipe("hello\n", "hello", stdout, stdinPipe, 150); err != nil {
|
|
| 131 |
- t.Fatal(err) |
|
| 132 |
- } |
|
| 133 |
- }) |
|
| 134 |
- |
|
| 135 |
- container := globalDaemon.List()[0] |
|
| 136 |
- |
|
| 137 |
- // Closing /bin/cat stdin, expect it to exit |
|
| 138 |
- if err := stdin.Close(); err != nil {
|
|
| 139 |
- t.Fatal(err) |
|
| 140 |
- } |
|
| 141 |
- |
|
| 142 |
- // as the process exited, CmdRun must finish and unblock. Wait for it |
|
| 143 |
- setTimeout(t, "Waiting for CmdRun timed out", 10*time.Second, func() {
|
|
| 144 |
- <-c1 |
|
| 145 |
- |
|
| 146 |
- go func() {
|
|
| 147 |
- cli.CmdWait(container.ID) |
|
| 148 |
- }() |
|
| 149 |
- |
|
| 150 |
- if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil {
|
|
| 151 |
- t.Fatal(err) |
|
| 152 |
- } |
|
| 153 |
- }) |
|
| 154 |
- |
|
| 155 |
- // Make sure that the client has been disconnected |
|
| 156 |
- setTimeout(t, "The client should have been disconnected once the remote process exited.", 2*time.Second, func() {
|
|
| 157 |
- // Expecting pipe i/o error, just check that read does not block |
|
| 158 |
- stdin.Read([]byte{})
|
|
| 159 |
- }) |
|
| 160 |
- |
|
| 161 |
- // Cleanup pipes |
|
| 162 |
- if err := closeWrap(stdin, stdinPipe, stdout, stdoutPipe); err != nil {
|
|
| 163 |
- t.Fatal(err) |
|
| 164 |
- } |
|
| 165 |
-} |
|
| 166 |
- |
|
| 167 | 116 |
// Expected behaviour: the process dies when the client disconnects |
| 168 | 117 |
func TestRunDisconnect(t *testing.T) {
|
| 169 | 118 |
|