package uk.ac.ox.zoo.seeg.abraid.mp.common.service.workflow.support.runrequest; import org.apache.commons.io.FileUtils; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import uk.ac.ox.zoo.seeg.abraid.mp.common.config.ConfigurationService; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.workflow.support.GitSourceCodeManager; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.workflow.support.SourceCodeManager; import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; import static com.googlecode.catchexception.CatchException.catchException; import static com.googlecode.catchexception.CatchException.caughtException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** * Tests for GitSourceCodeManager. * Copyright (c) 2014 University of Oxford */ public class GitSourceCodeManagerTest { @Rule public TemporaryFolder workingDir = new TemporaryFolder(); ///CHECKSTYLE:SUPPRESS VisibilityModifier @Rule public TemporaryFolder cacheDir = new TemporaryFolder(); ///CHECKSTYLE:SUPPRESS VisibilityModifier @Test public void updateRepositoryClonesRepositoryIfNeeded() throws Exception { // Arrange setupSourceCodeManager(setUpFakeRepo()); // Assert File baseRepoCacheDir = Paths.get(cacheDir.getRoot().toString(), "repos").toFile(); assertThat(baseRepoCacheDir.listFiles()).hasSize(1); File repoCacheDir = baseRepoCacheDir.listFiles()[0]; assertThat(getGitLogMessages(repoCacheDir)).containsOnly("foobar"); assertThat(FileUtils.readFileToString(Paths.get(repoCacheDir.getAbsolutePath(), ".git/config").toFile())) .contains("sharedRepository = group"); } @Test public void updateRepositoryPullsRepositoryIfNeeded() throws Exception { // Arrange SourceCodeManager target = setupSourceCodeManager(setUpFakeRepo()); File repoCacheDir = getRepoCloneDir(); // Act addCommitToRepo(repoCacheDir, "expected message"); target.updateRepository(); // Assert assertThat(getGitLogMessages(repoCacheDir)).containsOnly("foobar", "expected message"); } @Test public void getAvailableVersionsReturnsTags() throws Exception { // Arrange SourceCodeManager target = setupSourceCodeManager(setUpFakeRepo()); File repoCacheDir = getRepoCloneDir(); // Act addTagToRepo(repoCacheDir, "expected_tag"); List<String> result = target.getAvailableVersions(); // Assert assertThat(result).containsOnly("expected_tag"); } @Test public void provisionCopiesCode() throws Exception { // Arrange ConfigurationService configurationService = setUpFakeRepo(); SourceCodeManager target = setupSourceCodeManager(configurationService); File repoCacheDir = getRepoCloneDir(); File targetDir = workingDir.newFolder(); when(configurationService.getModelRepositoryVersion()).thenReturn("expected_tag"); // Act addTagToRepo(repoCacheDir, "expected_tag"); target.provision(targetDir); // Assert assertThat(targetDir.listFiles()).hasSize(1); assertThat(Paths.get(targetDir.toString(), ".git").toFile()).doesNotExist(); } @Test public void getSupportedModesForCurrentVersionReturnsCorrectModes() throws Exception { // Arrange ConfigurationService configurationService = setUpFakeRepo(); SourceCodeManager target = setupSourceCodeManager(configurationService); File repoCacheDir = getRepoCloneDir(); addFileToRepo(repoCacheDir, "data/abraid_modes.txt", "mode1\nmode2\nmode3\n"); when(configurationService.getModelRepositoryVersion()).thenReturn("expected_tag"); addTagToRepo(repoCacheDir, "expected_tag"); // Act Set<String> result = target.getSupportedModesForCurrentVersion(); // Assert assertThat(result).containsOnly("mode1", "mode2", "mode3"); } @Test public void provisionRejectsInvalidVersions() throws Exception { // Arrange ConfigurationService configurationService = setUpFakeRepo(); SourceCodeManager target = setupSourceCodeManager(configurationService); File repoCacheDir = getRepoCloneDir(); File targetDir = workingDir.newFolder(); when(configurationService.getModelRepositoryVersion()).thenReturn("expected_tag"); // Act addTagToRepo(repoCacheDir, "bad_tag"); catchException(target).provision(targetDir); // Assert assertThat(caughtException()).isInstanceOf(IllegalArgumentException.class).hasMessage("No such version"); } private Repository createGitRepository() throws Exception { File dir = workingDir.newFolder(); // Init repo File gitDir = Paths.get(dir.toString(), ".git").toFile(); Repository repo = FileRepositoryBuilder.create(gitDir); repo.create(); addCommitToRepo(repo.getDirectory().getParentFile(), "foobar"); return repo; } private void addCommitToRepo(File repo, String message) throws Exception { Git git = getGitFacade(repo); File randomFile = Paths.get(repo.toString(), UUID.randomUUID().toString().substring(0, 8)).toFile(); FileUtils.writeStringToFile(randomFile, UUID.randomUUID().toString()); git.add().addFilepattern(randomFile.getName()).call(); git.commit().setMessage(message).call(); } private List<String> getGitLogMessages(File repo) throws Exception { Git git = getGitFacade(repo); List<String> log = new ArrayList<>(); for (RevCommit commit : git.log().call()) { log.add(commit.getFullMessage()); } return log; } private void addTagToRepo(File repo, String id) throws Exception { Git git = getGitFacade(repo); git.tag().setName(id).call(); } private void addFileToRepo(File repo, String file, String content) throws Exception { Git git = getGitFacade(repo); File newFile = Paths.get(repo.getAbsolutePath(), file).toFile(); FileUtils.writeStringToFile(newFile, content); git.add().addFilepattern(file).call(); git.commit().setMessage("new file").call(); } private Git getGitFacade(File repo) throws IOException { FileRepositoryBuilder builder = new FileRepositoryBuilder(); Repository repository = builder.setGitDir(Paths.get(repo.toString(), ".git").toFile()) .readEnvironment() .findGitDir() .build(); return new Git(repository); } private File getRepoCloneDir() { return Paths.get(cacheDir.getRoot().toString(), "repos").toFile().listFiles()[0]; } private ConfigurationService setUpFakeRepo() throws Exception { Repository repo = createGitRepository(); ConfigurationService configurationService = mock(ConfigurationService.class); when(configurationService.getModelRepositoryUrl()).thenReturn(repo.getDirectory().getParent()); return configurationService; } private SourceCodeManager setupSourceCodeManager(ConfigurationService configurationService) throws Exception { SourceCodeManager target = new GitSourceCodeManager(configurationService, Paths.get(cacheDir.getRoot().toString(), "repos").toString()); target.updateRepository(); // initial clone return target; } }