data_objects 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/ChangeLog.markdown +20 -0
  2. data/LICENSE +1 -29
  3. data/README.markdown +16 -2
  4. data/Rakefile +41 -7
  5. data/lib/data_objects.rb +3 -2
  6. data/lib/data_objects/byte_array.rb +6 -0
  7. data/lib/data_objects/connection.rb +21 -9
  8. data/lib/data_objects/logger.rb +15 -15
  9. data/lib/data_objects/pooling.rb +250 -0
  10. data/lib/data_objects/reader.rb +16 -0
  11. data/lib/data_objects/spec/bacon.rb +9 -0
  12. data/lib/data_objects/spec/command_spec.rb +54 -47
  13. data/lib/data_objects/spec/connection_spec.rb +119 -30
  14. data/lib/data_objects/spec/encoding_spec.rb +64 -6
  15. data/lib/data_objects/spec/helpers/immediate_red_green_output.rb +59 -0
  16. data/lib/data_objects/spec/helpers/pending.rb +22 -0
  17. data/lib/data_objects/spec/helpers/ssl.rb +21 -0
  18. data/lib/data_objects/spec/reader_spec.rb +47 -24
  19. data/lib/data_objects/spec/result_spec.rb +10 -19
  20. data/lib/data_objects/spec/typecast/array_spec.rb +16 -20
  21. data/lib/data_objects/spec/typecast/bigdecimal_spec.rb +16 -24
  22. data/lib/data_objects/spec/typecast/boolean_spec.rb +16 -24
  23. data/lib/data_objects/spec/typecast/byte_array_spec.rb +11 -15
  24. data/lib/data_objects/spec/typecast/class_spec.rb +7 -11
  25. data/lib/data_objects/spec/typecast/date_spec.rb +17 -25
  26. data/lib/data_objects/spec/typecast/datetime_spec.rb +18 -26
  27. data/lib/data_objects/spec/typecast/float_spec.rb +19 -27
  28. data/lib/data_objects/spec/typecast/integer_spec.rb +10 -14
  29. data/lib/data_objects/spec/typecast/nil_spec.rb +18 -30
  30. data/lib/data_objects/spec/typecast/other_spec.rb +45 -0
  31. data/lib/data_objects/spec/typecast/range_spec.rb +16 -20
  32. data/lib/data_objects/spec/typecast/string_spec.rb +72 -13
  33. data/lib/data_objects/spec/typecast/time_spec.rb +11 -15
  34. data/lib/data_objects/utilities.rb +18 -0
  35. data/lib/data_objects/version.rb +1 -2
  36. data/spec/command_spec.rb +2 -2
  37. data/spec/connection_spec.rb +7 -5
  38. data/spec/do_mock2.rb +31 -0
  39. data/spec/pooling_spec.rb +162 -0
  40. data/spec/reader_spec.rb +7 -4
  41. data/spec/result_spec.rb +2 -2
  42. data/spec/spec_helper.rb +26 -5
  43. data/spec/transaction_spec.rb +11 -9
  44. data/tasks/metrics.rake +36 -0
  45. data/tasks/release.rake +10 -70
  46. data/tasks/spec.rake +16 -14
  47. data/tasks/yard.rake +9 -0
  48. data/tasks/yardstick.rake +19 -0
  49. metadata +53 -27
  50. data/HISTORY.markdown +0 -7
  51. data/Manifest.txt +0 -44
  52. data/spec/lib/pending_helpers.rb +0 -11
  53. data/spec/lib/rspec_immediate_feedback_formatter.rb +0 -53
  54. data/spec/lib/ssl_helpers.rb +0 -20
  55. data/tasks/gem.rake +0 -8
  56. data/tasks/install.rake +0 -13
@@ -1,15 +1,15 @@
1
- share_examples_for 'a driver supporting encodings' do
1
+ shared 'a driver supporting different encodings' do
2
2
 
3
- before :each do
3
+ before do
4
4
  @connection = DataObjects::Connection.new(CONFIG.uri)
