restility 0.0.3

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.
@@ -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