From ce3ea558ab509624a1c8d8499408f52ebb4bbe2b Mon Sep 17 00:00:00 2001 From: Marcin Raczkowski Date: Sat, 28 Aug 2010 18:47:39 +0200 Subject: IdentityMap - Tests for IM --- activerecord/lib/active_record/test_case.rb | 7 + .../test/cases/associations/join_model_test.rb | 2 +- activerecord/test/cases/identity_map_test.rb | 198 +++++++++++++++++++++ activerecord/test/cases/locking_test.rb | 13 ++ activerecord/test/cases/relations_test.rb | 6 + activerecord/test/fixtures/subscribers.yml | 4 + 6 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 activerecord/test/cases/identity_map_test.rb diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb index 014a900c71..c7557fb224 100644 --- a/activerecord/lib/active_record/test_case.rb +++ b/activerecord/lib/active_record/test_case.rb @@ -3,6 +3,13 @@ module ActiveRecord # # Defines some test assertions to test against SQL queries. class TestCase < ActiveSupport::TestCase #:nodoc: + setup :cleanup_identity_map + + def cleanup_identity_map + ActiveRecord::IdentityMap.current_repository_name = :test + ActiveRecord::Base.identity_map.clear + end + def assert_date_from_db(expected, actual, message = nil) # SybaseAdapter doesn't have a separate column type just for dates, # so the time is in the string and incorrectly formatted diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 96edcfbb35..21f61594d7 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -104,7 +104,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first - tag.author_id + assert_nothing_raised(NoMethodError) { tag.author_id } end def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key diff --git a/activerecord/test/cases/identity_map_test.rb b/activerecord/test/cases/identity_map_test.rb new file mode 100644 index 0000000000..915f3abd26 --- /dev/null +++ b/activerecord/test/cases/identity_map_test.rb @@ -0,0 +1,198 @@ +require "cases/helper" +require 'models/developer' +require 'models/project' +require 'models/company' +require 'models/topic' +require 'models/reply' +require 'models/computer' +require 'models/customer' +require 'models/order' +require 'models/post' +require 'models/author' +require 'models/tag' +require 'models/tagging' +require 'models/comment' +require 'models/sponsor' +require 'models/member' +require 'models/essay' +require 'models/subscriber' + +class IdentityMapTest < ActiveRecord::TestCase + fixtures :accounts, :companies, :developers, :projects, :topics, + :developers_projects, :computers, :authors, :author_addresses, + :posts, :tags, :taggings, :comments, :subscribers + + def test_find_id + assert_same( + Client.find(3), + Client.find(3) + ) + end + + def test_find_pkey + assert_same( + Subscriber.find('swistak'), + Subscriber.find('swistak') + ) + end + + def test_find_by_id + assert_same( + Client.find_by_id(3), + Client.find_by_id(3) + ) + end + + def test_find_by_pkey + assert_same( + Subscriber.find_by_nick('swistak'), + Subscriber.find_by_nick('swistak') + ) + end + + def test_find_first_id + assert_same( + Client.find(:first, :conditions => {:id => 1}), + Client.find(:first, :conditions => {:id => 1}) + ) + end + + def test_find_first_pkey + assert_same( + Subscriber.find(:first, :conditions => {:nick => 'swistak'}), + Subscriber.find(:first, :conditions => {:nick => 'swistak'}) + ) + end + + def test_creation + t1 = Topic.create("title" => "t1") + t2 = Topic.find(t1.id) + assert_same(t1, t2) + end + + def test_updating_of_pkey + s = Subscriber.find_by_nick('swistak') + assert s.update_attribute(:nick, 'swistakTheJester') + assert_equal('swistakTheJester', s.nick) + + assert stj = Subscriber.find_by_nick('swistakTheJester') + assert_same(s, stj) + end + + def test_changing_associations + t1 = Topic.create("title" => "t1") + t2 = Topic.create("title" => "t2") + r1 = Reply.new("title" => "r1", "content" => "r1") + + r1.topic = t1 + assert r1.save + + assert_same(t1.replies.first, r1) + + r1.topic = t2 + assert r1.save + + assert_same(t2.replies.first, r1) + assert_equal(0, t1.replies.size) + end + + def test_im_with_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins + tag = posts(:welcome).tags.first + tag_with_joins_and_select = posts(:welcome).tags.add_joins_and_select.first + assert_same(tag, tag_with_joins_and_select) + assert_nothing_raised(NoMethodError, "Joins/select was not loaded") { tag.author_id } + end + + def test_find_with_preloaded_associations + assert_queries(2) do + posts = Post.preload(:comments) + assert posts.first.comments.first + end + + # With IM we'll retrieve post object from previous query, it'll have comments + # already preloaded from first call + assert_queries(1) do + posts = Post.preload(:comments).to_a + assert posts.first.comments.first + end + + assert_queries(2) do + posts = Post.preload(:author) + assert posts.first.author + end + + # With IM we'll retrieve post object from previous query, it'll have comments + # already preloaded from first call + assert_queries(1) do + posts = Post.preload(:author).to_a + assert posts.first.author + end + + assert_queries(1) do + posts = Post.preload(:author, :comments).to_a + assert posts.first.author + assert posts.first.comments.first + end + end + + def test_find_with_included_associations + assert_queries(2) do + posts = Post.includes(:comments) + assert posts.first.comments.first + end + + assert_queries(1) do + posts = Post.scoped.includes(:comments) + assert posts.first.comments.first + end + + assert_queries(2) do + posts = Post.includes(:author) + assert posts.first.author + end + + assert_queries(1) do + posts = Post.includes(:author, :comments).to_a + assert posts.first.author + assert posts.first.comments.first + end + end + + def test_eager_loading_with_conditions_on_joined_table_preloads + posts = assert_queries(2) do + Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id') + end + assert_equal [posts(:welcome)], posts + assert_equal authors(:david), assert_no_queries { posts[0].author} + + posts = assert_queries(1) do + Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id') + end + assert_equal [posts(:welcome)], posts + assert_equal authors(:david), assert_no_queries { posts[0].author} + + posts = assert_queries(1) do + Post.find(:all, :include => :author, :joins => {:taggings => :tag}, :conditions => "tags.name = 'General'", :order => 'posts.id') + end + assert_equal posts(:welcome, :thinking), posts + + posts = assert_queries(2) do + Post.find(:all, :include => :author, :joins => {:taggings => {:tag => :taggings}}, :conditions => "taggings_tags.super_tag_id=2", :order => 'posts.id') + end + assert_equal posts(:welcome, :thinking), posts + end + + def test_eager_loading_with_conditions_on_string_joined_table_preloads + posts = assert_queries(2) do + Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :conditions => "comments.body like 'Thank you%'", :order => 'posts.id') + end + assert_equal [posts(:welcome)], posts + assert_equal authors(:david), assert_no_queries { posts[0].author} + + posts = assert_queries(1) do + Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id') + end + assert_equal [posts(:welcome)], posts + assert_equal authors(:david), assert_no_queries { posts[0].author} + end +end diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 4ddcdc010b..5ceb19e7c8 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -15,6 +15,11 @@ class ReadonlyFirstNamePerson < Person attr_readonly :first_name end +# Becouse of introduction of IdentityMap optimistic locking should only be needed +# in multithreaded applications, or when more then one software operates on database. +# +# I'm using ActiveRecord::IdentityMap.without to prevent Identity map from +# using one record here. class OptimisticLockingTest < ActiveRecord::TestCase fixtures :people, :legacy_things, :references @@ -23,6 +28,10 @@ class OptimisticLockingTest < ActiveRecord::TestCase # of a test (see test_increment_counter_*). self.use_transactional_fixtures = false + def setup + ActiveRecord::IdentityMap.enabled = false + end + def test_lock_existing p1 = Person.find(1) p2 = Person.find(1) @@ -215,6 +224,10 @@ class OptimisticLockingTest < ActiveRecord::TestCase end end + def teardown + ActiveRecord::IdentityMap.enabled = true + end + private def add_counter_column_to(model, col='test_count') diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 535bcd4396..eb268017f8 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -263,6 +263,7 @@ class RelationTest < ActiveRecord::TestCase end def test_find_with_preloaded_associations + ActiveRecord::IdentityMap.without do assert_queries(2) do posts = Post.preload(:comments) assert posts.first.comments.first @@ -288,9 +289,11 @@ class RelationTest < ActiveRecord::TestCase assert posts.first.author assert posts.first.comments.first end + end end def test_find_with_included_associations + ActiveRecord::IdentityMap.without do assert_queries(2) do posts = Post.includes(:comments) assert posts.first.comments.first @@ -311,6 +314,7 @@ class RelationTest < ActiveRecord::TestCase assert posts.first.author assert posts.first.comments.first end + end end def test_default_scope_with_conditions_string @@ -552,9 +556,11 @@ class RelationTest < ActiveRecord::TestCase end def test_relation_merging_with_preload + ActiveRecord::IdentityMap.without do [Post.scoped & Post.preload(:author), Post.preload(:author) & Post.scoped].each do |posts| assert_queries(2) { assert posts.first.author } end + end end def test_relation_merging_with_joins diff --git a/activerecord/test/fixtures/subscribers.yml b/activerecord/test/fixtures/subscribers.yml index 9ffb4a156f..c6a8c2fa24 100644 --- a/activerecord/test/fixtures/subscribers.yml +++ b/activerecord/test/fixtures/subscribers.yml @@ -5,3 +5,7 @@ first: second: nick: webster132 name: David Heinemeier Hansson + +thrid: + nick: swistak + name: Marcin Raczkowski \ No newline at end of file -- cgit v1.2.3