diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efdd5e8..fb85675 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,4 +78,4 @@ jobs: BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile DATABASE_URL: ${{ matrix.adapter }} WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }} - run: bundle exec rake + run: bin/rails db:reset test diff --git a/.gitignore b/.gitignore index d4f7e62..1d0f4a4 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ test/version_tmp tmp *.iml test/sqlite.db -.env \ No newline at end of file +.env +/test/dummy/log/ diff --git a/Gemfile b/Gemfile index fa75df1..7e29b04 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,8 @@ source 'https://rubygems.org' gemspec + +gem 'railties' + +gem 'pg' +gem 'sqlite3' \ No newline at end of file diff --git a/Rakefile b/Rakefile index f791690..79e247e 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,8 @@ YARD::Rake::YardocTask.new do |t| t.files = ['lib/**/*.rb', 'README.md'] end +APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__) +load APP_RAKEFILE require 'rake/testtask' Rake::TestTask.new do |t| diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000..6223410 --- /dev/null +++ b/bin/rails @@ -0,0 +1,13 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails gems +# installed from the root of your application. + +ENGINE_ROOT = File.expand_path("..", __dir__) +APP_PATH = File.expand_path("../test/dummy/config/application", __dir__) +ENV["RAILS_ENV"] ||= "test" +# Set up gems listed in the Gemfile. +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) +require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) + +require "rails/all" +require "rails/engine/commands" diff --git a/gemfiles/activerecord_6.1.gemfile b/gemfiles/activerecord_6.1.gemfile index b87ebba..1d10fc7 100644 --- a/gemfiles/activerecord_6.1.gemfile +++ b/gemfiles/activerecord_6.1.gemfile @@ -2,6 +2,9 @@ source "https://rubygems.org" +gem "railties" +gem "pg" +gem "sqlite3" gem "activerecord", "~> 6.1.0" platforms :ruby do diff --git a/gemfiles/activerecord_7.0.gemfile b/gemfiles/activerecord_7.0.gemfile index 3ef6b18..bc2bb97 100644 --- a/gemfiles/activerecord_7.0.gemfile +++ b/gemfiles/activerecord_7.0.gemfile @@ -2,6 +2,9 @@ source "https://rubygems.org" +gem "railties" +gem "pg" +gem "sqlite3" gem "activerecord", "~> 7.0.0" platforms :ruby do diff --git a/gemfiles/activerecord_7.1.gemfile b/gemfiles/activerecord_7.1.gemfile index a9455ae..0c67dcf 100644 --- a/gemfiles/activerecord_7.1.gemfile +++ b/gemfiles/activerecord_7.1.gemfile @@ -2,6 +2,9 @@ source "https://rubygems.org" +gem "railties" +gem "pg" +gem "sqlite3" gem "activerecord", "~> 7.1.0" platforms :ruby do diff --git a/lib/with_advisory_lock/database_adapter_support.rb b/lib/with_advisory_lock/database_adapter_support.rb index 640c9bc..1ef8f0f 100644 --- a/lib/with_advisory_lock/database_adapter_support.rb +++ b/lib/with_advisory_lock/database_adapter_support.rb @@ -20,7 +20,7 @@ def postgresql? end def sqlite? - @sym_name == :sqlite3 + [:sqlite3, :sqlite].include? @sym_name end end end diff --git a/test/dummy/Rakefile b/test/dummy/Rakefile new file mode 100644 index 0000000..6d1041e --- /dev/null +++ b/test/dummy/Rakefile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +require_relative 'config/application' + +Rails.application.load_tasks diff --git a/test/dummy/app/models/application_record.rb b/test/dummy/app/models/application_record.rb new file mode 100644 index 0000000..71fbba5 --- /dev/null +++ b/test/dummy/app/models/application_record.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/test/dummy/app/models/concerns/.keep b/test/dummy/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/dummy/app/models/label.rb b/test/dummy/app/models/label.rb new file mode 100644 index 0000000..dc5ac22 --- /dev/null +++ b/test/dummy/app/models/label.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class Label < ApplicationRecord +end diff --git a/test/dummy/app/models/tag.rb b/test/dummy/app/models/tag.rb new file mode 100644 index 0000000..a58b419 --- /dev/null +++ b/test/dummy/app/models/tag.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class Tag < ApplicationRecord + after_save do + TagAudit.create(tag_name: name) + Label.create(name: name) + end +end diff --git a/test/dummy/app/models/tag_audit.rb b/test/dummy/app/models/tag_audit.rb new file mode 100644 index 0000000..46bc1b3 --- /dev/null +++ b/test/dummy/app/models/tag_audit.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +class TagAudit < ApplicationRecord +end diff --git a/test/dummy/bin/rails b/test/dummy/bin/rails new file mode 100755 index 0000000..a31728a --- /dev/null +++ b/test/dummy/bin/rails @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/test/dummy/bin/rake b/test/dummy/bin/rake new file mode 100755 index 0000000..c199955 --- /dev/null +++ b/test/dummy/bin/rake @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/test/dummy/bin/setup b/test/dummy/bin/setup new file mode 100755 index 0000000..3a74034 --- /dev/null +++ b/test/dummy/bin/setup @@ -0,0 +1,35 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'fileutils' + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args, exception: true) +end + +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:prepare' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/test/dummy/config.ru b/test/dummy/config.ru new file mode 100644 index 0000000..5df2ee2 --- /dev/null +++ b/test/dummy/config.ru @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +require_relative 'config/environment' + +run Rails.application +Rails.application.load_server diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb new file mode 100644 index 0000000..fe4c3e0 --- /dev/null +++ b/test/dummy/config/application.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require_relative 'boot' + +require 'rails' +require 'active_record/railtie' +Bundler.require(*Rails.groups) +require 'with_advisory_lock' + +module Dummy + class Application < Rails::Application + config.load_defaults Rails::VERSION::STRING.to_f + end +end diff --git a/test/dummy/config/boot.rb b/test/dummy/config/boot.rb new file mode 100644 index 0000000..6d2cba0 --- /dev/null +++ b/test/dummy/config/boot.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Set up gems listed in the Gemfile. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) + +require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) diff --git a/test/dummy/config/database.yml b/test/dummy/config/database.yml new file mode 100644 index 0000000..6534a94 --- /dev/null +++ b/test/dummy/config/database.yml @@ -0,0 +1,4 @@ +test: + url: <%= ENV.fetch('DATABASE_URL', "sqlite3://#{Dir.tmpdir}/with_advisory_lock-#{Rails.gem_version}-#{RUBY_VERSION}.sqlite3") %> + properties: + allowPublicKeyRetrieval: true \ No newline at end of file diff --git a/test/dummy/config/environment.rb b/test/dummy/config/environment.rb new file mode 100644 index 0000000..d5abe55 --- /dev/null +++ b/test/dummy/config/environment.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/test/dummy/config/environments/test.rb b/test/dummy/config/environments/test.rb new file mode 100644 index 0000000..788f8d4 --- /dev/null +++ b/test/dummy/config/environments/test.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'active_support/core_ext/integer/time' + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # While tests run files are not watched, reloading is not necessary. + config.enable_reloading = false + + # Eager loading loads your entire application. When running a single test locally, + # this is usually not necessary, and can slow down your test suite. However, it's + # recommended that you enable it in continuous integration systems to ensure eager + # loading is working properly before deploying your code. + config.eager_load = ENV['CI'].present? + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + config.cache_store = :null_store + + # Render exception templates for rescuable exceptions and raise for other exceptions. + config.action_dispatch.show_exceptions = :rescuable + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] +end diff --git a/test/dummy/db/migrate/0_initial_schema.rb b/test/dummy/db/migrate/0_initial_schema.rb new file mode 100644 index 0000000..8c7994b --- /dev/null +++ b/test/dummy/db/migrate/0_initial_schema.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class InitialSchema < ActiveRecord::Migration[6.1] + create_table 'tags' do |t| + t.string 'name' + end + create_table 'tag_audits', id: false do |t| + t.string 'tag_name' + end + create_table 'labels', id: false do |t| + t.string 'name' + end +end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb new file mode 100644 index 0000000..0d9b545 --- /dev/null +++ b/test/dummy/db/schema.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 0) do + # These are extensions that must be enabled in order to support this database + enable_extension 'plpgsql' + + create_table 'labels', id: false, force: :cascade do |t| + t.string 'name' + end + + create_table 'tag_audits', id: false, force: :cascade do |t| + t.string 'tag_name' + end + + create_table 'tags', force: :cascade do |t| + t.string 'name' + end +end diff --git a/test/dummy/log/.keep b/test/dummy/log/.keep new file mode 100644 index 0000000..e69de29 diff --git a/test/test_helper.rb b/test/test_helper.rb index 14b0d01..ee569b1 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,40 +1,13 @@ # frozen_string_literal: true -require 'erb' -require 'active_record' -require 'with_advisory_lock' -require 'tmpdir' -require 'securerandom' -begin - require 'activerecord-trilogy-adapter' - ActiveSupport.on_load(:active_record) do - require "trilogy_adapter/connection" - ActiveRecord::Base.public_send :extend, TrilogyAdapter::Connection - end -rescue LoadError - # do nothing -end +ENV['RAILS_ENV'] = 'test' -ActiveRecord::Base.configurations = { - default_env: { - url: ENV.fetch('DATABASE_URL', "sqlite3://#{Dir.tmpdir}/with_advisory_lock_test#{RUBY_VERSION}-#{ActiveRecord.gem_version}.sqlite3"), - properties: { allowPublicKeyRetrieval: true } # for JRuby madness - } -} +require_relative 'dummy/config/environment' +ActiveRecord::Migrator.migrations_paths = [File.expand_path('../test/dummy/db/migrate', __dir__)] +require 'rails/test_help' ENV['WITH_ADVISORY_LOCK_PREFIX'] ||= SecureRandom.hex -ActiveRecord::Base.establish_connection - -def env_db - @env_db ||= ActiveRecord::Base.connection_db_config.adapter.to_sym -end - -ActiveRecord::Migration.verbose = false - -require 'test_models' -require 'minitest' -require 'maxitest/autorun' require 'mocha/minitest' class GemTestCase < ActiveSupport::TestCase @@ -49,9 +22,6 @@ def is_postgresql_adapter?; adapter_support.postgresql?; end setup do ENV['FLOCK_DIR'] = Dir.mktmpdir if is_sqlite3_adapter? - Tag.delete_all - TagAudit.delete_all - Label.delete_all end teardown do @@ -59,4 +29,4 @@ def is_postgresql_adapter?; adapter_support.postgresql?; end end end -puts "Testing with #{env_db} database, ActiveRecord #{ActiveRecord.gem_version} and #{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} as #{RUBY_VERSION}" +# puts "Testing with #{env_db} database, ActiveRecord #{ActiveRecord.gem_version} and #{RUBY_ENGINE} #{RUBY_ENGINE_VERSION} as #{RUBY_VERSION}" diff --git a/test/test_models.rb b/test/test_models.rb deleted file mode 100644 index 8d6fda1..0000000 --- a/test/test_models.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -ActiveRecord::Schema.define(version: 1) do - create_table 'tags', force: true do |t| - t.string 'name' - end - create_table 'tag_audits', id: false, force: true do |t| - t.string 'tag_name' - end - create_table 'labels', id: false, force: true do |t| - t.string 'name' - end -end - -class ApplicationRecord < ActiveRecord::Base - self.abstract_class = true -end - -class Tag < ApplicationRecord - after_save do - TagAudit.create(tag_name: name) - Label.create(name: name) - end -end - -class TagAudit < ApplicationRecord -end - -class Label < ApplicationRecord -end diff --git a/test/with_advisory_lock/active_record_query_cache_test.rb b/test/with_advisory_lock/active_record_query_cache_test.rb new file mode 100644 index 0000000..370a416 --- /dev/null +++ b/test/with_advisory_lock/active_record_query_cache_test.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'test_helper' +class ActiveRecordQueryCacheTest < GemTestCase + test 'does not disable quary cache by default' do + ActiveRecord::Base.expects(:uncached).never + Tag.with_advisory_lock('lock') { Tag.first } + end + + test 'can disable ActiveRecord query cache' do + ActiveRecord::Base.expects(:uncached).once + Tag.with_advisory_lock('a-lock', disable_query_cache: true) { Tag.first } + end +end diff --git a/test/with_advisory_lock/shared_test.rb b/test/with_advisory_lock/shared_test.rb index 7cd23a4..461fa61 100644 --- a/test/with_advisory_lock/shared_test.rb +++ b/test/with_advisory_lock/shared_test.rb @@ -36,10 +36,6 @@ def work end class SharedLocksTest < GemTestCase - def supported? - %i[trilogy mysql2 jdbcmysql].exclude?(env_db) - end - test 'does not allow two exclusive locks' do one = SharedTestWorker.new(false) assert_predicate(one, :locked?) @@ -54,7 +50,7 @@ def supported? class NotSupportedEnvironmentTest < SharedLocksTest setup do - skip if supported? + skip if is_mysql_adapter? end test 'raises an error when attempting to use a shared lock' do @@ -71,7 +67,7 @@ class NotSupportedEnvironmentTest < SharedLocksTest class SupportedEnvironmentTest < SharedLocksTest setup do - skip unless supported? + skip unless is_mysql_adapter? end test 'does allow two shared locks' do @@ -113,7 +109,7 @@ class SupportedEnvironmentTest < SharedLocksTest class PostgreSQLTest < SupportedEnvironmentTest setup do - skip unless env_db == :postgresql + skip unless is_postgresql_adapter? end def pg_lock_modes diff --git a/test/with_advisory_lock/transaction_test.rb b/test/with_advisory_lock/transaction_test.rb index 559f55c..22fb79b 100644 --- a/test/with_advisory_lock/transaction_test.rb +++ b/test/with_advisory_lock/transaction_test.rb @@ -3,12 +3,8 @@ require 'test_helper' class TransactionScopingTest < GemTestCase - def supported? - %i[postgresql jdbcpostgresql].include?(env_db) - end - test 'raises an error when attempting to use transaction level locks if not supported' do - skip if supported? + skip if is_postgresql_adapter? Tag.transaction do exception = assert_raises(ArgumentError) do @@ -23,7 +19,7 @@ def supported? class PostgresqlTest < TransactionScopingTest setup do - skip unless env_db == :postgresql + skip unless is_postgresql_adapter? @pg_lock_count = lambda do ApplicationRecord.connection.select_value("SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory';").to_i end diff --git a/test/with_advisory_lock/concern_test.rb b/test/with_advisory_lock/with_advisory_lock_concern_test.rb similarity index 87% rename from test/with_advisory_lock/concern_test.rb rename to test/with_advisory_lock/with_advisory_lock_concern_test.rb index 7e5f79c..ab26d58 100644 --- a/test/with_advisory_lock/concern_test.rb +++ b/test/with_advisory_lock/with_advisory_lock_concern_test.rb @@ -19,6 +19,8 @@ class WithAdvisoryLockConcernTest < GemTestCase assert_respond_to(Label.new, :advisory_lock_exists?) end end +<<<<<<<< HEAD:test/with_advisory_lock/with_advisory_lock_concern_test.rb +======== class ActiveRecordQueryCacheTest < GemTestCase test 'does not disable quary cache by default' do @@ -31,3 +33,4 @@ class ActiveRecordQueryCacheTest < GemTestCase Tag.with_advisory_lock('a-lock', disable_query_cache: true) { Tag.first } end end +>>>>>>>> origin/master:test/with_advisory_lock/concern_test.rb