package box import ( "reflect" "testing" "github.com/davis7dotsh/tx9/internal/state") func TestParseExecutorConfig(t *testing.T) { cfg, err := parseExecutorConfig( "https://nexus.example.ts.net/", "127.0.0.1:32770", "100.100.100.100, 192.168.40.1,100.100.100.100", ) if err != nil { t.Fatal(err) } if cfg.WebBaseURL != "https://nexus.example.ts.net" { t.Errorf("WebBaseURL = %q", cfg.WebBaseURL) } if cfg.PublishAddress() != "127.0.0.1:32770" { t.Errorf("PublishAddress() = %q", cfg.PublishAddress()) } wantDNS := []string{"100.100.100.100", "192.168.40.1"} if !reflect.DeepEqual(cfg.DNS, wantDNS) { t.Errorf("DNS = %#v, want %#v", cfg.DNS, wantDNS) }} func TestParseExecutorConfigRejectsInvalidValues(t *testing.T) { cases := []struct { name string webURL string publish string dns string }{ {name: "relative URL", webURL: "nexus.example.ts.net"}, {name: "URL path", webURL: "https://nexus.example.ts.net/executor"}, {name: "URL port", webURL: "https://nexus.example.ts.net:70000"}, {name: "URL trailing colon without port", webURL: "https://nexus.example.ts.net:"}, {name: "URL empty hostname", webURL: "https://:8443"}, {name: "publish hostname", publish: "localhost:32770"}, {name: "publish port", publish: "127.0.0.1:70000"}, {name: "DNS hostname", dns: "magicdns"}, {name: "IPv6 DNS with disabled container IPv6", dns: "fd7a:115c:a1e0::53"}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { if _, err := parseExecutorConfig(tc.webURL, tc.publish, tc.dns); err == nil { t.Fatal("expected an error") } }) }} func TestExecutorConfigPersistsAndEnvironmentOverrides(t *testing.T) { t.Setenv("HOME", t.TempDir()) name := "media-bot" stored := ExecutorConfig{ WebBaseURL: "https://old.example.ts.net", PublishIP: "127.0.0.1", PublishPort: "32770", DNS: []string{"100.100.100.100", "192.168.40.1"}, } if err := SaveExecutorConfig(name, "secret-token", stored); err != nil { t.Fatal(err) } t.Setenv(ExecutorWebBaseURLEnv, "https://new.example.ts.net") cfg, err := LoadExecutorConfig(name, ExecutorConfigOverrides{}) if err != nil { t.Fatal(err) } if cfg.WebBaseURL != "https://new.example.ts.net" { t.Errorf("WebBaseURL = %q", cfg.WebBaseURL) } if cfg.PublishAddress() != stored.PublishAddress() { t.Errorf("PublishAddress() = %q", cfg.PublishAddress()) } env, err := state.ReadBoxEnv(name) if err != nil { t.Fatal(err) } if env["EXECUTOR_MCP_TOKEN"] != "secret-token" { t.Error("executor token was not preserved") } if env[ExecutorPublishEnv] != "127.0.0.1:32770" { t.Errorf("stored publish address = %q", env[ExecutorPublishEnv]) } if env[ExecutorDNSEnv] != "100.100.100.100,192.168.40.1" { t.Errorf("stored DNS = %q", env[ExecutorDNSEnv]) } cfg, err = LoadExecutorConfig(name, ExecutorConfigOverrides{ WebBaseURL: "https://cli.example.ts.net", }) if err != nil { t.Fatal(err) } if cfg.WebBaseURL != "https://cli.example.ts.net" { t.Errorf("CLI WebBaseURL = %q", cfg.WebBaseURL) } cfg, err = LoadExecutorConfig(name, ExecutorConfigOverrides{Clear: true}) if err != nil { t.Fatal(err) } if cfg.WebBaseURL != "" || cfg.PublishAddress() != "" || len(cfg.DNS) != 0 { t.Errorf("cleared config = %#v", cfg) } // Saving the cleared config must delete the persisted keys on disk, not // just return zero values. if err := SaveExecutorConfig(name, "secret-token", cfg); err != nil { t.Fatal(err) } env, err = state.ReadBoxEnv(name) if err != nil { t.Fatal(err) } for _, key := range []string{ExecutorWebBaseURLEnv, ExecutorPublishEnv, ExecutorDNSEnv} { if _, ok := env[key]; ok { t.Errorf("cleared key %s still persisted", key) } } if env["EXECUTOR_MCP_TOKEN"] != "secret-token" { t.Error("executor token was not preserved through clear") }} func TestLoadExecutorConfigIgnoreStored(t *testing.T) { t.Setenv("HOME", t.TempDir()) name := "media-bot" stored := ExecutorConfig{ WebBaseURL: "https://stale.example.ts.net", PublishIP: "127.0.0.1", PublishPort: "32770", } if err := SaveExecutorConfig(name, "stale-token", stored); err != nil { t.Fatal(err) } cfg, err := LoadExecutorConfig(name, ExecutorConfigOverrides{IgnoreStored: true}) if err != nil { t.Fatal(err) } if cfg.WebBaseURL != "" || cfg.PublishAddress() != "" || len(cfg.DNS) != 0 { t.Errorf("IgnoreStored inherited persisted values: %#v", cfg) } // Explicit flags still win with IgnoreStored set. cfg, err = LoadExecutorConfig(name, ExecutorConfigOverrides{ WebBaseURL: "https://fresh.example.ts.net", IgnoreStored: true, }) if err != nil { t.Fatal(err) } if cfg.WebBaseURL != "https://fresh.example.ts.net" { t.Errorf("WebBaseURL = %q", cfg.WebBaseURL) }}
package box
import (
"reflect"
"testing"
"github.com/davis7dotsh/tx9/internal/state"
)
func TestParseExecutorConfig(t *testing.T) {
cfg, err := parseExecutorConfig(
"https://nexus.example.ts.net/",
"127.0.0.1:32770",
"100.100.100.100, 192.168.40.1,100.100.100.100",
)
if err != nil {
t.Fatal(err)
}
if cfg.WebBaseURL != "https://nexus.example.ts.net" {
t.Errorf("WebBaseURL = %q", cfg.WebBaseURL)
}
if cfg.PublishAddress() != "127.0.0.1:32770" {
t.Errorf("PublishAddress() = %q", cfg.PublishAddress())
}
wantDNS := []string{"100.100.100.100", "192.168.40.1"}
if !reflect.DeepEqual(cfg.DNS, wantDNS) {
t.Errorf("DNS = %#v, want %#v", cfg.DNS, wantDNS)
}
}
func TestParseExecutorConfigRejectsInvalidValues(t *testing.T) {
cases := []struct {
name string
webURL string
publish string
dns string
}{
{name: "relative URL", webURL: "nexus.example.ts.net"},
{name: "URL path", webURL: "https://nexus.example.ts.net/executor"},
{name: "URL port", webURL: "https://nexus.example.ts.net:70000"},
{name: "URL trailing colon without port", webURL: "https://nexus.example.ts.net:"},
{name: "URL empty hostname", webURL: "https://:8443"},
{name: "publish hostname", publish: "localhost:32770"},
{name: "publish port", publish: "127.0.0.1:70000"},
{name: "DNS hostname", dns: "magicdns"},
{name: "IPv6 DNS with disabled container IPv6", dns: "fd7a:115c:a1e0::53"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if _, err := parseExecutorConfig(tc.webURL, tc.publish, tc.dns); err == nil {
t.Fatal("expected an error")
}
})
}
}
func TestExecutorConfigPersistsAndEnvironmentOverrides(t *testing.T) {
t.Setenv("HOME", t.TempDir())
name := "media-bot"
stored := ExecutorConfig{
WebBaseURL: "https://old.example.ts.net",
PublishIP: "127.0.0.1",
PublishPort: "32770",
DNS: []string{"100.100.100.100", "192.168.40.1"},
}
if err := SaveExecutorConfig(name, "secret-token", stored); err != nil {
t.Fatal(err)
}
t.Setenv(ExecutorWebBaseURLEnv, "https://new.example.ts.net")
cfg, err := LoadExecutorConfig(name, ExecutorConfigOverrides{})
if err != nil {
t.Fatal(err)
}
if cfg.WebBaseURL != "https://new.example.ts.net" {
t.Errorf("WebBaseURL = %q", cfg.WebBaseURL)
}
if cfg.PublishAddress() != stored.PublishAddress() {
t.Errorf("PublishAddress() = %q", cfg.PublishAddress())
}
env, err := state.ReadBoxEnv(name)
if err != nil {
t.Fatal(err)
}
if env["EXECUTOR_MCP_TOKEN"] != "secret-token" {
t.Error("executor token was not preserved")
}
if env[ExecutorPublishEnv] != "127.0.0.1:32770" {
t.Errorf("stored publish address = %q", env[ExecutorPublishEnv])
}
if env[ExecutorDNSEnv] != "100.100.100.100,192.168.40.1" {
t.Errorf("stored DNS = %q", env[ExecutorDNSEnv])
}
cfg, err = LoadExecutorConfig(name, ExecutorConfigOverrides{
WebBaseURL: "https://cli.example.ts.net",
})
if err != nil {
t.Fatal(err)
}
if cfg.WebBaseURL != "https://cli.example.ts.net" {
t.Errorf("CLI WebBaseURL = %q", cfg.WebBaseURL)
}
cfg, err = LoadExecutorConfig(name, ExecutorConfigOverrides{Clear: true})
if err != nil {
t.Fatal(err)
}
if cfg.WebBaseURL != "" || cfg.PublishAddress() != "" || len(cfg.DNS) != 0 {
t.Errorf("cleared config = %#v", cfg)
}
// Saving the cleared config must delete the persisted keys on disk, not
// just return zero values.
if err := SaveExecutorConfig(name, "secret-token", cfg); err != nil {
t.Fatal(err)
}
env, err = state.ReadBoxEnv(name)
if err != nil {
t.Fatal(err)
}
for _, key := range []string{ExecutorWebBaseURLEnv, ExecutorPublishEnv, ExecutorDNSEnv} {
if _, ok := env[key]; ok {
t.Errorf("cleared key %s still persisted", key)
}
}
if env["EXECUTOR_MCP_TOKEN"] != "secret-token" {
t.Error("executor token was not preserved through clear")
}
}
func TestLoadExecutorConfigIgnoreStored(t *testing.T) {
t.Setenv("HOME", t.TempDir())
name := "media-bot"
stored := ExecutorConfig{
WebBaseURL: "https://stale.example.ts.net",
PublishIP: "127.0.0.1",
PublishPort: "32770",
}
if err := SaveExecutorConfig(name, "stale-token", stored); err != nil {
t.Fatal(err)
}
cfg, err := LoadExecutorConfig(name, ExecutorConfigOverrides{IgnoreStored: true})
if err != nil {
t.Fatal(err)
}
if cfg.WebBaseURL != "" || cfg.PublishAddress() != "" || len(cfg.DNS) != 0 {
t.Errorf("IgnoreStored inherited persisted values: %#v", cfg)
}
// Explicit flags still win with IgnoreStored set.
cfg, err = LoadExecutorConfig(name, ExecutorConfigOverrides{
WebBaseURL: "https://fresh.example.ts.net",
IgnoreStored: true,
})
if err != nil {
t.Fatal(err)
}
if cfg.WebBaseURL != "https://fresh.example.ts.net" {
t.Errorf("WebBaseURL = %q", cfg.WebBaseURL)
}
}