From 22bbbf191c9c964fe45c7c361e4ee812e586f2af Mon Sep 17 00:00:00 2001 From: Nicolas Rodriguez Date: Sat, 9 Jan 2021 09:33:45 +0100 Subject: [PATCH] Migrate from Travis to Github Actions (#373) Ruby 3.0 support --- .github/workflows/ci.yml | 96 +++++++++++++++ .gitignore | 3 +- .rspec | 2 +- .travis.yml | 36 ------ Appraisals | 15 +++ Rakefile | 17 ++- bin/appraisal | 29 +++++ bin/rake | 29 +++++ bin/rspec | 29 +++++ closure_tree.gemspec | 8 +- gemfiles/activerecord_6.1.gemfile | 19 +++ lib/closure_tree/has_closure_tree_root.rb | 2 +- .../cache_invalidation_spec.rb | 3 +- spec/{ => closure_tree}/cuisine_type_spec.rb | 2 +- .../has_closure_tree_root_spec.rb | 2 +- .../hierarchy_maintenance_spec.rb | 2 +- spec/{ => closure_tree}/label_spec.rb | 10 +- spec/{ => closure_tree}/matcher_spec.rb | 4 +- spec/{ => closure_tree}/metal_spec.rb | 2 +- spec/{ => closure_tree}/model_spec.rb | 4 +- .../{ => closure_tree}/namespace_type_spec.rb | 4 +- spec/{ => closure_tree}/parallel_spec.rb | 2 +- spec/{ => closure_tree}/pool_spec.rb | 2 +- spec/{ => closure_tree}/support_spec.rb | 2 +- spec/{ => closure_tree}/tag_spec.rb | 3 +- spec/{ => closure_tree}/user_spec.rb | 2 +- spec/{ => closure_tree}/uuid_tag_spec.rb | 3 +- spec/db/database.yml | 21 ---- spec/spec_helper.rb | 114 +++++++++++++++++- spec/support/database.rb | 52 -------- spec/support/database_cleaner.rb | 14 --- spec/support/hash_monkey_patch.rb | 13 -- spec/support/helpers.rb | 9 ++ spec/{db => support}/models.rb | 0 spec/{db => support}/schema.rb | 0 spec/support/sqlite3_with_advisory_lock.rb | 10 -- spec/{ => support}/tag_examples.rb | 2 +- 37 files changed, 372 insertions(+), 195 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml create mode 100755 bin/appraisal create mode 100755 bin/rake create mode 100755 bin/rspec create mode 100644 gemfiles/activerecord_6.1.gemfile rename spec/{ => closure_tree}/cache_invalidation_spec.rb (95%) rename spec/{ => closure_tree}/cuisine_type_spec.rb (97%) rename spec/{ => closure_tree}/has_closure_tree_root_spec.rb (99%) rename spec/{ => closure_tree}/hierarchy_maintenance_spec.rb (96%) rename spec/{ => closure_tree}/label_spec.rb (98%) rename spec/{ => closure_tree}/matcher_spec.rb (95%) rename spec/{ => closure_tree}/metal_spec.rb (98%) rename spec/{ => closure_tree}/model_spec.rb (80%) rename spec/{ => closure_tree}/namespace_type_spec.rb (91%) rename spec/{ => closure_tree}/parallel_spec.rb (99%) rename spec/{ => closure_tree}/pool_spec.rb (96%) rename spec/{ => closure_tree}/support_spec.rb (92%) rename spec/{ => closure_tree}/tag_spec.rb (55%) rename spec/{ => closure_tree}/user_spec.rb (99%) rename spec/{ => closure_tree}/uuid_tag_spec.rb (53%) delete mode 100644 spec/db/database.yml delete mode 100644 spec/support/database.rb delete mode 100644 spec/support/database_cleaner.rb delete mode 100644 spec/support/hash_monkey_patch.rb create mode 100644 spec/support/helpers.rb rename spec/{db => support}/models.rb (100%) rename spec/{db => support}/schema.rb (100%) delete mode 100644 spec/support/sqlite3_with_advisory_lock.rb rename spec/{ => support}/tag_examples.rb (99%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9068ee89 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,96 @@ +--- +name: CI + +on: + - push + - pull_request + +jobs: + rspec: + runs-on: ubuntu-20.04 + + services: + postgres: + image: 'postgres:13' + ports: ['5432:5432'] + env: + POSTGRES_PASSWORD: postgres + POSTGRES_DB: closure_tree + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + strategy: + fail-fast: false + matrix: + ruby: + - '3.0' + - '2.7' + - '2.6' + - '2.5' + rails: + - activerecord_6.1 + - activerecord_6.0 + - activerecord_5.2 + - activerecord_5.1 + - activerecord_5.0 + - activerecord_4.2 + - activerecord_edge + adapter: + - sqlite3 + - mysql2 + - postgresql + exclude: + - ruby: '2.7' + rails: activerecord_4.2 + - ruby: '3.0' + rails: activerecord_4.2 + - ruby: '3.0' + rails: activerecord_5.0 + - ruby: '3.0' + rails: activerecord_5.1 + - ruby: '3.0' + rails: activerecord_5.2 + - ruby: '2.5' + rails: activerecord_edge + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + + - name: Set DB Adapter + env: + RAILS_VERSION: ${{ matrix.rails }} + DB_ADAPTER: ${{ matrix.adapter }} + + # See: https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md#mysql + run: | + if [ "${DB_ADAPTER}" = "mysql2" ]; then + sudo systemctl start mysql.service + mysql -u root -proot -e 'create database closure_tree;' + fi + + - name: Bundle + env: + RAILS_VERSION: ${{ matrix.rails }} + DB_ADAPTER: ${{ matrix.adapter }} + BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile + run: | + gem install bundler + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + + - name: RSpec + env: + RAILS_VERSION: ${{ matrix.rails }} + DB_ADAPTER: ${{ matrix.adapter }} + BUNDLE_GEMFILE: gemfiles/${{ matrix.rails }}.gemfile + WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }} + run: bin/rake --trace spec:all diff --git a/.gitignore b/.gitignore index 62d9b3ab..a3fada8f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ tmp/ *.lock tmp/ .ruby-* -*.iml \ No newline at end of file +*.iml +coverage/ diff --git a/.rspec b/.rspec index 2e386bcc..4e1e0d2f 100644 --- a/.rspec +++ b/.rspec @@ -1 +1 @@ ---format documentation --color --order random +--color diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3035a424..00000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -cache: bundler -language: ruby - -rvm: - - 2.7.1 - - 2.6.3 - - 2.5.5 - -gemfile: - - gemfiles/activerecord_6.0.gemfile - - gemfiles/activerecord_5.2.gemfile - - gemfiles/activerecord_5.1.gemfile - - gemfiles/activerecord_5.0.gemfile - - gemfiles/activerecord_4.2.gemfile - - gemfiles/activerecord_edge.gemfile - -env: - - DB=sqlite - - DB=mysql - - DB=postgresql - -services: - - mysql - - postgresql - -script: WITH_ADVISORY_LOCK_PREFIX=$TRAVIS_JOB_ID bundle exec rake --trace spec:all - -matrix: - allow_failures: - - gemfile: gemfiles/activerecord_edge.gemfile - - gemfile: gemfiles/activerecord_6.0.gemfile - exclude: - - rvm: 2.5.5 - gemfile: gemfiles/activerecord_edge.gemfile - - rvm: 2.7.1 - gemfile: gemfiles/activerecord_4.2.gemfile diff --git a/Appraisals b/Appraisals index bbb038a0..98d02c51 100644 --- a/Appraisals +++ b/Appraisals @@ -74,6 +74,21 @@ appraise 'activerecord-6.0' do end end +appraise 'activerecord-6.1' do + gem 'activerecord', '~> 6.1.0' + platforms :ruby do + gem 'mysql2' + gem 'pg' + gem 'sqlite3' + end + + platforms :jruby do + gem 'activerecord-jdbcmysql-adapter' + gem 'activerecord-jdbcpostgresql-adapter' + gem 'activerecord-jdbcsqlite3-adapter' + end +end + appraise 'activerecord-edge' do gem 'activerecord', github: 'rails/rails' platforms :ruby do diff --git a/Rakefile b/Rakefile index a557c454..bb87ad7c 100644 --- a/Rakefile +++ b/Rakefile @@ -1,23 +1,20 @@ -begin - require 'bundler/setup' -rescue LoadError - puts 'You must `gem install bundler` and `bundle install` to run rake tasks' -end +# frozen_string_literal: true -Bundler::GemHelper.install_tasks +require 'bundler/gem_tasks' +require 'rspec/core/rake_task' -require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) do |task| - task.pattern = 'spec/*_spec.rb' + task.pattern = 'spec/closure_tree/*_spec.rb' end -task :default => :spec +task default: :spec namespace :spec do desc 'Run all spec variants' task :all do - rake = 'bundle exec rake' + rake = 'bin/rake' fail unless system("#{rake} spec:generators") + [['', ''], ['db_prefix_', ''], ['', '_db_suffix'], ['abc_', '_123']].each do |prefix, suffix| env = "DB_PREFIX=#{prefix} DB_SUFFIX=#{suffix}" fail unless system("#{rake} spec #{env}") diff --git a/bin/appraisal b/bin/appraisal new file mode 100755 index 00000000..0e7ba65d --- /dev/null +++ b/bin/appraisal @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'appraisal' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("appraisal", "appraisal") diff --git a/bin/rake b/bin/rake new file mode 100755 index 00000000..9275675e --- /dev/null +++ b/bin/rake @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rake' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rake", "rake") diff --git a/bin/rspec b/bin/rspec new file mode 100755 index 00000000..a6c78521 --- /dev/null +++ b/bin/rspec @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rspec' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rspec-core", "rspec") diff --git a/closure_tree.gemspec b/closure_tree.gemspec index a17b924f..45615d1b 100644 --- a/closure_tree.gemspec +++ b/closure_tree.gemspec @@ -1,5 +1,6 @@ -$LOAD_PATH.push File.expand_path('../lib', __FILE__) -require 'closure_tree/version' +# frozen_string_literal: true + +require_relative 'lib/closure_tree/version' Gem::Specification.new do |gem| gem.name = 'closure_tree' @@ -26,8 +27,11 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'database_cleaner' gem.add_development_dependency 'generator_spec' gem.add_development_dependency 'parallel' + gem.add_development_dependency 'pg' gem.add_development_dependency 'rspec-instafail' gem.add_development_dependency 'rspec-rails' + gem.add_development_dependency 'sqlite3' + gem.add_development_dependency 'simplecov' gem.add_development_dependency 'timecop' # gem.add_development_dependency 'byebug' # gem.add_development_dependency 'ruby-prof' # <- don't need this normally. diff --git a/gemfiles/activerecord_6.1.gemfile b/gemfiles/activerecord_6.1.gemfile new file mode 100644 index 00000000..899dfafd --- /dev/null +++ b/gemfiles/activerecord_6.1.gemfile @@ -0,0 +1,19 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "activerecord", "~> 6.1.0" + +platforms :ruby do + gem "mysql2" + gem "pg" + gem "sqlite3" +end + +platforms :jruby do + gem "activerecord-jdbcmysql-adapter" + gem "activerecord-jdbcpostgresql-adapter" + gem "activerecord-jdbcsqlite3-adapter" +end + +gemspec path: "../" diff --git a/lib/closure_tree/has_closure_tree_root.rb b/lib/closure_tree/has_closure_tree_root.rb index 7ac6aeec..70e327d1 100644 --- a/lib/closure_tree/has_closure_tree_root.rb +++ b/lib/closure_tree/has_closure_tree_root.rb @@ -8,7 +8,7 @@ def has_closure_tree_root(assoc_name, options = {}) options[:class_name] ||= assoc_name.to_s.sub(/\Aroot_/, "").classify options[:foreign_key] ||= self.name.underscore << "_id" - has_one assoc_name, -> { where(parent: nil) }, options + has_one assoc_name, -> { where(parent: nil) }, **options # Fetches the association, eager loading all children and given associations define_method("#{assoc_name}_including_tree") do |*args| diff --git a/spec/cache_invalidation_spec.rb b/spec/closure_tree/cache_invalidation_spec.rb similarity index 95% rename from spec/cache_invalidation_spec.rb rename to spec/closure_tree/cache_invalidation_spec.rb index b80da6dd..22e2dc68 100644 --- a/spec/cache_invalidation_spec.rb +++ b/spec/closure_tree/cache_invalidation_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' - -describe 'cache invalidation', cache: true do +RSpec.describe 'cache invalidation', cache: true do before do Timecop.travel(10.seconds.ago) do #create a long tree with 2 branch diff --git a/spec/cuisine_type_spec.rb b/spec/closure_tree/cuisine_type_spec.rb similarity index 97% rename from spec/cuisine_type_spec.rb rename to spec/closure_tree/cuisine_type_spec.rb index dbca1876..b59e72e6 100644 --- a/spec/cuisine_type_spec.rb +++ b/spec/closure_tree/cuisine_type_spec.rb @@ -9,7 +9,7 @@ def assert_lineage(e, m) expect(m.self_and_ancestors).to eq([m, e]) end -describe CuisineType do +RSpec.describe CuisineType do it "finds self and parents when children << is used" do e = CuisineType.new(:name => "e") m = CuisineType.new(:name => "m") diff --git a/spec/has_closure_tree_root_spec.rb b/spec/closure_tree/has_closure_tree_root_spec.rb similarity index 99% rename from spec/has_closure_tree_root_spec.rb rename to spec/closure_tree/has_closure_tree_root_spec.rb index 04fcccf0..8fad3ac7 100644 --- a/spec/has_closure_tree_root_spec.rb +++ b/spec/closure_tree/has_closure_tree_root_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe "has_closure_tree_root" do +RSpec.describe "has_closure_tree_root" do let!(:ct1) { ContractType.create!(name: "Type1") } let!(:ct2) { ContractType.create!(name: "Type2") } let!(:user1) { User.create!(email: "1@example.com", group_id: group.id) } diff --git a/spec/hierarchy_maintenance_spec.rb b/spec/closure_tree/hierarchy_maintenance_spec.rb similarity index 96% rename from spec/hierarchy_maintenance_spec.rb rename to spec/closure_tree/hierarchy_maintenance_spec.rb index 38794e35..a4ad09f5 100644 --- a/spec/hierarchy_maintenance_spec.rb +++ b/spec/closure_tree/hierarchy_maintenance_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe ClosureTree::HierarchyMaintenance do +RSpec.describe ClosureTree::HierarchyMaintenance do describe '.rebuild!' do it 'rebuild tree' do 20.times do |counter| diff --git a/spec/label_spec.rb b/spec/closure_tree/label_spec.rb similarity index 98% rename from spec/label_spec.rb rename to spec/closure_tree/label_spec.rb index ebc19ed0..859a14ca 100644 --- a/spec/label_spec.rb +++ b/spec/closure_tree/label_spec.rb @@ -41,7 +41,7 @@ def create_preorder_tree(suffix = "", &block) end end -describe Label do +RSpec.describe Label do context "destruction" do it "properly destroys descendents created with find_or_create_by_path" do c = Label.find_or_create_by_path %w(a b c) @@ -606,13 +606,13 @@ def roots_name_and_order it "checks parent of node" do expect(@a1.parent_of?(@b1)).to be_truthy - expect(@c2.parent_of?(@d2)).to be_truthy + expect(@c2.parent_of?(@d2)).to be_truthy expect(@c1.parent_of?(@b1)).to be_falsey end it "checks children of node" do expect(@d1.child_of?(@c1)).to be_truthy - expect(@c2.child_of?(@b1)).to be_truthy + expect(@c2.child_of?(@b1)).to be_truthy expect(@c3.child_of?(@b1)).to be_falsey end @@ -625,13 +625,13 @@ def roots_name_and_order it "checks ancestor of node" do expect(@a1.ancestor_of?(@d1)).to be_truthy expect(@b1.ancestor_of?(@d1)).to be_truthy - expect(@b1.ancestor_of?(@c3)).to be_falsey + expect(@b1.ancestor_of?(@c3)).to be_falsey end it "checks descendant of node" do expect(@c1.descendant_of?(@a1)).to be_truthy expect(@d2.descendant_of?(@a1)).to be_truthy - expect(@b1.descendant_of?(@a2)).to be_falsey + expect(@b1.descendant_of?(@a2)).to be_falsey end it "checks descendant of node" do diff --git a/spec/matcher_spec.rb b/spec/closure_tree/matcher_spec.rb similarity index 95% rename from spec/matcher_spec.rb rename to spec/closure_tree/matcher_spec.rb index e440d417..af64a81a 100644 --- a/spec/matcher_spec.rb +++ b/spec/closure_tree/matcher_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe 'ClosureTree::Test::Matcher' do - +RSpec.describe 'ClosureTree::Test::Matcher' do describe 'be_a_closure_tree' do it { expect(UUIDTag).to be_a_closure_tree } it { expect(User).to be_a_closure_tree } @@ -30,5 +29,4 @@ end end end - end diff --git a/spec/metal_spec.rb b/spec/closure_tree/metal_spec.rb similarity index 98% rename from spec/metal_spec.rb rename to spec/closure_tree/metal_spec.rb index ba88d6a7..f29f0af7 100644 --- a/spec/metal_spec.rb +++ b/spec/closure_tree/metal_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Metal do +RSpec.describe Metal do describe '#find_or_create_by_path' do def assert_correctness(grandchild) expect(grandchild).to be_a(Metal) diff --git a/spec/model_spec.rb b/spec/closure_tree/model_spec.rb similarity index 80% rename from spec/model_spec.rb rename to spec/closure_tree/model_spec.rb index b5789130..1744aa97 100644 --- a/spec/model_spec.rb +++ b/spec/closure_tree/model_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -describe ClosureTree::Model do +RSpec.describe ClosureTree::Model do describe '#_ct' do it 'should delegate to the Support instance on the class' do expect(Tag.new._ct).to eq(Tag._ct) end end -end \ No newline at end of file +end diff --git a/spec/namespace_type_spec.rb b/spec/closure_tree/namespace_type_spec.rb similarity index 91% rename from spec/namespace_type_spec.rb rename to spec/closure_tree/namespace_type_spec.rb index 788fbabd..1bf61706 100644 --- a/spec/namespace_type_spec.rb +++ b/spec/closure_tree/namespace_type_spec.rb @@ -1,7 +1,6 @@ require 'spec_helper' -describe Namespace::Type do - +RSpec.describe Namespace::Type do context "class injection" do it "should build hierarchy classname correctly" do expect(Namespace::Type.hierarchy_class.to_s).to eq("Namespace::TypeHierarchy") @@ -9,5 +8,4 @@ expect(Namespace::Type._ct.short_hierarchy_class_name).to eq("TypeHierarchy") end end - end diff --git a/spec/parallel_spec.rb b/spec/closure_tree/parallel_spec.rb similarity index 99% rename from spec/parallel_spec.rb rename to spec/closure_tree/parallel_spec.rb index 2ce72acb..4ec3a61a 100644 --- a/spec/parallel_spec.rb +++ b/spec/closure_tree/parallel_spec.rb @@ -45,7 +45,7 @@ def work end end -describe 'Concurrent creation' do +RSpec.describe 'Concurrent creation' do before :each do @target = nil @iterations = 5 diff --git a/spec/pool_spec.rb b/spec/closure_tree/pool_spec.rb similarity index 96% rename from spec/pool_spec.rb rename to spec/closure_tree/pool_spec.rb index de25c4fb..57ba0eb9 100644 --- a/spec/pool_spec.rb +++ b/spec/closure_tree/pool_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe 'Configuration' do +RSpec.describe 'Configuration' do it 'returns connection to the pool after has_closure_tree setup' do class TypeDuplicate < ActiveRecord::Base self.table_name = "namespace_type#{table_name_suffix}" diff --git a/spec/support_spec.rb b/spec/closure_tree/support_spec.rb similarity index 92% rename from spec/support_spec.rb rename to spec/closure_tree/support_spec.rb index 9f280ac4..1deb27bf 100644 --- a/spec/support_spec.rb +++ b/spec/closure_tree/support_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe ClosureTree::Support do +RSpec.describe ClosureTree::Support do let(:sut) { Tag._ct } it 'passes through table names without prefix and suffix' do expected = 'some_random_table_name' diff --git a/spec/tag_spec.rb b/spec/closure_tree/tag_spec.rb similarity index 55% rename from spec/tag_spec.rb rename to spec/closure_tree/tag_spec.rb index c602a865..2e5a39b1 100644 --- a/spec/tag_spec.rb +++ b/spec/closure_tree/tag_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' -require 'tag_examples' -describe Tag do +RSpec.describe Tag do it_behaves_like Tag end diff --git a/spec/user_spec.rb b/spec/closure_tree/user_spec.rb similarity index 99% rename from spec/user_spec.rb rename to spec/closure_tree/user_spec.rb index ee7a50fa..327224aa 100644 --- a/spec/user_spec.rb +++ b/spec/closure_tree/user_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "empty db" do +RSpec.describe "empty db" do context "empty db" do it "should return no entities" do diff --git a/spec/uuid_tag_spec.rb b/spec/closure_tree/uuid_tag_spec.rb similarity index 53% rename from spec/uuid_tag_spec.rb rename to spec/closure_tree/uuid_tag_spec.rb index 50a71975..5c32ac1a 100644 --- a/spec/uuid_tag_spec.rb +++ b/spec/closure_tree/uuid_tag_spec.rb @@ -1,6 +1,5 @@ require 'spec_helper' -require 'tag_examples' -describe UUIDTag do +RSpec.describe UUIDTag do it_behaves_like Tag end diff --git a/spec/db/database.yml b/spec/db/database.yml deleted file mode 100644 index 023e7971..00000000 --- a/spec/db/database.yml +++ /dev/null @@ -1,21 +0,0 @@ -common: &common - database: <%= db_name %> - host: localhost - pool: 50 - timeout: 5000 - reaping_frequency: 1000 - min_messages: ERROR - -sqlite: - <<: *common - adapter: <%= "jdbc" if defined? JRUBY_VERSION %>sqlite3 - -postgresql: - <<: *common - adapter: postgresql - username: postgres - -mysql: - <<: *common - adapter: mysql2 - username: root diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4cc8738c..7e3a0829 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,24 +1,126 @@ -$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib') - -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) -require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +# frozen_string_literal: true +require 'simplecov' require 'database_cleaner' require 'closure_tree/test/matcher' require 'tmpdir' require 'timecop' require 'forwardable' require 'parallel' + begin require 'foreigner' rescue LoadError #Foreigner is not needed in ActiveRecord 4.2+ end -Thread.abort_on_exception = true +require 'active_record' +require 'active_support/core_ext/array' -Dir['./spec/support/**/*.rb'].sort.each { |f| require f } +# Use in specs to skip some tests +def sqlite? + ENV.fetch('DB_ADAPTER', 'sqlite3') == 'sqlite3' +end +# Start Simplecov +SimpleCov.start do + add_filter 'spec/' +end + +# Configure RSpec RSpec.configure do |config| config.include ClosureTree::Test::Matcher + + config.color = true + config.fail_fast = false + + config.order = :random + Kernel.srand config.seed + + config.expect_with :rspec do |c| + c.syntax = :expect + end + + DatabaseCleaner.strategy = :truncation + + config.before do + DatabaseCleaner.start + end + + config.after do + DatabaseCleaner.clean + end + + # disable monkey patching + # see: https://relishapp.com/rspec/rspec-core/v/3-8/docs/configuration/zero-monkey-patching-mode + config.disable_monkey_patching! + + if sqlite? + config.before(:suite) do + ENV['FLOCK_DIR'] = Dir.mktmpdir + end + + config.after(:suite) do + FileUtils.remove_entry_secure ENV['FLOCK_DIR'] + end + end +end + +# Configure parallel specs +Thread.abort_on_exception = true + +# Configure advisory_lock +# See: https://github.com/ClosureTree/with_advisory_lock +ENV['WITH_ADVISORY_LOCK_PREFIX'] ||= SecureRandom.hex + +# Configure ActiveRecord +ActiveRecord::Migration.verbose = false +ActiveRecord::Base.table_name_prefix = ENV['DB_PREFIX'].to_s +ActiveRecord::Base.table_name_suffix = ENV['DB_SUFFIX'].to_s + +adapter = ENV.fetch('DB_ADAPTER', 'sqlite3') + +config = { + adapter: adapter, + database: 'closure_tree', + encoding: 'utf8', + pool: 50, + timeout: 5000, + reaping_frequency: 1000, + min_messages: 'ERROR', +} + +config = + case adapter + when 'postgresql' + config.merge(host: '127.0.0.1', port: 5432, username: 'postgres', password: 'postgres') + when 'mysql2' + config.merge(host: '127.0.0.1', port: 3306, username: 'root', password: 'root') + when 'sqlite3' + config.merge(database: ':memory:') + end + +case adapter +when 'postgresql' + # We need to switch on 'postgres' DB to destroy 'closure_tree' DB + ActiveRecord::Base.establish_connection(config.merge(database: 'postgres', schema_search_path: 'public')) + ActiveRecord::Base.connection.recreate_database(config[:database], config) + +when 'mysql2' + ActiveRecord::Base.establish_connection(config) + ActiveRecord::Base.connection.recreate_database(config[:database], { charset: 'utf8', collation: 'utf8_unicode_ci' }) end + +ActiveRecord::Base.establish_connection(config) +Foreigner.load if defined?(Foreigner) + +# Require our gem +require 'closure_tree' + +# Load test helpers +require_relative 'support/schema' +require_relative 'support/models' +require_relative 'support/tag_examples' +require_relative 'support/helpers' +require_relative 'support/exceed_query_limit' +require_relative 'support/query_counter' diff --git a/spec/support/database.rb b/spec/support/database.rb deleted file mode 100644 index 941ca775..00000000 --- a/spec/support/database.rb +++ /dev/null @@ -1,52 +0,0 @@ -database_folder = "#{File.dirname(__FILE__)}/../db" -database_adapter = ENV['DB'] ||= 'postgresql' - -def sqlite? - ENV['DB'] == 'sqlite' -end - -log = Logger.new('db.log') -log.sev_threshold = Logger::DEBUG -ActiveRecord::Base.logger = log - -ActiveRecord::Migration.verbose = false -ActiveRecord::Base.table_name_prefix = ENV['DB_PREFIX'].to_s -ActiveRecord::Base.table_name_suffix = ENV['DB_SUFFIX'].to_s - -def db_name - @db_name ||= "closure_tree_test_#{rand(1..2**31)}" -end - -ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read("#{database_folder}/database.yml")).result) - -config = ActiveRecord::Base.configurations[database_adapter] - -begin - case database_adapter - when 'sqlite' - ActiveRecord::Base.establish_connection(database_adapter.to_sym) - when 'mysql' - ActiveRecord::Base.establish_connection(config.merge('database' => nil)) - ActiveRecord::Base.connection.recreate_database(config['database'], {charset: 'utf8', collation: 'utf8_unicode_ci'}) - when 'postgresql' - ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) - ActiveRecord::Base.connection.recreate_database(config['database'], config.merge('encoding' => 'utf8')) - end -end unless ENV['NONUKES'] - -ActiveRecord::Base.establish_connection(config) -# Drop this when support for ActiveRecord 4.1 is removed -Foreigner.load if defined?(Foreigner) - -require "#{database_folder}/schema" -require "#{database_folder}/models" - -# See http://stackoverflow.com/a/22388177/1268016 -def count_queries(&block) - count = 0 - counter_fn = ->(name, started, finished, unique_id, payload) do - count += 1 unless %w[CACHE SCHEMA].include? payload[:name] - end - ActiveSupport::Notifications.subscribed(counter_fn, 'sql.active_record', &block) - count -end diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb deleted file mode 100644 index 119e8fe1..00000000 --- a/spec/support/database_cleaner.rb +++ /dev/null @@ -1,14 +0,0 @@ -RSpec.configure do |config| - - DatabaseCleaner.strategy = :truncation - - config.before(:each) do - ActiveRecord::Base.connection_pool.connection - DatabaseCleaner.start - end - - config.after(:each) do - ActiveRecord::Base.connection_pool.connection - DatabaseCleaner.clean - end -end diff --git a/spec/support/hash_monkey_patch.rb b/spec/support/hash_monkey_patch.rb deleted file mode 100644 index f6dbcde6..00000000 --- a/spec/support/hash_monkey_patch.rb +++ /dev/null @@ -1,13 +0,0 @@ -class Hash - def render_from_yield(&block) - reduce({}) do |h, entry| - k, v = entry - h[block.call(k)] = if v.is_a?(Hash) then - v.render_from_yield(&block) - else - block.call(v) - end - h - end - end -end diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb new file mode 100644 index 00000000..14047149 --- /dev/null +++ b/spec/support/helpers.rb @@ -0,0 +1,9 @@ +# See http://stackoverflow.com/a/22388177/1268016 +def count_queries(&block) + count = 0 + counter_fn = ->(name, started, finished, unique_id, payload) do + count += 1 unless %w[CACHE SCHEMA].include? payload[:name] + end + ActiveSupport::Notifications.subscribed(counter_fn, 'sql.active_record', &block) + count +end diff --git a/spec/db/models.rb b/spec/support/models.rb similarity index 100% rename from spec/db/models.rb rename to spec/support/models.rb diff --git a/spec/db/schema.rb b/spec/support/schema.rb similarity index 100% rename from spec/db/schema.rb rename to spec/support/schema.rb diff --git a/spec/support/sqlite3_with_advisory_lock.rb b/spec/support/sqlite3_with_advisory_lock.rb deleted file mode 100644 index cf96313e..00000000 --- a/spec/support/sqlite3_with_advisory_lock.rb +++ /dev/null @@ -1,10 +0,0 @@ -if sqlite? - RSpec.configure do |config| - config.before(:suite) do - ENV['FLOCK_DIR'] = Dir.mktmpdir - end - config.after(:suite) do - FileUtils.remove_entry_secure ENV['FLOCK_DIR'] - end - end -end \ No newline at end of file diff --git a/spec/tag_examples.rb b/spec/support/tag_examples.rb similarity index 99% rename from spec/tag_examples.rb rename to spec/support/tag_examples.rb index 14dd8cf7..6a21ee69 100644 --- a/spec/tag_examples.rb +++ b/spec/support/tag_examples.rb @@ -1,6 +1,6 @@ require 'spec_helper' -shared_examples_for Tag do +RSpec.shared_examples_for Tag do let (:tag_class) { described_class } let (:tag_hierarchy_class) { described_class.hierarchy_class }