Skip to content

Commit

Permalink
[main/test] fix tests, reorder main so that it's more testable
Browse files Browse the repository at this point in the history
  • Loading branch information
spezifisch committed Oct 13, 2024
1 parent 162c4a9 commit 73e4452
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 43 deletions.
107 changes: 67 additions & 40 deletions stmps.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,36 @@ import (

var osExit = os.Exit // A variable to allow mocking os.Exit in tests
var headlessMode bool // This can be set to true during tests
var testMode bool // This can be set to true during tests, too

func readConfig() {
func readConfig(configFile *string) error {
required_properties := []string{"auth.username", "auth.password", "server.host"}

viper.SetConfigName("stmp")
viper.SetConfigType("toml")
viper.AddConfigPath("$HOME/.config/stmp")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
if configFile != nil {
// use custom config file
viper.SetConfigFile(*configFile)
} else {
// lookup default dirs
viper.SetConfigName("stmp") // TODO this should be stmps
viper.SetConfigType("toml")
viper.AddConfigPath("$HOME/.config/stmp") // TODO this should be stmps
viper.AddConfigPath(".")
}

// read it
err := viper.ReadInConfig()
if err != nil {
fmt.Printf("Config file error: %s \n", err)
osExit(1)
return fmt.Errorf("Config file error: %s\n", err)
}

// validate
for _, prop := range required_properties {
if !viper.IsSet(prop) {
fmt.Printf("Config property %s is required\n", prop)
return fmt.Errorf("Config property %s is required\n", prop)
}
}

return nil
}

// parseConfig takes the first non-flag arguments from flags and parses it
Expand Down Expand Up @@ -85,11 +95,13 @@ func initCommandHandler(logger *logger.Logger) {
}

func main() {
// parse flags and config
help := flag.Bool("help", false, "Print usage")
enableMpris := flag.Bool("mpris", false, "Enable MPRIS2")
list := flag.Bool("list", false, "list server data")
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to `file`")
memprofile := flag.String("memprofile", "", "write memory profile to `file`")
configFile := flag.String("config", "c", "use config `file`")

flag.Parse()
if *help {
Expand All @@ -111,15 +123,58 @@ func main() {
defer pprof.StopCPUProfile()
}

// config gathering
if len(flag.Args()) > 0 {
parseConfig()
} else {
readConfig()
}

if err := readConfig(configFile); err != nil {
if configFile == nil {
fmt.Fprintf(os.Stderr, "Failed to read configuration: configuration file is nil\n")
} else {
fmt.Fprintf(os.Stderr, "Failed to read configuration from file '%s': %v\n", *configFile, err)
}
osExit(1)
}

logger := logger.Init()
initCommandHandler(logger)

// init mpv engine
player, err := mpvplayer.NewPlayer(logger)
if err != nil {
fmt.Println("Unable to initialize mpv. Is mpv installed?")
osExit(1)
}

var mprisPlayer *remote.MprisPlayer
// init mpris2 player control (linux only but fails gracefully on other systems)
if *enableMpris {
mprisPlayer, err = remote.RegisterMprisPlayer(player, logger)
if err != nil {
fmt.Printf("Unable to register MPRIS with DBUS: %s\n", err)
fmt.Println("Try running without MPRIS")
osExit(1)
}
defer mprisPlayer.Close()
}

// init macos mediaplayer control
if runtime.GOOS == "darwin" {
if err = remote.RegisterMPMediaHandler(player, logger); err != nil {
fmt.Printf("Unable to initialize MediaPlayer bindings: %s\n", err)
osExit(1)
} else {
logger.Print("MacOS MediaPlayer registered")
}
}

if testMode {
fmt.Println("Running in test mode for testing.")
osExit(0)
return
}

connection := subsonic.Init(logger)
connection.SetClientInfo(clientName, clientVersion)
connection.Username = viper.GetString("auth.username")
Expand Down Expand Up @@ -171,37 +226,9 @@ func main() {
osExit(0)
}

// init mpv engine
player, err := mpvplayer.NewPlayer(logger)
if err != nil {
fmt.Println("Unable to initialize mpv. Is mpv installed?")
osExit(1)
}

var mprisPlayer *remote.MprisPlayer
// init mpris2 player control (linux only but fails gracefully on other systems)
if *enableMpris {
mprisPlayer, err = remote.RegisterMprisPlayer(player, logger)
if err != nil {
fmt.Printf("Unable to register MPRIS with DBUS: %s\n", err)
fmt.Println("Try running without MPRIS")
osExit(1)
}
defer mprisPlayer.Close()
}

// init macos mediaplayer control
if runtime.GOOS == "darwin" {
if err = remote.RegisterMPMediaHandler(player, logger); err != nil {
fmt.Printf("Unable to initialize MediaPlayer bindings: %s\n", err)
osExit(1)
} else {
logger.Print("MacOS MediaPlayer registered")
}
}

if headlessMode {
fmt.Println("Running in headless mode for testing.")
osExit(0)
return
}

Expand Down
16 changes: 13 additions & 3 deletions stmps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"os"
"runtime"
"testing"

"github.com/spezifisch/stmps/logger"
Expand All @@ -22,21 +23,30 @@ func TestMainWithoutTUI(t *testing.T) {
exitCalled := false
osExit = func(code int) {
exitCalled = true

if code != 0 {
t.Fatalf("Unexpected exit with code: %d", code)
// Capture and print the stack trace
stackBuf := make([]byte, 1024)
stackSize := runtime.Stack(stackBuf, false)
stackTrace := string(stackBuf[:stackSize])

// Print the stack trace with new lines only
t.Fatalf("Unexpected exit with code: %d\nStack trace:\n%s\n", code, stackTrace)
}
// Since we don't abort execution here, we will run main() until the end or a panic.
}
headlessMode = true
testMode = true

// Restore osExit after the test
// Restore patches after the test
defer func() {
osExit = os.Exit
headlessMode = false
testMode = false
}()

// Set command-line arguments to trigger the help flag
os.Args = []string{"cmd", "--help"}
os.Args = []string{"cmd", "--config=stmp-example.toml", "--help"}

main()

Expand Down

0 comments on commit 73e4452

Please sign in to comment.