summaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorCI <CI@example.com>2020-10-06 08:01:25 +1100
committerJesse Duffield <jessedduffield@gmail.com>2020-10-10 00:23:01 +1100
commit2657060aa28d88e3089686ca1ab0a6343b653b01 (patch)
tree6ef3e563a08994d9d13234e6117c541c24ba1238 /pkg
parent2724f3888a288aed1d5075465e7905cff1b8923e (diff)
support running integration tests in parallel
Diffstat (limited to 'pkg')
-rw-r--r--pkg/gui/gui_test.go95
-rw-r--r--pkg/gui/recording.go24
2 files changed, 77 insertions, 42 deletions
diff --git a/pkg/gui/gui_test.go b/pkg/gui/gui_test.go
index cff8bce66..9f0e08fe7 100644
--- a/pkg/gui/gui_test.go
+++ b/pkg/gui/gui_test.go
@@ -32,27 +32,31 @@ import (
// TODO: support passing an env var for playback speed, given it's currently pretty fast
type integrationTest struct {
- name string
- fixture string
+ name string
+ fixture string
+ startSpeed int
}
func tests() []integrationTest {
return []integrationTest{
{
- name: "commit",
- fixture: "newFile",
+ name: "commit",
+ fixture: "newFile",
+ startSpeed: 10,
},
{
name: "squash",
fixture: "manyCommits",
},
{
- name: "patchBuilding",
- fixture: "updatedFile",
+ name: "patchBuilding",
+ fixture: "updatedFile",
+ startSpeed: 3,
},
{
- name: "patchBuilding2",
- fixture: "updatedFile",
+ name: "patchBuilding2",
+ fixture: "updatedFile",
+ startSpeed: 3,
},
{
name: "mergeConflicts",
@@ -69,9 +73,11 @@ func tests() []integrationTest {
}
}
-func generateSnapshot(t *testing.T) string {
+func generateSnapshot(t *testing.T, actualDir string) string {
osCommand := oscommands.NewDummyOSCommand()
- cmd := `bash -c "git status; cat ./*; git log --pretty=%B -p"`
+ cmd := fmt.Sprintf(`bash -c "cd %s && git status; cat ./*; git log --pretty=%%B -p"`, actualDir)
+
+ // need to copy from current directory to
snapshot, err := osCommand.RunCommandWithOutput(cmd)
assert.NoError(t, err)
@@ -96,12 +102,7 @@ func findOrCreateDir(path string) {
func Test(t *testing.T) {
tests := tests()
- gotoRootDirectory()
-
- rootDir, err := os.Getwd()
- if err != nil {
- panic(err)
- }
+ rootDir := getRootDirectory()
record := os.Getenv("RECORD_EVENTS") != ""
updateSnapshots := record || os.Getenv("UPDATE_SNAPSHOTS") != ""
@@ -110,7 +111,15 @@ func Test(t *testing.T) {
test := test
t.Run(test.name, func(t *testing.T) {
- speeds := []int{10, 5, 1}
+ if usePty() {
+ t.Parallel()
+ }
+
+ startSpeed := 10
+ if test.startSpeed != 0 {
+ startSpeed = test.startSpeed
+ }
+ speeds := []int{startSpeed, 5, 1}
if updateSnapshots {
// have to go at original speed if updating snapshots in case we go to fast and create a junk snapshot
speeds = []int{1}
@@ -120,21 +129,19 @@ func Test(t *testing.T) {
t.Logf("%s: attempting test at speed %d\n", test.name, speed)
testPath := filepath.Join(rootDir, "test", "integration", test.name)
+ actualDir := filepath.Join(testPath, "actual")
findOrCreateDir(testPath)
snapshotPath := filepath.Join(testPath, "snapshot.txt")
- err := os.Chdir(rootDir)
- assert.NoError(t, err)
-
- prepareIntegrationTestDir()
+ prepareIntegrationTestDir(testPath)
- err = createFixture(rootDir, test.fixture)
+ err := createFixture(rootDir, test.fixture, actualDir)
assert.NoError(t, err)
runLazygit(t, testPath, rootDir, record, speed)
- actual := generateSnapshot(t)
+ actual := generateSnapshot(t, actualDir)
if updateSnapshots {
err := ioutil.WriteFile(snapshotPath, []byte(actual), 0600)
@@ -146,6 +153,7 @@ func Test(t *testing.T) {
expected := string(expectedBytes)
if expected == actual {
+ t.Logf("%s: success at speed %d\n", test.name, speed)
break
}
@@ -158,9 +166,9 @@ func Test(t *testing.T) {
}
}
-func createFixture(rootDir string, name string) error {
+func createFixture(rootDir string, name string, actualDir string) error {
osCommand := oscommands.NewDummyOSCommand()
- cmd := exec.Command("bash", filepath.Join(rootDir, "test", "fixtures", fmt.Sprintf("%s.sh", name)))
+ cmd := exec.Command("bash", filepath.Join(rootDir, "test", "fixtures", fmt.Sprintf("%s.sh", name)), actualDir)
if err := osCommand.RunExecutable(cmd); err != nil {
return err
@@ -169,20 +177,27 @@ func createFixture(rootDir string, name string) error {
return nil
}
-func gotoRootDirectory() {
+func getRootDirectory() string {
+ path, err := os.Getwd()
+ if err != nil {
+ panic(err)
+ }
+
for {
- _, err := os.Stat(".git")
+ _, err := os.Stat(filepath.Join(path, ".git"))
if err == nil {
- return
+ return path
}
if !os.IsNotExist(err) {
panic(err)
}
- if err = os.Chdir(".."); err != nil {
- panic(err)
+ path = filepath.Dir(path)
+
+ if path == "/" {
+ panic("must run in lazygit folder or child folder")
}
}
}
@@ -193,6 +208,7 @@ func runLazygit(t *testing.T, testPath string, rootDir string, record bool, spee
replayPath := filepath.Join(testPath, "recording.json")
cmdStr := fmt.Sprintf("go run %s", filepath.Join(rootDir, "main.go"))
templateConfigDir := filepath.Join(rootDir, "test", "default_test_config")
+ actualDir := filepath.Join(testPath, "actual")
exists, err := osCommand.FileExists(filepath.Join(testPath, "config"))
assert.NoError(t, err)
@@ -201,14 +217,14 @@ func runLazygit(t *testing.T, testPath string, rootDir string, record bool, spee
templateConfigDir = filepath.Join(testPath, "config")
}
- configDir := filepath.Join(rootDir, "test", "integration_test_config")
+ configDir := filepath.Join(testPath, "used_config")
err = os.RemoveAll(configDir)
assert.NoError(t, err)
err = oscommands.CopyDir(templateConfigDir, configDir)
assert.NoError(t, err)
- cmdStr = fmt.Sprintf("%s --use-config-dir=%s", cmdStr, configDir)
+ cmdStr = fmt.Sprintf("%s --use-config-dir=%s --path=%s", cmdStr, configDir, actualDir)
cmd := osCommand.ExecutableFromString(cmdStr)
cmd.Env = append(cmd.Env, fmt.Sprintf("REPLAY_SPEED=%d", speed))
@@ -226,7 +242,7 @@ func runLazygit(t *testing.T, testPath string, rootDir string, record bool, spee
}
// if we're on CI we'll need to use a PTY. We can work that out by seeing if the 'TERM' env is defined.
- if os.Getenv("TERM") == "" {
+ if usePty() {
cmd.Env = append(cmd.Env, "TERM=xterm")
f, err := pty.StartWithSize(cmd, &pty.Winsize{Rows: 100, Cols: 100})
@@ -243,8 +259,13 @@ func runLazygit(t *testing.T, testPath string, rootDir string, record bool, spee
}
}
-func prepareIntegrationTestDir() {
- path := filepath.Join("test", "integration_test")
+func usePty() bool {
+ return true
+ return os.Getenv("TERM") == ""
+}
+
+func prepareIntegrationTestDir(testPath string) {
+ path := filepath.Join(testPath, "actual")
// remove contents of integration test directory
dir, err := ioutil.ReadDir(path)
@@ -261,8 +282,4 @@ func prepareIntegrationTestDir() {
for _, d := range dir {
os.RemoveAll(filepath.Join(path, d.Name()))
}
-
- if err := os.Chdir(path); err != nil {
- panic(err)
- }
}
diff --git a/pkg/gui/recording.go b/pkg/gui/recording.go
index e47dac0ae..0f8f9a370 100644
--- a/pkg/gui/recording.go
+++ b/pkg/gui/recording.go
@@ -28,6 +28,11 @@ func (gui *Gui) replayRecordedEvents() {
return
}
+ go func() {
+ time.Sleep(time.Second * 20)
+ log.Fatal("20 seconds is up, lazygit recording took too long to complete")
+ }()
+
events, err := gui.loadRecordedEvents()
if err != nil {
log.Fatal(err)
@@ -49,13 +54,26 @@ func (gui *Gui) replayRecordedEvents() {
}
}
- for _, event := range events {
+ // The playback could be paused at any time because integration tests run concurrently.
+ // Therefore we can't just check for a given event whether we've passed its timestamp,
+ // or else we'll have an explosion of keypresses after the test is resumed.
+ // We need to check if we've waited long enough since the last event was replayed.
+ for i, event := range events {
+ var prevEventTimestamp int64 = 0
+ if i > 0 {
+ prevEventTimestamp = events[i-1].Timestamp
+ }
+ timeToWait := (event.Timestamp - prevEventTimestamp) / int64(speed)
+ if i == 0 {
+ timeToWait += leeway
+ }
+ var timeWaited int64 = 0
middle:
for {
select {
case <-ticker.C:
- now := gui.timeSinceStart()*int64(speed) - leeway
- if gui.g != nil && now >= event.Timestamp {
+ timeWaited += 1
+ if gui.g != nil && timeWaited >= timeToWait {
gui.g.ReplayedEvents <- *event.Event
break middle
}