package oltp
import "testing"
func TestARepositoryWithNoAvatarIsNotAnError(t *testing.T) {
d := testDB(t)
got, ok, err := d.RepoAvatarOf("quarry")
if err != nil {
t.Fatalf("FAIL: absence reported as an error: %v", err)
}
if ok {
t.Errorf("FAIL: a repository nobody gave a mark has one: %+v", got)
}
}
func TestAnAvatarIsReplacedRatherThanDuplicated(t *testing.T) {
d := testDB(t)
first := RepoAvatar{Repo: "quarry", Key: "avatars/quarry/aaa", Mime: "image/png",
ETag: "aaa", Bytes: 120, SetBy: "dmestas"}
if err := d.SetRepoAvatar(first); err != nil {
t.Fatal(err)
}
second := RepoAvatar{Repo: "quarry", Key: "avatars/quarry/bbb", Mime: "image/webp",
ETag: "bbb", Bytes: 90, SetBy: "lou"}
if err := d.SetRepoAvatar(second); err != nil {
t.Fatal(err)
}
got, ok, err := d.RepoAvatarOf("quarry")
if err != nil || !ok {
t.Fatalf("FAIL: no avatar after two writes (ok=%v err=%v)", ok, err)
}
if got.Key != second.Key || got.Mime != second.Mime || got.ETag != second.ETag {
t.Errorf("FAIL: the second upload did not replace the first: %+v", got)
}
if got.SetBy != "lou" {
t.Errorf("FAIL: set_by = %q, want the person who replaced it", got.SetBy)
}
// One row, not two: the repository is the key.
var n int
if err := d.db.QueryRow(`SELECT count(*) FROM repo_avatar`).Scan(&n); err != nil {
t.Fatal(err)
}
if n != 1 {
t.Errorf("FAIL: %d rows for one repository", n)
}
}
// The listing reads every validator at once: a page that asked per row
// would issue one query per repository on the forge's front page.
func TestEveryValidatorComesBackInOneRead(t *testing.T) {
d := testDB(t)
for _, r := range []string{"quarry", "zit"} {
if err := d.SetRepoAvatar(RepoAvatar{Repo: r, Key: "avatars/" + r,
Mime: "image/png", ETag: r + "-tag"}); err != nil {
t.Fatal(err)
}
}
tags, err := d.RepoAvatarETags()
if err != nil {
t.Fatal(err)
}
if tags["quarry"] != "quarry-tag" || tags["zit"] != "zit-tag" {
t.Errorf("FAIL: validators = %v", tags)
}
if _, has := tags["orchard"]; has {
t.Errorf("FAIL: a repository with no mark appeared: %v", tags)
}
}
// Clearing forgets the page's decision and leaves the bytes: the split
// RFC 0016 already draws between a removal and a deletion.
func TestClearingForgetsTheRowAndNotTheObject(t *testing.T) {
d := testDB(t)
if err := d.SetRepoAvatar(RepoAvatar{Repo: "quarry", Key: "avatars/quarry",
Mime: "image/png", ETag: "t"}); err != nil {
t.Fatal(err)
}
if err := d.ClearRepoAvatar("quarry"); err != nil {
t.Fatal(err)
}
if _, ok, _ := d.RepoAvatarOf("quarry"); ok {
t.Errorf("FAIL: the mark survived being cleared")
}
}
// A row that could not be served is refused rather than stored.
func TestAnAvatarRowNeedsEnoughToServeIt(t *testing.T) {
d := testDB(t)
for _, bad := range []RepoAvatar{
{Key: "k", Mime: "image/png"},
{Repo: "quarry", Mime: "image/png"},
{Repo: "quarry", Key: "k"},
} {
if err := d.SetRepoAvatar(bad); err == nil {
t.Errorf("FAIL: stored an unservable row: %+v", bad)
}
}
}