summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorJamis Buck <jamis@37signals.com>2005-01-09 15:04:16 +0000
committerJamis Buck <jamis@37signals.com>2005-01-09 15:04:16 +0000
commitc51fa9fc3d7c0ec6f59bcaf3d352fae9325857e2 (patch)
treefa6c5fdee64da937145d594348100b03225a4207 /test
downloadthird_party-sqlite3-ruby-c51fa9fc3d7c0ec6f59bcaf3d352fae9325857e2.tar.gz
third_party-sqlite3-ruby-c51fa9fc3d7c0ec6f59bcaf3d352fae9325857e2.tar.xz
third_party-sqlite3-ruby-c51fa9fc3d7c0ec6f59bcaf3d352fae9325857e2.zip
Changed layout to support tagging and branching
Diffstat (limited to 'test')
-rw-r--r--test/bm.rb140
-rw-r--r--test/driver/dl/tc_driver.rb322
-rw-r--r--test/mocks.rb99
-rw-r--r--test/native-vs-dl.rb126
-rw-r--r--test/tc_database.rb216
-rw-r--r--test/tc_integration.rb838
-rw-r--r--test/tests.rb36
7 files changed, 1777 insertions, 0 deletions
diff --git a/test/bm.rb b/test/bm.rb
new file mode 100644
index 0000000..aacb4a1
--- /dev/null
+++ b/test/bm.rb
@@ -0,0 +1,140 @@
+require 'benchmark'
+
+N = 1000
+
+$VERBOSE=nil
+
+puts "file require"
+Benchmark.bm( 7 ) do |x|
+ x.report('sqlite') do
+ N.times do
+ $".delete_if { |i| i =~ /sqlite/ }
+ require 'sqlite'
+ end
+ end
+ x.report('sqlite3') do
+ N.times do
+ $".delete_if { |i| i =~ /sqlite3/ }
+ require 'sqlite3'
+ end
+ end
+end
+
+puts
+puts "database creation..."
+Benchmark.bm( 7 ) do |x|
+ x.report('sqlite') do
+ N.times do
+ File.delete "test.db" rescue nil
+ SQLite::Database.open( "test.db" ).close
+ end
+ end
+ x.report('sqlite3') do
+ N.times do
+ File.delete "test.db" rescue nil
+ SQLite3::Database.open( "test.db" ).close
+ end
+ end
+end
+File.delete "test.db" rescue nil
+
+SQLite::Database.open( "test.db" ).close
+SQLite3::Database.open( "test3.db" ).close
+
+puts
+puts "database open..."
+Benchmark.bm( 7 ) do |x|
+ x.report('sqlite') do
+ N.times do
+ SQLite::Database.open( "test.db" ).close
+ end
+ end
+ x.report('sqlite3') do
+ N.times do
+ SQLite3::Database.open( "test3.db" ).close
+ end
+ end
+end
+File.delete "test.db" rescue nil
+File.delete "test3.db" rescue nil
+
+db = SQLite::Database.open( "test.db" )
+db3 = SQLite3::Database.open( "test3.db" )
+
+db.execute "create table foo (a,b)"
+db3.execute "create table foo (a,b)"
+
+puts
+puts "insertions"
+Benchmark.bm( 7 ) do |x|
+ x.report('sqlite') do
+ db.transaction do
+ N.times do |i|
+ db.execute "insert into foo values (#{i}, #{i+1})"
+ end
+ end
+ end
+ x.report('sqlite3') do
+ db3.transaction do
+ N.times do |i|
+ db3.execute "insert into foo values (#{i}, #{i+1})"
+ end
+ end
+ end
+end
+
+puts
+puts "insertions using prepared statement"
+Benchmark.bm( 7 ) do |x|
+ x.report('sqlite') do
+ db.transaction do
+ stmt = db.prepare "insert into foo values (?,?)"
+ N.times { |i| stmt.execute i, i+1 }
+ end
+ end
+ x.report('sqlite3') do
+ db3.transaction do
+ db3.prepare( "insert into foo values (?,?)" ) do |stmt|
+ N.times { |i| stmt.execute i, i+1 }
+ end
+ end
+ end
+end
+
+db.close
+db3.close
+File.delete "test.db" rescue nil
+File.delete "test3.db" rescue nil
+
+db = SQLite::Database.open( "test.db" )
+db3 = SQLite3::Database.open( "test3.db" )
+
+db.execute "create table foo (a,b)"
+db.execute "insert into foo values (1,2)"
+db.execute "insert into foo values (3,4)"
+db.execute "insert into foo values (5,6)"
+
+db3.execute "create table foo (a,b)"
+db3.execute "insert into foo values (1,2)"
+db3.execute "insert into foo values (3,4)"
+db3.execute "insert into foo values (5,6)"
+
+puts
+puts "queries"
+Benchmark.bm( 7 ) do |x|
+ x.report('sqlite') do
+ N.times do
+ db.execute "select * from foo"
+ end
+ end
+ x.report('sqlite3') do
+ N.times do
+ db3.execute "select * from foo"
+ end
+ end
+end
+
+db.close
+db3.close
+File.delete "test.db" rescue nil
+File.delete "test3.db" rescue nil
diff --git a/test/driver/dl/tc_driver.rb b/test/driver/dl/tc_driver.rb
new file mode 100644
index 0000000..3dc59e3
--- /dev/null
+++ b/test/driver/dl/tc_driver.rb
@@ -0,0 +1,322 @@
+#--
+# =============================================================================
+# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * The names of its contributors may not be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =============================================================================
+#++
+
+$:.unshift "../../../lib"
+
+require 'sqlite3/constants'
+require 'sqlite3/driver/dl/driver'
+require 'test/unit'
+
+class TC_DL_Driver < Test::Unit::TestCase
+
+ def utf16ify( str )
+ chars = str.split(//)
+ chars.zip(["\0"] * chars.length).flatten.join
+ end
+
+ def setup
+ @driver = SQLite3::Driver::DL::Driver.new
+ @dbname = "test.db"
+ @db = nil
+ end
+
+ def teardown
+ @driver.close( @db ) rescue nil
+ File.delete @dbname rescue nil
+ end
+
+ def test_open
+ result, @db = @driver.open( @dbname )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert File.exist?( @dbname )
+ end
+
+ def test_open_utf16
+ name = utf16ify( @dbname )
+ result, @db = @driver.open( name, true )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert File.exist?( @dbname )
+ end
+
+ def test_errmsg
+ result, @db = @driver.open( @dbname )
+ msg = @driver.errmsg( @db )
+ assert_equal msg, "not an error"
+ end
+
+ def test_errmsg16
+ result, @db = @driver.open( @dbname )
+ msg = @driver.errmsg( @db, true )
+ assert_equal msg, utf16ify( "not an error" )
+ end
+
+ def test_prepare
+ result, @db = @driver.open( @dbname )
+ sql = "create table foo ( a, b )"
+ result, handle, remainder = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert_equal "", remainder
+ @driver.finalize( handle )
+ end
+
+ def test_prepare_error
+ result, @db = @driver.open( @dbname )
+ sql = "create tble foo ( a, b )"
+ result, handle, remainder = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::ERROR, result
+ end
+
+ def test_prepare_remainder
+ result, @db = @driver.open( @dbname )
+ sql = "create table foo ( a, b ); select * from foo"
+ result, handle, remainder = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert_equal " select * from foo", remainder
+ @driver.finalize( handle )
+ end
+
+ def test_prepare16
+ result, @db = @driver.open( @dbname )
+ sql = utf16ify( "create table foo ( a, b )" )
+ result, handle, remainder = @driver.prepare( @db, sql, true )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert_equal "", remainder
+ @driver.finalize( handle )
+ end
+
+ def test_prepare16_remainder
+ result, @db = @driver.open( @dbname )
+ sql = utf16ify( "create table foo ( a, b ); select * from foo" )
+ result, handle, remainder = @driver.prepare( @db, sql, true )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert_equal utf16ify( " select * from foo" ), remainder
+ @driver.finalize( handle )
+ end
+
+ def test_complete
+ assert @driver.complete?( "select * from foo;" )
+ end
+
+ def test_complete_fail
+ assert !@driver.complete?( "select * from foo" )
+ end
+
+ def test_complete16
+ assert @driver.complete?( utf16ify("select * from foo;"), true )
+ end
+
+ def create_foo
+ result, @db = @driver.open( @dbname )
+ sql = "create table foo ( a, b )"
+ result, handle, = @driver.prepare( @db, sql )
+ @driver.step( handle )
+ @driver.finalize( handle )
+ end
+
+ def populate_foo
+ create_foo
+ sql = "insert into foo values ( 100, 200 )"
+ result, handle, = @driver.prepare( @db, sql )
+ @driver.step( handle )
+ @driver.finalize( handle )
+ end
+
+ def test_step
+ populate_foo
+ sql = "select * from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ @driver.finalize( handle )
+ end
+
+ def test_step_fail
+ populate_foo
+ sql = "select * from"
+ result, handle, = @driver.prepare( @db, sql )
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::MISUSE, result
+ @driver.finalize( handle )
+ end
+
+ def test_bind_blob
+ create_foo
+ sql = "insert into foo (b) values (?)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_blob( handle, 1, "a\0b\1c\2d\0e" )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ sql = "select b from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ assert_equal "a\0b\1c\2d\0e", @driver.column_blob( handle, 0 )
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ end
+
+ def test_bind_double
+ create_foo
+ sql = "insert into foo (b) values (?)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_double( handle, 1, 3.14 )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ sql = "select b from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ assert_equal 3.14, @driver.column_double( handle, 0 )
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ end
+
+ def test_bind_int
+ create_foo
+ sql = "insert into foo (b) values (?)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_int( handle, 1, 14 )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ sql = "select b from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ assert_equal 14, @driver.column_int( handle, 0 )
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ end
+
+ def test_bind_null
+ create_foo
+ sql = "insert into foo (b) values (?)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_null( handle, 1 )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ sql = "select b from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ assert_equal SQLite3::Constants::ColumnType::NULL,
+ @driver.column_type( handle, 0 )
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ end
+
+ def test_bind_text
+ create_foo
+ sql = "insert into foo (b) values (?)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_text( handle, 1, "hello, world" )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ sql = "select b from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ assert_equal "hello, world", @driver.column_text( handle, 0 )
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ end
+
+ def test_bind_text16
+ create_foo
+ sql = "insert into foo (b) values (?)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_text( handle, 1, utf16ify("hello, world"), true )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::DONE, result
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ sql = "select b from foo"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.step( handle )
+ assert_equal SQLite3::Constants::ErrorCode::ROW, result
+ assert_equal "hello, world", @driver.column_text( handle, 0 )
+ result = @driver.finalize( handle )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ end
+
+ def test_bind_parameter_index
+ create_foo
+ sql = "insert into foo (b) values (:hello)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ result = @driver.bind_parameter_index( handle, ":hello" )
+ assert_equal 1, result
+ result = @driver.bind_parameter_index( handle, ":foo" )
+ assert_equal 0, result
+ @driver.finalize( handle )
+ end
+
+ def test_bind_parameter_name
+ create_foo
+ sql = "insert into foo (a,b) values (?,:foo)"
+ result, handle, = @driver.prepare( @db, sql )
+ assert_equal SQLite3::Constants::ErrorCode::OK, result
+ assert_nil nil, @driver.bind_parameter_name(handle,1)
+ assert_equal ":foo", @driver.bind_parameter_name(handle,2)
+ @driver.finalize( handle )
+ end
+
+end
diff --git a/test/mocks.rb b/test/mocks.rb
new file mode 100644
index 0000000..6843e52
--- /dev/null
+++ b/test/mocks.rb
@@ -0,0 +1,99 @@
+#--
+# =============================================================================
+# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * The names of its contributors may not be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =============================================================================
+#++
+
+require 'flexmock'
+
+class FlexMockWithArgs < FlexMock
+ attr_reader :mock_args
+ attr_reader :mock_blocks
+
+ def initialize
+ super
+ @mock_args = Hash.new { |h,k| h[k] = [] }
+ @mock_blocks = Hash.new { |h,k| h[k] = [] }
+ end
+
+ def method_missing( sym, *args, &block )
+ @mock_args[sym] << args
+ @mock_blocks[sym] << block
+ super
+ end
+end
+
+class Driver < FlexMockWithArgs
+ def self.instance
+ @@instance
+ end
+
+ def initialize
+ super
+ @@instance = self
+ mock_handle( :open ) { [0,"cookie"] }
+ mock_handle( :close ) { 0 }
+ mock_handle( :complete? ) { 0 }
+ mock_handle( :errmsg ) { "" }
+ mock_handle( :errcode ) { 0 }
+ mock_handle( :trace ) { nil }
+ mock_handle( :set_authorizer ) { 0 }
+ mock_handle( :prepare ) { [0,"stmt", "remainder"] }
+ mock_handle( :finalize ) { 0 }
+ mock_handle( :changes ) { 14 }
+ mock_handle( :total_changes ) { 28 }
+ mock_handle( :interrupt ) { 0 }
+ end
+end
+
+class Statement < FlexMockWithArgs
+ def self.instance
+ @@instance
+ end
+
+ attr_reader :handle
+ attr_reader :sql
+ attr_reader :last_result
+
+ def initialize( handle, sql )
+ super()
+ @@instance = self
+ @handle = handle
+ @sql = sql
+ mock_handle( :close ) { 0 }
+ mock_handle( :remainder ) { "" }
+ mock_handle( :execute ) do
+ @last_result = FlexMockWithArgs.new
+ @last_result.mock_handle( :each ) { @last_result.mock_blocks[:each].last.call ["foo"] }
+ @last_result.mock_handle( :inject ) { |a,| @last_result.mock_blocks[:inject].last.call a, ["foo"] }
+ @last_result.mock_handle( :columns ) { ["name"] }
+ @last_result
+ end
+ end
+end
diff --git a/test/native-vs-dl.rb b/test/native-vs-dl.rb
new file mode 100644
index 0000000..45e7e28
--- /dev/null
+++ b/test/native-vs-dl.rb
@@ -0,0 +1,126 @@
+$:.unshift "../lib", "../ext/sqlite3_api"
+
+require 'sqlite3'
+
+require 'benchmark'
+
+N = 1000
+
+$VERBOSE=nil
+
+puts "database creation..."
+Benchmark.bm( 7 ) do |x|
+ x.report('dl') do
+ N.times do
+ File.delete "test.db" rescue nil
+ SQLite3::Database.open( "test.db", :driver => "DL" ).close
+ end
+ end
+ x.report('native') do
+ N.times do
+ File.delete "test.db" rescue nil
+ SQLite3::Database.open( "test.db", :driver => "Native" ).close
+ end
+ end
+end
+File.delete "test.db" rescue nil
+
+SQLite3::Database.open( "test.db" ).close
+
+puts
+puts "database open..."
+Benchmark.bm( 7 ) do |x|
+ x.report('dl') do
+ N.times do
+ SQLite3::Database.open( "test.db", :driver => "DL" ).close
+ end
+ end
+ x.report('native') do
+ N.times do
+ SQLite3::Database.open( "test.db", :driver => "Native" ).close
+ end
+ end
+end
+File.delete "test.db" rescue nil
+
+dl = SQLite3::Database.open( "test-dl.db", :driver => "DL" )
+native = SQLite3::Database.open( "test-native.db", :driver => "Native" )
+
+dl.execute "create table foo (a,b)"
+native.execute "create table foo (a,b)"
+
+puts
+puts "insertions"
+Benchmark.bm( 7 ) do |x|
+ x.report('dl') do
+ dl.transaction do
+ N.times do |i|
+ dl.execute "insert into foo values (#{i}, #{i+1})"
+ end
+ end
+ end
+ x.report('native') do
+ native.transaction do
+ N.times do |i|
+ native.execute "insert into foo values (#{i}, #{i+1})"
+ end
+ end
+ end
+end
+
+puts
+puts "insertions using prepared statement"
+Benchmark.bm( 7 ) do |x|
+ x.report('dl') do
+ dl.transaction do
+ dl.prepare "insert into foo values (?,?)" do |stmt|
+ N.times { |i| stmt.execute i, i+1 }
+ end
+ end
+ end
+ x.report('native') do
+ native.transaction do
+ native.prepare( "insert into foo values (?,?)" ) do |stmt|
+ N.times { |i| stmt.execute i, i+1 }
+ end
+ end
+ end
+end
+
+dl.close
+native.close
+File.delete "test-dl.db" rescue nil
+File.delete "test-native.db" rescue nil
+
+dl = SQLite3::Database.open( "test-dl.db", :driver => "DL" )
+native = SQLite3::Database.open( "test-native.db", :driver => "Native" )
+
+dl.execute "create table foo (a,b)"
+dl.execute "insert into foo values (1,2)"
+dl.execute "insert into foo values (3,4)"
+dl.execute "insert into foo values (5,6)"
+
+native.execute "create table foo (a,b)"
+native.execute "insert into foo values (1,2)"
+native.execute "insert into foo values (3,4)"
+native.execute "insert into foo values (5,6)"
+
+puts
+puts "queries"
+Benchmark.bm( 7 ) do |x|
+ x.report('dl') do
+ N.times do
+ dl.execute "select * from foo"
+ end
+ end
+ x.report('native') do
+ N.times do
+ native.execute "select * from foo"
+ end
+ end
+end
+
+dl.close
+native.close
+File.delete "test-dl.db" rescue nil
+File.delete "test-native.db" rescue nil
diff --git a/test/tc_database.rb b/test/tc_database.rb
new file mode 100644
index 0000000..1aa2400
--- /dev/null
+++ b/test/tc_database.rb
@@ -0,0 +1,216 @@
+#--
+# =============================================================================
+# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * The names of its contributors may not be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# =============================================================================
+#++
+
+$:.unshift "../lib"
+
+require 'sqlite3/database'
+require 'test/unit'
+
+require 'mocks'
+
+class TC_Database_Init < Test::Unit::TestCase
+ def test_new
+ db = SQLite3::Database.new( "foo.db", :driver => Driver )
+ assert_equal 1, Driver.instance.mock_count(:open)
+ assert !db.closed?
+ assert_equal [["foo.db",false]], Driver.instance.mock_args[:open]
+ assert !db.results_as_hash
+ assert !db.type_translation
+ end
+
+ def test_open
+ db = SQLite3::Database.open( "foo.db", :driver => Driver )
+ assert_equal 1, Driver.instance.mock_count(:open)
+ assert !db.closed?
+ assert_equal [["foo.db",false]], Driver.instance.mock_args[:open]
+ assert !db.results_as_hash
+ assert !db.type_translation
+ end
+
+ def test_with_type_translation
+ db = SQLite3::Database.open( "foo.db", :driver => Driver,
+ :type_translation => true )
+ assert db.type_translation
+ end
+
+ def test_with_results_as_hash
+ db = SQLite3::Database.open( "foo.db", :driver => Driver,
+ :results_as_hash => true )
+ assert db.results_as_hash
+ end
+
+ def test_with_type_translation_and_results_as_hash
+ db = SQLite3::Database.open( "foo.db", :driver => Driver,
+ :results_as_hash => true,
+ :type_translation => true )
+ assert db.results_as_hash
+ assert db.type_translation
+ end
+end
+
+class TC_Database < Test::Unit::TestCase
+ def setup
+ @db = SQLite3::Database.open( "foo.db",
+ :driver => Driver, :statement_factory => Statement )
+ end
+
+ def test_quote
+ assert_equal "''one''two''three''", SQLite3::Database.quote(
+ "'one'two'three'" )
+ end
+
+ def test_complete
+ @db.complete? "foo"
+ assert_equal 1, Driver.instance.mock_count( :complete? )
+ end
+
+ def test_errmsg
+ @db.errmsg
+ assert_equal 1, Driver.instance.mock_count( :errmsg )
+ end
+
+ def test_errcode
+ @db.errcode
+ assert_equal 1, Driver.instance.mock_count( :errcode )
+ end
+
+ def test_translator
+ translator = @db.translator
+ assert_instance_of SQLite3::Translator, translator
+ end
+
+ def test_close
+ @db.close
+ assert_equal 1, Driver.instance.mock_count( :close )
+ assert @db.closed?
+ @db.close
+ assert_equal 1, Driver.instance.mock_count( :close )
+ end
+
+ def test_trace
+ @db.trace( 15 ) { "foo" }
+ driver = Driver.instance
+ assert_equal 1, driver.mock_count( :trace )
+ assert_equal [[ "cookie", 15 ]], driver.mock_args[:trace]
+ assert_equal 1, driver.mock_blocks[:trace].length
+ end
+
+ def test_authorizer
+ @db.authorizer( 15 ) { "foo" }
+ driver = Driver.instance
+ assert_equal 1, driver.mock_count( :set_authorizer )
+ assert_equal [[ "cookie", 15 ]], driver.mock_args[:set_authorizer]
+ assert_equal 1, driver.mock_blocks[:set_authorizer].length
+ end
+
+ def test_prepare_no_block
+ assert_nothing_raised { @db.prepare( "foo" ) }
+ assert_equal 0, Statement.instance.mock_count( :close )
+ end
+
+ def test_prepare_with_block
+ called = false
+ @db.prepare( "foo" ) { |stmt| called = true }
+ assert called
+ assert_equal 1, Statement.instance.mock_count( :close )
+ end
+
+ def test_execute_no_block
+ result = @db.execute( "foo", "bar", "baz" )
+ stmt = Statement.instance
+ assert_equal [["foo"]], result
+ assert_equal [["bar", "baz"]], stmt.mock_args[:execute]
+ end
+
+ def test_execute_with_block
+ called = false
+ @db.execute( "foo", "bar", "baz" ) do |row|
+ called = true
+ assert_equal ["foo"], row
+ end
+
+ stmt = Statement.instance
+ assert called
+ assert_equal [["bar", "baz"]], stmt.mock_args[:execute]
+ end
+
+ def test_execute2_no_block
+ result = @db.execute2( "foo", "bar", "baz" )
+ stmt = Statement.instance
+ assert_equal [["name"],["foo"]], result
+ assert_equal [["bar", "baz"]], stmt.mock_args[:execute]
+ end
+
+ def test_execute2_with_block
+ called = false
+ parts = [ ["name"],["foo"] ]
+ @db.execute2( "foo", "bar", "baz" ) do |row|
+ called = true
+ assert_equal parts.shift, row
+ end
+
+ stmt = Statement.instance
+ assert called
+ assert_equal [["bar", "baz"]], stmt.mock_args[:execute]
+ end
+
+ def test_execute_batch
+ @db.execute_batch( "foo", "bar", "baz" )
+ stmt = Statement.instance
+ assert_equal [["bar", "baz"]], stmt.mock_args[:execute]
+ end
+
+ def test_get_first_row
+ result = @db.get_first_row( "foo", "bar", "baz" )
+ assert_equal ["foo"], result
+ end
+
+ def test_get_first_value
+ result = @db.get_first_value( "foo", "bar", "baz" )
+ assert_equal "foo", result
+ end
+
+ def test_changes
+ assert_equal 14, @db.changes
+ assert_equal 1, Driver.instance.mock_count(:changes)
+ end
+
+ def test_total_changes
+ assert_equal 28, @db.total_changes
+ assert_equal 1, Driver.instance.mock_count(:total_changes)
+ end
+
+ def test_interrupt
+ @db.interrupt
+ assert_equal 1, Driver.instance.mock_count(:interrupt)
+ end
+end
diff --git a/test/tc_integration.rb b/test/tc_integration.rb
new file mode 100644
index 0000000..2dd6016
--- /dev/null
+++ b/test/tc_integration.rb
@@ -0,0 +1,838 @@
+$:.unshift "../lib"
+$:.unshift "../ext/sqlite3_api"
+
+require 'test/unit'
+require 'benchmark'
+require 'sqlite3/database'
+
+class String
+ def to_utf16
+ result = ""
+ self.each_byte { |b| result << b.chr << "\0" }
+ result
+ end
+
+ def from_utf16
+ result = ""
+ length.times do |i|
+ result << self[i,1] if i % 2 == 0 && self[i] != 0
+ end
+ result
+ end
+end
+
+module Integration
+
+ drivers_to_test = ( ENV["SQLITE3_DRIVERS"] || "Native" ).split(',')
+ drivers_to_test.each do |driver|
+
+ # == TC_OpenClose =========================================================
+
+ test_case = Class.new( Test::Unit::TestCase ) do
+ define_method( "test_create_close" ) do
+ begin
+ db = SQLite3::Database.new( "test-create.db",
+ :driver => driver )
+ assert File.exist?( "test-create.db" )
+ assert_nothing_raised { db.close }
+ ensure
+ File.delete( "test-create.db" ) rescue nil
+ end
+ end
+
+ define_method( "test_open_close" ) do
+ begin
+ File.open( "test-open.db", "w" ) { |f| }
+ assert File.exist?( "test-open.db" )
+ db = SQLite3::Database.new( "test-open.db",
+ :driver => driver )
+ assert_nothing_raised { db.close }
+ ensure
+ File.delete( "test-open.db" ) rescue nil
+ end
+ end
+
+ define_method( "test_bad_open" ) do
+ assert_raise( SQLite3::CantOpenException ) do
+ SQLite3::Database.new( ".", :driver => driver )
+ end
+ end
+ end
+ const_set( "TC_OpenClose_#{driver}", test_case )
+
+ # == TC_Database ==========================================================
+
+ test_case = Class.new( Test::Unit::TestCase ) do
+ define_method( "setup" ) do
+ @db = SQLite3::Database.new( "test.db", :driver=>driver )
+ @db.transaction do
+ @db.execute "create table foo ( a integer primary key, b text )"
+ @db.execute "insert into foo ( b ) values ( 'foo' )"
+ @db.execute "insert into foo ( b ) values ( 'bar' )"
+ @db.execute "insert into foo ( b ) values ( 'baz' )"
+ end
+ end
+
+ define_method( "teardown" ) do
+ @db.close
+ File.delete( "test.db" )
+ end
+
+ define_method( "test_complete_fail" ) do
+ assert !@db.complete?( "select * from foo" )
+ end
+ define_method( "test_complete_success" ) do
+ assert @db.complete?( "select * from foo;" )
+ end
+
+ define_method( "test_complete_fail_utf16" ) do
+ assert !@db.complete?( "select * from foo".to_utf16+"\0\0", true )
+ end
+ define_method( "test_complete_success_utf16" ) do
+ assert @db.complete?( "select * from foo;".to_utf16+"\0\0", true )
+ end
+
+ define_method( "test_errmsg" ) do
+ assert_equal "not an error", @db.errmsg
+ end
+
+ define_method( "test_errmsg_utf16" ) do
+ assert_equal "not an error".to_utf16, @db.errmsg(true)
+ end
+
+ define_method( "test_errcode" ) do
+ assert_equal 0, @db.errcode
+ end
+
+ define_method( "test_trace" ) do
+ result = nil
+ @db.trace( "data" ) { |data,sql| result = [ data, sql ]; 0 }
+ @db.execute "select * from foo"
+ assert_equal ["data","select * from foo"], result
+ end
+
+ define_method( "test_authorizer_okay" ) do
+ @db.authorizer( "data" ) { |data,type,a,b,c,d| 0 }
+ rows = @db.execute "select * from foo"
+ assert_equal 3, rows.length
+ end
+
+ define_method( "test_authorizer_error" ) do
+ @db.authorizer( "data" ) { |data,type,a,b,c,d| 1 }
+ assert_raise( SQLite3::AuthorizationException ) do
+ @db.execute "select * from foo"
+ end
+ end
+
+ define_method( "test_authorizer_silent" ) do
+ @db.authorizer( "data" ) { |data,type,a,b,c,d| 2 }
+ rows = @db.execute "select * from foo"
+ assert rows.empty?
+ end
+
+ define_method( "test_prepare_invalid_syntax" ) do
+ assert_raise( SQLite3::SQLException ) do
+ @db.prepare "select from foo"
+ end
+ end
+
+ define_method( "test_prepare_invalid_column" ) do
+ assert_raise( SQLite3::SQLException ) do
+ @db.prepare "select k from foo"
+ end
+ end
+
+ define_method( "test_prepare_invalid_table" ) do
+ assert_raise( SQLite3::SQLException ) do
+ @db.prepare "select * from barf"
+ end
+ end
+
+ define_method( "test_prepare_no_block" ) do
+ stmt = @db.prepare "select * from foo"
+ assert stmt.respond_to?(:execute)
+ stmt.close
+ end
+
+ define_method( "test_prepare_with_block" ) do
+ called = false
+ @db.prepare "select * from foo" do |stmt|
+ called = true
+ assert stmt.respond_to?(:execute)
+ end
+ assert called
+ end
+
+ define_method( "test_execute_no_block_no_bind_no_match" ) do
+ rows = @db.execute( "select * from foo where a > 100" )
+ assert rows.empty?
+ end
+
+ define_method( "test_execute_with_block_no_bind_no_match" ) do
+ called = false
+ @db.execute( "select * from foo where a > 100" ) do |row|
+ called = true
+ end
+ assert !called
+ end
+
+ define_method( "test_execute_no_block_with_bind_no_match" ) do
+ rows = @db.execute( "select * from foo where a > ?", 100 )
+ assert rows.empty?
+ end
+
+ define_method( "test_execute_with_block_with_bind_no_match" ) do
+ called = false
+ @db.execute( "select * from foo where a > ?", 100 ) do |row|
+ called = true
+ end
+ assert !called
+ end
+
+ define_method( "test_execute_no_block_no_bind_with_match" ) do
+ rows = @db.execute( "select * from foo where a = 1" )
+ assert_equal 1, rows.length
+ end
+
+ define_method( "test_execute_with_block_no_bind_with_match" ) do
+ called = 0
+ @db.execute( "select * from foo where a = 1" ) do |row|
+ called += 1
+ end
+ assert_equal 1, called
+ end
+
+ define_method( "test_execute_no_block_with_bind_with_match" ) do
+ rows = @db.execute( "select * from foo where a = ?", 1 )
+ assert_equal 1, rows.length
+ end
+
+ define_method( "test_execute_with_block_with_bind_with_match" ) do
+ called = 0
+ @db.execute( "select * from foo where a = ?", 1 ) do |row|
+ called += 1
+ end
+ assert_equal 1, called
+ end
+
+ define_method( "test_execute2_no_block_no_bind_no_match" ) do
+ columns, *rows = @db.execute2( "select * from foo where a > 100" )
+ assert rows.empty?
+ assert [ "a", "b" ], columns
+ end
+
+ define_method( "test_execute2_with_block_no_bind_no_match" ) do
+ called = 0
+ @db.execute2( "select * from foo where a > 100" ) do |row|
+ assert [ "a", "b" ], row unless called == 0
+ called += 1
+ end
+ assert_equal 1, called
+ end
+
+ define_method( "test_execute2_no_block_with_bind_no_match" ) do
+ columns, *rows = @db.execute2( "select * from foo where a > ?", 100 )
+ assert rows.empty?
+ assert [ "a", "b" ], columns
+ end
+
+ define_method( "test_execute2_with_block_with_bind_no_match" ) do
+ called = 0
+ @db.execute2( "select * from foo where a > ?", 100 ) do |row|
+ assert [ "a", "b" ], row unless called == 0
+ called += 1
+ end
+ assert_equal 1, called
+ end
+
+ define_method( "test_execute2_no_block_no_bind_with_match" ) do
+ columns, *rows = @db.execute2( "select * from foo where a = 1" )
+ assert_equal 1, rows.length
+ assert [ "a", "b" ], columns
+ end
+
+ define_method( "test_execute2_with_block_no_bind_with_match" ) do
+ called = 0
+ @db.execute2( "select * from foo where a = 1" ) do |row|
+ assert [ "a", "b" ], row unless called == 0
+ called += 1
+ end
+ assert_equal 2, called
+ end
+
+ define_method( "test_execute2_no_block_with_bind_with_match" ) do
+ columns, *rows = @db.execute2( "select * from foo where a = ?", 1 )
+ assert_equal 1, rows.length
+ assert [ "a", "b" ], columns
+ end
+
+ define_method( "test_execute2_with_block_with_bind_with_match" ) do
+ called = 0
+ @db.execute2( "select * from foo where a = ?", 1 ) do |row|
+ called += 1
+ end
+ assert_equal 2, called
+ end
+
+ define_method( "test_execute_batch_empty" ) do
+ assert_nothing_raised { @db.execute_batch "" }
+ end
+
+ define_method( "test_execute_batch_no_bind" ) do
+ @db.transaction do
+ @db.execute_batch <<-SQL
+ create table bar ( a, b, c );
+ insert into bar values ( 'one', 2, 'three' );
+ insert into bar values ( 'four', 5, 'six' );
+ insert into bar values ( 'seven', 8, 'nine' );
+ SQL
+ end
+ rows = @db.execute( "select * from bar" )
+ assert_equal 3, rows.length
+ end
+
+ define_method( "test_execute_batch_with_bind" ) do
+ @db.execute_batch( <<-SQL, 1 )
+ create table bar ( a, b, c );
+ insert into bar values ( 'one', 2, ? );
+ insert into bar values ( 'four', 5, ? );
+ insert into bar values ( 'seven', 8, ? );
+ SQL
+ rows = @db.execute( "select * from bar" ).map { |a,b,c| c }
+ assert_equal %w{1 1 1}, rows
+ end
+
+ define_method( "test_get_first_row_no_bind_no_match" ) do
+ result = @db.get_first_row( "select * from foo where a=100" )
+ assert_nil result
+ end
+
+ define_method( "test_get_first_row_no_bind_with_match" ) do
+ result = @db.get_first_row( "select * from foo where a=1" )
+ assert_equal [ "1", "foo" ], result
+ end
+
+ define_method( "test_get_first_row_with_bind_no_match" ) do
+ result = @db.get_first_row( "select * from foo where a=?", 100 )
+ assert_nil result
+ end
+
+ define_method( "test_get_first_row_with_bind_with_match" ) do
+ result = @db.get_first_row( "select * from foo where a=?", 1 )
+ assert_equal [ "1", "foo" ], result
+ end
+
+ define_method( "test_get_first_value_no_bind_no_match" ) do
+ result = @db.get_first_value( "select b, a from foo where a=100" )
+ assert_nil result
+ end
+
+ define_method( "test_get_first_value_no_bind_with_match" ) do
+ result = @db.get_first_value( "select b, a from foo where a=1" )
+ assert_equal "foo", result
+ end
+
+ define_method( "test_get_first_value_with_bind_no_match" ) do
+ result = @db.get_first_value( "select b, a from foo where a=?", 100 )
+ assert_nil result
+ end
+
+ define_method( "test_get_first_value_with_bind_with_match" ) do
+ result = @db.get_first_value( "select b, a from foo where a=?", 1 )
+ assert_equal "foo", result
+ end
+
+ define_method( "test_last_insert_row_id" ) do
+ @db.execute "insert into foo ( b ) values ( 'test' )"
+ assert_equal 4, @db.last_insert_row_id
+ @db.execute "insert into foo ( b ) values ( 'again' )"
+ assert_equal 5, @db.last_insert_row_id
+ end
+
+ define_method( "test_changes" ) do
+ @db.execute "insert into foo ( b ) values ( 'test' )"
+ assert_equal 1, @db.changes
+ @db.execute "delete from foo where 1=1"
+ assert_equal 4, @db.changes
+ end
+
+ define_method( "test_total_changes" ) do
+ assert_equal 3, @db.total_changes
+ @db.execute "insert into foo ( b ) values ( 'test' )"
+ @db.execute "delete from foo where 1=1"
+ assert_equal 8, @db.total_changes
+ end
+
+ define_method( "test_transaction_nest" ) do
+ assert_raise( SQLite3::SQLException ) do
+ @db.transaction do
+ @db.transaction do
+ end
+ end
+ end
+ end
+
+ define_method( "test_transaction_rollback" ) do
+ @db.transaction
+ @db.execute_batch <<-SQL
+ insert into foo (b) values ( 'test1' );
+ insert into foo (b) values ( 'test2' );
+ insert into foo (b) values ( 'test3' );
+ insert into foo (b) values ( 'test4' );
+ SQL
+ assert_equal 7, @db.get_first_value("select count(*) from foo").to_i
+ @db.rollback
+ assert_equal 3, @db.get_first_value("select count(*) from foo").to_i
+ end
+
+ define_method( "test_transaction_commit" ) do
+ @db.transaction
+ @db.execute_batch <<-SQL
+ insert into foo (b) values ( 'test1' );
+ insert into foo (b) values ( 'test2' );
+ insert into foo (b) values ( 'test3' );
+ insert into foo (b) values ( 'test4' );
+ SQL
+ assert_equal 7, @db.get_first_value("select count(*) from foo").to_i
+ @db.commit
+ assert_equal 7, @db.get_first_value("select count(*) from foo").to_i
+ end
+
+ define_method( "test_transaction_rollback_in_block" ) do
+ assert_raise( SQLite3::SQLException ) do
+ @db.transaction do
+ @db.rollback
+ end
+ end
+ end
+
+ define_method( "test_transaction_commit_in_block" ) do
+ assert_raise( SQLite3::SQLException ) do
+ @db.transaction do
+ @db.commit
+ end
+ end
+ end
+
+ define_method( "test_transaction_active" ) do
+ assert !@db.transaction_active?
+ @db.transaction
+ assert @db.transaction_active?
+ @db.commit
+ assert !@db.transaction_active?
+ end
+
+ define_method( "no_tests_at" ) do |file,line,method|
+ warn "[(#{self.class}):#{file}:#{line}] no tests for #{method}"
+ end
+
+ define_method( "test_interrupt" ) do
+ @db.create_function( "abort", 1 ) do |func,x|
+ @db.interrupt
+ func.result = x
+ end
+
+ assert_raise( SQLite3::SQLException ) do
+ @db.execute "select abort(a) from foo"
+ end
+ end
+
+ define_method( "test_busy_handler_outwait" ) do
+ begin
+ db2 = SQLite3::Database.open( "test.db", :driver=>driver )
+ handler_call_count = 0
+ db2.busy_handler do |data,count|
+ handler_call_count += 1
+ sleep 0.1
+ 1
+ end
+
+ t = Thread.new do
+ @db.transaction( :exclusive ) do
+ sleep 0.1
+ end
+ end
+
+ assert_nothing_raised do
+ db2.execute "insert into foo (b) values ( 'from 2' )"
+ end
+
+ assert_equal 1, handler_call_count
+
+ t.join
+ ensure
+ db2.close if db2
+ end
+ end
+
+ define_method( "test_busy_handler_impatient" ) do
+ begin
+ db2 = SQLite3::Database.open( "test.db", :driver=>driver )
+ handler_call_count = 0
+ db2.busy_handler do |data,count|
+ handler_call_count += 1
+ sleep 0.1
+ 0
+ end
+
+ t = Thread.new do
+ @db.transaction( :exclusive ) do
+ sleep 0.2
+ end
+ end
+
+ assert_raise( SQLite3::BusyException ) do
+ db2.execute "insert into foo (b) values ( 'from 2' )"
+ end
+
+ assert_equal 1, handler_call_count
+
+ t.join
+ ensure
+ db2.close if db2
+ end
+ end
+
+ define_method( "test_busy_timeout" ) do
+ begin
+ db2 = SQLite3::Database.open( "test.db", :driver=>driver )
+ db2.busy_timeout 300
+
+ t = Thread.new do
+ @db.transaction( :exclusive ) do
+ sleep 0.1
+ end
+ end
+
+ time = Benchmark.measure do
+ assert_raise( SQLite3::BusyException ) do
+ db2.execute "insert into foo (b) values ( 'from 2' )"
+ end
+ end
+ assert time.real*1000 >= 300
+
+ t.join
+ ensure
+ db2.close if db2
+ end
+ end
+
+ define_method( "test_create_function" ) do
+ @db.create_function( "munge", 1 ) do |func,x|
+ func.result = ">>>#{x}<<<"
+ end
+
+ value = @db.get_first_value( "select munge(b) from foo where a=1" )
+ assert_match( />>>.*<<</, value )
+ end
+
+ define_method( "test_create_aggregate_without_block" ) do
+ step = proc do |ctx,a|
+ ctx[:sum] ||= 0
+ ctx[:sum] += a.to_i
+ end
+
+ final = proc { |ctx| ctx.result = ctx[:sum] }
+
+ @db.create_aggregate( "accumulate", 1, step, final )
+
+ value = @db.get_first_value( "select accumulate(a) from foo" )
+ assert_equal "6", value
+ end
+
+ define_method( "test_create_aggregate_with_block" ) do
+ @db.create_aggregate( "accumulate", 1 ) do
+ step do |ctx,a|
+ ctx[:sum] ||= 0
+ ctx[:sum] += a.to_i
+ end
+
+ finalize { |ctx| ctx.result = ctx[:sum] }
+ end
+
+ value = @db.get_first_value( "select accumulate(a) from foo" )
+ assert_equal "6", value
+ end
+
+ define_method( "test_create_aggregate_with_no_data" ) do
+ @db.create_aggregate( "accumulate", 1 ) do
+ step do |ctx,a|
+ ctx[:sum] ||= 0
+ ctx[:sum] += a.to_i
+ end
+
+ finalize { |ctx| ctx.result = ctx[:sum] || 0 }
+ end
+
+ value = @db.get_first_value(
+ "select accumulate(a) from foo where a = 100" )
+ assert_equal "0", value
+ end
+
+ define_method( "test_create_aggregate_handler" ) do
+ handler = Class.new do
+ class << self
+ define_method( "arity" ) { 1 }
+ define_method( "text_rep" ) { SQLite3::Constants::TextRep::ANY }
+ define_method( "name" ) { "multiply" }
+ end
+ define_method( "step" ) do |ctx,a|
+ ctx[:buffer] ||= 1
+ ctx[:buffer] *= a.to_i
+ end
+ define_method( "finalize" ) { |ctx| ctx.result = ctx[:buffer] }
+ end
+
+ @db.create_aggregate_handler( handler )
+ value = @db.get_first_value( "select multiply(a) from foo" )
+ assert_equal "6", value
+ end
+ end
+ const_set( "TC_Database_#{driver}", test_case )
+
+ # == TC_Statement =========================================================
+
+ test_case = Class.new( Test::Unit::TestCase ) do
+ define_method( "setup" ) do
+ @db = SQLite3::Database.new( "test.db", :driver=>driver )
+ @db.transaction do
+ @db.execute "create table foo ( a integer primary key, b text )"
+ @db.execute "insert into foo ( b ) values ( 'foo' )"
+ @db.execute "insert into foo ( b ) values ( 'bar' )"
+ @db.execute "insert into foo ( b ) values ( 'baz' )"
+ end
+ @stmt = @db.prepare( "select * from foo where a in ( ?, :named )" )
+ end
+
+ define_method( "teardown" ) do
+ @stmt.close
+ @db.close
+ File.delete( "test.db" )
+ end
+
+ define_method( "test_remainder_empty" ) do
+ assert_equal "", @stmt.remainder
+ end
+
+ define_method( "test_remainder_nonempty" ) do
+ called = false
+ @db.prepare( "select * from foo;\n blah" ) do |stmt|
+ called = true
+ assert_equal "\n blah", stmt.remainder
+ end
+ assert called
+ end
+
+ define_method( "test_bind_params_empty" ) do
+ assert_nothing_raised { @stmt.bind_params }
+ assert @stmt.execute!.empty?
+ end
+
+ define_method( "test_bind_params_array" ) do
+ @stmt.bind_params 1, 2
+ assert_equal 2, @stmt.execute!.length
+ end
+
+ define_method( "test_bind_params_hash" ) do
+ @stmt.bind_params ":named" => 2
+ assert_equal 1, @stmt.execute!.length
+ end
+
+ define_method( "test_bind_params_mixed" ) do
+ @stmt.bind_params( 1, ":named" => 2 )
+ assert_equal 2, @stmt.execute!.length
+ end
+
+ define_method( "test_bind_param_by_index" ) do
+ @stmt.bind_params( 1, 2 )
+ assert_equal 2, @stmt.execute!.length
+ end
+
+ define_method( "test_bind_param_by_name_bad" ) do
+ assert_raise( SQLite3::Exception ) { @stmt.bind_param( "named", 2 ) }
+ end
+
+ define_method( "test_bind_param_by_name_good" ) do
+ @stmt.bind_param( ":named", 2 )
+ assert_equal 1, @stmt.execute!.length
+ end
+
+ define_method( "test_execute_no_bind_no_block" ) do
+ assert_instance_of SQLite3::ResultSet, @stmt.execute
+ end
+
+ define_method( "test_execute_with_bind_no_block" ) do
+ assert_instance_of SQLite3::ResultSet, @stmt.execute( 1, 2 )
+ end
+
+ define_method( "test_execute_no_bind_with_block" ) do
+ called = false
+ @stmt.execute { |row| called = true }
+ assert called
+ end
+
+ define_method( "test_execute_with_bind_with_block" ) do
+ called = 0
+ @stmt.execute( 1, 2 ) { |row| called += 1 }
+ assert_equal 1, called
+ end
+
+ define_method( "test_reexecute" ) do
+ r = @stmt.execute( 1, 2 )
+ assert_equal 2, r.to_a.length
+ assert_nothing_raised { r = @stmt.execute( 1, 2 ) }
+ assert_equal 2, r.to_a.length
+ end
+
+ define_method( "test_execute_bang_no_bind_no_block" ) do
+ assert @stmt.execute!.empty?
+ end
+
+ define_method( "test_execute_bang_with_bind_no_block" ) do
+ assert_equal 2, @stmt.execute!( 1, 2 ).length
+ end
+
+ define_method( "test_execute_bang_no_bind_with_block" ) do
+ called = 0
+ @stmt.execute! { |row| called += 1 }
+ assert_equal 0, called
+ end
+
+ define_method( "test_execute_bang_with_bind_with_block" ) do
+ called = 0
+ @stmt.execute!( 1, 2 ) { |row| called += 1 }
+ assert_equal 2, called
+ end
+
+ define_method( "test_columns" ) do
+ c1 = @stmt.columns
+ c2 = @stmt.columns
+ assert_same c1, c2
+ assert_equal 2, c1.length
+ end
+
+ define_method( "test_columns_computed" ) do
+ called = false
+ @db.prepare( "select count(*) from foo" ) do |stmt|
+ called = true
+ assert_equal [ "count(*)" ], stmt.columns
+ end
+ assert called
+ end
+
+ define_method( "test_types" ) do
+ t1 = @stmt.types
+ t2 = @stmt.types
+ assert_same t1, t2
+ assert_equal 2, t1.length
+ end
+
+ define_method( "test_types_computed" ) do
+ called = false
+ @db.prepare( "select count(*) from foo" ) do |stmt|
+ called = true
+ assert_equal [ nil ], stmt.types
+ end
+ assert called
+ end
+ end
+ const_set( "TC_Statement_#{driver}", test_case )
+
+ # == TC_ResultSet =========================================================
+
+ test_case = Class.new( Test::Unit::TestCase ) do
+ define_method( "setup" ) do
+ @db = SQLite3::Database.new( "test.db", :driver=>driver )
+ @db.transaction do
+ @db.execute "create table foo ( a integer primary key, b text )"
+ @db.execute "insert into foo ( b ) values ( 'foo' )"
+ @db.execute "insert into foo ( b ) values ( 'bar' )"
+ @db.execute "insert into foo ( b ) values ( 'baz' )"
+ end
+ @stmt = @db.prepare( "select * from foo where a in ( ?, ? )" )
+ @result = @stmt.execute
+ end
+
+ define_method( "teardown" ) do
+ @stmt.close
+ @db.close
+ File.delete( "test.db" )
+ end
+
+ define_method( "test_reset_unused" ) do
+ assert_nothing_raised { @result.reset }
+ assert @result.to_a.empty?
+ end
+
+ define_method( "test_reset_used" ) do
+ @result.to_a
+ assert_nothing_raised { @result.reset }
+ assert @result.to_a.empty?
+ end
+
+ define_method( "test_reset_with_bind" ) do
+ @result.to_a
+ assert_nothing_raised { @result.reset( 1, 2 ) }
+ assert_equal 2, @result.to_a.length
+ end
+
+ define_method( "test_eof_inner" ) do
+ @result.reset( 1 )
+ assert !@result.eof?
+ end
+
+ define_method( "test_eof_edge" ) do
+ @result.reset( 1 )
+ @result.next # to first row
+ @result.next # to end of result set
+ assert @result.eof?
+ end
+
+ define_method( "test_next_eof" ) do
+ @result.reset( 1 )
+ assert_not_nil @result.next
+ assert_nil @result.next
+ end
+
+ define_method( "test_next_no_type_translation_no_hash" ) do
+ @result.reset( 1 )
+ assert_equal [ "1", "foo" ], @result.next
+ end
+
+ define_method( "test_next_type_translation" ) do
+ @db.type_translation = true
+ @result.reset( 1 )
+ assert_equal [ 1, "foo" ], @result.next
+ end
+
+ define_method( "test_next_results_as_hash" ) do
+ @db.results_as_hash = true
+ @result.reset( 1 )
+ assert_equal( { "a" => "1", "b" => "foo", 0 => "1", 1 => "foo" },
+ @result.next )
+ end
+
+ define_method( "test_each" ) do
+ called = 0
+ @result.reset( 1, 2 )
+ @result.each { |row| called += 1 }
+ assert_equal 2, called
+ end
+
+ define_method( "test_enumerable" ) do
+ @result.reset( 1, 2 )
+ assert_equal 2, @result.to_a.length
+ end
+
+ define_method( "test_types" ) do
+ assert_equal [ "integer", "text" ], @result.types
+ end
+
+ define_method( "test_columns" ) do
+ assert_equal [ "a", "b" ], @result.columns
+ end
+ end
+ const_set( "TC_ResultSet_#{driver}", test_case )
+ end
+
+end
diff --git a/test/tests.rb b/test/tests.rb
new file mode 100644
index 0000000..3bded2c
--- /dev/null
+++ b/test/tests.rb
@@ -0,0 +1,36 @@
+#--
+# =============================================================================
+# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# * The names of its contributors may not be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# =============================================================================
+#++
+
+
+Dir.chdir File.dirname( __FILE__ )
+Dir["**/tc_*.rb"].each { |file| load file }