Merge pull request #18402 from overleaf/msm-git-bridge-pom

* [git-bridge] Extracted pom versions to properties

Managing versions as properties is a best practice
with pom files. An advantage in our case is ensuring
dependency groups (as simpleclient) are upgraded
together.

* [git-bridge] Remove '_' as keyword

* [git-bridge] Added formatting with 'fmt-maven-plugin'

* Remove java from .editorconfig

No longer needed as a formatter is now available

* Replace javadoc comments with multiline comments

Replaces "/**" with "/*", which then prevents the formatter
from adding HTML elements to comments

* [git-bridge] Formatted .java files

GitOrigin-RevId: 0997b838cee88c290d824a74444295e26392f26b
This commit is contained in:
Miguel Serrano
2024-06-14 12:42:59 +02:00
committed by Copybot
parent b34be6bea4
commit da5846209f
203 changed files with 9548 additions and 10742 deletions

View File

@@ -1,108 +1,110 @@
package uk.ac.ic.wlgitbridge.application.config;
import org.junit.Test;
import java.io.Reader;
import java.io.StringReader;
import static org.junit.Assert.*;
/**
import java.io.Reader;
import java.io.StringReader;
import org.junit.Test;
/*
* Created by winston on 25/10/15.
*/
public class ConfigTest {
@Test
public void testConstructWithOauth() {
Reader reader = new StringReader("{\n" +
" \"port\": 80,\n" +
" \"bindIp\": \"127.0.0.1\",\n" +
" \"idleTimeout\": 30000,\n" +
" \"rootGitDirectory\": \"/var/wlgb/git\",\n" +
" \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n" +
" \"postbackBaseUrl\": \"http://127.0.0.1\",\n" +
" \"serviceName\": \"Overleaf\",\n" +
" \"oauth2\": {\n" +
" \"oauth2ClientID\": \"clientID\",\n" +
" \"oauth2ClientSecret\": \"oauth2 client secret\",\n" +
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
" }\n" +
"}\n");
Config config = new Config(reader);
assertEquals(80, config.getPort());
assertEquals("/var/wlgb/git", config.getRootGitDirectory());
assertEquals("http://127.0.0.1:60000/api/v0/", config.getAPIBaseURL());
assertEquals("http://127.0.0.1/", config.getPostbackURL());
assertEquals("Overleaf", config.getServiceName());
assertTrue(config.isUsingOauth2());
assertEquals("clientID", config.getOauth2().getOauth2ClientID());
assertEquals("oauth2 client secret", config.getOauth2().getOauth2ClientSecret());
assertEquals("https://www.overleaf.com", config.getOauth2().getOauth2Server());
}
@Test
public void testConstructWithOauth() {
Reader reader =
new StringReader(
"{\n"
+ " \"port\": 80,\n"
+ " \"bindIp\": \"127.0.0.1\",\n"
+ " \"idleTimeout\": 30000,\n"
+ " \"rootGitDirectory\": \"/var/wlgb/git\",\n"
+ " \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n"
+ " \"postbackBaseUrl\": \"http://127.0.0.1\",\n"
+ " \"serviceName\": \"Overleaf\",\n"
+ " \"oauth2\": {\n"
+ " \"oauth2ClientID\": \"clientID\",\n"
+ " \"oauth2ClientSecret\": \"oauth2 client secret\",\n"
+ " \"oauth2Server\": \"https://www.overleaf.com\"\n"
+ " }\n"
+ "}\n");
Config config = new Config(reader);
assertEquals(80, config.getPort());
assertEquals("/var/wlgb/git", config.getRootGitDirectory());
assertEquals("http://127.0.0.1:60000/api/v0/", config.getAPIBaseURL());
assertEquals("http://127.0.0.1/", config.getPostbackURL());
assertEquals("Overleaf", config.getServiceName());
assertTrue(config.isUsingOauth2());
assertEquals("clientID", config.getOauth2().getOauth2ClientID());
assertEquals("oauth2 client secret", config.getOauth2().getOauth2ClientSecret());
assertEquals("https://www.overleaf.com", config.getOauth2().getOauth2Server());
}
@Test (expected = AssertionError.class)
public void testConstructWithoutOauth() {
Reader reader = new StringReader("{\n" +
" \"port\": 80,\n" +
" \"bindIp\": \"127.0.0.1\",\n" +
" \"idleTimeout\": 30000,\n" +
" \"rootGitDirectory\": \"/var/wlgb/git\",\n" +
" \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n" +
" \"postbackBaseUrl\": \"http://127.0.0.1\",\n" +
" \"serviceName\": \"Overleaf\",\n" +
" \"oauth2\": null\n" +
"}\n");
Config config = new Config(reader);
assertEquals(80, config.getPort());
assertEquals("/var/wlgb/git", config.getRootGitDirectory());
assertEquals("http://127.0.0.1:60000/api/v0/", config.getAPIBaseURL());
assertEquals("http://127.0.0.1/", config.getPostbackURL());
assertEquals("Overleaf", config.getServiceName());
assertFalse(config.isUsingOauth2());
config.getOauth2();
}
@Test
public void asSanitised() throws Exception {
Reader reader = new StringReader("{\n" +
" \"port\": 80,\n" +
" \"bindIp\": \"127.0.0.1\",\n" +
" \"idleTimeout\": 30000,\n" +
" \"rootGitDirectory\": \"/var/wlgb/git\",\n" +
" \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n" +
" \"postbackBaseUrl\": \"http://127.0.0.1\",\n" +
" \"serviceName\": \"Overleaf\",\n" +
" \"oauth2\": {\n" +
" \"oauth2ClientID\": \"my oauth2 client id\",\n" +
" \"oauth2ClientSecret\": \"my oauth2 client secret\",\n" +
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
" }\n" +
"}\n");
Config config = new Config(reader);
String expected = "{\n" +
" \"port\": 80,\n" +
" \"bindIp\": \"127.0.0.1\",\n" +
" \"idleTimeout\": 30000,\n" +
" \"rootGitDirectory\": \"/var/wlgb/git\",\n" +
" \"apiBaseURL\": \"http://127.0.0.1:60000/api/v0/\",\n" +
" \"postbackURL\": \"http://127.0.0.1/\",\n" +
" \"serviceName\": \"Overleaf\",\n" +
" \"oauth2\": {\n" +
" \"oauth2ClientID\": \"<oauth2ClientID>\",\n" +
" \"oauth2ClientSecret\": \"<oauth2ClientSecret>\",\n" +
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
" },\n" +
" \"userPasswordEnabled\": false,\n" +
" \"repoStore\": null,\n" +
" \"swapStore\": null,\n" +
" \"swapJob\": null,\n" +
" \"sqliteHeapLimitBytes\": 0\n" +
"}";
assertEquals(
"sanitised config did not hide sensitive fields",
expected,
config.getSanitisedString()
);
}
@Test(expected = AssertionError.class)
public void testConstructWithoutOauth() {
Reader reader =
new StringReader(
"{\n"
+ " \"port\": 80,\n"
+ " \"bindIp\": \"127.0.0.1\",\n"
+ " \"idleTimeout\": 30000,\n"
+ " \"rootGitDirectory\": \"/var/wlgb/git\",\n"
+ " \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n"
+ " \"postbackBaseUrl\": \"http://127.0.0.1\",\n"
+ " \"serviceName\": \"Overleaf\",\n"
+ " \"oauth2\": null\n"
+ "}\n");
Config config = new Config(reader);
assertEquals(80, config.getPort());
assertEquals("/var/wlgb/git", config.getRootGitDirectory());
assertEquals("http://127.0.0.1:60000/api/v0/", config.getAPIBaseURL());
assertEquals("http://127.0.0.1/", config.getPostbackURL());
assertEquals("Overleaf", config.getServiceName());
assertFalse(config.isUsingOauth2());
config.getOauth2();
}
@Test
public void asSanitised() throws Exception {
Reader reader =
new StringReader(
"{\n"
+ " \"port\": 80,\n"
+ " \"bindIp\": \"127.0.0.1\",\n"
+ " \"idleTimeout\": 30000,\n"
+ " \"rootGitDirectory\": \"/var/wlgb/git\",\n"
+ " \"apiBaseUrl\": \"http://127.0.0.1:60000/api/v0\",\n"
+ " \"postbackBaseUrl\": \"http://127.0.0.1\",\n"
+ " \"serviceName\": \"Overleaf\",\n"
+ " \"oauth2\": {\n"
+ " \"oauth2ClientID\": \"my oauth2 client id\",\n"
+ " \"oauth2ClientSecret\": \"my oauth2 client secret\",\n"
+ " \"oauth2Server\": \"https://www.overleaf.com\"\n"
+ " }\n"
+ "}\n");
Config config = new Config(reader);
String expected =
"{\n"
+ " \"port\": 80,\n"
+ " \"bindIp\": \"127.0.0.1\",\n"
+ " \"idleTimeout\": 30000,\n"
+ " \"rootGitDirectory\": \"/var/wlgb/git\",\n"
+ " \"apiBaseURL\": \"http://127.0.0.1:60000/api/v0/\",\n"
+ " \"postbackURL\": \"http://127.0.0.1/\",\n"
+ " \"serviceName\": \"Overleaf\",\n"
+ " \"oauth2\": {\n"
+ " \"oauth2ClientID\": \"<oauth2ClientID>\",\n"
+ " \"oauth2ClientSecret\": \"<oauth2ClientSecret>\",\n"
+ " \"oauth2Server\": \"https://www.overleaf.com\"\n"
+ " },\n"
+ " \"userPasswordEnabled\": false,\n"
+ " \"repoStore\": null,\n"
+ " \"swapStore\": null,\n"
+ " \"swapJob\": null,\n"
+ " \"sqliteHeapLimitBytes\": 0\n"
+ "}";
assertEquals(
"sanitised config did not hide sensitive fields", expected, config.getSanitisedString());
}
}

View File

