gopkg.in/src-d/enry.v1@v1.7.3/internal/code-generator/generator/generator_test.go (about) 1 package generator 2 3 import ( 4 "flag" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/suite" 14 ) 15 16 const ( 17 linguistURL = "https://github.com/github/linguist.git" 18 linguistClonedEnvVar = "ENRY_TEST_REPO" 19 commit = "e4560984058b4726010ca4b8f03ed9d0f8f464db" 20 samplesDir = "samples" 21 languagesFile = "lib/linguist/languages.yml" 22 23 testDir = "test_files" 24 assetsDir = "../assets" 25 26 // Extensions test 27 extensionGold = testDir + "/extension.gold" 28 extensionTestTmplPath = assetsDir + "/extension.go.tmpl" 29 extensionTestTmplName = "extension.go.tmpl" 30 31 // Heuristics test 32 heuristicsTestFile = "lib/linguist/heuristics.yml" 33 contentGold = testDir + "/content.gold" 34 contentTestTmplPath = assetsDir + "/content.go.tmpl" 35 contentTestTmplName = "content.go.tmpl" 36 37 // Vendor test 38 vendorTestFile = "lib/linguist/vendor.yml" 39 vendorGold = testDir + "/vendor.gold" 40 vendorTestTmplPath = assetsDir + "/vendor.go.tmpl" 41 vendorTestTmplName = "vendor.go.tmpl" 42 43 // Documentation test 44 documentationTestFile = "lib/linguist/documentation.yml" 45 documentationGold = testDir + "/documentation.gold" 46 documentationTestTmplPath = assetsDir + "/documentation.go.tmpl" 47 documentationTestTmplName = "documentation.go.tmpl" 48 49 // Types test 50 typeGold = testDir + "/type.gold" 51 typeTestTmplPath = assetsDir + "/type.go.tmpl" 52 typeTestTmplName = "type.go.tmpl" 53 54 // Interpreters test 55 interpreterGold = testDir + "/interpreter.gold" 56 interpreterTestTmplPath = assetsDir + "/interpreter.go.tmpl" 57 interpreterTestTmplName = "interpreter.go.tmpl" 58 59 // Filenames test 60 filenameGold = testDir + "/filename.gold" 61 filenameTestTmplPath = assetsDir + "/filename.go.tmpl" 62 filenameTestTmplName = "filename.go.tmpl" 63 64 // Aliases test 65 aliasGold = testDir + "/alias.gold" 66 aliasTestTmplPath = assetsDir + "/alias.go.tmpl" 67 aliasTestTmplName = "alias.go.tmpl" 68 69 // Frequencies test 70 frequenciesGold = testDir + "/frequencies.gold" 71 frequenciesTestTmplPath = assetsDir + "/frequencies.go.tmpl" 72 frequenciesTestTmplName = "frequencies.go.tmpl" 73 74 // commit test 75 commitGold = testDir + "/commit.gold" 76 commitTestTmplPath = assetsDir + "/commit.go.tmpl" 77 commitTestTmplName = "commit.go.tmpl" 78 79 // mime test 80 mimeTypeGold = testDir + "/mimeType.gold" 81 mimeTypeTestTmplPath = assetsDir + "/mimeType.go.tmpl" 82 mimeTypeTestTmplName = "mimeType.go.tmpl" 83 ) 84 85 type GeneratorTestSuite struct { 86 suite.Suite 87 tmpLinguist string 88 cloned bool 89 testCases []testCase 90 } 91 92 type testCase struct { 93 name string 94 fileToParse string 95 samplesDir string 96 tmplPath string 97 tmplName string 98 commit string 99 generate File 100 wantOut string 101 } 102 103 var updateGold = flag.Bool("update_gold", false, "Update golden test files") 104 105 func Test_GeneratorTestSuite(t *testing.T) { 106 suite.Run(t, new(GeneratorTestSuite)) 107 } 108 109 func (s *GeneratorTestSuite) maybeCloneLinguist() { 110 var err error 111 s.tmpLinguist = os.Getenv(linguistClonedEnvVar) 112 s.cloned = s.tmpLinguist == "" 113 if s.cloned { 114 s.tmpLinguist, err = ioutil.TempDir("", "linguist-") 115 assert.NoError(s.T(), err) 116 cmd := exec.Command("git", "clone", linguistURL, s.tmpLinguist) 117 err = cmd.Run() 118 assert.NoError(s.T(), err) 119 120 cwd, err := os.Getwd() 121 assert.NoError(s.T(), err) 122 123 err = os.Chdir(s.tmpLinguist) 124 assert.NoError(s.T(), err) 125 126 cmd = exec.Command("git", "checkout", commit) 127 err = cmd.Run() 128 assert.NoError(s.T(), err) 129 130 err = os.Chdir(cwd) 131 assert.NoError(s.T(), err) 132 } 133 } 134 135 func (s *GeneratorTestSuite) SetupSuite() { 136 s.maybeCloneLinguist() 137 s.testCases = []testCase{ 138 { 139 name: "Extensions()", 140 fileToParse: filepath.Join(s.tmpLinguist, languagesFile), 141 samplesDir: "", 142 tmplPath: extensionTestTmplPath, 143 tmplName: extensionTestTmplName, 144 commit: commit, 145 generate: Extensions, 146 wantOut: extensionGold, 147 }, 148 { 149 name: "Heuristics()", 150 fileToParse: filepath.Join(s.tmpLinguist, heuristicsTestFile), 151 samplesDir: "", 152 tmplPath: contentTestTmplPath, 153 tmplName: contentTestTmplName, 154 commit: commit, 155 generate: GenHeuristics, 156 wantOut: contentGold, 157 }, 158 { 159 name: "Vendor()", 160 fileToParse: filepath.Join(s.tmpLinguist, vendorTestFile), 161 samplesDir: "", 162 tmplPath: vendorTestTmplPath, 163 tmplName: vendorTestTmplName, 164 commit: commit, 165 generate: Vendor, 166 wantOut: vendorGold, 167 }, 168 { 169 name: "Documentation()", 170 fileToParse: filepath.Join(s.tmpLinguist, documentationTestFile), 171 samplesDir: "", 172 tmplPath: documentationTestTmplPath, 173 tmplName: documentationTestTmplName, 174 commit: commit, 175 generate: Documentation, 176 wantOut: documentationGold, 177 }, 178 { 179 name: "Types()", 180 fileToParse: filepath.Join(s.tmpLinguist, languagesFile), 181 samplesDir: "", 182 tmplPath: typeTestTmplPath, 183 tmplName: typeTestTmplName, 184 commit: commit, 185 generate: Types, 186 wantOut: typeGold, 187 }, 188 { 189 name: "Interpreters()", 190 fileToParse: filepath.Join(s.tmpLinguist, languagesFile), 191 samplesDir: "", 192 tmplPath: interpreterTestTmplPath, 193 tmplName: interpreterTestTmplName, 194 commit: commit, 195 generate: Interpreters, 196 wantOut: interpreterGold, 197 }, 198 { 199 name: "Filenames()", 200 fileToParse: filepath.Join(s.tmpLinguist, languagesFile), 201 samplesDir: filepath.Join(s.tmpLinguist, samplesDir), 202 tmplPath: filenameTestTmplPath, 203 tmplName: filenameTestTmplName, 204 commit: commit, 205 generate: Filenames, 206 wantOut: filenameGold, 207 }, 208 { 209 name: "Aliases()", 210 fileToParse: filepath.Join(s.tmpLinguist, languagesFile), 211 samplesDir: "", 212 tmplPath: aliasTestTmplPath, 213 tmplName: aliasTestTmplName, 214 commit: commit, 215 generate: Aliases, 216 wantOut: aliasGold, 217 }, 218 { 219 name: "Frequencies()", 220 samplesDir: filepath.Join(s.tmpLinguist, samplesDir), 221 tmplPath: frequenciesTestTmplPath, 222 tmplName: frequenciesTestTmplName, 223 commit: commit, 224 generate: Frequencies, 225 wantOut: frequenciesGold, 226 }, 227 { 228 name: "Commit()", 229 samplesDir: "", 230 tmplPath: commitTestTmplPath, 231 tmplName: commitTestTmplName, 232 commit: commit, 233 generate: Commit, 234 wantOut: commitGold, 235 }, 236 { 237 name: "MimeType()", 238 fileToParse: filepath.Join(s.tmpLinguist, languagesFile), 239 samplesDir: "", 240 tmplPath: mimeTypeTestTmplPath, 241 tmplName: mimeTypeTestTmplName, 242 commit: commit, 243 generate: MimeType, 244 wantOut: mimeTypeGold, 245 }, 246 } 247 } 248 249 func (s *GeneratorTestSuite) TearDownSuite() { 250 if s.cloned { 251 err := os.RemoveAll(s.tmpLinguist) 252 if err != nil { 253 s.T().Logf("Failed to clean up %s after the test.\n", s.tmpLinguist) 254 } 255 } 256 } 257 258 // TestUpdateGeneratorTestSuiteGold is a Gold results generation automation. 259 // It should only be enabled&run manually on every new Linguist version 260 // to update *.gold files. 261 func (s *GeneratorTestSuite) TestUpdateGeneratorTestSuiteGold() { 262 if !*updateGold { 263 s.T().Skip() 264 } 265 s.T().Logf("Generating new *.gold test files") 266 for _, test := range s.testCases { 267 dst := test.wantOut 268 s.T().Logf("Generating %s from %s\n", dst, test.fileToParse) 269 err := test.generate(test.fileToParse, test.samplesDir, dst, test.tmplPath, test.tmplName, test.commit) 270 assert.NoError(s.T(), err) 271 } 272 } 273 274 func (s *GeneratorTestSuite) TestGenerationFiles() { 275 for _, test := range s.testCases { 276 gold, err := ioutil.ReadFile(test.wantOut) 277 assert.NoError(s.T(), err) 278 279 outPath, err := ioutil.TempFile("/tmp", "generator-test-") 280 assert.NoError(s.T(), err) 281 defer os.Remove(outPath.Name()) 282 err = test.generate(test.fileToParse, test.samplesDir, outPath.Name(), test.tmplPath, test.tmplName, test.commit) 283 assert.NoError(s.T(), err) 284 out, err := ioutil.ReadFile(outPath.Name()) 285 assert.NoError(s.T(), err) 286 287 expected := normalizeSpaces(string(gold)) 288 actual := normalizeSpaces(string(out)) 289 assert.Equal(s.T(), expected, actual, "Test %s", test.name) 290 } 291 } 292 293 // normalizeSpaces returns a copy of str with whitespaces normalized. 294 // We use this to compare generated source as gofmt format may change. 295 // E.g for changes between Go 1.10 and 1.11 see 296 // https://go-review.googlesource.com/c/go/+/122295/ 297 func normalizeSpaces(str string) string { 298 return strings.Join(strings.Fields(str), " ") 299 }