]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6366 split ruby upgradeAndStart into three Java steps
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 28 Apr 2015 13:31:07 +0000 (15:31 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 5 May 2015 07:18:54 +0000 (09:18 +0200)
modified ruby scripts used by RubyBridge to define and instance a class instead of only define a method alone because mapping such script to a Java interface works only for the first script (at least in unit tests)
split upgrade_and_start from Ruby into two seperate Ruby tasks (trigger ActiveRecord migration on one side and web route (re)creation on the other) and a pure Java task to restart the container

15 files changed:
server/sonar-server/src/main/java/org/sonar/server/db/migrations/PlatformDatabaseMigration.java
server/sonar-server/src/main/java/org/sonar/server/ruby/CallDatabaseVersionUpgrade.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ruby/CallLoadJavaWebServices.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ruby/PlatformRubyBridge.java
server/sonar-server/src/main/java/org/sonar/server/ruby/RubyBridge.java
server/sonar-server/src/main/java/org/sonar/server/ruby/RubyRailsRoutes.java [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/ruby/call_databaseversion_upgrade.rb [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/ruby/call_load_java_web_services.rb [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/ruby/call_upgrade_and_start.rb [deleted file]
server/sonar-server/src/test/java/org/sonar/server/db/migrations/PlatformDatabaseMigrationAsynchronousTest.java
server/sonar-server/src/test/java/org/sonar/server/db/migrations/PlatformDatabaseMigrationConcurrentAccessTest.java
server/sonar-server/src/test/java/org/sonar/server/db/migrations/PlatformDatabaseMigrationTest.java
server/sonar-server/src/test/java/org/sonar/server/ruby/PlatformRubyBridgeTest.java
server/sonar-server/src/test/resources/org/sonar/server/ruby/database_version.rb
server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb

index f7fc0ad20608deff13df25b4696a57afd1ef5bb7..a983979c1244c9b1f8f41c04994d0df15788ce72 100644 (file)
  */
 package org.sonar.server.db.migrations;
 
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.ruby.RubyBridge;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
 import java.util.Date;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantLock;
 
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
+import org.sonar.server.platform.Platform;
+import org.sonar.server.ruby.RubyBridge;
+
 /**
  * Handles concurrency to make sure only one DB migration can run at a time.
  */
@@ -41,6 +44,7 @@ public class PlatformDatabaseMigration implements DatabaseMigration {
    * ExecutorService implements threads management.
    */
   private final PlatformDatabaseMigrationExecutorService executorService;
+  private final Platform platform;
   /**
    * This lock implements thread safety from concurrent calls of method {@link #startIt()}
    */
@@ -60,9 +64,10 @@ public class PlatformDatabaseMigration implements DatabaseMigration {
   @Nullable
   private Throwable failureError;
 
-  public PlatformDatabaseMigration(RubyBridge rubyBridge, PlatformDatabaseMigrationExecutorService executorService) {
+  public PlatformDatabaseMigration(RubyBridge rubyBridge, PlatformDatabaseMigrationExecutorService executorService, Platform platform) {
     this.rubyBridge = rubyBridge;
     this.executorService = executorService;
+    this.platform = platform;
   }
 
   @Override
@@ -96,19 +101,46 @@ public class PlatformDatabaseMigration implements DatabaseMigration {
         status = Status.RUNNING;
         startDate = new Date();
         failureError = null;
+        Profiler profiler = Profiler.create(LOGGER);
         try {
-          LOGGER.info("Starting DB Migration at {}", startDate);
-          rubyBridge.databaseMigration().trigger();
-          LOGGER.info("DB Migration ended successfully at {}", new Date());
+          profiler.startInfo("Starting DB Migration");
+          upgradeDb();
+          restartContainer();
+          recreateWebRoutes();
           status = Status.SUCCEEDED;
+          profiler.stopInfo("DB Migration ended successfully");
         } catch (Throwable t) {
-          LOGGER.error("DB Migration failed and ended at " + startDate + " with an exception", t);
+          profiler.stopInfo("DB migration failed");
+          LOGGER.error(
+            "DB Migration or container restart failed. Process ended with an exception", t
+            );
           status = Status.FAILED;
           failureError = t;
         } finally {
           running.getAndSet(false);
         }
       }
+
+      private void upgradeDb() {
+        Profiler profiler = Profiler.createIfTrace(LOGGER);
+        profiler.startTrace("Starting DB Migration");
+        rubyBridge.databaseMigration().trigger();
+        profiler.stopTrace("DB Migration ended");
+      }
+
+      private void restartContainer() {
+        Profiler profiler = Profiler.createIfTrace(LOGGER);
+        profiler.startTrace("Restarting container");
+        platform.doStart();
+        profiler.stopTrace("Container restarted successfully");
+      }
+
+      private void recreateWebRoutes() {
+        Profiler profiler = Profiler.createIfTrace(LOGGER);
+        profiler.startTrace("Recreating web routes");
+        rubyBridge.railsRoutes().recreate();
+        profiler.startTrace("Routes recreated successfully");
+      }
     });
   }
 
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ruby/CallDatabaseVersionUpgrade.java b/server/sonar-server/src/main/java/org/sonar/server/ruby/CallDatabaseVersionUpgrade.java
new file mode 100644 (file)
index 0000000..1212291
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ruby;
+
+/**
+ * Interface which must be top-level public class to be used by the Ruby engine but that hides name of the Ruby method
+ * in the Ruby script from the rest of the platform (only {@link RubyDatabaseMigration} is known to the platform).
+ */
+public interface CallDatabaseVersionUpgrade {
+
+  /**
+   * Java method that calls the upgrade_and_start method defined in the {@code call_databaseversion_upgrade.rb} script.
+   */
+  void callUpgrade();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ruby/CallLoadJavaWebServices.java b/server/sonar-server/src/main/java/org/sonar/server/ruby/CallLoadJavaWebServices.java
new file mode 100644 (file)
index 0000000..1b5fbe2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ruby;
+
+/**
+ * Interface which must be a top-level public class to be used by the Ruby engine but that hides name of the Ruby
+ * method in the Ruby script from the rest of the platform (only {@link RubyRailsRoutes} is known to the platform).
+ */
+public interface CallLoadJavaWebServices {
+  /**
+   * Java method that calls the call_upgrade_and_start method defined in the {@code call_load_java_web_services.rb} script.
+   */
+  void callLoadJavaWebServices();
+}
index 9c970319148e1876ea0d25393be7c03281ff46ee..3ac71e4f0135a50527ac02d23b7c6459ff1a6f9f 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.server.ruby;
 
+import java.io.IOException;
+import java.io.InputStream;
+import javax.annotation.Nullable;
 import org.jruby.Ruby;
 import org.jruby.RubyNil;
 import org.jruby.RubyRuntimeAdapter;
@@ -27,11 +30,9 @@ import org.jruby.javasupport.JavaEmbedUtils;
 import org.jruby.javasupport.JavaUtil;
 import org.jruby.runtime.builtin.IRubyObject;
 
-import java.io.IOException;
-import java.io.InputStream;
-
 public class PlatformRubyBridge implements RubyBridge {
-  private static final String CALL_UPGRADE_AND_START_RB_FILENAME = "call_upgrade_and_start.rb";
+  private static final String CALL_UPGRADE_AND_START_RB_FILENAME = "call_databaseversion_upgrade.rb";
+  private static final String CALL_LOAD_JAVA_WEB_SERVICES_RB_FILENAME = "call_load_java_web_services.rb";
 
   private final RackBridge rackBridge;
   private final RubyRuntimeAdapter adapter = JavaEmbedUtils.newRuntimeAdapter();
@@ -42,14 +43,28 @@ public class PlatformRubyBridge implements RubyBridge {
 
   @Override
   public RubyDatabaseMigration databaseMigration() {
-    final CallUpgradeAndStart callUpgradeAndStart = parseMethodScriptToInterface(
-      CALL_UPGRADE_AND_START_RB_FILENAME, CallUpgradeAndStart.class
+    final CallDatabaseVersionUpgrade callDatabaseVersionUpgrade = parseMethodScriptToInterface(
+      CALL_UPGRADE_AND_START_RB_FILENAME, CallDatabaseVersionUpgrade.class
       );
 
     return new RubyDatabaseMigration() {
       @Override
       public void trigger() {
-        callUpgradeAndStart.callUpgradeAndStart();
+        callDatabaseVersionUpgrade.callUpgrade();
+      }
+    };
+  }
+
+  @Override
+  public RubyRailsRoutes railsRoutes() {
+    final CallLoadJavaWebServices callLoadJavaWebServices = parseMethodScriptToInterface(
+      CALL_LOAD_JAVA_WEB_SERVICES_RB_FILENAME, CallLoadJavaWebServices.class
+      );
+
+    return new RubyRailsRoutes() {
+      @Override
+      public void recreate() {
+        callLoadJavaWebServices.callLoadJavaWebServices();
       }
     };
   }
@@ -61,7 +76,7 @@ public class PlatformRubyBridge implements RubyBridge {
   private <T> T parseMethodScriptToInterface(String fileName, Class<T> clazz) {
     try (InputStream in = getClass().getResourceAsStream(fileName)) {
       Ruby rubyRuntime = rackBridge.getRubyRuntime();
-      JavaEmbedUtils.EvalUnit evalUnit = adapter.parse(rubyRuntime, in, fileName, 0);
+      JavaEmbedUtils.EvalUnit evalUnit = JavaEmbedUtils.newRuntimeAdapter().parse(rubyRuntime, in, fileName, 0);
       IRubyObject rubyObject = evalUnit.run();
       Object receiver = JavaEmbedUtils.rubyToJava(rubyObject);
       T wrapper = getInstance(rubyRuntime, receiver, clazz);
@@ -75,7 +90,7 @@ public class PlatformRubyBridge implements RubyBridge {
    * Fork of method {@link org.jruby.embed.internal.EmbedRubyInterfaceAdapterImpl#getInstance(Object, Class)}
    */
   @SuppressWarnings("unchecked")
-  public <T> T getInstance(Ruby runtime, Object receiver, Class<T> clazz) {
+  public <T> T getInstance(Ruby runtime, @Nullable Object receiver, @Nullable Class<T> clazz) {
     if (clazz == null || !clazz.isInterface()) {
       return null;
     }
@@ -97,15 +112,4 @@ public class PlatformRubyBridge implements RubyBridge {
     }
   }
 
-  /**
-   * Interface which must be public to be used by the Ruby engine but that hides name of the Ruby method in the Ruby
-   * script from the rest of the platform (only {@link RubyDatabaseMigration} is known to the platform).
-   */
-  public interface CallUpgradeAndStart {
-
-    /**
-     * Java method that calls the upgrade_and_start method defined in the {@code call_upgrade_and_start.rb} script.
-     */
-    void callUpgradeAndStart();
-  }
 }
index 1861263d51639483771f4b81275bad9420780219..36e893d770e46b6730b1a5819166d811267e5568 100644 (file)
@@ -30,4 +30,11 @@ public interface RubyBridge {
    * @return a  {@link RubyDatabaseMigration}
    */
   RubyDatabaseMigration databaseMigration();
+
+  /**
+   * Returns a class that allows calling the (re)creation of web routes in Rails.
+   *
+   * @return a {@link RubyRailsRoutes}
+   */
+  RubyRailsRoutes railsRoutes();
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ruby/RubyRailsRoutes.java b/server/sonar-server/src/main/java/org/sonar/server/ruby/RubyRailsRoutes.java
new file mode 100644 (file)
index 0000000..c5298cb
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.server.ruby;
+
+public interface RubyRailsRoutes {
+  /**
+   * Triggers the (re)creation of web route in Ruby On Rails.
+   * <strong>This is not thread safe!</strong>
+   */
+  void recreate();
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ruby/call_databaseversion_upgrade.rb b/server/sonar-server/src/main/resources/org/sonar/server/ruby/call_databaseversion_upgrade.rb
new file mode 100644 (file)
index 0000000..b53c60d
--- /dev/null
@@ -0,0 +1,12 @@
+# this script defines a method which calls the class method "upgrade" of the DatabaseVersion class defined
+# in /server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb
+
+require 'database_version'
+
+class RbCallUpgrade
+  include Java::org.sonar.server.ruby.CallDatabaseVersionUpgrade
+  def call_upgrade
+    DatabaseVersion.upgrade
+  end
+end
+RbCallUpgrade.new
\ No newline at end of file
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ruby/call_load_java_web_services.rb b/server/sonar-server/src/main/resources/org/sonar/server/ruby/call_load_java_web_services.rb
new file mode 100644 (file)
index 0000000..7623e05
--- /dev/null
@@ -0,0 +1,12 @@
+# this script defines a method which calls the class method "load_java_web_services" of the DatabaseVersion class
+# definedin /server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb
+
+require 'database_version'
+
+class RbCallLoadJavaWebServices
+  include Java::org.sonar.server.ruby.CallLoadJavaWebServices
+  def call_load_java_web_services
+    DatabaseVersion.load_java_web_services
+  end
+end
+RbCallLoadJavaWebServices.new
\ No newline at end of file
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ruby/call_upgrade_and_start.rb b/server/sonar-server/src/main/resources/org/sonar/server/ruby/call_upgrade_and_start.rb
deleted file mode 100644 (file)
index 5359ff1..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# this script defines a method which calls the class method "upgrade_and_start" of the DatabaseVersion class defined
-# in /server/sonar-web/src/main/webapp/WEB-INF/lib/database_version.rb
-
-require 'database_version'
-
-def call_upgrade_and_start
-  DatabaseVersion.upgrade_and_start
-end
\ No newline at end of file
index 1eb35d1873bdba5119304fa56595d671d546a934..978174fd191848dfef3cf5a1e348688d596eb131 100644 (file)
 package org.sonar.server.db.migrations;
 
 import com.google.common.base.Throwables;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import org.junit.After;
-import org.junit.Before;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.sonar.server.platform.Platform;
 import org.sonar.server.ruby.RubyBridge;
 import org.sonar.server.ruby.RubyDatabaseMigration;
 
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+import static org.mockito.Mockito.mock;
 
 public class PlatformDatabaseMigrationAsynchronousTest {
 
@@ -54,17 +53,10 @@ public class PlatformDatabaseMigrationAsynchronousTest {
       });
     }
   };
-  @Mock
-  private RubyDatabaseMigration rubyDatabaseMigration;
-  @Mock
-  private RubyBridge rubyBridge;
-  private PlatformDatabaseMigration underTest;
-
-  @Before
-  public void setUp() throws Exception {
-    MockitoAnnotations.initMocks(this);
-    underTest = new PlatformDatabaseMigration(rubyBridge, executorService);
-  }
+  private RubyDatabaseMigration rubyDatabaseMigration = mock(RubyDatabaseMigration.class);
+  private RubyBridge rubyBridge = mock(RubyBridge.class);
+  private Platform platform = mock(Platform.class);
+  private PlatformDatabaseMigration underTest = new PlatformDatabaseMigration(rubyBridge, executorService, platform);
 
   @After
   public void tearDown() throws Exception {
index d7d212b3c52255fb418d7caf2ceb36436419d296..b4b9c767484c496e1888f4cd9809688d3f200e4b 100644 (file)
@@ -27,8 +27,10 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.junit.After;
 import org.junit.Test;
+import org.sonar.server.platform.Platform;
 import org.sonar.server.ruby.RubyBridge;
 import org.sonar.server.ruby.RubyDatabaseMigration;
+import org.sonar.server.ruby.RubyRailsRoutes;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -71,7 +73,9 @@ public class PlatformDatabaseMigrationConcurrentAccessTest {
     }
   };
   private RubyBridge rubyBridge = mock(RubyBridge.class);
-  private PlatformDatabaseMigration underTest = new PlatformDatabaseMigration(rubyBridge, executorService);
+  private Platform platform = mock(Platform.class);
+  private RubyRailsRoutes railsRoutes = mock(RubyRailsRoutes.class);
+  private PlatformDatabaseMigration underTest = new PlatformDatabaseMigration(rubyBridge, executorService, platform);
 
   @After
   public void tearDown() throws Exception {
@@ -81,6 +85,7 @@ public class PlatformDatabaseMigrationConcurrentAccessTest {
   @Test
   public void two_concurrent_calls_to_startit_call_trigger_only_once() throws Exception {
     when(rubyBridge.databaseMigration()).thenReturn(rubyDatabaseMigration);
+    when(rubyBridge.railsRoutes()).thenReturn(railsRoutes);
 
     pool.submit(new CallStartit());
     pool.submit(new CallStartit());
index 7000c36f84157005a03f5e87f4d8205c5725b181..2d98d836989172cae086939a9f689a3d107514f8 100644 (file)
  */
 package org.sonar.server.db.migrations;
 
-import org.junit.Before;
+import java.util.Date;
 import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.InOrder;
+import org.sonar.server.platform.Platform;
 import org.sonar.server.ruby.RubyBridge;
 import org.sonar.server.ruby.RubyDatabaseMigration;
-
-import java.util.Date;
+import org.sonar.server.ruby.RubyRailsRoutes;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 /**
  * Unit test for PlatformDatabaseMigration which does not test any of its concurrency management and asynchronous execution code.
  */
 public class PlatformDatabaseMigrationTest {
-  private static final Throwable AN_ERROR = new RuntimeException();
+  private static final Throwable AN_ERROR = new RuntimeException("runtime exception created on purpose");
 
   /**
    * Implementation of execute runs Runnable synchronously.
@@ -49,17 +49,13 @@ public class PlatformDatabaseMigrationTest {
       command.run();
     }
   };
-  @Mock
-  private RubyDatabaseMigration rubyDatabaseMigration;
-  @Mock
-  private RubyBridge rubyBridge;
-  private PlatformDatabaseMigration underTest;
-
-  @Before
-  public void setUp() throws Exception {
-    MockitoAnnotations.initMocks(this);
-    underTest = new PlatformDatabaseMigration(rubyBridge, executorService);
-  }
+  private RubyBridge rubyBridge = mock(RubyBridge.class);
+  private RubyDatabaseMigration rubyDatabaseMigration = mock(RubyDatabaseMigration.class);
+  private RubyRailsRoutes rubyRailsRoutes = mock(RubyRailsRoutes.class);
+  private Platform platform = mock(Platform.class);
+  private InOrder inOrder = inOrder(rubyDatabaseMigration, rubyBridge, rubyRailsRoutes, platform);
+
+  private PlatformDatabaseMigration underTest = new PlatformDatabaseMigration(rubyBridge, executorService, platform);
 
   @Test
   public void status_is_NONE_when_component_is_created() throws Exception {
@@ -79,16 +75,22 @@ public class PlatformDatabaseMigrationTest {
   @Test
   public void startit_calls_databasemigration_trigger_in_a_separate_thread() throws Exception {
     when(rubyBridge.databaseMigration()).thenReturn(rubyDatabaseMigration);
+    when(rubyBridge.railsRoutes()).thenReturn(rubyRailsRoutes);
 
     underTest.startIt();
 
-    verify(rubyBridge).databaseMigration();
-    verify(rubyDatabaseMigration).trigger();
+    inOrder.verify(rubyBridge).databaseMigration();
+    inOrder.verify(rubyDatabaseMigration).trigger();
+    inOrder.verify(platform).doStart();
+    inOrder.verify(rubyBridge).railsRoutes();
+    inOrder.verify(rubyRailsRoutes).recreate();
+    inOrder.verifyNoMoreInteractions();
   }
 
   @Test
   public void status_is_SUCCEEDED_and_failure_is_null_when_trigger_runs_without_an_exception() throws Exception {
     when(rubyBridge.databaseMigration()).thenReturn(rubyDatabaseMigration);
+    when(rubyBridge.railsRoutes()).thenReturn(rubyRailsRoutes);
 
     underTest.startIt();
 
@@ -131,10 +133,12 @@ public class PlatformDatabaseMigrationTest {
   private void mockTriggerThrowsError() {
     when(rubyBridge.databaseMigration()).thenReturn(rubyDatabaseMigration);
     doThrow(AN_ERROR).when(rubyDatabaseMigration).trigger();
+    when(rubyBridge.railsRoutes()).thenReturn(rubyRailsRoutes);
   }
 
   private void mockTriggerDoesNothing() {
     when(rubyBridge.databaseMigration()).thenReturn(rubyDatabaseMigration);
     doNothing().when(rubyDatabaseMigration).trigger();
+    when(rubyBridge.railsRoutes()).thenReturn(rubyRailsRoutes);
   }
 }
index 527f48fc104bcb8044bf5bc9334be1520e3859ab..56729daec6f5b0dfd33d78035442d65d0b88824b 100644 (file)
 package org.sonar.server.ruby;
 
 import com.google.common.collect.ImmutableList;
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
 import org.jruby.embed.LocalContextScope;
 import org.jruby.embed.ScriptingContainer;
 import org.jruby.exceptions.RaiseException;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.io.File;
-import java.net.URISyntaxException;
-import java.net.URL;
-
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -51,7 +50,7 @@ public class PlatformRubyBridgeTest {
    */
   private static ScriptingContainer setupScriptingContainer() {
     try {
-      ScriptingContainer container = new ScriptingContainer(LocalContextScope.CONCURRENT);
+      ScriptingContainer container = new ScriptingContainer(LocalContextScope.THREADSAFE);
       URL resource = PlatformRubyBridge.class.getResource("database_version.rb");
       String dirPath = new File(resource.toURI()).getParentFile().getPath();
       container.setLoadPaths(ImmutableList.of(dirPath));
@@ -75,4 +74,18 @@ public class PlatformRubyBridgeTest {
     }
   }
 
+  /**
+   * unit test only makes sure the wrapping and method forwarding provided by JRuby works so building the
+   * RubyRailsRoutes object and calling its trigger method is enough as it would otherwise raise an exception
+   */
+  @Test
+  public void testRailsRoutes() {
+    try {
+      underTest.railsRoutes().recreate();
+    } catch (RaiseException e) {
+      e.printStackTrace();
+      throw new RuntimeException("Loading error with container loadPath " + container.getLoadPaths(), e);
+    }
+  }
+
 }
index e1cc2ca163d787a5e96c6f6d73f605c826a5dab1..46797b911dcfb3a03d813d44d98af7fe09351860 100644 (file)
@@ -3,7 +3,11 @@
 # it would otherwise raise an exception
 class DatabaseVersion
 
-  def self.upgrade_and_start
+  def self.upgrade
+
+  end
+
+  def self.load_java_web_services
 
   end
 
index 9473dfe33566a35a15d8c6c29ab420600f687bc0..b1e7da54f355249562ce3dcf4fe6c160e7e4b3e9 100644 (file)
@@ -58,6 +58,10 @@ class DatabaseVersion
     $uptodate
   end
 
+  def self.upgrade
+    ActiveRecord::Migrator.migrate(migrations_path)
+  end
+
   def self.upgrade_and_start
     ActiveRecord::Migrator.migrate(migrations_path)
     Java::OrgSonarServerPlatform::Platform.getInstance().doStart()