diff --git a/analyzer_test.go b/analyzer_test.go index 7804bba..6a0f25f 100644 --- a/analyzer_test.go +++ b/analyzer_test.go @@ -21,13 +21,13 @@ import ( "go/ast" "go/parser" "go/token" - "io/ioutil" "os" - "path" + "path/filepath" "testing" "time" goheader "github.com/denis-tingaikin/go-header" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -48,263 +48,218 @@ func header(header string) *goheader.Target { Path: os.TempDir(), } } -func TestAnalyzer_YearRangeValue_ShouldWorkWithComplexVariables(t *testing.T) { - var conf goheader.Configuration - var vals, err = conf.GetValues() - require.NoError(t, err) - vals["my-val"] = &goheader.RegexpValue{ - RawValue: "{{year-range }} B", - } - var a = goheader.New(goheader.WithTemplate("A {{ my-val }}"), goheader.WithValues(vals)) - require.Nil(t, a.Analyze(header(fmt.Sprintf("A 2000-%v B", time.Now().Year())))) -} -func TestAnalyzer_Analyze1(t *testing.T) { - a := goheader.New( - goheader.WithTemplate("A {{ YEAR }}\nB"), - goheader.WithValues(map[string]goheader.Value{ - "YEAR": &goheader.ConstValue{ - RawValue: "2020", - }, - })) - issue := a.Analyze(header(`A 2020 -B`)) - require.Nil(t, issue) -} - -func TestAnalyzer_Analyze2(t *testing.T) { - a := goheader.New( - goheader.WithTemplate("{{COPYRIGHT HOLDER}}TEXT"), - goheader.WithValues(map[string]goheader.Value{ - "COPYRIGHT HOLDER": &goheader.RegexpValue{ - RawValue: "(A {{ YEAR }}\n(.*)\n)+", - }, - "YEAR": &goheader.ConstValue{ - RawValue: "2020", - }, - })) - issue := a.Analyze(header(`A 2020 -B -A 2020 -B -TEXT -`)) - require.Nil(t, issue) -} - -func TestAnalyzer_Analyze3(t *testing.T) { - a := goheader.New( - goheader.WithTemplate("{{COPYRIGHT HOLDER}}TEXT"), - goheader.WithValues(map[string]goheader.Value{ - "COPYRIGHT HOLDER": &goheader.RegexpValue{ - RawValue: "(A {{ YEAR }}\n(.*)\n)+", - }, - "YEAR": &goheader.ConstValue{ - RawValue: "2020", - }, - })) - issue := a.Analyze(header(`A 2020 -B -A 2021 -B -TEXT -`)) - require.NotNil(t, issue) -} +func TestAnalyzer_Analyze(t *testing.T) { + testCases := []struct { + desc string + filename string + config string + assert assert.ValueAssertionFunc + }{ + { + desc: "const value", + filename: "constvalue/constvalue.go", + config: "constvalue/constvalue.yml", + assert: assert.Nil, + }, + { + desc: "regexp value", + filename: "regexpvalue/regexpvalue.go", + config: "regexpvalue/regexpvalue.yml", + assert: assert.Nil, + }, + { + desc: "regexp value with issue", + filename: "regexpvalue_issue/regexpvalue_issue.go", + config: "regexpvalue_issue/regexpvalue_issue.yml", + assert: assert.NotNil, + }, + { + desc: "nested values", + filename: "nestedvalues/nestedvalues.go", + config: "nestedvalues/nestedvalues.yml", + assert: assert.Nil, + }, + { + desc: "header comment", + filename: "headercomment/headercomment.go", + config: "headercomment/headercomment.yml", + assert: assert.Nil, + }, + { + desc: "readme", + filename: "readme/readme.go", + config: "readme/readme.yml", + assert: assert.Nil, + }, + } -func TestAnalyzer_Analyze4(t *testing.T) { - a := goheader.New( - goheader.WithTemplate("{{ A }}"), - goheader.WithValues(map[string]goheader.Value{ - "A": &goheader.RegexpValue{ - RawValue: "[{{ B }}{{ C }}]{{D}}", - }, - "B": &goheader.ConstValue{ - RawValue: "a-", - }, - "C": &goheader.RegexpValue{ - RawValue: "z", - }, - "D": &goheader.ConstValue{ - RawValue: "{{E}}", - }, - "E": &goheader.ConstValue{ - RawValue: "{7}", - }, - })) - issue := a.Analyze(header(`abcdefg`)) - require.Nil(t, issue) -} + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + cfg := &goheader.Configuration{} -func TestAnalyzer_Analyze5(t *testing.T) { - a := goheader.New(goheader.WithTemplate("abc")) - p := path.Join(os.TempDir(), t.Name()+".go") - defer func() { - _ = os.Remove(p) - }() - err := ioutil.WriteFile(p, []byte("/*abc*///comment\npackage abc"), os.ModePerm) - require.Nil(t, err) - s := token.NewFileSet() - f, err := parser.ParseFile(s, p, nil, parser.ParseComments) - require.Nil(t, err) - require.Nil(t, a.Analyze(&goheader.Target{File: f, Path: p})) -} + err := cfg.Parse(filepath.Join("testdata", test.config)) + require.NoError(t, err) -func TestREADME(t *testing.T) { - a := goheader.New( - goheader.WithTemplate(`{{ MY COMPANY }} -SPDX-License-Identifier: Apache-2.0 + values, err := cfg.GetValues() + require.NoError(t, err) -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at: + tmpl, err := cfg.GetTemplate() + require.NoError(t, err) - http://www.apache.org/licenses/LICENSE-2.0 + a := goheader.New( + goheader.WithValues(values), + goheader.WithTemplate(tmpl), + ) -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License.`), - goheader.WithValues(map[string]goheader.Value{ - "MY COMPANY": &goheader.ConstValue{ - RawValue: "mycompany.com", - }, - })) - issue := a.Analyze(header(`mycompany.com -SPDX-License-Identifier: Apache-2.0 + filename := filepath.Join("testdata", test.filename) -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at: + file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.ParseComments) + require.NoError(t, err) - http://www.apache.org/licenses/LICENSE-2.0 + issue := a.Analyze(&goheader.Target{Path: filename, File: file}) -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License.`)) - require.Nil(t, issue) + test.assert(t, issue) + }) + } } -func TestFix(t *testing.T) { - const pkg = ` - -// Package foo -package foo - -func Foo() { println("Foo") } -` - - analyze := func(header string) goheader.Issue { - a := goheader.New( - goheader.WithTemplate(`{{ MY COMPANY }} -SPDX-License-Identifier: Foo`), - goheader.WithValues(map[string]goheader.Value{ - "MY COMPANY": &goheader.ConstValue{ - RawValue: "mycompany.com", +func TestAnalyzer_Analyze_fix(t *testing.T) { + testCases := []struct { + desc string + filename string + config string + expected goheader.Fix + }{ + { + desc: "Line comment", + filename: "fix/linecomment.go", + config: "fix/fix.yml", + expected: goheader.Fix{ + Actual: []string{ + "// mycompany.net", + "// SPDX-License-Identifier: Foo", }, - })) - - fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "foo.go", header+pkg, parser.ParseComments) - require.NoError(t, err) - - issue := a.Analyze(&goheader.Target{ - File: file, - Path: t.TempDir(), - }) - require.NotNil(t, issue) - require.NotNil(t, issue.Fix()) - return issue + Expected: []string{ + "// mycompany.com", + "// SPDX-License-Identifier: Foo", + }, + }, + }, + { + desc: "Block comment 1", + filename: "fix/blockcomment1.go", + config: "fix/fix.yml", + expected: goheader.Fix{ + Actual: []string{ + "/* mycompany.net", + "SPDX-License-Identifier: Foo */", + }, + Expected: []string{ + "/* mycompany.com", + "SPDX-License-Identifier: Foo */", + }, + }, + }, + { + desc: "Block comment 2", + filename: "fix/blockcomment2.go", + config: "fix/fix.yml", + expected: goheader.Fix{ + Actual: []string{ + "/*", + "mycompany.net", + "SPDX-License-Identifier: Foo */", + }, + Expected: []string{ + "/*", + "mycompany.com", + "SPDX-License-Identifier: Foo */", + }, + }, + }, + { + desc: "Block comment 3", + filename: "fix/blockcomment3.go", + config: "fix/fix.yml", + expected: goheader.Fix{ + Actual: []string{ + "/* mycompany.net", + "SPDX-License-Identifier: Foo", + "*/", + }, + Expected: []string{ + "/* mycompany.com", + "SPDX-License-Identifier: Foo", + "*/", + }, + }, + }, + { + desc: "Block comment 4", + filename: "fix/blockcomment4.go", + config: "fix/fix.yml", + expected: goheader.Fix{ + Actual: []string{ + "/*", + "", + "mycompany.net", + "SPDX-License-Identifier: Foo", + "", + "*/", + }, + Expected: []string{ + "/*", + "", + "mycompany.com", + "SPDX-License-Identifier: Foo", + "", + "*/", + }, + }, + }, } - t.Run("Line comment", func(t *testing.T) { - issue := analyze(`// mycompany.net -// SPDX-License-Identifier: Foo`) + for _, test := range testCases { + t.Run(test.desc, func(t *testing.T) { + cfg := &goheader.Configuration{} - require.Equal(t, []string{ - "// mycompany.net", - "// SPDX-License-Identifier: Foo", - }, issue.Fix().Actual) - require.Equal(t, []string{ - "// mycompany.com", - "// SPDX-License-Identifier: Foo", - }, issue.Fix().Expected) - }) + err := cfg.Parse(filepath.Join("testdata", test.config)) + require.NoError(t, err) - t.Run("Block comment 1", func(t *testing.T) { - issue := analyze(`/* mycompany.net -SPDX-License-Identifier: Foo */`) + values, err := cfg.GetValues() + require.NoError(t, err) - require.Equal(t, []string{ - "/* mycompany.net", - "SPDX-License-Identifier: Foo */", - }, issue.Fix().Actual) - require.Equal(t, []string{ - "/* mycompany.com", - "SPDX-License-Identifier: Foo */", - }, issue.Fix().Expected) - }) + tmpl, err := cfg.GetTemplate() + require.NoError(t, err) - t.Run("Block comment 2", func(t *testing.T) { - issue := analyze(`/* -mycompany.net -SPDX-License-Identifier: Foo */`) + a := goheader.New( + goheader.WithValues(values), + goheader.WithTemplate(tmpl), + ) - require.Equal(t, []string{ - "/*", - "mycompany.net", - "SPDX-License-Identifier: Foo */", - }, issue.Fix().Actual) - require.Equal(t, []string{ - "/*", - "mycompany.com", - "SPDX-License-Identifier: Foo */", - }, issue.Fix().Expected) - }) + filename := filepath.Join("testdata", test.filename) - t.Run("Block comment 3", func(t *testing.T) { - issue := analyze(`/* mycompany.net -SPDX-License-Identifier: Foo -*/`) + file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.ParseComments) + require.NoError(t, err) - require.Equal(t, []string{ - "/* mycompany.net", - "SPDX-License-Identifier: Foo", - "*/", - }, issue.Fix().Actual) - require.Equal(t, []string{ - "/* mycompany.com", - "SPDX-License-Identifier: Foo", - "*/", - }, issue.Fix().Expected) - }) + issue := a.Analyze(&goheader.Target{Path: filename, File: file}) - t.Run("Block comment 4", func(t *testing.T) { - issue := analyze(`/* + assert.Equal(t, test.expected.Actual, issue.Fix().Actual) + assert.Equal(t, test.expected.Expected, issue.Fix().Expected) + }) + } +} -mycompany.net -SPDX-License-Identifier: Foo +func TestAnalyzer_YearRangeValue_ShouldWorkWithComplexVariables(t *testing.T) { + var conf goheader.Configuration + var vals, err = conf.GetValues() + require.NoError(t, err) -*/`) + vals["my-val"] = &goheader.RegexpValue{ + RawValue: "{{year-range }} B", + } - require.Equal(t, []string{ - "/*", - "", - "mycompany.net", - "SPDX-License-Identifier: Foo", - "", - "*/", - }, issue.Fix().Actual) - require.Equal(t, []string{ - "/*", - "", - "mycompany.com", - "SPDX-License-Identifier: Foo", - "", - "*/", - }, issue.Fix().Expected) - }) + var a = goheader.New(goheader.WithTemplate("A {{ my-val }}"), goheader.WithValues(vals)) + require.Nil(t, a.Analyze(header(fmt.Sprintf("A 2000-%v B", time.Now().Year())))) } diff --git a/config.go b/config.go index c881b63..8e0b7b2 100644 --- a/config.go +++ b/config.go @@ -29,7 +29,7 @@ import ( // Configuration represents go-header linter setup parameters type Configuration struct { // Values is map of values. Supports two types 'const` and `regexp`. Values can be used recursively. - Values map[string]map[string]string `yaml:"values"'` + Values map[string]map[string]string `yaml:"values"` // Template is template for checking. Uses values. Template string `yaml:"template"` // TemplatePath path to the template file. Useful if need to load the template from a specific file. diff --git a/testdata/constvalue/constvalue.go b/testdata/constvalue/constvalue.go new file mode 100644 index 0000000..2821a69 --- /dev/null +++ b/testdata/constvalue/constvalue.go @@ -0,0 +1,4 @@ +// A 2020 +// B + +package constvalue diff --git a/testdata/constvalue/constvalue.yml b/testdata/constvalue/constvalue.yml new file mode 100644 index 0000000..533edf0 --- /dev/null +++ b/testdata/constvalue/constvalue.yml @@ -0,0 +1,8 @@ +template: |- + A {{ YEAR }} + B + +values: + const: + 'YEAR': '2020' + diff --git a/testdata/fix/blockcomment1.go b/testdata/fix/blockcomment1.go new file mode 100644 index 0000000..d3c58d0 --- /dev/null +++ b/testdata/fix/blockcomment1.go @@ -0,0 +1,7 @@ +/* mycompany.net +SPDX-License-Identifier: Foo */ + +// Package foo +package foo + +func _() { println("Foo") } diff --git a/testdata/fix/blockcomment2.go b/testdata/fix/blockcomment2.go new file mode 100644 index 0000000..b81e13b --- /dev/null +++ b/testdata/fix/blockcomment2.go @@ -0,0 +1,8 @@ +/* +mycompany.net +SPDX-License-Identifier: Foo */ + +// Package foo +package foo + +func _() { println("Foo") } diff --git a/testdata/fix/blockcomment3.go b/testdata/fix/blockcomment3.go new file mode 100644 index 0000000..c6976cf --- /dev/null +++ b/testdata/fix/blockcomment3.go @@ -0,0 +1,8 @@ +/* mycompany.net +SPDX-License-Identifier: Foo +*/ + +// Package foo +package foo + +func _() { println("Foo") } diff --git a/testdata/fix/blockcomment4.go b/testdata/fix/blockcomment4.go new file mode 100644 index 0000000..1cba8c8 --- /dev/null +++ b/testdata/fix/blockcomment4.go @@ -0,0 +1,11 @@ +/* + +mycompany.net +SPDX-License-Identifier: Foo + +*/ + +// Package foo +package foo + +func _() { println("Foo") } diff --git a/testdata/fix/fix.yml b/testdata/fix/fix.yml new file mode 100644 index 0000000..264e7b4 --- /dev/null +++ b/testdata/fix/fix.yml @@ -0,0 +1,8 @@ +template: |- + {{ MY COMPANY }} + SPDX-License-Identifier: Foo + +values: + const: + 'MY COMPANY': 'mycompany.com' + diff --git a/testdata/fix/linecomment.go b/testdata/fix/linecomment.go new file mode 100644 index 0000000..c0625f6 --- /dev/null +++ b/testdata/fix/linecomment.go @@ -0,0 +1,7 @@ +// mycompany.net +// SPDX-License-Identifier: Foo + +// Package foo +package foo + +func _() { println("Foo") } diff --git a/testdata/headercomment/headercomment.go b/testdata/headercomment/headercomment.go new file mode 100644 index 0000000..023b771 --- /dev/null +++ b/testdata/headercomment/headercomment.go @@ -0,0 +1,3 @@ +/*abc*/ // comment + +package headercomment diff --git a/testdata/headercomment/headercomment.yml b/testdata/headercomment/headercomment.yml new file mode 100644 index 0000000..dc06b76 --- /dev/null +++ b/testdata/headercomment/headercomment.yml @@ -0,0 +1 @@ +template: abc diff --git a/testdata/nestedvalues/nestedvalues.go b/testdata/nestedvalues/nestedvalues.go new file mode 100644 index 0000000..40de6f6 --- /dev/null +++ b/testdata/nestedvalues/nestedvalues.go @@ -0,0 +1,3 @@ +// abcdefg + +package nestedvalues diff --git a/testdata/nestedvalues/nestedvalues.yml b/testdata/nestedvalues/nestedvalues.yml new file mode 100644 index 0000000..bed8105 --- /dev/null +++ b/testdata/nestedvalues/nestedvalues.yml @@ -0,0 +1,10 @@ +template: '{{ A }}' + +values: + regexp: + 'A': '[{{ B }}{{ C }}]{{D}}' + const: + 'B': 'a-' + 'C': 'z' + 'D': '{{E}}' + 'E': '{7}' diff --git a/testdata/readme/readme.go b/testdata/readme/readme.go new file mode 100644 index 0000000..f89b236 --- /dev/null +++ b/testdata/readme/readme.go @@ -0,0 +1,16 @@ +// mycompany.com +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package readme diff --git a/testdata/readme/readme.yml b/testdata/readme/readme.yml new file mode 100644 index 0000000..aca0e60 --- /dev/null +++ b/testdata/readme/readme.yml @@ -0,0 +1,18 @@ +values: + const: + MY COMPANY: mycompany.com +template: |- + {{ MY COMPANY }} + SPDX-License-Identifier: Apache-2.0 + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/testdata/regexpvalue/regexpvalue.go b/testdata/regexpvalue/regexpvalue.go new file mode 100644 index 0000000..5d595f1 --- /dev/null +++ b/testdata/regexpvalue/regexpvalue.go @@ -0,0 +1,7 @@ +// A 2020 +// B +// A 2020 +// B +// TEXT + +package regexpvalue diff --git a/testdata/regexpvalue/regexpvalue.yml b/testdata/regexpvalue/regexpvalue.yml new file mode 100644 index 0000000..555bc0d --- /dev/null +++ b/testdata/regexpvalue/regexpvalue.yml @@ -0,0 +1,11 @@ +template: |- + {{COPYRIGHT HOLDER}}TEXT + +values: + const: + 'YEAR': '2020' + regexp: + 'COPYRIGHT HOLDER': |- + (A {{ YEAR }} + (.*) + )+ diff --git a/testdata/regexpvalue_issue/regexpvalue_issue.go b/testdata/regexpvalue_issue/regexpvalue_issue.go new file mode 100644 index 0000000..2ae32b9 --- /dev/null +++ b/testdata/regexpvalue_issue/regexpvalue_issue.go @@ -0,0 +1,7 @@ +// A 2020 +// B +// A 2021 +// B +// TEXT + +package regexpvalue diff --git a/testdata/regexpvalue_issue/regexpvalue_issue.yml b/testdata/regexpvalue_issue/regexpvalue_issue.yml new file mode 100644 index 0000000..555bc0d --- /dev/null +++ b/testdata/regexpvalue_issue/regexpvalue_issue.yml @@ -0,0 +1,11 @@ +template: |- + {{COPYRIGHT HOLDER}}TEXT + +values: + const: + 'YEAR': '2020' + regexp: + 'COPYRIGHT HOLDER': |- + (A {{ YEAR }} + (.*) + )+