Introduce a commercial license option alongside AGPL-3.0-only, require a CLA for contributors, and document the terms in COMMERCIAL.md and NOTICE. Add a script to stamp SPDX headers on Go files and apply it across the tree.
97 lines
3.8 KiB
Go
97 lines
3.8 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
package config
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
// TestDeploymentNameDefaultsWhenUnset covers the fallback DeploymentName
|
|
// gives every caller (including render tests that never run cmd/start.go's
|
|
// viper.SetDefault): unset resolves to the generic product name, not an
|
|
// empty string.
|
|
func TestDeploymentNameDefaultsWhenUnset(t *testing.T) {
|
|
viper.Reset()
|
|
if got := DeploymentName(); got != DefaultDeploymentName {
|
|
t.Errorf("DeploymentName() with nothing configured = %q, want %q", got, DefaultDeploymentName)
|
|
}
|
|
}
|
|
|
|
// TestDeploymentNameTrimsAndPrefersConfigured covers the configured-value
|
|
// path (deployment-identity scenario: "Configured name appears identically
|
|
// on both surfaces") and that surrounding whitespace from an operator's env
|
|
// value doesn't leak into the rendered name.
|
|
func TestDeploymentNameTrimsAndPrefersConfigured(t *testing.T) {
|
|
viper.Reset()
|
|
viper.Set("deployment-name", " Solidarity Web Collective ")
|
|
if got, want := DeploymentName(), "Solidarity Web Collective"; got != want {
|
|
t.Errorf("DeploymentName() = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
// TestDeploymentNameWhitespaceOnlyFallsBack: an explicitly blank override
|
|
// still resolves to a safe, non-blank name at read time — ValidateStart is
|
|
// the boot-time gate that refuses this configuration outright (see
|
|
// TestValidateStart_Errors's "blank deployment-name" case); this is defense
|
|
// in depth for any caller that runs before or without validation.
|
|
func TestDeploymentNameWhitespaceOnlyFallsBack(t *testing.T) {
|
|
viper.Reset()
|
|
viper.Set("deployment-name", " ")
|
|
if got := DeploymentName(); got != DefaultDeploymentName {
|
|
t.Errorf("DeploymentName() with whitespace-only override = %q, want %q", got, DefaultDeploymentName)
|
|
}
|
|
}
|
|
|
|
// requiredGroupSpecs mirrors a two-key required-together group the way
|
|
// Stripe/FedWiki/Discourse declare theirs (RequiredGroup ties the pair;
|
|
// ValidateStart's validateRequiredGroups rejects a half-set group at boot,
|
|
// so by the time RequiredKeysUnresolved runs the group is always all-set or
|
|
// all-unset — but the function reports every unresolved member, not just
|
|
// one, so a caller can name what's missing even from an invalid in-flight
|
|
// state).
|
|
var requiredGroupSpecs = []ConfigKey{
|
|
{Name: "acme-url", Type: TypeURL, RequiredGroup: "Acme"},
|
|
{Name: "acme-token", Secret: true, RequiredGroup: "Acme"},
|
|
{Name: "acme-region", Default: "us", Usage: "not required"},
|
|
}
|
|
|
|
func TestRequiredKeysUnresolved(t *testing.T) {
|
|
t.Run("nothing set reports every required key", func(t *testing.T) {
|
|
viper.Reset()
|
|
got := RequiredKeysUnresolved(requiredGroupSpecs)
|
|
want := []string{"acme-url", "acme-token"}
|
|
if len(got) != len(want) || got[0] != want[0] || got[1] != want[1] {
|
|
t.Errorf("RequiredKeysUnresolved = %v, want %v", got, want)
|
|
}
|
|
})
|
|
|
|
t.Run("fully configured reports nothing", func(t *testing.T) {
|
|
viper.Reset()
|
|
viper.Set("acme-url", "https://acme.example.com")
|
|
viper.Set("acme-token", "sekret")
|
|
if got := RequiredKeysUnresolved(requiredGroupSpecs); len(got) != 0 {
|
|
t.Errorf("RequiredKeysUnresolved = %v, want none missing", got)
|
|
}
|
|
})
|
|
|
|
t.Run("a key with no RequiredGroup is never reported", func(t *testing.T) {
|
|
viper.Reset()
|
|
if got := RequiredKeysUnresolved([]ConfigKey{{Name: "acme-region", Default: "us"}}); len(got) != 0 {
|
|
t.Errorf("RequiredKeysUnresolved = %v, want none (no RequiredGroup)", got)
|
|
}
|
|
})
|
|
|
|
t.Run("whitespace-only value counts as unresolved", func(t *testing.T) {
|
|
viper.Reset()
|
|
viper.Set("acme-url", " ")
|
|
viper.Set("acme-token", "sekret")
|
|
got := RequiredKeysUnresolved(requiredGroupSpecs)
|
|
if len(got) != 1 || got[0] != "acme-url" {
|
|
t.Errorf("RequiredKeysUnresolved = %v, want [acme-url]", got)
|
|
}
|
|
})
|
|
}
|