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

Function TestPluginSocketCommunication

e2e/cli-plugins/socket_test.go:149–246  ·  view source on GitHub ↗
(t *testing.T)

Source from the content-addressed store, hash-verified

147}
148
149func TestPluginSocketCommunication(t *testing.T) {
150 run, _, cleanup := prepare(t)
151 defer cleanup()
152
153 t.Run("attached", func(t *testing.T) {
154 t.Run("the socket is not closed + the plugin receives a signal due to pgid", func(t *testing.T) {
155 cmd := run("presocket", "test-socket")
156 command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
157
158 ptmx, err := pty.Start(command)
159 assert.NilError(t, err, "failed to launch command with fake TTY")
160
161 // send a SIGINT to the process group after 1 second, since
162 // we're simulating an "attached TTY" scenario and a TTY would
163 // send a signal to the process group
164 go func() {
165 <-time.After(time.Second)
166 err := syscall.Kill(-command.Process.Pid, syscall.SIGINT)
167 assert.NilError(t, err, "failed to signal process group")
168 }()
169 out, err := io.ReadAll(ptmx)
170 if err != nil && !strings.Contains(err.Error(), "input/output error") {
171 t.Fatal("failed to get command output")
172 }
173
174 // the plugin is attached to the TTY, so the parent process
175 // ignores the received signal, and the plugin receives a SIGINT
176 // as well
177 assert.Equal(t, string(out), "received SIGINT\r\nexit after 3 seconds\r\n")
178 })
179 })
180
181 t.Run("detached", func(t *testing.T) {
182 t.Run("the plugin does not get signalled", func(t *testing.T) {
183 cmd := run("presocket", "test-socket")
184 command := exec.Command(cmd.Command[0], cmd.Command[1:]...)
185 command.SysProcAttr = &syscall.SysProcAttr{
186 Setpgid: true,
187 }
188
189 // send a SIGINT to the process group after 1 second
190 go func() {
191 <-time.After(time.Second)
192 err := syscall.Kill(command.Process.Pid, syscall.SIGINT)
193 assert.NilError(t, err, "failed to signal CLI process")
194 }()
195 out, err := command.CombinedOutput()
196
197 var exitError *exec.ExitError
198 assert.Assert(t, errors.As(err, &exitError))
199 assert.Check(t, exitError.Exited())
200 assert.Check(t, is.Equal(exitError.ExitCode(), 2))
201
202 // the plugin does not get signalled, but it does get its
203 // context canceled by the CLI through the socket
204 const expected = "test-socket: exiting after context was done"
205 actual := strings.TrimSpace(string(out))
206 assert.Check(t, is.Equal(actual, expected))

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…