1package enry
2
3import (
4	"bytes"
5	"fmt"
6	"io/ioutil"
7	"path/filepath"
8	"testing"
9
10	"github.com/stretchr/testify/assert"
11	"github.com/stretchr/testify/require"
12)
13
14func TestIsVendor(t *testing.T) {
15	tests := []struct {
16		path     string
17		expected bool
18	}{
19		{"cache/", true},
20		{"random/cache/", true},
21		{"cache", false},
22		{"dependencies/", true},
23		{"Dependencies/", true},
24		{"dependency/", false},
25		{"dist/", true},
26		{"dist", false},
27		{"random/dist/", true},
28		{"random/dist", false},
29		{"deps/", true},
30		{"configure", true},
31		{"a/configure", true},
32		{"config.guess", true},
33		{"config.guess/", false},
34		{".vscode/", true},
35		{"doc/_build/", true},
36		{"a/docs/_build/", true},
37		{"a/dasdocs/_build-vsdoc.js", true},
38		{"a/dasdocs/_build-vsdoc.j", false},
39		{"foo/bar", false},
40		{".sublime-project", true},
41		{"foo/vendor/foo", true},
42		{"leaflet.draw-src.js", true},
43		{"foo/bar/MochiKit.js", true},
44		{"foo/bar/dojo.js", true},
45		{"foo/env/whatever", true},
46		{"foo/.imageset/bar", true},
47		{"Vagrantfile", true},
48	}
49	for _, tt := range tests {
50		t.Run(tt.path, func(t *testing.T) {
51			if got := IsVendor(tt.path); got != tt.expected {
52				t.Errorf("IsVendor() = %v, expected %v", got, tt.expected)
53			}
54		})
55	}
56}
57
58func BenchmarkIsVendor(b *testing.B) {
59	for i := 0; i < b.N; i++ {
60		IsVendor(".vscode/")
61		IsVendor("cache/")
62		IsVendor("foo/bar")
63		IsVendor("foo/bar/MochiKit.js")
64	}
65}
66
67func TestIsDocumentation(t *testing.T) {
68	tests := []struct {
69		name     string
70		path     string
71		expected bool
72	}{
73		{name: "TestIsDocumentation_1", path: "foo", expected: false},
74		{name: "TestIsDocumentation_2", path: "README", expected: true},
75	}
76
77	for _, test := range tests {
78		is := IsDocumentation(test.path)
79		assert.Equal(t, is, test.expected, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
80	}
81}
82
83func TestIsImage(t *testing.T) {
84	tests := []struct {
85		name     string
86		path     string
87		expected bool
88	}{
89		{name: "TestIsImage_1", path: "invalid.txt", expected: false},
90		{name: "TestIsImage_2", path: "image.png", expected: true},
91		{name: "TestIsImage_3", path: "image.jpg", expected: true},
92		{name: "TestIsImage_4", path: "image.jpeg", expected: true},
93		{name: "TestIsImage_5", path: "image.gif", expected: true},
94	}
95
96	for _, test := range tests {
97		is := IsImage(test.path)
98		assert.Equal(t, is, test.expected, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
99	}
100}
101
102func TestGetMimeType(t *testing.T) {
103	tests := []struct {
104		name     string
105		path     string
106		lang     string
107		expected string
108	}{
109		{name: "TestGetMimeType_1", path: "text.txt", lang: "", expected: "text/plain"},
110		{name: "TestGetMimeType_2", path: "file.go", lang: "Go", expected: "text/x-go"},
111		{name: "TestGetMimeType_3", path: "image.png", lang: "", expected: "image/png"},
112	}
113
114	for _, test := range tests {
115		is := GetMIMEType(test.path, test.lang)
116		assert.Equal(t, is, test.expected, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
117	}
118}
119
120func TestIsConfiguration(t *testing.T) {
121	tests := []struct {
122		name     string
123		path     string
124		expected bool
125	}{
126		{name: "TestIsConfiguration_1", path: "foo", expected: false},
127		{name: "TestIsConfiguration_2", path: "foo.ini", expected: true},
128		{name: "TestIsConfiguration_3", path: "/test/path/foo.json", expected: true},
129	}
130
131	for _, test := range tests {
132		is := IsConfiguration(test.path)
133		assert.Equal(t, is, test.expected, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
134	}
135}
136
137func TestIsBinary(t *testing.T) {
138	tests := []struct {
139		name     string
140		data     []byte
141		expected bool
142	}{
143		{name: "TestIsBinary_1", data: []byte("foo"), expected: false},
144		{name: "TestIsBinary_2", data: []byte{0}, expected: true},
145		{name: "TestIsBinary_3", data: bytes.Repeat([]byte{'o'}, 8000), expected: false},
146	}
147
148	for _, test := range tests {
149		is := IsBinary(test.data)
150		assert.Equal(t, is, test.expected, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
151	}
152}
153
154func TestIsDotFile(t *testing.T) {
155	tests := []struct {
156		name     string
157		path     string
158		expected bool
159	}{
160		{name: "TestIsDotFile_1", path: "foo/bar/./", expected: false},
161		{name: "TestIsDotFile_2", path: "./", expected: false},
162	}
163
164	for _, test := range tests {
165		is := IsDotFile(test.path)
166		assert.Equal(t, test.expected, is, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
167	}
168}
169func TestIsTestFile(t *testing.T) {
170	tests := []struct {
171		name     string
172		path     string
173		expected bool
174	}{
175		{name: "TestPHP_Is", path: "tests/FooTest.php", expected: true},
176		{name: "TestPHP_Not", path: "foo/FooTest.php", expected: false},
177		{name: "TestJava_Is_1", path: "test/FooTest.java", expected: true},
178		{name: "TestJava_Is_2", path: "test/FooTests.java", expected: true},
179		{name: "TestJava_Is_3", path: "test/TestFoo.java", expected: true},
180		{name: "TestJava_Is_4", path: "test/qux/TestFoo.java", expected: true},
181		{name: "TestJava_Not", path: "foo/FooTest.java", expected: false},
182		{name: "TestScala_Is_1", path: "test/FooTest.scala", expected: true},
183		{name: "TestScala_Is_2", path: "test/FooTests.scala", expected: true},
184		{name: "TestScala_Is_3", path: "test/FooSpec.scala", expected: true},
185		{name: "TestScala_Is_4", path: "test/qux/FooSpecs.scala", expected: true},
186		{name: "TestScala_Not", path: "foo/FooTest.scala", expected: false},
187		{name: "TestPython_Is", path: "test_foo.py", expected: true},
188		{name: "TestPython_Not", path: "foo_test.py", expected: false},
189		{name: "TestGo_Is", path: "foo_test.go", expected: true},
190		{name: "TestGo_Not", path: "test_foo.go", expected: false},
191		{name: "TestRuby_Is_1", path: "foo_test.rb", expected: true},
192		{name: "TestRuby_Is_1", path: "foo_spec.rb", expected: true},
193		{name: "TestRuby_Not", path: "foo_specs.rb", expected: false},
194		{name: "TestCSharp_Is_1", path: "FooTest.cs", expected: true},
195		{name: "TestCSharp_Is_2", path: "foo/FooTests.cs", expected: true},
196		{name: "TestCSharp_Not", path: "foo/TestFoo.cs", expected: false},
197		{name: "TestJavaScript_Is_1", path: "foo.test.js", expected: true},
198		{name: "TestJavaScript_Is_2", path: "foo.spec.js", expected: true},
199		{name: "TestJavaScript_Not", path: "footest.js", expected: false},
200		{name: "TestTypeScript_Is_1", path: "foo.test.ts", expected: true},
201		{name: "TestTypeScript_Is_2", path: "foo.spec.ts", expected: true},
202		{name: "TestTypeScript_Not", path: "footest.ts", expected: false},
203	}
204
205	for _, test := range tests {
206		is := IsTest(test.path)
207		assert.Equal(t, test.expected, is, fmt.Sprintf("%v: is = %v, expected: %v", test.name, is, test.expected))
208	}
209}
210
211func TestGetColor(t *testing.T) {
212	tests := []struct {
213		name     string
214		language string
215		expected string
216	}{
217		{name: "TestGetColor_1", language: "Go", expected: "#00ADD8"},
218		{name: "TestGetColor_2", language: "SomeRandom", expected: "#cccccc"},
219		{name: "TestGetColor_3", language: "HTML", expected: "#e34c26"},
220		{name: "TestGetColor_4", language: "HTML+PHP", expected: "#e34c26"},
221	}
222
223	for _, test := range tests {
224		color := GetColor(test.language)
225		assert.Equal(t, test.expected, color, fmt.Sprintf("%v: is = %v, expected: %v", test.name, color, test.expected))
226	}
227}
228
229func TestIsGenerated(t *testing.T) {
230	testCases := []struct {
231		file      string
232		load      bool
233		generated bool
234	}{
235		// Xcode project files
236		{"Binary/MainMenu.nib", false, true},
237		{"Dummy/foo.xcworkspacedata", false, true},
238		{"Dummy/foo.xcuserstate", false, true},
239
240		//Cocoapods
241		{"Pods/Pods.xcodeproj", false, true},
242		{"Pods/SwiftDependency/foo.swift", false, true},
243		{"Pods/ObjCDependency/foo.h", false, true},
244		{"Pods/ObjCDependency/foo.m", false, true},
245		{"Dummy/Pods/Pods.xcodeproj", false, true},
246		{"Dummy/Pods/SwiftDependency/foo.swift", false, true},
247		{"Dummy/Pods/ObjCDependency/foo.h", false, true},
248		{"Dummy/Pods/ObjCDependency/foo.m", false, true},
249
250		//Carthage
251		{"Carthage/Build/.Dependency.version", false, true},
252		{"Carthage/Build/iOS/Dependency.framework", false, true},
253		{"Carthage/Build/Mac/Dependency.framework", false, true},
254		{"src/Carthage/Build/.Dependency.version", false, true},
255		{"src/Carthage/Build/iOS/Dependency.framework", false, true},
256		{"src/Carthage/Build/Mac/Dependency.framework", false, true},
257
258		//Go-specific vendored paths
259		{"go/vendor/github.com/foo.go", false, true},
260		{"go/vendor/golang.org/src/foo.c", false, true},
261		{"go/vendor/gopkg.in/some/nested/path/foo.go", false, true},
262
263		//.NET designer file
264		{"Dummy/foo.designer.cs", false, true},
265		{"Dummy/foo.Designer.cs", false, true},
266		{"Dummy/foo.designer.vb", false, true},
267		{"Dummy/foo.Designer.vb", false, true},
268
269		//Composer generated composer.lock file
270		{"JSON/composer.lock", false, true},
271
272		//Node modules
273		{"Dummy/node_modules/foo.js", false, true},
274
275		//npm shrinkwrap file
276		{"Dummy/npm-shrinkwrap.json", false, true},
277		{"Dummy/package-lock.json", false, true},
278		{"JavaScript/jquery-1.6.1.min.js", true, true},
279
280		//Yarn Plug'n'Play file
281		{".pnp.js", false, true},
282		{".pnp.cjs", false, true},
283		{".pnp.mjs", false, true},
284
285		//Godep saved dependencies
286		{"Godeps/Godeps.json", false, true},
287		{"Godeps/_workspace/src/github.com/kr/s3/sign.go", false, true},
288
289		//Generated by Zephir
290		{"C/exception.zep.c", false, true},
291		{"C/exception.zep.h", false, true},
292		{"PHP/exception.zep.php", false, true},
293
294		//Minified files
295		{"JavaScript/jquery-1.6.1.min.js", true, true},
296
297		//JavaScript with source-maps
298		{"JavaScript/namespace.js", true, true},
299		{"Generated/inline.js", true, true},
300
301		//CSS with source-maps
302		{"Generated/linked.css", true, true},
303		{"Generated/inline.css", true, true},
304
305		//Source-map
306		{"Data/bootstrap.css.map", true, true},
307		{"Generated/linked.css.map", true, true},
308		{"Data/sourcemap.v3.map", true, true},
309		{"Data/sourcemap.v1.map", true, true},
310
311		//Specflow
312		{"Features/BindingCulture.feature.cs", false, true},
313
314		//JFlex
315		{"Java/JFlexLexer.java", true, true},
316
317		//GrammarKit
318		{"Java/GrammarKit.java", true, true},
319
320		//roxygen2
321		{"R/import.Rd", true, true},
322
323		//PostScript
324		{"PostScript/lambda.pfa", true, true},
325
326		//Perl ppport.h
327		{"Generated/ppport.h", true, true},
328
329		//Graphql Relay
330		{"Javascript/__generated__/App_user.graphql.js", false, true},
331
332		//Game Maker Studio 2
333		{"JSON/GMS2_Project.yyp", true, true},
334		{"JSON/2ea73365-b6f1-4bd1-a454-d57a67e50684.yy", true, true},
335		{"Generated/options_main.inherited.yy", true, true},
336
337		//Pipenv
338		{"Dummy/Pipfile.lock", false, true},
339
340		//HTML
341		{"HTML/attr-swapped.html", true, true},
342		{"HTML/extra-attr.html", true, true},
343		{"HTML/extra-spaces.html", true, true},
344		{"HTML/extra-tags.html", true, true},
345		{"HTML/grohtml.html", true, true},
346		{"HTML/grohtml.xhtml", true, true},
347		{"HTML/makeinfo.html", true, true},
348		{"HTML/mandoc.html", true, true},
349		{"HTML/node78.html", true, true},
350		{"HTML/org-mode.html", true, true},
351		{"HTML/quotes-double.html", true, true},
352		{"HTML/quotes-none.html", true, true},
353		{"HTML/quotes-single.html", true, true},
354		{"HTML/uppercase.html", true, true},
355		{"HTML/ronn.html", true, true},
356		{"HTML/unknown.html", true, false},
357		{"HTML/no-content.html", true, false},
358		{"HTML/pages.html", true, true},
359
360		//GIMP
361		{"C/image.c", true, true},
362		{"C/image.h", true, true},
363
364		//Haxe
365		{"Generated/Haxe/main.js", true, true},
366		{"Generated/Haxe/main.py", true, true},
367		{"Generated/Haxe/main.lua", true, true},
368		{"Generated/Haxe/Main.cpp", true, true},
369		{"Generated/Haxe/Main.h", true, true},
370		{"Generated/Haxe/Main.java", true, true},
371		{"Generated/Haxe/Main.cs", true, true},
372		{"Generated/Haxe/Main.php", true, true},
373	}
374
375	for _, tt := range testCases {
376		t.Run(tt.file, func(t *testing.T) {
377			var content []byte
378			if tt.load {
379				var err error
380				content, err = ioutil.ReadFile(filepath.Join("_testdata", tt.file))
381				require.NoError(t, err)
382			}
383
384			result := IsGenerated(tt.file, content)
385			require.Equal(t, tt.generated, result)
386		})
387	}
388}
389
390func TestFoo(t *testing.T) {
391	file := "HTML/uppercase.html"
392	content, err := ioutil.ReadFile("_testdata/" + file)
393	require.NoError(t, err)
394	require.True(t, IsGenerated(file, content))
395}
396