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