diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2023-05-27 13:11:25 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2023-05-27 13:11:25 +1000 |
commit | b146c055784b5add8dfb748f1b7beb3faa88c293 (patch) | |
tree | 4cb2d8e023bdf09a6ff563b816898076fdfd5897 | |
parent | 6c7f893f7a7848234ba7fd516417c7aebecfeea4 (diff) |
-rw-r--r-- | pkg/commands/oscommands/cmd_obj_runner_win.go | 40 | ||||
-rw-r--r-- | pkg/gui/gui.go | 1 | ||||
-rw-r--r-- | pkg/gui/gui_driver.go | 1 | ||||
-rw-r--r-- | pkg/gui/test_mode.go | 54 | ||||
-rw-r--r-- | pkg/integration/clients/go_test.go | 4 | ||||
-rw-r--r-- | pkg/integration/components/runner.go | 11 | ||||
-rw-r--r-- | pkg/integration/tests/ui/double_popup.go | 3 | ||||
-rw-r--r-- | pkg/integration/types/types.go | 1 | ||||
-rw-r--r-- | pkg/logs/logs.go | 1 | ||||
-rwxr-xr-x | test/files/pre-push | 15 |
10 files changed, 51 insertions, 80 deletions
diff --git a/pkg/commands/oscommands/cmd_obj_runner_win.go b/pkg/commands/oscommands/cmd_obj_runner_win.go index 6893a2535..083a035e6 100644 --- a/pkg/commands/oscommands/cmd_obj_runner_win.go +++ b/pkg/commands/oscommands/cmd_obj_runner_win.go @@ -4,48 +4,20 @@ package oscommands import ( - "bytes" - "io" "os/exec" - "github.com/sasha-s/go-deadlock" + "github.com/creack/pty" ) -type Buffer struct { - b bytes.Buffer - m deadlock.Mutex -} - -func (b *Buffer) Read(p []byte) (n int, err error) { - b.m.Lock() - defer b.m.Unlock() - return b.b.Read(p) -} - -func (b *Buffer) Write(p []byte) (n int, err error) { - b.m.Lock() - defer b.m.Unlock() - return b.b.Write(p) -} - -// TODO: Remove this hack and replace it with a proper way to run commands live on windows. We still have an issue where if a password is requested, the request for a password is written straight to stdout because we can't control the stdout of a subprocess of a subprocess. Keep an eye on https://github.com/creack/pty/pull/109 func (self *cmdObjRunner) getCmdHandler(cmd *exec.Cmd) (*cmdHandler, error) { - stdoutReader, stdoutWriter := io.Pipe() - cmd.Stdout = stdoutWriter - - buf := &Buffer{} - cmd.Stdin = buf - - if err := cmd.Start(); err != nil { + ptmx, err := pty.Start(cmd) + if err != nil { return nil, err } - // because we don't yet have windows support for a pty, we instead just - // pass our standard stream handlers and because there's no pty to close - // we pass a no-op function for that. return &cmdHandler{ - stdoutPipe: stdoutReader, - stdinPipe: buf, - close: func() error { return nil }, + stdoutPipe: ptmx, + stdinPipe: ptmx, + close: ptmx.Close, }, nil } diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 4c69a4e4e..a169373af 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -617,6 +617,7 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error { gui.c.Log.Info("starting main loop") + defer gui.handlePanicInTest(startArgs.IntegrationTest) gui.handleTestMode(startArgs.IntegrationTest) return gui.g.MainLoop() diff --git a/pkg/gui/gui_driver.go b/pkg/gui/gui_driver.go index a90578b65..d4f140b56 100644 --- a/pkg/gui/gui_driver.go +++ b/pkg/gui/gui_driver.go @@ -70,6 +70,7 @@ func (self *GuiDriver) Fail(message string) { self.gui.g.Close() // need to give the gui time to close time.Sleep(time.Millisecond * 100) + self.Log("test failed") panic(fullMessage) } diff --git a/pkg/gui/test_mode.go b/pkg/gui/test_mode.go index 5b61f3ccc..ed45542d6 100644 --- a/pkg/gui/test_mode.go +++ b/pkg/gui/test_mode.go @@ -19,46 +19,54 @@ type IntegrationTest interface { } func (gui *Gui) handleTestMode(test integrationTypes.IntegrationTest) { - if os.Getenv(components.SANDBOX_ENV_VAR) == "true" { + if os.Getenv(components.SANDBOX_ENV_VAR) == "true" || test == nil { return } - if test != nil { - go func() { - time.Sleep(time.Millisecond * 100) + go func() { + defer gui.handlePanicInTest(test) - defer handlePanic() + time.Sleep(time.Millisecond * 100) - guiDriver := &GuiDriver{gui: gui} - test.Run(guiDriver) + guiDriver := &GuiDriver{gui: gui} + test.Run(guiDriver) - // if we're here then the test must have passed: it panics upon failure - if err := result.LogSuccess(); err != nil { - panic(err) - } + // if we're here then the test must have passed: it panics upon failure + gui.Log.Warnf("test %s logging success", test.Name()) + if err := result.LogSuccess(); err != nil { + gui.Log.Warnf("test %s failed to log success!", test.Name()) + panic(err) + } - gui.g.Update(func(*gocui.Gui) error { - return gocui.ErrQuit - }) + gui.g.Update(func(*gocui.Gui) error { + return gocui.ErrQuit + }) - time.Sleep(time.Second * 1) + time.Sleep(time.Second * 1) - log.Fatal("gocui should have already exited") - }() + log.Fatal("gocui should have already exited") + }() - go utils.Safe(func() { - time.Sleep(time.Second * 40) - log.Fatal("40 seconds is up, lazygit recording took too long to complete") - }) - } + go utils.Safe(func() { + defer gui.handlePanicInTest(test) + + time.Sleep(time.Second * 40) + panic("40 seconds is up, lazygit recording took too long to complete") + }) } -func handlePanic() { +func (gui *Gui) handlePanicInTest(test integrationTypes.IntegrationTest) { + if test == nil { + return + } + if r := recover(); r != nil { buf := make([]byte, 4096*4) // arbitrarily large buffer size stackSize := runtime.Stack(buf, false) stackTrace := string(buf[:stackSize]) + gui.Log.Warnf("test %s panicked!", test.Name()) + if err := result.LogFailure(fmt.Sprintf("%v\n%s", r, stackTrace)); err != nil { panic(err) } diff --git a/pkg/integration/clients/go_test.go b/pkg/integration/clients/go_test.go index cf938ccc8..565569254 100644 --- a/pkg/integration/clients/go_test.go +++ b/pkg/integration/clients/go_test.go @@ -82,12 +82,9 @@ func runCmdHeadless(cmd *exec.Cmd) error { _, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 300, Cols: 300}) if err != nil { - panic(err) return err } - fmt.Println("about to wait") - _ = cmd.Wait() time.Sleep(time.Second) @@ -99,7 +96,6 @@ func runCmdHeadless(cmd *exec.Cmd) error { if !result.Success { return errors.New(result.Message) } - fmt.Printf("test succeeded") return nil } diff --git a/pkg/integration/components/runner.go b/pkg/integration/components/runner.go index c6266d397..57e59523e 100644 --- a/pkg/integration/components/runner.go +++ b/pkg/integration/components/runner.go @@ -35,14 +35,12 @@ func RunTests( projectRootDir := utils.GetLazyRootDirectory() err := os.Chdir(projectRootDir) if err != nil { - panic(err) return err } testDir := filepath.Join(projectRootDir, "test", "results") if err := buildLazygit(); err != nil { - panic(err) return err } @@ -63,7 +61,6 @@ func RunTests( err := runTest(test, paths, projectRootDir, logf, runCmd, sandbox, keyPressDelay, gitVersion) if err != nil { if i == maxAttempts-1 { - panic(err) return err } logf("retrying test %s", test.Name()) @@ -100,18 +97,17 @@ func runTest( } if err := prepareTestDir(test, paths, projectRootDir); err != nil { - panic(err) return err } cmd, err := getLazygitCommand(test, paths, projectRootDir, sandbox, keyPressDelay) if err != nil { - panic(err) + return err } err = runCmd(cmd) if err != nil { - panic(err) + return err } return nil @@ -164,7 +160,6 @@ func getGitVersion() (*git_commands.GitVersion, error) { cmdObj := osCommand.Cmd.New([]string{"git", "--version"}) versionStr, err := cmdObj.RunWithOutput() if err != nil { - panic(err) return nil, err } return git_commands.ParseGitVersion(versionStr) @@ -175,14 +170,12 @@ func getLazygitCommand(test *IntegrationTest, paths Paths, rootDir string, sandb err := os.RemoveAll(paths.Config()) if err != nil { - panic(err) return nil, err } templateConfigDir := filepath.Join(rootDir, "test", "default_test_config") err = oscommands.CopyDir(templateConfigDir, paths.Config()) if err != nil { - panic(err) return nil, err } diff --git a/pkg/integration/tests/ui/double_popup.go b/pkg/integration/tests/ui/double_popup.go index 2d6b7fe20..9843c3e48 100644 --- a/pkg/integration/tests/ui/double_popup.go +++ b/pkg/integration/tests/ui/double_popup.go @@ -16,6 +16,9 @@ var DoublePopup = NewIntegrationTest(NewIntegrationTestArgs{ Run: func(t *TestDriver, keys config.KeybindingConfig) { t.Views().Branches(). Focus(). + Lines( + Contains("master"), + ). // arbitrarily bringing up a popup PressPrimaryAction() diff --git a/pkg/integration/types/types.go b/pkg/integration/types/types.go index a26ac67af..193d06c86 100644 --- a/pkg/integration/types/types.go +++ b/pkg/integration/types/types.go @@ -13,6 +13,7 @@ import ( type IntegrationTest interface { Run(GuiDriver) SetupConfig(config *config.AppConfig) + Name() string } // this is the interface through which our integration tests interact with the lazygit gui diff --git a/pkg/logs/logs.go b/pkg/logs/logs.go index 3558e52a6..bc3279c87 100644 --- a/pkg/logs/logs.go +++ b/pkg/logs/logs.go @@ -35,6 +35,7 @@ func NewProductionLogger() *logrus.Entry { } func NewDevelopmentLogger(logPath string) *logrus.Entry { + logPath = `C:\Users\New\AppData\Roaming\jesseduffield\lazygit\development.log` logger := logrus.New() logger.SetLevel(getLogLevel()) diff --git a/test/files/pre-push b/test/files/pre-push index 3b758c1b1..0ec35d20a 100755 --- a/test/files/pre-push +++ b/test/files/pre-push @@ -8,20 +8,15 @@ # this will hang if you're using git from the command line, so only enable this # when you are testing the credentials view in lazygit -exec < /dev/tty +read -p "Username for 'github': " username +read -p "Password for 'github': " password -echo -n "Username for 'github': " -read username +echo -echo -n "Password for 'github': " -# this will print the password to the log view but real git won't do that. -# We could use read -s but that's not POSIX compliant. -read password - -if [ "$username" = "username" -a "$password" = "password" ]; then +if [[ "$username" == "username" && "$password" == "password" ]]; then echo "success" exit 0 fi ->&2 echo "incorrect username/password" +echo "incorrect username/password" >&2 exit 1 |