2 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.transport
;
40 import java
.io
.IOException
;
41 import java
.util
.HashMap
;
42 import java
.util
.HashSet
;
45 import org
.spearce
.jgit
.errors
.NotSupportedException
;
46 import org
.spearce
.jgit
.errors
.TransportException
;
47 import org
.spearce
.jgit
.lib
.ObjectId
;
48 import org
.spearce
.jgit
.lib
.ProgressMonitor
;
49 import org
.spearce
.jgit
.lib
.Ref
;
50 import org
.spearce
.jgit
.lib
.Repository
;
51 import org
.spearce
.jgit
.lib
.RepositoryTestCase
;
52 import org
.spearce
.jgit
.lib
.TextProgressMonitor
;
53 import org
.spearce
.jgit
.lib
.RefUpdate
.Result
;
54 import org
.spearce
.jgit
.transport
.RemoteRefUpdate
.Status
;
56 public class PushProcessTest
extends RepositoryTestCase
{
57 private PushProcess process
;
59 private MockTransport transport
;
61 private HashSet
<RemoteRefUpdate
> refUpdates
;
63 private HashSet
<Ref
> advertisedRefs
;
65 private Status connectionUpdateStatus
;
68 public void setUp() throws Exception
{
70 transport
= new MockTransport(db
, new URIish());
71 refUpdates
= new HashSet
<RemoteRefUpdate
>();
72 advertisedRefs
= new HashSet
<Ref
>();
73 connectionUpdateStatus
= Status
.OK
;
77 * Test for fast-forward remote update.
81 public void testUpdateFastForward() throws IOException
{
82 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
83 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
84 "refs/heads/master", false, null, null);
85 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
86 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
87 testOneUpdateStatus(rru
, ref
, Status
.OK
, true);
91 * Test for non fast-forward remote update, when remote object is not known
92 * to local repository.
96 public void testUpdateNonFastForwardUnknownObject() throws IOException
{
97 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
98 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
99 "refs/heads/master", false, null, null);
100 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
101 ObjectId
.fromString("0000000000000000000000000000000000000001"));
102 testOneUpdateStatus(rru
, ref
, Status
.REJECTED_NONFASTFORWARD
, null);
106 * Test for non fast-forward remote update, when remote object is known to
107 * local repository, but it is not an ancestor of new object.
109 * @throws IOException
111 public void testUpdateNonFastForward() throws IOException
{
112 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
113 "ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
114 "refs/heads/master", false, null, null);
115 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
116 ObjectId
.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9"));
117 testOneUpdateStatus(rru
, ref
, Status
.REJECTED_NONFASTFORWARD
, null);
121 * Test for non fast-forward remote update, when force update flag is set.
123 * @throws IOException
125 public void testUpdateNonFastForwardForced() throws IOException
{
126 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
127 "ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
128 "refs/heads/master", true, null, null);
129 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
130 ObjectId
.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9"));
131 testOneUpdateStatus(rru
, ref
, Status
.OK
, false);
135 * Test for remote ref creation.
137 * @throws IOException
139 public void testUpdateCreateRef() throws IOException
{
140 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
141 "ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
142 "refs/heads/master", false, null, null);
143 testOneUpdateStatus(rru
, null, Status
.OK
, true);
147 * Test for remote ref deletion.
149 * @throws IOException
151 public void testUpdateDelete() throws IOException
{
152 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
, null,
153 "refs/heads/master", false, null, null);
154 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
155 ObjectId
.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9"));
156 testOneUpdateStatus(rru
, ref
, Status
.OK
, true);
160 * Test for remote ref deletion (try), when that ref doesn't exist on remote
163 * @throws IOException
165 public void testUpdateDeleteNonExisting() throws IOException
{
166 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
, null,
167 "refs/heads/master", false, null, null);
168 testOneUpdateStatus(rru
, null, Status
.NON_EXISTING
, null);
172 * Test for remote ref update, when it is already up to date.
174 * @throws IOException
176 public void testUpdateUpToDate() throws IOException
{
177 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
178 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
179 "refs/heads/master", false, null, null);
180 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
181 ObjectId
.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9"));
182 testOneUpdateStatus(rru
, ref
, Status
.UP_TO_DATE
, null);
186 * Test for remote ref update with expected remote object.
188 * @throws IOException
190 public void testUpdateExpectedRemote() throws IOException
{
191 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
192 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
193 "refs/heads/master", false, null, ObjectId
194 .fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
195 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
196 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
197 testOneUpdateStatus(rru
, ref
, Status
.OK
, true);
201 * Test for remote ref update with expected old object set, when old object
202 * is not that expected one.
204 * @throws IOException
206 public void testUpdateUnexpectedRemote() throws IOException
{
207 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
208 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
209 "refs/heads/master", false, null, ObjectId
210 .fromString("0000000000000000000000000000000000000001"));
211 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
212 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
213 testOneUpdateStatus(rru
, ref
, Status
.REJECTED_REMOTE_CHANGED
, null);
217 * Test for remote ref update with expected old object set, when old object
218 * is not that expected one and force update flag is set (which should have
219 * lower priority) - shouldn't change behavior.
221 * @throws IOException
223 public void testUpdateUnexpectedRemoteVsForce() throws IOException
{
224 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
225 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
226 "refs/heads/master", true, null, ObjectId
227 .fromString("0000000000000000000000000000000000000001"));
228 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
229 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
230 testOneUpdateStatus(rru
, ref
, Status
.REJECTED_REMOTE_CHANGED
, null);
234 * Test for remote ref update, when connection rejects update.
236 * @throws IOException
238 public void testUpdateRejectedByConnection() throws IOException
{
239 connectionUpdateStatus
= Status
.REJECTED_OTHER_REASON
;
240 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
241 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
242 "refs/heads/master", false, null, null);
243 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
244 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
245 testOneUpdateStatus(rru
, ref
, Status
.REJECTED_OTHER_REASON
, null);
249 * Test for remote refs updates with mixed cases that shouldn't depend on
252 * @throws IOException
254 public void testUpdateMixedCases() throws IOException
{
255 final RemoteRefUpdate rruOk
= new RemoteRefUpdate(db
, null,
256 "refs/heads/master", false, null, null);
257 final Ref refToChange
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
258 ObjectId
.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9"));
259 final RemoteRefUpdate rruReject
= new RemoteRefUpdate(db
, null,
260 "refs/heads/nonexisting", false, null, null);
261 refUpdates
.add(rruOk
);
262 refUpdates
.add(rruReject
);
263 advertisedRefs
.add(refToChange
);
265 assertEquals(Status
.OK
, rruOk
.getStatus());
266 assertEquals(true, rruOk
.isFastForward());
267 assertEquals(Status
.NON_EXISTING
, rruReject
.getStatus());
271 * Test for local tracking ref update.
273 * @throws IOException
275 public void testTrackingRefUpdateEnabled() throws IOException
{
276 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
277 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
278 "refs/heads/master", false, "refs/remotes/test/master", null);
279 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
280 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
282 advertisedRefs
.add(ref
);
283 final PushResult result
= executePush();
284 final TrackingRefUpdate tru
= result
285 .getTrackingRefUpdate("refs/remotes/test/master");
287 assertEquals("refs/remotes/test/master", tru
.getLocalName());
288 assertEquals(Result
.NEW
, tru
.getResult());
292 * Test for local tracking ref update disabled.
294 * @throws IOException
296 public void testTrackingRefUpdateDisabled() throws IOException
{
297 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
298 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
299 "refs/heads/master", false, null, null);
300 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
301 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
303 advertisedRefs
.add(ref
);
304 final PushResult result
= executePush();
305 assertTrue(result
.getTrackingRefUpdates().isEmpty());
309 * Test for local tracking ref update when remote update has failed.
311 * @throws IOException
313 public void testTrackingRefUpdateOnReject() throws IOException
{
314 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
315 "ac7e7e44c1885efb472ad54a78327d66bfc4ecef",
316 "refs/heads/master", false, null, null);
317 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
318 ObjectId
.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9"));
319 final PushResult result
= testOneUpdateStatus(rru
, ref
,
320 Status
.REJECTED_NONFASTFORWARD
, null);
321 assertTrue(result
.getTrackingRefUpdates().isEmpty());
325 * Test for push operation result - that contains expected elements.
327 * @throws IOException
329 public void testPushResult() throws IOException
{
330 final RemoteRefUpdate rru
= new RemoteRefUpdate(db
,
331 "2c349335b7f797072cf729c4f3bb0914ecb6dec9",
332 "refs/heads/master", false, "refs/remotes/test/master", null);
333 final Ref ref
= new Ref(Ref
.Storage
.LOOSE
, "refs/heads/master",
334 ObjectId
.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef"));
336 advertisedRefs
.add(ref
);
337 final PushResult result
= executePush();
338 assertEquals(1, result
.getTrackingRefUpdates().size());
339 assertEquals(1, result
.getAdvertisedRefs().size());
340 assertEquals(1, result
.getRemoteUpdates().size());
341 assertNotNull(result
.getTrackingRefUpdate("refs/remotes/test/master"));
342 assertNotNull(result
.getAdvertisedRef("refs/heads/master"));
343 assertNotNull(result
.getRemoteUpdate("refs/heads/master"));
346 private PushResult
testOneUpdateStatus(final RemoteRefUpdate rru
,
347 final Ref advertisedRef
, final Status expectedStatus
,
348 Boolean fastForward
) throws NotSupportedException
,
351 if (advertisedRef
!= null)
352 advertisedRefs
.add(advertisedRef
);
353 final PushResult result
= executePush();
354 assertEquals(expectedStatus
, rru
.getStatus());
355 if (fastForward
!= null)
356 assertEquals(fastForward
.booleanValue(), rru
.isFastForward());
360 private PushResult
executePush() throws NotSupportedException
,
362 process
= new PushProcess(transport
, refUpdates
);
363 return process
.execute(new TextProgressMonitor());
366 private class MockTransport
extends Transport
{
367 MockTransport(Repository local
, URIish uri
) {
372 public FetchConnection
openFetch() throws NotSupportedException
,
374 throw new NotSupportedException("mock");
378 public PushConnection
openPush() throws NotSupportedException
,
380 return new MockPushConnection();
384 public void close() {
389 private class MockPushConnection
extends BaseConnection
implements
391 MockPushConnection() {
392 final Map
<String
, Ref
> refsMap
= new HashMap
<String
, Ref
>();
393 for (final Ref r
: advertisedRefs
)
394 refsMap
.put(r
.getName(), r
);
399 public void close() {
403 public void push(ProgressMonitor monitor
,
404 Map
<String
, RemoteRefUpdate
> refsToUpdate
)
405 throws TransportException
{
406 for (final RemoteRefUpdate rru
: refsToUpdate
.values()) {
407 assertEquals(Status
.NOT_ATTEMPTED
, rru
.getStatus());
408 rru
.setStatus(connectionUpdateStatus
);