diff --git a/agent/internal/config/config_test.go b/agent/internal/config/config_test.go deleted file mode 100644 index 924a85a..0000000 --- a/agent/internal/config/config_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package config - -import ( - "runtime" - "strings" - "testing" -) - -func TestConfigDirByOS(t *testing.T) { - d := ConfigDir() - if runtime.GOOS == "windows" { - if !strings.Contains(strings.ToLower(d), "programdata") { - t.Fatalf("windows config dir = %q, want ProgramData path", d) - } - } else { - if d != "/etc/vantage" { - t.Fatalf("unix config dir = %q, want /etc/vantage", d) - } - } -} diff --git a/server/internal/grpc/pb/vantage_pb_test.go b/server/internal/grpc/pb/vantage_pb_test.go deleted file mode 100644 index 56cc75b..0000000 --- a/server/internal/grpc/pb/vantage_pb_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package pb - -import ( - "encoding/json" - "testing" -) - -func TestProxyClientMsgRoundTrip(t *testing.T) { - in := &ProxyClientMsg{Data: []byte{0x00, 0xff, 0x10}} - raw, err := json.Marshal(in) - if err != nil { - t.Fatalf("marshal: %v", err) - } - var out ProxyClientMsg - if err := json.Unmarshal(raw, &out); err != nil { - t.Fatalf("unmarshal: %v", err) - } - if string(out.Data) != string(in.Data) { - t.Fatalf("data mismatch: got %v want %v", out.Data, in.Data) - } - if out.Open != nil || out.Close != nil { - t.Fatalf("empty oneof fields should stay nil, got open=%v close=%v", out.Open, out.Close) - } -} - -func TestOpenProxyCmdOnServerCommand(t *testing.T) { - cmd := &ServerCommand{CommandId: "c1", OpenProxy: &OpenProxyCmd{ProxyId: "p1", Port: 22}} - raw, err := json.Marshal(cmd) - if err != nil { - t.Fatalf("marshal: %v", err) - } - var out ServerCommand - if err := json.Unmarshal(raw, &out); err != nil { - t.Fatalf("unmarshal: %v", err) - } - if out.OpenProxy == nil || out.OpenProxy.ProxyId != "p1" || out.OpenProxy.Port != 22 { - t.Fatalf("open_proxy did not round-trip: %+v", out.OpenProxy) - } -} diff --git a/shared/mail/render_test.go b/shared/mail/render_test.go deleted file mode 100644 index a1da628..0000000 --- a/shared/mail/render_test.go +++ /dev/null @@ -1,161 +0,0 @@ -package mail - -import ( - "strings" - "testing" - "time" -) - -// Every template is parsed in init(), so a broken one panics the process at -// boot rather than at send time. This test renders each of them with realistic -// data, because parsing does not catch a field that does not exist on the data -// a Send* method actually passes. -func TestRenderAll(t *testing.T) { - expires := time.Date(2026, 8, 14, 9, 0, 0, 0, time.UTC) - - cases := []struct { - name string - data any - subject string - wants []string - }{ - {"verification", struct { - Link string - TTLHours int - }{"https://hq.example/verify?token=abc", 24}, - "Verify your Vantage account", - []string{"https://hq.example/verify?token=abc", "24 hours"}}, - - {"invite", struct{ AccountName, Link string }{ - "Acme & Co", "https://hq.example/accept-invite?token=abc"}, - "You have been invited to Acme & Co on Vantage", - []string{"Acme & Co", "accept-invite"}}, - - {"license", struct{ InstanceName, Blob string }{"acme", "BLOB-123"}, - "Your Vantage licence key", []string{"BLOB-123"}}, - - {"instanceready", struct { - InstanceName, LoginURL string - Expires time.Time - }{"acme", "https://acme.vantage.example", expires}, - "acme is ready", []string{"14 August 2026", "acme.vantage.example"}}, - - {"renewed", struct { - InstanceName string - Expires time.Time - }{"acme", expires}, "acme renewed", []string{"14 August 2026"}}, - - {"expiring", struct { - InstanceName, PortalURL string - Expires time.Time - }{"acme", "https://hq.example/billing", expires}, - "acme expires on 14 August", []string{"hq.example/billing"}}, - - {"expired", struct { - InstanceName, PortalURL string - DeleteOn time.Time - }{"acme", "https://hq.example/billing", expires}, - "acme is now read-only", []string{"read-only", "14 August 2026"}}, - - {"deletionwarning", struct { - InstanceName, PortalURL, When string - DeleteOn time.Time - }{"acme", "https://hq.example/billing", "tomorrow", expires}, - "acme will be deleted tomorrow", []string{"cannot be undone"}}, - - {"linkreminder", struct{ InstanceName, PortalURL string }{ - "acme", "https://hq.example"}, - "Finish setting up acme", []string{"not linked yet"}}, - - {"cancelled", struct{ InstanceName string }{"acme"}, - "Your Vantage subscription is cancelled", []string{"changes are disabled", "cancelled"}}, - - {"pastdue", struct{ InstanceName, PortalURL string }{"acme", "https://hq.example"}, - "Payment failed for your Vantage subscription", []string{"retried"}}, - - {"monitoralert", MonitorEvent{ - MonitorName: "api.example", Type: "http", - OldStatus: "up", NewStatus: "down", - Message: "connection refused", Time: expires, Down: true}, - "[Vantage] api.example (http) is DOWN: connection refused", - []string{"api.example", "connection refused", "2026-08-14"}}, - - {"contact", struct { - Enquiry - Received string - }{Enquiry{Name: "Ada", Email: "ada@example.com", Servers: "10", - Topic: "sales", Message: "hello"}, "now"}, - "[Vantage] sales ada@example.com", []string{"ada@example.com", "hello"}}, - } - - if len(cases) != len(sets) { - t.Fatalf("%d templates on disk but %d covered", len(sets), len(cases)) - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - m, err := render(c.name, c.data) - if err != nil { - t.Fatalf("render: %v", err) - } - if m.Subject != c.subject { - t.Errorf("subject = %q, want %q", m.Subject, c.subject) - } - if !strings.Contains(m.HTML, "Sent by Vantage") { - t.Error("html body is missing the layout footer") - } - if !strings.Contains(m.HTML, "#071628") { - t.Error("html body is not on the control plane ground") - } - if !strings.Contains(m.Text, "VANTAGE") { - t.Error("text body is missing the layout header") - } - if strings.Contains(m.Text, "<") && strings.Contains(m.Text, "style=") { - t.Error("markup leaked into the text part") - } - for _, want := range c.wants { - if !strings.Contains(m.HTML, want) && !strings.Contains(m.Text, want) { - t.Errorf("neither part contains %q", want) - } - } - }) - } -} - -// A header value carrying CRLF must not be able to start a new header. -func TestEnvelopeStripsHeaderInjection(t *testing.T) { - s := Sender{Host: "localhost", Port: "587", From: "vantage@example.com"} - b, err := s.envelope(message{ - To: "someone@example.com\r\nBcc: attacker@example.com", - Subject: "hello", - Text: "body", - HTML: "

body

", - }) - if err != nil { - t.Fatalf("envelope: %v", err) - } - if strings.Contains(string(b), "\r\nBcc:") { - t.Fatal("CRLF in a recipient produced an extra header") - } -} - -// Both parts must be present: a client that refuses HTML should not get a -// blank message, and a text-only message scores worse with spam filters. -func TestEnvelopeIsMultipartAlternative(t *testing.T) { - s := Sender{Host: "localhost", Port: "587", From: "vantage@example.com"} - b, err := s.envelope(message{To: "a@example.com", Subject: "s", Text: "TEXTBODY", HTML: "

HTMLBODY

"}) - if err != nil { - t.Fatalf("envelope: %v", err) - } - got := string(b) - for _, want := range []string{ - "Content-Type: multipart/alternative; boundary=", - "Message-ID: <", "Date: ", - "text/plain; charset=utf-8", "text/html; charset=utf-8", - "TEXTBODY", "HTMLBODY", - } { - if !strings.Contains(got, want) { - t.Errorf("envelope is missing %q", want) - } - } -}