~nvalcarcel/ubuntu/lucid/puppet/fix-546677

« back to all changes in this revision

Viewing changes to spec/unit/network/http/mongrel/rest.rb

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2009-12-23 00:48:10 UTC
  • mfrom: (1.1.10 upstream) (3.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091223004810-3i4oryds922g5n59
Tags: 0.25.1-3ubuntu1
* Merge from debian testing.  Remaining changes:
  - debian/rules:
    + Don't start puppet when first installing puppet.
  - debian/puppet.conf, lib/puppet/defaults.rb:
    + Move templates to /etc/puppet
  - lib/puppet/defaults.rb:
    + Fix /var/lib/puppet/state ownership.
  - man/man8/puppet.conf.8: 
    + Fix broken URL in manpage.
  - debian/control:
    + Update maintainer accordint to spec.
    + Puppetmaster Recommends -> Suggests
    + Created puppet-testsuite as a seperate. Allow the users to run puppet's 
      testsuite.
  - tests/Rakefile: Fix rakefile so that the testsuite can acutally be ran.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env ruby
2
2
 
3
3
require File.dirname(__FILE__) + '/../../../../spec_helper'
 
4
 
4
5
require 'puppet/network/http'
5
6
 
6
 
describe "Puppet::Network::HTTP::MongrelREST", "when initializing" do
 
7
describe "Puppet::Network::HTTP::MongrelREST" do
7
8
    confine "Mongrel is not available" => Puppet.features.mongrel?
8
 
 
9
9
    before do
10
10
        require 'puppet/network/http/mongrel/rest'
11
 
 
12
 
        @mock_mongrel = mock('Mongrel server')
13
 
        @mock_mongrel.stubs(:register)
14
 
        @mock_model = mock('indirected model')
15
 
        Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@mock_model)
16
 
        @params = { :server => @mock_mongrel, :handler => :foo }
17
 
    end
18
 
 
19
 
    it "should require access to a Mongrel server" do
20
 
        Proc.new { Puppet::Network::HTTP::MongrelREST.new(@params.delete_if {|k,v| :server == k })}.should raise_error(ArgumentError)
21
 
    end
22
 
 
23
 
    it "should require an indirection name" do
24
 
        Proc.new { Puppet::Network::HTTP::MongrelREST.new(@params.delete_if {|k,v| :handler == k })}.should raise_error(ArgumentError)        
25
 
    end
26
 
 
27
 
    it "should look up the indirection model from the indirection name" do
28
 
        Puppet::Indirector::Indirection.expects(:model).with(:foo).returns(@mock_model)
29
 
        Puppet::Network::HTTP::MongrelREST.new(@params)
30
 
    end
31
 
 
32
 
    it "should fail if the indirection is not known" do
33
 
        Puppet::Indirector::Indirection.expects(:model).with(:foo).returns(nil)
34
 
        Proc.new { Puppet::Network::HTTP::MongrelREST.new(@params) }.should raise_error(ArgumentError)
35
 
    end
36
 
end
37
 
 
38
 
describe "Puppet::Network::HTTP::MongrelREST", "when receiving a request" do
39
 
    confine "Mongrel is not available" => Puppet.features.mongrel?
40
 
 
41
 
    before do
42
 
        @mock_request = stub('mongrel http request')
43
 
        @mock_head = stub('response head')
44
 
        @mock_body = stub('response body', :write => true)
45
 
        @mock_response = stub('mongrel http response')
46
 
        @mock_response.stubs(:start).yields(@mock_head, @mock_body)
47
 
        @mock_model_class = stub('indirected model class')
48
 
        @mock_mongrel = stub('mongrel http server', :register => true)
49
 
        Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@mock_model_class)
50
 
        @handler = Puppet::Network::HTTP::MongrelREST.new(:server => @mock_mongrel, :handler => :foo)
51
 
    end
52
 
 
53
 
    def setup_find_request(params = {})
54
 
        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'GET', 
