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 JGitTestUtil()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 */ getName()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 */ assertEquals(byte[] exp, byte[] act)98 public static void assertEquals(byte[] exp, byte[] act) { 99 Assert.assertEquals(s(exp), s(act)); 100 } 101 s(byte[] raw)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 */ getTestResourceFile(String fileName)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 */ copyTestResource(String name, File dest)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 cl()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 */ writeTrashFile(final Repository db, final String name, final String data)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 */ writeTrashFile(final Repository db, final String subdir, final String name, final String data)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 */ write(File f, String body)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 */ read(File file)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 */ read(Repository db, String name)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 */ check(Repository db, String name)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 */ deleteTrashFile(final Repository db, final String name)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 */ writeLink(Repository db, String link, String target)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 */ concat(byte[]... b)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 } 319