diff options
Diffstat (limited to 'activerecord/test')
-rw-r--r-- | activerecord/test/adapter_test_sqlserver.rb | 67 | ||||
-rw-r--r-- | activerecord/test/locking_test.rb | 155 | ||||
-rw-r--r-- | activerecord/test/migration_test.rb | 17 |
3 files changed, 157 insertions, 82 deletions
diff --git a/activerecord/test/adapter_test_sqlserver.rb b/activerecord/test/adapter_test_sqlserver.rb new file mode 100644 index 0000000000..11f244e9f7 --- /dev/null +++ b/activerecord/test/adapter_test_sqlserver.rb @@ -0,0 +1,67 @@ +require 'abstract_unit'
+require 'fixtures/default'
+require 'fixtures/post'
+require 'fixtures/task'
+
+class SqlServerAdapterTest < Test::Unit::TestCase
+ fixtures :posts, :tasks
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def test_execute_without_block_closes_statement
+ assert_all_statements_used_are_closed do
+ @connection.execute("SELECT 1")
+ end
+ end
+
+ def test_execute_with_block_closes_statement
+ assert_all_statements_used_are_closed do
+ @connection.execute("SELECT 1") do |sth|
+ assert !sth.finished?, "Statement should still be alive within block"
+ end
+ end
+ end
+
+ def test_insert_with_identity_closes_statement
+ assert_all_statements_used_are_closed do
+ @connection.insert("INSERT INTO accounts ([id], [firm_id],[credit_limit]) values (999, 1, 50)")
+ end
+ end
+
+ def test_insert_without_identity_closes_statement
+ assert_all_statements_used_are_closed do
+ @connection.insert("INSERT INTO accounts ([firm_id],[credit_limit]) values (1, 50)")
+ end
+ end
+
+ def test_active_closes_statement
+ assert_all_statements_used_are_closed do
+ @connection.active?
+ end
+ end
+
+ def assert_all_statements_used_are_closed(&block)
+ existing_handles = []
+ ObjectSpace.each_object(DBI::StatementHandle) {|handle| existing_handles << handle}
+ GC.disable
+
+ yield
+
+ used_handles = []
+ ObjectSpace.each_object(DBI::StatementHandle) {|handle| used_handles << handle unless existing_handles.include? handle}
+
+ assert_block "No statements were used within given block" do
+ used_handles.size > 0
+ end
+
+ ObjectSpace.each_object(DBI::StatementHandle) do |handle|
+ assert_block "Statement should have been closed within given block" do
+ handle.finished?
+ end
+ end
+ ensure
+ GC.enable
+ end
+end
diff --git a/activerecord/test/locking_test.rb b/activerecord/test/locking_test.rb index 58c34a69e3..00df4bb8e4 100644 --- a/activerecord/test/locking_test.rb +++ b/activerecord/test/locking_test.rb @@ -63,91 +63,96 @@ end # 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.) -class PessimisticLockingTest < Test::Unit::TestCase - self.use_transactional_fixtures = false - fixtures :people - def setup - @allow_concurrency = ActiveRecord::Base.allow_concurrency - ActiveRecord::Base.allow_concurrency = true - end - - def teardown - ActiveRecord::Base.allow_concurrency = @allow_concurrency - end +# TODO: The SQL Server adapter currently has no support for pessimistic locking - # Test that the adapter doesn't blow up on add_lock! - def test_sane_find_with_lock - assert_nothing_raised do - Person.transaction do - Person.find 1, :lock => true - end +unless current_adapter?(:SQLServerAdapter) + class PessimisticLockingTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + fixtures :people + + def setup + @allow_concurrency = ActiveRecord::Base.allow_concurrency + ActiveRecord::Base.allow_concurrency = true end - end - - # Test no-blowup for scoped lock. - def test_sane_find_with_lock - assert_nothing_raised do - Person.transaction do - Person.with_scope(:find => { :lock => true }) do - Person.find 1 + + def teardown + ActiveRecord::Base.allow_concurrency = @allow_concurrency + end + + # Test that the adapter doesn't blow up on add_lock! + def test_sane_find_with_lock + assert_nothing_raised do + Person.transaction do + Person.find 1, :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 + + # Test no-blowup for scoped lock. + def test_sane_find_with_lock + assert_nothing_raised do + Person.transaction do + Person.with_scope(:find => { :lock => true }) do + Person.find 1 + end + end end end - end - - if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) - 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 - } + + # 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 - - 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 + + if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) + 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 - 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 + + 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 - - 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 diff --git a/activerecord/test/migration_test.rb b/activerecord/test/migration_test.rb index 3d4dfedf3e..649ee54439 100644 --- a/activerecord/test/migration_test.rb +++ b/activerecord/test/migration_test.rb @@ -39,8 +39,8 @@ if ActiveRecord::Base.connection.supports_migrations? end Reminder.reset_column_information - %w(last_name key bio age height wealth birthday favorite_day male - mail administrator).each do |column| + %w(last_name key bio age height wealth birthday favorite_day + male administrator).each do |column| Person.connection.remove_column('people', column) rescue nil end Person.connection.remove_column("people", "first_name") rescue nil @@ -177,11 +177,13 @@ if ActiveRecord::Base.connection.supports_migrations? Person.connection.create_table :testings do |t| t.column :foo, :string end - Person.connection.execute "insert into testings values (1, 'hello')" + + con = Person.connection + Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')" assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" } assert_raises(ActiveRecord::StatementInvalid) do - Person.connection.execute "insert into testings values (2, 'hello', NULL)" + Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)" end ensure Person.connection.drop_table :testings rescue nil @@ -267,7 +269,7 @@ if ActiveRecord::Base.connection.supports_migrations? assert_equal Time, bob.birthday.class if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter) - # SQL Server, Sybase, and Oracle don't differentiate between date/time + # Sybase, and Oracle don't differentiate between date/time assert_equal Time, bob.favorite_day.class else assert_equal Date, bob.favorite_day.class @@ -355,7 +357,8 @@ if ActiveRecord::Base.connection.supports_migrations? ActiveRecord::Base.connection.rename_table :octopuses, :octopi # Using explicit id in insert for compatibility across all databases - assert_nothing_raised { ActiveRecord::Base.connection.execute "INSERT INTO octopi VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" } + con = ActiveRecord::Base.connection + assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" } assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1") @@ -379,7 +382,7 @@ if ActiveRecord::Base.connection.supports_migrations? old_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns") assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false } - new_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns") + new_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns") assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false } assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true } |