Files
spa-server/compliance_test.go
T

108 lines
2.9 KiB
Go
Raw Permalink Normal View History

package spaserver
import (
"context"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"strings"
"testing"
"code.nochebuena.dev/einherjar/contracts/lifecycle"
"code.nochebuena.dev/einherjar/contracts/logging"
)
// Compile-time interface check (CT-5 / I-8).
var _ lifecycle.Component = (*Server)(nil)
// TestAtMostOneExportedTypePerFile enforces CT-6: at most one exported TypeSpec
// per non-test, non-doc .go file in the root package.
func TestAtMostOneExportedTypePerFile(t *testing.T) {
fset := token.NewFileSet()
pkgs, err := parser.ParseDir(fset, ".", func(fi os.FileInfo) bool {
name := fi.Name()
return !strings.HasSuffix(name, "_test.go") && name != "doc.go"
}, 0)
if err != nil {
t.Fatalf("parse: %v", err)
}
for _, pkg := range pkgs {
for path, file := range pkg.Files {
base := filepath.Base(path)
count := 0
for _, decl := range file.Decls {
gd, ok := decl.(*ast.GenDecl)
if !ok {
continue
}
for _, spec := range gd.Specs {
ts, ok := spec.(*ast.TypeSpec)
if ok && ts.Name.IsExported() {
count++
}
}
}
if count > 1 {
t.Errorf("%s: %d exported TypeSpecs (max 1)", base, count)
}
}
}
}
// TestDefaultConfig_Defaults verifies that DefaultConfig returns non-zero values (S-4).
func TestDefaultConfig_Defaults(t *testing.T) {
cfg := DefaultConfig()
if cfg.Port == 0 {
t.Error("Port must have a non-zero default")
}
if cfg.StaticDir == "" {
t.Error("StaticDir must have a non-empty default")
}
}
// TestDefaultConfig_EnvOverride verifies that environment variables are respected.
func TestDefaultConfig_EnvOverride(t *testing.T) {
t.Setenv("EINHERJAR_SPA_PORT", "9090")
t.Setenv("EINHERJAR_SPA_STATIC_DIR", "/tmp/www")
cfg := DefaultConfig()
if cfg.Port != 9090 {
t.Errorf("Port = %d, want 9090", cfg.Port)
}
if cfg.StaticDir != "/tmp/www" {
t.Errorf("StaticDir = %q, want /tmp/www", cfg.StaticDir)
}
}
// TestServer_Lifecycle verifies that OnInit/OnStart/OnStop complete without error
// on a free port.
func TestServer_Lifecycle(t *testing.T) {
cfg := Config{Port: 0, StaticDir: t.TempDir()}
srv := NewServer(newStubLogger(), cfg)
if err := srv.OnInit(); err != nil {
t.Fatalf("OnInit: %v", err)
}
if err := srv.OnStart(); err != nil {
t.Fatalf("OnStart: %v", err)
}
if err := srv.OnStop(); err != nil {
t.Fatalf("OnStop: %v", err)
}
}
// --- helpers ---
type stubLogger struct{}
func newStubLogger() *stubLogger { return &stubLogger{} }
func (s *stubLogger) Debug(msg string, args ...any) {}
func (s *stubLogger) Info(msg string, args ...any) {}
func (s *stubLogger) Warn(msg string, args ...any) {}
func (s *stubLogger) Error(msg string, err error, args ...any) {}
func (s *stubLogger) With(args ...any) logging.Logger { return s }
func (s *stubLogger) WithContext(ctx context.Context) logging.Logger { return s }