1 /* 2 * Copyright (C) 2009-2017, Google Inc. 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 11 package org.eclipse.jgit.junit.http; 12 13 import static org.junit.Assert.fail; 14 15 import java.io.IOException; 16 import java.net.URI; 17 import java.net.URISyntaxException; 18 import java.util.Collection; 19 import java.util.Collections; 20 import java.util.HashSet; 21 import java.util.List; 22 import java.util.Set; 23 24 import org.eclipse.jetty.servlet.ServletContextHandler; 25 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; 26 import org.eclipse.jgit.junit.TestRepository; 27 import org.eclipse.jgit.lib.AnyObjectId; 28 import org.eclipse.jgit.lib.Constants; 29 import org.eclipse.jgit.lib.ObjectId; 30 import org.eclipse.jgit.lib.Repository; 31 import org.eclipse.jgit.revwalk.RevCommit; 32 import org.eclipse.jgit.revwalk.RevObject; 33 import org.eclipse.jgit.transport.RefSpec; 34 import org.eclipse.jgit.transport.RemoteRefUpdate; 35 import org.eclipse.jgit.transport.URIish; 36 37 /** 38 * Base class for HTTP related transport testing. 39 */ 40 public abstract class HttpTestCase extends LocalDiskRepositoryTestCase { 41 /** Constant <code>master="Constants.R_HEADS + Constants.MASTER"</code> */ 42 protected static final String master = Constants.R_HEADS + Constants.MASTER; 43 44 /** In-memory application server; subclass must start. */ 45 protected AppServer server; 46 47 /** {@inheritDoc} */ 48 @Override setUp()49 public void setUp() throws Exception { 50 super.setUp(); 51 server = createServer(); 52 } 53 54 /** {@inheritDoc} */ 55 @Override tearDown()56 public void tearDown() throws Exception { 57 server.tearDown(); 58 super.tearDown(); 59 } 60 61 /** 62 * Create the {@link AppServer}.This default implementation creates a server 63 * without SSLsupport listening for HTTP connections on a dynamically chosen 64 * port, which can be gotten once the server has been started via its 65 * {@link org.eclipse.jgit.junit.http.AppServer#getPort()} method. 66 * Subclasses may override if they need a more specialized server. 67 * 68 * @return the {@link org.eclipse.jgit.junit.http.AppServer}. 69 * @since 4.9 70 */ createServer()71 protected AppServer createServer() { 72 return new AppServer(); 73 } 74 75 /** 76 * Create TestRepository 77 * 78 * @return the TestRepository 79 * @throws IOException 80 */ createTestRepository()81 protected TestRepository<Repository> createTestRepository() 82 throws IOException { 83 return new TestRepository<>(createBareRepository()); 84 } 85 86 /** 87 * Convert path to URIish 88 * 89 * @param path 90 * @return the URIish 91 * @throws URISyntaxException 92 */ toURIish(String path)93 protected URIish toURIish(String path) throws URISyntaxException { 94 URI u = server.getURI().resolve(path); 95 return new URIish(u.toString()); 96 } 97 98 /** 99 * Convert a path relative to the app's context path to a URIish 100 * 101 * @param app 102 * @param name 103 * @return the warnings (if any) from the last execution 104 * @throws URISyntaxException 105 */ toURIish(ServletContextHandler app, String name)106 protected URIish toURIish(ServletContextHandler app, String name) 107 throws URISyntaxException { 108 String p = app.getContextPath(); 109 if (!p.endsWith("/") && !name.startsWith("/")) 110 p += "/"; 111 p += name; 112 return toURIish(p); 113 } 114 115 /** 116 * Get requests. 117 * 118 * @return list of events 119 */ getRequests()120 protected List<AccessEvent> getRequests() { 121 return server.getRequests(); 122 } 123 124 /** 125 * Get requests. 126 * 127 * @param base 128 * @param path 129 * 130 * @return list of events 131 */ getRequests(URIish base, String path)132 protected List<AccessEvent> getRequests(URIish base, String path) { 133 return server.getRequests(base, path); 134 } 135 136 /** 137 * Get requests. 138 * 139 * @param path 140 * 141 * @return list of events 142 */ getRequests(String path)143 protected List<AccessEvent> getRequests(String path) { 144 return server.getRequests(path); 145 } 146 147 /** 148 * Run fsck 149 * 150 * @param db 151 * @param tips 152 * @throws Exception 153 */ fsck(Repository db, RevObject... tips)154 protected static void fsck(Repository db, RevObject... tips) 155 throws Exception { 156 try (TestRepository<? extends Repository> tr = 157 new TestRepository<>(db)) { 158 tr.fsck(tips); 159 } 160 } 161 162 /** 163 * Mirror refs 164 * 165 * @param refs 166 * @return set of RefSpecs 167 */ mirror(String... refs)168 protected static Set<RefSpec> mirror(String... refs) { 169 HashSet<RefSpec> r = new HashSet<>(); 170 for (String name : refs) { 171 RefSpec rs = new RefSpec(name); 172 rs = rs.setDestination(name); 173 rs = rs.setForceUpdate(true); 174 r.add(rs); 175 } 176 return r; 177 } 178 179 /** 180 * Push a commit 181 * 182 * @param from 183 * @param q 184 * @return collection of RefUpdates 185 * @throws IOException 186 */ push(TestRepository from, RevCommit q)187 protected static Collection<RemoteRefUpdate> push(TestRepository from, 188 RevCommit q) throws IOException { 189 final Repository db = from.getRepository(); 190 final String srcExpr = q.name(); 191 final String dstName = master; 192 final boolean forceUpdate = true; 193 final String localName = null; 194 final ObjectId oldId = null; 195 196 RemoteRefUpdate u = new RemoteRefUpdate(db, srcExpr, dstName, 197 forceUpdate, localName, oldId); 198 return Collections.singleton(u); 199 } 200 201 /** 202 * Create loose object path 203 * 204 * @param base 205 * @param id 206 * @return path of the loose object 207 */ loose(URIish base, AnyObjectId id)208 public static String loose(URIish base, AnyObjectId id) { 209 final String objectName = id.name(); 210 final String d = objectName.substring(0, 2); 211 final String f = objectName.substring(2); 212 return join(base, "objects/" + d + "/" + f); 213 } 214 215 /** 216 * Join a base URIish and a path 217 * 218 * @param base 219 * @param path 220 * a relative path 221 * @return the joined path 222 */ join(URIish base, String path)223 public static String join(URIish base, String path) { 224 if (path.startsWith("/")) 225 fail("Cannot join absolute path " + path + " to URIish " + base); 226 227 String dir = base.getPath(); 228 if (!dir.endsWith("/")) 229 dir += "/"; 230 return dir + path; 231 } 232 233 /** 234 * Rewrite a url 235 * 236 * @param url 237 * @param newProtocol 238 * @param newPort 239 * @return the rewritten url 240 */ rewriteUrl(String url, String newProtocol, int newPort)241 protected static String rewriteUrl(String url, String newProtocol, 242 int newPort) { 243 String newUrl = url; 244 if (newProtocol != null && !newProtocol.isEmpty()) { 245 int schemeEnd = newUrl.indexOf("://"); 246 if (schemeEnd >= 0) { 247 newUrl = newProtocol + newUrl.substring(schemeEnd); 248 } 249 } 250 if (newPort > 0) { 251 newUrl = newUrl.replaceFirst(":\\d+/", ":" + newPort + "/"); 252 } else { 253 // Remove the port, if any 254 newUrl = newUrl.replaceFirst(":\\d+/", "/"); 255 } 256 return newUrl; 257 } 258 259 /** 260 * Extend a path 261 * 262 * @param uri 263 * @param pathComponents 264 * @return the extended URIish 265 * @throws URISyntaxException 266 */ extendPath(URIish uri, String pathComponents)267 protected static URIish extendPath(URIish uri, String pathComponents) 268 throws URISyntaxException { 269 String raw = uri.toString(); 270 String newComponents = pathComponents; 271 if (!newComponents.startsWith("/")) { 272 newComponents = '/' + newComponents; 273 } 274 if (!newComponents.endsWith("/")) { 275 newComponents += '/'; 276 } 277 int i = raw.lastIndexOf('/'); 278 raw = raw.substring(0, i) + newComponents + raw.substring(i + 1); 279 return new URIish(raw); 280 } 281 } 282