MCPcopy Index your code
hub / github.com/docker/cli / TestPluginSocketBackwardsCompatible

Function TestPluginSocketBackwardsCompatible

e2e/cli-plugins/socket_test.go:21–147  ·  view source on GitHub ↗

TestPluginSocketBackwardsCompatible executes a plugin binary that does not connect to the CLI plugin socket, simulating a plugin compiled against an older version of the CLI, and ensures that backwards compatibility is maintained.

(t *testing.T)

Source from the content-addressed store, hash-verified

19// a plugin compiled against an older version of the CLI, and
20// ensures that backwards compatibility is maintained.
21func TestPluginSocketBackwardsCompatible(t *testing.T) {
22 run, _, cleanup := prepare(t)
23 defer cleanup()
24
25 t.Run("attached", func(t *testing.T) {
26 t.Run("the plugin gets signalled if attached to a TTY", func(t *testing.T) {
27 cmd := run("presocket", "test-no-socket")
28 command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
29
30 ptmx, err := pty.Start(command)
31 assert.NilError(t, err, "failed to launch command with fake TTY")
32
33 // send a SIGINT to the process group after 1 second, since
34 // we're simulating an "attached TTY" scenario and a TTY would
35 // send a signal to the process group
36 go func() {
37 <-time.After(time.Second)
38 err := syscall.Kill(-command.Process.Pid, syscall.SIGINT)
39 assert.NilError(t, err, "failed to signal process group")
40 }()
41 out, err := io.ReadAll(ptmx)
42 if err != nil && !strings.Contains(err.Error(), "input/output error") {
43 t.Fatal("failed to get command output")
44 }
45
46 // the plugin is attached to the TTY, so the parent process
47 // ignores the received signal, and the plugin receives a SIGINT
48 // as well
49 assert.Equal(t, string(out), "received SIGINT\r\nexit after 3 seconds\r\n")
50 })
51
52 // ensure that we don't break plugins that attempt to read from the TTY
53 // (see: https://github.com/moby/moby/issues/47073)
54 // (remove me if/when we decide to break compatibility here)
55 t.Run("the plugin can read from the TTY", func(t *testing.T) {
56 cmd := run("presocket", "tty")
57 command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
58
59 ptmx, err := pty.Start(command)
60 assert.NilError(t, err, "failed to launch command with fake TTY")
61 _, _ = ptmx.WriteString("hello!")
62
63 done := make(chan error)
64 go func() {
65 <-time.After(time.Second)
66 _, err := io.ReadAll(ptmx)
67 done <- err
68 }()
69
70 select {
71 case cmdErr := <-done:
72 if cmdErr != nil && !strings.Contains(cmdErr.Error(), "input/output error") {
73 t.Fatal("failed to get command output")
74 }
75 case <-time.After(5 * time.Second):
76 t.Fatal("timed out! plugin process probably stuck")
77 }
78 })

Callers

nothing calls this directly

Calls 5

prepareFunction · 0.85
ContainsMethod · 0.80
runFunction · 0.50
CommandMethod · 0.45
ErrorMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…