package oltp
import "testing"
func TestARepositoryWithNoAvatarIsNotAnError(t *testing.T) {
d := testDB(t)
got, ok, err := d.AvatarOf(AvatarRepo, "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 := Avatar{Kind: AvatarRepo, Name: "quarry", Key: "avatars/quarry/aaa", Mime: "image/png",
ETag: "aaa", Bytes: 120, SetBy: "dmestas"}
if err := d.SetAvatar(first); err != nil {
t.Fatal(err)
}
second := Avatar{Kind: AvatarRepo, Name: "quarry", Key: "avatars/quarry/bbb", Mime: "image/webp",
ETag: "bbb", Bytes: 90, SetBy: "lou"}
if err := d.SetAvatar(second); err != nil {
t.Fatal(err)
}
got, ok, err := d.AvatarOf(AvatarRepo, "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 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.SetAvatar(Avatar{Kind: AvatarRepo, Name: r, Key: "avatars/" + r,
Mime: "image/png", ETag: r + "-tag"}); err != nil {
t.Fatal(err)
}
}
tags, err := d.AvatarETags(AvatarRepo)
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.SetAvatar(Avatar{Kind: AvatarRepo, Name: "quarry", Key: "avatars/quarry",
Mime: "image/png", ETag: "t"}); err != nil {
t.Fatal(err)
}
if err := d.ClearAvatar(AvatarRepo, "quarry"); err != nil {
t.Fatal(err)
}
if _, ok, _ := d.AvatarOf(AvatarRepo, "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 []Avatar{
{Kind: AvatarRepo, Key: "k", Mime: "image/png"},
{Kind: AvatarRepo, Name: "quarry", Mime: "image/png"},
{Kind: AvatarRepo, Name: "quarry", Key: "k"},
} {
if err := d.SetAvatar(bad); err == nil {
t.Errorf("FAIL: stored an unservable row: %+v", bad)
}
}
}
// A team and a repository may hold the same name — teams share the
// ACCOUNT namespace and repositories have their own — so the kind is
// half the key and not a label.
func TestATeamAndARepositoryOfOneNameKeepSeparateMarks(t *testing.T) {
d := testDB(t)
if err := d.SetAvatar(Avatar{Kind: AvatarRepo, Name: "quarry",
Key: "avatars/repo/quarry", Mime: "image/png", ETag: "repo-tag"}); err != nil {
t.Fatal(err)
}
if err := d.SetAvatar(Avatar{Kind: AvatarTeam, Name: "quarry",
Key: "avatars/team/quarry", Mime: "image/webp", ETag: "team-tag"}); err != nil {
t.Fatal(err)
}
repo, ok, err := d.AvatarOf(AvatarRepo, "quarry")
if err != nil || !ok || repo.ETag != "repo-tag" {
t.Errorf("FAIL: the repository's mark = %+v (ok=%v err=%v)", repo, ok, err)
}
team, ok, err := d.AvatarOf(AvatarTeam, "quarry")
if err != nil || !ok || team.ETag != "team-tag" {
t.Errorf("FAIL: the team's mark = %+v (ok=%v err=%v)", team, ok, err)
}
// And a listing of one kind never shows the other's.
tags, err := d.AvatarETags(AvatarTeam)
if err != nil {
t.Fatal(err)
}
if tags["quarry"] != "team-tag" || len(tags) != 1 {
t.Errorf("FAIL: team validators = %v", tags)
}
}
// A kind nobody defined is refused rather than stored as a third sort
// of thing nothing will ever read.
func TestAnUnknownKindIsRefused(t *testing.T) {
d := testDB(t)
if err := d.SetAvatar(Avatar{Kind: "person", Name: "dmestas",
Key: "k", Mime: "image/png"}); err == nil {
t.Error("FAIL: stored a mark of an unknown kind")
}
}