TestLoggingProcessAdapterTrailingChunk verifies that the logger forwards all of the container's output, including a final chunk that has no trailing newline, rather than holding that chunk back until something closes the stream. The container's stdio FIFOs are modelled with os.Pipe; closing the writ
(t *testing.T)
| 149 | // write end models the container exiting and containerd closing the FIFO. |
| 150 | // Regression test for https://github.com/containerd/nerdctl/issues/5006 |
| 151 | func TestLoggingProcessAdapterTrailingChunk(t *testing.T) { |
| 152 | const expected = "'Hello World!\nThere is no newline'" |
| 153 | |
| 154 | stdoutR, stdoutW, err := os.Pipe() |
| 155 | if err != nil { |
| 156 | t.Fatal(err) |
| 157 | } |
| 158 | defer stdoutR.Close() |
| 159 | stderrR, stderrW, err := os.Pipe() |
| 160 | if err != nil { |
| 161 | t.Fatal(err) |
| 162 | } |
| 163 | defer stderrR.Close() |
| 164 | |
| 165 | driver := &MockDriver{} |
| 166 | config := &logging.Config{ |
| 167 | Stdout: stdoutR, |
| 168 | Stderr: stderrR, |
| 169 | } |
| 170 | |
| 171 | // Write the container's output, including a trailing chunk without a newline, |
| 172 | // then close the write ends to model the container exiting. |
| 173 | if _, err := stdoutW.WriteString(expected); err != nil { |
| 174 | t.Fatal(err) |
| 175 | } |
| 176 | stdoutW.Close() |
| 177 | stderrW.Close() |
| 178 | |
| 179 | ctx, cancel := context.WithCancel(context.Background()) |
| 180 | defer cancel() |
| 181 | |
| 182 | // getContainerWait never reports an exit here: completion is driven by the |
| 183 | // FIFOs reaching EOF, as it usually is in practice. |
| 184 | var getContainerWaitMock ContainerWaitFunc = func(ctx context.Context, address string, config *logging.Config, outputSeen func() bool) (<-chan containerd.ExitStatus, error) { |
| 185 | return make(chan containerd.ExitStatus), nil |
| 186 | } |
| 187 | |
| 188 | if err := loggingProcessAdapter(ctx, driver, "testDataStore", "", getContainerWaitMock, config); err != nil { |
| 189 | t.Fatal(err) |
| 190 | } |
| 191 | |
| 192 | if actual := strings.Join(driver.receivedStdout, ""); actual != expected { |
| 193 | t.Fatalf("stdout is %q, expected %q", actual, expected) |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | // TestLoggingProcessAdapterSyncTrailingChunk verifies the same trailing-chunk |
| 198 | // behaviour for a driver that writes synchronously (SyncDriver), which is the |
nothing calls this directly
no test coverage detected
searching dependent graphs…