2010-04-04 19:17:50 +00:00
# encoding: UTF-8
2010-07-06 22:41:44 +00:00
require 'spec_helper'
2010-04-04 19:17:50 +00:00
describe Mysql2 :: Client do
before ( :each ) do
@client = Mysql2 :: Client . new
end
2010-07-11 06:15:54 +00:00
if defined? Encoding
it " should raise an exception on create for invalid encodings " do
lambda {
c = Mysql2 :: Client . new ( :encoding = > " fake " )
} . should raise_error ( Mysql2 :: Error )
end
end
2010-08-20 16:56:36 +00:00
it " should accept connect flags and pass them to # connect " do
klient = Class . new ( Mysql2 :: Client ) do
attr_reader :connect_args
def connect * args
@connect_args || = [ ]
@connect_args << args
end
end
client = klient . new :flags = > Mysql2 :: Client :: FOUND_ROWS
client . connect_args . last . last . should == Mysql2 :: Client :: FOUND_ROWS
end
it " should default flags to 0 " do
klient = Class . new ( Mysql2 :: Client ) do
attr_reader :connect_args
def connect * args
@connect_args || = [ ]
@connect_args << args
end
end
client = klient . new
client . connect_args . last . last . should == 0
end
2010-08-02 03:20:48 +00:00
it " should have a global default_query_options hash " do
Mysql2 :: Client . should respond_to ( :default_query_options )
end
2010-04-06 05:47:16 +00:00
it " should be able to connect via SSL options " do
pending ( " DON'T WORRY, THIS TEST PASSES :) - but is machine-specific. You need to have MySQL running with SSL configured and enabled. Then update the paths in this test to your needs and remove the pending state. " )
ssl_client = nil
lambda {
ssl_client = Mysql2 :: Client . new (
:sslkey = > '/path/to/client-key.pem' ,
:sslcert = > '/path/to/client-cert.pem' ,
:sslca = > '/path/to/ca-cert.pem' ,
:sslcapath = > '/path/to/newcerts/' ,
:sslcipher = > 'DHE-RSA-AES256-SHA'
)
} . should_not raise_error ( Mysql2 :: Error )
results = ssl_client . query ( " SHOW STATUS WHERE Variable_name = \" Ssl_version \" OR Variable_name = \" Ssl_cipher \" " ) . to_a
results [ 0 ] [ 'Variable_name' ] . should eql ( 'Ssl_cipher' )
results [ 0 ] [ 'Value' ] . should_not be_nil
results [ 0 ] [ 'Value' ] . class . should eql ( String )
results [ 1 ] [ 'Variable_name' ] . should eql ( 'Ssl_version' )
results [ 1 ] [ 'Value' ] . should_not be_nil
results [ 1 ] [ 'Value' ] . class . should eql ( String )
end
2010-05-06 00:38:08 +00:00
it " should respond to # close " do
2010-07-30 06:22:42 +00:00
@client . should respond_to ( :close )
2010-05-06 00:38:08 +00:00
end
it " should be able to close properly " do
@client . close . should be_nil
end
2010-04-04 19:17:50 +00:00
it " should respond to # query " do
2010-07-30 06:22:42 +00:00
@client . should respond_to ( :query )
2010-04-04 19:17:50 +00:00
end
2010-08-02 03:20:48 +00:00
context " # query " do
it " should accept an options hash that inherits from Mysql2::Client.default_query_options " do
@client . query " SELECT 1 " , :something = > :else
@client . query_options . should eql ( @client . query_options . merge ( :something = > :else ) )
end
it " should return results as a hash by default " do
@client . query ( " SELECT 1 " ) . first . class . should eql ( Hash )
end
it " should be able to return results as an array " do
@client . query ( " SELECT 1 " , :as = > :array ) . first . class . should eql ( Array )
@client . query ( " SELECT 1 " ) . each ( :as = > :array )
end
it " should be able to return results with symbolized keys " do
@client . query ( " SELECT 1 " , :symbolize_keys = > true ) . first . keys [ 0 ] . class . should eql ( Symbol )
end
2010-08-04 03:37:49 +00:00
it " should not allow another query to be sent without fetching a result first " do
@client . query ( " SELECT 1 " , :async = > true )
lambda {
@client . query ( " SELECT 1 " )
} . should raise_error ( Mysql2 :: Error )
end
2010-08-19 02:06:05 +00:00
# XXX this test is not deterministic (because Unix signal handling is not)
# and may fail on a loaded system
it " should run signal handlers while waiting for a response " do
mark = { }
trap ( :USR1 ) { mark [ :USR1 ] = Time . now }
begin
mark [ :START ] = Time . now
pid = fork do
sleep 1 # wait for client "SELECT sleep(2)" query to start
Process . kill ( :USR1 , Process . ppid )
sleep # wait for explicit kill to prevent GC disconnect
end
@client . query ( " SELECT sleep(2) " )
mark [ :END ] = Time . now
mark . include? ( :USR1 ) . should be_true
( mark [ :USR1 ] - mark [ :START ] ) . should > = 1
( mark [ :USR1 ] - mark [ :START ] ) . should < 1 . 1
( mark [ :END ] - mark [ :USR1 ] ) . should > 0 . 9
( mark [ :END ] - mark [ :START ] ) . should > = 2
( mark [ :END ] - mark [ :START ] ) . should < 2 . 1
Process . kill ( :TERM , pid )
Process . waitpid2 ( pid )
ensure
trap ( :USR1 , 'DEFAULT' )
end
end if RUBY_PLATFORM !~ / mingw|mswin /
2010-08-02 03:20:48 +00:00
end
2010-04-04 19:17:50 +00:00
it " should respond to # escape " do
2010-07-30 06:22:42 +00:00
@client . should respond_to ( :escape )
2010-04-04 19:17:50 +00:00
end
it " # escape should return a new SQL-escape version of the passed string " do
@client . escape ( " abc'def \" ghi \0 jkl%mno " ) . should eql ( " abc \\ 'def \\ \" ghi \\ 0jkl%mno " )
end
it " # escape should return the passed string if nothing was escaped " do
str = " plain "
@client . escape ( str ) . object_id . should eql ( str . object_id )
end
it " should respond to # info " do
2010-07-30 06:22:42 +00:00
@client . should respond_to ( :info )
2010-04-04 19:17:50 +00:00
end
it " # info should return a hash containing the client version ID and String " do
info = @client . info
info . class . should eql ( Hash )
info . should have_key ( :id )
info [ :id ] . class . should eql ( Fixnum )
info . should have_key ( :version )
info [ :version ] . class . should eql ( String )
end
2010-07-09 05:22:20 +00:00
if defined? Encoding
2010-06-15 01:14:28 +00:00
context " strings returned by # info " do
2010-07-09 05:22:20 +00:00
it " should default to the connection's encoding if Encoding.default_internal is nil " do
2010-06-15 01:14:28 +00:00
Encoding . default_internal = nil
@client . info [ :version ] . encoding . should eql ( Encoding . find ( 'utf-8' ) )
2010-07-09 05:22:20 +00:00
client2 = Mysql2 :: Client . new :encoding = > 'ascii'
client2 . info [ :version ] . encoding . should eql ( Encoding . find ( 'us-ascii' ) )
2010-06-15 01:14:28 +00:00
end
it " should use Encoding.default_internal " do
Encoding . default_internal = Encoding . find ( 'utf-8' )
@client . info [ :version ] . encoding . should eql ( Encoding . default_internal )
Encoding . default_internal = Encoding . find ( 'us-ascii' )
@client . info [ :version ] . encoding . should eql ( Encoding . default_internal )
end
end
end
2010-04-04 19:17:50 +00:00
it " should respond to # server_info " do
2010-07-30 06:22:42 +00:00
@client . should respond_to ( :server_info )
2010-04-04 19:17:50 +00:00
end
it " # server_info should return a hash containing the client version ID and String " do
server_info = @client . server_info
server_info . class . should eql ( Hash )
server_info . should have_key ( :id )
server_info [ :id ] . class . should eql ( Fixnum )
server_info . should have_key ( :version )
server_info [ :version ] . class . should eql ( String )
end
2010-04-05 06:31:32 +00:00
2010-07-09 05:22:20 +00:00
if defined? Encoding
2010-06-15 01:14:28 +00:00
context " strings returned by # server_info " do
2010-07-09 05:22:20 +00:00
it " should default to the connection's encoding if Encoding.default_internal is nil " do
2010-06-15 01:14:28 +00:00
Encoding . default_internal = nil
@client . server_info [ :version ] . encoding . should eql ( Encoding . find ( 'utf-8' ) )
2010-07-09 05:22:20 +00:00
client2 = Mysql2 :: Client . new :encoding = > 'ascii'
client2 . server_info [ :version ] . encoding . should eql ( Encoding . find ( 'us-ascii' ) )
2010-06-15 01:14:28 +00:00
end
it " should use Encoding.default_internal " do
Encoding . default_internal = Encoding . find ( 'utf-8' )
@client . server_info [ :version ] . encoding . should eql ( Encoding . default_internal )
Encoding . default_internal = Encoding . find ( 'us-ascii' )
@client . server_info [ :version ] . encoding . should eql ( Encoding . default_internal )
end
end
end
2010-04-05 06:31:32 +00:00
it " should respond to # socket " do
2010-07-30 06:22:42 +00:00
@client . should respond_to ( :socket )
2010-04-05 06:31:32 +00:00
end
it " # socket should return a Fixnum (file descriptor from C) " do
@client . socket . class . should eql ( Fixnum )
@client . socket . should_not eql ( 0 )
end
2010-04-05 06:46:42 +00:00
it " should raise a Mysql2::Error exception upon connection failure " do
lambda {
bad_client = Mysql2 :: Client . new :host = > " dfjhdi9wrhw " , :username = > 'asdfasdf8d2h'
} . should raise_error ( Mysql2 :: Error )
lambda {
good_client = Mysql2 :: Client . new
} . should_not raise_error ( Mysql2 :: Error )
end
2010-04-07 16:16:30 +00:00
2010-08-07 20:52:46 +00:00
it " threaded queries should be supported " do
threads , results = [ ] , { }
connect = lambda { Mysql2 :: Client . new ( :host = > " localhost " , :username = > " root " ) }
Timeout . timeout ( 0 . 7 ) do
5 . times {
threads << Thread . new do
results [ Thread . current . object_id ] = connect . call . query ( " SELECT sleep(0.5) as result " )
end
}
end
threads . each { | t | t . join }
results . keys . sort . should eql ( threads . map { | t | t . object_id } . sort )
end
2010-04-07 16:16:30 +00:00
it " evented async queries should be supported " do
# should immediately return nil
@client . query ( " SELECT sleep(0.1) " , :async = > true ) . should eql ( nil )
io_wrapper = IO . for_fd ( @client . socket )
loops = 0
loop do
if IO . select ( [ io_wrapper ] , nil , nil , 0 . 05 )
break
else
loops += 1
end
end
# make sure we waited some period of time
( loops > = 1 ) . should be_true
result = @client . async_result
result . class . should eql ( Mysql2 :: Result )
end
2010-04-07 16:36:36 +00:00
2010-04-07 16:47:45 +00:00
context 'write operations api' do
before ( :each ) do
@client . query " USE test "
@client . query " CREATE TABLE lastIdTest (`id` int(11) NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`)) "
end
after ( :each ) do
@client . query " DROP TABLE lastIdTest "
end
it " should respond to # last_id " do
@client . should respond_to ( :last_id )
end
it " # last_id should return a Fixnum, the from the last INSERT/UPDATE " do
@client . last_id . should eql ( 0 )
@client . query " INSERT INTO lastIdTest (blah) VALUES (1234) "
@client . last_id . should eql ( 1 )
end
it " should respond to # last_id " do
@client . should respond_to ( :last_id )
end
it " # last_id should return a Fixnum, the from the last INSERT/UPDATE " do
@client . query " INSERT INTO lastIdTest (blah) VALUES (1234) "
@client . affected_rows . should eql ( 1 )
@client . query " UPDATE lastIdTest SET blah=4321 WHERE id=1 "
@client . affected_rows . should eql ( 1 )
end
2010-04-07 16:36:36 +00:00
end
2010-07-06 22:41:44 +00:00
end