/* Copyright (c) 2012-2014 Boundless and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/edl-v10.html
*
* Contributors:
* Gabriel Roldan (Boundless) - initial implementation
*/
package org.locationtech.geogig.api.porcelain;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.locationtech.geogig.api.Context;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.Platform;
import org.locationtech.geogig.api.Ref;
import org.locationtech.geogig.api.RevTree;
import org.locationtech.geogig.api.plumbing.RefParse;
import org.locationtech.geogig.api.plumbing.ResolveGeogigDir;
import org.locationtech.geogig.api.plumbing.UpdateRef;
import org.locationtech.geogig.api.plumbing.UpdateSymRef;
import org.locationtech.geogig.di.PluginDefaults;
import org.locationtech.geogig.repository.Repository;
import org.locationtech.geogig.repository.RepositoryConnectionException;
import org.locationtech.geogig.storage.ObjectDatabase;
import org.locationtech.geogig.storage.memory.HeapObjectDatabse;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.base.Optional;
/**
*
*/
public class InitOpTest {
private Platform platform;
private Context injector;
private PluginDefaults defaults;
private InitOp init;
@Rule
public final TemporaryFolder tempFolder = new TemporaryFolder();
private File workingDir;
private Repository mockRepo;
private RefParse mockRefParse;
private UpdateRef mockUpdateRef;
private UpdateSymRef mockUpdateSymRef;
private ObjectDatabase objectDatabase;
@Rule
public ExpectedException exception = ExpectedException.none();
@Before
public void setUp() throws IOException, RepositoryConnectionException {
injector = mock(Context.class);
mockRefParse = mock(RefParse.class);
when(mockRefParse.setName(anyString())).thenReturn(mockRefParse);
mockUpdateRef = mock(UpdateRef.class);
when(mockUpdateRef.setName(anyString())).thenReturn(mockUpdateRef);
when(mockUpdateRef.setDelete(anyBoolean())).thenReturn(mockUpdateRef);
when(mockUpdateRef.setNewValue((ObjectId) anyObject())).thenReturn(mockUpdateRef);
when(mockUpdateRef.setOldValue((ObjectId) anyObject())).thenReturn(mockUpdateRef);
when(mockUpdateRef.setReason(anyString())).thenReturn(mockUpdateRef);
mockUpdateSymRef = mock(UpdateSymRef.class);
when(mockUpdateSymRef.setName(anyString())).thenReturn(mockUpdateSymRef);
when(mockUpdateSymRef.setDelete(anyBoolean())).thenReturn(mockUpdateSymRef);
when(mockUpdateSymRef.setNewValue(anyString())).thenReturn(mockUpdateSymRef);
when(mockUpdateSymRef.setOldValue(anyString())).thenReturn(mockUpdateSymRef);
when(mockUpdateSymRef.setReason(anyString())).thenReturn(mockUpdateSymRef);
when(injector.command(eq(RefParse.class))).thenReturn(mockRefParse);
when(injector.command(eq(UpdateRef.class))).thenReturn(mockUpdateRef);
when(injector.command(eq(UpdateSymRef.class))).thenReturn(mockUpdateSymRef);
platform = mock(Platform.class);
when(injector.platform()).thenReturn(platform);
defaults = PluginDefaults.NO_PLUGINS;
init = new InitOp(defaults);
init.setContext(injector);
mockRepo = mock(Repository.class);
objectDatabase = new HeapObjectDatabse();
when(mockRepo.objectDatabase()).thenReturn(objectDatabase);
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
objectDatabase.open();
return null;
}
}).when(mockRepo).open();
workingDir = tempFolder.getRoot();
when(platform.pwd()).thenReturn(workingDir);
}
@Test
public void testNullWorkingDir() {
when(platform.pwd()).thenReturn(null);
exception.expect(IllegalStateException.class);
init.call();
when(platform.pwd()).thenReturn(workingDir);
}
@Test
public void testCreateNewRepo() throws Exception {
when(injector.repository()).thenReturn(mockRepo);
Optional<Ref> absent = Optional.absent();
when(mockRefParse.call()).thenReturn(absent);
Repository created = init.call();
assertSame(mockRepo, created);
assertTrue(new File(workingDir, ".geogig").exists());
assertTrue(new File(workingDir, ".geogig").isDirectory());
verify(injector, times(1)).repository();
verify(platform, atLeastOnce()).pwd();
verify(mockUpdateRef, times(1)).setName(eq(Ref.MASTER));
verify(mockUpdateRef, times(1)).setName(eq(Ref.WORK_HEAD));
verify(mockUpdateRef, times(1)).setName(eq(Ref.STAGE_HEAD));
verify(mockUpdateRef, times(1)).setNewValue(eq(ObjectId.NULL));
verify(mockUpdateRef, times(2)).setNewValue(eq(RevTree.EMPTY_TREE_ID));
verify(mockUpdateRef, times(3)).setReason(anyString());
verify(mockUpdateRef, times(3)).call();
verify(mockUpdateSymRef, times(1)).setName(eq(Ref.HEAD));
verify(mockUpdateSymRef, times(1)).setNewValue(eq(Ref.MASTER));
verify(mockUpdateSymRef, times(1)).call();
assertEquals(RevTree.EMPTY, objectDatabase.get(RevTree.EMPTY_TREE_ID));
}
@Test
public void testReinitializeExistingRepo() throws Exception {
when(injector.repository()).thenReturn(mockRepo);
Optional<Ref> absent = Optional.absent();
when(mockRefParse.call()).thenReturn(absent);
Repository created = init.call();
assertSame(mockRepo, created);
verify(mockUpdateRef, times(3)).call();
verify(mockUpdateSymRef, times(1)).call();
assertTrue(new File(workingDir, ".geogig").exists());
assertTrue(new File(workingDir, ".geogig").isDirectory());
Ref master = new Ref(Ref.MASTER, ObjectId.forString("hash me"));
when(mockRefParse.call()).thenReturn(Optional.of(master));
Context injector = mock(Context.class);
when(injector.command(eq(RefParse.class))).thenReturn(mockRefParse);
when(injector.platform()).thenReturn(platform);
when(injector.repository()).thenReturn(mockRepo);
init.setContext(injector);
assertTrue(ResolveGeogigDir.lookup(platform.pwd()).isPresent());
assertNotNull(init.call());
verify(platform, atLeastOnce()).pwd();
assertTrue(ResolveGeogigDir.lookup(platform.pwd()).isPresent());
verify(injector, never()).command(eq(UpdateRef.class));
verify(injector, never()).command(eq(UpdateSymRef.class));
assertEquals(RevTree.EMPTY, objectDatabase.get(RevTree.EMPTY_TREE_ID));
}
@Test
public void testReinitializeExistingRepoFromInsideASubdirectory() throws Exception {
testCreateNewRepo();
File subDir = new File(new File(workingDir, "subdir1"), "subdir2");
assertTrue(subDir.mkdirs());
when(platform.pwd()).thenReturn(subDir);
assertTrue(ResolveGeogigDir.lookup(platform.pwd()).isPresent());
assertNotNull(init.call());
verify(platform, atLeastOnce()).pwd();
}
}