Cleanup tests for repository dao

This commit is contained in:
René Pfeuffer
2019-05-14 10:08:45 +02:00
parent c63510536a
commit e0ad5c76a7
3 changed files with 241 additions and 347 deletions

View File

@@ -13,6 +13,7 @@ public abstract class RepositoryLocationResolver {
return create(type); return create(type);
} }
@FunctionalInterface
public interface RepositoryLocationResolverInstance<T> { public interface RepositoryLocationResolverInstance<T> {
T getLocation(String repositoryId); T getLocation(String repositoryId);
} }

View File

@@ -62,7 +62,6 @@ public class XmlRepositoryDAO implements RepositoryDAO {
private final MetadataStore metadataStore = new MetadataStore(); private final MetadataStore metadataStore = new MetadataStore();
private final SCMContextProvider context;
private final PathBasedRepositoryLocationResolver repositoryLocationResolver; private final PathBasedRepositoryLocationResolver repositoryLocationResolver;
private final FileSystem fileSystem; private final FileSystem fileSystem;
@@ -70,8 +69,7 @@ public class XmlRepositoryDAO implements RepositoryDAO {
private final Map<NamespaceAndName, Repository> byNamespaceAndName; private final Map<NamespaceAndName, Repository> byNamespaceAndName;
@Inject @Inject
public XmlRepositoryDAO(SCMContextProvider context, PathBasedRepositoryLocationResolver repositoryLocationResolver, FileSystem fileSystem) { public XmlRepositoryDAO(PathBasedRepositoryLocationResolver repositoryLocationResolver, FileSystem fileSystem) {
this.context = context;
this.repositoryLocationResolver = repositoryLocationResolver; this.repositoryLocationResolver = repositoryLocationResolver;
this.fileSystem = fileSystem; this.fileSystem = fileSystem;
@@ -165,7 +163,9 @@ public class XmlRepositoryDAO implements RepositoryDAO {
byNamespaceAndName.put(clone.getNamespaceAndName(), clone); byNamespaceAndName.put(clone.getNamespaceAndName(), clone);
} }
Path repositoryPath = repositoryLocationResolver.create(Path.class).getLocation(repository.getId()); Path repositoryPath = repositoryLocationResolver
.create(Path.class)
.getLocation(repository.getId());
Path metadataPath = resolveDataPath(repositoryPath); Path metadataPath = resolveDataPath(repositoryPath);
metadataStore.write(metadataPath, clone); metadataStore.write(metadataPath, clone);
} }

View File

@@ -2,64 +2,86 @@ package sonia.scm.repository.xml;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.junitpioneer.jupiter.TempDirectory; import org.junitpioneer.jupiter.TempDirectory;
import org.mockito.Answers; import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness; import org.mockito.quality.Strictness;
import sonia.scm.SCMContextProvider; import sonia.scm.SCMContextProvider;
import sonia.scm.io.DefaultFileSystem; import sonia.scm.io.DefaultFileSystem;
import sonia.scm.io.FileSystem; import sonia.scm.io.FileSystem;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryPermission;
import sonia.scm.util.IOUtil;
import sun.misc.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.BiConsumer;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static sonia.scm.repository.RepositoryTestData.createHeartOfGold;
@ExtendWith({MockitoExtension.class, TempDirectory.class}) @ExtendWith({MockitoExtension.class, TempDirectory.class})
@MockitoSettings(strictness = Strictness.LENIENT) @MockitoSettings(strictness = Strictness.LENIENT)
class XmlRepositoryDAOTest { class XmlRepositoryDAOTest {
private static final Repository REPOSITORY = createRepository("42"); private final Repository REPOSITORY = createRepository("42");
@Mock @Mock
private SCMContextProvider context;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PathBasedRepositoryLocationResolver locationResolver; private PathBasedRepositoryLocationResolver locationResolver;
@Captor
private ArgumentCaptor<BiConsumer<String, Path>> forAllCaptor;
private FileSystem fileSystem = new DefaultFileSystem(); private FileSystem fileSystem = new DefaultFileSystem();
private XmlRepositoryDAO dao; private XmlRepositoryDAO dao;
private Path basePath;
@BeforeEach @BeforeEach
void createDAO(@TempDirectory.TempDir Path basePath) { void createDAO(@TempDirectory.TempDir Path basePath) {
this.basePath = basePath; when(locationResolver.create(Path.class)).thenReturn(locationResolver::create);
when(locationResolver.create(anyString())).thenAnswer(invocation -> createMockedRepoPath(basePath, invocation));
when(locationResolver.create(anyString())).thenAnswer(invocation -> {
Path resolvedPath = basePath.resolve(invocation.getArgument(0).toString());
Files.createDirectories(resolvedPath);
return resolvedPath;
});
when(locationResolver.remove(anyString())).thenAnswer(invocation -> basePath.resolve(invocation.getArgument(0).toString())); when(locationResolver.remove(anyString())).thenAnswer(invocation -> basePath.resolve(invocation.getArgument(0).toString()));
when(context.getBaseDirectory()).thenReturn(basePath.toFile());
dao = createDAO();
} }
private XmlRepositoryDAO createDAO() { private Path createMockedRepoPath(@TempDirectory.TempDir Path basePath, InvocationOnMock invocation) {
return new XmlRepositoryDAO(context, locationResolver, fileSystem); Path resolvedPath = basePath.resolve(invocation.getArgument(0).toString());
try {
Files.createDirectories(resolvedPath);
} catch (IOException e) {
fail(e);
}
return resolvedPath;
}
@Nested
class WithEmptyDatabase {
@BeforeEach
void createDAO() {
dao = new XmlRepositoryDAO(locationResolver, fileSystem);
} }
@Test @Test
@@ -120,272 +142,143 @@ class XmlRepositoryDAOTest {
assertThat(content).contains("change"); assertThat(content).contains("change");
} }
// @Test @Test
// void shouldReturnFalseForEachContainsMethod() { void shouldReturnFalseForEachContainsMethod() {
// Repository heartOfGold = createHeartOfGold(); assertThat(dao.contains(REPOSITORY)).isFalse();
// assertThat(dao.contains(REPOSITORY.getId())).isFalse();
// assertThat(dao.contains(heartOfGold)).isFalse(); assertThat(dao.contains(REPOSITORY.getNamespaceAndName())).isFalse();
// assertThat(dao.contains(heartOfGold.getId())).isFalse(); }
// assertThat(dao.contains(heartOfGold.getNamespaceAndName())).isFalse();
// } @Test
// void shouldReturnNullForEachGetMethod() {
// @Test assertThat(dao.get("42")).isNull();
// void shouldReturnNullForEachGetMethod() { assertThat(dao.get(new NamespaceAndName("hitchhiker", "HeartOfGold"))).isNull();
// assertThat(dao.get("42")).isNull(); }
// assertThat(dao.get(new NamespaceAndName("hitchhiker","HeartOfGold"))).isNull();
// } @Test
// void shouldReturnRepository() {
// @Test dao.add(REPOSITORY);
// void shouldReturnRepository() {
// Repository heartOfGold = createHeartOfGold(); assertThat(dao.get("42")).isEqualTo(REPOSITORY);
// dao.add(heartOfGold); assertThat(dao.get(new NamespaceAndName("space", "42"))).isEqualTo(REPOSITORY);
// }
// assertThat(dao.get("42")).isEqualTo(heartOfGold);
// assertThat(dao.get(new NamespaceAndName("hitchhiker","HeartOfGold"))).isEqualTo(heartOfGold); @Test
// } void shouldNotReturnTheSameInstance() {
// dao.add(REPOSITORY);
// @Test
// void shouldNotReturnTheSameInstance() { Repository repository = dao.get("42");
// Repository heartOfGold = createHeartOfGold(); assertThat(repository).isNotSameAs(REPOSITORY);
// dao.add(heartOfGold); }
//
// Repository repository = dao.get("42"); @Test
// assertThat(repository).isNotSameAs(heartOfGold); void shouldReturnAllRepositories() {
// } dao.add(REPOSITORY);
//
// @Test Repository secondRepository = createRepository("23");
// void shouldReturnAllRepositories() { dao.add(secondRepository);
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold); Collection<Repository> repositories = dao.getAll();
// assertThat(repositories)
// Repository puzzle = createPuzzle(); .containsExactlyInAnyOrder(REPOSITORY, secondRepository);
// dao.add(puzzle); }
//
// Collection<Repository> repositories = dao.getAll(); @Test
// assertThat(repositories).containsExactlyInAnyOrder(heartOfGold, puzzle); void shouldModifyRepositoryTwice() {
// } REPOSITORY.setDescription("HeartOfGold");
// dao.add(REPOSITORY);
// private Repository createPuzzle() { assertThat(dao.get("42").getDescription()).isEqualTo("HeartOfGold");
// Repository puzzle = RepositoryTestData.create42Puzzle();
// puzzle.setId("42+1"); Repository heartOfGold = createRepository("42");
// return puzzle; heartOfGold.setDescription("Heart of Gold");
// } dao.modify(heartOfGold);
//
// @Test assertThat(dao.get("42").getDescription()).isEqualTo("Heart of Gold");
// void shouldModifyRepository() { }
// Repository heartOfGold = createHeartOfGold();
// heartOfGold.setDescription("HeartOfGold"); @Test
// dao.add(heartOfGold); void shouldRemoveRepository() {
// assertThat(dao.get("42").getDescription()).isEqualTo("HeartOfGold"); dao.add(REPOSITORY);
// assertThat(dao.contains("42")).isTrue();
// heartOfGold = createHeartOfGold();
// heartOfGold.setDescription("Heart of Gold"); dao.delete(REPOSITORY);
// dao.modify(heartOfGold); assertThat(dao.contains("42")).isFalse();
// assertThat(dao.contains(REPOSITORY.getNamespaceAndName())).isFalse();
// assertThat(dao.get("42").getDescription()).isEqualTo("Heart of Gold");
// } Path storePath = metadataFile(REPOSITORY.getId());
//
// @Test assertThat(storePath).doesNotExist();
// void shouldRemoveRepository() { }
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold); @Test
// assertThat(dao.contains("42")).isTrue(); void shouldRenameTheRepository() {
// dao.add(REPOSITORY);
// dao.delete(heartOfGold);
// assertThat(dao.contains("42")).isFalse(); REPOSITORY.setNamespace("hg2tg");
// assertThat(dao.contains(new NamespaceAndName("hitchhiker", "HeartOfGold"))).isFalse(); REPOSITORY.setName("hog");
// }
// dao.modify(REPOSITORY);
// @Test
// void shouldUpdateLastModifiedAfterEachWriteOperation() { Repository repository = dao.get("42");
// Repository heartOfGold = createHeartOfGold(); assertThat(repository.getNamespace()).isEqualTo("hg2tg");
// dao.add(heartOfGold); assertThat(repository.getName()).isEqualTo("hog");
//
// Long firstLastModified = dao.getLastModified(); assertThat(dao.contains(new NamespaceAndName("hg2tg", "hog"))).isTrue();
// assertThat(firstLastModified).isNotNull(); assertThat(dao.contains(new NamespaceAndName("hitchhiker", "HeartOfGold"))).isFalse();
//
// Repository puzzle = createPuzzle(); String content = getXmlFileContent(REPOSITORY.getId());
// dao.add(puzzle); assertThat(content).contains("<name>hog</name>");
// }
// Long lastModifiedAdded = dao.getLastModified();
// assertThat(lastModifiedAdded).isGreaterThan(firstLastModified); @Test
// void shouldDeleteRepositoryEvenWithChangedNamespace() {
// heartOfGold.setDescription("Heart of Gold"); dao.add(REPOSITORY);
// dao.modify(heartOfGold);
// REPOSITORY.setNamespace("hg2tg");
// Long lastModifiedModified = dao.getLastModified(); REPOSITORY.setName("hog");
// assertThat(lastModifiedModified).isGreaterThan(lastModifiedAdded);
// dao.delete(REPOSITORY);
// dao.delete(puzzle);
// assertThat(dao.contains(new NamespaceAndName("space", "42"))).isFalse();
// Long lastModifiedRemoved = dao.getLastModified(); }
// assertThat(lastModifiedRemoved).isGreaterThan(lastModifiedModified);
// } @Test
// void shouldRemoveRepositoryDirectoryAfterDeletion() {
// @Test dao.add(REPOSITORY);
// void shouldRenameTheRepository() {
// Repository heartOfGold = createHeartOfGold(); Path path = locationResolver.create(REPOSITORY.getId());
// dao.add(heartOfGold); assertThat(path).isDirectory();
//
// heartOfGold.setNamespace("hg2tg"); dao.delete(REPOSITORY);
// heartOfGold.setName("hog"); assertThat(path).doesNotExist();
// }
// dao.modify(heartOfGold);
// @Test
// Repository repository = dao.get("42"); void shouldPersistPermissions() {
// assertThat(repository.getNamespace()).isEqualTo("hg2tg"); REPOSITORY.setPermissions(asList(new RepositoryPermission("trillian", asList("read", "write"), false), new RepositoryPermission("vogons", singletonList("delete"), true)));
// assertThat(repository.getName()).isEqualTo("hog"); dao.add(REPOSITORY);
//
// assertThat(dao.contains(new NamespaceAndName("hg2tg", "hog"))).isTrue(); String content = getXmlFileContent(REPOSITORY.getId());
// assertThat(dao.contains(new NamespaceAndName("hitchhiker", "HeartOfGold"))).isFalse(); System.out.println(content);
// } assertThat(content).containsSubsequence("trillian", "<verb>read</verb>", "<verb>write</verb>");
// assertThat(content).containsSubsequence("vogons", "<verb>delete</verb>");
// @Test }
// void shouldDeleteRepositoryEvenWithChangedNamespace() { }
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold); @Test
// void shouldReadExistingRepositoriesFromPathDatabase(@TempDirectory.TempDir Path basePath) throws IOException {
// heartOfGold.setNamespace("hg2tg"); doNothing().when(locationResolver).forAllPaths(forAllCaptor.capture());
// heartOfGold.setName("hog"); XmlRepositoryDAO dao = new XmlRepositoryDAO(locationResolver, fileSystem);
//
// dao.delete(heartOfGold); Path repositoryPath = basePath.resolve("existing");
// Files.createDirectories(repositoryPath);
// assertThat(dao.contains(new NamespaceAndName("hitchhiker", "HeartOfGold"))).isFalse(); URL metadataUrl = Resources.getResource("sonia/scm/store/repositoryDaoMetadata.xml");
// } Files.copy(metadataUrl.openStream(), repositoryPath.resolve("metadata.xml"));
//
// @Test forAllCaptor.getValue().accept("existing", repositoryPath);
// void shouldReturnThePathForTheRepository() {
// Path repositoryPath = Paths.get("r", "42"); assertThat(dao.contains(new NamespaceAndName("space", "existing"))).isTrue();
// when(initialLocationResolver.getPath("42")).thenReturn(repositoryPath); }
//
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// Path path = dao.getPath("42");
// assertThat(path).isEqualTo(repositoryPath);
// }
//
// @Test
// void shouldCreateTheDirectoryForTheRepository() {
// Path repositoryPath = Paths.get("r", "42");
// when(initialLocationResolver.getPath("42")).thenReturn(repositoryPath);
//
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// Path path = getAbsolutePathFromDao("42");
// assertThat(path).isDirectory();
// }
//
// @Test
// void shouldRemoveRepositoryDirectoryAfterDeletion() {
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// Path path = getAbsolutePathFromDao(heartOfGold.getId());
// assertThat(path).isDirectory();
//
// dao.delete(heartOfGold);
// assertThat(path).doesNotExist();
// }
//
// private Path getAbsolutePathFromDao(String id) {
// return context.resolve(dao.getPath(id));
// }
//
// @Test
// void shouldCreateRepositoryPathDatabase() throws IOException {
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// Path storePath = dao.resolveStorePath();
// assertThat(storePath).isRegularFile();
//
// String content = content(storePath);
//
// assertThat(content).contains(heartOfGold.getId());
// assertThat(content).contains(dao.getPath(heartOfGold.getId()).toString());
// }
//
// private String content(Path storePath) throws IOException {
// return new String(Files.readAllBytes(storePath), Charsets.UTF_8);
// }
//
// @Test
// void shouldStoreRepositoryMetadataAfterAdd() throws IOException {
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// Path repositoryDirectory = getAbsolutePathFromDao(heartOfGold.getId());
// Path metadataPath = dao.resolveDataPath(repositoryDirectory);
//
// assertThat(metadataPath).isRegularFile();
//
// String content = content(metadataPath);
// assertThat(content).contains(heartOfGold.getName());
// assertThat(content).contains(heartOfGold.getNamespace());
// assertThat(content).contains(heartOfGold.getDescription());
// }
//
// @Test
// void shouldUpdateRepositoryMetadataAfterModify() throws IOException {
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// heartOfGold.setDescription("Awesome Spaceship");
// dao.modify(heartOfGold);
//
// Path repositoryDirectory = getAbsolutePathFromDao(heartOfGold.getId());
// Path metadataPath = dao.resolveDataPath(repositoryDirectory);
//
// String content = content(metadataPath);
// assertThat(content).contains("Awesome Spaceship");
// }
//
// @Test
// void shouldPersistPermissions() throws IOException {
// Repository heartOfGold = createHeartOfGold();
// heartOfGold.setPermissions(asList(new RepositoryPermission("trillian", asList("read", "write"), false), new RepositoryPermission("vogons", Collections.singletonList("delete"), true)));
// dao.add(heartOfGold);
//
// Path repositoryDirectory = getAbsolutePathFromDao(heartOfGold.getId());
// Path metadataPath = dao.resolveDataPath(repositoryDirectory);
//
// String content = content(metadataPath);
// System.out.println(content);
// assertThat(content).containsSubsequence("trillian", "<verb>read</verb>", "<verb>write</verb>");
// assertThat(content).containsSubsequence("vogons", "<verb>delete</verb>");
// }
//
// @Test
// void shouldReadPathDatabaseAndMetadataOfRepositories() {
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// // reload data
// dao = createDAO();
//
// heartOfGold = dao.get("42");
// assertThat(heartOfGold.getName()).isEqualTo("HeartOfGold");
//
// Path path = getAbsolutePathFromDao(heartOfGold.getId());
// assertThat(path).isDirectory();
// }
//
// @Test
// void shouldReadCreationTimeAndLastModifedDateFromDatabase() {
// Repository heartOfGold = createHeartOfGold();
// dao.add(heartOfGold);
//
// Long creationTime = dao.getCreationTime();
// Long lastModified = dao.getLastModified();
//
// // reload data
// dao = createDAO();
//
// assertThat(dao.getCreationTime()).isEqualTo(creationTime);
// assertThat(dao.getLastModified()).isEqualTo(lastModified);
// }
private String getXmlFileContent(String id) { private String getXmlFileContent(String id) {
Path storePath = metadataFile(id); Path storePath = metadataFile(id);
@@ -407,6 +300,6 @@ class XmlRepositoryDAOTest {
} }
private static Repository createRepository(String id) { private static Repository createRepository(String id) {
return new Repository(id, "xml", "space", "id"); return new Repository(id, "xml", "space", id);
} }
} }