@@ -1,5 +1,13 @@
package uk.ac.ic.wlgitbridge.bridge;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import uk.ac.ic.wlgitbridge.application.config.Config;
@@ -17,96 +25,66 @@ import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Optional;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
/**
/*
* Created by winston on 20/08/2016.
*/
public class BridgeTest {
private Bridge bridge;
private Bridge bridge;
private ProjectLock lock;
private RepoStore repoStore;
private DBStore dbStore;
private SwapStore swapStore;
private SnapshotApiFacade snapshotAPI;
private ResourceCache resourceCache;
private SwapJob swapJob;
private GcJob gcJob;
private ProjectLock lock;
private RepoStore repoStore;
private DBStore dbStore;
private SwapStore swapStore;
private SnapshotApiFacade snapshotAPI;
private ResourceCache resourceCache;
private SwapJob swapJob;
private GcJob gcJob;
@Before
public void setup() {
lock = mock(ProjectLock.class);
repoStore = mock(RepoStore.class);
dbStore = mock(DBStore.class);
swapStore = mock(SwapStore.class);
snapshotAPI = mock(SnapshotApiFacade.class);
resourceCache = mock(ResourceCache.class);
swapJob = mock(SwapJob.class);
gcJob = mock(GcJob.class);
bridge = new Bridge(
new Config(
0,
"",
0,
"",
"",
"",
"",
null,
false,
null,
null,
null,
0),
lock,
repoStore,
dbStore,
swapStore,
swapJob,
gcJob,
snapshotAPI,
resourceCache
);
}
@Before
public void setup() {
lock = mock(ProjectLock.class);
repoStore = mock(RepoStore.class);
dbStore = mock(DBStore.class);
swapStore = mock(SwapStore.class);
snapshotAPI = mock(SnapshotApiFacade.class);
resourceCache = mock(ResourceCache.class);
swapJob = mock(SwapJob.class);
gcJob = mock(GcJob.class);
bridge =
new Bridge(
new Config(0, "", 0, "", "", "", "", null, false, null, null, null, 0),
lock,
repoStore,
dbStore,
swapStore,
swapJob,
gcJob,
snapshotAPI,
resourceCache);
}
@Test
public void shutdownStopsSwapAndGcJobs() {
bridge.startBackgroundJobs();
verify(swapJob).start();
verify(gcJob).start();
bridge.doShutdown();
verify(swapJob).stop();
verify(gcJob).stop();
}
@Test
public void updatingRepositorySetsLastAccessedTime(
) throws IOException, GitUserException, CannotAcquireLockException {
ProjectRepo repo = mock(ProjectRepo.class);
when(repoStore.getExistingRepo("asdf")).thenReturn(repo);
when(dbStore.getProjectState("asdf")).thenReturn(ProjectState.PRESENT);
when(snapshotAPI.projectExists(Optional.empty(), "asdf")).thenReturn(true);
when(
snapshotAPI.getDoc(Optional.empty(), "asdf")
).thenReturn(Optional.of(mock(GetDocResult.class)));
when(
snapshotAPI.getSnapshots(
any(),
any(),
anyInt()
)
).thenReturn(new ArrayDeque<>());
bridge.getUpdatedRepo(Optional.empty(), "asdf");
verify(dbStore).setLastAccessedTime(eq("asdf"), any());
}
@Test
public void shutdownStopsSwapAndGcJobs() {
bridge.startBackgroundJobs();
verify(swapJob).start();
verify(gcJob).start();
bridge.doShutdown();
verify(swapJob).stop();
verify(gcJob).stop();
}
@Test
public void updatingRepositorySetsLastAccessedTime()
throws IOException, GitUserException, CannotAcquireLockException {
ProjectRepo repo = mock(ProjectRepo.class);
when(repoStore.getExistingRepo("asdf")).thenReturn(repo);
when(dbStore.getProjectState("asdf")).thenReturn(ProjectState.PRESENT);
when(snapshotAPI.projectExists(Optional.empty(), "asdf")).thenReturn(true);
when(snapshotAPI.getDoc(Optional.empty(), "asdf"))
.thenReturn(Optional.of(mock(GetDocResult.class)));
when(snapshotAPI.getSnapshots(any(), any(), anyInt())).thenReturn(new ArrayDeque<>());
bridge.getUpdatedRepo(Optional.empty(), "asdf");
verify(dbStore).setLastAccessedTime(eq("asdf"), any());
}
}

View File

@@ -1,173 +1,135 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
/*
* Created by winston on 23/08/2016.
*/
public class SqliteDBStoreTest {
private SqliteDBStore dbStore;
private SqliteDBStore dbStore;
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
dbStore = new SqliteDBStore(tmpFolder.newFile("dbStore.db"));
}
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
dbStore = new SqliteDBStore(tmpFolder.newFile("dbStore.db"));
}
@Test
public void testGetNumProjects() {
assertEquals(0, dbStore.getNumProjects());
dbStore.setLatestVersionForProject("asdf", 1);
assertEquals(1, dbStore.getNumProjects());
dbStore.setLatestVersionForProject("asdf1", 2);
assertEquals(2, dbStore.getNumProjects());
dbStore.setLatestVersionForProject("asdf1", 3);
assertEquals(2, dbStore.getNumProjects());
}
@Test
public void testGetNumProjects() {
assertEquals(0, dbStore.getNumProjects());
dbStore.setLatestVersionForProject("asdf", 1);
assertEquals(1, dbStore.getNumProjects());
dbStore.setLatestVersionForProject("asdf1", 2);
assertEquals(2, dbStore.getNumProjects());
dbStore.setLatestVersionForProject("asdf1", 3);
assertEquals(2, dbStore.getNumProjects());
}
@Test
public void swapTableStartsOutEmpty() {
assertNull(dbStore.getOldestUnswappedProject());
}
@Test
public void swapTableStartsOutEmpty() {
assertNull(dbStore.getOldestUnswappedProject());
}
@Test
public void testGetOldestUnswappedProject() {
dbStore.setLatestVersionForProject("older", 3);
dbStore.setLastAccessedTime(
"older",
Timestamp.valueOf(
LocalDateTime.now().minus(5, ChronoUnit.SECONDS)
)
);
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime(
"asdf",
Timestamp.valueOf(
LocalDateTime.now().minus(1, ChronoUnit.SECONDS)
)
);
assertEquals("older", dbStore.getOldestUnswappedProject());
dbStore.setLastAccessedTime(
"older",
Timestamp.valueOf(
LocalDateTime.now()
)
);
assertEquals("asdf", dbStore.getOldestUnswappedProject());
}
@Test
public void testGetOldestUnswappedProject() {
dbStore.setLatestVersionForProject("older", 3);
dbStore.setLastAccessedTime(
"older", Timestamp.valueOf(LocalDateTime.now().minus(5, ChronoUnit.SECONDS)));
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime(
"asdf", Timestamp.valueOf(LocalDateTime.now().minus(1, ChronoUnit.SECONDS)));
assertEquals("older", dbStore.getOldestUnswappedProject());
dbStore.setLastAccessedTime("older", Timestamp.valueOf(LocalDateTime.now()));
assertEquals("asdf", dbStore.getOldestUnswappedProject());
}
@Test
public void swapAndRestore() {
String projectName = "something";
String compression = "bzip2";
dbStore.setLatestVersionForProject(projectName, 42);
dbStore.swap(projectName, compression);
assertNull(dbStore.getOldestUnswappedProject());
assertEquals(dbStore.getSwapCompression(projectName), compression);
// and restore
dbStore.restore(projectName);
assertEquals(dbStore.getSwapCompression(projectName), null);
}
@Test
public void swapAndRestore() {
String projectName = "something";
String compression = "bzip2";
dbStore.setLatestVersionForProject(projectName, 42);
dbStore.swap(projectName, compression);
assertNull(dbStore.getOldestUnswappedProject());
assertEquals(dbStore.getSwapCompression(projectName), compression);
// and restore
dbStore.restore(projectName);
assertEquals(dbStore.getSwapCompression(projectName), null);
}
@Test
public void noOldestProjectIfAllEvicted() {
dbStore.setLatestVersionForProject("older", 3);
dbStore.swap("older", "bzip2");
assertNull(dbStore.getOldestUnswappedProject());
}
@Test
public void noOldestProjectIfAllEvicted() {
dbStore.setLatestVersionForProject("older", 3);
dbStore.swap("older", "bzip2");
assertNull(dbStore.getOldestUnswappedProject());
}
@Test
public void nullLastAccessedTimesDoNotCount() {
dbStore.setLatestVersionForProject("older", 2);
dbStore.setLastAccessedTime(
"older",
Timestamp.valueOf(
LocalDateTime.now().minus(5, ChronoUnit.SECONDS)
)
);
dbStore.setLatestVersionForProject("newer", 3);
dbStore.setLastAccessedTime(
"newer",
Timestamp.valueOf(
LocalDateTime.now()
)
);
assertEquals("older", dbStore.getOldestUnswappedProject());
dbStore.swap("older", "bzip2");
assertEquals("newer", dbStore.getOldestUnswappedProject());
}
@Test
public void nullLastAccessedTimesDoNotCount() {
dbStore.setLatestVersionForProject("older", 2);
dbStore.setLastAccessedTime(
"older", Timestamp.valueOf(LocalDateTime.now().minus(5, ChronoUnit.SECONDS)));
dbStore.setLatestVersionForProject("newer", 3);
dbStore.setLastAccessedTime("newer", Timestamp.valueOf(LocalDateTime.now()));
assertEquals("older", dbStore.getOldestUnswappedProject());
dbStore.swap("older", "bzip2");
assertEquals("newer", dbStore.getOldestUnswappedProject());
}
@Test
public void missingProjectLastAccessedTimeCanBeSet() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime(
"asdf",
Timestamp.valueOf(LocalDateTime.now())
);
assertEquals("asdf", dbStore.getOldestUnswappedProject());
}
@Test
public void missingProjectLastAccessedTimeCanBeSet() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime("asdf", Timestamp.valueOf(LocalDateTime.now()));
assertEquals("asdf", dbStore.getOldestUnswappedProject());
}
@Test
public void testGetNumUnswappedProjects() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime(
"asdf",
Timestamp.valueOf(LocalDateTime.now())
);
assertEquals(1, dbStore.getNumUnswappedProjects());
dbStore.swap(
"asdf",
"bzip2"
);
assertEquals(0, dbStore.getNumUnswappedProjects());
}
@Test
public void testGetNumUnswappedProjects() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime("asdf", Timestamp.valueOf(LocalDateTime.now()));
assertEquals(1, dbStore.getNumUnswappedProjects());
dbStore.swap("asdf", "bzip2");
assertEquals(0, dbStore.getNumUnswappedProjects());
}
@Test
public void projectStateIsNotPresentIfNotInDBAtAll() {
assertEquals(
ProjectState.NOT_PRESENT,
dbStore.getProjectState("asdf")
);
}
@Test
public void projectStateIsNotPresentIfNotInDBAtAll() {
assertEquals(ProjectState.NOT_PRESENT, dbStore.getProjectState("asdf"));
}
@Test
public void projectStateIsPresentIfProjectHasLastAccessed() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime(
"asdf",
Timestamp.valueOf(LocalDateTime.now())
);
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("asdf"));
}
@Test
public void projectStateIsPresentIfProjectHasLastAccessed() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime("asdf", Timestamp.valueOf(LocalDateTime.now()));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("asdf"));
}
@Test
public void projectStateIsSwappedIfLastAccessedIsNull() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.swap("asdf", "bzip2");
assertEquals(ProjectState.SWAPPED, dbStore.getProjectState("asdf"));
}
@Test
public void projectStateIsSwappedIfLastAccessedIsNull() {
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.swap("asdf", "bzip2");
assertEquals(ProjectState.SWAPPED, dbStore.getProjectState("asdf"));
}
@Test
public void testDeleteProject() {
dbStore.setLatestVersionForProject("project1", 1);
dbStore.setLatestVersionForProject("project2", 1);
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project1"));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project2"));
dbStore.deleteProject("project1");
assertEquals(ProjectState.NOT_PRESENT, dbStore.getProjectState("project1"));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project2"));
}
@Test
public void testDeleteProject() {
dbStore.setLatestVersionForProject("project1", 1);
dbStore.setLatestVersionForProject("project2", 1);
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project1"));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project2"));
dbStore.deleteProject("project1");
assertEquals(ProjectState.NOT_PRESENT, dbStore.getProjectState("project1"));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project2"));
}
}

