diff --git a/cmd/server/main.go b/cmd/server/main.go index dde5b0adc..b86503065 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -189,6 +189,7 @@ func main() { if err := cmd.Run(context.Background(), os.Args); err != nil { fmt.Println(err) + os.Exit(1) } } diff --git a/cmd/server/main_test.go b/cmd/server/main_test.go index dc82bf086..b1c3669dd 100644 --- a/cmd/server/main_test.go +++ b/cmd/server/main_test.go @@ -16,11 +16,80 @@ package main import ( "os" + "os/exec" + "path/filepath" "testing" "github.com/stretchr/testify/require" + + "github.com/livekit/livekit-server/version" ) +func TestMain(m *testing.M) { + if os.Getenv("LIVEKIT_TEST_RUN_MAIN") == "1" { + main() + os.Exit(0) + } + os.Exit(m.Run()) +} + +func TestMainExitCode(t *testing.T) { + testBinary, err := os.Executable() + require.NoError(t, err) + missingConfig := filepath.Join(t.TempDir(), "missing.yaml") + + for _, tt := range []struct { + name string + args []string + exitCode int + output string + }{ + { + name: "missing config", + args: []string{"--config", missingConfig, "ports"}, + exitCode: 1, + output: missingConfig, + }, + { + name: "unknown flag", + args: []string{"--unknown-flag"}, + exitCode: 1, + output: "flag provided but not defined", + }, + { + name: "invalid flag value", + args: []string{"--dev=invalid"}, + exitCode: 1, + output: "invalid value", + }, + { + name: "help", + args: []string{"--help"}, + output: "High performance WebRTC server", + }, + { + name: "version", + args: []string{"--version"}, + output: version.Version, + }, + } { + t.Run(tt.name, func(t *testing.T) { + cmd := exec.CommandContext(t.Context(), testBinary, tt.args...) + // Run the real entry point without inheriting server configuration. + cmd.Env = []string{"LIVEKIT_TEST_RUN_MAIN=1"} + output, err := cmd.CombinedOutput() + if tt.exitCode == 0 { + require.NoError(t, err, string(output)) + } else { + var exitErr *exec.ExitError + require.ErrorAs(t, err, &exitErr, string(output)) + require.Equal(t, tt.exitCode, exitErr.ExitCode(), string(output)) + } + require.Contains(t, string(output), tt.output) + }) + } +} + type testStruct struct { configFileName string configBody string