X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=vendor%2Frails%2Factiverecord%2Ftest%2Fcases%2Flocking_test.rb;fp=vendor%2Frails%2Factiverecord%2Ftest%2Fcases%2Flocking_test.rb;h=0000000000000000000000000000000000000000;hb=36d9f3351a3b4e8159279445190e2287ffdea86c;hp=e1772355911ca70c26f6a91b139fafc8ba54e291;hpb=913cf6054b1d29b5d2f5e620304af7ee77cc1f1f;p=feedcatcher.git diff --git a/vendor/rails/activerecord/test/cases/locking_test.rb b/vendor/rails/activerecord/test/cases/locking_test.rb deleted file mode 100644 index e177235..0000000 --- a/vendor/rails/activerecord/test/cases/locking_test.rb +++ /dev/null @@ -1,322 +0,0 @@ -require "cases/helper" -require 'models/person' -require 'models/reader' -require 'models/legacy_thing' -require 'models/reference' - -class LockWithoutDefault < ActiveRecord::Base; end - -class LockWithCustomColumnWithoutDefault < ActiveRecord::Base - set_table_name :lock_without_defaults_cust - set_locking_column :custom_lock_version -end - -class ReadonlyFirstNamePerson < Person - attr_readonly :first_name -end - -class OptimisticLockingTest < ActiveRecord::TestCase - fixtures :people, :legacy_things, :references - - # need to disable transactional fixtures, because otherwise the sqlite3 - # adapter (at least) chokes when we try and change the schema in the middle - # of a test (see test_increment_counter_*). - self.use_transactional_fixtures = false - - def test_lock_existing - p1 = Person.find(1) - p2 = Person.find(1) - assert_equal 0, p1.lock_version - assert_equal 0, p2.lock_version - - p1.first_name = 'stu' - p1.save! - assert_equal 1, p1.lock_version - assert_equal 0, p2.lock_version - - p2.first_name = 'sue' - assert_raise(ActiveRecord::StaleObjectError) { p2.save! } - end - - def test_lock_destroy - p1 = Person.find(1) - p2 = Person.find(1) - assert_equal 0, p1.lock_version - assert_equal 0, p2.lock_version - - p1.first_name = 'stu' - p1.save! - assert_equal 1, p1.lock_version - assert_equal 0, p2.lock_version - - assert_raises(ActiveRecord::StaleObjectError) { p2.destroy } - - assert p1.destroy - assert_equal true, p1.frozen? - assert_raises(ActiveRecord::RecordNotFound) { Person.find(1) } - end - - def test_lock_repeating - p1 = Person.find(1) - p2 = Person.find(1) - assert_equal 0, p1.lock_version - assert_equal 0, p2.lock_version - - p1.first_name = 'stu' - p1.save! - assert_equal 1, p1.lock_version - assert_equal 0, p2.lock_version - - p2.first_name = 'sue' - assert_raise(ActiveRecord::StaleObjectError) { p2.save! } - p2.first_name = 'sue2' - assert_raise(ActiveRecord::StaleObjectError) { p2.save! } - end - - def test_lock_new - p1 = Person.new(:first_name => 'anika') - assert_equal 0, p1.lock_version - - p1.first_name = 'anika2' - p1.save! - p2 = Person.find(p1.id) - assert_equal 0, p1.lock_version - assert_equal 0, p2.lock_version - - p1.first_name = 'anika3' - p1.save! - assert_equal 1, p1.lock_version - assert_equal 0, p2.lock_version - - p2.first_name = 'sue' - assert_raise(ActiveRecord::StaleObjectError) { p2.save! } - end - - def test_lock_new_with_nil - p1 = Person.new(:first_name => 'anika') - p1.save! - p1.lock_version = nil # simulate bad fixture or column with no default - p1.save! - assert_equal 1, p1.lock_version - end - - - def test_lock_column_name_existing - t1 = LegacyThing.find(1) - t2 = LegacyThing.find(1) - assert_equal 0, t1.version - assert_equal 0, t2.version - - t1.tps_report_number = 700 - t1.save! - assert_equal 1, t1.version - assert_equal 0, t2.version - - t2.tps_report_number = 800 - assert_raise(ActiveRecord::StaleObjectError) { t2.save! } - end - - def test_lock_column_is_mass_assignable - p1 = Person.create(:first_name => 'bianca') - assert_equal 0, p1.lock_version - assert_equal p1.lock_version, Person.new(p1.attributes).lock_version - - p1.first_name = 'bianca2' - p1.save! - assert_equal 1, p1.lock_version - assert_equal p1.lock_version, Person.new(p1.attributes).lock_version - end - - def test_lock_without_default_sets_version_to_zero - t1 = LockWithoutDefault.new - assert_equal 0, t1.lock_version - end - - def test_lock_with_custom_column_without_default_sets_version_to_zero - t1 = LockWithCustomColumnWithoutDefault.new - assert_equal 0, t1.custom_lock_version - end - - def test_readonly_attributes - assert_equal Set.new([ 'first_name' ]), ReadonlyFirstNamePerson.readonly_attributes - - p = ReadonlyFirstNamePerson.create(:first_name => "unchangeable name") - p.reload - assert_equal "unchangeable name", p.first_name - - p.update_attributes(:first_name => "changed name") - p.reload - assert_equal "unchangeable name", p.first_name - end - - { :lock_version => Person, :custom_lock_version => LegacyThing }.each do |name, model| - define_method("test_increment_counter_updates_#{name}") do - counter_test model, 1 do |id| - model.increment_counter :test_count, id - end - end - - define_method("test_decrement_counter_updates_#{name}") do - counter_test model, -1 do |id| - model.decrement_counter :test_count, id - end - end - - define_method("test_update_counters_updates_#{name}") do - counter_test model, 1 do |id| - model.update_counters id, :test_count => 1 - end - end - end - - def test_quote_table_name - ref = references(:michael_magician) - ref.favourite = !ref.favourite - assert ref.save - end - - # Useful for partial updates, don't only update the lock_version if there - # is nothing else being updated. - def test_update_without_attributes_does_not_only_update_lock_version - assert_nothing_raised do - p1 = Person.new(:first_name => 'anika') - p1.send(:update_with_lock, []) - end - end - - private - - def add_counter_column_to(model) - model.connection.add_column model.table_name, :test_count, :integer, :null => false, :default => 0 - model.reset_column_information - # OpenBase does not set a value to existing rows when adding a not null default column - model.update_all(:test_count => 0) if current_adapter?(:OpenBaseAdapter) - end - - def remove_counter_column_from(model) - model.connection.remove_column model.table_name, :test_count - model.reset_column_information - end - - def counter_test(model, expected_count) - add_counter_column_to(model) - object = model.find(:first) - assert_equal 0, object.test_count - assert_equal 0, object.send(model.locking_column) - yield object.id - object.reload - assert_equal expected_count, object.test_count - assert_equal 1, object.send(model.locking_column) - ensure - remove_counter_column_from(model) - end -end - - -# TODO: test against the generated SQL since testing locking behavior itself -# is so cumbersome. Will deadlock Ruby threads if the underlying db.execute -# blocks, so separate script called by Kernel#system is needed. -# (See exec vs. async_exec in the PostgreSQL adapter.) - -# TODO: The Sybase, and OpenBase adapters currently have no support for pessimistic locking - -unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) - class PessimisticLockingTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false - fixtures :people, :readers - - def setup - # Avoid introspection queries during tests. - Person.columns; Reader.columns - end - - # Test typical find. - def test_sane_find_with_lock - assert_nothing_raised do - Person.transaction do - Person.find 1, :lock => true - end - end - end - - # Test scoped lock. - def test_sane_find_with_scoped_lock - assert_nothing_raised do - Person.transaction do - Person.with_scope(:find => { :lock => true }) do - Person.find 1 - end - end - end - end - - # PostgreSQL protests SELECT ... FOR UPDATE on an outer join. - unless current_adapter?(:PostgreSQLAdapter) - # Test locked eager find. - def test_eager_find_with_lock - assert_nothing_raised do - Person.transaction do - Person.find 1, :include => :readers, :lock => true - end - end - end - end - - # Locking a record reloads it. - def test_sane_lock_method - assert_nothing_raised do - Person.transaction do - person = Person.find 1 - old, person.first_name = person.first_name, 'fooman' - person.lock! - assert_equal old, person.first_name - end - end - end - - if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) - use_concurrent_connections - - def test_no_locks_no_wait - first, second = duel { Person.find 1 } - assert first.end > second.end - end - - def test_second_lock_waits - assert [0.2, 1, 5].any? { |zzz| - first, second = duel(zzz) { Person.find 1, :lock => true } - second.end > first.end - } - end - - protected - def duel(zzz = 5) - t0, t1, t2, t3 = nil, nil, nil, nil - - a = Thread.new do - t0 = Time.now - Person.transaction do - yield - sleep zzz # block thread 2 for zzz seconds - end - t1 = Time.now - end - - b = Thread.new do - sleep zzz / 2.0 # ensure thread 1 tx starts first - t2 = Time.now - Person.transaction { yield } - t3 = Time.now - end - - a.join - b.join - - assert t1 > t0 + zzz - assert t2 > t0 - assert t3 > t2 - [t0.to_f..t1.to_f, t2.to_f..t3.to_f] - end - end - end -end