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.SetRepoAbout("proj", "https://proj.example", "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)
}
}
}