restility 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,191 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require "rest"
4
+ require 'active_support/builder' unless defined?(Builder)
5
+
6
+ class HtmlPrinter < Printer
7
+
8
+ attr_accessor :output_dir
9
+
10
+ def initialize
11
+ super()
12
+ @output_dir = "html"
13
+ @xml_examples = Hash.new
14
+ @xml_schemas = Hash.new
15
+
16
+ @docbook_tag_mapping = {
17
+ "command" => "tt",
18
+ "filename" => "tt",
19
+ "emphasis" => "em",
20
+ "replaceable" => "em",
21
+ }
22
+
23
+ end
24
+
25
+ def do_prepare
26
+ unless File.exists? @output_dir
27
+ Dir.mkdir @output_dir
28
+ end
29
+ @index = File.new( @output_dir + "/index.html", "w" )
30
+ @html = Builder::XmlMarkup.new( :target => @index, :indent => 2 )
31
+ @html.comment! "This file was generated by restility at #{Time.now}"
32
+ end
33
+
34
+ def do_finish
35
+ puts "Written #{@index.path}"
36
+
37
+ @xml_examples.each do |f,b|
38
+ if !XmlFile.exist?( f )
39
+ STDERR.puts "XML Example '#{f}' is missing."
40
+ else
41
+ XmlFile.copy f, @output_dir
42
+ end
43
+ end
44
+ @xml_schemas.each do |f,b|
45
+ if !XmlFile.exist?( f )
46
+ STDERR.puts "XML Schema '#{f}' is missing."
47
+ else
48
+ XmlFile.copy f, @output_dir
49
+ end
50
+ end
51
+
52
+ @index.close
53
+ end
54
+
55
+ def print_section section
56
+ if ( !section.root? )
57
+ tag = "h#{section.level}"
58
+ @html.tag!( tag, section )
59
+ end
60
+ section.print_children self
61
+ end
62
+
63
+ def print_request request
64
+ @html.div( "class" => "request" ) do
65
+
66
+ @html.p do
67
+ @html.a( "name" => request.id ) do
68
+ @html.b request.to_s
69
+ end
70
+ end
71
+
72
+ if false
73
+ host = request.host
74
+ if ( host )
75
+ @html.p "Host: " + host.name
76
+ end
77
+ end
78
+
79
+ if request.parameters.size > 0
80
+ @html.p "Arguments:"
81
+ @html.ul do
82
+ request.parameters.each do |p|
83
+ @html.li p.to_s
84
+ end
85
+ end
86
+ end
87
+ request.print_children self
88
+
89
+ end
90
+ end
91
+
92
+ def replace_docbook_tags text
93
+ @docbook_tag_mapping.each do |docbook, html|
94
+ text.gsub! "<#{docbook}>", "<#{html}>"
95
+ text.gsub! "</#{docbook}>", "</#{html}>"
96
+ end
97
+ end
98
+
99
+ def print_text text
100
+ @html.p do |p|
101
+ text.text.each do |t|
102
+ replace_docbook_tags t
103
+ p << t << "\n"
104
+ end
105
+ end
106
+ end
107
+
108
+ def print_parameter parameter
109
+ end
110
+
111
+ def print_host host
112
+ @html.p "Host: " + host.name
113
+ end
114
+
115
+ def print_result result
116
+ @html.p "Result: " + result.name
117
+ end
118
+
119
+ def print_body body
120
+ @html.p "Body: " + body.name
121
+ end
122
+
123
+ def print_xmlresult result
124
+ print_xml_links "Result", result.name, result.schema
125
+ end
126
+
127
+ def print_xmlbody body
128
+ print_xml_links "Body", body.name, body.schema
129
+ end
130
+
131
+ def print_xml_links title, xmlname, schema
132
+ example = xmlname + ".xml"
133
+ if ( !schema || schema.empty? )
134
+ schema = xmlname + ".xsd"
135
+ end
136
+ @xml_examples[ example ] = true
137
+ @xml_schemas[ schema ] = true
138
+ @html.p do |p|
139
+ p << title
140
+ p << ": "
141
+ has_example = XmlFile.exist? example
142
+ has_schema = XmlFile.exist? schema
143
+ if has_example
144
+ @html.a( "Example", "href" => example )
145
+ end
146
+ if has_schema
147
+ p << " ";
148
+ @html.a( "Schema", "href" => schema )
149
+ end
150
+ if( !has_example && !has_schema )
151
+ p << xmlname
152
+ end
153
+ end
154
+ end
155
+
156
+ def print_contents contents
157
+ @html.tag! "h#{contents.level}", "Table of Contents"
158
+ @html.p do |p|
159
+ p << create_contents_list( contents.root, 1 )
160
+ end
161
+ end
162
+
163
+ def create_contents_list section, min_level
164
+ result = ""
165
+ section.children.each do |s|
166
+ if ( s.is_a? Section )
167
+ result += create_contents_list s, min_level
168
+ end
169
+ if ( s.is_a? Request )
170
+ result += "<li><a href=\"##{s.id}\">" + h( s.to_s ) + "</a></li>\n"
171
+ end
172
+ end
173
+ endresult = ""
174
+ if ( !result.empty? )
175
+ if ( section.level > min_level )
176
+ endresult = "<li>" + h( section.to_s ) + "</li>\n"
177
+ end
178
+ if ( section.level >= min_level )
179
+ endresult += "<ul>\n" + result + "</ul>\n"
180
+ else
181
+ endresult = result
182
+ end
183
+ end
184
+ endresult
185
+ end
186
+
187
+ def print_version version
188
+ @html.p "Version: " + version.to_s
189
+ end
190
+
191
+ end
data/lib/rest_test.rb ADDED
@@ -0,0 +1,351 @@
1
+ require "net/https"
2
+ require "tempfile"
3
+
4
+ class ParameterError < Exception
5
+ end
6
+
7
+ class TestContext
8
+
9
+ attr_writer :show_xmlbody, :request_filter, :show_passed, :output_html
10
+
11
+ def initialize requests
12
+ @host_aliases = Hash.new
13
+
14
+ @output = ""
15
+
16
+ @requests = requests
17
+ start
18
+ end
19
+
20
+ def start
21
+ @tested = 0
22
+ @unsupported = 0
23
+ @failed = 0
24
+ @passed = 0
25
+ @error = 0
26
+ @skipped = 0
27
+ end
28
+
29
+ def bold str
30
+ if @output_html
31
+ str.gsub! /</, "&lt;"
32
+ str.gsub! />/, "&gt;"
33
+ "<b>#{str}</b>"
34
+ else
35
+ "\033[1m#{str}\033[0m"
36
+ end
37
+ end
38
+
39
+ def red str
40
+ bold str
41
+ # "\E[31m#{str}\E[30m"
42
+ end
43
+
44
+ def green str
45
+ bold str
46
+ end
47
+
48
+ def magenta str
49
+ bold str
50
+ end
51
+
52
+ def get_binding
53
+ return binding()
54
+ end
55
+
56
+ def unsupported
57
+ out magenta( " UNSUPPORTED" )
58
+ @unsupported += 1
59
+ out_flush
60
+ end
61
+
62
+ def failed
63
+ out red( " FAILED" )
64
+ @failed += 1
65
+ out_flush
66
+ end
67
+
68
+ def passed
69
+ out green( " PASSED" )
70
+ @passed += 1
71
+ if ( @show_passed )
72
+ out_flush
73
+ else
74
+ out_clear
75
+ end
76
+ end
77
+
78
+ def skipped
79
+ # out magenta( " SKIPPED" )
80
+ @skipped += 1
81
+ out_flush
82
+ end
83
+
84
+ def error str = nil
85
+ error_str = " ERROR"
86
+ if ( str )
87
+ error_str += ": " + str
88
+ end
89
+ out red( error_str )
90
+ @error += 1
91
+ out_flush
92
+ end
93
+
94
+ def alias_host old, new
95
+ @host_aliases[ old ] = new
96
+ end
97
+
98
+ def out str
99
+ @output += str + "\n";
100
+ end
101
+
102
+ def out_clear
103
+ @output = ""
104
+ end
105
+
106
+ def out_flush
107
+ print @output
108
+ out_clear
109
+ end
110
+
111
+ def request arg, return_code = nil, xml_check_wanted = true
112
+ @tested += 1
113
+
114
+ if ( @request_filter && arg !~ /#{@request_filter}/ )
115
+ skipped
116
+ return nil
117
+ end
118
+
119
+ out bold( "REQUEST: " + arg )
120
+
121
+ request = @requests.find { |r|
122
+ r.to_s == arg
123
+ }
124
+
125
+ if ( !request )
126
+ STDERR.puts " Request not defined"
127
+ return nil
128
+ end
129
+
130
+ xml_bodies = request.all_children XmlBody
131
+ if ( !xml_bodies.empty? )
132
+ xml_body = xml_bodies[0]
133
+ out " XMLBODY: " + xml_body.name
134
+ end
135
+
136
+ xml_results = request.all_children XmlResult
137
+ if ( !xml_results.empty? )
138
+ xml_result = xml_results[0]
139
+ out " XMLRESULT: " + xml_result.name
140
+ end
141
+
142
+ out " host: '#{request.host}'"
143
+
144
+ host = request.host.to_s
145
+ if ( !host || host.empty? )
146
+ error "No host defined"
147
+ return nil
148
+ end
149
+
150
+ if @host_aliases[ host ]
151
+ host = @host_aliases[ host ]
152
+ end
153
+
154
+ out " aliased host: #{host}"
155
+
156
+ begin
157
+ path = substitute_parameters request
158
+ rescue ParameterError
159
+ error
160
+ return nil
161
+ end
162
+
163
+ out " Path: " + path
164
+
165
+ splitted_host = host.split( ":" )
166
+
167
+ host_name = splitted_host[0]
168
+ host_port = splitted_host[1]
169
+
170
+ out " Host name: #{host_name} port: #{host_port}"
171
+
172
+ if ( request.verb == "GET" )
173
+ req = Net::HTTP::Get.new( path )
174
+ if ( true||@user )
175
+ req.basic_auth( @user, @password )
176
+ end
177
+ response = Net::HTTP.start( host_name, host_port ) do |http|
178
+ http.request( req )
179
+ end
180
+ if ( response.is_a? Net::HTTPRedirection )
181
+ location = URI.parse response["location"]
182
+ out " Redirected to #{location}, scheme is #{location.scheme}"
183
+ http = Net::HTTP.new( location.host, location.port )
184
+ if location.scheme == "https"
185
+ http.use_ssl = true
186
+ end
187
+ http.start do |http|
188
+ req = Net::HTTP::Get.new( location.path )
189
+
190
+ if ( @user )
191
+ out " setting user #{@user}"
192
+ req.basic_auth( @user, @password )
193
+ end
194
+
195
+ out " calling #{location.host}, #{location.port}"
196
+ response = http.request( req )
197
+ end
198
+ end
199
+ elsif( request.verb == "POST" )
200
+ req = Net::HTTP::Post.new( path )
201
+ if ( @user )
202
+ req.basic_auth( @user, @password )
203
+ end
204
+ response = Net::HTTP.start( host_name, host_port ) do |http|
205
+ http.request( req, "" )
206
+ end
207
+ elsif( request.verb == "PUT" )
208
+ if ( !@data_body )
209
+ error "No body data defined for PUT"
210
+ return nil
211
+ end
212
+
213
+ if ( xml_body && @show_xmlbody )
214
+ out "Request body:"
215
+ out @data_body
216
+ end
217
+
218
+ req = Net::HTTP::Put.new( path )
219
+ if ( @user )
220
+ req.basic_auth( @user, @password )
221
+ end
222
+ response = Net::HTTP.start( host_name, host_port ) do |http|
223
+ http.request( req, @data_body )
224
+ end
225
+ else
226
+ STDERR.puts " Test of method '#{request.verb}' not supported yet."
227
+ unsupported
228
+ return nil
229
+ end
230
+
231
+ if ( response )
232
+ out " return code: #{response.code}"
233
+ if ( xml_result && @show_xmlbody )
234
+ out "Response body:"
235
+ out response.body
236
+ end
237
+
238
+ if ( ( return_code && response.code == return_code.to_s ) ||
239
+ ( response.is_a? Net::HTTPSuccess ) )
240
+ if ( xml_check_wanted && xml_result )
241
+ if ( xml_result.schema )
242
+ schema_file = xml_result.schema
243
+ else
244
+ schema_file = xml_result.name + ".xsd"
245
+ end
246
+ if ( validate_xml response.body, schema_file )
247
+ out " Response validates against schema '#{schema_file}'"
248
+ passed
249
+ else
250
+ failed
251
+ end
252
+ else
253
+ passed
254
+ end
255
+ else
256
+ failed
257
+ end
258
+ end
259
+
260
+ response
261
+
262
+ end
263
+
264
+ def substitute_parameters request
265
+ path = request.path.clone
266
+
267
+ request.parameters.each do |parameter|
268
+ p = parameter.name
269
+ arg = eval( "@arg_#{parameter.name}" )
270
+ if ( !arg )
271
+ out " Can't substitute parameter '#{p}'. " +
272
+ "No variable @arg_#{p} defined."
273
+ raise ParameterError
274
+ end
275
+ path.gsub! /<#{p}>/, arg
276
+ end
277
+
278
+ path
279
+ end
280
+
281
+ def validate_xml xml, schema_file
282
+ tmp = Tempfile.new('rest_test_validator')
283
+ tmp.print xml
284
+ tmp_path = tmp.path
285
+ tmp.close
286
+
287
+ found_schema_file = XmlFile.find_file schema_file
288
+
289
+ if ( !found_schema_file )
290
+ out " Unable to find schema file '#{schema_file}'"
291
+ return false
292
+ end
293
+
294
+ cmd = "/usr/bin/xmllint --noout --schema #{found_schema_file} #{tmp_path} 2>&1"
295
+ # puts "CMD: " + cmd
296
+ output = `#{cmd}`
297
+ if $?.exitstatus > 0
298
+ out "xmllint return value: #{$?.exitstatus}"
299
+ out output
300
+ return false
301
+ end
302
+ return true
303
+ end
304
+
305
+ def print_summary
306
+ undefined = @tested - @unsupported - @failed - @passed - @error - @skipped
307
+
308
+ puts "#tester passed #{@passed}"
309
+ puts "#tester failed #{@failed}"
310
+ puts "#tester error #{@error}"
311
+ puts "#tester skipped #{@unsupported + @skipped + undefined}"
312
+
313
+ puts
314
+
315
+ puts "Total #{@tested} tests"
316
+ puts " #{@passed} passed"
317
+ puts " #{@failed} failed"
318
+ if ( @unsupported > 0 )
319
+ puts " #{@unsupported} unsupported"
320
+ end
321
+ if ( @error > 0 )
322
+ puts " #{@error} errors"
323
+ end
324
+ if ( @skipped > 0 )
325
+ puts " #{@skipped} skipped"
326
+ end
327
+ if ( undefined > 0 )
328
+ puts " #{undefined} undefined"
329
+ end
330
+
331
+ end
332
+
333
+ end
334
+
335
+ class TestRunner
336
+
337
+ attr_reader :context
338
+
339
+ def initialize requests
340
+ @context = TestContext.new requests
341
+ end
342
+
343
+ def run testfile
344
+ File.open testfile do |file|
345
+ eval( file.read, @context.get_binding )
346
+ end
347
+
348
+ @context.print_summary
349
+ end
350
+
351
+ end
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,27 @@
1
+ desc 'Release the website and new gem version'
2
+ task :deploy => [:check_version, :website, :release] do
3
+ puts "Remember to create SVN tag:"
4
+ puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
5
+ "svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
6
+ puts "Suggested comment:"
7
+ puts "Tagging release #{CHANGES}"
8
+ end
9
+
10
+ desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
11
+ task :local_deploy => [:website_generate, :install_gem]
12
+
13
+ task :check_version do
14
+ unless ENV['VERSION']
15
+ puts 'Must pass a VERSION=x.y.z release version'
16
+ exit
17
+ end
18
+ unless ENV['VERSION'] == VERS
19
+ puts "Please update your version.rb to match the release version, currently #{VERS}"
20
+ exit
21
+ end
22
+ end
23
+
24
+ desc 'Install the package as a gem, without generating documentation(ri/rdoc)'
25
+ task :install_gem_no_doc => [:clean, :package] do
26
+ sh "#{'sudo ' unless Hoe::WINDOZE }gem install pkg/*.gem --no-rdoc --no-ri"
27
+ end
@@ -0,0 +1,7 @@
1
+ task :ruby_env do
2
+ RUBY_APP = if RUBY_PLATFORM =~ /java/
3
+ "jruby"
4
+ else
5
+ "ruby"
6
+ end unless defined? RUBY_APP
7
+ end
@@ -0,0 +1,9 @@
1
+ # stubs for the website generation
2
+ # To install the website framework:
3
+ # script/generate website
4
+
5
+ task :website_generate
6
+
7
+ task :website_upload
8
+
9
+ task :website => :publish_docs
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/restility'
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestRestility < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end