55
 
                                                Mongrel::Const::REQUEST_PATH => '/foo/key',
56
 
                                                'QUERY_STRING' => ''}.merge(params))
57
 
        @mock_model_class.stubs(:find)
58
 
    end
59
 
 
60
 
    def setup_search_request(params = {})
61
 
        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'GET', 
62
 
                                                Mongrel::Const::REQUEST_PATH => '/foos',
63
 
                                                'QUERY_STRING' => '' }.merge(params))
64
 
        @mock_model_class.stubs(:search).returns([])        
65
 
    end
66
 
 
67
 
    def setup_destroy_request(params = {})
68
 
        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'DELETE', 
69
 
                                                Mongrel::Const::REQUEST_PATH => '/foo/key',
70
 
                                                'QUERY_STRING' => '' }.merge(params))
71
 
        @mock_model_class.stubs(:destroy)
72
 
    end
73
 
 
74
 
    def setup_save_request(params = {})
75
 
        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'PUT', 
76
 
                                                Mongrel::Const::REQUEST_PATH => '/foo',
77
 
                                                'QUERY_STRING' => '' }.merge(params))
78
 
        @mock_request.stubs(:body).returns('this is a fake request body')
79
 
        @mock_model_instance = stub('indirected model instance', :save => true)
80
 
        @mock_model_class.stubs(:from_yaml).returns(@mock_model_instance)
81
 
    end
82
 
 
83
 
    def setup_bad_request
84
 
        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'POST', Mongrel::Const::REQUEST_PATH => '/foos'})        
85
 
    end
86
 
 
87
 
    it "should call the model find method if the request represents a singular HTTP GET" do
88
 
        setup_find_request
89
 
        @mock_model_class.expects(:find).with { |key, args| key == 'key' }
90
 
        @handler.process(@mock_request, @mock_response)
91
 
    end
92
 
 
93
 
    it "should call the model search method if the request represents a plural HTTP GET" do
94
 
        setup_search_request
95
 
        @mock_model_class.expects(:search).returns([])
96
 
        @handler.process(@mock_request, @mock_response)
97
 
    end
98
 
 
99
 
    it "should call the model destroy method if the request represents an HTTP DELETE" do
100
 
        setup_destroy_request
101
 
        @mock_model_class.expects(:destroy).with { |key, args| key == 'key' }
102
 
        @handler.process(@mock_request, @mock_response)
103
 
    end
104
 
 
105
 
    it "should call the model save method if the request represents an HTTP PUT" do
106
 
        setup_save_request
107
 
        @mock_model_instance.expects(:save)
108
 
        @handler.process(@mock_request, @mock_response)
109
 
    end
110
 
 
111
 
    it "should fail if the HTTP method isn't supported" do
112
 
        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'POST', Mongrel::Const::REQUEST_PATH => '/foo'})
113
 
        @mock_response.expects(:start).with(404)
114
 
        @handler.process(@mock_request, @mock_response)
115
 
    end
116
 
 
117
 
    it "should fail if the request's pluralization is wrong" do
118
 
        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'DELETE', Mongrel::Const::REQUEST_PATH => '/foos/key'})
119
 
        @mock_response.expects(:start).with(404)
120
 
        @handler.process(@mock_request, @mock_response)
121
 
 
122
 
        @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'PUT', Mongrel::Const::REQUEST_PATH => '/foos/key'})
123
 
        @mock_response.expects(:start).with(404)
124
 
        @handler.process(@mock_request, @mock_response)
125
 
    end
126
 
 
127
 
    it "should fail if the request is for an unknown path" do
128
 
        @mock_request.stubs(:params).returns({  Mongrel::Const::REQUEST_METHOD => 'GET', 
129
 
                                                Mongrel::Const::REQUEST_PATH => '/bar/key',
130
 
                                                'QUERY_STRING' => '' })
131
 
        @mock_response.expects(:start).with(404)
