Compare commits
1 Commits
github-rel
...
writing-in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f555ddb74 |
@@ -1,12 +1,15 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/result"
|
||||
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
@@ -24,7 +27,15 @@ func (gui *Gui) handleTestMode(test integrationTypes.IntegrationTest) {
|
||||
go func() {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
|
||||
test.Run(&GuiDriver{gui: gui})
|
||||
defer handlePanic()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
gui.g.Update(func(*gocui.Gui) error {
|
||||
return gocui.ErrQuit
|
||||
@@ -42,6 +53,21 @@ func (gui *Gui) handleTestMode(test integrationTypes.IntegrationTest) {
|
||||
}
|
||||
}
|
||||
|
||||
func handlePanic() {
|
||||
if r := recover(); r != nil {
|
||||
buf := make([]byte, 4096*4) // arbitrarily large buffer size
|
||||
stackSize := runtime.Stack(buf, false)
|
||||
stackTrace := string(buf[:stackSize])
|
||||
|
||||
if err := result.LogFailure(fmt.Sprintf("%v\n%s", r, stackTrace)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Re-panic
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
|
||||
func Headless() bool {
|
||||
return os.Getenv("HEADLESS") != ""
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package clients
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/result"
|
||||
"github.com/jesseduffield/lazygit/pkg/integration/tests"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -63,6 +65,9 @@ func runCmdHeadless(cmd *exec.Cmd) error {
|
||||
"TERM=xterm",
|
||||
)
|
||||
|
||||
resultPath := result.GetResultPath()
|
||||
result.SetResultPathEnvVar(cmd, resultPath)
|
||||
|
||||
// not writing stderr to the pty because we want to capture a panic if
|
||||
// there is one. But some commands will not be in tty mode if stderr is
|
||||
// not a terminal. We'll need to keep an eye out for that.
|
||||
@@ -79,10 +84,20 @@ func runCmdHeadless(cmd *exec.Cmd) error {
|
||||
|
||||
_, _ = io.Copy(ioutil.Discard, f)
|
||||
|
||||
if cmd.Wait() != nil {
|
||||
// return an error with the stderr output
|
||||
return errors.New(stderr.String())
|
||||
_ = cmd.Wait()
|
||||
|
||||
result, err := result.ReadResult(resultPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading integration test result: %w", err)
|
||||
}
|
||||
if !result.Success {
|
||||
return errors.New(result.Message)
|
||||
}
|
||||
|
||||
// if cmd.Wait() != nil {
|
||||
// // return an error with the stderr output
|
||||
// return errors.New(stderr.String())
|
||||
// }
|
||||
|
||||
return f.Close()
|
||||
}
|
||||
|
||||
102
pkg/integration/result/result.go
Normal file
102
pkg/integration/result/result.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package result
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// On windows the pty package is failing to obtain stderr text when a test fails,
|
||||
// so this is our workaround: when a test fails, it writes the result to a file,
|
||||
// and then the test runner reads the file and checks the result
|
||||
|
||||
const PathEnvVar = "LAZYGIT_INTEGRATION_TEST_RESULT_PATH"
|
||||
|
||||
type IntegrationTestResult struct {
|
||||
Success bool
|
||||
Message string
|
||||
}
|
||||
|
||||
func LogFailure(message string) error {
|
||||
return writeResult(failure(message))
|
||||
}
|
||||
|
||||
func LogSuccess() error {
|
||||
return writeResult(success())
|
||||
}
|
||||
|
||||
func failure(message string) IntegrationTestResult {
|
||||
return IntegrationTestResult{Success: false, Message: message}
|
||||
}
|
||||
|
||||
func success() IntegrationTestResult {
|
||||
return IntegrationTestResult{Success: true}
|
||||
}
|
||||
|
||||
func writeResult(result IntegrationTestResult) error {
|
||||
resultPath := os.Getenv(PathEnvVar)
|
||||
if resultPath == "" {
|
||||
return fmt.Errorf("Environment variable %s not set", PathEnvVar)
|
||||
}
|
||||
|
||||
file, err := os.Create(resultPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
encoder := json.NewEncoder(file)
|
||||
err = encoder.Encode(result)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error encoding JSON: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reads the result file stored by the lazygit test, and deletes the file
|
||||
func ReadResult(resultPath string) (IntegrationTestResult, error) {
|
||||
file, err := os.Open(resultPath)
|
||||
if err != nil {
|
||||
return IntegrationTestResult{}, fmt.Errorf("Error creating file: %w", err)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(file)
|
||||
var result IntegrationTestResult
|
||||
err = decoder.Decode(&result)
|
||||
if err != nil {
|
||||
file.Close()
|
||||
return IntegrationTestResult{}, fmt.Errorf("Error decoding JSON: %w", err)
|
||||
}
|
||||
|
||||
file.Close()
|
||||
_ = os.Remove(resultPath)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func SetResultPathEnvVar(cmd *exec.Cmd, resultPath string) {
|
||||
cmd.Env = append(
|
||||
cmd.Env,
|
||||
fmt.Sprintf("%s=%s", PathEnvVar, resultPath),
|
||||
)
|
||||
}
|
||||
|
||||
func GetResultPath() string {
|
||||
return filepath.Join(os.TempDir(), fmt.Sprintf("lazygit_result_%s.json", generateRandomString(10)))
|
||||
}
|
||||
|
||||
func generateRandomString(length int) string {
|
||||
buffer := make([]byte, length)
|
||||
_, err := rand.Read(buffer)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Could not generate random string: %s", err))
|
||||
}
|
||||
|
||||
randomString := base64.URLEncoding.EncodeToString(buffer)
|
||||
return randomString[:length]
|
||||
}
|
||||
@@ -27,7 +27,7 @@ var Commit = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
PressPrimaryAction(). // stage file
|
||||
Lines(
|
||||
Contains("A myfile").IsSelected(),
|
||||
Contains("?? myfile2"),
|
||||
Contains("?? myfile23"),
|
||||
).
|
||||
SelectNextItem().
|
||||
PressPrimaryAction(). // stage other file
|
||||
|
||||
Reference in New Issue
Block a user