package project import ( "path/filepath" "testing" "github.com/github/codeql-go/extractor/util" "golang.org/x/mod/modfile" ) func testStartsWithAnyOf(t *testing.T, path string, prefix string, expectation bool) { result := startsWithAnyOf(path, []string{prefix}) if result != expectation { t.Errorf("Expected startsWithAnyOf(%s, %s) to be %t, but it is %t.", path, prefix, expectation, result) } } func TestStartsWithAnyOf(t *testing.T) { testStartsWithAnyOf(t, ".", ".", true) testStartsWithAnyOf(t, ".", "dir", true) testStartsWithAnyOf(t, ".", filepath.Join("foo", "bar"), true) testStartsWithAnyOf(t, "dir", "dir", true) testStartsWithAnyOf(t, "foo", filepath.Join("foo", "bar"), true) testStartsWithAnyOf(t, filepath.Join("foo", "bar"), filepath.Join("foo", "bar"), true) testStartsWithAnyOf(t, filepath.Join("foo", "bar"), filepath.Join("foo", "bar", "baz"), true) testStartsWithAnyOf(t, filepath.Join("foo", "bar"), "foo", false) testStartsWithAnyOf(t, filepath.Join("foo", "bar"), "bar", false) testStartsWithAnyOf(t, filepath.Join("foo", "bar"), filepath.Join("foo", "baz"), false) } func parseModFile(t *testing.T, contents string) *modfile.File { modFile, err := modfile.Parse("go.mod", []byte(contents), nil) if err != nil { t.Errorf("Unable to parse %s: %s.\n", contents, err.Error()) } return modFile } func parseWorkFile(t *testing.T, contents string) *modfile.WorkFile { workFile, err := modfile.ParseWork("go.work", []byte(contents), nil) if err != nil { t.Errorf("Unable to parse %s: %s.\n", contents, err.Error()) } return workFile } func TestRequiredGoVersion(t *testing.T) { type ModVersionPair struct { FileContents string ExpectedVersion string } modules := []ModVersionPair{ {"go 1.20", "v1.20"}, {"go 1.21.2", "v1.21.2"}, {"go 1.21rc1", "v1.21.0-rc1"}, {"go 1.21rc1\ntoolchain go1.22.0", "v1.22.0"}, {"go 1.21rc1\ntoolchain go1.22rc1", "v1.22.0-rc1"}, } for _, testData := range modules { // `go.mod` and `go.work` files have mostly the same format modFile := parseModFile(t, testData.FileContents) workFile := parseWorkFile(t, testData.FileContents) mod := GoModule{ Path: "test", // irrelevant Module: modFile, } work := GoWorkspace{ WorkspaceFile: workFile, } result := mod.RequiredGoVersion() if result == nil { t.Errorf( "Expected mod.RequiredGoVersion() to return %s for the below `go.mod` file, but got nothing:\n%s", testData.ExpectedVersion, testData.FileContents, ) } else if result != util.NewSemVer(testData.ExpectedVersion) { t.Errorf( "Expected mod.RequiredGoVersion() to return %s for the below `go.mod` file, but got %s:\n%s", testData.ExpectedVersion, result, testData.FileContents, ) } result = work.RequiredGoVersion() if result == nil { t.Errorf( "Expected mod.RequiredGoVersion() to return %s for the below `go.work` file, but got nothing:\n%s", testData.ExpectedVersion, testData.FileContents, ) } else if result != util.NewSemVer(testData.ExpectedVersion) { t.Errorf( "Expected mod.RequiredGoVersion() to return %s for the below `go.work` file, but got %s:\n%s", testData.ExpectedVersion, result, testData.FileContents, ) } } }