5
5
  end
6
6
 
7
- after :each do
7
+ after do
8
8
  @connection.close
9
9
  end
10
10
 
11
11
 
12
- it { @connection.should respond_to(:character_set) }
12
+ it 'should respond to #character_set' do @connection.should.respond_to(:character_set) end
13
13
 
14
14
  describe 'character_set' do
15
15
 
@@ -25,7 +25,9 @@ share_examples_for 'a driver supporting encodings' do
25
25
 
26
26
  after { @latin1_connection.close }
27
27
 
28
- it { @latin1_connection.character_set.should == 'ISO-8859-1' }
28
+ it 'the character set should be ISO-8859-1' do
29
+ @latin1_connection.character_set.should == 'ISO-8859-1'
30
+ end
29
31
  end
30
32
 
31
33
  describe 'uses UTF-8 when an invalid encoding is given' do
@@ -35,9 +37,65 @@ share_examples_for 'a driver supporting encodings' do
35
37
 
36
38
  after { @latin1_connection.close }
37
39
 
38
- it { @latin1_connection.character_set.should == 'UTF-8' }
40
+ it 'the character set should be UTF-8' do
41
+ @latin1_connection.character_set.should == 'UTF-8'
42
+ end
39
43
  end
44
+ end
45
+ end
46
+
47
+ shared 'returning correctly encoded strings for the default encoding' do
48
+
49
+
50
+ setup_test_environment
51
+
52
+ before do
53
+ @connection = DataObjects::Connection.new(CONFIG.uri)
54
+ end
55
+
56
+ after do
57
+ @connection.close
58
+ end
59
+
60
+ if defined?(::Encoding)
61
+ describe 'with encoded string support' do
40
62
 
63
+ describe 'reading a String' do
64
+ before do
65
+ @reader = @connection.create_command("SELECT name FROM widgets WHERE ad_description = ?").execute_reader('Buy this product now!')
66
+ @reader.next!
67
+ @values = @reader.values
68
+ end
69
+
70
+ after do
71
+ @reader.close
72
+ end
73
+
74
+ it 'should return UTF-8 encoded String' do
75
+ @values.first.should.be.kind_of(String)
76
+ @values.first.encoding.name.should == 'UTF-8'
77
+ end
78
+ end
41
79
 
80
+ describe 'reading a ByteArray' do
81
+ before do
82
+ @command = @connection.create_command("SELECT ad_image FROM widgets WHERE ad_description = ?")
83
+ @command.set_types(Extlib::ByteArray)
84
+ @reader = @command.execute_reader('Buy this product now!')
85
+ @reader.next!
86
+ @values = @reader.values
87
+ end
88
+
89
+ after do
90
+ @reader.close
91
+ end
92
+
93
+ it 'should return ASCII-8BIT encoded ByteArray' do
94
+ @values.first.should.be.kind_of(::Extlib::ByteArray)
95
+ @values.first.encoding.name.should == 'ASCII-8BIT'
96
+ end
97
+ end
98
+ end
42
99
  end
100
+
43
101
  end
