tartrazine/internal/code-generator/generator/generator_test.go

358 lines
11 KiB
Go
Raw Normal View History

2017-04-04 11:10:35 +00:00
package generator
import (
"flag"
"fmt"
2017-04-04 11:10:35 +00:00
"io/ioutil"
"os"
2017-05-25 10:33:26 +00:00
"os/exec"
"path/filepath"
"strings"
2017-04-04 11:10:35 +00:00
"testing"
"github.com/go-enry/go-enry/v2/internal/tokenizer"
2017-04-04 11:10:35 +00:00
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
2017-05-25 10:33:26 +00:00
"github.com/stretchr/testify/suite"
2017-04-04 11:10:35 +00:00
)
var (
linguistURL = "https://github.com/github/linguist.git"
linguistClonedEnvVar = "ENRY_TEST_REPO"
2022-10-06 08:23:21 +00:00
commit = "bf853f1c663903e3ee35935189760191f1c45e1c"
samplesDir = "samples"
languagesFile = filepath.Join("lib", "linguist", "languages.yml")
testDir = "test_files"
assetsDir = filepath.Join("..", "assets")
2017-05-25 10:33:26 +00:00
// Extensions test
extensionGold = filepath.Join(testDir, "extension.gold")
extensionTestTmplPath = filepath.Join(assetsDir, "extension.go.tmpl")
2017-06-13 11:56:07 +00:00
extensionTestTmplName = "extension.go.tmpl"
2017-04-05 14:01:31 +00:00
// Heuristics test
heuristicsTestFile = filepath.Join("lib", "linguist", "heuristics.yml")
contentGold = filepath.Join(testDir, "content.gold")
contentTestTmplPath = filepath.Join(assetsDir, "content.go.tmpl")
contentTestTmplName = "content.go.tmpl"
2017-04-06 15:31:17 +00:00
// Vendor test
vendorTestFile = filepath.Join("lib", "linguist", "vendor.yml")
vendorGold = filepath.Join(testDir, "vendor.gold")
vendorTestTmplPath = filepath.Join(assetsDir, "vendor.go.tmpl")
vendorTestTmplName = "vendor.go.tmpl"
// Documentation test
documentationTestFile = filepath.Join("lib", "linguist", "documentation.yml")
documentationGold = filepath.Join(testDir, "documentation.gold")
documentationTestTmplPath = filepath.Join(assetsDir, "documentation.go.tmpl")
documentationTestTmplName = "documentation.go.tmpl"
2017-04-11 09:26:23 +00:00
// Types test
typeGold = filepath.Join(testDir, "type.gold")
typeTestTmplPath = filepath.Join(assetsDir, "type.go.tmpl")
2017-06-13 11:56:07 +00:00
typeTestTmplName = "type.go.tmpl"
// Interpreters test
interpreterGold = filepath.Join(testDir, "interpreter.gold")
interpreterTestTmplPath = filepath.Join(assetsDir, "interpreter.go.tmpl")
2017-06-13 11:56:07 +00:00
interpreterTestTmplName = "interpreter.go.tmpl"
// Filenames test
filenameGold = filepath.Join(testDir, "filename.gold")
filenameTestTmplPath = filepath.Join(assetsDir, "filename.go.tmpl")
2017-06-13 11:56:07 +00:00
filenameTestTmplName = "filename.go.tmpl"
// Aliases test
aliasGold = filepath.Join(testDir, "alias.gold")
aliasTestTmplPath = filepath.Join(assetsDir, "alias.go.tmpl")
2017-06-13 11:56:07 +00:00
aliasTestTmplName = "alias.go.tmpl"
2017-05-25 10:33:26 +00:00
// Frequencies test
frequenciesGold = filepath.Join(testDir, "frequencies.gold")
frequenciesTestTmplPath = filepath.Join(assetsDir, "frequencies.go.tmpl")
2017-05-25 10:33:26 +00:00
frequenciesTestTmplName = "frequencies.go.tmpl"
// commit test
commitGold = filepath.Join(testDir, "commit.gold")
commitTestTmplPath = filepath.Join(assetsDir, "commit.go.tmpl")
commitTestTmplName = "commit.go.tmpl"
2017-07-11 09:13:49 +00:00
// mime test
mimeTypeGold = filepath.Join(testDir, "mimeType.gold")
mimeTypeTestTmplPath = filepath.Join(assetsDir, "mimeType.go.tmpl")
2017-07-11 09:13:49 +00:00
mimeTypeTestTmplName = "mimeType.go.tmpl"
// colors test
colorsGold = filepath.Join(testDir, "colors.gold")
colorsTestTmplPath = filepath.Join(assetsDir, "colors.go.tmpl")
colorsTestTmplName = "colors.go.tmpl"
// colors test
groupsGold = filepath.Join(testDir, "groups.gold")
groupsTestTmplPath = filepath.Join(assetsDir, "groups.go.tmpl")
groupsTestTmplName = "groups.go.tmpl"
2017-04-04 11:10:35 +00:00
)
2017-05-25 10:33:26 +00:00
type GeneratorTestSuite struct {
suite.Suite
tmpLinguistDir string
isCleanupNeeded bool
testCases []testCase
2017-05-25 10:33:26 +00:00
}
type testCase struct {
name string
fileToParse string
samplesDir string
tmplPath string
tmplName string
commit string
generate File
wantOut string
}
var updateGold = flag.Bool("update_gold", false, "Update golden test files")
func Test_GeneratorTestSuite(t *testing.T) {
2017-05-29 08:05:16 +00:00
suite.Run(t, new(GeneratorTestSuite))
}
func (s *GeneratorTestSuite) maybeCloneLinguist() {
var err error
s.tmpLinguistDir = os.Getenv(linguistClonedEnvVar)
isLinguistCloned := s.tmpLinguistDir != ""
if !isLinguistCloned {
s.tmpLinguistDir, err = ioutil.TempDir("", "linguist-")
require.NoError(s.T(), err)
s.T().Logf("Cloning Linguist repo to '%s' as %s was not set\n",
s.tmpLinguistDir, linguistClonedEnvVar)
2022-11-23 21:04:53 +00:00
cmd := exec.Command("git", "clone", "--depth", "100", linguistURL, s.tmpLinguistDir)
err = cmd.Run()
require.NoError(s.T(), err)
s.isCleanupNeeded = true
}
2017-05-25 10:33:26 +00:00
cwd, err := os.Getwd()
require.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
err = os.Chdir(s.tmpLinguistDir)
require.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
cmd := exec.Command("git", "checkout", commit)
err = cmd.Run()
require.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
err = os.Chdir(cwd)
require.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
}
func (s *GeneratorTestSuite) SetupSuite() {
s.maybeCloneLinguist()
s.testCases = []testCase{
2017-04-04 11:10:35 +00:00
{
2017-06-13 11:56:07 +00:00
name: "Extensions()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
tmplPath: extensionTestTmplPath,
tmplName: extensionTestTmplName,
commit: commit,
generate: Extensions,
2017-06-13 11:56:07 +00:00
wantOut: extensionGold,
2017-04-04 11:10:35 +00:00
},
2017-04-05 14:01:31 +00:00
{
2017-06-13 11:56:07 +00:00
name: "Heuristics()",
fileToParse: filepath.Join(s.tmpLinguistDir, heuristicsTestFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
2017-04-05 14:01:31 +00:00
tmplPath: contentTestTmplPath,
tmplName: contentTestTmplName,
2017-06-13 11:56:07 +00:00
commit: commit,
generate: GenHeuristics,
wantOut: contentGold,
2017-04-05 14:01:31 +00:00
},
2017-04-06 15:31:17 +00:00
{
2017-06-13 11:56:07 +00:00
name: "Vendor()",
fileToParse: filepath.Join(s.tmpLinguistDir, vendorTestFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
tmplPath: vendorTestTmplPath,
tmplName: vendorTestTmplName,
2017-06-13 11:56:07 +00:00
commit: commit,
2017-04-06 15:31:17 +00:00
generate: Vendor,
wantOut: vendorGold,
2017-04-06 15:31:17 +00:00
},
{
2017-06-13 11:56:07 +00:00
name: "Documentation()",
fileToParse: filepath.Join(s.tmpLinguistDir, documentationTestFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
tmplPath: documentationTestTmplPath,
tmplName: documentationTestTmplName,
2017-06-13 11:56:07 +00:00
commit: commit,
generate: Documentation,
wantOut: documentationGold,
},
2017-04-11 09:26:23 +00:00
{
2017-06-13 11:56:07 +00:00
name: "Types()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
tmplPath: typeTestTmplPath,
tmplName: typeTestTmplName,
commit: commit,
2017-04-11 09:26:23 +00:00
generate: Types,
2017-06-13 11:56:07 +00:00
wantOut: typeGold,
2017-04-11 09:26:23 +00:00
},
{
2017-06-13 11:56:07 +00:00
name: "Interpreters()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
tmplPath: interpreterTestTmplPath,
tmplName: interpreterTestTmplName,
commit: commit,
generate: Interpreters,
2017-06-13 11:56:07 +00:00
wantOut: interpreterGold,
},
{
2017-06-13 11:56:07 +00:00
name: "Filenames()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
samplesDir: filepath.Join(s.tmpLinguistDir, samplesDir),
2017-06-13 11:56:07 +00:00
tmplPath: filenameTestTmplPath,
tmplName: filenameTestTmplName,
commit: commit,
generate: Filenames,
2017-06-13 11:56:07 +00:00
wantOut: filenameGold,
},
{
2017-06-13 11:56:07 +00:00
name: "Aliases()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
2017-06-13 11:56:07 +00:00
samplesDir: "",
tmplPath: aliasTestTmplPath,
tmplName: aliasTestTmplName,
commit: commit,
generate: Aliases,
2017-06-13 11:56:07 +00:00
wantOut: aliasGold,
},
2017-05-25 10:33:26 +00:00
{
2017-06-13 11:56:07 +00:00
name: "Frequencies()",
samplesDir: filepath.Join(s.tmpLinguistDir, samplesDir),
2017-05-25 10:33:26 +00:00
tmplPath: frequenciesTestTmplPath,
tmplName: frequenciesTestTmplName,
2017-06-13 11:56:07 +00:00
commit: commit,
generate: Frequencies,
2017-05-25 10:33:26 +00:00
wantOut: frequenciesGold,
},
{
name: "Commit()",
samplesDir: "",
tmplPath: commitTestTmplPath,
tmplName: commitTestTmplName,
commit: commit,
generate: Commit,
wantOut: commitGold,
},
2017-07-11 09:13:49 +00:00
{
name: "MimeType()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
2017-07-11 09:13:49 +00:00
samplesDir: "",
tmplPath: mimeTypeTestTmplPath,
tmplName: mimeTypeTestTmplName,
commit: commit,
generate: MimeType,
wantOut: mimeTypeGold,
},
{
name: "Colors()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
samplesDir: "",
tmplPath: colorsTestTmplPath,
tmplName: colorsTestTmplName,
commit: commit,
generate: Colors,
wantOut: colorsGold,
},
{
name: "Groups()",
fileToParse: filepath.Join(s.tmpLinguistDir, languagesFile),
samplesDir: "",
tmplPath: groupsTestTmplPath,
tmplName: groupsTestTmplName,
commit: commit,
generate: Groups,
wantOut: groupsGold,
},
2017-05-25 10:33:26 +00:00
}
}
func (s *GeneratorTestSuite) TearDownSuite() {
if s.isCleanupNeeded {
err := os.RemoveAll(s.tmpLinguistDir)
assert.NoError(s.T(), err)
}
}
2017-05-25 10:33:26 +00:00
// TestUpdateGeneratorTestSuiteGold is a Gold results generation automation.
// It should only be enabled&run manually on every new Linguist version
// to update *.gold files.
func (s *GeneratorTestSuite) TestUpdateGeneratorTestSuiteGold() {
if !*updateGold {
s.T().Skip()
}
s.T().Logf("Generating new *.gold test files")
for _, test := range s.testCases {
dst := test.wantOut
s.T().Logf("Generating %s from %s\n", dst, test.fileToParse)
err := test.generate(test.fileToParse, test.samplesDir, dst, test.tmplPath, test.tmplName, test.commit)
assert.NoError(s.T(), err)
}
}
func (s *GeneratorTestSuite) TestGenerationFiles() {
for _, test := range s.testCases {
2017-05-25 10:33:26 +00:00
gold, err := ioutil.ReadFile(test.wantOut)
assert.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
outPath, err := ioutil.TempFile("", "generator-test-")
assert.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
defer os.Remove(outPath.Name())
2017-06-13 11:56:07 +00:00
err = test.generate(test.fileToParse, test.samplesDir, outPath.Name(), test.tmplPath, test.tmplName, test.commit)
assert.NoError(s.T(), err)
2017-05-25 10:33:26 +00:00
out, err := ioutil.ReadFile(outPath.Name())
assert.NoError(s.T(), err)
expected := normalizeSpaces(string(gold))
actual := normalizeSpaces(string(out))
// this produces large unreadable output, so we do it 'manually' instead
// assert.Equal(s.T(), expected, actual, "Test %s", test.name)
if expected != actual {
assert.Fail(s.T(), fmt.Sprintf("%s output is different from %q", test.name, test.wantOut))
diff, err := text_diff(gold, out)
if err != nil {
s.T().Logf("Failed produce a diff between expected and actual: %s", err.Error())
s.T().Logf("Expected %q", expected[:400])
s.T().Logf("Actual %q", actual[:400])
}
s.T().Logf("\n%s", diff)
}
2017-05-25 10:33:26 +00:00
}
}
func (s *GeneratorTestSuite) TestTokenizerOnATS() {
const suspiciousSample = "samples/ATS/csv_parse.hats"
sFile := filepath.Join(s.tmpLinguistDir, suspiciousSample)
content, err := ioutil.ReadFile(sFile)
require.NoError(s.T(), err)
tokens := tokenizer.Tokenize(content)
assert.Equal(s.T(), 381, len(tokens), "Number of tokens using LF as line endings")
}
// normalizeSpaces returns a copy of str with whitespaces normalized.
// We use this to compare generated source as gofmt format may change.
// E.g for changes between Go 1.10 and 1.11 see
// https://go-review.googlesource.com/c/go/+/122295/
func normalizeSpaces(str string) string {
return strings.Join(strings.Fields(str), " ")
}