Skip to content
quarry Artifact [3dd8e64d59]
Login

Artifact [3dd8e64d59]

Artifact 3dd8e64d599c0aa95e8ed24bb816874ddb56d14c91d13bfea7827f9d09adca94:


package api

import (
	"context"
	"errors"
	"slices"
	"testing"

	"craftdesign.group/quarry/internal/zitcli"
)

// zit's current is the target and its other the branch; the forge says
// theirs and ours, and swaps them here and nowhere else — regions and
// blobs alike.
func TestConflictFileOfSaysOursForTheBranch(t *testing.T) {
	cf := conflictFileOf(zitcli.MergeFile{Path: "f.txt", Kind: "text", Base: "b", Current: "c", Other: "o",
		Mode: map[string]string{"base": "regular", "current": "regular", "other": "executable"},
		Regions: []zitcli.MergeRegion{
			{Kind: "current", Base: [2]int{0, 1}, Current: [2]int{0, 2}, Other: [2]int{0, 1}},
			{Kind: "other", Base: [2]int{1, 1}, Current: [2]int{2, 2}, Other: [2]int{1, 3}},
			{Kind: "conflict", Base: [2]int{1, 2}, Current: [2]int{2, 3}, Other: [2]int{3, 5}},
		}})
	if cf.Ours.Blob != "o" || cf.Theirs.Blob != "c" || cf.Base.Blob != "b" || cf.Ours.Mode != "executable" {
		t.Errorf("FAIL: sides %+v %+v %+v", cf.Ours, cf.Theirs, cf.Base)
	}
	var kinds []string
	for _, r := range cf.Regions {
		kinds = append(kinds, r.Kind)
	}
	if !slices.Equal(kinds, []string{"theirs", "ours", "conflict"}) {
		t.Errorf("FAIL: regions %v", kinds)
	}
	if r := cf.Regions[2]; r.Ours != (lineSpan{3, 5}) || r.Theirs != (lineSpan{2, 3}) {
		t.Errorf("FAIL: a conflict's ranges are not swapped with its sides: %+v", r)
	}
}

type fakeBlobs map[string]string

func (f fakeBlobs) ArtifactSize(_ context.Context, h string) (int, error) {
	b, ok := f[h]
	if !ok {
		return 0, errors.New("no such blob")
	}
	return len(b), nil
}

func (f fakeBlobs) ArtifactRaw(_ context.Context, h string, max int) ([]byte, error) {
	b, ok := f[h]
	if !ok || len(b) > max {
		return nil, errors.New("no")
	}
	return []byte(b), nil
}

// Each side's lines are read by its blob, as zit counts them; a side the
// other added has none; an oversized or unreadable side keeps the file
// listed but undrawn.
func TestReadConflictSides(t *testing.T) {
	blobs := fakeBlobs{"o": "a\nB\n", "c": "a\nb\nc", "big": string(make([]byte, maxConflictBytes+1))}
	cf := conflictFile{Ours: conflictSide{Blob: "o"}, Theirs: conflictSide{Blob: "c"}}
	if why := readConflictSides(context.Background(), blobs, &cf); why != "" {
		t.Fatalf("FAIL: %s", why)
	}
	if !slices.Equal(cf.Ours.Lines, []string{"a", "B"}) || !slices.Equal(cf.Theirs.Lines, []string{"a", "b", "c"}) || cf.Base.Lines != nil {
		t.Errorf("FAIL: lines %q %q %q", cf.Ours.Lines, cf.Theirs.Lines, cf.Base.Lines)
	}
	if why := readConflictSides(context.Background(), blobs, &conflictFile{Ours: conflictSide{Blob: "big"}}); why != "too large" {
		t.Errorf("FAIL: an oversized side gave %q", why)
	}
	if why := readConflictSides(context.Background(), blobs, &conflictFile{Ours: conflictSide{Blob: "gone"}}); why != "unreadable" {
		t.Errorf("FAIL: a missing blob gave %q", why)
	}
}