@@ -0,0 +1,59 @@
1
+ module Bacon
2
+ module ImmediateRedGreenOutput
3
+
4
+ def handle_specification(name)
5
+ yield
6
+ @current_group = name
7
+ end
8
+
9
+ def handle_requirement(description)
10
+ error = yield
11
+ if error.empty?
12
+ example_passed
13
+ elsif error == 'PENDING'
14
+ example_pending
15
+ else
16
+ example_failed(error, description, Counter[:specifications])
17
+ end
18
+ end
19
+
20
+ def handle_summary
21
+ puts
22
+ puts ErrorLog
23
+ counter = Counter.values_at(:specifications, :requirements, :failed, :errors, :pending)
24
+ message = ("%d tests, %d assertions, %d failures, %d errors, %d pending" % counter)
25
+ color = (counter[2].to_i != 0 || counter[3].to_i != 0 ? :red : (counter[4].to_i != 0 ? :yellow : :green))
26
+ puts self.send(color, message)
27
+ end
28
+
29
+ private
30
+
31
+ def example_failed(error, description, counter)
32
+ if @current_group
33
+ puts
34
+ puts @current_group
35
+ @current_group = nil # only print the group name once
36
+ end
37
+
38
+ if error == 'FAILED'
39
+ puts red("- #{description} (FAILED - #{counter})")
40
+ puts ErrorLog if Backtraces # dump stacktrace immediately
41
+ else
42
+ puts red("- #{description} (ERROR - #{counter})")
43
+ end
44
+ end
45
+
46
+ def example_passed
47
+ print green('.')
48
+ end
49
+
50
+ def example_pending
51
+ print yellow('*')
52
+ end
53
+
54
+ def red(s) "\e[31m#{s}\e[0m"; end
55
+ def green(s) "\e[32m#{s}\e[0m"; end
56
+ def yellow(s) "\e[33m#{s}\e[0m"; end
57
+
58
+ end
59
+ end
@@ -0,0 +1,22 @@
1
+ module DataObjects::Spec
2
+ module Pending
3
+
4
+ def pending(message = '')
5
+ raise Bacon::Error.new(:pending, message)
6
+ end
7
+
8
+ def pending_if(message, boolean)
9
+ if boolean
10
+ pending(message) { yield }
11
+ else
12
+ yield
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ module Bacon
19
+ class Context
20
+ include DataObjects::Spec::Pending
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'pathname'
2
+ require 'cgi'
3
+
4
+ module SSLHelpers
5
+
6
+ CERTS_DIR = Pathname(__FILE__).dirname.join('ssl_certs').to_s
7
+
8
+ CONFIG = OpenStruct.new
9
+ CONFIG.ca_cert = File.join(CERTS_DIR, 'ca-cert.pem')
10
+ CONFIG.ca_key = File.join(CERTS_DIR, 'ca-key.pem')
11
+ CONFIG.server_cert = File.join(CERTS_DIR, 'server-cert.pem')
12
+ CONFIG.server_key = File.join(CERTS_DIR, 'server-key.pem')
13
+ CONFIG.client_cert = File.join(CERTS_DIR, 'client-cert.pem')
14
+ CONFIG.client_key = File.join(CERTS_DIR, 'client-key.pem')
15
+ CONFIG.cipher = 'AES128-SHA'
16
+
17
+ def self.query(*keys)
18
+ keys.map { |key| "ssl[#{key}]=#{CGI::escape(CONFIG.send(key))}" }.join('&')
19
+ end
20
+
21
+ end
@@ -1,22 +1,18 @@
1
- share_examples_for 'a Reader' do
1
+ shared 'a Reader' do
2
2
 
3
- include DataObjectsSpecHelpers
3
+ setup_test_environment
4
4
 
5
- before :all do
6
- setup_test_environment
7
- end
8
-
9
- before :each do
5
+ before do
10
6
  @connection = DataObjects::Connection.new(CONFIG.uri)
11
7
  @reader = @connection.create_command("SELECT code, name FROM widgets WHERE ad_description = ? order by id").execute_reader('Buy this product now!')
12
8
  end
13
9
 
14
- after :each do
10
+ after do
15
11
  @reader.close
16
12
  @connection.close
17
13
  end
18
14
 
19
- it { @reader.should respond_to(:fields) }
15
+ it 'should respond to #fields' do @reader.should.respond_to(:fields) end
20
16
 
21
17
  describe 'fields' do
22
18
 
@@ -28,21 +24,21 @@ share_examples_for 'a Reader' do
28
24
 
29
25
  end
30
26
 
31
- it { @reader.should respond_to(:values) }
27
+ it 'should respond to #values' do @reader.should.respond_to(:values) end
32
28
 
33
29
  describe 'values' do
34
30
 
35
31
  describe 'when the reader is uninitialized' do
36
32
 
37
33
  it 'should raise an error' do
38
- lambda { @reader.values }.should raise_error
34
+ should.raise(DataObjects::DataError) { @reader.values }
39
35
  end