132
 
        @handler.process(@mock_request, @mock_response)
133
 
    end
134
 
 
135
 
    describe "and determining the request parameters", :shared => true do
136
 
        confine "Mongrel is not available" => Puppet.features.mongrel?
137
 
 
 
11
    end
 
12
 
 
13
 
 
14
    it "should include the Puppet::Network::HTTP::Handler module" do
 
15
        Puppet::Network::HTTP::MongrelREST.ancestors.should be_include(Puppet::Network::HTTP::Handler)
 
16
    end
 
17
 
 
18
    describe "when initializing" do
 
19
        it "should call the Handler's initialization hook with its provided arguments as the server and handler" do
 
20
            Puppet::Network::HTTP::MongrelREST.any_instance.expects(:initialize_for_puppet).with(:server => "my", :handler => "arguments")
 
21
            Puppet::Network::HTTP::MongrelREST.new(:server => "my", :handler => "arguments")
 
22
        end
 
23
    end
 
24
 
 
25
    describe "when receiving a request" do
138
26
        before do
139
 
            @mock_request.stubs(:params).returns({})
140
 
        end
141
 
 
142
 
        it "should include the HTTP request parameters" do
143
 
            @mock_request.expects(:params).returns('QUERY_STRING' => 'foo=baz&bar=xyzzy')
144
 
            result = @handler.params(@mock_request)
145
 
            result["foo"].should == "baz"
146
 
            result["bar"].should == "xyzzy"
147
 
        end
148
 
 
149
 
        it "should pass the client's ip address to model find" do
150
 
            @mock_request.stubs(:params).returns("REMOTE_ADDR" => "ipaddress")
151
 
            @handler.params(@mock_request)[:ip].should == "ipaddress"
152
 
        end
153
 
 
154
 
        it "should use the :ssl_client_header to determine the parameter when looking for the certificate" do
155
 
            Puppet.settings.stubs(:value).returns "eh"
156
 
            Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"
157
 
            @mock_request.stubs(:params).returns("myheader" => "/CN=host.domain.com")
158
 
            @handler.params(@mock_request)
159
 
        end
160
 
 
161
 
        it "should retrieve the hostname by matching the certificate parameter" do
162
 
            Puppet.settings.stubs(:value).returns "eh"
163
 
            Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"
164
 
            @mock_request.stubs(:params).returns("myheader" => "/CN=host.domain.com")
165
 
            @handler.params(@mock_request)[:node].should == "host.domain.com"
166
 
        end
167
 
 
168
 
        it "should use the :ssl_client_header to determine the parameter for checking whether the host certificate is valid" do
169
 
            Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
170
 
            Puppet.settings.expects(:value).with(:ssl_client_verify_header).returns "myheader"
171
 
            @mock_request.stubs(:params).returns("myheader" => "SUCCESS", "certheader" => "/CN=host.domain.com")
172
 
            @handler.params(@mock_request)
173
 
        end
174
 
 
175
 
        it "should consider the host authenticated if the validity parameter contains 'SUCCESS'" do
176
 
            Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
177
 
            Puppet.settings.stubs(:value).with(:ssl_client_verify_header).returns "myheader"
178
 
            @mock_request.stubs(:params).returns("myheader" => "SUCCESS", "certheader" => "/CN=host.domain.com")
179
 
            @handler.params(@mock_request)[:authenticated].should be_true
180
 
        end
181
 
 
182
 
        it "should consider the host unauthenticated if the validity parameter does not contain 'SUCCESS'" do
183
 
            Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
184
 
            Puppet.settings.stubs(:value).with(:ssl_client_verify_header).returns "myheader"
185
 
            @mock_request.stubs(:params).returns("myheader" => "whatever", "certheader" => "/CN=host.domain.com")
186
 
            @handler.params(@mock_request)[:authenticated].should be_false
187
 
        end
188
 
 
189
 
        it "should consider the host unauthenticated if no certificate information is present" do
190
 
            Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
