initial commit
This commit is contained in:
commit
23816d00f7
71 changed files with 14497 additions and 0 deletions
172
backend/scripts/docgen/main_test.go
Normal file
172
backend/scripts/docgen/main_test.go
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go-doc/storage"
|
||||
)
|
||||
|
||||
func TestScanDetectsNewProjectsAndEditsButSettlesWhenIdle(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
writeProject(t, filepath.Join(root, "go-alpha"))
|
||||
|
||||
im := newImporter(options{root: root}, newEngine(t), discardLogger())
|
||||
|
||||
// A project nobody has seen counts as changed.
|
||||
changed := scan(t, im)
|
||||
if want := []string{"go-alpha"}; !equal(changed, want) {
|
||||
t.Fatalf("first scan = %v, want %v", changed, want)
|
||||
}
|
||||
|
||||
// An untouched project must not re-import on every poll.
|
||||
if changed := scan(t, im); len(changed) != 0 {
|
||||
t.Errorf("idle scan reported %v, want no changes", changed)
|
||||
}
|
||||
|
||||
// A project that appears mid-run is picked up.
|
||||
writeProject(t, filepath.Join(root, "go-beta"))
|
||||
if changed := scan(t, im); !equal(changed, []string{"go-beta"}) {
|
||||
t.Errorf("scan after a new project = %v, want [go-beta]", changed)
|
||||
}
|
||||
|
||||
// An edit to an existing project is picked up, once.
|
||||
writeProject(t, filepath.Join(root, "go-alpha"))
|
||||
if changed := scan(t, im); !equal(changed, []string{"go-alpha"}) {
|
||||
t.Errorf("scan after an edit = %v, want [go-alpha]", changed)
|
||||
}
|
||||
if changed := scan(t, im); len(changed) != 0 {
|
||||
t.Errorf("the edit was reported twice: %v", changed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScanForgetsProjectsThatLeaveTheWorkspace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
project := filepath.Join(root, "go-alpha")
|
||||
writeProject(t, project)
|
||||
|
||||
var logs strings.Builder
|
||||
im := newImporter(options{root: root}, newEngine(t),
|
||||
slog.New(slog.NewTextHandler(&logs, &slog.HandlerOptions{Level: slog.LevelDebug})))
|
||||
|
||||
if changed := scan(t, im); len(changed) != 1 {
|
||||
t.Fatalf("first scan = %v, want one project", changed)
|
||||
}
|
||||
logs.Reset()
|
||||
|
||||
if err := os.RemoveAll(project); err != nil {
|
||||
t.Fatalf("remove project: %v", err)
|
||||
}
|
||||
|
||||
if changed := scan(t, im); len(changed) != 0 {
|
||||
t.Errorf("a departed project was treated as changed: %v", changed)
|
||||
}
|
||||
if !strings.Contains(logs.String(), "project left the workspace") {
|
||||
t.Errorf("a departed project was not reported:\n%s", logs.String())
|
||||
}
|
||||
|
||||
// Coming back is a change again rather than a silent no-op.
|
||||
writeProject(t, project)
|
||||
if changed := scan(t, im); !equal(changed, []string{"go-alpha"}) {
|
||||
t.Errorf("scan after the project returned = %v, want [go-alpha]", changed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoverHonoursAppsAndSkip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
root := t.TempDir()
|
||||
for _, name := range []string{"go-alpha", "go-beta", "go-doc", "not-a-go-app"} {
|
||||
writeProject(t, filepath.Join(root, name))
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
opts options
|
||||
want []string
|
||||
}{
|
||||
{name: "default skips go-doc", opts: options{root: root, skip: "go-doc"}, want: []string{"go-alpha", "go-beta"}},
|
||||
{name: "-apps narrows the run", opts: options{root: root, skip: "", apps: "go-beta"}, want: []string{"go-beta"}},
|
||||
{name: "no skip at all", opts: options{root: root}, want: []string{"go-alpha", "go-beta", "go-doc"}},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
im := newImporter(tc.opts, newEngine(t), discardLogger())
|
||||
got, err := im.Discover()
|
||||
if err != nil {
|
||||
t.Fatalf("discover: %v", err)
|
||||
}
|
||||
if strings.Join(got, ",") != strings.Join(tc.want, ",") {
|
||||
t.Errorf("discover = %v, want %v", got, tc.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoverReportsAMissingWorkspace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
im := newImporter(options{root: filepath.Join(t.TempDir(), "absent")}, newEngine(t), discardLogger())
|
||||
if _, err := im.Discover(); err == nil {
|
||||
t.Fatal("a missing workspace should be reported, not silently ignored")
|
||||
}
|
||||
}
|
||||
|
||||
func scan(t *testing.T, im *importer) []string {
|
||||
t.Helper()
|
||||
changed, err := im.Scan()
|
||||
if err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
names := make([]string, 0, len(changed))
|
||||
for name := range changed {
|
||||
names = append(names, name)
|
||||
}
|
||||
sort.Strings(names)
|
||||
return names
|
||||
}
|
||||
|
||||
func equal(got, want []string) bool {
|
||||
return strings.Join(got, ",") == strings.Join(want, ",")
|
||||
}
|
||||
|
||||
func newEngine(t *testing.T) *storage.Engine {
|
||||
t.Helper()
|
||||
engine, err := storage.New(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatalf("provision engine: %v", err)
|
||||
}
|
||||
return engine
|
||||
}
|
||||
|
||||
func discardLogger() *slog.Logger {
|
||||
return slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{Level: slog.LevelDebug}))
|
||||
}
|
||||
|
||||
func writeProject(t *testing.T, root string) {
|
||||
t.Helper()
|
||||
if err := os.MkdirAll(filepath.Join(root, "internal"), 0o755); err != nil {
|
||||
t.Fatalf("mkdir %s: %v", root, err)
|
||||
}
|
||||
files := map[string]string{
|
||||
"go.mod": "module example.com/" + filepath.Base(root) + "\n\ngo 1.27.1\n",
|
||||
"README.md": "# " + filepath.Base(root) + "\n\nIt serves an HTTP API.\n",
|
||||
"internal/app.go": "package internal\n\n// Run starts the app.\nfunc Run() error { return nil }\n",
|
||||
"internal/app_t.go": "placeholder\n",
|
||||
}
|
||||
for name, content := range files {
|
||||
if err := os.WriteFile(filepath.Join(root, filepath.FromSlash(name)), []byte(content), 0o644); err != nil {
|
||||
t.Fatalf("write %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue