Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: move test to minitest #434

Merged
merged 1 commit into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion closure_tree.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
gem.required_ruby_version = '>= 3.0.0'

gem.add_runtime_dependency 'activerecord', '>= 6.1.0'
gem.add_runtime_dependency 'with_advisory_lock', '>= 4.0.0'
gem.add_runtime_dependency 'with_advisory_lock', '>= 5.0.0'

gem.add_development_dependency 'appraisal'
gem.add_development_dependency 'database_cleaner'
Expand Down
38 changes: 0 additions & 38 deletions spec/closure_tree/cache_invalidation_spec.rb

This file was deleted.

36 changes: 36 additions & 0 deletions test/closure_tree/cache_invalidation_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
require 'test_helper'

class CacheInvalidationTest < ActiveSupport::TestCase
def setup
Timecop.travel(10.seconds.ago) do
#create a long tree with 2 branch
@root = MenuItem.create(
name: SecureRandom.hex(10)
)
2.times do
parent = @root
10.times do
parent = parent.children.create(
name: SecureRandom.hex(10)
)
end
end
@first_leaf = MenuItem.leaves.first
@second_leaf = MenuItem.leaves.last
end
end

test "touch option should invalidate cache for all it ancestors" do
old_time_stamp = @first_leaf.ancestors.pluck(:updated_at)
@first_leaf.touch
new_time_stamp = @first_leaf.ancestors.pluck(:updated_at)
assert_not_equal old_time_stamp, new_time_stamp, 'Cache not invalidated for all ancestors'
end

test "touch option should not invalidate cache for another branch" do
old_time_stamp = @second_leaf.updated_at
@first_leaf.touch
new_time_stamp = @second_leaf.updated_at
assert_equal old_time_stamp, new_time_stamp, 'Cache incorrectly invalidated for another branch'
end
end
80 changes: 80 additions & 0 deletions test/closure_tree/has_closure_tree_root_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
require "test_helper"

class HasClosureTreeRootTest < ActiveSupport::TestCase
setup do
ENV['FLOCK_DIR'] = Dir.mktmpdir
end

teardown do
FileUtils.remove_entry_secure ENV['FLOCK_DIR']
end
def create_tree(group)
@ct1 = ContractType.create!(name: "Type1")
@ct2 = ContractType.create!(name: "Type2")
@user1 = User.create!(email: "1@example.com", group_id: group.id)
@user2 = User.create!(email: "2@example.com", group_id: group.id)
@user3 = User.create!(email: "3@example.com", group_id: group.id)
@user4 = User.create!(email: "4@example.com", group_id: group.id)
@user5 = User.create!(email: "5@example.com", group_id: group.id)
@user6 = User.create!(email: "6@example.com", group_id: group.id)

# The tree (contract types in parens)
#
# U1(1)
# / \
# U2(1) U3(1&2)
# / / \
# U4(2) U5(1) U6(2)

@user1.children << @user2
@user1.children << @user3
@user2.children << @user4
@user3.children << @user5
@user3.children << @user6

@user1.contracts.create!(title: "Contract 1", contract_type: @ct1)
@user2.contracts.create!(title: "Contract 2", contract_type: @ct1)
@user3.contracts.create!(title: "Contract 3", contract_type: @ct1)
@user3.contracts.create!(title: "Contract 4", contract_type: @ct2)
@user4.contracts.create!(title: "Contract 5", contract_type: @ct2)
@user5.contracts.create!(title: "Contract 6", contract_type: @ct1)
@user6.contracts.create!(title: "Contract 7", contract_type: @ct2)
end

test "loads all nodes in a constant number of queries" do
group = Group.create!(name: "TheGrouping")
create_tree(group)
reloaded_group = group.reload
exceed_query_limit(2) do
root = reloaded_group.root_user_including_tree
assert_equal "2@example.com", root.children[0].email
assert_equal "3@example.com", root.children[0].parent.children[1].email
end
end

test "loads all nodes plus single association in a constant number of queries" do
group = Group.create!(name: "TheGrouping")
create_tree(group)
reloaded_group = group.reload
exceed_query_limit(3) do
root = reloaded_group.root_user_including_tree(:contracts)
assert_equal "2@example.com", root.children[0].email
assert_equal "3@example.com", root.children[0].parent.children[1].email
assert_equal "Contract 7", root.children[0].children[0].contracts[0].user.parent.parent.children[1].children[1].contracts[0].title
end
end

test "loads all nodes and associations in a constant number of queries" do
group = Group.create!(name: "TheGrouping")
create_tree(group)
reloaded_group = group.reload
exceed_query_limit(4) do
root = reloaded_group.root_user_including_tree(contracts: :contract_type)
assert_equal "2@example.com", root.children[0].email
assert_equal "3@example.com", root.children[0].parent.children[1].email
assert_equal %w[Type1 Type2], root.children[1].contracts.map(&:contract_type).map(&:name)
assert_equal "Type1", root.children[1].children[0].contracts[0].contract_type.name
assert_equal "Type2", root.children[0].children[0].contracts[0].user.parent.parent.children[1].children[1].contracts[0].contract_type.name
end
end
end
29 changes: 29 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
require 'database_cleaner'
require 'support/query_counter'
require 'parallel'
require 'timecop'

ActiveRecord::Base.configurations = {
default_env: {
Expand Down Expand Up @@ -61,9 +62,37 @@ class Spec
end
end

class ActiveSupport::TestCase
def exceed_query_limit(num, &block)
counter = QueryCounter.new
ActiveSupport::Notifications.subscribed(counter.to_proc, 'sql.active_record', &block)
assert counter.query_count <= num, "Expected to run maximum #{num} queries, but ran #{counter.query_count}"
end

class QueryCounter
attr_reader :query_count

def initialize
@query_count = 0
end

def to_proc
lambda(&method(:callback))
end

def callback(name, start, finish, message_id, values)
@query_count += 1 unless %w(CACHE SCHEMA).include?(values[:name])
end
end
end

# Configure parallel tests
Thread.abort_on_exception = true

# Configure advisory_lock
# See: https://github.com/ClosureTree/with_advisory_lock
ENV['WITH_ADVISORY_LOCK_PREFIX'] ||= SecureRandom.hex

require 'closure_tree'
require_relative '../spec/support/schema'
require_relative '../spec/support/models'