191
 
            Puppet.settings.stubs(:value).with(:ssl_client_verify_header).returns "myheader"
192
 
            @mock_request.stubs(:params).returns("myheader" => nil, "certheader" => "SUCCESS")
193
 
            @handler.params(@mock_request)[:authenticated].should be_false
194
 
        end
195
 
 
196
 
        it "should not pass a node name to model method if no certificate information is present" do
197
 
            Puppet.settings.stubs(:value).returns "eh"
198
 
            Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"
199
 
            @mock_request.stubs(:params).returns("myheader" => nil)
200
 
            @handler.params(@mock_request).should_not be_include(:node)
201
 
        end
202
 
    end
203
 
 
204
 
    describe "when finding a model instance" do |variable|
205
 
        confine "Mongrel is not available" => Puppet.features.mongrel?
206
 
 
207
 
        it "should fail to find model if key is not specified" do
208
 
            @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'GET', Mongrel::Const::REQUEST_PATH => '/foo'})
209
 
            @mock_response.expects(:start).with(404)
210
 
            @handler.process(@mock_request, @mock_response)
211
 
        end
212
 
 
213
 
        it "should use a common method for determining the request parameters" do
214
 
            setup_find_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
215
 
            @handler.expects(:params).returns(:foo => :baz, :bar => :xyzzy)
216
 
            @mock_model_class.expects(:find).with do |key, args|
217
 
                args[:foo] == :baz and args[:bar] == :xyzzy
218
 
            end
219
 
            @handler.process(@mock_request, @mock_response)
220
 
        end
221
 
 
222
 
        it "should generate a 200 response when a model find call succeeds" do
223
 
            setup_find_request
224
 
            @mock_response.expects(:start).with(200)
225
 
            @handler.process(@mock_request, @mock_response)
226
 
        end
227
 
 
228
 
        it "should return a serialized object when a model find call succeeds" do
229
 
            setup_find_request
230
 
            @mock_model_instance = stub('model instance')
231
 
            @mock_model_instance.expects(:to_yaml)
232
 
            @mock_model_class.stubs(:find).returns(@mock_model_instance)
233
 
            @handler.process(@mock_request, @mock_response)                  
234
 
        end
235
 
 
236
 
        it "should serialize a controller exception when an exception is thrown by find" do
237
 
           setup_find_request
238
 
           @mock_model_class.expects(:find).raises(ArgumentError) 
239
 
           @mock_response.expects(:start).with(404)
240
 
           @handler.process(@mock_request, @mock_response)        
241
 
        end
242
 
    end
243
 
 
244
 
    describe "when destroying a model instance" do |variable|
245
 
        confine "Mongrel is not available" => Puppet.features.mongrel?
246
 
 
247
 
        it "should fail to destroy model if key is not specified" do
248
 
            @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'DELETE', Mongrel::Const::REQUEST_PATH => '/foo'})
249
 
            @mock_response.expects(:start).with(404)
250
 
            @handler.process(@mock_request, @mock_response)
251
 
        end
252
 
 
253
 
        it "should use a common method for determining the request parameters" do
254
 
            setup_destroy_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
255
 
            @handler.expects(:params).returns(:foo => :baz, :bar => :xyzzy)
256
 
            @mock_model_class.expects(:destroy).with do |key, args|
257
 
                args[:foo] == :baz and args[:bar] == :xyzzy
258
 
            end
259
 
            @handler.process(@mock_request, @mock_response)
260
 
        end
261
 
 
262
 
        it "should pass HTTP request parameters to model destroy" do
263
 
            setup_destroy_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
264
 
            @mock_model_class.expects(:destroy).with do |key, args|
265
 
                key == 'key' and args['foo'] == 'baz' and args['bar'] == 'xyzzy'
266
 
            end
267
 
            @handler.process(@mock_request, @mock_response)
268
 
        end
269
 
 
270
 
        it "should generate a 200 response when a model destroy call succeeds" do
