750b7abcd5
- .claude/CLAUDE.md - .claude/agents/fn-recopilador/SKILL.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - bash/functions/infra/build_cpp_windows.sh - cpp/CMakeLists.txt - cpp/PATTERNS.md - cpp/framework/app_base.cpp - cpp/framework/app_base.h - dev/issues/README.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
109 lines
3.1 KiB
Go
109 lines
3.1 KiB
Go
package infra
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSSHConfigWrite_CreatesFileAndDir(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
entries := []SSHConfigEntry{{Alias: "prod", HostName: "10.0.0.1", User: "admin", Port: 22}}
|
|
if err := SSHConfigWrite(entries); err != nil {
|
|
t.Fatalf("write: %v", err)
|
|
}
|
|
configPath := filepath.Join(home, ".ssh", "config")
|
|
data, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
t.Fatalf("read back: %v", err)
|
|
}
|
|
content := string(data)
|
|
if !strings.Contains(content, "Host prod") || !strings.Contains(content, "HostName 10.0.0.1") {
|
|
t.Errorf("unexpected content: %q", content)
|
|
}
|
|
info, err := os.Stat(configPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if perm := info.Mode().Perm(); perm != 0600 {
|
|
t.Errorf("expected 0600, got %o", perm)
|
|
}
|
|
dirInfo, err := os.Stat(filepath.Join(home, ".ssh"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if perm := dirInfo.Mode().Perm(); perm != 0700 {
|
|
t.Errorf("expected dir 0700, got %o", perm)
|
|
}
|
|
}
|
|
|
|
func TestSSHConfigWrite_BackupExisting(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
sshDir := filepath.Join(home, ".ssh")
|
|
if err := os.MkdirAll(sshDir, 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
configPath := filepath.Join(sshDir, "config")
|
|
original := []byte("Host old\n HostName 1.1.1.1\n")
|
|
if err := os.WriteFile(configPath, original, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
entries := []SSHConfigEntry{{Alias: "new", HostName: "2.2.2.2"}}
|
|
if err := SSHConfigWrite(entries); err != nil {
|
|
t.Fatalf("write: %v", err)
|
|
}
|
|
backup, err := os.ReadFile(filepath.Join(sshDir, "config.bak"))
|
|
if err != nil {
|
|
t.Fatalf("backup not found: %v", err)
|
|
}
|
|
if string(backup) != string(original) {
|
|
t.Errorf("backup mismatch: got %q", backup)
|
|
}
|
|
current, err := os.ReadFile(configPath)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(string(current), "Host new") {
|
|
t.Errorf("config not overwritten: %q", current)
|
|
}
|
|
}
|
|
|
|
func TestSSHConfigWrite_NoBackupWhenAbsent(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
if err := SSHConfigWrite([]SSHConfigEntry{{Alias: "a"}}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(home, ".ssh", "config.bak")); !os.IsNotExist(err) {
|
|
t.Errorf("expected no backup when config did not exist, stat err=%v", err)
|
|
}
|
|
}
|
|
|
|
func TestSSHConfigWriteRead_Roundtrip(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
original := []SSHConfigEntry{
|
|
{Alias: "prod", HostName: "10.0.0.1", User: "admin", Port: 22, IdentityFile: "~/.ssh/id_prod"},
|
|
{Alias: "staging", HostName: "10.0.0.2", User: "deploy", Port: 2222},
|
|
}
|
|
if err := SSHConfigWrite(original); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
parsed, err := SSHConfigRead()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(parsed) != len(original) {
|
|
t.Fatalf("expected %d entries, got %d", len(original), len(parsed))
|
|
}
|
|
for i := range original {
|
|
if parsed[i].Alias != original[i].Alias || parsed[i].HostName != original[i].HostName ||
|
|
parsed[i].User != original[i].User || parsed[i].Port != original[i].Port {
|
|
t.Errorf("roundtrip[%d] mismatch: %+v vs %+v", i, parsed[i], original[i])
|
|
}
|
|
}
|
|
}
|