Skip to content
quarry Artifact [02a3cb3752]
Login

Artifact [02a3cb3752]

Artifact 02a3cb3752232c59d210f7899c4a281fb3b5f512efb4755bd2e09e1af0ab67c0:


package oltp

import (
	"path/filepath"
	"testing"
)

func TestRepoAboutRoundTrip(t *testing.T) {
	db := testDB(t)
	if err := db.AddRepo("proj", t.TempDir(), "a project", Public); err != nil {
		t.Fatal(err)
	}
	if err := db.SetRepoHomepage("proj", "https://proj.example"); err != nil {
		t.Fatal(err)
	}
	if err := db.SetRepoTopics("proj", "forge zit go"); err != nil {
		t.Fatal(err)
	}
	r, ok, err := db.RepoByName("proj")
	if err != nil || !ok {
		t.Fatalf("RepoByName: ok=%v err=%v", ok, err)
	}
	if r.Homepage != "https://proj.example" || r.Topics != "forge zit go" {
		t.Fatalf("about not stored: %+v", r)
	}
	rows, err := db.Repos()
	if err != nil || len(rows) != 1 {
		t.Fatalf("Repos: %v %v", rows, err)
	}
	if rows[0].Homepage != "https://proj.example" || rows[0].Topics != "forge zit go" {
		t.Fatalf("Repos misses about: %+v", rows[0])
	}
}

// Chat is on for every repository until a maintainer turns it off, and
// the setting survives a round trip.
func TestRepoChatSetting(t *testing.T) {
	db, err := Open(filepath.Join(t.TempDir(), "o.db"))
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	if err := db.AddRepo("alpha", t.TempDir(), "", "public"); err != nil {
		t.Fatal(err)
	}
	r, ok, _ := db.RepoByName("alpha")
	if !ok || !r.Chat {
		t.Fatalf("a new repository has chat off: %+v ok=%v", r, ok)
	}
	if err := db.SetRepoChat("alpha", false); err != nil {
		t.Fatal(err)
	}
	if r, _, _ = db.RepoByName("alpha"); r.Chat {
		t.Errorf("chat still on after turning it off")
	}
	rows, _ := db.Repos()
	if len(rows) != 1 || rows[0].Chat {
		t.Errorf("the listing disagrees: %+v", rows)
	}
}

// Mirrorable is on for every repository until an admin turns it off,
// the flag survives a round trip through RepoByName and Repos, and the
// column migrates onto a store written before it existed.
func TestRepoMirrorableRoundTrip(t *testing.T) {
	db := testDB(t)
	if err := db.AddRepo("alpha", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	r, ok, err := db.RepoByName("alpha")
	if err != nil || !ok || !r.Mirrorable {
		t.Fatalf("a new repository is not mirrorable by default: %+v ok=%v err=%v", r, ok, err)
	}
	if err := db.SetRepoMirrorable("alpha", false); err != nil {
		t.Fatal(err)
	}
	if r, _, _ = db.RepoByName("alpha"); r.Mirrorable {
		t.Error("still mirrorable after turning it off")
	}
	rows, err := db.Repos()
	if err != nil || len(rows) != 1 || rows[0].Mirrorable {
		t.Errorf("the listing disagrees: %+v (err %v)", rows, err)
	}
}

// The column migrates onto a store that predates it: Open must not
// fail, and a repository written under the old schema reads as
// mirrorable by the column's own default rather than erroring.
func TestMirrorableColumnMigratesOntoAnOlderStore(t *testing.T) {
	path := filepath.Join(t.TempDir(), "oltp.db")
	db, err := Open(path)
	if err != nil {
		t.Fatal(err)
	}
	if err := db.AddRepo("legacy", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	if _, err := db.db.Exec(`ALTER TABLE repo DROP COLUMN mirrorable`); err != nil {
		t.Fatalf("simulating the pre-migration shape: %v", err)
	}
	db.Close()

	db2, err := Open(path)
	if err != nil {
		t.Fatalf("reopening a store that predates mirrorable: %v", err)
	}
	defer db2.Close()
	r, ok, err := db2.RepoByName("legacy")
	if err != nil || !ok || !r.Mirrorable {
		t.Fatalf("migrated repository is not mirrorable by default: %+v ok=%v err=%v", r, ok, err)
	}
}

// MayMirror is the sync gate's own question, and it is NOT the same as
// the stored flag: a private repository is never mirrorable regardless
// of what the flag says, because mirroring is "may other people keep a
// copy", and a private repository already answered no to "may other
// people see this at all". An unknown repository answers no too, the
// same invisible-not-forbidden posture the rest of the forge uses.
func TestMayMirrorRefusesPrivateRegardlessOfTheFlag(t *testing.T) {
	db := testDB(t)
	if err := db.AddRepo("open", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	if err := db.AddRepo("closed", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	if err := db.SetRepoMirrorable("closed", false); err != nil {
		t.Fatal(err)
	}
	if err := db.AddRepo("vault", t.TempDir(), "", Public); err != nil {
		t.Fatal(err)
	}
	// vault flips private AFTER the flag is left on: the veto must come
	// from visibility, not from an admin having remembered to also
	// flip mirrorable.
	if err := db.SetRepoVisibility("vault", Private); err != nil {
		t.Fatal(err)
	}

	cases := []struct {
		repo string
		want bool
	}{
		{"open", true},
		{"closed", false},
		{"vault", false},
		{"nope", false}, // unregistered: not there, not "yes"
	}
	for _, c := range cases {
		got, err := db.MayMirror(c.repo)
		if err != nil {
			t.Fatalf("MayMirror(%q): %v", c.repo, err)
		}
		if got != c.want {
			t.Errorf("MayMirror(%q) = %v, want %v", c.repo, got, c.want)
		}
	}
}