This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch enhance
in repository https://gitbox.apache.org/repos/asf/skywalking-eyes.git

commit 03d5afbb89e24a98c6082295eb18f2c056502fdf
Author: kezhenxu94 <[email protected]>
AuthorDate: Tue Dec 22 18:12:07 2020 +0800

    Enhance checking/fixing command, more tests, more comment styles
    
    - `fix` command should properly tackle shebang and xml declaration;
    - Add more known comment styles;
    - Add more test cases;
    - Support checking a single file for debugging;
---
 .github/workflows/license-eye-check.yaml           |   3 +
 .gitignore                                         |   1 +
 .golangci.yml                                      |   2 +-
 license-eye/Makefile                               |   3 +-
 license-eye/assets/languages.yaml                  |   8 +
 license-eye/assets/styles.yaml                     |  31 ++-
 license-eye/commands/header/check.go               |   5 +
 license-eye/internal/logger/log.go                 |   2 +-
 license-eye/pkg/comments/config.go                 |  11 +-
 license-eye/pkg/config/{Config.go => config.go}    |   0
 license-eye/pkg/header/check.go                    |  13 +-
 license-eye/pkg/header/check_test.go               | 143 +++++++++++++
 license-eye/pkg/header/config.go                   |  14 +-
 license-eye/pkg/header/fix.go                      |  28 ++-
 license-eye/pkg/header/fix_test.go                 | 236 ++++++++++++++++-----
 .../test/testdata/.licenserc_for_test_check.yaml   |   2 +-
 .../test/testdata/.licenserc_for_test_fix.yaml     |   2 +-
 .../testdata/include_test/with_license/testcase.go |   3 +-
 .../include_test/with_license/testcase.java        |  11 +-
 .../testdata/include_test/with_license/testcase.ml |  19 ++
 .../include_test/without_license/testcase.py       |   1 +
 21 files changed, 441 insertions(+), 97 deletions(-)

diff --git a/.github/workflows/license-eye-check.yaml 
b/.github/workflows/license-eye-check.yaml
index cd40f8c..2bcfd23 100644
--- a/.github/workflows/license-eye-check.yaml
+++ b/.github/workflows/license-eye-check.yaml
@@ -50,3 +50,6 @@ jobs:
 
       - name: Build
         run: make build
+
+      - name: Build Docker Image
+        run: make docker
diff --git a/.gitignore b/.gitignore
index a559c8f..a90f1dd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@
 bin/
 license-eye/assets/assets.gen.go
 .DS_Store
+coverage.txt
diff --git a/.golangci.yml b/.golangci.yml
index ca0227f..f4a7795 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -51,7 +51,7 @@ linters-settings:
     disabled-checks:
       - ifElseChain
   funlen:
-    lines: 100
+    lines: 150
     statements: 50
   whitespace:
     multi-if: false
diff --git a/license-eye/Makefile b/license-eye/Makefile
index 0629e37..09f9fca 100644
--- a/license-eye/Makefile
+++ b/license-eye/Makefile
@@ -61,7 +61,7 @@ codegen: clean
 
 .PHONY: test
 test: clean codegen
-       $(GO_TEST) ./...
+       $(GO_TEST) ./... -coverprofile=coverage.txt -covermode=atomic
        @>&2 echo "Great, all tests passed."
 
 .PHONY: $(PLATFORMS)
