View Javadoc
1   /*
2    * Copyright (C) 2009, Google Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  
44  package org.eclipse.jgit.revwalk;
45  
46  import static org.junit.Assert.assertEquals;
47  import static org.junit.Assert.assertFalse;
48  import static org.junit.Assert.assertNotNull;
49  import static org.junit.Assert.assertNull;
50  import static org.junit.Assert.assertTrue;
51  
52  import java.io.IOException;
53  import java.util.List;
54  
55  import org.eclipse.jgit.junit.RepositoryTestCase;
56  import org.eclipse.jgit.lib.Constants;
57  import org.eclipse.jgit.lib.ObjectId;
58  import org.junit.Test;
59  
60  public class FooterLineTest extends RepositoryTestCase {
61  	@Test
62  	public void testNoFooters_EmptyBody() throws IOException {
63  		final RevCommit commit = parse("");
64  		final List<FooterLine> footers = commit.getFooterLines();
65  		assertNotNull(footers);
66  		assertEquals(0, footers.size());
67  	}
68  
69  	@Test
70  	public void testNoFooters_NewlineOnlyBody1() throws IOException {
71  		final RevCommit commit = parse("\n");
72  		final List<FooterLine> footers = commit.getFooterLines();
73  		assertNotNull(footers);
74  		assertEquals(0, footers.size());
75  	}
76  
77  	@Test
78  	public void testNoFooters_NewlineOnlyBody5() throws IOException {
79  		final RevCommit commit = parse("\n\n\n\n\n");
80  		final List<FooterLine> footers = commit.getFooterLines();
81  		assertNotNull(footers);
82  		assertEquals(0, footers.size());
83  	}
84  
85  	@Test
86  	public void testNoFooters_OneLineBodyNoLF() throws IOException {
87  		final RevCommit commit = parse("this is a commit");
88  		final List<FooterLine> footers = commit.getFooterLines();
89  		assertNotNull(footers);
90  		assertEquals(0, footers.size());
91  	}
92  
93  	@Test
94  	public void testNoFooters_OneLineBodyWithLF() throws IOException {
95  		final RevCommit commit = parse("this is a commit\n");
96  		final List<FooterLine> footers = commit.getFooterLines();
97  		assertNotNull(footers);
98  		assertEquals(0, footers.size());
99  	}
100 
101 	@Test
102 	public void testNoFooters_ShortBodyNoLF() throws IOException {
103 		final RevCommit commit = parse("subject\n\nbody of commit");
104 		final List<FooterLine> footers = commit.getFooterLines();
105 		assertNotNull(footers);
106 		assertEquals(0, footers.size());
107 	}
108 
109 	@Test
110 	public void testNoFooters_ShortBodyWithLF() throws IOException {
111 		final RevCommit commit = parse("subject\n\nbody of commit\n");
112 		final List<FooterLine> footers = commit.getFooterLines();
113 		assertNotNull(footers);
114 		assertEquals(0, footers.size());
115 	}
116 
117 	@Test
118 	public void testSignedOffBy_OneUserNoLF() throws IOException {
119 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
120 				+ "Signed-off-by: A. U. Thor <a@example.com>");
121 		final List<FooterLine> footers = commit.getFooterLines();
122 		FooterLine f;
123 
124 		assertNotNull(footers);
125 		assertEquals(1, footers.size());
126 
127 		f = footers.get(0);
128 		assertEquals("Signed-off-by", f.getKey());
129 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
130 		assertEquals("a@example.com", f.getEmailAddress());
131 	}
132 
133 	@Test
134 	public void testSignedOffBy_OneUserWithLF() throws IOException {
135 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
136 				+ "Signed-off-by: A. U. Thor <a@example.com>\n");
137 		final List<FooterLine> footers = commit.getFooterLines();
138 		FooterLine f;
139 
140 		assertNotNull(footers);
141 		assertEquals(1, footers.size());
142 
143 		f = footers.get(0);
144 		assertEquals("Signed-off-by", f.getKey());
145 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
146 		assertEquals("a@example.com", f.getEmailAddress());
147 	}
148 
149 	@Test
150 	public void testSignedOffBy_IgnoreWhitespace() throws IOException {
151 		// We only ignore leading whitespace on the value, trailing
152 		// is assumed part of the value.
153 		//
154 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
155 				+ "Signed-off-by:   A. U. Thor <a@example.com>  \n");
156 		final List<FooterLine> footers = commit.getFooterLines();
157 		FooterLine f;
158 
159 		assertNotNull(footers);
160 		assertEquals(1, footers.size());
161 
162 		f = footers.get(0);
163 		assertEquals("Signed-off-by", f.getKey());
164 		assertEquals("A. U. Thor <a@example.com>  ", f.getValue());
165 		assertEquals("a@example.com", f.getEmailAddress());
166 	}
167 
168 	@Test
169 	public void testEmptyValueNoLF() throws IOException {
170 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
171 				+ "Signed-off-by:");
172 		final List<FooterLine> footers = commit.getFooterLines();
173 		FooterLine f;
174 
175 		assertNotNull(footers);
176 		assertEquals(1, footers.size());
177 
178 		f = footers.get(0);
179 		assertEquals("Signed-off-by", f.getKey());
180 		assertEquals("", f.getValue());
181 		assertNull(f.getEmailAddress());
182 	}
183 
184 	@Test
185 	public void testEmptyValueWithLF() throws IOException {
186 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
187 				+ "Signed-off-by:\n");
188 		final List<FooterLine> footers = commit.getFooterLines();
189 		FooterLine f;
190 
191 		assertNotNull(footers);
192 		assertEquals(1, footers.size());
193 
194 		f = footers.get(0);
195 		assertEquals("Signed-off-by", f.getKey());
196 		assertEquals("", f.getValue());
197 		assertNull(f.getEmailAddress());
198 	}
199 
200 	@Test
201 	public void testShortKey() throws IOException {
202 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
203 				+ "K:V\n");
204 		final List<FooterLine> footers = commit.getFooterLines();
205 		FooterLine f;
206 
207 		assertNotNull(footers);
208 		assertEquals(1, footers.size());
209 
210 		f = footers.get(0);
211 		assertEquals("K", f.getKey());
212 		assertEquals("V", f.getValue());
213 		assertNull(f.getEmailAddress());
214 	}
215 
216 	@Test
217 	public void testNonDelimtedEmail() throws IOException {
218 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
219 				+ "Acked-by: re@example.com\n");
220 		final List<FooterLine> footers = commit.getFooterLines();
221 		FooterLine f;
222 
223 		assertNotNull(footers);
224 		assertEquals(1, footers.size());
225 
226 		f = footers.get(0);
227 		assertEquals("Acked-by", f.getKey());
228 		assertEquals("re@example.com", f.getValue());
229 		assertEquals("re@example.com", f.getEmailAddress());
230 	}
231 
232 	@Test
233 	public void testNotEmail() throws IOException {
234 		final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n"
235 				+ "Acked-by: Main Tain Er\n");
236 		final List<FooterLine> footers = commit.getFooterLines();
237 		FooterLine f;
238 
239 		assertNotNull(footers);
240 		assertEquals(1, footers.size());
241 
242 		f = footers.get(0);
243 		assertEquals("Acked-by", f.getKey());
244 		assertEquals("Main Tain Er", f.getValue());
245 		assertNull(f.getEmailAddress());
246 	}
247 
248 	@Test
249 	public void testSignedOffBy_ManyUsers() throws IOException {
250 		final RevCommit commit = parse("subject\n\nbody of commit\n"
251 				+ "Not-A-Footer-Line: this line must not be read as a footer\n"
252 				+ "\n" // paragraph break, now footers appear in final block
253 				+ "Signed-off-by: A. U. Thor <a@example.com>\n"
254 				+ "CC:            <some.mailing.list@example.com>\n"
255 				+ "Acked-by: Some Reviewer <sr@example.com>\n"
256 				+ "Signed-off-by: Main Tain Er <mte@example.com>\n");
257 		final List<FooterLine> footers = commit.getFooterLines();
258 		FooterLine f;
259 
260 		assertNotNull(footers);
261 		assertEquals(4, footers.size());
262 
263 		f = footers.get(0);
264 		assertEquals("Signed-off-by", f.getKey());
265 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
266 		assertEquals("a@example.com", f.getEmailAddress());
267 
268 		f = footers.get(1);
269 		assertEquals("CC", f.getKey());
270 		assertEquals("<some.mailing.list@example.com>", f.getValue());
271 		assertEquals("some.mailing.list@example.com", f.getEmailAddress());
272 
273 		f = footers.get(2);
274 		assertEquals("Acked-by", f.getKey());
275 		assertEquals("Some Reviewer <sr@example.com>", f.getValue());
276 		assertEquals("sr@example.com", f.getEmailAddress());
277 
278 		f = footers.get(3);
279 		assertEquals("Signed-off-by", f.getKey());
280 		assertEquals("Main Tain Er <mte@example.com>", f.getValue());
281 		assertEquals("mte@example.com", f.getEmailAddress());
282 	}
283 
284 	@Test
285 	public void testSignedOffBy_SkipNonFooter() 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 				+ "not really a footer line but we'll skip it anyway\n"
292 				+ "Acked-by: Some Reviewer <sr@example.com>\n"
293 				+ "Signed-off-by: Main Tain Er <mte@example.com>\n");
294 		final List<FooterLine> footers = commit.getFooterLines();
295 		FooterLine f;
296 
297 		assertNotNull(footers);
298 		assertEquals(4, footers.size());
299 
300 		f = footers.get(0);
301 		assertEquals("Signed-off-by", f.getKey());
302 		assertEquals("A. U. Thor <a@example.com>", f.getValue());
303 
304 		f = footers.get(1);
305 		assertEquals("CC", f.getKey());
306 		assertEquals("<some.mailing.list@example.com>", f.getValue());
307 
308 		f = footers.get(2);
309 		assertEquals("Acked-by", f.getKey());
310 		assertEquals("Some Reviewer <sr@example.com>", f.getValue());
311 
312 		f = footers.get(3);
313 		assertEquals("Signed-off-by", f.getKey());
314 		assertEquals("Main Tain Er <mte@example.com>", f.getValue());
315 	}
316 
317 	@Test
318 	public void testFilterFootersIgnoreCase() throws IOException {
319 		final RevCommit commit = parse("subject\n\nbody of commit\n"
320 				+ "Not-A-Footer-Line: this line must not be read as a footer\n"
321 				+ "\n" // paragraph break, now footers appear in final block
322 				+ "Signed-Off-By: A. U. Thor <a@example.com>\n"
323 				+ "CC:            <some.mailing.list@example.com>\n"
324 				+ "Acked-by: Some Reviewer <sr@example.com>\n"
325 				+ "signed-off-by: Main Tain Er <mte@example.com>\n");
326 		final List<String> footers = commit.getFooterLines("signed-off-by");
327 
328 		assertNotNull(footers);
329 		assertEquals(2, footers.size());
330 
331 		assertEquals("A. U. Thor <a@example.com>", footers.get(0));
332 		assertEquals("Main Tain Er <mte@example.com>", footers.get(1));
333 	}
334 
335 	@Test
336 	public void testMatchesBugId() throws IOException {
337 		final RevCommit commit = parse("this is a commit subject for test\n"
338 				+ "\n" // paragraph break, now footers appear in final block
339 				+ "Simple-Bug-Id: 42\n");
340 		final List<FooterLine> footers = commit.getFooterLines();
341 
342 		assertNotNull(footers);
343 		assertEquals(1, footers.size());
344 
345 		final FooterLine line = footers.get(0);
346 		assertNotNull(line);
347 		assertEquals("Simple-Bug-Id", line.getKey());
348 		assertEquals("42", line.getValue());
349 
350 		final FooterKey bugid = new FooterKey("Simple-Bug-Id");
351 		assertTrue("matches Simple-Bug-Id", line.matches(bugid));
352 		assertFalse("not Signed-off-by", line.matches(FooterKey.SIGNED_OFF_BY));
353 		assertFalse("not CC", line.matches(FooterKey.CC));
354 	}
355 
356 	private RevCommit parse(String msg) throws IOException {
357 		final StringBuilder buf = new StringBuilder();
358 		buf.append("tree " + ObjectId.zeroId().name() + "\n");
359 		buf.append("author A. U. Thor <a@example.com> 1 +0000\n");
360 		buf.append("committer A. U. Thor <a@example.com> 1 +0000\n");
361 		buf.append("\n");
362 		buf.append(msg);
363 
364 		try (RevWalk walk = new RevWalk(db)) {
365 			RevCommit c = new RevCommit(ObjectId.zeroId());
366 			c.parseCanonical(walk, Constants.encode(buf.toString()));
367 			return c;
368 		}
369 	}
370 }