From 3c376a817e6b825df192a4d3fdb65404e1276f81 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Fri, 9 May 2025 11:15:01 +0200 Subject: [PATCH 1/3] fix: avoid adding extraneous line feed when tail logs Signed-off-by: fahed dorgaa --- cmd/nerdctl/container/container_logs_test.go | 28 ++++++++++++++++++++ pkg/logging/json_logger_test.go | 3 ++- pkg/logging/jsonfile/jsonfile.go | 2 +- pkg/logging/logging.go | 2 +- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index 0ea37dab378..12bf2568a5b 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -394,6 +394,34 @@ func TestLogsWithDetails(t *testing.T) { testCase.Run(t) } +func TestLogsFollowNoExtraneousLineFeed(t *testing.T) { + testCase := nerdtest.Setup() + // This test verifies that `nerdctl logs -f` does not add extraneous line feeds + testCase.Require = require.Not(require.Windows) + + testCase.Setup = func(data test.Data, helpers test.Helpers) { + // Create a container that outputs a message without a trailing newline + // and then sleeps to keep the container running for the logs -f command + helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, + "sh", "-c", "printf 'Hello without newline'; sleep 5") + } + + testCase.Cleanup = func(data test.Data, helpers test.Helpers) { + helpers.Anyhow("rm", "-f", data.Identifier()) + } + + testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { + // Use logs -f to follow the logs + // The container will exit after 5 seconds, so we don't need an explicit timeout + return helpers.Command("logs", "-f", data.Identifier()) + } + + // Verify that the output is exactly "Hello without newline" without any additional line feeds + testCase.Expected = test.Expects(0, nil, expect.Equals("Hello without newline")) + + testCase.Run(t) +} + func TestLogsWithStartContainer(t *testing.T) { testCase := nerdtest.Setup() diff --git a/pkg/logging/json_logger_test.go b/pkg/logging/json_logger_test.go index 7d0be36285d..7b41c10a68c 100644 --- a/pkg/logging/json_logger_test.go +++ b/pkg/logging/json_logger_test.go @@ -73,6 +73,7 @@ func TestReadRotatedJSONLog(t *testing.T) { time.Sleep(1 * time.Millisecond) logData, _ := json.Marshal(log) file.Write(logData) + file.Write([]byte("\n")) if line == 5 { file.Close() @@ -104,7 +105,7 @@ func TestReadRotatedJSONLog(t *testing.T) { close(containerStopped) if expectedStdout != stdoutBuf.String() { - t.Errorf("expected: %s, acoutal: %s", expectedStdout, stdoutBuf.String()) + t.Errorf("expected: %s, actual: %s", expectedStdout, stdoutBuf.String()) } } diff --git a/pkg/logging/jsonfile/jsonfile.go b/pkg/logging/jsonfile/jsonfile.go index a1693cda0d7..6e6f7984eda 100644 --- a/pkg/logging/jsonfile/jsonfile.go +++ b/pkg/logging/jsonfile/jsonfile.go @@ -54,7 +54,7 @@ func Encode(stdout <-chan string, stderr <-chan string, writer io.Writer) error Stream: name, } for logEntry := range dataChan { - e.Log = logEntry + "\n" + e.Log = logEntry e.Time = time.Now().UTC() encMu.Lock() encErr := enc.Encode(e) diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index eab10cbd726..3030660cf0e 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -255,7 +255,7 @@ func loggingProcessAdapter(ctx context.Context, driver Driver, dataStore, addres var s string s, err = r.ReadString('\n') if len(s) > 0 { - dataChan <- strings.TrimSuffix(s, "\n") + dataChan <- s } if err != nil && err != io.EOF { From 87a976dc6354b73c0fa7bb400885b14dbd4741af Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Sat, 10 May 2025 01:57:17 +0200 Subject: [PATCH 2/3] test: add delay to ensure logs are available before following Signed-off-by: fahed dorgaa --- cmd/nerdctl/container/container_logs_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index 12bf2568a5b..deac334f6e2 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -413,6 +413,8 @@ func TestLogsFollowNoExtraneousLineFeed(t *testing.T) { testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { // Use logs -f to follow the logs // The container will exit after 5 seconds, so we don't need an explicit timeout + // Arbitrary, but we need to wait until the logs show up + time.Sleep(3 * time.Second) return helpers.Command("logs", "-f", data.Identifier()) } From a5d170183ce47d49f97213505aca1ce36d87d082 Mon Sep 17 00:00:00 2001 From: fahed dorgaa Date: Sat, 10 May 2025 14:44:27 +0200 Subject: [PATCH 3/3] test: remove unnecessary sleep in container setup for log tests Signed-off-by: fahed dorgaa --- cmd/nerdctl/container/container_logs_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/nerdctl/container/container_logs_test.go b/cmd/nerdctl/container/container_logs_test.go index deac334f6e2..d6011260e4e 100644 --- a/cmd/nerdctl/container/container_logs_test.go +++ b/cmd/nerdctl/container/container_logs_test.go @@ -401,9 +401,8 @@ func TestLogsFollowNoExtraneousLineFeed(t *testing.T) { testCase.Setup = func(data test.Data, helpers test.Helpers) { // Create a container that outputs a message without a trailing newline - // and then sleeps to keep the container running for the logs -f command helpers.Ensure("run", "-d", "--name", data.Identifier(), testutil.CommonImage, - "sh", "-c", "printf 'Hello without newline'; sleep 5") + "sh", "-c", "printf 'Hello without newline'") } testCase.Cleanup = func(data test.Data, helpers test.Helpers) { @@ -412,7 +411,6 @@ func TestLogsFollowNoExtraneousLineFeed(t *testing.T) { testCase.Command = func(data test.Data, helpers test.Helpers) test.TestableCommand { // Use logs -f to follow the logs - // The container will exit after 5 seconds, so we don't need an explicit timeout // Arbitrary, but we need to wait until the logs show up time.Sleep(3 * time.Second) return helpers.Command("logs", "-f", data.Identifier())