271
 
            setup_destroy_request
272
 
            @mock_response.expects(:start).with(200)
273
 
            @handler.process(@mock_request, @mock_response)
274
 
        end
275
 
 
276
 
        it "should return a serialized success result when a model destroy call succeeds" do
277
 
            setup_destroy_request
278
 
            @mock_model_class.stubs(:destroy).returns(true)
279
 
            @mock_body.expects(:write).with("--- true\n")
280
 
            @handler.process(@mock_request, @mock_response)
281
 
        end
282
 
 
283
 
        it "should serialize a controller exception when an exception is thrown by destroy" do
284
 
            setup_destroy_request
285
 
            @mock_model_class.expects(:destroy).raises(ArgumentError) 
286
 
            @mock_response.expects(:start).with(404)
287
 
            @handler.process(@mock_request, @mock_response)                 
288
 
        end
289
 
    end
290
 
 
291
 
    describe "when saving a model instance" do |variable|    
292
 
        confine "Mongrel is not available" => Puppet.features.mongrel?
293
 
 
294
 
        it "should fail to save model if data is not specified" do
295
 
            @mock_request.stubs(:params).returns({ Mongrel::Const::REQUEST_METHOD => 'PUT', Mongrel::Const::REQUEST_PATH => '/foo'})
296
 
            @mock_request.stubs(:body).returns('')
297
 
            @mock_response.expects(:start).with(404)
298
 
            @handler.process(@mock_request, @mock_response)
299
 
        end
300
 
 
301
 
        it "should use a common method for determining the request parameters" do
302
 
            setup_save_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
303
 
            @handler.expects(:params).returns(:foo => :baz, :bar => :xyzzy)
304
 
            @mock_model_instance.expects(:save).with do |args|
305
 
                args[:foo] == :baz and args[:bar] == :xyzzy
306
 
            end
307
 
            @handler.process(@mock_request, @mock_response)
308
 
        end
309
 
 
310
 
        it "should generate a 200 response when a model save call succeeds" do
311
 
            setup_save_request
312
 
            @mock_response.expects(:start).with(200)
313
 
            @handler.process(@mock_request, @mock_response)
314
 
        end
315
 
 
316
 
        it "should return a serialized object when a model save call succeeds" do
317
 
            setup_save_request
318
 
            @mock_model_instance.stubs(:save).returns(@mock_model_instance)
319
 
            @mock_model_instance.expects(:to_yaml).returns('foo')
320
 
            @handler.process(@mock_request, @mock_response)        
321
 
        end
322
 
 
323
 
        it "should serialize a controller exception when an exception is thrown by save" do
324
 
            setup_save_request
325
 
            @mock_model_instance.expects(:save).raises(ArgumentError) 
326
 
            @mock_response.expects(:start).with(404)
327
 
            @handler.process(@mock_request, @mock_response)                         
328
 
        end
329
 
    end
330
 
 
331
 
    describe "when searching for model instances" do |variable|
332
 
        confine "Mongrel is not available" => Puppet.features.mongrel?
333
 
 
334
 
        it "should use a common method for determining the request parameters" do
335
 
            setup_search_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
336
 
            @handler.expects(:params).returns(:foo => :baz, :bar => :xyzzy)
337
 
            @mock_model_class.expects(:search).with do |args|
338
 
                args[:foo] == :baz and args[:bar] == :xyzzy
339
 
            end
340
 
            @handler.process(@mock_request, @mock_response)
341
 
        end
342
 
 
343
 
        it "should pass HTTP request parameters to model search" do
344
 
            setup_search_request('QUERY_STRING' => 'foo=baz&bar=xyzzy')
345
 
            @mock_model_class.expects(:search).with do |args|
346
 
                args['foo'] == 'baz' and args['bar'] == 'xyzzy'
347
 
            end.returns([])
348
 
            @handler.process(@mock_request, @mock_response)
349
 
        end      