@@ -80,3 +80,4 @@ docker:
 clean:
        -rm -rf bin
        -rm -rf assets/*.gen.go
+       -rm -rf coverage.txt
diff --git a/license-eye/assets/languages.yaml 
b/license-eye/assets/languages.yaml
index e4af70e..6a249db 100644
--- a/license-eye/assets/languages.yaml
+++ b/license-eye/assets/languages.yaml
@@ -2232,6 +2232,7 @@ Haskell:
   codemirror_mode: haskell
   codemirror_mime_type: text/x-haskell
   language_id: 157
+  comment_style_id: CurlyBracketDash
 Haxe:
   type: programming
   ace_mode: haxe
@@ -3708,6 +3709,7 @@ OCaml:
     - ocamlscript
   tm_scope: source.ocaml
   language_id: 255
+  comment_style_id: RoundBracketAsterisk
 ObjDump:
   type: data
   extensions:
@@ -3977,6 +3979,7 @@ PLSQL:
     - ".trg"
     - ".vw"
   language_id: 273
+  comment_style_id: DoubleDash
 PLpgSQL:
   type: programming
   ace_mode: pgsql
@@ -3987,6 +3990,7 @@ PLpgSQL:
     - ".pgsql"
     - ".sql"
   language_id: 274
+  comment_style_id: DoubleDash
 POV-Ray SDL:
   type: programming
   aliases:
@@ -5026,6 +5030,7 @@ SQL:
     - ".udf"
     - ".viw"
   language_id: 333
+  comment_style_id: DoubleDash
 SQLPL:
   type: programming
   ace_mode: sql
@@ -5036,6 +5041,7 @@ SQLPL:
     - ".sql"
     - ".db2"
   language_id: 334
+  comment_style_id: DoubleDash
 SRecode Template:
   type: markup
   color: "#348a34"
@@ -5549,6 +5555,7 @@ TSQL:
   ace_mode: sql
   tm_scope: source.tsql
   language_id: 918334941
+  comment_style_id: DoubleDash
 TSV:
   type: data
   ace_mode: text
@@ -5969,6 +5976,7 @@ Vim script:
     - vimrc
   ace_mode: text
   language_id: 388
+  comment_style_id: Quotes
 Visual Basic .NET:
   type: programming
   color: "#945db7"
diff --git a/license-eye/assets/styles.yaml b/license-eye/assets/styles.yaml
index deb64a5..216232f 100644
--- a/license-eye/assets/styles.yaml
+++ b/license-eye/assets/styles.yaml
@@ -18,16 +18,17 @@
 
 - id: DoubleSlash
   start: '//'
-  middle: ~
-  end: ~
+  middle: '//'
+  end: '//'
 
 - id: Hashtag
+  after: '(?m)^*#!.+$'
   start: '#'
-  middle: ~
-  end: ~
-  skip: '^#!'
+  middle: '#'
+  end: '#'
 
 - id: AngleBracket
+  after: '(?ms)^<\?.+?\?>$'
   start: '<!--'
   middle: '  ~'
   end: '-->'
@@ -38,3 +39,23 @@
   middle: ' *'          # <2>
   end: ' */'            # <3>
 # end::SlashAsterisk[]
+
+- id: RoundBracketAsterisk
+  start: '(*'
+  middle: '(*'
+  end: '(*'
+
+- id: CurlyBracketDash
+  start: '{-'
+  middle: ~
+  end: '-}'
+
+- id: DoubleDash
+  start: '--'
+  middle: '--'
+  end: '--'
+
+- id: Quotes
+  start: '"'
+  middle: '"'
+  end: '"'
diff --git a/license-eye/commands/header/check.go 
b/license-eye/commands/header/check.go
index 1de9115..c349ace 100644
--- a/license-eye/commands/header/check.go
+++ b/license-eye/commands/header/check.go
@@ -37,6 +37,11 @@ var CheckCommand = &cobra.Command{
                        return err
                }
 
