From 772560bdd9611c15fa6975d2be132f176949b1bc Mon Sep 17 00:00:00 2001
From: Robert Scott <code@humanleg.org.uk>
Date: Sun, 7 Jan 2018 22:10:28 +0000
Subject: [PATCH v1 2/4] JOSMTestRules: add assumeRevision method to allow
 JOSM's apparent version to be mocked

---
 .../josm/testutils/JOSMTestRules.java              | 39 ++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java b/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java
index cec968231..8cf19f9aa 100644
--- a/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java
+++ b/test/unit/org/openstreetmap/josm/testutils/JOSMTestRules.java
@@ -2,6 +2,7 @@
 package org.openstreetmap.josm.testutils;
 
 import java.awt.Color;
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.security.GeneralSecurityException;
@@ -15,6 +16,7 @@ import org.junit.runners.model.InitializationError;
 import org.junit.runners.model.Statement;
 import org.openstreetmap.josm.JOSMFixture;
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.TestUtils;
 import org.openstreetmap.josm.actions.DeleteAction;
 import org.openstreetmap.josm.command.DeleteCommand;
 import org.openstreetmap.josm.data.UserIdentityManager;
@@ -22,6 +24,7 @@ import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
 import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
 import org.openstreetmap.josm.data.projection.Projections;
+import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
 import org.openstreetmap.josm.gui.oauth.OAuthAuthorizationWizard;
@@ -58,6 +61,8 @@ public class JOSMTestRules implements TestRule {
     private APIType useAPI = APIType.NONE;
     private String i18n = null;
     private TileSourceRule tileSourceRule;
+    private String assumeRevisionString;
+    private Version originalVersion;
     private boolean platform;
     private boolean useProjection;
     private boolean useProjectionNadGrids;
@@ -136,6 +141,17 @@ public class JOSMTestRules implements TestRule {
     }
 
     /**
+     * Mock this test's assumed JOSM version (as reported by
+     * {@link Version}).
+     * @param revisionProperties mock contents of JOSM's {@code REVISION} properties file
+     * @return this instance, for easy chaining
+     */
+    public JOSMTestRules assumeRevision(final String revisionProperties) {
+        this.assumeRevisionString = revisionProperties;
+        return this;
+    }
+
+    /**
      * Enable the dev.openstreetmap.org API for this test.
      * @return this instance, for easy chaining
      */
@@ -286,6 +302,14 @@ public class JOSMTestRules implements TestRule {
         return this;
     }
 
+    private static class MockVersion extends Version {
+        public MockVersion(final String propertiesString) {
+            super.initFromRevisionInfo(
+                new ByteArrayInputStream(propertiesString.getBytes())
+            );
+        }
+    }
+
     @Override
     public Statement apply(Statement base, Description description) {
         Statement statement = base;
@@ -318,12 +342,18 @@ public class JOSMTestRules implements TestRule {
      * Set up before running a test
      * @throws InitializationError If an error occured while creating the required environment.
      */
-    protected void before() throws InitializationError {
+    protected void before() throws InitializationError, ReflectiveOperationException {
         // Tests are running headless by default.
         System.setProperty("java.awt.headless", "true");
 
         cleanUpFromJosmFixture();
 
+        if (this.assumeRevisionString != null) {
+            this.originalVersion = Version.getInstance();
+            final Version replacementVersion = new MockVersion(this.assumeRevisionString);
+            TestUtils.setPrivateStaticField(Version.class, "instance", replacementVersion);
+        }
+
         Config.setPreferencesInstance(Main.pref);
         Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance());
         // All tests use the same timezone.
@@ -466,7 +496,7 @@ public class JOSMTestRules implements TestRule {
      * Clean up after running a test
      */
     @SuppressFBWarnings("DM_GC")
-    protected void after() {
+    protected void after() throws ReflectiveOperationException {
         // Sync AWT Thread
         GuiHelper.runInEDTAndWait(new Runnable() {
             @Override
@@ -480,6 +510,11 @@ public class JOSMTestRules implements TestRule {
         // TODO: Remove global listeners and other global state.
         Main.pref.resetToInitialState();
         Main.platform = null;
+
+        if (this.assumeRevisionString != null && this.originalVersion != null) {
+            TestUtils.setPrivateStaticField(Version.class, "instance", this.originalVersion);
+        }
+
         // Parts of JOSM uses weak references - destroy them.
         System.gc();
     }
-- 
2.11.0

