View Javadoc
1   /*
2    * Copyright (C) 2009, Google Inc. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  
11  package org.eclipse.jgit.revwalk;
12  
13  import static org.junit.Assert.assertEquals;
14  import static org.junit.Assert.assertFalse;
15  import static org.junit.Assert.assertNotNull;
16  import static org.junit.Assert.assertNull;
17  import static org.junit.Assert.assertTrue;
18  
19  import java.io.IOException;
20  import java.util.List;
21  
22  import org.eclipse.jgit.junit.RepositoryTestCase;
23  import org.eclipse.jgit.lib.Constants;
24  import org.eclipse.jgit.lib.ObjectId;
25  import org.junit.Test;
26  
27  public class FooterLineTest extends RepositoryTestCase {
28  	@Test
29  	public void testNoFooters_EmptyBody() throws IOException {
30  		final RevCommit commit = parse("");
31  		final List<FooterLine> footers = commit.getFooterLines();
32  		assertNotNull(footers);
33  		assertEquals(0, footers.size());
34  	}
35  
36  	@Test
37  	public void testNoFooters_NewlineOnlyBody1() throws IOException {
38  		final RevCommit commit = parse("\n");
39  		final List<FooterLine> footers = commit.getFooterLines();
40  		assertNotNull(footers);
41  		assertEquals(0, footers.size());
42  	}
43  
44  	@Test
45  	public void testNoFooters_NewlineOnlyBody5() throws IOException {
46  		final RevCommit commit = parse("\n\n\n\n\n");
47  		final List<FooterLine> footers = commit.getFooterLines();
48  		assertNotNull(footers);
49  		assertEquals(0, footers.size());
50  	}
51  
52  	@Test
53  	public void testNoFooters_OneLineBodyNoLF() throws IOException {
54  		final RevCommit commit = parse("this is a commit");
55  		final List<FooterLine> footers = commit.getFooterLines();
56  		assertNotNull(footers);
57  		assertEquals(0, footers.size());
58  	}
59  
60  	@Test
61  	public void testNoFooters_OneLineBodyWithLF() throws IOException {
62  		final RevCommit commit = parse("this is a commit\n");
63  		final List<FooterLine> footers = commit.getFooterLines();
64  		assertNotNull(footers);
65  		assertEquals(0, footers.size());
66  	}
67  
68  	@Test
69  	public void testNoFooters_ShortBodyNoLF() throws IOException {
70  		final RevCommit commit = parse("subject\n\nbody of commit");
71  		final List<FooterLine> footers = commit.getFooterLines();
72  		assertNotNull(footers);
73  		assertEquals(0, footers.size());
74  	}
75  
76  	@Test
77  	public void testNoFooters_ShortBodyWithLF() throws IOException {
78  		final RevCommit commit = parse("subject\n\nbody of commit\n");
79  		final List<FooterLine> footers = commit.getFooterLines();
80  		assertNotNull(footers);
81  		assertEquals(0, footers.size());
82  	}
83  
84  	@Test
85  	public void testSignedOffBy_OneUserNoLF() throws IOException {
86  		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
87  				+ "Signed-off-by: A. U. Thor <a@example.com>");
88  		final List<FooterLine> footers = commit.getFooterLines();
89  		FooterLine f;
90  
91  		assertNotNull(footers);
92  		assertEquals(1, footers.size());
93  
94  		f = footers.get(0);
95  		assertEquals("Signed-off-by", f.getKey());
96  		assertEquals("A. U. Thor <a@example.com>", f.getValue());
97  		assertEquals("a@example.com", f.getEmailAddress());
98  	}
99  
100 	@Test
101 	public void testSignedOffBy_OneUserWithLF() throws IOException {
102 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
103 				+ "Signed-off-by: A. U. Thor <a@example.com>\n");
104 		final List<FooterLine> footers = commit.getFooterLines();
105 		FooterLine f;
106 
107 		assertNotNull(footers);
108 		assertEquals(1, footers.size());
109 
110 		f = footers.get(0);
111 		assertEquals("Signed-off-by", f.getKey());
112 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
113 		assertEquals("a@example.com", f.getEmailAddress());
114 	}
115 
116 	@Test
117 	public void testSignedOffBy_IgnoreWhitespace() throws IOException {
118 		// We only ignore leading whitespace on the value, trailing
119 		// is assumed part of the value.
120 		//
121 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
122 				+ "Signed-off-by:   A. U. Thor <a@example.com>  \n");
123 		final List<FooterLine> footers = commit.getFooterLines();
124 		FooterLine f;
125 
126 		assertNotNull(footers);
127 		assertEquals(1, footers.size());
128 
129 		f = footers.get(0);
130 		assertEquals("Signed-off-by", f.getKey());
131 		assertEquals("A. U. Thor <a@example.com>  ", f.getValue());
132 		assertEquals("a@example.com", f.getEmailAddress());
133 	}
134 
135 	@Test
136 	public void testEmptyValueNoLF() throws IOException {
137 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
138 				+ "Signed-off-by:");
139 		final List<FooterLine> footers = commit.getFooterLines();
140 		FooterLine f;
141 
142 		assertNotNull(footers);
143 		assertEquals(1, footers.size());
144 
145 		f = footers.get(0);
146 		assertEquals("Signed-off-by", f.getKey());
147 		assertEquals("", f.getValue());
148 		assertNull(f.getEmailAddress());
149 	}
150 
151 	@Test
152 	public void testEmptyValueWithLF() throws IOException {
153 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
154 				+ "Signed-off-by:\n");
155 		final List<FooterLine> footers = commit.getFooterLines();
156 		FooterLine f;
157 
158 		assertNotNull(footers);
159 		assertEquals(1, footers.size());
160 
161 		f = footers.get(0);
162 		assertEquals("Signed-off-by", f.getKey());
163 		assertEquals("", f.getValue());
164 		assertNull(f.getEmailAddress());
165 	}
166 
167 	@Test
168 	public void testShortKey() throws IOException {
169 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
170 				+ "K:V\n");
171 		final List<FooterLine> footers = commit.getFooterLines();
172 		FooterLine f;
173 
174 		assertNotNull(footers);
175 		assertEquals(1, footers.size());
176 
177 		f = footers.get(0);
178 		assertEquals("K", f.getKey());
179 		assertEquals("V", f.getValue());
180 		assertNull(f.getEmailAddress());
181 	}
182 
183 	@Test
184 	public void testNonDelimtedEmail() throws IOException {
185 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
186 				+ "Acked-by: re@example.com\n");
187 		final List<FooterLine> footers = commit.getFooterLines();
188 		FooterLine f;
189 
190 		assertNotNull(footers);
191 		assertEquals(1, footers.size());
192 
193 		f = footers.get(0);
194 		assertEquals("Acked-by", f.getKey());
195 		assertEquals("re@example.com", f.getValue());
196 		assertEquals("re@example.com", f.getEmailAddress());
197 	}
198 
199 	@Test
200 	public void testNotEmail() throws IOException {
201 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
202 				+ "Acked-by: Main Tain Er\n");
203 		final List<FooterLine> footers = commit.getFooterLines();
204 		FooterLine f;
205 
206 		assertNotNull(footers);
207 		assertEquals(1, footers.size());
208 
209 		f = footers.get(0);
210 		assertEquals("Acked-by", f.getKey());
211 		assertEquals("Main Tain Er", f.getValue());
212 		assertNull(f.getEmailAddress());
213 	}
214 
215 	@Test
216 	public void testSignedOffBy_ManyUsers() throws IOException {
217 		final RevCommit commit = parse("subject\n\nbody of commit\n"
218 				+ "Not-A-Footer-Line: this line must not be read as a footer\n"
219 				+ "\n" // paragraph break, now footers appear in final block
220 				+ "Signed-off-by: A. U. Thor <a@example.com>\n"
221 				+ "CC:            <some.mailing.list@example.com>\n"
222 				+ "Acked-by: Some Reviewer <sr@example.com>\n"
223 				+ "Signed-off-by: Main Tain Er <mte@example.com>\n");
224 		final List<FooterLine> footers = commit.getFooterLines();
225 		FooterLine f;
226 
227 		assertNotNull(footers);
228 		assertEquals(4, footers.size());
229 
230 		f = footers.get(0);
231 		assertEquals("Signed-off-by", f.getKey());
232 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
233 		assertEquals("a@example.com", f.getEmailAddress());
234 
235 		f = footers.get(1);
236 		assertEquals("CC", f.getKey());
237 		assertEquals("<some.mailing.list@example.com>", f.getValue());
238 		assertEquals("some.mailing.list@example.com", f.getEmailAddress());
239 
240 		f = footers.get(2);
241 		assertEquals("Acked-by", f.getKey());
242 		assertEquals("Some Reviewer <sr@example.com>", f.getValue());
243 		assertEquals("sr@example.com", f.getEmailAddress());
244 
245 		f = footers.get(3);
246 		assertEquals("Signed-off-by", f.getKey());
247 		assertEquals("Main Tain Er <mte@example.com>", f.getValue());
248 		assertEquals("mte@example.com", f.getEmailAddress());
249 	}
250 
251 	@Test
252 	public void testSignedOffBy_SkipNonFooter() throws IOException {
253 		final RevCommit commit = parse("subject\n\nbody of commit\n"
254 				+ "Not-A-Footer-Line: this line must not be read as a footer\n"
255 				+ "\n" // paragraph break, now footers appear in final block
256 				+ "Signed-off-by: A. U. Thor <a@example.com>\n"
257 				+ "CC:            <some.mailing.list@example.com>\n"
258 				+ "not really a footer line but we'll skip it anyway\n"
259 				+ "Acked-by: Some Reviewer <sr@example.com>\n"
260 				+ "Signed-off-by: Main Tain Er <mte@example.com>\n");
261 		final List<FooterLine> footers = commit.getFooterLines();
262 		FooterLine f;
263 
264 		assertNotNull(footers);
265 		assertEquals(4, footers.size());
266 
267 		f = footers.get(0);
268 		assertEquals("Signed-off-by", f.getKey());
269 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
270 
271 		f = footers.get(1);
272 		assertEquals("CC", f.getKey());
273 		assertEquals("<some.mailing.list@example.com>", f.getValue());
274 
275 		f = footers.get(2);
276 		assertEquals("Acked-by", f.getKey());
277 		assertEquals("Some Reviewer <sr@example.com>", f.getValue());
278 
279 		f = footers.get(3);
280 		assertEquals("Signed-off-by", f.getKey());
281 		assertEquals("Main Tain Er <mte@example.com>", f.getValue());
282 	}
283 
284 	@Test
285 	public void testFilterFootersIgnoreCase() throws IOException {
286 		final RevCommit commit = parse("subject\n\nbody of commit\n"
287 				+ "Not-A-Footer-Line: this line must not be read as a footer\n"
288 				+ "\n" // paragraph break, now footers appear in final block
289 				+ "Signed-Off-By: A. U. Thor <a@example.com>\n"
290 				+ "CC:            <some.mailing.list@example.com>\n"
291 				+ "Acked-by: Some Reviewer <sr@example.com>\n"
292 				+ "signed-off-by: Main Tain Er <mte@example.com>\n");
293 		final List<String> footers = commit.getFooterLines("signed-off-by");
294 
295 		assertNotNull(footers);
296 		assertEquals(2, footers.size());
297 
298 		assertEquals("A. U. Thor <a@example.com>", footers.get(0));
299 		assertEquals("Main Tain Er <mte@example.com>", footers.get(1));
300 	}
301 
302 	@Test
303 	public void testMatchesBugId() throws IOException {
304 		final RevCommit commit = parse("this is a commit subject for test\n"
305 				+ "\n" // paragraph break, now footers appear in final block
306 				+ "Simple-Bug-Id: 42\n");
307 		final List<FooterLine> footers = commit.getFooterLines();
308 
309 		assertNotNull(footers);
310 		assertEquals(1, footers.size());
311 
312 		final FooterLine line = footers.get(0);
313 		assertNotNull(line);
314 		assertEquals("Simple-Bug-Id", line.getKey());
315 		assertEquals("42", line.getValue());
316 
317 		final FooterKey bugid = new FooterKey("Simple-Bug-Id");
318 		assertTrue("matches Simple-Bug-Id", line.matches(bugid));
319 		assertFalse("not Signed-off-by", line.matches(FooterKey.SIGNED_OFF_BY));
320 		assertFalse("not CC", line.matches(FooterKey.CC));
321 	}
322 
323 	private RevCommit parse(String msg) throws IOException {
324 		final StringBuilder buf = new StringBuilder();
325 		buf.append("tree " + ObjectId.zeroId().name() + "\n");
326 		buf.append("author A. U. Thor <a@example.com> 1 +0000\n");
327 		buf.append("committer A. U. Thor <a@example.com> 1 +0000\n");
328 		buf.append("\n");
329 		buf.append(msg);
330 
331 		try (RevWalk walk = new RevWalk(db)) {
332 			RevCommit c = new RevCommit(ObjectId.zeroId());
333 			c.parseCanonical(walk, Constants.encode(buf.toString()));
334 			return c;
335 		}
336 	}
337 }