350
 
 
351
 
        it "should generate a 200 response when a model search call succeeds" do
352
 
            setup_search_request
353
 
            @mock_response.expects(:start).with(200)
354
 
            @handler.process(@mock_request, @mock_response)
355
 
        end
356
 
 
357
 
        it "should return a list of serialized objects when a model search call succeeds" do
358
 
            setup_search_request
359
 
            mock_matches = [1..5].collect {|i| mock("model instance #{i}", :to_yaml => "model instance #{i}") }
360
 
            @mock_model_class.stubs(:search).returns(mock_matches)
361
 
            @handler.process(@mock_request, @mock_response)                          
362
 
        end
363
 
 
364
 
        it "should serialize a controller exception when an exception is thrown by search" do
365
 
            setup_search_request
366
 
            @mock_model_class.expects(:search).raises(ArgumentError) 
367
 
            @mock_response.expects(:start).with(404)
368
 
            @handler.process(@mock_request, @mock_response)                
369
 
        end
370
 
    end    
371
 
 
372
 
    it "should serialize a controller exception if the request fails" do
373
 
        setup_bad_request     
374
 
        @mock_response.expects(:start).with(404)
375
 
        @handler.process(@mock_request, @mock_response)        
 
27
            @params = {}
 
28
            @request = stub('mongrel http request', :params => @params)
 
29
 
 
30
            @head = stub('response head')
 
31
            @body = stub('response body', :write => true)
 
32
            @response = stub('mongrel http response')
 
33
            @response.stubs(:start).yields(@head, @body)
 
34
            @model_class = stub('indirected model class')
 
35
            @mongrel = stub('mongrel http server', :register => true)
 
36
            Puppet::Indirector::Indirection.stubs(:model).with(:foo).returns(@model_class)
 
37
            @handler = Puppet::Network::HTTP::MongrelREST.new(:server => @mongrel, :handler => :foo)
 
38
        end
 
39
 
 
40
        describe "and using the HTTP Handler interface" do
 
41
            it "should return the HTTP_ACCEPT parameter as the accept header" do
 
42
                @params.expects(:[]).with("HTTP_ACCEPT").returns "myaccept"
 
43
                @handler.accept_header(@request).should == "myaccept"
 
44
            end
 
45
 
 
46
            it "should return the Content-Type parameter as the Content-Type header" do
 
47
                @params.expects(:[]).with("HTTP_CONTENT_TYPE").returns "mycontent"
 
48
                @handler.content_type_header(@request).should == "mycontent"
 
49
            end
 
50
 
 
51
            it "should use the REQUEST_METHOD as the http method" do
 
52
                @params.expects(:[]).with(Mongrel::Const::REQUEST_METHOD).returns "mymethod"
 
53
                @handler.http_method(@request).should == "mymethod"
 
54
            end
 
55
 
 
56
            it "should return the request path as the path" do
 
57
                @params.expects(:[]).with(Mongrel::Const::REQUEST_PATH).returns "/foo/bar"
 
58
                @handler.path(@request).should == "/foo/bar"
 
59
            end
 
60
 
 
61
            it "should return the request body as the body" do
 
62
                @request.expects(:body).returns StringIO.new("mybody")
 
63
                @handler.body(@request).should == "mybody"
 
64
            end
 
65
 
 
66
            it "should set the response's content-type header when setting the content type" do
 
67
                @header = mock 'header'
 
68
                @response.expects(:header).returns @header
 
69
                @header.expects(:[]=).with('Content-Type', "mytype")
 
70
 
 
71
                @handler.set_content_type(@response, "mytype")
 
72
            end
 
73
 
 
74
            it "should set the status and write the body when setting the response for a successful request" do
 
75
                head = mock 'head'
 
76
                body = mock 'body'
 
77
                @response.expects(:start).with(200).yields(head, body)
 
78
 
 
79
                body.expects(:write).with("mybody")
 
80
 
 
81
                @handler.set_response(@response, "mybody", 200)
 
