272 lines
6.6 KiB
Go
272 lines
6.6 KiB
Go
package config
|
|
|
|
import (
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLoadUsesSafeDefaults(t *testing.T) {
|
|
cfg, err := Load(emptyEnvironment)
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
|
|
if cfg.HTTPAddress != "127.0.0.1:8080" {
|
|
t.Fatalf("HTTPAddress = %q", cfg.HTTPAddress)
|
|
}
|
|
if cfg.DatabasePath != filepath.FromSlash("var/cmroubao.db") {
|
|
t.Fatalf("DatabasePath = %q", cfg.DatabasePath)
|
|
}
|
|
if cfg.AssetDirectory != filepath.FromSlash("var/assets") {
|
|
t.Fatalf("AssetDirectory = %q", cfg.AssetDirectory)
|
|
}
|
|
if cfg.ReadHeaderTimeout <= 0 ||
|
|
cfg.ReadTimeout <= 0 ||
|
|
cfg.WriteTimeout <= 0 ||
|
|
cfg.IdleTimeout <= 0 ||
|
|
cfg.ShutdownTimeout <= 0 ||
|
|
cfg.MaxHeaderBytes <= 0 {
|
|
t.Fatal("server safety limits must all be positive")
|
|
}
|
|
if cfg.ClaimLease != 10*time.Minute ||
|
|
cfg.RunningLease != 30*time.Minute ||
|
|
cfg.ReadinessTTL != 2*time.Minute {
|
|
t.Fatalf(
|
|
"lifecycle durations = %s / %s / %s",
|
|
cfg.ClaimLease,
|
|
cfg.RunningLease,
|
|
cfg.ReadinessTTL,
|
|
)
|
|
}
|
|
if cfg.ShutdownTimeout > 30*time.Second {
|
|
t.Fatalf("ShutdownTimeout = %s", cfg.ShutdownTimeout)
|
|
}
|
|
if cfg.ShunyunbaoURL != "https://www.shunyunbaoerp.com" ||
|
|
cfg.ShunyunbaoUsername != "" || cfg.ShunyunbaoPassword != "" ||
|
|
cfg.ShunyunbaoTimeout != 30*time.Second {
|
|
t.Fatalf(
|
|
"shunyunbao defaults = %q / %q / %q / %s",
|
|
cfg.ShunyunbaoURL,
|
|
cfg.ShunyunbaoUsername,
|
|
cfg.ShunyunbaoPassword,
|
|
cfg.ShunyunbaoTimeout,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestLoadAcceptsExplicitConfiguration(t *testing.T) {
|
|
values := map[string]string{
|
|
HTTPAddressEnvironment: "192.0.2.10:9090",
|
|
DatabasePathEnvironment: "tmp/test.db",
|
|
AssetDirectoryEnvironment: "tmp/assets",
|
|
TLSCertificateEnvironment: "tmp/server.crt",
|
|
TLSPrivateKeyEnvironment: "tmp/server.key",
|
|
ClaimLeaseEnvironment: "15m",
|
|
RunningLeaseEnvironment: "45m",
|
|
ReadinessTTLEnvironment: "3m",
|
|
ShunyunbaoURLEnvironment: "https://erp.example.test:8443",
|
|
ShunyunbaoUsernameEnvironment: "service-user",
|
|
ShunyunbaoPasswordEnvironment: " pass with spaces ",
|
|
}
|
|
|
|
cfg, err := Load(mapEnvironment(values))
|
|
if err != nil {
|
|
t.Fatalf("Load() error = %v", err)
|
|
}
|
|
|
|
if cfg.HTTPAddress != values[HTTPAddressEnvironment] {
|
|
t.Fatalf("HTTPAddress = %q", cfg.HTTPAddress)
|
|
}
|
|
if cfg.DatabasePath != filepath.Clean(values[DatabasePathEnvironment]) {
|
|
t.Fatalf("DatabasePath = %q", cfg.DatabasePath)
|
|
}
|
|
if cfg.AssetDirectory != filepath.Clean(values[AssetDirectoryEnvironment]) {
|
|
t.Fatalf("AssetDirectory = %q", cfg.AssetDirectory)
|
|
}
|
|
if cfg.TLSCertificate != filepath.Clean(values[TLSCertificateEnvironment]) ||
|
|
cfg.TLSPrivateKey != filepath.Clean(values[TLSPrivateKeyEnvironment]) {
|
|
t.Fatalf(
|
|
"TLS files = %q / %q",
|
|
cfg.TLSCertificate,
|
|
cfg.TLSPrivateKey,
|
|
)
|
|
}
|
|
if cfg.ClaimLease != 15*time.Minute ||
|
|
cfg.RunningLease != 45*time.Minute ||
|
|
cfg.ReadinessTTL != 3*time.Minute {
|
|
t.Fatalf(
|
|
"lifecycle durations = %s / %s / %s",
|
|
cfg.ClaimLease,
|
|
cfg.RunningLease,
|
|
cfg.ReadinessTTL,
|
|
)
|
|
}
|
|
if cfg.ShunyunbaoURL != values[ShunyunbaoURLEnvironment] ||
|
|
cfg.ShunyunbaoUsername != values[ShunyunbaoUsernameEnvironment] ||
|
|
cfg.ShunyunbaoPassword != values[ShunyunbaoPasswordEnvironment] {
|
|
t.Fatalf("shunyunbao config was not preserved")
|
|
}
|
|
}
|
|
|
|
func TestLoadRejectsUnsafeOrInvalidValues(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
values map[string]string
|
|
}{
|
|
{
|
|
name: "non HTTPS shunyunbao URL",
|
|
values: map[string]string{
|
|
ShunyunbaoURLEnvironment: "http://erp.example.test",
|
|
},
|
|
},
|
|
{
|
|
name: "shunyunbao URL path",
|
|
values: map[string]string{
|
|
ShunyunbaoURLEnvironment: "https://erp.example.test/private",
|
|
},
|
|
},
|
|
{
|
|
name: "shunyunbao username without password",
|
|
values: map[string]string{
|
|
ShunyunbaoUsernameEnvironment: "service-user",
|
|
},
|
|
},
|
|
{
|
|
name: "shunyunbao password without username",
|
|
values: map[string]string{
|
|
ShunyunbaoPasswordEnvironment: "password",
|
|
},
|
|
},
|
|
{
|
|
name: "blank explicit address",
|
|
values: map[string]string{
|
|
HTTPAddressEnvironment: " ",
|
|
},
|
|
},
|
|
{
|
|
name: "address without host",
|
|
values: map[string]string{
|
|
HTTPAddressEnvironment: ":8080",
|
|
},
|
|
},
|
|
{
|
|
name: "invalid port",
|
|
values: map[string]string{
|
|
HTTPAddressEnvironment: "127.0.0.1:70000",
|
|
},
|
|
},
|
|
{
|
|
name: "memory database",
|
|
values: map[string]string{
|
|
DatabasePathEnvironment: ":memory:",
|
|
},
|
|
},
|
|
{
|
|
name: "database DSN",
|
|
values: map[string]string{
|
|
DatabasePathEnvironment: "file:test.db?mode=memory",
|
|
},
|
|
},
|
|
{
|
|
name: "database directory",
|
|
values: map[string]string{
|
|
DatabasePathEnvironment: "./",
|
|
},
|
|
},
|
|
{
|
|
name: "non SQLite extension",
|
|
values: map[string]string{
|
|
DatabasePathEnvironment: "var/database.txt",
|
|
},
|
|
},
|
|
{
|
|
name: "asset root directory",
|
|
values: map[string]string{
|
|
AssetDirectoryEnvironment: string(filepath.Separator),
|
|
},
|
|
},
|
|
{
|
|
name: "asset current directory",
|
|
values: map[string]string{
|
|
AssetDirectoryEnvironment: ".",
|
|
},
|
|
},
|
|
{
|
|
name: "non loopback without TLS",
|
|
values: map[string]string{
|
|
HTTPAddressEnvironment: "0.0.0.0:8080",
|
|
},
|
|
},
|
|
{
|
|
name: "TLS certificate without key",
|
|
values: map[string]string{
|
|
TLSCertificateEnvironment: "tmp/server.crt",
|
|
},
|
|
},
|
|
{
|
|
name: "blank TLS key",
|
|
values: map[string]string{
|
|
TLSCertificateEnvironment: "tmp/server.crt",
|
|
TLSPrivateKeyEnvironment: " ",
|
|
},
|
|
},
|
|
{
|
|
name: "claim lease below minimum",
|
|
values: map[string]string{
|
|
ClaimLeaseEnvironment: "59s",
|
|
},
|
|
},
|
|
{
|
|
name: "running lease below minimum",
|
|
values: map[string]string{
|
|
RunningLeaseEnvironment: "4m59s",
|
|
},
|
|
},
|
|
{
|
|
name: "running lease above maximum",
|
|
values: map[string]string{
|
|
RunningLeaseEnvironment: "121m",
|
|
},
|
|
},
|
|
{
|
|
name: "invalid readiness TTL",
|
|
values: map[string]string{
|
|
ReadinessTTLEnvironment: "soon",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
if _, err := Load(mapEnvironment(test.values)); err == nil {
|
|
t.Fatal("Load() error = nil")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestLoadDatabasePathIgnoresHTTPConfiguration(t *testing.T) {
|
|
path, err := LoadDatabasePath(mapEnvironment(map[string]string{
|
|
HTTPAddressEnvironment: "invalid",
|
|
DatabasePathEnvironment: "tmp/migration.sqlite",
|
|
}))
|
|
if err != nil {
|
|
t.Fatalf("LoadDatabasePath() error = %v", err)
|
|
}
|
|
if path != filepath.Clean("tmp/migration.sqlite") {
|
|
t.Fatalf("path = %q", path)
|
|
}
|
|
}
|
|
|
|
func emptyEnvironment(string) (string, bool) {
|
|
return "", false
|
|
}
|
|
|
|
func mapEnvironment(values map[string]string) LookupEnvironment {
|
|
return func(name string) (string, bool) {
|
|
value, exists := values[name]
|
|
return value, exists
|
|
}
|
|
}
|