go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/git/footer/footer_test.go (about)

     1  // Copyright 2020 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package footer
    16  
    17  import (
    18  	"strings"
    19  	"testing"
    20  
    21  	"go.chromium.org/luci/common/data/strpair"
    22  
    23  	. "github.com/smartystreets/goconvey/convey"
    24  )
    25  
    26  func TestNormalizeKey(t *testing.T) {
    27  	t.Parallel()
    28  
    29  	Convey("NormalizeKey", t, func() {
    30  		Convey("Remove surrounding whitespace", func() {
    31  			So(NormalizeKey("   R   "), ShouldEqual, "R")
    32  		})
    33  
    34  		Convey("Convert key to title case", func() {
    35  			So(NormalizeKey("BUG"), ShouldEqual, "Bug")
    36  			So(NormalizeKey("GIT-FOOTER"), ShouldEqual, "Git-Footer")
    37  			So(NormalizeKey("GiT-fOoTeR"), ShouldEqual, "Git-Footer")
    38  			So(NormalizeKey("123-_ABC"), ShouldEqual, "123-_abc")
    39  		})
    40  	})
    41  }
    42  
    43  func TestParseLine(t *testing.T) {
    44  	t.Parallel()
    45  
    46  	parse := func(line, expectedKey, expectedValue string) {
    47  		actualKey, actualValue := ParseLine(line)
    48  		So(actualKey, ShouldEqual, expectedKey)
    49  		So(actualValue, ShouldEqual, expectedValue)
    50  	}
    51  
    52  	Convey("ParseLine", t, func() {
    53  		Convey("Parse valid footer line", func() {
    54  			parse("GIT-FOOTER: 12345", "Git-Footer", "12345")
    55  			parse("GIT-FOOTER: here could be anything",
    56  				"Git-Footer", "here could be anything")
    57  			parse("    GIT-FOOTER:     whitespace     ", "Git-Footer", "whitespace")
    58  		})
    59  		Convey("Parse invalid footer line", func() {
    60  			parseInvalid := func(line string) {
    61  				parse(line, "", "")
    62  			}
    63  			parseInvalid("NOT VALID")
    64  			parseInvalid("GIT-FOOTER=12345")
    65  			parseInvalid("GIT-FOOTER  :  12345")    // additional whitespace
    66  			parseInvalid("GIT|FOOTER: 12345")       // invalid key
    67  			parseInvalid("http://www.google.com/")  // in ignore list
    68  			parseInvalid("https://www.google.com/") // in ignore list
    69  		})
    70  	})
    71  }
    72  
    73  func TestParseLines(t *testing.T) {
    74  	t.Parallel()
    75  
    76  	Convey("ParseLines", t, func() {
    77  		Convey("Simple", func() {
    78  			actual := ParseLines([]string{
    79  				"Git-Foo: foo",
    80  				"Git-Bar: bar",
    81  			})
    82  			So(actual, ShouldResemble, strpair.ParseMap([]string{
    83  				"Git-Foo:foo",
    84  				"Git-Bar:bar",
    85  			}))
    86  		})
    87  		Convey("Omit malformed lines", func() {
    88  			actual := ParseLines([]string{
    89  				"Git-Foo: foo",
    90  				"Random string in the middle",
    91  				"Git-Bar: bar",
    92  				"Random string at the end",
    93  			})
    94  			So(actual, ShouldResemble, strpair.ParseMap([]string{
    95  				"Git-Foo:foo",
    96  				"Git-Bar:bar",
    97  			}))
    98  		})
    99  
   100  		Convey("Honer footer ordering", func() {
   101  			actual := ParseLines([]string{
   102  				"Git-Footer:foo",
   103  				"Git-Footer:bar",
   104  				"Git-Footer:baz",
   105  			})
   106  			So(actual["Git-Footer"], ShouldResemble, []string{"baz", "bar", "foo"})
   107  		})
   108  	})
   109  }
   110  
   111  func TestSplitLines(t *testing.T) {
   112  	t.Parallel()
   113  
   114  	assertSplitAt := func(message string, splitLineNum int) {
   115  		nonFooterLines, footerLines := SplitLines(message)
   116  		messageLines := strings.Split(message, "\n")
   117  
   118  		So(nonFooterLines, ShouldResemble, messageLines[:splitLineNum])
   119  		So(footerLines, ShouldResemble, messageLines[splitLineNum:])
   120  	}
   121  
   122  	Convey("SplitLines", t, func() {
   123  		Convey("Simple", func() {
   124  			message := `commit message
   125  
   126  commit details...
   127  
   128  Git-Footer: 12345
   129  Git-Footer: 23456`
   130  			assertSplitAt(message, 4)
   131  		})
   132  
   133  		Convey("Include malformed lines in last paragraph", func() {
   134  			message := `commit message
   135  
   136  commit details...
   137  
   138  Git-Footer: 12345
   139  Random String in between
   140  Git-Footer: 23456
   141  Random Stuff at the end`
   142  			assertSplitAt(message, 4)
   143  		})
   144  
   145  		Convey("Does not split when whole message is footer", func() {
   146  			message := `Git-Footer: 12345
   147  Git-Footer: 23456`
   148  			nonFooterLines, footerLines := SplitLines(message)
   149  			So(footerLines, ShouldBeNil)
   150  			So(nonFooterLines, ShouldResemble, strings.Split(message, "\n"))
   151  		})
   152  
   153  		Convey("Splits last paragraph when it starts with text", func() {
   154  			message := `commit message
   155  
   156  commit details...
   157  
   158  This line should be non-footer line
   159  Git-Footer: 12345
   160  Git-Footer: 23456`
   161  			nonFooterLines, footerLines := SplitLines(message)
   162  			messageLines := strings.Split(message, "\n")
   163  
   164  			So(footerLines, ShouldResemble, messageLines[len(messageLines)-2:])
   165  			expectedNonFooterLines := append([]string(nil), messageLines[:len(messageLines)-2]...)
   166  			expectedNonFooterLines = append(expectedNonFooterLines, "")
   167  			So(nonFooterLines, ShouldResemble, expectedNonFooterLines)
   168  		})
   169  
   170  		Convey("Trims leading and trailing new lines", func() {
   171  			message := `
   172  
   173  commit message
   174  
   175  Git-Footer: 12345
   176  
   177  
   178  `
   179  			nonFooterLines, footerLines := SplitLines(message)
   180  			So(nonFooterLines, ShouldResemble, []string{"commit message", ""})
   181  			So(footerLines, ShouldResemble, []string{"Git-Footer: 12345"})
   182  		})
   183  	})
   184  }