View Javadoc
1   /*
2    * Copyright (C) 2008-2009, Google Inc.
3    * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com>
4    * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk> and others
5    *
6    * This program and the accompanying materials are made available under the
7    * terms of the Eclipse Distribution License v. 1.0 which is available at
8    * https://www.eclipse.org/org/documents/edl-v10.php.
9    *
10   * SPDX-License-Identifier: BSD-3-Clause
11   */
12  
13  package org.eclipse.jgit.junit;
14  
15  import static java.nio.charset.StandardCharsets.UTF_8;
16  
17  import java.io.File;
18  import java.io.FileNotFoundException;
19  import java.io.FileOutputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStreamWriter;
23  import java.io.Writer;
24  import java.lang.reflect.Method;
25  import java.net.URISyntaxException;
26  import java.net.URL;
27  import java.nio.file.Path;
28  
29  import org.eclipse.jgit.lib.Repository;
30  import org.eclipse.jgit.util.FileUtils;
31  import org.eclipse.jgit.util.IO;
32  import org.eclipse.jgit.util.RawParseUtils;
33  import org.junit.Assert;
34  import org.junit.Test;
35  
36  /**
37   * Abstract test util class
38   */
39  public abstract class JGitTestUtil {
40  	/** Constant <code>CLASSPATH_TO_RESOURCES="org/eclipse/jgit/test/resources/"</code> */
41  	public static final String CLASSPATH_TO_RESOURCES = "org/eclipse/jgit/test/resources/";
42  
43  	private JGitTestUtil() {
44  		throw new UnsupportedOperationException();
45  	}
46  
47  	/**
48  	 * Get name of current test by inspecting stack trace
49  	 *
50  	 * @return the name
51  	 */
52  	public static String getName() {
53  		GatherStackTrace stack;
54  		try {
55  			throw new GatherStackTrace();
56  		} catch (GatherStackTrace wanted) {
57  			stack = wanted;
58  		}
59  
60  		try {
61  			for (StackTraceElement stackTrace : stack.getStackTrace()) {
62  				String className = stackTrace.getClassName();
63  				String methodName = stackTrace.getMethodName();
64  				Method method;
65  				try {
66  					method = Class.forName(className) //
67  							.getMethod(methodName, (Class[]) null);
68  				} catch (NoSuchMethodException e) {
69  					// could be private, i.e. not a test method
70  					// could have arguments, not handled
71  					continue;
72  				}
73  
74  				Test annotation = method.getAnnotation(Test.class);
75  				if (annotation != null)
76  					return methodName;
77  			}
78  		} catch (ClassNotFoundException shouldNeverOccur) {
79  			// Fall through and crash.
80  		}
81  
82  		throw new AssertionError("Cannot determine name of current test");
83  	}
84  
85  	@SuppressWarnings("serial")
86  	private static class GatherStackTrace extends Exception {
87  		// Thrown above to collect the stack frame.
88  	}
89  
90  	/**
91  	 * Assert byte arrays are equal
92  	 *
93  	 * @param exp
94  	 *            expected value
95  	 * @param act
96  	 *            actual value
97  	 */
98  	public static void assertEquals(byte[] exp, byte[] act) {
99  		Assert.assertEquals(s(exp), s(act));
100 	}
101 
102 	private static String s(byte[] raw) {
103 		return RawParseUtils.decode(raw);
104 	}
105 
106 	/**
107 	 * Get test resource file.
108 	 *
109 	 * @param fileName
110 	 * @return the test resource file
111 	 */
112 	public static File getTestResourceFile(String fileName) {
113 		if (fileName == null || fileName.length() <= 0) {
114 			return null;
115 		}
116 		final URL url = cl().getResource(CLASSPATH_TO_RESOURCES + fileName);
117 		if (url == null) {
118 			// If URL is null then try to load it as it was being
119 			// loaded previously
120 			return new File("tst", fileName);
121 		}
122 		if ("jar".equals(url.getProtocol())) {
123 			try {
124 				File tmp = File.createTempFile("tmp_", "_" + fileName);
125 				copyTestResource(fileName, tmp);
126 				return tmp;
127 			} catch (IOException err) {
128 				throw new RuntimeException("Cannot create temporary file", err);
129 			}
130 		}
131 		try {
132 			return new File(url.toURI());
133 		} catch (IllegalArgumentException e) {
134 			throw new IllegalArgumentException(e.getMessage() + " " + url);
135 		} catch (URISyntaxException e) {
136 			return new File(url.getPath());
137 		}
138 	}
139 
140 	/**
141 	 * Copy test resource.
142 	 *
143 	 * @param name
144 	 * @param dest
145 	 * @throws IOException
146 	 */
147 	public static void copyTestResource(String name, File dest)
148 			throws IOException {
149 		URL url = cl().getResource(CLASSPATH_TO_RESOURCES + name);
150 		if (url == null)
151 			throw new FileNotFoundException(name);
152 		try (InputStream in = url.openStream();
153 				FileOutputStream out = new FileOutputStream(dest)) {
154 			byte[] buf = new byte[4096];
155 			for (int n; (n = in.read(buf)) > 0;)
156 				out.write(buf, 0, n);
157 		}
158 	}
159 
160 	private static ClassLoader cl() {
161 		return JGitTestUtil.class.getClassLoader();
162 	}
163 
164 	/**
165 	 * Write a trash file.
166 	 *
167 	 * @param db
168 	 * @param name
169 	 * @param data
170 	 * @return the trash file
171 	 * @throws IOException
172 	 */
173 	public static File writeTrashFile(final Repository db,
174 			final String name, final String data) throws IOException {
175 		File path = new File(db.getWorkTree(), name);
176 		write(path, data);
177 		return path;
178 	}
179 
180 	/**
181 	 * Write a trash file.
182 	 *
183 	 * @param db
184 	 * @param subdir
185 	 * @param name
186 	 * @param data
187 	 * @return the trash file
188 	 * @throws IOException
189 	 */
190 	public static File writeTrashFile(final Repository db,
191 			final String subdir,
192 			final String name, final String data) throws IOException {
193 		File path = new File(db.getWorkTree() + "/" + subdir, name);
194 		write(path, data);
195 		return path;
196 	}
197 
198 	/**
199 	 * Write a string as a UTF-8 file.
200 	 *
201 	 * @param f
202 	 *            file to write the string to. Caller is responsible for making
203 	 *            sure it is in the trash directory or will otherwise be cleaned
204 	 *            up at the end of the test. If the parent directory does not
205 	 *            exist, the missing parent directories are automatically
206 	 *            created.
207 	 * @param body
208 	 *            content to write to the file.
209 	 * @throws IOException
210 	 *             the file could not be written.
211 	 */
212 	public static void write(File f, String body)
213 			throws IOException {
214 		FileUtils.mkdirs(f.getParentFile(), true);
215 		try (Writer w = new OutputStreamWriter(new FileOutputStream(f),
216 				UTF_8)) {
217 			w.write(body);
218 		}
219 	}
220 
221 	/**
222 	 * Fully read a UTF-8 file and return as a string.
223 	 *
224 	 * @param file
225 	 *            file to read the content of.
226 	 * @return UTF-8 decoded content of the file, empty string if the file
227 	 *         exists but has no content.
228 	 * @throws IOException
229 	 *             the file does not exist, or could not be read.
230 	 */
231 	public static String read(File file) throws IOException {
232 		final byte[] body = IO.readFully(file);
233 		return new String(body, 0, body.length, UTF_8);
234 	}
235 
236 	/**
237 	 * Read a file's content
238 	 *
239 	 * @param db
240 	 * @param name
241 	 * @return the content of the file
242 	 * @throws IOException
243 	 */
244 	public static String read(Repository db, String name)
245 			throws IOException {
246 		File file = new File(db.getWorkTree(), name);
247 		return read(file);
248 	}
249 
250 	/**
251 	 * Check if file exists
252 	 *
253 	 * @param db
254 	 * @param name
255 	 *            name of the file
256 	 * @return {@code true} if the file exists
257 	 */
258 	public static boolean check(Repository db, String name) {
259 		File file = new File(db.getWorkTree(), name);
260 		return file.exists();
261 	}
262 
263 	/**
264 	 * Delete a trash file.
265 	 *
266 	 * @param db
267 	 * @param name
268 	 * @throws IOException
269 	 */
270 	public static void deleteTrashFile(final Repository db,
271 			final String name) throws IOException {
272 		File path = new File(db.getWorkTree(), name);
273 		FileUtils.delete(path);
274 	}
275 
276 	/**
277 	 * Write a symbolic link
278 	 *
279 	 * @param db
280 	 *            the repository
281 	 * @param link
282 	 *            the path of the symbolic link to create
283 	 * @param target
284 	 *            the target of the symbolic link
285 	 * @return the path to the symbolic link
286 	 * @throws Exception
287 	 * @since 4.2
288 	 */
289 	public static Path writeLink(Repository db, String link,
290 			String target) throws Exception {
291 		return FileUtils.createSymLink(new File(db.getWorkTree(), link),
292 				target);
293 	}
294 
295 	/**
296 	 * Concatenate byte arrays.
297 	 *
298 	 * @param b
299 	 *            byte arrays to combine together.
300 	 * @return a single byte array that contains all bytes copied from input
301 	 *         byte arrays.
302 	 * @since 4.9
303 	 */
304 	public static byte[] concat(byte[]... b) {
305 		int n = 0;
306 		for (byte[] a : b) {
307 			n += a.length;
308 		}
309 
310 		byte[] data = new byte[n];
311 		n = 0;
312 		for (byte[] a : b) {
313 			System.arraycopy(a, 0, data, n, a.length);
314 			n += a.length;
315 		}
316 		return data;
317 	}
318 }