128 lines
5.1 KiB
Go
128 lines
5.1 KiB
Go
package app_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"proxyctl/internal/app"
|
|
"proxyctl/internal/profile"
|
|
"proxyctl/internal/target"
|
|
)
|
|
|
|
type fakeTarget struct {
|
|
available bool
|
|
state target.State
|
|
setErr error
|
|
confirmation string
|
|
calls []bool
|
|
}
|
|
|
|
func (f *fakeTarget) ID() string { return "shell" }
|
|
func (f *fakeTarget) Description() target.Description {
|
|
return target.Description{Name: "Shell", Summary: "Shell summary", Details: "Shell details"}
|
|
}
|
|
func (f *fakeTarget) Availability(context.Context) target.Availability {
|
|
return target.Availability{Available: f.available, Evidence: "fake detection"}
|
|
}
|
|
func (f *fakeTarget) Inspect(context.Context, *profile.Profile) target.Inspection {
|
|
return target.Inspection{State: f.state, Evidence: "actual state"}
|
|
}
|
|
func (f *fakeTarget) Confirmation(bool) string { return f.confirmation }
|
|
func (f *fakeTarget) SetDesired(_ context.Context, enabled bool, _ *profile.Profile) target.OperationResult {
|
|
f.calls = append(f.calls, enabled)
|
|
if f.setErr == nil {
|
|
if enabled {
|
|
f.state = target.Enabled
|
|
} else {
|
|
f.state = target.Disabled
|
|
}
|
|
}
|
|
return target.OperationResult{Inspection: target.Inspection{State: f.state, Evidence: "re-inspected actual state"}, Err: f.setErr}
|
|
}
|
|
|
|
func TestApplicationTargetSeamRequiresActiveProfileAndReturnsTruthfulResults(t *testing.T) {
|
|
adapter := &fakeTarget{available: true, state: target.External}
|
|
application, err := app.NewWithTargets(profile.NewFileStore(filepath.Join(t.TempDir(), "profiles.json")), []target.Target{adapter})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result := application.Dispatch(app.Intent{Kind: app.RefreshTargets}); result.Err != nil {
|
|
t.Fatal(result.Err)
|
|
}
|
|
initial := application.Snapshot()
|
|
if len(initial.Targets) != 1 || initial.Targets[0].State != target.External || initial.Targets[0].Description.Summary != "Shell summary" {
|
|
t.Fatalf("initial Target snapshot = %#v", initial.Targets)
|
|
}
|
|
|
|
result := application.Dispatch(app.Intent{Kind: app.SetTargetDesired, TargetID: "shell", Enabled: true})
|
|
if result.Err == nil || !strings.Contains(result.Err.Error(), "Profile management") || len(adapter.calls) != 0 || result.Snapshot.Targets[0].State != target.External {
|
|
t.Fatalf("enable without Active Profile = %#v, calls=%v", result, adapter.calls)
|
|
}
|
|
|
|
createAndActivate(t, application)
|
|
result = application.Dispatch(app.Intent{Kind: app.SetTargetDesired, TargetID: "shell", Enabled: true})
|
|
if result.Err != nil || result.Snapshot.Targets[0].State != target.Enabled || len(adapter.calls) != 1 {
|
|
t.Fatalf("enable result = %#v", result)
|
|
}
|
|
|
|
adapter.setErr = errors.New("permission denied")
|
|
adapter.state = target.Drifted
|
|
result = application.Dispatch(app.Intent{Kind: app.SetTargetDesired, TargetID: "shell", Enabled: false})
|
|
if result.Err == nil || result.Snapshot.Targets[0].State != target.Drifted || result.Snapshot.Targets[0].Evidence != "actual state" {
|
|
t.Fatalf("failed operation not truthful: %#v", result)
|
|
}
|
|
}
|
|
|
|
func TestApplicationRequiresTargetConfirmationBeforeMutation(t *testing.T) {
|
|
adapter := &fakeTarget{available: true, state: target.Disabled, confirmation: "Docker will restart immediately and may disrupt running work."}
|
|
application, err := app.NewWithTargets(profile.NewFileStore(filepath.Join(t.TempDir(), "profiles.json")), []target.Target{targetWithID{fakeTarget: adapter, id: "docker-daemon"}})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
createAndActivate(t, application)
|
|
|
|
warning := application.Dispatch(app.Intent{Kind: app.SetTargetDesired, TargetID: "docker-daemon", Enabled: true})
|
|
if warning.Confirmation == "" || warning.Err != nil || len(adapter.calls) != 0 || warning.Snapshot.Targets[0].State != target.Disabled {
|
|
t.Fatalf("unconfirmed result = %#v, calls=%v", warning, adapter.calls)
|
|
}
|
|
confirmed := application.Dispatch(app.Intent{Kind: app.SetTargetDesired, TargetID: "docker-daemon", Enabled: true, Confirm: true})
|
|
if confirmed.Err != nil || len(adapter.calls) != 1 || confirmed.Snapshot.Targets[0].State != target.Enabled {
|
|
t.Fatalf("confirmed result = %#v, calls=%v", confirmed, adapter.calls)
|
|
}
|
|
}
|
|
|
|
type targetWithID struct {
|
|
*fakeTarget
|
|
id string
|
|
}
|
|
|
|
func (t targetWithID) ID() string { return t.id }
|
|
|
|
func TestApplicationHidesUnavailableTargetButKeepsExplanation(t *testing.T) {
|
|
adapter := &fakeTarget{available: false, state: target.Disabled}
|
|
application, err := app.NewWithTargets(profile.NewFileStore(filepath.Join(t.TempDir(), "profiles.json")), []target.Target{adapter})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result := application.Dispatch(app.Intent{Kind: app.RefreshTargets}); result.Err != nil {
|
|
t.Fatal(result.Err)
|
|
}
|
|
got := application.Snapshot().Targets[0]
|
|
if got.Available || got.AvailabilityEvidence != "fake detection" {
|
|
t.Fatalf("unavailable Target = %#v", got)
|
|
}
|
|
}
|
|
|
|
func createAndActivate(t *testing.T, application *app.Application) {
|
|
t.Helper()
|
|
if result := application.Dispatch(app.Intent{Kind: app.CreateProfile, Profile: profile.Profile{Name: "office", SingleURL: "http://proxy.example:8080"}}); result.Err != nil {
|
|
t.Fatal(result.Err)
|
|
}
|
|
if result := application.Dispatch(app.Intent{Kind: app.ActivateProfile, Name: "office"}); result.Err != nil {
|
|
t.Fatal(result.Err)
|
|
}
|
|
}
|