From bf3a378139c7a43955a82f7cfa321e1d8f6f272a Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 20 May 2022 19:11:39 +0300 Subject: [PATCH 1/7] bug: Add test that breaks ptytest on Intel Mac --- pty/ptytest/ptytest_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index 5792492c6df1e..eee767ac43948 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -1,8 +1,11 @@ package ptytest_test import ( + "os/exec" "testing" + "github.com/stretchr/testify/require" + "github.com/coder/coder/pty/ptytest" ) @@ -15,4 +18,13 @@ func TestPtytest(t *testing.T) { pty.ExpectMatch("write") pty.WriteLine("read") }) + // nolint:paralleltest + t.Run("Do not hang on Intel macOS", func(t *testing.T) { + cmd := exec.Command("sh", "-c", "for i in $(seq 1 1000); do echo $i; done") + pty := ptytest.New(t) + cmd.Stdin = pty.Input() + cmd.Stdout = pty.Output() + err := cmd.Run() + require.NoError(t, err) + }) } From 65f330410f86305df0c64baedf9280b5b3fbc52e Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 20 May 2022 19:15:07 +0300 Subject: [PATCH 2/7] Simplify test, no need to output more than one line --- pty/ptytest/ptytest_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index eee767ac43948..5dba173f0df65 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -20,7 +20,7 @@ func TestPtytest(t *testing.T) { }) // nolint:paralleltest t.Run("Do not hang on Intel macOS", func(t *testing.T) { - cmd := exec.Command("sh", "-c", "for i in $(seq 1 1000); do echo $i; done") + cmd := exec.Command("sh", "-c", "echo hi, I will cause a hang") pty := ptytest.New(t) cmd.Stdin = pty.Input() cmd.Stdout = pty.Output() From 638acb6f24d3a5a3b3a237b72bac97725247e735 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 20 May 2022 11:30:21 -0500 Subject: [PATCH 3/7] Add test using cobra cmd --- pty/ptytest/ptytest_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index 5dba173f0df65..542fbe9f39839 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -1,9 +1,11 @@ package ptytest_test import ( + "fmt" "os/exec" "testing" + "github.com/spf13/cobra" "github.com/stretchr/testify/require" "github.com/coder/coder/pty/ptytest" @@ -18,6 +20,7 @@ func TestPtytest(t *testing.T) { pty.ExpectMatch("write") pty.WriteLine("read") }) + // nolint:paralleltest t.Run("Do not hang on Intel macOS", func(t *testing.T) { cmd := exec.Command("sh", "-c", "echo hi, I will cause a hang") @@ -27,4 +30,23 @@ func TestPtytest(t *testing.T) { err := cmd.Run() require.NoError(t, err) }) + + // nolint:paralleltest + t.Run("CobraCommandWorksLinux", func(t *testing.T) { + // Example with cobra command instead of exec. More abstractions, but + // for some reason works on linux. + cmd := cobra.Command{ + Use: "test", + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Println("Hello world") + return nil + }, + } + + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + err := cmd.Execute() + require.NoError(t, err) + }) } From 7692c5d249acffa8ae46f41f28e72201d17207b0 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 7 Jun 2022 12:57:26 +0300 Subject: [PATCH 4/7] Create proper test to fully reproduce the issue on macOS --- pty/ptytest/ptytest_test.go | 54 ++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index 542fbe9f39839..a6622d0ca756a 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -2,7 +2,7 @@ package ptytest_test import ( "fmt" - "os/exec" + "strings" "testing" "github.com/spf13/cobra" @@ -21,32 +21,36 @@ func TestPtytest(t *testing.T) { pty.WriteLine("read") }) - // nolint:paralleltest - t.Run("Do not hang on Intel macOS", func(t *testing.T) { - cmd := exec.Command("sh", "-c", "echo hi, I will cause a hang") - pty := ptytest.New(t) - cmd.Stdin = pty.Input() - cmd.Stdout = pty.Output() - err := cmd.Run() - require.NoError(t, err) - }) + t.Run("Cobra ptytest should not hang when output is not consumed", func(t *testing.T) { + t.Parallel() - // nolint:paralleltest - t.Run("CobraCommandWorksLinux", func(t *testing.T) { - // Example with cobra command instead of exec. More abstractions, but - // for some reason works on linux. - cmd := cobra.Command{ - Use: "test", - RunE: func(cmd *cobra.Command, args []string) error { - fmt.Println("Hello world") - return nil - }, + tests := []struct { + name string + output string + }{ + {name: "1024 is safe (does not exceed macOS buffer)", output: strings.Repeat(".", 1024)}, + {name: "1025 exceeds macOS buffer (must not hang)", output: strings.Repeat(".", 1025)}, } + for _, tt := range tests { + tt := tt + // nolint:paralleltest // Avoid parallel test to more easily identify the issue. + t.Run(tt.name, func(t *testing.T) { + // Example with cobra command instead of exec. More abstractions, but + // for some reason works on linux. + cmd := cobra.Command{ + Use: "test", + RunE: func(cmd *cobra.Command, args []string) error { + fmt.Fprint(cmd.OutOrStdout(), tt.output) + return nil + }, + } - pty := ptytest.New(t) - cmd.SetIn(pty.Input()) - cmd.SetOut(pty.Output()) - err := cmd.Execute() - require.NoError(t, err) + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + err := cmd.Execute() + require.NoError(t, err) + }) + } }) } From 034cfa64d6848da1a380864283f55763f84663e9 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 7 Jun 2022 12:59:08 +0300 Subject: [PATCH 5/7] Add large output --- pty/ptytest/ptytest_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index a6622d0ca756a..49c263614fcc4 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -30,6 +30,7 @@ func TestPtytest(t *testing.T) { }{ {name: "1024 is safe (does not exceed macOS buffer)", output: strings.Repeat(".", 1024)}, {name: "1025 exceeds macOS buffer (must not hang)", output: strings.Repeat(".", 1025)}, + {name: "10241 large output", output: strings.Repeat(".", 10241)}, // 1024 * 10 + 1 } for _, tt := range tests { tt := tt From 487f338fa4bd256640698934e9ed1fdf3567d1ad Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 7 Jun 2022 16:44:05 +0300 Subject: [PATCH 6/7] Skip failing tests on darwin and windows --- pty/ptytest/ptytest_test.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index 49c263614fcc4..ee6c1c507d723 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -2,6 +2,7 @@ package ptytest_test import ( "fmt" + "runtime" "strings" "testing" @@ -25,19 +26,22 @@ func TestPtytest(t *testing.T) { t.Parallel() tests := []struct { - name string - output string + name string + output string + isPlatformBug bool // See https://github.com/coder/coder/issues/2122. }{ {name: "1024 is safe (does not exceed macOS buffer)", output: strings.Repeat(".", 1024)}, - {name: "1025 exceeds macOS buffer (must not hang)", output: strings.Repeat(".", 1025)}, - {name: "10241 large output", output: strings.Repeat(".", 10241)}, // 1024 * 10 + 1 + {name: "1025 exceeds macOS buffer (must not hang)", output: strings.Repeat(".", 1025), isPlatformBug: true}, + {name: "10241 large output", output: strings.Repeat(".", 10241), isPlatformBug: true}, // 1024 * 10 + 1 } for _, tt := range tests { tt := tt // nolint:paralleltest // Avoid parallel test to more easily identify the issue. t.Run(tt.name, func(t *testing.T) { - // Example with cobra command instead of exec. More abstractions, but - // for some reason works on linux. + if tt.isPlatformBug && (runtime.GOOS == "darwin" || runtime.GOOS == "windows") { + t.Skip("This test does not (currently) work on macOS or Windows") + } + cmd := cobra.Command{ Use: "test", RunE: func(cmd *cobra.Command, args []string) error { From 75b62969d43d04fc532656792f6232fcf741253b Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 7 Jun 2022 16:52:32 +0300 Subject: [PATCH 7/7] chore: Write better skip message --- pty/ptytest/ptytest_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pty/ptytest/ptytest_test.go b/pty/ptytest/ptytest_test.go index ee6c1c507d723..7dfba01f04478 100644 --- a/pty/ptytest/ptytest_test.go +++ b/pty/ptytest/ptytest_test.go @@ -28,7 +28,7 @@ func TestPtytest(t *testing.T) { tests := []struct { name string output string - isPlatformBug bool // See https://github.com/coder/coder/issues/2122. + isPlatformBug bool // See https://github.com/coder/coder/issues/2122 for more info. }{ {name: "1024 is safe (does not exceed macOS buffer)", output: strings.Repeat(".", 1024)}, {name: "1025 exceeds macOS buffer (must not hang)", output: strings.Repeat(".", 1025), isPlatformBug: true}, @@ -39,7 +39,7 @@ func TestPtytest(t *testing.T) { // nolint:paralleltest // Avoid parallel test to more easily identify the issue. t.Run(tt.name, func(t *testing.T) { if tt.isPlatformBug && (runtime.GOOS == "darwin" || runtime.GOOS == "windows") { - t.Skip("This test does not (currently) work on macOS or Windows") + t.Skip("This test hangs on macOS and Windows, see https://github.com/coder/coder/issues/2122") } cmd := cobra.Command{