40
36
 
41
37
  end
42
38
 
43
39
  describe 'when the reader is moved to the first result' do
44
40
 
45
- before do
41
+ before do
46
42
  @reader.next!
47
43
  end
48
44
 
@@ -54,7 +50,7 @@ share_examples_for 'a Reader' do
54
50
 
55
51
  describe 'when the reader is moved to the second result' do
56
52
 
57
- before do
53
+ before do
58
54
  @reader.next!; @reader.next!
59
55
  end
60
56
 
@@ -71,20 +67,20 @@ share_examples_for 'a Reader' do
71
67
  end
72
68
 
73
69
  it 'should raise an error again' do
74
- lambda { @reader.values }.should raise_error
70
+ should.raise(DataObjects::DataError) { @reader.values }
75
71
  end
76
72
  end
77
73
 
78
74
  end
79
75
 
80
- it { @reader.should respond_to(:close) }
76
+ it 'should respond to #close' do @reader.should.respond_to(:close) end
81
77
 
82
78
  describe 'close' do
83
79
 
84
80
  describe 'on an open reader' do
85
81
 
86
82
  it 'should return true' do
87
- @reader.close.should be_true
83
+ @reader.close.should.be.true
88
84
  end
89
85
 
90
86
  end
@@ -96,21 +92,21 @@ share_examples_for 'a Reader' do
96
92
  end
97
93
 
98
94
  it 'should return false' do
99
- @reader.close.should be_false
95
+ @reader.close.should.be.false
100
96
  end
101
97
 
102
98
  end
103
99
 
104
100
  end
105
101
 
106
- it { @reader.should respond_to(:next!) }
102
+ it 'should respond to #next!' do @reader.should.respond_to(:next!) end
107
103
 
108
104
  describe 'next!' do
109
105
 
110
106
  describe 'successfully moving the cursor initially' do
111
107
 
112
108
  it 'should return true' do
113
- @reader.next!.should be_true
109
+ @reader.next!.should.be.true
114
110
  end
115
111
 
116
112
  end
@@ -122,9 +118,9 @@ share_examples_for 'a Reader' do
122
118
  end
123
119
 
124
120
  it 'should move the cursor to the next value' do
125
- lambda { @reader.next! }.should change(@reader, :values).
126
- from(["W0000001", "Widget 1"]).
127
- to(["W0000002", "Widget 2"])
121
+ @reader.values.should == ["W0000001", "Widget 1"]
122
+ lambda { @reader.next! }.should.change { @reader.values }
123
+ @reader.values.should == ["W0000002", "Widget 2"]
128
124
  end
129
125
 
130
126
  end
@@ -136,14 +132,14 @@ share_examples_for 'a Reader' do
136
132
  end
137
133
 
138
134
  it 'should return false when the end is reached' do
139
- @reader.next!.should be_false
135
+ @reader.next!.should.be.false
140
136
  end
141
137
 
142
138
  end
143
139
 
144
140
  end
145
141
 
146
- it { @reader.should respond_to(:field_count) }
142
+ it 'should respond to #field_count' do @reader.should.respond_to(:field_count) end
147
143
 
148
144
  describe 'field_count' do
149
145
 
@@ -153,4 +149,31 @@ share_examples_for 'a Reader' do
153
149
 
154
150
  end
155
151
 
152
+ it 'should respond to #values' do @reader.should.respond_to(:values) end
153
+
154
+ describe 'each' do
155
+
156
+ it 'should yield each row to the block' do
157
+ rows_yielded = 0
158
+ @reader.each do |row|
159
+ row.should.respond_to(:[])
160
+
161
+ row.size.should == 2
162
+
163
+ # the field names need to be case insensitive as some drivers such as
164
+ # do_derby, do_h2, do_hsqldb return the field names as uppercase
165
+ (row['name'] || row['NAME']).should.be.kind_of(String)
166
+ (row['code'] || row['CODE']).should.be.kind_of(String)
167
+
168
+ rows_yielded += 1
169
+ end
170
+ rows_yielded.should == 15
171
+ end
172
+
173
+ it 'should return the reader' do
174
+ @reader.each { |row| }.should.equal(@reader)
175
+ end
176
+
177
+ end
178
+
156
179
  end
