Merge branch 'master' into 4638-ssh-notification
[arvados.git] / services / api / app / controllers / database_controller.rb
index 91d98e50f915b48e7c8f4ed43b6641d6015ce29a..831451435ef9f9adb47d974cdb91697f9db43f71 100644 (file)
@@ -5,30 +5,56 @@ class DatabaseController < ApplicationController
   def reset
     raise ArvadosModel::PermissionDeniedError unless Rails.env == 'test'
 
+    # Sanity check: If someone has actually logged in here, this might
+    # not really be a throwaway database. Client test suites should
+    # use @example.com email addresses when creating user records, so
+    # we can tell they're not valuable.
+    user_uuids = User.
+      where('email is null or email not like ?', '%@example.com').
+      collect &:uuid
+    fixture_uuids =
+      YAML::load_file(File.expand_path('../../../test/fixtures/users.yml',
+                                       __FILE__)).
+      values.collect { |u| u['uuid'] }
+    unexpected_uuids = user_uuids - fixture_uuids
+    if unexpected_uuids.any?
+      logger.error("Running in test environment, but non-fixture users exist: " +
+                   "#{unexpected_uuids}")
+      raise ArvadosModel::PermissionDeniedError
+    end
+
     require 'active_record/fixtures'
 
     # What kinds of fixtures do we have?
     fixturesets = Dir.glob(Rails.root.join('test', 'fixtures', '*.yml')).
       collect { |yml| yml.match(/([^\/]*)\.yml$/)[1] }
 
-    # Delete existing fixtures (and everything else) from fixture
-    # tables
-    fixturesets.each do |x|
-      x.classify.constantize.unscoped.delete_all
-    end
+    ActiveRecord::Base.transaction do
+      # Avoid deadlock by locking all tables before doing anything
+      # drastic.
+      table_names = '"' + fixturesets.sort.join('","') + '"'
+      ActiveRecord::Base.connection.execute \
+      "LOCK TABLE #{table_names} IN ACCESS EXCLUSIVE MODE"
 
-    # create_fixtures() is a no-op for cached fixture sets, so uncache
-    # them all.
-    ActiveRecord::Fixtures.reset_cache
-    ActiveRecord::Fixtures.
-      create_fixtures(Rails.root.join('test', 'fixtures'), fixturesets)
+      # Delete existing fixtures (and everything else) from fixture
+      # tables
+      fixturesets.each do |x|
+        x.classify.constantize.unscoped.delete_all
+      end
 
-    # Dump cache of permissions etc.
-    Rails.cache.clear
-    ActiveRecord::Base.connection.clear_query_cache
+      # create_fixtures() is a no-op for cached fixture sets, so
+      # uncache them all.
+      ActiveRecord::Fixtures.reset_cache
+      ActiveRecord::Fixtures.
+        create_fixtures(Rails.root.join('test', 'fixtures'), fixturesets)
 
-    # Reload database seeds
-    DatabaseSeeds.install
+      # Dump cache of permissions etc.
+      Rails.cache.clear
+      ActiveRecord::Base.connection.clear_query_cache
+
+      # Reload database seeds
+      DatabaseSeeds.install
+    end
 
     # Done.
     render json: {success: true}