Files
PilotVault/API Server/internal/plugins/builtin/filetransfer/filetransfer_test.go
T
tajniak81andClaude Opus 4.8 afc6952eda Initial commit: PilotVault multi-service project
Add API Server (Go/PocketBase), Web App (Go BFF + Vue), Fly App
(Flutter/DJI MSDK), Adobe Plugin, and Docker/Docker AIO deployment
configs. Design assets and build artifacts are gitignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 11:43:33 +02:00

98 lines
2.6 KiB
Go

package filetransfer
import (
"context"
"testing"
"pilotvault/apiserver/internal/plugins"
)
func TestDescriptor(t *testing.T) {
p := &Plugin{}
d := p.Descriptor()
if d.Name != "filetransfer" {
t.Fatalf("name = %q, want filetransfer", d.Name)
}
if d.Kind != plugins.KindBuiltin {
t.Fatalf("kind = %q, want builtin", d.Kind)
}
if len(d.Capabilities) == 0 {
t.Fatal("expected capabilities")
}
// Every secret field must be flagged so the manager masks it.
for _, f := range d.ConfigFields {
if f.Key == "password" || f.Key == "privateKey" || f.Key == "keyPassphrase" {
if !f.Secret {
t.Errorf("config field %q must be Secret", f.Key)
}
}
}
}
func TestInitDefaults(t *testing.T) {
p := &Plugin{}
if err := p.Init(context.Background(), map[string]string{"host": "h", "username": "u"}); err != nil {
t.Fatal(err)
}
if p.protocol != protoSFTP {
t.Errorf("default protocol = %q, want sftp", p.protocol)
}
if p.effectivePort() != 22 {
t.Errorf("default sftp port = %d, want 22", p.effectivePort())
}
p.protocol = protoFTP
if p.effectivePort() != 21 {
t.Errorf("default ftp port = %d, want 21", p.effectivePort())
}
}
func TestResolve(t *testing.T) {
p := &Plugin{basePath: "/uploads"}
cases := map[string]string{
"": "/uploads",
"a/b.txt": "/uploads/a/b.txt",
"/etc/abs": "/etc/abs",
}
for in, want := range cases {
if got := p.resolve(in); got != want {
t.Errorf("resolve(%q) = %q, want %q", in, got, want)
}
}
}
// TestHealthCheckUnreachable confirms an unreachable host is classified as down
// (not a panic) — the graceful-failure path Init/HealthCheck must guarantee.
func TestHealthCheckUnreachable(t *testing.T) {
p := &Plugin{}
// Port 1 is reserved and refuses connections quickly.
if err := p.Init(context.Background(), map[string]string{
"protocol": protoSFTP, "host": "127.0.0.1", "port": "1",
"username": "u", "password": "pw",
}); err != nil {
t.Fatal(err)
}
h := p.HealthCheck(context.Background())
if h.Status != plugins.StatusDown {
t.Errorf("status = %q, want down (detail=%q)", h.Status, h.Detail)
}
}
func TestHostKeyFingerprintMismatch(t *testing.T) {
cb, err := hostKeyChecker("SHA256:doesnotmatch")
if err != nil {
t.Fatal(err)
}
if cb == nil {
t.Fatal("expected a callback")
}
}
// TestRegistered confirms the plugin registered itself with the shared registry
// via init(), so the manager will surface it.
func TestRegistered(t *testing.T) {
m := plugins.NewManager(t.TempDir() + "/plugins.json")
if _, ok := m.Get("filetransfer"); !ok {
t.Fatal("filetransfer not registered in the plugin manager")
}
}