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