82
            end
 
83
 
 
84
            it "should set the status and reason and write the body when setting the response for a successful request" do
 
85
                head = mock 'head'
 
86
                body = mock 'body'
 
87
                @response.expects(:start).with(400, false, "mybody").yields(head, body)
 
88
 
 
89
                body.expects(:write).with("mybody")
 
90
 
 
91
                @handler.set_response(@response, "mybody", 400)
 
92
            end
 
93
        end
 
94
 
 
95
        describe "and determining the request parameters" do
 
96
            before do
 
97
                @request.stubs(:params).returns({})
 
98
            end
 
99
 
 
100
            it "should skip empty parameter values" do
 
101
                @request.expects(:params).returns('QUERY_STRING' => "&=")
 
102
                lambda { @handler.params(@request) }.should_not raise_error
 
103
            end
 
104
 
 
105
            it "should include the HTTP request parameters, with the keys as symbols" do
 
106
                @request.expects(:params).returns('QUERY_STRING' => 'foo=baz&bar=xyzzy')
 
107
                result = @handler.params(@request)
 
108
                result[:foo].should == "baz"
 
109
                result[:bar].should == "xyzzy"
 
110
            end
 
111
 
 
112
            it "should CGI-decode the HTTP parameters" do
 
113
                encoding = CGI.escape("foo bar")
 
114
                @request.expects(:params).returns('QUERY_STRING' => "foo=#{encoding}")
 
115
                result = @handler.params(@request)
 
116
                result[:foo].should == "foo bar"
 
117
            end
 
118
 
 
119
            it "should convert the string 'true' to the boolean" do
 
120
                @request.expects(:params).returns('QUERY_STRING' => 'foo=true')
 
121
                result = @handler.params(@request)
 
122
                result[:foo].should be_true
 
123
            end
 
124
 
 
125
            it "should convert the string 'false' to the boolean" do
 
126
                @request.expects(:params).returns('QUERY_STRING' => 'foo=false')
 
127
                result = @handler.params(@request)
 
128
                result[:foo].should be_false
 
129
            end
 
130
 
 
131
            it "should convert integer arguments to Integers" do
 
132
                @request.expects(:params).returns('QUERY_STRING' => 'foo=15')
 
133
                result = @handler.params(@request)
 
134
                result[:foo].should == 15
 
135
            end
 
136
 
 
137
            it "should convert floating point arguments to Floats" do
 
138
                @request.expects(:params).returns('QUERY_STRING' => 'foo=1.5')
 
139
                result = @handler.params(@request)
 
140
                result[:foo].should == 1.5
 
141
            end
 
142
 
 
143
            it "should YAML-load and URI-decode values that are YAML-encoded" do
 
144
                escaping = CGI.escape(YAML.dump(%w{one two}))
 
145
                @request.expects(:params).returns('QUERY_STRING' => "foo=#{escaping}")
 
146
                result = @handler.params(@request)
 
147
                result[:foo].should == %w{one two}
 
148
            end
 
149
 
 
150
            it "should not allow the client to set the node via the query string" do
 
151
                @request.stubs(:params).returns('QUERY_STRING' => "node=foo")
 
152
                @handler.params(@request)[:node].should be_nil
 
153
            end
 
154
 
 
155
            it "should not allow the client to set the IP address via the query string" do
 
156
                @request.stubs(:params).returns('QUERY_STRING' => "ip=foo")
 
157
                @handler.params(@request)[:ip].should be_nil
 
158
            end
 
159
 
 
160
            it "should pass the client's ip address to model find" do
 
161
                @request.stubs(:params).returns("REMOTE_ADDR" => "ipaddress")
 
162
                @handler.params(@request)[:ip].should == "ipaddress"
 
163
            end
 
164
 
 
165
            it "should pass the client's provided X-Forwared-For value as the ip" do
 
166
                @request.stubs(:params).returns("HTTP_X_FORWARDED_FOR" => "ipaddress")
 
