forked from cloudposse/atmos
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain_plan_diff_integration_test.go
More file actions
126 lines (105 loc) 路 3.99 KB
/
Copy pathmain_plan_diff_integration_test.go
File metadata and controls
126 lines (105 loc) 路 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"os"
"path/filepath"
"runtime"
"testing"
"time"
errUtils "github.com/cloudposse/atmos/errors"
)
func TestMainTerraformPlanDiffIntegration(t *testing.T) {
// We need to intercept calls to os.Exit so the test doesn't fail
oldOsExit := errUtils.OsExit
defer func() { errUtils.OsExit = oldOsExit }()
// Create a channel to communicate the exit code
exitCodeCh := make(chan int, 1)
// Mock the OsExit function to capture the exit code
errUtils.OsExit = func(code int) {
t.Logf("Exit code set to: %d", code)
exitCodeCh <- code
// Do not actually exit the process
}
// Helper function to run main and get the exit code
runMainWithExitCode := func() int {
// Clear the channel
select {
case <-exitCodeCh:
// Drain any previous value
default:
// Channel is empty
}
// Create a done channel to signal when main has completed
done := make(chan struct{})
// Run main in a goroutine
go func() {
defer close(done)
main()
// If main returns without calling OsExit, send 0
select {
case exitCodeCh <- 0:
default:
// Channel already has a value, which means OsExit was called
}
}()
// Wait for exit code and ensure goroutine completes (all platforms)
select {
case code := <-exitCodeCh:
<-done // Wait for main to finish including all defers
return code
case <-done:
// Main completed without calling OsExit
return <-exitCodeCh
}
}
// Change to the tests/fixtures/scenarios/plan-diff directory
t.Chdir("tests/fixtures/scenarios/plan-diff")
// This integration test calls main() directly (via runMainWithExitCode) which reads os.Args internally.
// Using os.Args is necessary for testing the complete main() execution path.
// main() has no parameters and must read os.Args to get command-line arguments.
origArgs := os.Args
defer func() { os.Args = origArgs }()
// Create a temporary directory for plan files
tmpDir := t.TempDir()
origPlanFile := filepath.Join(tmpDir, "orig.plan")
newPlanFile := filepath.Join(tmpDir, "new.plan")
// Generate the original plan
os.Args = []string{"atmos", "terraform", "plan", "component-1", "-s", "nonprod", "-out=" + origPlanFile}
exitCode := runMainWithExitCode()
t.Logf("After first plan, exit code: %d", exitCode)
if exitCode != 0 {
t.Fatalf("plan command failed with exit code %d", exitCode)
}
// Generate a new plan with a different variable
os.Args = []string{"atmos", "terraform", "plan", "component-1", "-s", "nonprod", "-out=" + newPlanFile, "-var", "foo=new-value"}
exitCode = runMainWithExitCode()
t.Logf("After second plan, exit code: %d", exitCode)
if exitCode != 0 {
t.Fatalf("plan command with variable failed with exit code %d", exitCode)
}
// Run the plan-diff command
os.Args = []string{"atmos", "terraform", "plan-diff", "component-1", "-s", "nonprod", "--orig=" + origPlanFile, "--new=" + newPlanFile}
exitCode = runMainWithExitCode()
t.Logf("After plan-diff, exit code: %d", exitCode)
// The plan-diff command should set the exit code to 2 when plans are different
if exitCode != 2 {
t.Fatalf("plan-diff command should have returned exit code 2, got %d", exitCode)
}
// Add a delay to ensure Windows file operations are complete and file handles are released
if runtime.GOOS == "windows" {
time.Sleep(2 * time.Second)
} else {
time.Sleep(500 * time.Millisecond)
}
// Verify the original plan file still exists before the second invocation
if _, err := os.Stat(origPlanFile); err != nil {
t.Fatalf("original plan file no longer exists before second plan-diff: %v", err)
}
// Test with generating a new plan on the fly
os.Args = []string{"atmos", "terraform", "plan-diff", "component-1", "-s", "nonprod", "--orig=" + origPlanFile, "-var", "foo=new-value"}
exitCode = runMainWithExitCode()
t.Logf("After on-the-fly plan-diff, exit code: %d", exitCode)
// The plan-diff command should set the exit code to 2 when plans are different
if exitCode != 2 {
t.Fatalf("plan-diff command with on-the-fly plan should have returned exit code 2, got %d", exitCode)
}
}