socle

lang_test.go

package main

import (
	"testing"
)

// TestClassifyPath pins the filename-only classification pass, one row per rule:
// plain classification, the markup case, the skip heuristics (vendored, dotfile,
// documentation), unclassifiable paths, and the ambiguous-extension escape hatch.
func TestClassifyPath(t *testing.T) {
	t.Parallel()
	for _, c := range []struct {
		path         string
		lang         string
		needsContent bool
	}{
		{"src/hello.go", "Go", false},
		{"src/style.css", "CSS", false},
		{"Makefile", "Makefile", false},
		{"design.md", "Markdown", false}, // classified fine; prose is excluded later, by countsToward
		{"src/lib.rs", "", true},         // several candidate languages: classify by content
		{"vendor/mini.js", "", false},    // vendored
		{"testdata/gen.go", "", false},   // vendored (linguist treats test fixtures so)
		{".gitignore", "", false},        // dotfile
		{"docs/guide.html", "", false},   // documentation
		{"README.md", "", false},         // documentation too, READMEs count as docs
		{"LICENSE", "", false},           // unclassifiable by name
		{"notes", "", false},             // no extension, no known filename
	} {
		lang, needsContent := classifyPath(c.path)
		if lang != c.lang || needsContent != c.needsContent {
			t.Errorf("classifyPath(%q) = %q, %v; want %q, %v", c.path, lang, needsContent, c.lang, c.needsContent)
		}
	}
}

// TestCountsToward pins the type filter: programming and markup make the meter;
// data, prose, and the unknown empty string do not.
func TestCountsToward(t *testing.T) {
	t.Parallel()
	for _, c := range []struct {
		lang string
		want bool
	}{
		{"Go", true},
		{"Rust", true},
		{"CSS", true},        // markup
		{"HTML", true},       // markup
		{"Markdown", false},  // prose
		{"Text", false},      // prose
		{"YAML", false},      // data
		{"Go Module", false}, // data
		{"", false},
	} {
		if got := countsToward(c.lang); got != c.want {
			t.Errorf("countsToward(%q) = %v, want %v", c.lang, got, c.want)
		}
	}
}

// TestLanguageStats runs the whole computation against the fixture repo:
// Go, Rust (via the content sniff), and CSS counted by blob size, descending;
// prose, data, vendored, and dotfile content absent.
func TestLanguageStats(t *testing.T) {
	t.Parallel()
	r := fixtureRepo(t)
	size := func(path string) int64 {
		t.Helper()
		n, err := r.blobSize(fixtureShaMain, path)
		if err != nil {
			t.Fatal(err)
		}
		return n
	}
	want := []langStat{
		{"Go", size("src/hello.go")},
		{"Rust", size("src/lib.rs")},
		{"CSS", size("src/style.css")},
	}
	got, err := languageStats(r, fixtureShaMain)
	if err != nil {
		t.Fatal(err)
	}
	if len(got) != len(want) {
		t.Fatalf("languageStats = %+v, want %+v", got, want)
	}
	for i := range want {
		if got[i] != want[i] {
			t.Errorf("stat %d = %+v, want %+v", i, got[i], want[i])
		}
	}
}

// TestLangCacheBounds pins the cache's FIFO eviction: the capacity holds,
// the oldest key leaves first, and lookups tell hits from misses.
func TestLangCacheBounds(t *testing.T) {
	t.Parallel()
	c := newLangCache(2)
	c.put("a", []langStat{{"Go", 1}})
	c.put("b", []langStat{{"Go", 2}})
	if _, ok := c.get("a"); !ok {
		t.Error("a missing before capacity was exceeded")
	}
	c.put("c", []langStat{{"Go", 3}})
	if _, ok := c.get("a"); ok {
		t.Error("a survived eviction; want FIFO drop of the oldest")
	}
	for _, key := range []string{"b", "c"} {
		if _, ok := c.get(key); !ok {
			t.Errorf("%s missing after eviction of a", key)
		}
	}
	if _, ok := c.get("never"); ok {
		t.Error("get invented an entry")
	}
}

// TestLangStatsCached proves the server-level path consults the cache:
// a planted cache entry is returned instead of a fresh computation.
func TestLangStatsCached(t *testing.T) {
	t.Parallel()
	s := fixtureServer(t)
	rp := s.snap.Load().repos["fixturama"]
	planted := []langStat{{"Ada", 42}}
	s.langs.put(langCacheKey(rp.name, fixtureShaMain), planted)
	got, err := s.langStats(rp, fixtureShaMain)
	if err != nil {
		t.Fatal(err)
	}
	if len(got) != 1 || got[0] != planted[0] {
		t.Errorf("langStats = %+v, want the planted %+v", got, planted)
	}
}

lang_test.go · 4.0 KiB · 245d322a2e