File: command_spec.rb

package info (click to toggle)
libdataobjects-ruby 0.10.2-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 336 kB
  • ctags: 200
  • sloc: ruby: 2,729; makefile: 2
file content (229 lines) | stat: -rw-r--r-- 6,829 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
WINDOWS = Gem.win_platform? || (JRUBY && ENV_JAVA['os.name'] =~ /windows/i)

shared 'a Command' do

  setup_test_environment

  before do
    @connection = DataObjects::Connection.new(CONFIG.uri)
    @command    = @connection.create_command("INSERT INTO users (name) VALUES (?)")
    @reader     = @connection.create_command("SELECT code, name FROM widgets WHERE ad_description = ?")
  end

  after do
    @connection.close
  end

  it 'should be a kind of Command' do @command.should.be.kind_of(DataObjects::Command) end

  it 'should respond to #execute_non_query' do @command.should.respond_to(:execute_non_query) end

  describe 'execute_non_query' do

    describe 'with an invalid statement' do

      before do
        @invalid_command = @connection.create_command("INSERT INTO non_existent_table (tester) VALUES (1)")
      end

      it 'should raise an error on an invalid query' do
        should.raise(DataObjects::SQLError) { @invalid_command.execute_non_query }
      end

      it 'should raise an error with too few binding parameters' do
        lambda { @command.execute_non_query("Too", "Many") }.should.raise(ArgumentError).
          message.should.match(/Binding mismatch: 2 for 1/)
      end

      it 'should raise an error with too many binding parameters' do
        lambda { @command.execute_non_query }.should.raise(ArgumentError).
          message.should.match(/Binding mismatch: 0 for 1/)
      end

    end

    describe 'with a valid statement' do

      it 'should not raise an error with an explicit nil as parameter' do
        should.not.raise(ArgumentError) { @command.execute_non_query(nil) }
      end

    end

    describe 'with a valid statement and ? inside quotes' do

      before do
        @command_with_quotes = @connection.create_command("INSERT INTO users (name) VALUES ('will it work? ')")
      end

      it 'should not raise an error' do
        should.not.raise(ArgumentError) { @command_with_quotes.execute_non_query }
      end

    end

  end

  it 'should respond to #execute_reader' do @command.should.respond_to(:execute_reader) end

  describe 'execute_reader' do

    describe 'with an invalid reader' do

      before do
        @invalid_reader = @connection.create_command("SELECT * FROM non_existent_widgets WHERE ad_description = ?")
      end

      it 'should raise an error on an invalid query' do
        # FIXME JRuby (and MRI): Should this be an ArgumentError or DataObjects::SQLError?
        should.raise(ArgumentError, DataObjects::SQLError) { @invalid_reader.execute_reader }
      end

      it 'should raise an error with too few binding parameters' do
        lambda { @reader.execute_reader("Too", "Many") }.should.raise(ArgumentError).
          message.should.match(/Binding mismatch: 2 for 1/)
      end

      it 'should raise an error with too many binding parameters' do
        lambda { @reader.execute_reader }.should.raise(ArgumentError).
          message.should.match(/Binding mismatch: 0 for 1/)
      end

    end

    describe 'with a valid reader' do

      it 'should not raise an error with an explicit nil as parameter' do
        should.not.raise(ArgumentError) { @reader.execute_reader(nil) }
      end

    end

    describe 'with a valid reader and ? inside column alias' do

      before do
        @reader_with_quotes = @connection.create_command("SELECT code AS \"code?\", name FROM widgets WHERE ad_description = ?")
      end

      it 'should not raise an error' do
        should.not.raise(ArgumentError) { @reader_with_quotes.execute_reader(nil) }
      end

    end


  end

  it 'should respond to #set_types' do @command.should.respond_to(:set_types) end

  describe 'set_types' do

    describe 'is invalid when used with a statement' do

      before do
        @command.set_types(String)
      end

      it 'should raise an error when types are set' do
        should.raise(ArgumentError) { @command.execute_non_query }
      end

    end

    describe 'with an invalid reader' do

      it 'should raise an error with too few types' do
        @reader.set_types(String)
        lambda { @reader.execute_reader("One parameter") }.should.raise(ArgumentError).
          message.should.match(/Field-count mismatch. Expected 1 fields, but the query yielded 2/)
      end

      it 'should raise an error with too many types' do
        @reader.set_types(String, String, BigDecimal)
        lambda { @reader.execute_reader("One parameter") }.should.raise(ArgumentError).
          message.should.match(/Field-count mismatch. Expected 3 fields, but the query yielded 2/)
      end

    end

    describe 'with a valid reader' do

      it 'should not raise an error with correct number of types' do
        @reader.set_types(String, String)
        should.not.raise(ArgumentError) { @result = @reader.execute_reader('Buy this product now!') }
        should.not.raise(DataObjects::SQLError) { @result.next! }
        should.not.raise(DataObjects::DataError) { @result.values }
        @result.close
      end

      it 'should also support old style array argument types' do
        @reader.set_types([String, String])
        should.not.raise(ArgumentError) { @result = @reader.execute_reader('Buy this product now!') }
        should.not.raise(DataObjects::DataError) { @result.next! }
        should.not.raise(DataObjects::DataError) { @result.values }
        @result.close
      end

      it 'should allow subtype types' do
        class MyString < String; end
        @reader.set_types(MyString, String)
        should.not.raise(ArgumentError) { @result = @reader.execute_reader('Buy this product now!') }
        should.not.raise(DataObjects::DataError) { @result.next! }
        should.not.raise(DataObjects::DataError) { @result.values }
        @result.close
      end
    end

  end

  it 'should respond to #to_s' do @command.should.respond_to(:to_s) end

  describe 'to_s' do

  end


end

shared 'a Command with async' do

  setup_test_environment

  describe 'running queries in parallel' do

    before do

      threads = []

      @start = Time.now
      4.times do |i|
        threads << Thread.new do
          connection = DataObjects::Connection.new(CONFIG.uri)
          command = connection.create_command(CONFIG.sleep)
          if CONFIG.sleep =~ /^SELECT/i
            reader = command.execute_reader
            reader.next!
            reader.close
          else
            result = command.execute_non_query
          end
          connection.close
        end
      end

      threads.each{|t| t.join }
      @finish = Time.now
    end

    after do
      @connection.close
    end

    it "should finish within 2 seconds" do
      pending_if("Ruby on Windows doesn't support asynchronous operations", WINDOWS) do
        (@finish - @start).should < 2
      end
    end

  end
end