Skip to content
quarry Artifact [f8a2ea3561]
Login

Artifact [f8a2ea3561]

Artifact f8a2ea3561f5c2b929b54a7be103c3189d9a1f42a5716b3ce93cf0f0f039d849:


package harness

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"testing"

	"craftdesign.group/quarry/internal/api"
	"craftdesign.group/quarry/internal/artifact"
	"craftdesign.group/quarry/internal/index"
	"craftdesign.group/quarry/internal/ingest"
	"craftdesign.group/quarry/internal/ops"
	"craftdesign.group/quarry/internal/chat"
	"craftdesign.group/quarry/internal/events"
	"craftdesign.group/quarry/internal/semdiff"
	"craftdesign.group/quarry/internal/web"
	"craftdesign.group/quarry/internal/zitcli"
)

// artifactFoldServe builds the index the PRE-crosslink way — every
// structural artifact, manifests included, through fold() — and serves
// it. The reference implementation the crosslink path must equal.
func artifactFoldServe(t *testing.T, name, store, dataDir string) *httptest.Server {
	t.Helper()
	ix, err := index.Open(filepath.Join(dataDir, name+".db"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { ix.Close() })
	cli := zitcli.New(store)
	var batch []index.Parsed
	if _, err := cli.FramesEachStructural(zitcli.Cursor{}, func(a zitcli.Artifact) error {
		art, perr := artifact.Parse(a.Bytes)
		if perr != nil || art == nil {
			return nil
		}
		batch = append(batch, index.Parsed{Hash: a.Hash, Art: art})
		return nil
	}); err != nil {
		t.Fatal(err)
	}
	ingest.DeriveChanges(cli, batch)
	if err := ix.FoldNow(batch); err != nil {
		t.Fatal(err)
	}
	// The nav shows a Chat tab only where a chat plane runs; the
	// crosslink side has one, so the reference must too, or the two
	// pages differ on something that is not the fold.
	ev, err := events.Start(filepath.Join(dataDir, name+"-nats"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(ev.Close)
	room, err := chat.New(ev.Conn(), ev.JS())
	if err != nil {
		t.Fatal(err)
	}
	deps := api.Deps{Version: "0.0.0-harness", Repos: api.NewRepos(nil), Chat: room}
	zc := cli
	deps.Repos.Put(name, &api.Repo{Index: ix, Zit: cli,
		Sync:   func() (int, error) { return 0, nil },
		Leaves: func() (map[string]bool, error) { return zc.Leaves(context.Background()) }})
	r := ops.NewRegistry()
	if err := api.RegisterAll(r, deps); err != nil {
		t.Fatal(err)
	}
	apiRouter, err := api.Router(r, "0.0.0-harness", nil)
	if err != nil {
		t.Fatal(err)
	}
	m := http.NewServeMux()
	m.Handle("/api/", apiRouter)
	m.Handle("/", web.Handler(r, nil, nil))
	srv := httptest.NewServer(m)
	t.Cleanup(srv.Close)
	return srv
}

// TestCrosslinkMatchesArtifactFold is the parity proof zit#109 demands:
// an index built from `zit crosslink` + non-manifest frames must be
// semantically identical to one built by folding every artifact — on
// pages, APIs, per-entry last-change data, and CHECK-IN search (the
// surface a missing search_doc silently broke once already).
func TestCrosslinkMatchesArtifactFold(t *testing.T) {
	store := buildStore(t, "parityseed")
	repos := map[string]string{"parity": store}

	crosslink := ingestAndServe(t, repos, filepath.Join(t.TempDir(), "a"))
	reference := artifactFoldServe(t, "parity", store, t.TempDir())

	sf := []surface{
		{"/r/parity/timeline", semdiff.HTML},
		{"/api/v1/r/parity/timeline?y=ci", semdiff.JSON},
		{"/r/parity/branch", semdiff.HTML},
		{"/api/v1/r/parity/branch", semdiff.JSON},
		{"/api/v1/r/parity/tree/trunk/", semdiff.JSON},
		{"/api/v1/r/parity/search?q=parityseed&kind=checkin", semdiff.JSON},
		{"/api/v1/r/parity/counts", semdiff.JSON},
	}
	var tl struct {
		Entries []struct{ Hash string } `json:"entries"`
	}
	if err := json.Unmarshal(snapshot(t, reference, "/api/v1/r/parity/timeline?y=ci"), &tl); err != nil {
		t.Fatal(err)
	}
	if len(tl.Entries) == 0 {
		t.Fatal("reference has no check-ins")
	}
	for _, e := range tl.Entries {
		sf = append(sf,
			surface{"/r/parity/checkin/" + e.Hash, semdiff.HTML},
			surface{"/api/v1/r/parity/checkin/" + e.Hash, semdiff.JSON})
	}
	for _, s := range sf {
		a := snapshot(t, crosslink, s.path)
		b := snapshot(t, reference, s.path)
		diff, err := semdiff.Diff(s.kind, a, b)
		if err != nil {
			t.Fatalf("%s: %v", s.path, err)
		}
		if diff != "" {
			t.Errorf("%s diverges:\n%s", s.path, diff)
		}
	}
	// The search surface must also be NON-EMPTY on both sides, or an
	// equal pair of empty answers proves nothing.
	var hits struct {
		Count int `json:"count"`
	}
	if err := json.Unmarshal(snapshot(t, crosslink, "/api/v1/r/parity/search?q=parityseed&kind=checkin"), &hits); err != nil {
		t.Fatal(err)
	}
	if hits.Count == 0 {
		t.Fatal("check-in search found nothing on the crosslink build")
	}
}