Quellcode durchsuchen

Implement and test the swap job, and add integration test

Winston Li vor 10 Jahren
Ursprung
Commit
9936fbe3c9
20 geänderte Dateien mit 258 neuen und 45 gelöschten Zeilen
  1. 1 1
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java
  2. 8 0
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java
  3. 4 1
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java
  4. 0 3
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java
  5. 4 0
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java
  6. 1 0
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java
  7. 4 4
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLReceivePackFactory.java
  8. 4 4
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/hook/WriteLatexPutHook.java
  9. 6 5
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java
  10. 5 5
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/PostbackContents.java
  11. 4 4
      services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/PostbackHandler.java
  12. 96 18
      services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/WLGitBridgeIntegrationTest.java
  13. 27 0
      services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java
  14. 90 0
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/state.json
  15. 1 0
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/foo/bar/test.tex
  16. 1 0
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/main.tex
  17. BIN
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/overleaf-white-410.png
  18. BIN
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png
  19. 1 0
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/foo/bar/test.tex
  20. 1 0
      services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/main.tex

+ 1 - 1
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java

@@ -25,7 +25,7 @@ public class GitBridgeApp implements Runnable {
             "usage: writelatex-git-bridge config_file";
             "usage: writelatex-git-bridge config_file";
 
 
     private String configFilePath;
     private String configFilePath;
-    private Config config;
+    Config config;
     private GitBridgeServer server;
     private GitBridgeServer server;
 
 
     /**
     /**

+ 8 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java

@@ -98,6 +98,14 @@ public class Config implements JSONSource {
             postbackURL += "/";
             postbackURL += "/";
         }
         }
         oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class);
         oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class);
+        swapStore = new Gson().fromJson(
+                configObject.get("swapStore"),
+                SwapStoreConfig.class
+        );
+        swapJob = new Gson().fromJson(
+                configObject.get("swapJob"),
+                SwapJobConfig.class
+        );
     }
     }
 
 
     public String getSanitisedString() {
     public String getSanitisedString() {

+ 4 - 1
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java

@@ -10,6 +10,9 @@ import java.util.Collection;
  */
  */
 public interface RepoStore {
 public interface RepoStore {
 
 
+    /* Still need to get rid of these two methods.
+       Main dependency: GitRepoStore needs a Repository which needs a directory.
+       Instead, use a visitor or something. */
     String getRepoStorePath();
     String getRepoStorePath();
 
 
     File getRootDirectory();
     File getRootDirectory();
@@ -20,7 +23,7 @@ public interface RepoStore {
 
 
     long totalSize();
     long totalSize();
 
 
-    /*
+    /**
      * Tars and bzip2s the .git directory of the given project. Throws an
      * Tars and bzip2s the .git directory of the given project. Throws an
      * IOException if the project doesn't exist. The returned stream is a copy
      * IOException if the project doesn't exist. The returned stream is a copy
      * of the original .git directory, which must be deleted using remove().
      * of the original .git directory, which must be deleted using remove().

+ 0 - 3
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java

@@ -5,9 +5,6 @@ package uk.ac.ic.wlgitbridge.bridge.swap.job;
  */
  */
 public class SwapJobConfig {
 public class SwapJobConfig {
 
 
-    public static final SwapJobConfig DEFAULT =
-            new SwapJobConfig(1, 1, 2, 3600000);
-
     private final int minProjects;
     private final int minProjects;
     private final int lowGiB;
     private final int lowGiB;
     private final int highGiB;
     private final int highGiB;

+ 4 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java

@@ -19,6 +19,10 @@ public class InMemorySwapStore implements SwapStore {
         store = new HashMap<>();
         store = new HashMap<>();
     }
     }
 
 
+    public InMemorySwapStore(SwapStoreConfig __) {
+        this();
+    }
+
     @Override
     @Override
     public void upload(
     public void upload(
             String projectName,
             String projectName,

+ 1 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java

@@ -17,6 +17,7 @@ public interface SwapStore {
 
 
                 {
                 {
                     put("noop", NoopSwapStore::new);
                     put("noop", NoopSwapStore::new);
+                    put("memory", InMemorySwapStore::new);
                     put("s3", S3SwapStore::new);
                     put("s3", S3SwapStore::new);
                 }
                 }
 
 

+ 4 - 4
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/WLReceivePackFactory.java

@@ -19,10 +19,10 @@ import javax.servlet.http.HttpServletRequest;
 /* */
 /* */
 public class WLReceivePackFactory implements ReceivePackFactory<HttpServletRequest> {
 public class WLReceivePackFactory implements ReceivePackFactory<HttpServletRequest> {
 
 
-    private final Bridge bridgeAPI;
+    private final Bridge bridge;
 
 
-    public WLReceivePackFactory(Bridge bridgeAPI) {
-        this.bridgeAPI = bridgeAPI;
+    public WLReceivePackFactory(Bridge bridge) {
+        this.bridge = bridge;
     }
     }
 
 
     @Override
     @Override
@@ -33,7 +33,7 @@ public class WLReceivePackFactory implements ReceivePackFactory<HttpServletReque
         if (hostname == null) {
         if (hostname == null) {
             hostname = httpServletRequest.getLocalName();
             hostname = httpServletRequest.getLocalName();
         }
         }
-        receivePack.setPreReceiveHook(new WriteLatexPutHook(bridgeAPI, hostname, oauth2));
+        receivePack.setPreReceiveHook(new WriteLatexPutHook(bridge, hostname, oauth2));
         return receivePack;
         return receivePack;
     }
     }
 
 

+ 4 - 4
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/git/handler/hook/WriteLatexPutHook.java

@@ -26,12 +26,12 @@ import java.util.Iterator;
  */
  */
 public class WriteLatexPutHook implements PreReceiveHook {
 public class WriteLatexPutHook implements PreReceiveHook {
 
 
-    private final Bridge bridgeAPI;
+    private final Bridge bridge;
     private final String hostname;
     private final String hostname;
     private final Credential oauth2;
     private final Credential oauth2;
 
 
-    public WriteLatexPutHook(Bridge bridgeAPI, String hostname, Credential oauth2) {
-        this.bridgeAPI = bridgeAPI;
+    public WriteLatexPutHook(Bridge bridge, String hostname, Credential oauth2) {
+        this.bridge = bridge;
         this.hostname = hostname;
         this.hostname = hostname;
         this.oauth2 = oauth2;
         this.oauth2 = oauth2;
     }
     }
@@ -75,7 +75,7 @@ public class WriteLatexPutHook implements PreReceiveHook {
     private void handleReceiveCommand(Credential oauth2, Repository repository, ReceiveCommand receiveCommand) throws IOException, GitUserException {
     private void handleReceiveCommand(Credential oauth2, Repository repository, ReceiveCommand receiveCommand) throws IOException, GitUserException {
         checkBranch(receiveCommand);
         checkBranch(receiveCommand);
         checkForcedPush(receiveCommand);
         checkForcedPush(receiveCommand);
-        bridgeAPI.putDirectoryContentsToProjectWithName(
+        bridge.putDirectoryContentsToProjectWithName(
                 oauth2,
                 oauth2,
                 repository.getWorkTree().getName(),
                 repository.getWorkTree().getName(),
                 getPushedDirectoryContents(repository,
                 getPushedDirectoryContents(repository,

+ 6 - 5
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java

@@ -37,7 +37,7 @@ import java.util.EnumSet;
  */
  */
 public class GitBridgeServer {
 public class GitBridgeServer {
 
 
-    private final Bridge bridgeAPI;
+    private final Bridge bridge;
 
 
     private final Server jettyServer;
     private final Server jettyServer;
 
 
@@ -58,7 +58,7 @@ public class GitBridgeServer {
                 ).resolve(".wlgb").resolve("wlgb.db").toFile()
                 ).resolve(".wlgb").resolve("wlgb.db").toFile()
         );
         );
         SwapStore swapStore = SwapStore.fromConfig(config.getSwapStore());
         SwapStore swapStore = SwapStore.fromConfig(config.getSwapStore());
-        bridgeAPI = Bridge.make(
+        bridge = Bridge.make(
                 repoStore,
                 repoStore,
                 dbStore,
                 dbStore,
                 swapStore,
                 swapStore,
@@ -83,6 +83,7 @@ public class GitBridgeServer {
     public void start() {
     public void start() {
         try {
         try {
             jettyServer.start();
             jettyServer.start();
+            bridge.startSwapJob();
             Log.info(Util.getServiceName() + "-Git Bridge server started");
             Log.info(Util.getServiceName() + "-Git Bridge server started");
             Log.info("Listening on port: " + port);
             Log.info("Listening on port: " + port);
             Log.info("Bridged to: " + apiBaseURL);
             Log.info("Bridged to: " + apiBaseURL);
@@ -118,7 +119,7 @@ public class GitBridgeServer {
 
 
         HandlerCollection handlers = new HandlerList();
         HandlerCollection handlers = new HandlerList();
         handlers.addHandler(initResourceHandler());
         handlers.addHandler(initResourceHandler());
-        handlers.addHandler(new PostbackHandler(bridgeAPI));
+        handlers.addHandler(new PostbackHandler(bridge));
         handlers.addHandler(new DefaultHandler());
         handlers.addHandler(new DefaultHandler());
 
 
         api.setHandler(handlers);
         api.setHandler(handlers);
@@ -143,7 +144,7 @@ public class GitBridgeServer {
                 new ServletHolder(
                 new ServletHolder(
                         new WLGitServlet(
                         new WLGitServlet(
                                 servletContextHandler,
                                 servletContextHandler,
-                                bridgeAPI
+                                bridge
                         )
                         )
                 ),
                 ),
                 "/*"
                 "/*"
@@ -152,7 +153,7 @@ public class GitBridgeServer {
     }
     }
 
 
     private Handler initResourceHandler() {
     private Handler initResourceHandler() {
-        ResourceHandler resourceHandler = new FileHandler(bridgeAPI);
+        ResourceHandler resourceHandler = new FileHandler(bridge);
         resourceHandler.setResourceBase(
         resourceHandler.setResourceBase(
                 new File(rootGitDirectoryPath, ".wlgb/atts").getAbsolutePath()
                 new File(rootGitDirectoryPath, ".wlgb/atts").getAbsolutePath()
         );
         );

+ 5 - 5
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/PostbackContents.java

@@ -17,7 +17,7 @@ public class PostbackContents implements JSONSource {
 
 
     private static final String CODE_SUCCESS = "upToDate";
     private static final String CODE_SUCCESS = "upToDate";
 
 
-    private final Bridge bridgeAPI;
+    private final Bridge bridge;
     private final String projectName;
     private final String projectName;
     private final String postbackKey;
     private final String postbackKey;
 
 
@@ -26,8 +26,8 @@ public class PostbackContents implements JSONSource {
     private int versionID;
     private int versionID;
     private SnapshotPostException exception;
     private SnapshotPostException exception;
 
 
-    public PostbackContents(Bridge bridgeAPI, String projectName, String postbackKey, String contents) {
-        this.bridgeAPI = bridgeAPI;
+    public PostbackContents(Bridge bridge, String projectName, String postbackKey, String contents) {
+        this.bridge = bridge;
         this.projectName = projectName;
         this.projectName = projectName;
         this.postbackKey = postbackKey;
         this.postbackKey = postbackKey;
         snapshotPostExceptionBuilder = new SnapshotPostExceptionBuilder();
         snapshotPostExceptionBuilder = new SnapshotPostExceptionBuilder();
@@ -43,9 +43,9 @@ public class PostbackContents implements JSONSource {
 
 
     public void processPostback() throws UnexpectedPostbackException {
     public void processPostback() throws UnexpectedPostbackException {
         if (exception == null) {
         if (exception == null) {
-            bridgeAPI.postbackReceivedSuccessfully(projectName, postbackKey, versionID);
+            bridge.postbackReceivedSuccessfully(projectName, postbackKey, versionID);
         } else {
         } else {
-            bridgeAPI.postbackReceivedWithException(projectName, postbackKey, exception);
+            bridge.postbackReceivedWithException(projectName, postbackKey, exception);
         }
         }
     }
     }
 
 

+ 4 - 4
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/PostbackHandler.java

@@ -19,10 +19,10 @@ import java.io.IOException;
  */
  */
 public class PostbackHandler extends AbstractHandler {
 public class PostbackHandler extends AbstractHandler {
 
 
-    private final Bridge bridgeAPI;
+    private final Bridge bridge;
 
 
-    public PostbackHandler(Bridge bridgeAPI) {
-        this.bridgeAPI = bridgeAPI;
+    public PostbackHandler(Bridge bridge) {
+        this.bridge = bridge;
     }
     }
 
 
     @Override
     @Override
@@ -39,7 +39,7 @@ public class PostbackHandler extends AbstractHandler {
                 String projectName = parts[1];
                 String projectName = parts[1];
                 String postbackKey = parts[2];
                 String postbackKey = parts[2];
                 Log.info(baseRequest.getMethod() + " <- " + baseRequest.getHttpURI());
                 Log.info(baseRequest.getMethod() + " <- " + baseRequest.getHttpURI());
-                PostbackContents postbackContents = new PostbackContents(bridgeAPI, projectName, postbackKey, contents);
+                PostbackContents postbackContents = new PostbackContents(bridge, projectName, postbackKey, contents);
                 JsonObject body = new JsonObject();
                 JsonObject body = new JsonObject();
 
 
                 try {
                 try {

+ 96 - 18
services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest.java → services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/WLGitBridgeIntegrationTest.java

@@ -1,13 +1,14 @@
-package uk.ac.ic.wlgitbridge;
+package uk.ac.ic.wlgitbridge.application;
 
 
 import com.ning.http.client.AsyncHttpClient;
 import com.ning.http.client.AsyncHttpClient;
 import com.ning.http.client.Response;
 import com.ning.http.client.Response;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.IOUtils;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.junit.Rule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.junit.rules.TemporaryFolder;
-import uk.ac.ic.wlgitbridge.application.GitBridgeApp;
+import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
 import uk.ac.ic.wlgitbridge.snapshot.servermock.server.MockSnapshotServer;
 import uk.ac.ic.wlgitbridge.snapshot.servermock.server.MockSnapshotServer;
 import uk.ac.ic.wlgitbridge.snapshot.servermock.state.SnapshotAPIState;
 import uk.ac.ic.wlgitbridge.snapshot.servermock.state.SnapshotAPIState;
 import uk.ac.ic.wlgitbridge.snapshot.servermock.state.SnapshotAPIStateBuilder;
 import uk.ac.ic.wlgitbridge.snapshot.servermock.state.SnapshotAPIStateBuilder;
@@ -102,6 +103,9 @@ public class WLGitBridgeIntegrationTest {
         put("canServePushedFiles", new HashMap<String, SnapshotAPIState>() {{
         put("canServePushedFiles", new HashMap<String, SnapshotAPIState>() {{
             put("state", new SnapshotAPIStateBuilder(getResourceAsStream("/canServePushedFiles/state/state.json")).build());
             put("state", new SnapshotAPIStateBuilder(getResourceAsStream("/canServePushedFiles/state/state.json")).build());
         }});
         }});
+        put("wlgbCanSwapProjects", new HashMap<String, SnapshotAPIState>() {{
+            put("state", new SnapshotAPIStateBuilder(getResourceAsStream("/wlgbCanSwapProjects/state/state.json")).build());
+        }});
     }};
     }};
 
 
     @Rule
     @Rule
@@ -587,6 +591,38 @@ public class WLGitBridgeIntegrationTest {
         wlgb.stop();
         wlgb.stop();
     }
     }
 
 
+    @Test
+    public void wlgbCanSwapProjects(
+    ) throws IOException, GitAPIException, InterruptedException {
+        MockSnapshotServer server = new MockSnapshotServer(
+                3874,
+                getResource("/wlgbCanSwapProjects").toFile()
+        );
+        server.start();
+        server.setState(states.get("wlgbCanSwapProjects").get("state"));
+        GitBridgeApp wlgb = new GitBridgeApp(new String[] {
+                makeConfigFile(33874, 3874, new SwapJobConfig(1, 0, 0, 250))
+        });
+        wlgb.run();
+        File dir = folder.newFolder();
+        File rootGitDir = new File(wlgb.config.getRootGitDirectory());
+        File testProj1ServerDir = new File(rootGitDir, "testproj1");
+        File testProj2ServerDir = new File(rootGitDir, "testproj2");
+        File testProj1Dir = cloneRepository("testproj1", 33874, dir);
+        assertTrue(testProj1ServerDir.exists());
+        assertFalse(testProj2ServerDir.exists());
+        cloneRepository("testproj2", 33874, dir);
+        while (testProj1ServerDir.exists());
+        assertFalse(testProj1ServerDir.exists());
+        assertTrue(testProj2ServerDir.exists());
+        FileUtils.deleteDirectory(testProj1Dir);
+        cloneRepository("testproj1", 33874, dir);
+        while (testProj2ServerDir.exists());
+        assertTrue(testProj1ServerDir.exists());
+        assertFalse(testProj2ServerDir.exists());
+        wlgb.stop();
+    }
+
     private File cloneRepository(String repositoryName, int port, File dir) throws IOException, InterruptedException {
     private File cloneRepository(String repositoryName, int port, File dir) throws IOException, InterruptedException {
         String repo = "git clone http://127.0.0.1:" + port + "/" + repositoryName + ".git";
         String repo = "git clone http://127.0.0.1:" + port + "/" + repositoryName + ".git";
         Process gitProcess = runtime.exec(repo, null, dir);
         Process gitProcess = runtime.exec(repo, null, dir);
@@ -606,30 +642,72 @@ public class WLGitBridgeIntegrationTest {
         return repositoryDir;
         return repositoryDir;
     }
     }
 
 
-    private String makeConfigFile(int port, int apiPort) throws IOException {
+    private String makeConfigFile(
+            int port,
+            int apiPort
+    ) throws IOException {
+        return makeConfigFile(port, apiPort, null);
+    }
+
+    private String makeConfigFile(
+            int port,
+            int apiPort,
+            SwapJobConfig swapCfg
+    ) throws IOException {
         File wlgb = folder.newFolder();
         File wlgb = folder.newFolder();
         File config = folder.newFile();
         File config = folder.newFile();
         PrintWriter writer = new PrintWriter(config);
         PrintWriter writer = new PrintWriter(config);
-        writer.println("{\n" +
-            "\t\"port\": " + port + ",\n" +
-            "\t\"rootGitDirectory\": \"" + wlgb.getAbsolutePath() + "\",\n" +
-            "\t\"apiBaseUrl\": \"http://127.0.0.1:" + apiPort + "/api/v0\",\n" +
-            "\t\"username\": \"\",\n" +
-            "\t\"password\": \"\",\n" +
-            "\t\"postbackBaseUrl\": \"http://127.0.0.1:" + port + "\",\n" +
-            "\t\"serviceName\": \"Overleaf\"\n," +
-            "    \"oauth2\": {\n" +
-            "        \"oauth2ClientID\": \"clientID\",\n" +
-            "        \"oauth2ClientSecret\": \"oauth2 client secret\",\n" +
-            "        \"oauth2Server\": \"https://www.overleaf.com\"\n" +
-            "    }\n" +
-            "}\n");
+        String cfgStr =
+                "{\n" +
+                "    \"port\": " + port + ",\n" +
+                "    \"rootGitDirectory\": \"" +
+                        wlgb.getAbsolutePath() +
+                        "\",\n" +
+                "    \"apiBaseUrl\": \"http://127.0.0.1:" +
+                        apiPort +
+                        "/api/v0\",\n" +
+                "    \"username\": \"\",\n" +
+                "    \"password\": \"\",\n" +
+                "    \"postbackBaseUrl\": \"http://127.0.0.1:" +
+                        port +
+                        "\",\n" +
+                "    \"serviceName\": \"Overleaf\",\n" +
+                "    \"oauth2\": {\n" +
+                "        \"oauth2ClientID\": \"clientID\",\n" +
+                "        \"oauth2ClientSecret\": \"oauth2 client secret\",\n" +
+                "        \"oauth2Server\": \"https://www.overleaf.com\"\n" +
+                "    }";
+        if (swapCfg != null) {
+            cfgStr += ",\n" +
+                    "    \"swapStore\": {\n" +
+                    "        \"type\": \"memory\"\n" +
+                    "    },\n" +
+                    "    \"swapJob\": {\n" +
+                    "        \"minProjects\": " +
+                    swapCfg.getMinProjects() +
+                    ",\n" +
+                    "        \"lowGiB\": " +
+                    swapCfg.getLowGiB() +
+                    ",\n" +
+                    "        \"highGiB\": " +
+                    swapCfg.getHighGiB() +
+                    ",\n" +
+                    "        \"intervalMillis\": " +
+                    swapCfg.getIntervalMillis() +
+                    "\n" +
+                    "    }\n";
+        }
+        cfgStr += "}\n";
+        writer.print(cfgStr);
         writer.close();
         writer.close();
         return config.getAbsolutePath();
         return config.getAbsolutePath();
     }
     }
 
 
     private Path getResource(String path) {
     private Path getResource(String path) {
-        return Paths.get("src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest" + path);
+        return Paths.get(
+                "src/test/resources/" +
+                "uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest" + path
+        );
     }
     }
 
 
     private InputStream getResourceAsStream(String path) {
     private InputStream getResourceAsStream(String path) {

+ 27 - 0
services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java

@@ -3,15 +3,25 @@ package uk.ac.ic.wlgitbridge.bridge;
 import org.junit.Before;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.Test;
 import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
 import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
+import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
 import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
 import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
 import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
 import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
 import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache;
 import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache;
 import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotAPI;
 import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotAPI;
 import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJob;
 import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJob;
 import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
 import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
+import uk.ac.ic.wlgitbridge.data.model.Snapshot;
+import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
 
 
+import java.io.IOException;
+import java.util.ArrayDeque;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 
 /**
 /**
  * Created by winston on 20/08/2016.
  * Created by winston on 20/08/2016.
@@ -56,4 +66,21 @@ public class BridgeTest {
         verify(swapJob).stop();
         verify(swapJob).stop();
     }
     }
 
 
+    @Test
+    public void updatingRepositorySetsLastAccessedTime(
+    ) throws IOException, GitUserException {
+        ProjectRepo repo = mock(ProjectRepo.class);
+        when(repo.getProjectName()).thenReturn("asdf");
+        when(dbStore.getProjectState("asdf")).thenReturn(ProjectState.PRESENT);
+        when(
+                snapshotAPI.getSnapshotsForProjectAfterVersion(
+                        any(),
+                        any(),
+                        anyInt()
+                )
+        ).thenReturn(new ArrayDeque<Snapshot>());
+        bridge.updateRepository(null, repo);
+        verify(dbStore).setLastAccessedTime(eq("asdf"), any());
+    }
+
 }
 }

+ 90 - 0
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/state.json

@@ -0,0 +1,90 @@
+[
+	{
+		"project": "testproj1",
+		"getDoc": {
+			"versionID": 1,
+			"createdAt": "2014-11-30T18:40:58.123Z",
+			"email": "jdleesmiller+1@gmail.com",
+			"name": "John+1"
+		},
+		"getSavedVers": [
+        	{
+        		"versionID": 1,
+        		"comment": "added more info on doc GET and error details",
+        		"email": "jdleesmiller+1@gmail.com",
+        		"name": "John+1",
+        		"createdAt": "2014-11-30T18:47:01.456Z"
+        	}
+		],
+		"getForVers": [
+			{
+				"versionID": 1,
+				"srcs": [
+                    {
+                    	"content": "content\n",
+                    	"path": "main.tex"
+                    },
+                    {
+                    	"content": "This text is from another file.",
+                    	"path": "foo/bar/test.tex"
+                    }
+	            ],
+	            "atts": [
+	            	{
+	            		"url": "http://127.0.0.1:3874/state/testproj1/overleaf-white-410.png",
+	            		"path": "overleaf-white-410.png"
+	            	}
+	            ]
+	        }
+		],
+		"push": "success",
+		"postback": {
+			"type": "success",
+			"versionID": 2
+		}
+	},
+	{
+        "project": "testproj2",
+        "getDoc": {
+            "versionID": 1,
+            "createdAt": "2014-11-30T18:40:58.123Z",
+            "email": "jdleesmiller+1@gmail.com",
+            "name": "John+1"
+        },
+        "getSavedVers": [
+            {
+                "versionID": 1,
+                "comment": "added more info on doc GET and error details",
+                "email": "jdleesmiller+1@gmail.com",
+                "name": "John+1",
+                "createdAt": "2014-11-30T18:47:01.456Z"
+            }
+        ],
+        "getForVers": [
+            {
+                "versionID": 1,
+                "srcs": [
+                    {
+                        "content": "different content\n",
+                        "path": "main.tex"
+                    },
+                    {
+                        "content": "a different one",
+                        "path": "foo/bar/test.tex"
+                    }
+                ],
+                "atts": [
+                    {
+                        "url": "http://127.0.0.1:3874/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png",
+                        "path": "editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png"
+                    }
+                ]
+            }
+        ],
+        "push": "success",
+        "postback": {
+            "type": "success",
+            "versionID": 2
+        }
+    }
+]

+ 1 - 0
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/foo/bar/test.tex

@@ -0,0 +1 @@
+This text is from another file.

+ 1 - 0
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/main.tex

@@ -0,0 +1 @@
+content

BIN
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj1/overleaf-white-410.png


BIN
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png


+ 1 - 0
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/foo/bar/test.tex

@@ -0,0 +1 @@
+a different one

+ 1 - 0
services/git-bridge/src/test/resources/uk/ac/ic/wlgitbridge/WLGitBridgeIntegrationTest/wlgbCanSwapProjects/state/testproj2/main.tex

@@ -0,0 +1 @@
+different content