Skip to content
quarry Artifact [612320e85f]
Login

Artifact [612320e85f]

Artifact 612320e85f68c90250a6ef6f09768196ba4e29733f32c280b00300d14099829a:


package zitcli

import (
	"bufio"
	"context"
	"maps"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// crosslink's lines line counts the file line before it, and "- -" is a
// binary file. A lines line with no file before it is malformed.
func TestParseCrosslinkLineCounts(t *testing.T) {
	stream := "crosslink 1\n" +
		"checkin bb22 893869787000 aa11\n" +
		"comment 0\n\n" +
		"file M src/main.c\nlines 12 3\n" +
		"file A logo.png\nlines - -\n" +
		"file D gone\\sname.txt\n" +
		"end\n"
	var got CrosslinkRecord
	if err := parseCrosslink(bufio.NewReader(strings.NewReader(stream)),
		func(r CrosslinkRecord) error { got = r; return nil }); err != nil {
		t.Fatal(err)
	}
	want := map[string]LineCount{"src/main.c": {12, 3}, "logo.png": {-1, -1}}
	if !maps.Equal(got.Lines, want) {
		t.Errorf("FAIL: lines %v, want %v (the uncounted delete absent)", got.Lines, want)
	}
	bad := "crosslink 1\ncheckin dd44 900000000000\ncomment 0\n\nlines 1 2\nend\n"
	if err := parseCrosslink(bufio.NewReader(strings.NewReader(bad)), func(CrosslinkRecord) error { return nil }); err == nil {
		t.Error("FAIL: a lines line with no file before it was accepted")
	}
}

// A live fold counts with numstat and a rebuild with crosslink; both
// must give the same numbers for the same check-in.
func TestNumStatAgreesWithCrosslink(t *testing.T) {
	dir := testRepo(t, 1)
	if err := os.WriteFile(filepath.Join(dir, "a.txt"), []byte("one\ntwo\nthree\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(filepath.Join(dir, "b.bin"), []byte{0, 1, 2, 0}, 0o644); err != nil {
		t.Fatal(err)
	}
	run(t, dir, "add", "b.bin")
	run(t, dir, "commit", "-m", "edit a, add b")
	z := New(dir)
	tip, _, err := z.Info(context.Background(), "trunk")
	if err != nil {
		t.Fatal(err)
	}
	num, err := z.NumStat(context.Background(), tip)
	if err != nil {
		t.Fatal(err)
	}
	var cross map[string]LineCount
	if err := z.Crosslink(context.Background(), func(r CrosslinkRecord) error {
		if r.Hash == tip {
			cross = r.Lines
		}
		return nil
	}); err != nil {
		t.Fatal(err)
	}
	if !maps.Equal(num, cross) || num["a.txt"] != (LineCount{3, 1}) || num["b.bin"] != (LineCount{-1, -1}) {
		t.Errorf("FAIL: numstat %v, crosslink %v", num, cross)
	}
}