167
                @handler.params(@request)[:ip].should == "ipaddress"
 
168
            end
 
169
 
 
170
            it "should pass the client's provided X-Forwared-For first value as the ip" do
 
171
                @request.stubs(:params).returns("HTTP_X_FORWARDED_FOR" => "ipproxy1,ipproxy2,ipaddress")
 
172
                @handler.params(@request)[:ip].should == "ipaddress"
 
173
            end
 
174
 
 
175
            it "should pass the client's provided X-Forwared-For value as the ip instead of the REMOTE_ADDR" do
 
176
                @request.stubs(:params).returns("REMOTE_ADDR" => "remote_addr")
 
177
                @request.stubs(:params).returns("HTTP_X_FORWARDED_FOR" => "ipaddress")
 
178
                @handler.params(@request)[:ip].should == "ipaddress"
 
179
            end
 
180
 
 
181
            it "should use the :ssl_client_header to determine the parameter when looking for the certificate" do
 
182
                Puppet.settings.stubs(:value).returns "eh"
 
183
                Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"
 
184
                @request.stubs(:params).returns("myheader" => "/CN=host.domain.com")
 
185
                @handler.params(@request)
 
186
            end
 
187
 
 
188
            it "should retrieve the hostname by matching the certificate parameter" do
 
189
                Puppet.settings.stubs(:value).returns "eh"
 
190
                Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"
 
191
                @request.stubs(:params).returns("myheader" => "/CN=host.domain.com")
 
192
                @handler.params(@request)[:node].should == "host.domain.com"
 
193
            end
 
194
 
 
195
            it "should use the :ssl_client_header to determine the parameter for checking whether the host certificate is valid" do
 
196
                Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
 
197
                Puppet.settings.expects(:value).with(:ssl_client_verify_header).returns "myheader"
 
198
                @request.stubs(:params).returns("myheader" => "SUCCESS", "certheader" => "/CN=host.domain.com")
 
199
                @handler.params(@request)
 
200
            end
 
201
 
 
202
            it "should consider the host authenticated if the validity parameter contains 'SUCCESS'" do
 
203
                Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
 
204
                Puppet.settings.stubs(:value).with(:ssl_client_verify_header).returns "myheader"
 
205
                @request.stubs(:params).returns("myheader" => "SUCCESS", "certheader" => "/CN=host.domain.com")
 
206
                @handler.params(@request)[:authenticated].should be_true
 
207
            end
 
208
 
 
209
            it "should consider the host unauthenticated if the validity parameter does not contain 'SUCCESS'" do
 
210
                Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
 
211
                Puppet.settings.stubs(:value).with(:ssl_client_verify_header).returns "myheader"
 
212
                @request.stubs(:params).returns("myheader" => "whatever", "certheader" => "/CN=host.domain.com")
 
213
                @handler.params(@request)[:authenticated].should be_false
 
214
            end
 
215
 
 
216
            it "should consider the host unauthenticated if no certificate information is present" do
 
217
                Puppet.settings.stubs(:value).with(:ssl_client_header).returns "certheader"
 
218
                Puppet.settings.stubs(:value).with(:ssl_client_verify_header).returns "myheader"
 
219
                @request.stubs(:params).returns("myheader" => nil, "certheader" => "SUCCESS")
 
220
                @handler.params(@request)[:authenticated].should be_false
 
221
            end
 
222
 
 
223
            it "should resolve the node name with an ip address look-up if no certificate is present" do
 
224
                Puppet.settings.stubs(:value).returns "eh"
 
225
                Puppet.settings.expects(:value).with(:ssl_client_header).returns "myheader"
 
226
                @request.stubs(:params).returns("myheader" => nil)
 
227
                @handler.expects(:resolve_node).returns("host.domain.com")
 
228
                @handler.params(@request)[:node].should == "host.domain.com"
 
229
            end
 
230
        end
376
231
    end
377
232
end