iop/apps/node/cmd/node/main_test.go
toki ff161b9b12 feat: runtime reconnect config refresh milestone completion
- Add runtime-reconnect-config-refresh milestone and SDD
- Archive m-runtime-reconnect-config-refresh task with full logs
- Update edge/node domain rules, bootstrap, transport sessions
- Update config package and node.yaml configuration
- Update documentation and ROADMAP/PHASE files
2026-06-21 16:14:16 +09:00

171 lines
4.6 KiB
Go

package main
import (
"bytes"
"path/filepath"
"strings"
"testing"
"iop/packages/go/version"
)
func TestRootCmdIncludesOperationalCommands(t *testing.T) {
root := rootCmd()
want := map[string]bool{
"serve": false,
"version": false,
"config": false,
"setup": false,
}
for _, c := range root.Commands() {
if _, ok := want[c.Name()]; ok {
want[c.Name()] = true
}
}
for name, ok := range want {
if !ok {
t.Errorf("root command missing %q", name)
}
}
cfg, _, err := root.Find([]string{"config"})
if err != nil {
t.Fatalf("find config: %v", err)
}
subs := map[string]bool{"print": false, "check": false}
for _, c := range cfg.Commands() {
if _, ok := subs[c.Name()]; ok {
subs[c.Name()] = true
}
}
for name, ok := range subs {
if !ok {
t.Errorf("config subcommand missing %q", name)
}
}
}
func TestVersionCmdPrintsVersion(t *testing.T) {
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
root.SetArgs([]string{"version"})
if err := root.Execute(); err != nil {
t.Fatalf("execute: %v", err)
}
got := strings.TrimSpace(out.String())
if got != version.Version {
t.Fatalf("version output = %q, want %q", got, version.Version)
}
}
func TestConfigCheckCmdLoadsNodeConfig(t *testing.T) {
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
root.SetArgs([]string{"config", "check", "--config", "../../../../configs/node.yaml"})
if err := root.Execute(); err != nil {
t.Fatalf("execute: %v\n%s", err, out.String())
}
if !strings.Contains(out.String(), "OK") {
t.Fatalf("expected OK in output, got %q", out.String())
}
}
func TestConfigPrintCmdPrintsResolvedConfig(t *testing.T) {
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
root.SetArgs([]string{"config", "print", "--config", "../../../../configs/node.yaml"})
if err := root.Execute(); err != nil {
t.Fatalf("execute: %v\n%s", err, out.String())
}
if out.Len() == 0 {
t.Fatal("expected non-empty YAML output")
}
for _, want := range []string{"reconnect:", "interval_sec: 10", "max_attempts: 10"} {
if !strings.Contains(out.String(), want) {
t.Errorf("config print output missing %q\n---\n%s", want, out.String())
}
}
}
func TestSetupDryRunUsesNodeDefaults(t *testing.T) {
cfgFile = "configs/node.yaml" // reset to root default
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
root.SetArgs([]string{"setup", "--dry-run", "--binary", "/usr/local/bin/iop-node"})
if err := root.Execute(); err != nil {
t.Fatalf("execute: %v\n%s", err, out.String())
}
s := out.String()
for _, want := range []string{
"/etc/iop/node.yaml",
"/var/lib/iop/node",
"/etc/systemd/system/iop-node.service",
"/usr/local/bin/iop-node serve --config /etc/iop/node.yaml",
"--- unit preview ---",
"--- config preview ---",
} {
if !strings.Contains(s, want) {
t.Errorf("dry-run output missing %q\n---\n%s", want, s)
}
}
if strings.Contains(s, "configs/node.yaml") {
t.Errorf("setup default leaked root dev config path: %s", s)
}
}
func TestSetupDryRunAcceptsExplicitConfig(t *testing.T) {
cfgFile = "configs/node.yaml" // reset
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
custom := filepath.Join(t.TempDir(), "node.yaml")
root.SetArgs([]string{"--config", custom, "setup", "--dry-run", "--binary", "/usr/local/bin/iop-node"})
if err := root.Execute(); err != nil {
t.Fatalf("execute: %v\n%s", err, out.String())
}
if !strings.Contains(out.String(), custom) {
t.Errorf("explicit config not used; output:\n%s", out.String())
}
}
func TestSetupDryRunConfigSubcmdPosition(t *testing.T) {
cfgFile = "configs/node.yaml" // reset
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
custom := filepath.Join(t.TempDir(), "node.yaml")
root.SetArgs([]string{"setup", "--config", custom, "--dry-run", "--binary", "/usr/local/bin/iop-node"})
if err := root.Execute(); err != nil {
t.Fatalf("execute: %v\n%s", err, out.String())
}
if !strings.Contains(out.String(), custom) {
t.Errorf("subcommand-position --config not used; output:\n%s", out.String())
}
}
func TestSetupHelpShowsNodeDefault(t *testing.T) {
cfgFile = "configs/node.yaml" // reset
root := rootCmd()
var out bytes.Buffer
root.SetOut(&out)
root.SetErr(&out)
root.SetArgs([]string{"setup", "--help"})
_ = root.Execute()
s := out.String()
if strings.Contains(s, `"configs/node.yaml"`) {
t.Errorf("setup --help must not show dev default configs/node.yaml; output:\n%s", s)
}
if !strings.Contains(s, "/etc/iop/node.yaml") {
t.Errorf("setup --help must show /etc/iop/node.yaml; output:\n%s", s)
}
}