package config import ( "os" "path/filepath" "strings" "testing" ) func writeFile(t *testing.T, name string, mode os.FileMode, content string) string { t.Helper() path := filepath.Join(t.TempDir(), name) if err := os.WriteFile(path, []byte(content), mode); err != nil { t.Fatal(err) } return path } func TestLoadEnvOnly(t *testing.T) { t.Setenv("MGLPI_URL", "https://cmdb.example/apirest.php/") t.Setenv("MGLPI_APP_TOKEN", "a1") t.Setenv("MGLPI_USER_TOKEN", "u1") cfg, src, err := Load("") if err != nil { t.Fatalf("Load: %v", err) } if cfg.BaseURL != "https://cmdb.example/apirest.php" { t.Errorf("BaseURL = %q, want trailing slash trimmed", cfg.BaseURL) } if cfg.AppToken != "a1" || cfg.UserToken != "u1" { t.Errorf("tokens = %q/%q", cfg.AppToken, cfg.UserToken) } if cfg.ProfileID != 0 { t.Errorf("ProfileID = %d, want 0 when unset", cfg.ProfileID) } if src.Env == "" { t.Errorf("source env = %q, want a key name", src.Env) } } func TestLoadFileOnly(t *testing.T) { path := writeFile(t, "env", 0o600, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=a2\nMGLPI_USER_TOKEN=u2\nMGLPI_PROFILE_ID=5\n") cfg, _, err := Load(path) if err != nil { t.Fatalf("Load: %v", err) } if cfg.BaseURL != "https://cmdb.example/apirest.php" || cfg.AppToken != "a2" || cfg.UserToken != "u2" { t.Errorf("cfg = %+v", cfg) } if cfg.ProfileID != 5 { t.Errorf("ProfileID = %d, want 5", cfg.ProfileID) } } func TestLoadEnvWinsOverFile(t *testing.T) { t.Setenv("MGLPI_USER_TOKEN", "env-user") path := writeFile(t, "env", 0o600, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=fa\nMGLPI_USER_TOKEN=file-user\n") cfg, src, err := Load(path) if err != nil { t.Fatalf("Load: %v", err) } if cfg.UserToken != "env-user" { t.Errorf("UserToken = %q, want env value to win", cfg.UserToken) } if src.File != "" && src.Env != "MGLPI_USER_TOKEN" { t.Errorf("source = %+v", src) } } func TestLoadRejectsLooseFile(t *testing.T) { path := writeFile(t, "env", 0o644, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=a\nMGLPI_USER_TOKEN=u\n") _, _, err := Load(path) if err == nil || !strings.Contains(err.Error(), "insecure mode") { t.Fatalf("err = %v, want insecure-mode rejection", err) } } func TestLoadMissingEverything(t *testing.T) { _, _, err := Load(filepath.Join(t.TempDir(), "absent")) if err == nil || !strings.Contains(err.Error(), "MGLPI_URL") { t.Fatalf("err = %v, want guidance naming MGLPI_URL", err) } } func TestLoadTokenAbsent(t *testing.T) { t.Setenv("MGLPI_URL", "https://cmdb.example/apirest.php") t.Setenv("MGLPI_APP_TOKEN", "a") path := writeFile(t, "env", 0o600, "# nothing useful\n") _, _, err := Load(path) if err == nil || !strings.Contains(err.Error(), "MGLPI_USER_TOKEN") { t.Fatalf("err = %v, want MGLPI_USER_TOKEN named", err) } } func TestLoadMalformedLineReportsNumberOnly(t *testing.T) { path := writeFile(t, "env", 0o600, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=secret-app\nMGLPI_USER_TOKEN=secret-user\nBROKEN LINE HERE\n") _, _, err := Load(path) if err == nil || !strings.Contains(err.Error(), "line 4") { t.Fatalf("err = %v, want line-number-only diagnostic", err) } if err != nil && (strings.Contains(err.Error(), "secret-app") || strings.Contains(err.Error(), "secret-user")) { t.Fatalf("err = %v leaks file contents", err) } } func TestLoadQuotedAndExported(t *testing.T) { path := writeFile(t, "env", 0o600, "export MGLPI_URL=\"https://cmdb.example/apirest.php\"\nexport MGLPI_APP_TOKEN='a3'\nexport MGLPI_USER_TOKEN=u3\n") cfg, _, err := Load(path) if err != nil { t.Fatalf("Load: %v", err) } if cfg.BaseURL != "https://cmdb.example/apirest.php" || cfg.AppToken != "a3" || cfg.UserToken != "u3" { t.Errorf("cfg = %+v, want quotes stripped", cfg) } } func TestProfileIDValidation(t *testing.T) { t.Run("absent is 0", func(t *testing.T) { path := writeFile(t, "env", 0o600, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=a\nMGLPI_USER_TOKEN=u\n") cfg, _, err := Load(path) if err != nil || cfg.ProfileID != 0 { t.Fatalf("cfg = %+v err = %v", cfg, err) } }) t.Run("empty string is 0", func(t *testing.T) { path := writeFile(t, "env", 0o600, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=a\nMGLPI_USER_TOKEN=u\nMGLPI_PROFILE_ID=\n") cfg, _, err := Load(path) if err != nil || cfg.ProfileID != 0 { t.Fatalf("cfg = %+v err = %v", cfg, err) } }) t.Run("garbage is an error that never echoes the value", func(t *testing.T) { path := writeFile(t, "env", 0o600, "MGLPI_URL=https://cmdb.example/apirest.php\nMGLPI_APP_TOKEN=a\nMGLPI_USER_TOKEN=u\nMGLPI_PROFILE_ID=hotliner\n") _, _, err := Load(path) if err == nil || !strings.Contains(err.Error(), "MGLPI_PROFILE_ID") { t.Fatalf("err = %v, want MGLPI_PROFILE_ID named", err) } if strings.Contains(err.Error(), "hotliner") { t.Fatalf("err = %v echoes the value", err) } }) }