+               if len(args) > 0 {
+                       logger.Log.Debugln("Overriding paths with command line 
args.")
+                       config.Header.Paths = args
+               }
+
                if err := header.Check(&config.Header, &result); err != nil {
                        return err
                }
diff --git a/license-eye/internal/logger/log.go 
b/license-eye/internal/logger/log.go
index 7fc102e..1c641e8 100644
--- a/license-eye/internal/logger/log.go
+++ b/license-eye/internal/logger/log.go
@@ -29,7 +29,7 @@ func init() {
        if Log == nil {
                Log = logrus.New()
        }
-       Log.Level = logrus.DebugLevel
+       Log.Level = logrus.InfoLevel
        Log.SetOutput(os.Stdout)
        Log.SetFormatter(&logrus.TextFormatter{
                DisableTimestamp:       true,
diff --git a/license-eye/pkg/comments/config.go 
b/license-eye/pkg/comments/config.go
index 8b2db6f..28f4462 100644
--- a/license-eye/pkg/comments/config.go
+++ b/license-eye/pkg/comments/config.go
@@ -27,6 +27,7 @@ import (
 
 type CommentStyle struct {
        ID     string `yaml:"id"`
+       After  string `yaml:"after"`
        Start  string `yaml:"start"`
        Middle string `yaml:"middle"`
        End    string `yaml:"end"`
@@ -39,15 +40,6 @@ func (style *CommentStyle) Validate() error {
        return nil
 }
 
-func (style *CommentStyle) Finalize() {
-       if style.Middle == "" {
-               style.Middle = style.Start
-       }
-       if style.End == "" {
-               style.End = style.Start
-       }
-}
-
 type Language struct {
        Type           string   `yaml:"type"`
        Extensions     []string `yaml:"extensions"`
@@ -107,7 +99,6 @@ func initCommentStyles() {
        }
 
        for _, style := range styles {
-               style.Finalize()
                comments[style.ID] = style
        }
 }
diff --git a/license-eye/pkg/config/Config.go b/license-eye/pkg/config/config.go
similarity index 100%
rename from license-eye/pkg/config/Config.go
rename to license-eye/pkg/config/config.go
diff --git a/license-eye/pkg/header/check.go b/license-eye/pkg/header/check.go
index a0541e6..af187a0 100644
--- a/license-eye/pkg/header/check.go
+++ b/license-eye/pkg/header/check.go
@@ -29,7 +29,7 @@ import (
        "github.com/bmatcuk/doublestar/v2"
 )
 
-const CommentChars = "/*#- !~'\"(){}"
+var Punctuations = regexp.MustCompile("[\\[\\]/*:;\\s#\\-!~'\"(){}?]+") // 
TODO: also trim stop words
 
 // Check checks the license headers of the specified paths/globs.
 func Check(config *ConfigHeader, result *Result) error {
@@ -111,28 +111,29 @@ func CheckFile(file string, config *ConfigHeader, result 
*Result) error {
        reader, err := os.Open(file)
 
        if err != nil {
-               return nil
+               return err
        }
 
        var lines []string
 
        scanner := bufio.NewScanner(reader)
        for scanner.Scan() {
-               line := strings.ToLower(strings.Trim(scanner.Text(), 
CommentChars))
-               line = regexp.MustCompile("[ '\"]+").ReplaceAllString(line, " ")
+               line := 
strings.ToLower(Punctuations.ReplaceAllString(scanner.Text(), " "))
                if len(line) > 0 {
                        lines = append(lines, line)
                }
        }
 
-       content := strings.Join(lines, " ")
+       content := Punctuations.ReplaceAllString(strings.Join(lines, " "), " ")
        license, pattern := config.NormalizedLicense(), 
config.NormalizedPattern()
 
        if strings.Contains(content, license) || (pattern != nil && 
pattern.MatchString(content)) {
                result.Succeed(file)
        } else {
                logger.Log.Debugln("Content is:", content)
-               logger.Log.Debugln("Pattern is:", pattern)
+               if pattern != nil {
+                       logger.Log.Debugln("Pattern is:", pattern)
+               }
 
                result.Fail(file)
        }
diff --git a/license-eye/pkg/header/check_test.go 
b/license-eye/pkg/header/check_test.go
new file mode 100644
index 0000000..2cc2de7
--- /dev/null
+++ b/license-eye/pkg/header/check_test.go
@@ -0,0 +1,143 @@
+//
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you 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
+//
+//     http://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 header
+
+import (
+       "io/ioutil"
+       "path/filepath"
+       "strings"
+       "testing"
+
+       "gopkg.in/yaml.v3"
+)
+
+var c struct {
+       Header ConfigHeader `yaml:"header"`
+}
+
+func init() {
+       content, err := 
ioutil.ReadFile("../../test/testdata/.licenserc_for_test_check.yaml")
+       if err != nil {
+               panic(err)
+       }
+       if err := yaml.Unmarshal(content, &c); err != nil {
+               panic(err)
+       }
+       if err := c.Header.Finalize(); err != nil {
+               panic(err)
+       }
+}
+
+func TestCheckFile(t *testing.T) {
+       type args struct {
+               name       string
+               file       string
+               result     *Result
+               wantErr    bool
+               hasFailure bool
+       }
+       tests := func() []args {
+               files, err := 
filepath.Glob("../../test/testdata/include_test/with_license/*")
+               if err != nil {
+                       t.Error(err)
+               }
+
+               var cases []args
+
+               for _, file := range files {
+                       cases = append(cases, args{
+                               name:       file,
+                               file:       file,
+                               result:     &Result{},
+                               wantErr:    false,
+                               hasFailure: false,
+                       })
+               }
+
+               return cases
+       }()
+
+       if len(tests) == 0 {
+               t.Errorf("Tests should not be empty")
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if strings.TrimSpace(c.Header.License) == "" {
+                               t.Errorf("License should not be empty")
+                       }
+                       if err := CheckFile(tt.file, &c.Header, tt.result); 
(err != nil) != tt.wantErr {
+                               t.Errorf("CheckFile() error = %v, wantErr %v", 
err, tt.wantErr)
+                       }
+                       if len(tt.result.Ignored) > 0 {
+                               t.Errorf("Should not ignore any file, %v", 
tt.result.Ignored)
+                       }
+                       if tt.result.HasFailure() != tt.hasFailure {
+                               t.Errorf("CheckFile() result has failure = %v, 
wanted = %v", tt.result.Failure, tt.hasFailure)
+                       }
+               })
+       }
+}
+
+func TestCheckFileFailure(t *testing.T) {
+       type args struct {
+               name       string
+               file       string
+               result     *Result
+               wantErr    bool
+               hasFailure bool
+       }
+       tests := func() []args {
+               files, err := 
filepath.Glob("../../test/testdata/include_test/without_license/*")
+               if err != nil {
+                       panic(err)
+               }
+
+               var cases []args
+
+               for _, file := range files {
+                       cases = append(cases, args{
+                               name:       file,
+                               file:       file,
+                               result:     &Result{},
+                               wantErr:    false,
+                               hasFailure: true,
+                       })
+               }
+
+               return cases
+       }()
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if strings.TrimSpace(c.Header.License) == "" {
+                               t.Errorf("License should not be empty")
+                       }
+                       if err := CheckFile(tt.file, &c.Header, tt.result); 
(err != nil) != tt.wantErr {
+                               t.Errorf("CheckFile() error = %v, wantErr %v", 
err, tt.wantErr)
+                       }
+                       if len(tt.result.Ignored) > 0 {
+                               t.Errorf("Should not ignore any file, %v", 
tt.result.Ignored)
+                       }
+                       if tt.result.HasFailure() != tt.hasFailure {
+                               t.Errorf("CheckFile() result has failure = %v, 
wanted = %v", tt.result.Failure, tt.hasFailure)
+                       }
+               })
+       }
+}
diff --git a/license-eye/pkg/header/config.go b/license-eye/pkg/header/config.go
index 0293d1f..82f4361 100644
--- a/license-eye/pkg/header/config.go
+++ b/license-eye/pkg/header/config.go
@@ -36,17 +36,15 @@ type ConfigHeader struct {
 }
 
 // NormalizedLicense returns the normalized string of the license content,
-// "normalized" means the linebreaks and CommentChars are all trimmed.
+// "normalized" means the linebreaks and Punctuations are all trimmed.
 func (config *ConfigHeader) NormalizedLicense() string {
        var lines []string
        for _, line := range strings.Split(config.License, "\n") {
                if len(line) > 0 {
-                       line = strings.ToLower(strings.Trim(line, CommentChars))
-                       line = regexp.MustCompile(" +").ReplaceAllString(line, 
" ")
-                       lines = append(lines, line)
+                       lines = append(lines, 
Punctuations.ReplaceAllString(line, " "))
                }
        }
-       return strings.Join(lines, " ")
+       return 
strings.ToLower(regexp.MustCompile("(?m)[\\s\"']+").ReplaceAllString(strings.Join(lines,
 " "), " "))
 }
 
 func (config *ConfigHeader) NormalizedPattern() *regexp.Regexp {
@@ -57,11 +55,11 @@ func (config *ConfigHeader) NormalizedPattern() 
*regexp.Regexp {
        var lines []string
        for _, line := range strings.Split(config.Pattern, "\n") {
                if len(line) > 0 {
-                       line = regexp.MustCompile("[ 
\"']+").ReplaceAllString(line, " ")
-                       lines = append(lines, strings.TrimSpace(line))
+                       lines = append(lines, line)
                }
        }
-       return regexp.MustCompile("(?i).*" + strings.Join(lines, " ") + ".*")
+       content := 
regexp.MustCompile("(?m)[\\s\"':;/\\-]+").ReplaceAllString(strings.Join(lines, 
" "), " ")
+       return regexp.MustCompile("(?i).*" + content + ".*")
 }
 
 // Parse reads and parses the header check configurations in config file.
diff --git a/license-eye/pkg/header/fix.go b/license-eye/pkg/header/fix.go
index a710106..40acde7 100644
--- a/license-eye/pkg/header/fix.go
+++ b/license-eye/pkg/header/fix.go
@@ -22,6 +22,7 @@ import (
        "fmt"
        "io/ioutil"
        "os"
+       "regexp"
        "strings"
 
        "github.com/apache/skywalking-eyes/license-eye/internal/logger"
@@ -60,12 +61,14 @@ func InsertComment(file string, style 
*comments.CommentStyle, config *ConfigHead
                return err
        }
 
-       lines, err := generateLicenseHeader(style, config)
+       licenseHeader, err := generateLicenseHeader(style, config)
        if err != nil {
                return err
        }
 
-       if err := ioutil.WriteFile(file, append([]byte(lines), content...), 
stat.Mode()); err != nil {
+       content = rewriteContent(style, content, licenseHeader)
+
+       if err := ioutil.WriteFile(file, content, stat.Mode()); err != nil {
                return err
        }
 
@@ -74,7 +77,22 @@ func InsertComment(file string, style 
*comments.CommentStyle, config *ConfigHead
        return nil
 }
 
-// TODO: tackle with shebang and xml declaration
+func rewriteContent(style *comments.CommentStyle, content []byte, 
licenseHeader string) []byte {
+       if style.After == "" {
+               return append([]byte(licenseHeader), content...)
+       }
+
+       content = []byte(strings.TrimLeft(string(content), " \n"))
+       afterPattern := regexp.MustCompile(style.After)
+       location := afterPattern.FindIndex(content)
+       if location == nil || len(location) != 2 {
+               return append([]byte(licenseHeader), content...)
+       }
+       return append(content[0:location[1]],
+               append(append([]byte("\n"), []byte(licenseHeader)...), 
content[location[1]+1:]...)...,
+       )
+}
+
 func generateLicenseHeader(style *comments.CommentStyle, config *ConfigHeader) 
(string, error) {
        if err := style.Validate(); err != nil {
                return "", err
@@ -82,7 +100,7 @@ func generateLicenseHeader(style *comments.CommentStyle, 
config *ConfigHeader) (
 
        middleLines := strings.Split(config.License, "\n")
        for i, line := range middleLines {
-               middleLines[i] = fmt.Sprintf("%v %v", style.Middle, line)
+               middleLines[i] = strings.TrimRight(fmt.Sprintf("%v %v", 
style.Middle, line), " ")
        }
 
        lines := fmt.Sprintf("%v\n%v\n", style.Start, strings.Join(middleLines, 
"\n"))
@@ -90,5 +108,5 @@ func generateLicenseHeader(style *comments.CommentStyle, 
config *ConfigHeader) (
                lines += style.End
        }
 
-       return lines, nil
+       return strings.TrimSpace(lines) + "\n", nil
 }
diff --git a/license-eye/pkg/header/fix_test.go 
b/license-eye/pkg/header/fix_test.go
index a3ea449..c6f307f 100644
--- a/license-eye/pkg/header/fix_test.go
+++ b/license-eye/pkg/header/fix_test.go
@@ -1,85 +1,63 @@
+//
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you 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
+//
+//     http://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 header
 
 import (
+       "reflect"
        "testing"
 
        "github.com/apache/skywalking-eyes/license-eye/pkg/comments"
 )
 
 var config = &ConfigHeader{
-       License: `
-Licensed to Apache Software Foundation (ASF) under one or more
-contributor license agreements. See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-Apache Software Foundation (ASF) licenses this file to you 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
-
- http://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.
-`,
+       License: `Apache License 2.0
+  http://www.apache.org/licenses/LICENSE-2.0
+Apache License 2.0`,
 }
 
-func Test(t *testing.T) {
+func TestFix(t *testing.T) {
        tests := []struct {
                filename string
                comments string
        }{
                {
                        filename: "Test.java",
-                       comments: `/* 
- * Licensed to Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * Apache Software Foundation (ASF) licenses this file to you 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
- * 
- *  http://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.
- * 
+                       comments: `/*
+ * Apache License 2.0
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * Apache License 2.0
  */
 `,
                },
                {
                        filename: "Test.py",
                        comments: `#
-# Licensed to Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# Apache Software Foundation (ASF) licenses this file to you 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
-# 
-#  http://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.
-# 
-#
+# Apache License 2.0
+#   http://www.apache.org/licenses/LICENSE-2.0
+# Apache License 2.0
 `,
                },
        }
        for _, test := range tests {
                t.Run(test.filename, func(t *testing.T) {
                        style := comments.FileCommentStyle(test.filename)
-                       if c, err := generateLicenseHeader(style, config); err 
!= nil && c != test.comments {
+                       if c, err := generateLicenseHeader(style, config); err 
!= nil || c != test.comments {
                                t.Log("Actual:", c)
                                t.Log("Expected:", test.comments)
                                t.Logf("Middle:'%v'\n", style.Middle)
@@ -89,3 +67,155 @@ func Test(t *testing.T) {
                })
        }
 }
+
+func TestRewriteContent(t *testing.T) {
+       tests := []struct {
+               name            string
+               style           *comments.CommentStyle
+               content         string
+               licenseHeader   string
+               expectedContent string
+       }{
+               {
+                       name:  "Ocaml",
+                       style: comments.FileCommentStyle("test.ml"),
+                       content: `print_string "hello worlds!\n";;
+`,
+                       licenseHeader: getLicenseHeader("test.ml", t.Error),
+                       expectedContent: `(*
+(* Apache License 2.0
+(*   http://www.apache.org/licenses/LICENSE-2.0
+(* Apache License 2.0
+print_string "hello worlds!\n";;
+`},
+               {
+                       name:  "Python with Shebang",
+                       style: comments.FileCommentStyle("test.py"),
+                       content: `
+#!/usr/bin/env python3
+if __name__ == '__main__':
+    print('Hello World')
+`,
+                       licenseHeader: getLicenseHeader("test.py", t.Error),
+                       expectedContent: `#!/usr/bin/env python3
+#
+# Apache License 2.0
+#   http://www.apache.org/licenses/LICENSE-2.0
+# Apache License 2.0
+if __name__ == '__main__':
+    print('Hello World')
+`},
+               {
+                       name:  "Python",
+                       style: comments.FileCommentStyle("test.py"),
+                       content: `
+if __name__ == '__main__':
+    print('Hello World')
+`,
+                       licenseHeader: getLicenseHeader("test.py", t.Error),
+                       expectedContent: `#
+# Apache License 2.0
+#   http://www.apache.org/licenses/LICENSE-2.0
+# Apache License 2.0
+if __name__ == '__main__':
+    print('Hello World')
+`},
+               {
+                       name:  "XML one line declaration",
+                       style: comments.FileCommentStyle("test.xml"),
+                       content: `
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+  <modelVersion>4.0.0</modelVersion>
+</project>
+`,
+                       licenseHeader: getLicenseHeader("test.xml", t.Error),
+                       expectedContent: `<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Apache License 2.0
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~ Apache License 2.0
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+</project>
+`},
+               {
+                       name:  "XML multi-line declaration",
+                       style: comments.FileCommentStyle("test.xml"),
+                       content: `
+<?xml
+  version="1.0"
+  encoding="UTF-8"
+?>
+<project>
+  <modelVersion>4.0.0</modelVersion>
+</project>
+`,
+                       licenseHeader: getLicenseHeader("test.xml", t.Error),
+                       expectedContent: `<?xml
+  version="1.0"
+  encoding="UTF-8"
+?>
+<!--
+  ~ Apache License 2.0
+  ~   http://www.apache.org/licenses/LICENSE-2.0
+  ~ Apache License 2.0
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+</project>
+`},
+               {
+                       name:          "SQL",
+                       style:         comments.FileCommentStyle("test.sql"),
+                       content:       `select * from user;`,
+                       licenseHeader: getLicenseHeader("test.sql", t.Error),
+                       expectedContent: `--
+-- Apache License 2.0
+--   http://www.apache.org/licenses/LICENSE-2.0
+-- Apache License 2.0
+select * from user;`},
+               {
+                       name:          "Haskell",
+                       style:         comments.FileCommentStyle("test.hs"),
+                       content:       `import Foundation.Hashing.Hashable`,
+                       licenseHeader: getLicenseHeader("test.hs", t.Error),
+                       expectedContent: `{-
+ Apache License 2.0
+   http://www.apache.org/licenses/LICENSE-2.0
+ Apache License 2.0
+-}
+import Foundation.Hashing.Hashable`},
+               {
+                       name:  "Vim",
+                       style: comments.FileCommentStyle("test.vim"),
+                       content: `echo 'Hello' | echo 'world!'
+`,
+                       licenseHeader: getLicenseHeader("test.vim", t.Error),
+                       expectedContent: `"
+" Apache License 2.0
+"   http://www.apache.org/licenses/LICENSE-2.0
+" Apache License 2.0
+echo 'Hello' | echo 'world!'
+`},
+       }
+       for _, test := range tests {
+               t.Run(test.name, func(t *testing.T) {
+                       content := rewriteContent(test.style, 
[]byte(test.content), test.licenseHeader)
+                       if !reflect.DeepEqual(content, 
[]byte(test.expectedContent)) {
+                               t.Log("Actual\n" + string(content))
+                               t.Log("Expected\n" + test.expectedContent)
+                               t.Fail()
+                       }
+               })
+       }
+}
+
+func getLicenseHeader(filename string, tError func(args ...interface{})) 
string {
+       s, err := generateLicenseHeader(comments.FileCommentStyle(filename), 
config)
+       if err != nil {
+               tError(err)
+       }
+       return s
+}
diff --git a/license-eye/test/testdata/.licenserc_for_test_check.yaml 
b/license-eye/test/testdata/.licenserc_for_test_check.yaml
index 1ae329e..eee7d39 100644
--- a/license-eye/test/testdata/.licenserc_for_test_check.yaml
+++ b/license-eye/test/testdata/.licenserc_for_test_check.yaml
@@ -18,7 +18,7 @@ header:
     under the License.
 
   paths:
-    - 'testdata/**'
+    - 'test/testdata/**'
 
   paths-ignore:
     - '**/.DS_Store'
diff --git a/license-eye/test/testdata/.licenserc_for_test_fix.yaml 
b/license-eye/test/testdata/.licenserc_for_test_fix.yaml
index 008e9f4..facb12f 100644
--- a/license-eye/test/testdata/.licenserc_for_test_fix.yaml
+++ b/license-eye/test/testdata/.licenserc_for_test_fix.yaml
@@ -18,7 +18,7 @@ header:
     under the License.
 
   paths:
-    - 'testdata/include_test/**'
+    - 'test/testdata/include_test/**'
 
   paths-ignore:
     - '**/.DS_Store'
diff --git a/license-eye/test/testdata/include_test/with_license/testcase.go 
b/license-eye/test/testdata/include_test/with_license/testcase.go
index c382b60..9b47627 100644
--- a/license-eye/test/testdata/include_test/with_license/testcase.go
+++ b/license-eye/test/testdata/include_test/with_license/testcase.go
@@ -2,7 +2,8 @@
 // license agreements. See the NOTICE file distributed with
 // this work for additional information regarding copyright
 // ownership. Apache Software Foundation (ASF) licenses this file to you under
-// the Apache License, Version 2.0 (the "License"); you may
+// 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
 //
diff --git a/license-eye/test/testdata/include_test/with_license/testcase.java 
b/license-eye/test/testdata/include_test/with_license/testcase.java
index a388cbc..c24ce1f 100644
--- a/license-eye/test/testdata/include_test/with_license/testcase.java
+++ b/license-eye/test/testdata/include_test/with_license/testcase.java
@@ -1,9 +1,12 @@
 /**
- * Licensed to Apache Software Foundation (ASF) under one or more contributor
+ * Licensed to Apache Software Foundation
+ * (ASF) under one or more contributor
  * license agreements. See the NOTICE file distributed with
  * this work for additional information regarding copyright
- * ownership. Apache Software Foundation (ASF) licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
+ * ownership. Apache Software Foundation
+ * (ASF) licenses this file to you 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
  *
@@ -12,7 +15,7 @@
  * 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
+ * KIND, either express or implied.       See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
diff --git a/license-eye/test/testdata/include_test/with_license/testcase.ml 
b/license-eye/test/testdata/include_test/with_license/testcase.ml
new file mode 100644
index 0000000..246ff88
--- /dev/null
+++ b/license-eye/test/testdata/include_test/with_license/testcase.ml
@@ -0,0 +1,19 @@
+(* Licensed to Apache Software Foundation (ASF) under one or more contributor
+(* license agreements. See the NOTICE file distributed with
+(* this work for additional information regarding copyright
+(* ownership. Apache Software Foundation (ASF) licenses this file to you 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
+(*
+(*     http://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.
+
+let to_string = function Left -> "Left" | Non -> "Non" | Right -> "Right"
diff --git a/license-eye/test/testdata/include_test/without_license/testcase.py 
b/license-eye/test/testdata/include_test/without_license/testcase.py
index 5030e1c..ce55ff9 100644
--- a/license-eye/test/testdata/include_test/without_license/testcase.py
+++ b/license-eye/test/testdata/include_test/without_license/testcase.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 # Esse enim dolore adipisicing in cillum eiusmod excepteur quis nisi sit dolor 
anim anim id id nostrud nostrud tempor.
 # Elit sit enim cillum adipisicing non magna aute nostrud ullamco dolor dolore 
consequat ut ea occaecat veniam incididunt
 #  occaecat consectetur eiusmod sint eiusmod aute eu duis fugiat dolore in 
laboris enim eiusmod aliquip nisi aliqua irure 

Reply via email to