View Javadoc
1   /*
2    * Copyright (C) 2012, IBM Corporation and others.
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  package org.eclipse.jgit.lib;
44  
45  import static org.junit.Assert.assertEquals;
46  
47  import java.io.File;
48  import java.io.IOException;
49  import java.nio.file.Path;
50  import java.util.ArrayList;
51  import java.util.Arrays;
52  import java.util.List;
53  
54  import org.eclipse.jgit.junit.JGitTestUtil;
55  import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
56  import org.eclipse.jgit.pgm.CLIGitCommand;
57  import org.eclipse.jgit.pgm.CLIGitCommand.Result;
58  import org.eclipse.jgit.pgm.TextBuiltin.TerminatedByHelpException;
59  import org.junit.Before;
60  
61  public class CLIRepositoryTestCase extends LocalDiskRepositoryTestCase {
62  	/** Test repository, initialized for this test case. */
63  	protected Repository db;
64  
65  	@Override
66  	@Before
67  	public void setUp() throws Exception {
68  		super.setUp();
69  		db = createWorkRepository();
70  	}
71  
72  	/**
73  	 * Executes specified git commands (with arguments)
74  	 *
75  	 * @param cmds
76  	 *            each string argument must be a valid git command line, e.g.
77  	 *            "git branch -h"
78  	 * @return command output
79  	 * @throws Exception
80  	 */
81  	protected String[] executeUnchecked(String... cmds) throws Exception {
82  		List<String> result = new ArrayList<>(cmds.length);
83  		for (String cmd : cmds) {
84  			result.addAll(CLIGitCommand.executeUnchecked(cmd, db));
85  		}
86  		return result.toArray(new String[0]);
87  	}
88  
89  	/**
90  	 * Executes specified git commands (with arguments), throws exception and
91  	 * stops execution on first command which output contains a 'fatal:' error
92  	 *
93  	 * @param cmds
94  	 *            each string argument must be a valid git command line, e.g.
95  	 *            "git branch -h"
96  	 * @return command output
97  	 * @throws Exception
98  	 */
99  	protected String[] execute(String... cmds) throws Exception {
100 		List<String> result = new ArrayList<>(cmds.length);
101 		for (String cmd : cmds) {
102 			Result r = CLIGitCommand.executeRaw(cmd, db);
103 			if (r.ex instanceof TerminatedByHelpException) {
104 				result.addAll(r.errLines());
105 			} else if (r.ex != null) {
106 				throw r.ex;
107 			}
108 			result.addAll(r.outLines());
109 		}
110 		return result.toArray(new String[0]);
111 	}
112 
113 	/**
114 	 * @param link
115 	 *            the path of the symbolic link to create
116 	 * @param target
117 	 *            the target of the symbolic link
118 	 * @return the path to the symbolic link
119 	 * @throws Exception
120 	 */
121 	protected Path writeLink(String link, String target) throws Exception {
122 		return JGitTestUtil.writeLink(db, link, target);
123 	}
124 
125 	protected File writeTrashFile(final String name, final String data)
126 			throws IOException {
127 		return JGitTestUtil.writeTrashFile(db, name, data);
128 	}
129 
130 	@Override
131 	protected String read(final File file) throws IOException {
132 		return JGitTestUtil.read(file);
133 	}
134 
135 	protected void deleteTrashFile(final String name) throws IOException {
136 		JGitTestUtil.deleteTrashFile(db, name);
137 	}
138 
139 	/**
140 	 * Execute the given commands and print the output to stdout. Use this
141 	 * function instead of the normal {@link #execute(String...)} when preparing
142 	 * a test case: the command is executed and then its output is printed on
143 	 * stdout, thus making it easier to prepare the correct command and expected
144 	 * output for the test case.
145 	 *
146 	 * @param cmds
147 	 *            The commands to execute
148 	 * @return the result of the command, see {@link #execute(String...)}
149 	 * @throws Exception
150 	 */
151 	protected String[] executeAndPrint(String... cmds) throws Exception {
152 		String[] lines = execute(cmds);
153 		for (String line : lines) {
154 			System.out.println(line);
155 		}
156 		return lines;
157 	}
158 
159 	/**
160 	 * Execute the given commands and print test code comparing expected and
161 	 * actual output. Use this function instead of the normal
162 	 * {@link #execute(String...)} when preparing a test case: the command is
163 	 * executed and test code is generated using the command output as a
164 	 * template of what is expected. The code generated is printed on stdout and
165 	 * can be pasted in the test case function.
166 	 *
167 	 * @param cmds
168 	 *            The commands to execute
169 	 * @return the result of the command, see {@link #execute(String...)}
170 	 * @throws Exception
171 	 */
172 	protected String[] executeAndPrintTestCode(String... cmds) throws Exception {
173 		String[] lines = execute(cmds);
174 		String cmdString = cmdString(cmds);
175 		if (lines.length == 0)
176 			System.out.println("\t\tassertTrue(execute(" + cmdString
177 					+ ").length == 0);");
178 		else {
179 			System.out
180 					.println("\t\tassertArrayOfLinesEquals(new String[] { //");
181 			System.out.print("\t\t\t\t\t\t\"" + escapeJava(lines[0]));
182 			for (int i=1; i<lines.length; i++) {
183 				System.out.println("\", //");
184 				System.out.print("\t\t\t\t\t\t\"" + escapeJava(lines[i]));
185 			}
186 			System.out.println("\" //");
187 			System.out.println("\t\t\t\t}, execute(" + cmdString + ")); //");
188 		}
189 		return lines;
190 	}
191 
192 	protected String cmdString(String... cmds) {
193 		if (cmds.length == 0)
194 			return "";
195 		else if (cmds.length == 1)
196 			return "\"" + escapeJava(cmds[0]) + "\"";
197 		else {
198 			StringBuilder sb = new StringBuilder(cmdString(cmds[0]));
199 			for (int i=1; i<cmds.length; i++) {
200 				sb.append(", ");
201 				sb.append(cmdString(cmds[i]));
202 			}
203 			return sb.toString();
204 		}
205 	}
206 
207 	protected String escapeJava(String line) {
208 		// very crude implementation but ok for generating test code
209 		return line.replaceAll("\"", "\\\\\"") //
210 				.replaceAll("\\\\", "\\\\\\")
211 				.replaceAll("\t", "\\\\t");
212 	}
213 
214 	protected void assertStringArrayEquals(String expected, String[] actual) {
215 		// if there is more than one line, ignore last one if empty
216 		assertEquals(1,
217 				actual.length > 1 && actual[actual.length - 1].equals("")
218 						? actual.length - 1 : actual.length);
219 		assertEquals(expected, actual[0]);
220 	}
221 
222 	protected void assertArrayOfLinesEquals(String[] expected, String[] actual) {
223 		assertEquals(toString(expected), toString(actual));
224 	}
225 
226 	public static String toString(String... lines) {
227 		return toString(Arrays.asList(lines));
228 	}
229 
230 	public static String toString(List<String> lines) {
231 		StringBuilder b = new StringBuilder();
232 		for (String s : lines) {
233 			// trim indentation, to simplify tests
234 			s = s.trim();
235 			if (s != null && !s.isEmpty()) {
236 				b.append(s);
237 				b.append('\n');
238 			}
239 		}
240 		// delete last line break to allow simpler tests with one line compare
241 		if (b.length() > 0 && b.charAt(b.length() - 1) == '\n') {
242 			b.deleteCharAt(b.length() - 1);
243 		}
244 		return b.toString();
245 	}
246 
247 	public static boolean contains(List<String> lines, String str) {
248 		for (String s : lines) {
249 			if (s.contains(str)) {
250 				return true;
251 			}
252 		}
253 		return false;
254 	}
255 }