@@ -1,21 +1,17 @@
1
- share_examples_for 'a Result' do
1
+ shared 'a Result' do
2
2
 
3
- include DataObjectsSpecHelpers
3
+ setup_test_environment
4
4
 
5
- before :all do
6
- setup_test_environment
7
- end
8
-
9
- before :each do
5
+ before do
10
6
  @connection = DataObjects::Connection.new(CONFIG.uri)
11
7
  @result = @connection.create_command("INSERT INTO users (name) VALUES (?)").execute_non_query("monkey")
12
8
  end
13
9
 
14
- after :each do
10
+ after do
15
11
  @connection.close
16
12
  end
17
13
 
18
- it { @result.should respond_to(:affected_rows) }
14
+ it 'should respond to #affected_rows' do @result.should.respond_to(:affected_rows) end
19
15
 
20
16
  describe 'affected_rows' do
21
17
 
@@ -27,15 +23,10 @@ share_examples_for 'a Result' do
27
23
 
28
24
  end
29
25
 
30
- share_examples_for 'a Result which returns inserted keys' do
31
-
32
- include DataObjectsSpecHelpers
26
+ shared 'a Result which returns inserted keys' do
33
27
 
34
- before :all do
28
+ before do
35
29
  setup_test_environment
36
- end
37
-
38
- before :each do
39
30
  @connection = DataObjects::Connection.new(CONFIG.uri)
40
31
  command = @connection.create_command("INSERT INTO users (name) VALUES (?)")
41
32
  # execute the command twice and expose the second result
@@ -43,15 +34,15 @@ share_examples_for 'a Result which returns inserted keys' do
43
34
  @result = command.execute_non_query("monkey")
44
35
  end
45
36
 
46
- after :each do
37
+ after do
47
38
  @connection.close
48
39
  end
49
40
 
50
- it { @result.should respond_to(:affected_rows) }
41
+ it 'should respond to #affected_rows' do @result.should.respond_to(:affected_rows) end
51
42
 
52
43
  describe 'insert_id' do
53
44
 
54
- it 'should return the number of affected rows' do
45
+ it 'should return the insert_id' do
55
46
  # This is actually the 2nd record inserted
56
47
  @result.insert_id.should == 2
57
48
  end
@@ -1,36 +1,32 @@
1
- share_examples_for 'supporting Array' do
1
+ shared 'supporting Array' do
2
2
 
3
- include DataObjectsSpecHelpers
3
+ setup_test_environment
4
4
 
5
- before :all do
6
- setup_test_environment
7
- end
8
-
9
- before :each do
5
+ before do
10
6
  @connection = DataObjects::Connection.new(CONFIG.uri)
11
7
  end
12
8
 
13
- after :each do
9
+ after do
14
10
  @connection.close
15
11
  end
16
12
 
17
13
  describe 'passing an Array as a parameter in execute_reader' do
18
14
 
19
- before do
20
- @reader = @connection.create_command("SELECT * FROM widgets WHERE id in ?").execute_reader([2,3,4,5])
21
- end
15
+ before do
16
+ @reader = @connection.create_command("SELECT * FROM widgets WHERE id in ?").execute_reader([2,3,4,5])
17
+ end
22
18
 
23
- after do
24
- @reader.close
25
- end
19
+ after do
20
+ @reader.close
21
+ end
26
22
 
27
- it 'should return correct number of rows' do
28
- counter = 0
29
- while(@reader.next!) do
30
- counter += 1
31
- end
32
- counter.should == 4
23
+ it 'should return correct number of rows' do
24
+ counter = 0
25
+ while(@reader.next!) do
26
+ counter += 1
33
27
  end
28
+ counter.should == 4
29
+ end
34
30
 
35
31
  end
36
32
  end