View File

@@ -1,24 +1,17 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Test;
public class DeleteFilesForProjectSQLUpdateTest {
@Test
public void testGetSQL() {
DeleteFilesForProjectSQLUpdate update =
new DeleteFilesForProjectSQLUpdate(
"projname",
"path1",
"path2"
);
assertEquals(
"DELETE FROM `url_index_store` " +
"WHERE `project_name` = ? " +
"AND path IN (?, ?);\n",
update.getSQL()
);
}
}
@Test
public void testGetSQL() {
DeleteFilesForProjectSQLUpdate update =
new DeleteFilesForProjectSQLUpdate("projname", "path1", "path2");
assertEquals(
"DELETE FROM `url_index_store` " + "WHERE `project_name` = ? " + "AND path IN (?, ?);\n",
update.getSQL());
}
}

View File

@@ -1,5 +1,13 @@
package uk.ac.ic.wlgitbridge.bridge.gc;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.*;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -11,113 +19,101 @@ import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
import uk.ac.ic.wlgitbridge.data.ProjectLockImpl;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.*;
/**
/*
* Created by winston on 16/02/2017.
*/
public class GcJobImplTest {
RepoStore repoStore = mock(RepoStore.class);
RepoStore repoStore = mock(RepoStore.class);
ProjectLock locks;
ProjectLock locks;
GcJobImpl gcJob;
GcJobImpl gcJob;
@Before
public void setup() {
locks = new ProjectLockImpl();
gcJob = new GcJobImpl(repoStore, locks, 5);
@Before
public void setup() {
locks = new ProjectLockImpl();
gcJob = new GcJobImpl(repoStore, locks, 5);
}
@After
public void teardown() {
gcJob.stop();
}
@Test
public void addedProjectsAreAllEventuallyGcedOnce() throws Exception {
int numProjects = 5;
/* Make the mocks, make expectations, and keep a reference to them */
final OngoingStubbing<ProjectRepo>[] o =
new OngoingStubbing[] {when(repoStore.getExistingRepo(anyString()))};
List<ProjectRepo> mockRepos =
IntStream.range(0, numProjects)
.mapToObj(i -> String.valueOf((char) ('a' + i)))
.map(
proj -> {
gcJob.queueForGc(proj);
ProjectRepo mockRepo = mock(ProjectRepo.class);
o[0] = o[0].thenReturn(mockRepo);
return mockRepo;
})
.collect(Collectors.toList());
CompletableFuture<Void> fut = gcJob.waitForRun();
gcJob.start();
fut.join();
for (ProjectRepo mock : mockRepos) {
verify(mock).runGC();
verify(mock).deleteIncomingPacks();
}
/* Nothing should happen on the next run */
when(repoStore.getExistingRepo(anyString())).thenThrow(new IllegalStateException());
gcJob.waitForRun().join();
}
@After
public void teardown() {
gcJob.stop();
}
@Test
public void addedProjectsAreAllEventuallyGcedOnce() throws Exception {
int numProjects = 5;
/* Make the mocks, make expectations, and keep a reference to them */
final OngoingStubbing<ProjectRepo>[] o = new OngoingStubbing[] {
when(repoStore.getExistingRepo(anyString()))
};
List<ProjectRepo> mockRepos = IntStream.range(
0, numProjects
).mapToObj(i ->
String.valueOf((char) ('a' + i))
).map(proj -> {
gcJob.queueForGc(proj);
ProjectRepo mockRepo = mock(ProjectRepo.class);
o[0] = o[0].thenReturn(mockRepo);
return mockRepo;
}).collect(Collectors.toList());
CompletableFuture<Void> fut = gcJob.waitForRun();
gcJob.start();
fut.join();
for (ProjectRepo mock : mockRepos) {
verify(mock).runGC();
verify(mock).deleteIncomingPacks();
}
/* Nothing should happen on the next run */
when(repoStore.getExistingRepo(anyString())).thenThrow(
new IllegalStateException()
);
gcJob.waitForRun().join();
}
@Test
public void cannotOverlapGcRuns() throws Exception {
CompletableFuture<Void> runningForever = new CompletableFuture<>();
gcJob.onPostGc(() -> {
try {
/* Pretend the GC is taking forever */
runningForever.join();
} catch (Throwable e) {
runningForever.completeExceptionally(e);
}
@Test
public void cannotOverlapGcRuns() throws Exception {
CompletableFuture<Void> runningForever = new CompletableFuture<>();
gcJob.onPostGc(
() -> {
try {
/* Pretend the GC is taking forever */
runningForever.join();
} catch (Throwable e) {
runningForever.completeExceptionally(e);
}
});
CompletableFuture<Void> fut = gcJob.waitForRun();
gcJob.start();
fut.join();
CompletableFuture<Void> ranAgain = new CompletableFuture<>();
gcJob.onPreGc(() -> ranAgain.complete(null));
/* Should not run again any time soon */
for (int i = 0; i < 50; ++i) {
assertFalse(ranAgain.isDone());
/* The gc interval is 5 ms, so 50 1ms sleeps should be more than
enough without making the test slow */
Thread.sleep(1);
}
assertFalse(runningForever.isCompletedExceptionally());
CompletableFuture<Void> fut = gcJob.waitForRun();
gcJob.start();
fut.join();
CompletableFuture<Void> ranAgain = new CompletableFuture<>();
gcJob.onPreGc(() -> ranAgain.complete(null));
/* Should not run again any time soon */
for (int i = 0; i < 50; ++i) {
assertFalse(ranAgain.isDone());
/* The gc interval is 5 ms, so 50 1ms sleeps should be more than
enough without making the test slow */
Thread.sleep(1);
}
assertFalse(runningForever.isCompletedExceptionally());
}
@Test
public void willNotGcProjectUntilItIsUnlocked()
throws InterruptedException, IOException {
ProjectRepo repo = mock(ProjectRepo.class);
when(repoStore.getExistingRepo(anyString())).thenReturn(repo);
gcJob.onPostGc(gcJob::stop);
gcJob.queueForGc("a");
CompletableFuture<Void> fut = gcJob.waitForRun();
try (LockGuard __ = locks.lockGuard("a")) {
gcJob.start();
for (int i = 0; i < 50; ++i) {
assertFalse(fut.isDone());
Thread.sleep(1);
}
} catch (CannotAcquireLockException e) {
throw new RuntimeException(e);
}
/* Now that we've released the lock, fut should complete */
fut.join();
@Test
public void willNotGcProjectUntilItIsUnlocked() throws InterruptedException, IOException {
ProjectRepo repo = mock(ProjectRepo.class);
when(repoStore.getExistingRepo(anyString())).thenReturn(repo);
gcJob.onPostGc(gcJob::stop);
gcJob.queueForGc("a");
CompletableFuture<Void> fut = gcJob.waitForRun();
try (LockGuard __ = locks.lockGuard("a")) {
gcJob.start();
for (int i = 0; i < 50; ++i) {
assertFalse(fut.isDone());
Thread.sleep(1);
}
} catch (CannotAcquireLockException e) {
throw new RuntimeException(e);
}
/* Now that we've released the lock, fut should complete */
fut.join();
}
}

View File

@@ -1,93 +1,80 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import uk.ac.ic.wlgitbridge.util.Files;
import static org.junit.Assert.*;
import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Optional;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import uk.ac.ic.wlgitbridge.util.Files;
import static org.junit.Assert.*;
/**
/*
* Created by winston on 23/08/2016.
*/
public class FSGitRepoStoreTest {
public static File makeTempRepoDir(
TemporaryFolder tmpFolder,
String name
) throws IOException {
File tmp = tmpFolder.newFolder(name);
Path rootdir = Paths.get(
"src/test/resources/uk/ac/ic/wlgitbridge/"
+ "bridge/repo/FSGitRepoStoreTest/rootdir"
);
FileUtils.copyDirectory(rootdir.toFile(), tmp);
Files.renameAll(tmp, "DOTgit", ".git");
return tmp;
public static File makeTempRepoDir(TemporaryFolder tmpFolder, String name) throws IOException {
File tmp = tmpFolder.newFolder(name);
Path rootdir =
Paths.get(
"src/test/resources/uk/ac/ic/wlgitbridge/" + "bridge/repo/FSGitRepoStoreTest/rootdir");
FileUtils.copyDirectory(rootdir.toFile(), tmp);
Files.renameAll(tmp, "DOTgit", ".git");
return tmp;
}
private FSGitRepoStore repoStore;
private File original;
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
File tmp = makeTempRepoDir(tmpFolder, "rootdir");
original = tmpFolder.newFolder("original");
FileUtils.copyDirectory(tmp, original);
repoStore = new FSGitRepoStore(tmp.getAbsolutePath(), Optional.empty());
}
@Test
public void testPurgeNonexistentProjects() {
File toDelete = new File(repoStore.getRootDirectory(), "idontexist");
File wlgb = new File(repoStore.getRootDirectory(), ".wlgb");
assertTrue(toDelete.exists());
assertTrue(wlgb.exists());
repoStore.purgeNonexistentProjects(Arrays.asList("proj1", "proj2"));
assertFalse(toDelete.exists());
assertTrue(wlgb.exists());
}
@Test
public void totalSizeShouldChangeWhenFilesAreCreatedAndDeleted() throws IOException {
long old = repoStore.totalSize();
File temp = new File(repoStore.getRootDirectory(), "__temp.txt");
try (OutputStream out = new FileOutputStream(temp)) {
out.write(new byte[16 * 1024 * 1024]);
}
long new_ = repoStore.totalSize();
assertTrue(new_ > old);
assertTrue(temp.delete());
long new__ = repoStore.totalSize();
assertTrue(new__ < new_);
}
private FSGitRepoStore repoStore;
private File original;
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
File tmp = makeTempRepoDir(tmpFolder, "rootdir");
original = tmpFolder.newFolder("original");
FileUtils.copyDirectory(tmp, original);
repoStore = new FSGitRepoStore(tmp.getAbsolutePath(), Optional.empty());
}
@Test
public void testPurgeNonexistentProjects() {
File toDelete = new File(
repoStore.getRootDirectory(), "idontexist"
);
File wlgb = new File(repoStore.getRootDirectory(), ".wlgb");
assertTrue(toDelete.exists());
assertTrue(wlgb.exists());
repoStore.purgeNonexistentProjects(Arrays.asList("proj1", "proj2"));
assertFalse(toDelete.exists());
assertTrue(wlgb.exists());
}
@Test
public void totalSizeShouldChangeWhenFilesAreCreatedAndDeleted()
throws IOException {
long old = repoStore.totalSize();
File temp = new File(repoStore.getRootDirectory(), "__temp.txt");
try (
OutputStream out = new FileOutputStream(
temp
)
) {
out.write(new byte[16 * 1024 * 1024]);
}
long new_ = repoStore.totalSize();
assertTrue(new_ > old);
assertTrue(temp.delete());
long new__ = repoStore.totalSize();
assertTrue(new__ < new_);
}
@Test
public void zipAndUnzipShouldBeTheSame() throws IOException {
File expected = new File(original, "proj1");
File actual = new File(repoStore.getRootDirectory(), "proj1");
assertTrue(Files.contentsAreEqual(expected, actual));
InputStream zipped = repoStore.bzip2Project("proj1");
repoStore.remove("proj1");
assertFalse(actual.exists());
repoStore.unbzip2Project("proj1", zipped);
assertTrue(Files.contentsAreEqual(expected, actual));
}
}
@Test
public void zipAndUnzipShouldBeTheSame() throws IOException {
File expected = new File(original, "proj1");
File actual = new File(repoStore.getRootDirectory(), "proj1");
assertTrue(Files.contentsAreEqual(expected, actual));
InputStream zipped = repoStore.bzip2Project("proj1");
repoStore.remove("proj1");
assertFalse(actual.exists());
repoStore.unbzip2Project("proj1", zipped);
assertTrue(Files.contentsAreEqual(expected, actual));
}
}

View File

@@ -1,6 +1,17 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.*;
import com.google.api.client.repackaged.com.google.common.base.Preconditions;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Supplier;
import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
@@ -12,189 +23,150 @@ import uk.ac.ic.wlgitbridge.data.filestore.RepositoryFile;
import uk.ac.ic.wlgitbridge.snapshot.servermock.util.FileUtil;
import uk.ac.ic.wlgitbridge.util.Files;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Supplier;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.lessThan;
import static org.junit.Assert.*;
/**
/*
* Created by winston on 08/10/2016.
*/
public class GitProjectRepoTest {
public static File makeTempRepoDir(
TemporaryFolder tmpFolder,
String name
) throws IOException {
File tmp = tmpFolder.newFolder(name);
Path rootdir = Paths.get(
"src/test/resources/uk/ac/ic/wlgitbridge/"
+ "bridge/repo/GitProjectRepoTest/rootdir"
);
FileUtils.copyDirectory(rootdir.toFile(), tmp);
Files.renameAll(tmp, "DOTgit", ".git");
return tmp;
public static File makeTempRepoDir(TemporaryFolder tmpFolder, String name) throws IOException {
File tmp = tmpFolder.newFolder(name);
Path rootdir =
Paths.get(
"src/test/resources/uk/ac/ic/wlgitbridge/" + "bridge/repo/GitProjectRepoTest/rootdir");
FileUtils.copyDirectory(rootdir.toFile(), tmp);
Files.renameAll(tmp, "DOTgit", ".git");
return tmp;
}
private File rootdir;
FSGitRepoStore repoStore;
GitProjectRepo repo;
GitProjectRepo badGitignore;
GitProjectRepo incoming;
GitProjectRepo withoutIncoming;
@Rule public TemporaryFolder tmpFolder = new TemporaryFolder();
@Before
public void setup() throws IOException {
rootdir = makeTempRepoDir(tmpFolder, "rootdir");
repoStore = new FSGitRepoStore(rootdir.getAbsolutePath(), Optional.empty());
repo = fromExistingDir("repo");
badGitignore = fromExistingDir("badgitignore");
incoming = fromExistingDir("incoming");
withoutIncoming = fromExistingDir("without_incoming");
}
private GitProjectRepo fromExistingDir(String dir) throws IOException {
GitProjectRepo ret = GitProjectRepo.fromName(dir);
ret.useExistingRepository(repoStore);
return ret;
}
private GitDirectoryContents makeDirContents(String... contents) {
Preconditions.checkArgument(contents.length % 2 == 0);
List<RawFile> files = new ArrayList<>(contents.length / 2);
for (int i = 0; i + 1 < contents.length; i += 2) {
files.add(new RepositoryFile(contents[i], contents[i + 1].getBytes(StandardCharsets.UTF_8)));
}
return new GitDirectoryContents(
files,
repoStore.getRootDirectory(),
"repo",
"Winston Li",
"git@winston.li",
"Commit Message",
new Date());
}
private File rootdir;
FSGitRepoStore repoStore;
GitProjectRepo repo;
GitProjectRepo badGitignore;
GitProjectRepo incoming;
GitProjectRepo withoutIncoming;
@Test
public void deletingIgnoredFileOnAppDeletesFromTheRepo() throws IOException {
GitDirectoryContents contents = makeDirContents(".gitignore", "*.ignored\n");
repo.commitAndGetMissing(contents);
repo.resetHard();
File dir = repo.getDotGitDir();
assertEquals(
new HashSet<String>(Arrays.asList(".git", ".gitignore")),
new HashSet<String>(Arrays.asList(dir.list())));
}
@Rule
public TemporaryFolder tmpFolder = new TemporaryFolder();
@Test
public void addingIgnoredFilesOnAppAddsToTheRepo() throws IOException {
GitDirectoryContents contents =
makeDirContents(
".gitignore",
"*.ignored\n",
"file1.ignored",
"",
"file1.txt",
"",
"file2.txt",
"",
"added.ignored",
"");
repo.commitAndGetMissing(contents);
repo.resetHard();
assertEquals(
new HashSet<String>(
Arrays.asList(
".git", ".gitignore", "file1.ignored", "file1.txt", "file2.txt", "added.ignored")),
new HashSet<String>(Arrays.asList(repo.getDotGitDir().list())));
}
@Before
public void setup() throws IOException {
rootdir = makeTempRepoDir(tmpFolder, "rootdir");
repoStore = new FSGitRepoStore(rootdir.getAbsolutePath(), Optional.empty());
repo = fromExistingDir("repo");
badGitignore = fromExistingDir("badgitignore");
incoming = fromExistingDir("incoming");
withoutIncoming = fromExistingDir("without_incoming");
}
@Test
public void badGitignoreShouldNotThrow() throws IOException {
GitDirectoryContents contents =
makeDirContents(
".gitignore",
"*.ignored\n",
"file1.ignored",
"",
"file1.txt",
"",
"file2.txt",
"",
"added.ignored",
"");
badGitignore.commitAndGetMissing(contents);
}
private GitProjectRepo fromExistingDir(String dir) throws IOException {
GitProjectRepo ret = GitProjectRepo.fromName(dir);
ret.useExistingRepository(repoStore);
return ret;
}
private static long repoSize(ProjectRepo repo) {
return FileUtils.sizeOfDirectory(repo.getProjectDir());
}
private GitDirectoryContents makeDirContents(
String... contents
) {
Preconditions.checkArgument(contents.length % 2 == 0);
List<RawFile> files = new ArrayList<>(contents.length / 2);
for (int i = 0; i + 1 < contents.length; i += 2) {
files.add(
new RepositoryFile(
contents[i],
contents[i + 1].getBytes(StandardCharsets.UTF_8)
)
);
}
return new GitDirectoryContents(
files,
repoStore.getRootDirectory(),
"repo",
"Winston Li",
"git@winston.li",
"Commit Message",
new Date()
);
}
@Test
public void runGCReducesTheSizeOfARepoWithGarbage() throws IOException {
long beforeSize = repoSize(repo);
repo.runGC();
long afterSize = repoSize(repo);
assertThat(beforeSize, lessThan(afterSize));
}
@Test
public void deletingIgnoredFileOnAppDeletesFromTheRepo(
) throws IOException {
GitDirectoryContents contents = makeDirContents(
".gitignore",
"*.ignored\n"
);
repo.commitAndGetMissing(contents);
repo.resetHard();
File dir = repo.getDotGitDir();
assertEquals(
new HashSet<String>(Arrays.asList(".git", ".gitignore")),
new HashSet<String>(Arrays.asList(dir.list()))
);
}
@Test
public void runGCDoesNothingOnARepoWithoutGarbage() throws IOException {
repo.runGC();
long beforeSize = repoSize(repo);
repo.runGC();
long afterSize = repoSize(repo);
assertThat(beforeSize, equalTo(afterSize));
}
@Test
public void addingIgnoredFilesOnAppAddsToTheRepo() throws IOException {
GitDirectoryContents contents = makeDirContents(
".gitignore",
"*.ignored\n",
"file1.ignored",
"",
"file1.txt",
"",
"file2.txt",
"",
"added.ignored",
""
);
repo.commitAndGetMissing(contents);
repo.resetHard();
assertEquals(
new HashSet<String>(Arrays.asList(
".git",
".gitignore",
"file1.ignored",
"file1.txt",
"file2.txt",
"added.ignored"
)),
new HashSet<String>(Arrays.asList(repo.getDotGitDir().list()))
);
}
@Test
public void badGitignoreShouldNotThrow() throws IOException {
GitDirectoryContents contents = makeDirContents(
".gitignore",
"*.ignored\n",
"file1.ignored",
"",
"file1.txt",
"",
"file2.txt",
"",
"added.ignored",
""
);
badGitignore.commitAndGetMissing(contents);
}
private static long repoSize(ProjectRepo repo) {
return FileUtils.sizeOfDirectory(repo.getProjectDir());
}
@Test
public void runGCReducesTheSizeOfARepoWithGarbage() throws IOException {
long beforeSize = repoSize(repo);
repo.runGC();
long afterSize = repoSize(repo);
assertThat(beforeSize, lessThan(afterSize));
}
@Test
public void runGCDoesNothingOnARepoWithoutGarbage() throws IOException {
repo.runGC();
long beforeSize = repoSize(repo);
repo.runGC();
long afterSize = repoSize(repo);
assertThat(beforeSize, equalTo(afterSize));
}
@Test
public void deleteIncomingPacksDeletesIncomingPacks() throws IOException {
Supplier<Boolean> dirsAreEq = () -> FileUtil.directoryDeepEquals(
incoming.getProjectDir(), withoutIncoming.getProjectDir()
);
assertFalse(dirsAreEq.get());
incoming.deleteIncomingPacks();
assertTrue(dirsAreEq.get());
}
@Test
public void deleteIncomingPacksOnDirWithoutIncomingPacksDoesNothing()
throws IOException {
File actual = withoutIncoming.getProjectDir();
File expected = tmpFolder.newFolder();
FileUtils.copyDirectory(actual, expected);
withoutIncoming.deleteIncomingPacks();
assertTrue(FileUtil.directoryDeepEquals(actual, expected));
}
@Test
public void deleteIncomingPacksDeletesIncomingPacks() throws IOException {
Supplier<Boolean> dirsAreEq =
() ->
FileUtil.directoryDeepEquals(incoming.getProjectDir(), withoutIncoming.getProjectDir());
assertFalse(dirsAreEq.get());
incoming.deleteIncomingPacks();
assertTrue(dirsAreEq.get());
}
@Test
public void deleteIncomingPacksOnDirWithoutIncomingPacksDoesNothing() throws IOException {
File actual = withoutIncoming.getProjectDir();
File expected = tmpFolder.newFolder();
FileUtils.copyDirectory(actual, expected);
withoutIncoming.deleteIncomingPacks();
assertTrue(FileUtil.directoryDeepEquals(actual, expected));
}
}

View File

@@ -1,7 +1,16 @@
package uk.ac.ic.wlgitbridge.bridge.resource;
import io.netty.handler.codec.http.HttpHeaders;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import java.io.IOException;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.bridge.util.CastUtil;
@@ -9,115 +18,101 @@ import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
import uk.ac.ic.wlgitbridge.io.http.ning.NingHttpClientFacade;
import uk.ac.ic.wlgitbridge.util.FunctionT;
import java.io.IOException;
import java.util.HashMap;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
public class UrlResourceCacheTest {
private static String PROJ = "proj";
private static String PROJ = "proj";
private static String URL = "http://localhost/file.jpg";
private static String URL = "http://localhost/file.jpg";
private static String NEW_PATH = "file1.jpg";
private static String NEW_PATH = "file1.jpg";
private final NingHttpClientFacade http = mock(NingHttpClientFacade.class);
private final NingHttpClientFacade http = mock(NingHttpClientFacade.class);
private final DBStore dbStore = mock(DBStore.class);
private final DBStore dbStore = mock(DBStore.class);
private final UrlResourceCache cache = new UrlResourceCache(dbStore, http);
private final UrlResourceCache cache = new UrlResourceCache(dbStore, http);
private static HttpHeaders withContentLength(long cl) {
return new DefaultHttpHeaders().add("Content-Length", String.valueOf(cl));
}
private static HttpHeaders withContentLength(long cl) {
return new DefaultHttpHeaders().add("Content-Length", String.valueOf(cl));
}
private void respondWithContentLength(long cl, long actual)
throws ExecutionException {
when(http.get(any(), any())).thenAnswer(invoc -> {
Object[] args = invoc.getArguments();
//noinspection unchecked
((FunctionT<
HttpHeaders, Boolean, SizeLimitExceededException
>) args[1]).apply(withContentLength(cl));
return new byte[CastUtil.assumeInt(actual)];
});
}
private void respondWithContentLength(long cl, long actual) throws ExecutionException {
when(http.get(any(), any()))
.thenAnswer(
invoc -> {
Object[] args = invoc.getArguments();
//noinspection unchecked
((FunctionT<HttpHeaders, Boolean, SizeLimitExceededException>) args[1])
.apply(withContentLength(cl));
return new byte[CastUtil.assumeInt(actual)];
});
}
private void respondWithContentLength(long cl) throws ExecutionException {
respondWithContentLength(cl, cl);
}
private void respondWithContentLength(long cl) throws ExecutionException {
respondWithContentLength(cl, cl);
}
private void getWithMaxLength(Optional<Long> max)
throws IOException, SizeLimitExceededException {
cache.get(
PROJ, URL, NEW_PATH, new HashMap<>(), new HashMap<>(), max);
}
private void getWithMaxLength(Optional<Long> max) throws IOException, SizeLimitExceededException {
cache.get(PROJ, URL, NEW_PATH, new HashMap<>(), new HashMap<>(), max);
}
private void getUrl(String url) throws IOException, SizeLimitExceededException {
cache.get(PROJ, url, NEW_PATH, new HashMap<>(), new HashMap<>(), Optional.empty());
}
private void getUrl(String url) throws IOException, SizeLimitExceededException {
cache.get(PROJ, url, NEW_PATH, new HashMap<>(), new HashMap<>(), Optional.empty());
}
private void getWithMaxLength(long max)
throws IOException, SizeLimitExceededException {
getWithMaxLength(Optional.of(max));
}
private void getWithMaxLength(long max) throws IOException, SizeLimitExceededException {
getWithMaxLength(Optional.of(max));
}
private void getWithoutLimit()
throws IOException, SizeLimitExceededException {
getWithMaxLength(Optional.empty());
}
private void getWithoutLimit() throws IOException, SizeLimitExceededException {
getWithMaxLength(Optional.empty());
}
@Test
public void getDoesNotThrowWhenContentLengthLT() throws Exception {
respondWithContentLength(1);
getWithMaxLength(2);
}
@Test
public void getDoesNotThrowWhenContentLengthLT() throws Exception {
respondWithContentLength(1);
getWithMaxLength(2);
}
@Test
public void getDoesNotThrowWhenContentLengthEQ() throws Exception {
respondWithContentLength(2);
getWithMaxLength(2);
}
@Test
public void getDoesNotThrowWhenContentLengthEQ() throws Exception {
respondWithContentLength(2);
getWithMaxLength(2);
}
@Test (expected = SizeLimitExceededException.class)
public void getThrowsSizeLimitExceededWhenContentLengthGT()
throws Exception {
respondWithContentLength(3);
getWithMaxLength(2);
}
@Test(expected = SizeLimitExceededException.class)
public void getThrowsSizeLimitExceededWhenContentLengthGT() throws Exception {
respondWithContentLength(3);
getWithMaxLength(2);
}
@Test
public void getWithEmptyContentIsValid() throws Exception {
respondWithContentLength(0);
getWithMaxLength(0);
}
@Test
public void getWithEmptyContentIsValid() throws Exception {
respondWithContentLength(0);
getWithMaxLength(0);
}
@Test
public void getWithoutLimitDoesNotThrow() throws Exception {
respondWithContentLength(Integer.MAX_VALUE, 0);
getWithoutLimit();
}
@Test
public void getWithoutLimitDoesNotThrow() throws Exception {
respondWithContentLength(Integer.MAX_VALUE, 0);
getWithoutLimit();
}
@Test (expected = SizeLimitExceededException.class)
public void getThrowsIfActualContentTooBig() throws Exception {
respondWithContentLength(0, 10);
getWithMaxLength(5);
}
@Test
public void tokenIsRemovedFromCacheKey() throws Exception {
String url = "http://history.overleaf.com/projects/1234/blobs/abdef?token=secretencryptedstuff&_path=test.tex";
String cacheKey = "http://history.overleaf.com/projects/1234/blobs/abdef?token=REMOVED&_path=test.tex";
respondWithContentLength(123);
getUrl(url);
verify(dbStore).getPathForURLInProject(PROJ, cacheKey);
verify(dbStore).addURLIndexForProject(PROJ, cacheKey, NEW_PATH);
}
@Test(expected = SizeLimitExceededException.class)
public void getThrowsIfActualContentTooBig() throws Exception {
respondWithContentLength(0, 10);
getWithMaxLength(5);
}
@Test
public void tokenIsRemovedFromCacheKey() throws Exception {
String url =
"http://history.overleaf.com/projects/1234/blobs/abdef?token=secretencryptedstuff&_path=test.tex";
String cacheKey =
"http://history.overleaf.com/projects/1234/blobs/abdef?token=REMOVED&_path=test.tex";
respondWithContentLength(123);
getUrl(url);
verify(dbStore).getPathForURLInProject(PROJ, cacheKey);
verify(dbStore).addURLIndexForProject(PROJ, cacheKey, NEW_PATH);
}
}

View File

@@ -1,5 +1,13 @@
package uk.ac.ic.wlgitbridge.bridge.swap.job;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
@@ -15,152 +23,148 @@ import uk.ac.ic.wlgitbridge.bridge.swap.store.InMemorySwapStore;
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
import uk.ac.ic.wlgitbridge.data.ProjectLockImpl;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
/*
* Created by winston on 20/08/2016.
*/
public class SwapJobImplTest {
private SwapJobImpl swapJob;
private SwapJobImpl swapJob;
private ProjectLock lock;
private RepoStore repoStore;
private DBStore dbStore;
private SwapStore swapStore;
private ProjectLock lock;
private RepoStore repoStore;
private DBStore dbStore;
private SwapStore swapStore;
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
lock = new ProjectLockImpl();
repoStore = new FSGitRepoStore(
FSGitRepoStoreTest.makeTempRepoDir(
tmpFolder,
"repostore"
).getAbsolutePath(),
100_000,
FileUtils::sizeOfDirectory
);
dbStore = new SqliteDBStore(tmpFolder.newFile());
dbStore.setLatestVersionForProject("proj1", 0);
dbStore.setLatestVersionForProject("proj2", 0);
dbStore.setLastAccessedTime(
"proj1",
Timestamp.valueOf(LocalDateTime.now())
);
dbStore.setLastAccessedTime(
"proj2",
Timestamp.valueOf(
LocalDateTime.now().minus(1, ChronoUnit.SECONDS)
)
);
swapStore = new InMemorySwapStore();
swapJob = new SwapJobImpl(
1,
15000,
30000,
Duration.ofMillis(100),
SwapJob.CompressionMethod.Bzip2,
lock,
repoStore,
dbStore,
swapStore
);
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
lock = new ProjectLockImpl();
repoStore =
new FSGitRepoStore(
FSGitRepoStoreTest.makeTempRepoDir(tmpFolder, "repostore").getAbsolutePath(),
100_000,
FileUtils::sizeOfDirectory);
dbStore = new SqliteDBStore(tmpFolder.newFile());
dbStore.setLatestVersionForProject("proj1", 0);
dbStore.setLatestVersionForProject("proj2", 0);
dbStore.setLastAccessedTime("proj1", Timestamp.valueOf(LocalDateTime.now()));
dbStore.setLastAccessedTime(
"proj2", Timestamp.valueOf(LocalDateTime.now().minus(1, ChronoUnit.SECONDS)));
swapStore = new InMemorySwapStore();
swapJob =
new SwapJobImpl(
1,
15000,
30000,
Duration.ofMillis(100),
SwapJob.CompressionMethod.Bzip2,
lock,
repoStore,
dbStore,
swapStore);
}
@After
public void teardown() {
if (swapJob != null) {
swapJob.stop();
}
}
@After
public void teardown() {
if(swapJob != null) {
swapJob.stop();
}
private void waitASecond() {
try {
Thread.sleep(1 * 1000);
} catch (Exception _e) {
}
}
private void waitASecond() {
try { Thread.sleep(1 * 1000); } catch (Exception _e) {}
}
@Test
public void startingTimerAlwaysCausesASwap() {
swapJob.lowWatermarkBytes = 16384;
swapJob.interval = Duration.ofHours(1);
assertEquals(0, swapJob.swaps.get());
swapJob.start();
do {
waitASecond();
} while (swapJob.swaps.get() <= 0);
assertTrue(swapJob.swaps.get() > 0);
}
@Test
public void startingTimerAlwaysCausesASwap() {
swapJob.lowWatermarkBytes = 16384;
swapJob.interval = Duration.ofHours(1);
assertEquals(0, swapJob.swaps.get());
swapJob.start();
do { waitASecond(); } while (swapJob.swaps.get() <= 0);
assertTrue(swapJob.swaps.get() > 0);
}
@Test
public void swapsHappenEveryInterval() {
swapJob.lowWatermarkBytes = 16384;
assertEquals(0, swapJob.swaps.get());
swapJob.start();
do {
waitASecond();
} while (swapJob.swaps.get() <= 1);
assertTrue(swapJob.swaps.get() > 1);
}
@Test
public void swapsHappenEveryInterval() {
swapJob.lowWatermarkBytes = 16384;
assertEquals(0, swapJob.swaps.get());
swapJob.start();
do { waitASecond(); } while (swapJob.swaps.get() <= 1);
assertTrue(swapJob.swaps.get() > 1);
}
@Test
public void noProjectsGetSwappedWhenUnderHighWatermark() {
swapJob.highWatermarkBytes = 65536;
assertEquals(2, dbStore.getNumUnswappedProjects());
swapJob.start();
do {
waitASecond();
} while (swapJob.swaps.get() < 1);
assertEquals(2, dbStore.getNumUnswappedProjects());
}
@Test
public void noProjectsGetSwappedWhenUnderHighWatermark() {
swapJob.highWatermarkBytes = 65536;
assertEquals(2, dbStore.getNumUnswappedProjects());
swapJob.start();
do { waitASecond(); } while (swapJob.swaps.get() < 1);
assertEquals(2, dbStore.getNumUnswappedProjects());
}
@Test
public void correctProjGetSwappedWhenOverHighWatermark(
) throws IOException {
swapJob.lowWatermarkBytes = 16384;
assertEquals(2, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
swapJob.start();
do { waitASecond(); } while (swapJob.swaps.get() < 1);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj1", dbStore.getOldestUnswappedProject());
assertEquals("bzip2", dbStore.getSwapCompression("proj2"));
swapJob.restore("proj2");
assertEquals(null, dbStore.getSwapCompression("proj2"));
int numSwaps = swapJob.swaps.get();
do { waitASecond(); } while (swapJob.swaps.get() <= numSwaps);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
}
@Test
public void swapCompressionGzip() throws IOException {
swapJob = new SwapJobImpl(
1,
15000,
30000,
Duration.ofMillis(100),
SwapJob.CompressionMethod.Gzip,
lock,
repoStore,
dbStore,
swapStore
);
swapJob.lowWatermarkBytes = 16384;
assertEquals(2, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
swapJob.start();
do { waitASecond(); } while (swapJob.swaps.get() < 1);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj1", dbStore.getOldestUnswappedProject());
assertEquals("gzip", dbStore.getSwapCompression("proj2"));
swapJob.restore("proj2");
assertEquals(null, dbStore.getSwapCompression("proj2"));
int numSwaps = swapJob.swaps.get();
do { waitASecond(); } while (swapJob.swaps.get() <= numSwaps);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
}
@Test
public void correctProjGetSwappedWhenOverHighWatermark() throws IOException {
swapJob.lowWatermarkBytes = 16384;
assertEquals(2, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
swapJob.start();
do {
waitASecond();
} while (swapJob.swaps.get() < 1);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj1", dbStore.getOldestUnswappedProject());
assertEquals("bzip2", dbStore.getSwapCompression("proj2"));
swapJob.restore("proj2");
assertEquals(null, dbStore.getSwapCompression("proj2"));
int numSwaps = swapJob.swaps.get();
do {
waitASecond();
} while (swapJob.swaps.get() <= numSwaps);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
}
@Test
public void swapCompressionGzip() throws IOException {
swapJob =
new SwapJobImpl(
1,
15000,
30000,
Duration.ofMillis(100),
SwapJob.CompressionMethod.Gzip,
lock,
repoStore,
dbStore,
swapStore);
swapJob.lowWatermarkBytes = 16384;
assertEquals(2, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
swapJob.start();
do {
waitASecond();
} while (swapJob.swaps.get() < 1);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj1", dbStore.getOldestUnswappedProject());
assertEquals("gzip", dbStore.getSwapCompression("proj2"));
swapJob.restore("proj2");
assertEquals(null, dbStore.getSwapCompression("proj2"));
int numSwaps = swapJob.swaps.get();
do {
waitASecond();
} while (swapJob.swaps.get() <= numSwaps);
assertEquals(1, dbStore.getNumUnswappedProjects());
assertEquals("proj2", dbStore.getOldestUnswappedProject());
}
}

View File

@@ -1,96 +1,56 @@
package uk.ac.ic.wlgitbridge.bridge.swap.store;
import static org.junit.Assert.assertArrayEquals;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import uk.ac.ic.wlgitbridge.bridge.swap.store.InMemorySwapStore;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import static org.junit.Assert.assertArrayEquals;
/**
/*
* Created by winston on 23/08/2016.
*/
public class InMemorySwapStoreTest {
private final InMemorySwapStore swapStore = new InMemorySwapStore();
private final InMemorySwapStore swapStore = new InMemorySwapStore();
@Rule
public final ExpectedException exception = ExpectedException.none();
@Rule public final ExpectedException exception = ExpectedException.none();
@Test
public void downloadingNonExistentFileThrows() {
exception.expect(IllegalArgumentException.class);
swapStore.openDownloadStream("asdf");
}
@Test
public void downloadingNonExistentFileThrows() {
exception.expect(IllegalArgumentException.class);
swapStore.openDownloadStream("asdf");
}
@Test
public void canDownloadUploadedFiles() throws IOException {
byte[] proj1Contents = "helloproj1".getBytes();
byte[] proj2Contents = "asdfproj2".getBytes();
swapStore.upload(
"proj1",
new ByteArrayInputStream(proj1Contents),
proj1Contents.length
);
swapStore.upload(
"proj2",
new ByteArrayInputStream(proj2Contents),
proj2Contents.length
);
assertArrayEquals(
proj1Contents,
IOUtils.toByteArray(swapStore.openDownloadStream("proj1"))
);
assertArrayEquals(
proj2Contents,
IOUtils.toByteArray(swapStore.openDownloadStream("proj2"))
);
}
@Test
public void canDownloadUploadedFiles() throws IOException {
byte[] proj1Contents = "helloproj1".getBytes();
byte[] proj2Contents = "asdfproj2".getBytes();
swapStore.upload("proj1", new ByteArrayInputStream(proj1Contents), proj1Contents.length);
swapStore.upload("proj2", new ByteArrayInputStream(proj2Contents), proj2Contents.length);
assertArrayEquals(proj1Contents, IOUtils.toByteArray(swapStore.openDownloadStream("proj1")));
assertArrayEquals(proj2Contents, IOUtils.toByteArray(swapStore.openDownloadStream("proj2")));
}
@Test
public void uploadingForTheSameProjectOverwritesTheFile(
) throws IOException {
byte[] proj1Contents = "helloproj1".getBytes();
byte[] proj1NewContents = "goodbyeproj1".getBytes();
swapStore.upload(
"proj1",
new ByteArrayInputStream(proj1Contents),
proj1Contents.length
);
assertArrayEquals(
proj1Contents,
IOUtils.toByteArray(swapStore.openDownloadStream("proj1"))
);
swapStore.upload(
"proj1",
new ByteArrayInputStream(proj1NewContents),
proj1NewContents.length
);
assertArrayEquals(
proj1NewContents,
IOUtils.toByteArray(swapStore.openDownloadStream("proj1"))
);
}
@Test
public void uploadingForTheSameProjectOverwritesTheFile() throws IOException {
byte[] proj1Contents = "helloproj1".getBytes();
byte[] proj1NewContents = "goodbyeproj1".getBytes();
swapStore.upload("proj1", new ByteArrayInputStream(proj1Contents), proj1Contents.length);
assertArrayEquals(proj1Contents, IOUtils.toByteArray(swapStore.openDownloadStream("proj1")));
swapStore.upload("proj1", new ByteArrayInputStream(proj1NewContents), proj1NewContents.length);
assertArrayEquals(proj1NewContents, IOUtils.toByteArray(swapStore.openDownloadStream("proj1")));
}
@Test
public void canRemoveFiles() throws IOException {
byte[] projContents = "total garbage".getBytes();
swapStore.upload(
"proj",
new ByteArrayInputStream(projContents),
projContents.length
);
assertArrayEquals(
projContents,
IOUtils.toByteArray(swapStore.openDownloadStream("proj"))
);
swapStore.remove("proj");
exception.expect(IllegalArgumentException.class);
swapStore.openDownloadStream("proj");
}
}
@Test
public void canRemoveFiles() throws IOException {
byte[] projContents = "total garbage".getBytes();
swapStore.upload("proj", new ByteArrayInputStream(projContents), projContents.length);
assertArrayEquals(projContents, IOUtils.toByteArray(swapStore.openDownloadStream("proj")));
swapStore.remove("proj");
exception.expect(IllegalArgumentException.class);
swapStore.openDownloadStream("proj");
}
}

View File

@@ -2,41 +2,41 @@ package uk.ac.ic.wlgitbridge.bridge.swap.store;
import org.junit.Before;
/**
/*
* Created by winston on 21/08/2016.
*/
public class S3SwapStoreTest {
private static final String accessKey = null;
private static final String secret = null;
private static final String bucketName = "com.overleaf.testbucket";
private static final String region = "us-east-1";
private static final String accessKey = null;
private static final String secret = null;
private static final String bucketName = "com.overleaf.testbucket";
private static final String region = "us-east-1";
private S3SwapStore s3;
private S3SwapStore s3;
@Before
public void setup() {
if (accessKey == null || secret == null) {
s3 = null;
return;
}
s3 = new S3SwapStore(accessKey, secret, bucketName, region);
@Before
public void setup() {
if (accessKey == null || secret == null) {
s3 = null;
return;
}
s3 = new S3SwapStore(accessKey, secret, bucketName, region);
}
// @Ignore
// @Test
// public void testUploadDownloadDelete() throws Exception {
// assumeNotNull(s3);
// String projName = "abc123";
// byte[] contents = "hello".getBytes();
// s3.upload(
// projName,
// new ByteArrayInputStream(contents),
// contents.length
// );
// InputStream down = s3.openDownloadStream(projName);
// s3.remove(projName);
// assertArrayEquals(contents, IOUtils.toByteArray(down));
// }
// @Ignore
// @Test
// public void testUploadDownloadDelete() throws Exception {
// assumeNotNull(s3);
// String projName = "abc123";
// byte[] contents = "hello".getBytes();
// s3.upload(
// projName,
// new ByteArrayInputStream(contents),
// contents.length
// );
// InputStream down = s3.openDownloadStream(projName);
// s3.remove(projName);
// assertArrayEquals(contents, IOUtils.toByteArray(down));
// }
}

View File

@@ -1,5 +1,13 @@
package uk.ac.ic.wlgitbridge.data.model;
import static org.junit.Assert.assertEquals;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Rule;
@@ -16,66 +24,51 @@ import uk.ac.ic.wlgitbridge.bridge.resource.UrlResourceCache;
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static org.junit.Assert.assertEquals;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
/**
/*
* Created by m on 20/11/15.
*/
public class ResourceFetcherTest {
@Rule
public MockServerRule mockServerRule = new MockServerRule(this);
@Rule public MockServerRule mockServerRule = new MockServerRule(this);
private MockServerClient mockServerClient;
private MockServerClient mockServerClient;
@Test
public void fetchesFilesThatAreMissingFromUrlStoreCache() throws IOException, GitUserException {
final String testProjectName = "123abc";
final String testUrl = "http://localhost:" + mockServerRule.getPort() + "/123abc";
final String oldTestPath = "testPath";
final String newTestPath = "missingPath";
@Test
public void fetchesFilesThatAreMissingFromUrlStoreCache() throws IOException, GitUserException {
final String testProjectName = "123abc";
final String testUrl = "http://localhost:" + mockServerRule.getPort() + "/123abc";
final String oldTestPath = "testPath";
final String newTestPath = "missingPath";
mockServerClient.when(
request()
.withMethod("GET")
.withPath("/123abc")
)
.respond(
response()
.withStatusCode(200)
.withBody("content")
);
mockServerClient
.when(request().withMethod("GET").withPath("/123abc"))
.respond(response().withStatusCode(200).withBody("content"));
final Mockery context = new Mockery();
final DBStore dbStore = context.mock(DBStore.class);
context.checking(new Expectations() {{
final Mockery context = new Mockery();
final DBStore dbStore = context.mock(DBStore.class);
context.checking(
new Expectations() {
{
// It should fetch the file once it finds it is missing.
oneOf(dbStore).getPathForURLInProject(testProjectName, testUrl);
will(returnValue(oldTestPath));
// It should update the URL index store once it has fetched; at present, it does not actually change the stored path.
// It should update the URL index store once it has fetched; at present, it does not
// actually change the stored path.
oneOf(dbStore).addURLIndexForProject(testProjectName, testUrl, oldTestPath);
}});
}
});
ResourceCache resources = new UrlResourceCache(dbStore);
TemporaryFolder repositoryFolder = new TemporaryFolder();
repositoryFolder.create();
String repoStorePath = repositoryFolder.getRoot().getAbsolutePath();
RepoStore repoStore = new FSGitRepoStore(repoStorePath, Optional.empty());
ProjectRepo repo = repoStore.initRepo("repo");
Map<String, RawFile> fileTable = repo.getDirectory().getFileTable();
Map<String, byte[]> fetchedUrls = new HashMap<>();
resources.get(
testProjectName, testUrl, newTestPath,
fileTable, fetchedUrls, Optional.empty());
ResourceCache resources = new UrlResourceCache(dbStore);
TemporaryFolder repositoryFolder = new TemporaryFolder();
repositoryFolder.create();
String repoStorePath = repositoryFolder.getRoot().getAbsolutePath();
RepoStore repoStore = new FSGitRepoStore(repoStorePath, Optional.empty());
ProjectRepo repo = repoStore.initRepo("repo");
Map<String, RawFile> fileTable = repo.getDirectory().getFileTable();
Map<String, byte[]> fetchedUrls = new HashMap<>();
resources.get(testProjectName, testUrl, newTestPath, fileTable, fetchedUrls, Optional.empty());
// We don't bother caching in this case, at present.
assertEquals(0, fetchedUrls.size());
}
// We don't bother caching in this case, at present.
assertEquals(0, fetchedUrls.size());
}
}

View File

@@ -1,59 +1,54 @@
package uk.ac.ic.wlgitbridge.snapshot.push;
import static org.junit.Assert.*;
import org.junit.Assert;
import org.junit.Test;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InternalErrorException;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.UnexpectedPostbackException;
import static org.junit.Assert.*;
/**
/*
* Created by winston on 05/04/2016.
*/
public class PostbackManagerTest {
private final PostbackManager postbackManager = new PostbackManager();
private final PostbackManager postbackManager = new PostbackManager();
@Test
public void testRaceWithVersionId()
throws UnexpectedPostbackException,
SnapshotPostException {
String key = postbackManager.makeKeyForProject("proj");
postbackManager.postVersionIDForProject("proj", 1, key);
int versionId = postbackManager.waitForVersionIdOrThrow("proj");
assertEquals("Version id didn't match posted", 1, versionId);
}
@Test
public void testRaceWithException() throws UnexpectedPostbackException,
SnapshotPostException {
String key = postbackManager.makeKeyForProject("proj");
InternalErrorException ex = new InternalErrorException();
postbackManager.postExceptionForProject("proj", ex, key);
try {
postbackManager.waitForVersionIdOrThrow("proj");
} catch (InternalErrorException e) {
Assert.assertSame("Wrong exception was thrown", ex, e);
return;
}
Assert.fail("Exception wasn't thrown as required");
}
@Test
public void testTableConsistency() throws UnexpectedPostbackException,
SnapshotPostException {
String key1 = postbackManager.makeKeyForProject("proj1");
assertEquals(1, postbackManager.postbackContentsTable.size());
String key2 = postbackManager.makeKeyForProject("proj2");
assertEquals(2, postbackManager.postbackContentsTable.size());
postbackManager.postVersionIDForProject("proj1", 1, key1);
postbackManager.postVersionIDForProject("proj2", 1, key2);
assertEquals(2, postbackManager.postbackContentsTable.size());
postbackManager.waitForVersionIdOrThrow("proj1");
assertEquals(1, postbackManager.postbackContentsTable.size());
postbackManager.waitForVersionIdOrThrow("proj2");
Assert.assertTrue(postbackManager.postbackContentsTable.isEmpty());
@Test
public void testRaceWithVersionId() throws UnexpectedPostbackException, SnapshotPostException {
String key = postbackManager.makeKeyForProject("proj");
postbackManager.postVersionIDForProject("proj", 1, key);
int versionId = postbackManager.waitForVersionIdOrThrow("proj");
assertEquals("Version id didn't match posted", 1, versionId);
}
@Test
public void testRaceWithException() throws UnexpectedPostbackException, SnapshotPostException {
String key = postbackManager.makeKeyForProject("proj");
InternalErrorException ex = new InternalErrorException();
postbackManager.postExceptionForProject("proj", ex, key);
try {
postbackManager.waitForVersionIdOrThrow("proj");
} catch (InternalErrorException e) {
Assert.assertSame("Wrong exception was thrown", ex, e);
return;
}
Assert.fail("Exception wasn't thrown as required");
}
@Test
public void testTableConsistency() throws UnexpectedPostbackException, SnapshotPostException {
String key1 = postbackManager.makeKeyForProject("proj1");
assertEquals(1, postbackManager.postbackContentsTable.size());
String key2 = postbackManager.makeKeyForProject("proj2");
assertEquals(2, postbackManager.postbackContentsTable.size());
postbackManager.postVersionIDForProject("proj1", 1, key1);
postbackManager.postVersionIDForProject("proj2", 1, key2);
assertEquals(2, postbackManager.postbackContentsTable.size());
postbackManager.waitForVersionIdOrThrow("proj1");
assertEquals(1, postbackManager.postbackContentsTable.size());
postbackManager.waitForVersionIdOrThrow("proj2");
Assert.assertTrue(postbackManager.postbackContentsTable.isEmpty());
}
}

View File

@@ -1,61 +1,130 @@
package uk.ac.ic.wlgitbridge.snapshot.servermock.util;
import org.junit.Assert;
import org.junit.Test;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Assert;
import org.junit.Test;
public class FileUtilTest {
@Test
public void returnsTrueWhenFilesAreEqualInBothDirectories() throws URISyntaxException {
Path eq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenFilesAreEqualInBothDirectories/eq1").toURI());
Path eq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenFilesAreEqualInBothDirectories/eq2").toURI());
Assert.assertTrue(FileUtil.gitDirectoriesAreEqual(eq1, eq2));
}
@Test
public void returnsTrueWhenFilesAreEqualInBothDirectories() throws URISyntaxException {
Path eq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenFilesAreEqualInBothDirectories/eq1")
.toURI());
Path eq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenFilesAreEqualInBothDirectories/eq2")
.toURI());
Assert.assertTrue(FileUtil.gitDirectoriesAreEqual(eq1, eq2));
}
@Test
public void returnsTrueWhenRecursiveFilesAreEqualInBothDirectores() throws URISyntaxException {
Path eq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenRecursiveFilesAreEqualInBothDirectories/eq1").toURI());
Path eq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenRecursiveFilesAreEqualInBothDirectories/eq2").toURI());
Assert.assertTrue(FileUtil.gitDirectoriesAreEqual(eq1, eq2));
}
@Test
public void returnsTrueWhenRecursiveFilesAreEqualInBothDirectores() throws URISyntaxException {
Path eq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenRecursiveFilesAreEqualInBothDirectories/eq1")
.toURI());
Path eq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueWhenRecursiveFilesAreEqualInBothDirectories/eq2")
.toURI());
Assert.assertTrue(FileUtil.gitDirectoriesAreEqual(eq1, eq2));
}
@Test
public void returnsFalseWhenFilesAreNotEqualInBothDirectories() throws URISyntaxException {
Path neq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenFilesAreNotEqualInBothDirectories/neq1").toURI());
Path neq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenFilesAreNotEqualInBothDirectories/neq2").toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsFalseWhenFilesAreNotEqualInBothDirectories() throws URISyntaxException {
Path neq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenFilesAreNotEqualInBothDirectories/neq1")
.toURI());
Path neq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenFilesAreNotEqualInBothDirectories/neq2")
.toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsFalseWhenRecursiveFilesAreNotEqualInBothDirectories() throws URISyntaxException {
Path neq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenRecursiveFilesAreNotEqualInBothDirectories/neq1").toURI());
Path neq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenRecursiveFilesAreNotEqualInBothDirectories/neq2").toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsFalseWhenRecursiveFilesAreNotEqualInBothDirectories()
throws URISyntaxException {
Path neq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenRecursiveFilesAreNotEqualInBothDirectories/neq1")
.toURI());
Path neq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseWhenRecursiveFilesAreNotEqualInBothDirectories/neq2")
.toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsTrueEvenIfGitDirectoriesAreNotEqual() throws URISyntaxException {
Path neq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueEvenIfGitDirectoriesAreNotEqual/eq1").toURI());
Path neq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueEvenIfGitDirectoriesAreNotEqual/eq2").toURI());
Assert.assertTrue(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsTrueEvenIfGitDirectoriesAreNotEqual() throws URISyntaxException {
Path neq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueEvenIfGitDirectoriesAreNotEqual/eq1")
.toURI());
Path neq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsTrueEvenIfGitDirectoriesAreNotEqual/eq2")
.toURI());
Assert.assertTrue(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsFalseIfFileNamesAreNotEqual() throws URISyntaxException {
Path neq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfFileNamesAreNotEqual/neq1").toURI());
Path neq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfFileNamesAreNotEqual/neq2").toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsFalseIfFileNamesAreNotEqual() throws URISyntaxException {
Path neq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfFileNamesAreNotEqual/neq1")
.toURI());
Path neq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfFileNamesAreNotEqual/neq2")
.toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
@Test
public void returnsFalseIfInnerDirectoryNamesAreNotEqual() throws URISyntaxException {
Path neq1 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfInnerDirectoryNamesAreNotEqual/neq1").toURI());
Path neq2 = Paths.get(getClass().getResource("/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfInnerDirectoryNamesAreNotEqual/neq2").toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
}
@Test
public void returnsFalseIfInnerDirectoryNamesAreNotEqual() throws URISyntaxException {
Path neq1 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfInnerDirectoryNamesAreNotEqual/neq1")
.toURI());
Path neq2 =
Paths.get(
getClass()
.getResource(
"/uk/ac/ic/wlgitbridge/snapshot/servermock/util/FileUtilTest/returnsFalseIfInnerDirectoryNamesAreNotEqual/neq2")
.toURI());
Assert.assertFalse(FileUtil.gitDirectoriesAreEqual(neq1, neq2));
}
}

View File

@@ -3,16 +3,15 @@ package uk.ac.ic.wlgitbridge.util;
import org.junit.Assert;
import org.junit.Test;
/**
/*
* Created by winston on 23/08/2016.
*/
public class ProjectTest {
@Test
public void testValidProjectNames() {
Assert.assertFalse(Project.isValidProjectName(null));
Assert.assertFalse(Project.isValidProjectName(""));
Assert.assertFalse(Project.isValidProjectName(".wlgb"));
}
@Test
public void testValidProjectNames() {
Assert.assertFalse(Project.isValidProjectName(null));
Assert.assertFalse(Project.isValidProjectName(""));
Assert.assertFalse(Project.isValidProjectName(".wlgb"));
}
}

View File

@@ -1,76 +1,70 @@
package uk.ac.ic.wlgitbridge.util;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static org.junit.Assert.assertTrue;
/**
/*
* Created by winston on 23/08/2016.
*/
public class TarTest {
private static final String RESOURCE_DIR
= "/uk/ac/ic/wlgitbridge/util/TarTest";
private static final String RESOURCE_DIR = "/uk/ac/ic/wlgitbridge/util/TarTest";
private File testDir;
private File dirWithEmptyFile;
private File tmpDir;
private File testDir;
private File dirWithEmptyFile;
private File tmpDir;
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
testDir = ResourceUtil.copyOfFolderResource(
RESOURCE_DIR + "/testdir",
tmpFolder::newFolder);
dirWithEmptyFile = ResourceUtil.copyOfFolderResource(
RESOURCE_DIR + "/dir_with_empty_file",
tmpFolder::newFolder);
tmpDir = tmpFolder.newFolder();
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
testDir = ResourceUtil.copyOfFolderResource(RESOURCE_DIR + "/testdir", tmpFolder::newFolder);
dirWithEmptyFile =
ResourceUtil.copyOfFolderResource(
RESOURCE_DIR + "/dir_with_empty_file", tmpFolder::newFolder);
tmpDir = tmpFolder.newFolder();
}
/*
* Compresses inputDir and decompresses to outputDir. Checks equality
* between outputDir and inputDir.
* @param inputDir the directory to compress
* @param outputDir the output directory. Must be empty.
* @param compressFunction compression function
* @param decompressFunction decompression function
* @throws IOException
*/
private static void assertCompDecompEqual(
File inputDir,
File outputDir,
FunctionT<File, InputStream, IOException> compressFunction,
BiConsumerT<InputStream, File, IOException> decompressFunction)
throws IOException {
try (InputStream tarbz2 = compressFunction.apply(inputDir)) {
decompressFunction.accept(tarbz2, outputDir);
File unzipped = new File(outputDir, inputDir.getName());
assertTrue(Files.contentsAreEqual(inputDir, unzipped));
}
}
/**
* Compresses inputDir and decompresses to outputDir. Checks equality
* between outputDir and inputDir.
* @param inputDir the directory to compress
* @param outputDir the output directory. Must be empty.
* @param compressFunction compression function
* @param decompressFunction decompression function
* @throws IOException
*/
private static void assertCompDecompEqual(
File inputDir,
File outputDir,
FunctionT<File, InputStream, IOException> compressFunction,
BiConsumerT<InputStream, File, IOException> decompressFunction
) throws IOException {
try (InputStream tarbz2 = compressFunction.apply(inputDir)) {
decompressFunction.accept(tarbz2, outputDir);
File unzipped = new File(outputDir, inputDir.getName());
assertTrue(Files.contentsAreEqual(inputDir, unzipped));
}
}
@Test
public void tarAndUntarProducesTheSameResult() throws IOException {
assertCompDecompEqual(testDir, tmpDir, Tar::tar, Tar::untar);
}
@Test
public void tarAndUntarProducesTheSameResult() throws IOException {
assertCompDecompEqual(testDir, tmpDir, Tar::tar, Tar::untar);
}
@Test
public void tarbz2AndUntarbz2ProducesTheSameResult() throws IOException {
assertCompDecompEqual(testDir, tmpDir, Tar.bz2::zip, Tar.bz2::unzip);
}
@Test
public void tarbz2WorksOnDirectoriesWithAnEmptyFile() throws IOException {
assertCompDecompEqual(
dirWithEmptyFile, tmpDir, Tar.bz2::zip, Tar.bz2::unzip);
}
@Test
public void tarbz2AndUntarbz2ProducesTheSameResult() throws IOException {
assertCompDecompEqual(testDir, tmpDir, Tar.bz2::zip, Tar.bz2::unzip);
}
@Test
public void tarbz2WorksOnDirectoriesWithAnEmptyFile() throws IOException {
assertCompDecompEqual(dirWithEmptyFile, tmpDir, Tar.bz2::zip, Tar.bz2::unzip);
}
}

View File

@@ -1,19 +1,18 @@
package uk.ac.ic.wlgitbridge.util;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
import org.junit.Test;
/*
* Created by winston on 23/08/2016.
*/
public class TimerUtilsTest {
@Test
public void testMakeTimerTask() {
int[] iPtr = new int[] { 3 };
TimerUtils.makeTimerTask(() -> iPtr[0] = 5).run();
assertEquals(5, iPtr[0]);
}
@Test
public void testMakeTimerTask() {
int[] iPtr = new int[] {3};
TimerUtils.makeTimerTask(() -> iPtr[0] = 5).run();
assertEquals(5, iPtr[0]);
}
}