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 }