Skip to content

Commit 2bb6323

Browse files
committed
test: add unit tests for main helpers
1 parent 494570b commit 2bb6323

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed

cmd/main_test.go

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"os/exec"
6+
"testing"
7+
8+
"go.uber.org/zap"
9+
)
10+
11+
const (
12+
ENTER_VALUE = "Enter value"
13+
INPUT_REQUIRED = "Input required"
14+
RECEIVED_INPUT = "Received input"
15+
)
16+
17+
// setupZapLogger is assumed to be defined in the same module.
18+
// If it is in a different package, import that package accordingly.
19+
20+
func TestSetupZapLoggerVerbose(t *testing.T) {
21+
// Set up the logger in verbose mode.
22+
setupZapLogger(true)
23+
24+
// The global logger (zap.L()) should allow debug logs.
25+
// Check that debug logs are enabled.
26+
if !zap.L().Core().Enabled(zap.DebugLevel) {
27+
t.Error("Expected debug level to be enabled in verbose mode but it is not")
28+
}
29+
30+
// Optionally, check that Info level logs are enabled.
31+
if !zap.L().Core().Enabled(zap.InfoLevel) {
32+
t.Error("Expected info level to be enabled in verbose mode but it is not")
33+
}
34+
}
35+
36+
func TestSetupZapLoggerNonVerbose(t *testing.T) {
37+
// Set up the logger in non-verbose (production) mode.
38+
setupZapLogger(false)
39+
40+
// The global logger (zap.L()) should not allow debug logs.
41+
if zap.L().Core().Enabled(zap.DebugLevel) {
42+
t.Error("Expected debug level to be disabled in non-verbose mode but it is enabled")
43+
}
44+
45+
// Info level logs must remain enabled.
46+
if !zap.L().Core().Enabled(zap.InfoLevel) {
47+
t.Error("Expected info level to be enabled in non-verbose mode but it is not")
48+
}
49+
}
50+
51+
// TestPromptForInputNonEmpty verifies that promptForInput returns the expected input
52+
// when a single token (with surrounding spaces) is provided.
53+
func TestPromptForInputNonEmpty(t *testing.T) {
54+
// Backup the original os.Stdin and restore it after the test.
55+
origStdin := os.Stdin
56+
defer func() { os.Stdin = origStdin }()
57+
58+
// Create a temporary file with a single token input.
59+
tempFile, err := os.CreateTemp("", "stdin")
60+
if err != nil {
61+
t.Fatalf("Failed to create temporary file: %v", err)
62+
}
63+
defer os.Remove(tempFile.Name())
64+
65+
// Write a single token with extra spaces. Note that fmt.Scanln reads a single token.
66+
input := " hello \n"
67+
if _, err := tempFile.WriteString(input); err != nil {
68+
t.Fatalf("Failed to write to temporary file: %v", err)
69+
}
70+
71+
// Reset the file offset to the beginning.
72+
if _, err := tempFile.Seek(0, 0); err != nil {
73+
t.Fatalf("Failed to reset file offset: %v", err)
74+
}
75+
76+
// Set the temporary file as os.Stdin.
77+
os.Stdin = tempFile
78+
79+
result := promptForInput("Enter text")
80+
expected := "hello"
81+
82+
if result != expected {
83+
t.Errorf("Expected %q, but got %q", expected, result)
84+
}
85+
}
86+
87+
// TestPromptForInputEmpty verifies that promptForInput calls zap.L().Fatal when no input token is provided.
88+
// Since fmt.Scanln returns an error ("unexpected newline") for an empty line, the function will call Fatal,
89+
// which results in os.Exit(1). To test this behavior without terminating the test run, we execute the test
90+
// in a subprocess.
91+
func TestPromptForInputEmpty(t *testing.T) {
92+
// Check if we are running inside the subprocess.
93+
if os.Getenv("BE_CRASHER") == "1" {
94+
// In the subprocess, create a temporary file that contains only a newline.
95+
tempFile, err := os.CreateTemp("", "stdin")
96+
if err != nil {
97+
os.Exit(2)
98+
}
99+
defer os.Remove(tempFile.Name())
100+
101+
if _, err := tempFile.WriteString("\n"); err != nil {
102+
os.Exit(2)
103+
}
104+
if _, err := tempFile.Seek(0, 0); err != nil {
105+
os.Exit(2)
106+
}
107+
os.Stdin = tempFile
108+
109+
// Calling promptForInput is expected to invoke zap.L().Fatal and exit.
110+
// Therefore, subsequent lines should never be reached.
111+
promptForInput("Enter text")
112+
// If we reach here, exit with a non-zero status.
113+
os.Exit(3)
114+
}
115+
116+
// Set up the command to run this test in a subprocess.
117+
cmd := exec.Command(os.Args[0], "-test.run=TestPromptForInputEmpty")
118+
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
119+
output, err := cmd.CombinedOutput()
120+
121+
// We expect the subprocess to exit with a non-zero exit code.
122+
if err == nil {
123+
t.Fatalf("Expected subprocess to fail, but it succeeded with output: %q", output)
124+
}
125+
}
126+
127+
// TestPromptForMandatoryInputWithDefault tests that if a non-empty defaultValue is provided,
128+
// the function returns it trimmed and does not prompt the user.
129+
func TestPromptForMandatoryInputWithDefault(t *testing.T) {
130+
defaultVal := " providedValue "
131+
res := promptForMandatoryInput(defaultVal, ENTER_VALUE, INPUT_REQUIRED, RECEIVED_INPUT, false, false)
132+
expected := "providedValue"
133+
if res != expected {
134+
t.Errorf("Expected %q but got %q", expected, res)
135+
}
136+
}
137+
138+
// TestPromptForMandatoryInputWithPrompt tests that if defaultValue is empty and prompting is enabled,
139+
// the function calls promptForInput and returns the user input trimmed.
140+
// We simulate the user input via a temporary file assigned to os.Stdin.
141+
func TestPromptForMandatoryInputWithPrompt(t *testing.T) {
142+
// Backup the original os.Stdin.
143+
origStdin := os.Stdin
144+
defer func() { os.Stdin = origStdin }()
145+
146+
// Create a temporary file to simulate user input.
147+
tempFile, err := os.CreateTemp("", "stdin")
148+
if err != nil {
149+
t.Fatalf("Failed to create temporary file: %v", err)
150+
}
151+
defer os.Remove(tempFile.Name())
152+
153+
// Write input; note that promptForInput uses fmt.Scanln which requires a single token.
154+
input := " userInput \n"
155+
if _, err := tempFile.WriteString(input); err != nil {
156+
t.Fatalf("Failed to write to temporary file: %v", err)
157+
}
158+
if _, err := tempFile.Seek(0, 0); err != nil {
159+
t.Fatalf("Failed to reset file offset: %v", err)
160+
}
161+
os.Stdin = tempFile
162+
163+
res := promptForMandatoryInput("", ENTER_VALUE, INPUT_REQUIRED, RECEIVED_INPUT, false, false)
164+
expected := "userInput"
165+
if res != expected {
166+
t.Errorf("Expected %q but got %q", expected, res)
167+
}
168+
}
169+
170+
// TestPromptForMandatoryInputEmptyPrompt tests that if prompting is enabled but the user provides empty input,
171+
// the function logs a fatal error and exits. We use a subprocess to capture os.Exit.
172+
func TestPromptForMandatoryInputEmptyPrompt(t *testing.T) {
173+
// If BE_CRASHER_MANDATORY_EMPTY is set in the environment, this indicates we are in the subprocess.
174+
if os.Getenv("BE_CRASHER_MANDATORY_EMPTY") == "1" {
175+
// Create a temporary file with only a newline to simulate empty input.
176+
tempFile, err := os.CreateTemp("", "stdin")
177+
if err != nil {
178+
os.Exit(2)
179+
}
180+
defer os.Remove(tempFile.Name())
181+
if _, err := tempFile.WriteString("\n"); err != nil {
182+
os.Exit(2)
183+
}
184+
if _, err := tempFile.Seek(0, 0); err != nil {
185+
os.Exit(2)
186+
}
187+
os.Stdin = tempFile
188+
189+
// This call is expected to trigger zap.L().Fatal and exit the process.
190+
_ = promptForMandatoryInput("", ENTER_VALUE, INPUT_REQUIRED, RECEIVED_INPUT, false, false)
191+
// Should not reach here; exit with non-zero code if it does.
192+
os.Exit(3)
193+
}
194+
195+
// Run the subprocess test.
196+
cmd := exec.Command(os.Args[0], "-test.run=TestPromptForMandatoryInputEmptyPrompt")
197+
cmd.Env = append(os.Environ(), "BE_CRASHER_MANDATORY_EMPTY=1")
198+
output, err := cmd.CombinedOutput()
199+
if err == nil {
200+
t.Fatalf("Expected subprocess to exit with fatal error, but it succeeded, output: %q", output)
201+
}
202+
// Optionally, check output contains INPUT_REQUIRED message or similar, if desired.
203+
}
204+
205+
// TestPromptForMandatoryInputPromptDisabled tests that if prompting is disabled and no defaultValue is provided,
206+
// the function logs a fatal error and exits. Again, we use a subprocess.
207+
func TestPromptForMandatoryInputPromptDisabled(t *testing.T) {
208+
if os.Getenv("BE_CRASHER_MANDATORY_DISABLED") == "1" {
209+
// With prompting disabled, the function should log a fatal error immediately.
210+
_ = promptForMandatoryInput("", ENTER_VALUE, INPUT_REQUIRED, RECEIVED_INPUT, true, false)
211+
os.Exit(3)
212+
}
213+
214+
cmd := exec.Command(os.Args[0], "-test.run=TestPromptForMandatoryInputPromptDisabled")
215+
cmd.Env = append(os.Environ(), "BE_CRASHER_MANDATORY_DISABLED=1")
216+
output, err := cmd.CombinedOutput()
217+
if err == nil {
218+
t.Fatalf("Expected subprocess to fail due to prompting disabled, but it succeeded, output: %q", output)
219+
}
220+
// Optionally, further validate that output contains "Prompting is disabled" if needed.
221+
}

0 commit comments

Comments
 (0)