rest-object 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ # Module to be included for REST Object
2
+ #
3
+ require_relative 'rest-object/gree_json.rb'
4
+
5
+ module RestObject
6
+
7
+ # response is a Net:HTTPResponse object returned from REST call
8
+ attr_reader :response, :code, :body
9
+
10
+ def initialize(response)
11
+ @response = response
12
+ @code = response.code
13
+ @body = response.body
14
+ end
15
+
16
+ def is_restful?
17
+ begin
18
+ return (JSON.parse(@body).class == Hash)
19
+ rescue
20
+ return false
21
+ end
22
+ end
23
+
24
+ # Verify if @code is 200
25
+ def is_successful?
26
+ @code == "200"
27
+ end
28
+
29
+ # Verify if @code is 4xx
30
+ def is_client_error?
31
+ end
32
+
33
+ # Verify if @code is 5xx
34
+ def is_server_error?
35
+ end
36
+
37
+ # Verify API response body
38
+ def verify_rest_body(expected, content_type = :json)
39
+ if content_type == :json
40
+ GreeJson.check_json_response(expected, @body)
41
+ else
42
+ return (@body == expected)
43
+ end
44
+ end
45
+
46
+ # Verify API response header
47
+ def verify_rest_header(expected)
48
+ end
49
+
50
+ end
51
+
52
+
53
+ # Unit test
54
+ if __FILE__ == $0
55
+ GreeLog.level = Logger::INFO
56
+ GreeLog.echo_to_screen = true
57
+
58
+ end
59
+
@@ -0,0 +1,93 @@
1
+ # convenience functions for dealing with errors and exceptions
2
+
3
+ require 'pp'
4
+
5
+ require_relative 'gree_ruby_extensions.rb'
6
+ require_relative 'gree_logger.rb'
7
+
8
+ module GreeErr
9
+
10
+ # Construct an error message string saying 2 things are not identical
11
+ def self.msg_not_identical(value_name, var1, var2)
12
+ return "#{value_name} is not identical: #1 = #{value_1}, #2 = #{value_2}"
13
+ end
14
+
15
+ # Construct an error message string saying something has an unsupported value
16
+ def self.msg_unsupported(value_name, value)
17
+ return "Unsupported #{value_name}: '#{value}'"
18
+ end
19
+
20
+ # Raise a RuntimeError when 2 things are not identical
21
+ def self.not_identical_raise(value_name, value_1, value_2)
22
+ raise RuntimeError, self.msg_not_identical(value_name, value_1, value_2), caller
23
+ end
24
+
25
+ def self.raise(*args)
26
+ _log_message = ""
27
+ # look for a backtrace to include
28
+ for _arg in args
29
+ if _arg.respond_to? :backtrace
30
+ _log_message << " " << _arg.backtrace.join("\n ")
31
+ end
32
+ end
33
+ # if no backtrace found, add generic
34
+ if _log_message == ""
35
+ _log_message << " " << caller.join("\n ")
36
+ end
37
+ _log_message = "Exception-> " + args.pretty_inspect + _log_message
38
+ GreeLog.error(previous_function_name + "()") {
39
+ _log_message
40
+ }
41
+ Kernel.raise *args
42
+ end
43
+
44
+ # Raise an ArgumentError when an argument has unsupported value
45
+ def self.unsupported_raise(value_name, value)
46
+ raise ArgumentError, self.msg_unsupported(value_name, value), caller
47
+ end
48
+
49
+ # Execute block, ignoring the specified exception type (default: all exceptions)
50
+ def self.with_ignored_exceptions(exception_types = StandardError)
51
+ begin
52
+ yield
53
+ rescue exception_types => _the_exception
54
+ # Ignore the exception
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ # ======================
61
+ # SELF-TEST
62
+ # ======================
63
+
64
+ if $0 == __FILE__
65
+ def test
66
+ GreeLog.handler=Logger.new(
67
+ File.join(File.expand_path(File.dirname(__FILE__)), 'test-' + Time.now.strftime('%Y-%m-%d-%H%M%S') + '.log')
68
+ )
69
+
70
+ begin
71
+ GreeErr.raise 'this is an error message'
72
+ rescue
73
+ end
74
+
75
+ begin
76
+ GreeErr.raise ArgumentError
77
+ rescue
78
+ end
79
+
80
+ begin
81
+ GreeErr.raise ArgumentError, 'this is a message for ArgumentError exception'
82
+ rescue
83
+ end
84
+
85
+ begin
86
+ GreeErr.raise
87
+ rescue
88
+ end
89
+ end
90
+
91
+ test
92
+
93
+ end
@@ -0,0 +1,79 @@
1
+ # Utilities for JSON handling
2
+
3
+ require_relative "gree_logger.rb"
4
+ require 'json'
5
+
6
+ module GreeJson
7
+
8
+ # Validate a JSON response, comparing to an expected hash
9
+ # TODO: add strict parm to check for extra keys
10
+ def self.check_json_response(expected, response)
11
+ begin
12
+ result = JSON.parse(response)
13
+ _validate_json_or_json_array(expected, result)
14
+ rescue => ex
15
+ GreeLog.puts "EXCEPTION: #{ex.message}\n"
16
+ GreeLog.puts "EXPECTED\n#{expected.inspect}\n"
17
+ GreeLog.puts "ACTUAL\n#{response}\nEND"
18
+ # rethrow the message to remove the recursive stack trace
19
+ raise ex.message
20
+ end
21
+ end
22
+
23
+ def self._validate_json_or_json_array(expected, actual)
24
+ if actual.class == Array
25
+ _validate_json_array(expected, actual, actual.count)
26
+ else
27
+ _validate_json(expected, actual)
28
+ end
29
+ end
30
+
31
+ def self._validate_json(expected, actual)
32
+ if actual.nil?
33
+ raise "missing field(s) in response: expected=#{expected} - actual == nil"
34
+ end
35
+ expected.each do |k, v|
36
+ a = actual[k.to_s]
37
+ #if a.nil?
38
+ if !actual.has_key?(k.to_s)
39
+ raise "missing \"#{k}\" property in JSON response, expected: #{v.inspect}"
40
+ end
41
+ case v
42
+ when Hash
43
+ if a.class != Hash
44
+ raise "got #{a.class} instead of JSON object for #{k}"
45
+ end
46
+ _validate_json(v, a)
47
+ when Array
48
+ if a.class != Array
49
+ raise "got JSON object instead of array for #{k}"
50
+ end
51
+ _validate_json_array(v, a, k.to_s)
52
+ when Regexp
53
+ a.should match v
54
+ else
55
+ a.should == v unless v == :any
56
+ end
57
+ end
58
+ end
59
+
60
+ def self._validate_json_array(expected, actual, k)
61
+ if actual.class != Array
62
+ raise "#{k} in response is not an array as expected"
63
+ end
64
+ if expected.count != actual.count
65
+ raise "Error in #{k} array: expected #{expected.count} items, got #{actual.count}"
66
+ end
67
+ expected.each_index do |i|
68
+ _validate_json(expected[i], actual[i])
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+
75
+ # Unit test
76
+ if __FILE__ == $0
77
+
78
+ end
79
+
@@ -0,0 +1,101 @@
1
+ # Utilities for log handling
2
+
3
+ require 'logger'
4
+ require 'pp'
5
+
6
+ class GreeLog
7
+
8
+ @@logger=nil
9
+ @@echo_to_screen = false
10
+
11
+ def self.close
12
+ @@logger.close
13
+ @@logger = nil
14
+ end
15
+
16
+ def self.echo_to_screen
17
+ return @@echo_to_screen
18
+ end
19
+
20
+ def self.echo_to_screen=(value)
21
+ @@echo_to_screen=value
22
+ end
23
+
24
+ def self.logger
25
+ return @@logger
26
+ end
27
+
28
+ def self.logger=(logger_object)
29
+ @@logger=logger_object
30
+ end
31
+
32
+ def self.logging?
33
+ return !@@logger.nil?
34
+ end
35
+
36
+ def self.method_missing(method_name, *method_args, &block)
37
+ if @@echo_to_screen
38
+ puts "[#{Time.now.strftime('%H:%M:%S')}] #{method_name.to_s.upcase} -- #{previous_function_name}: #{method_args.inspect} #{(block ? '{' + block.to_s + '}' : '')}"
39
+ end
40
+ if @@logger
41
+ @@logger.progname = previous_function_name
42
+ @@logger.send(method_name, *method_args, &block)
43
+ end
44
+ end
45
+
46
+ # print out a message without escaping the the quotes, newlines ...
47
+ def self.puts(message)
48
+ if @@echo_to_screen
49
+ Kernel.puts "#{message}"
50
+ end
51
+ if @@logger
52
+ @@logger.progname = previous_function_name
53
+ @@logger.send("info", message)
54
+ end
55
+ end
56
+
57
+ # Returns the name of the function from which this method was called, by looking at the call stack. If call stack
58
+ # is empty, returns "(anonymous)"
59
+ #
60
+ # def foo
61
+ # puts current_function_name
62
+ # end
63
+ #
64
+ # foo -> "foo"
65
+ #
66
+ # current_function_name -> "(anonymous)"
67
+ #
68
+ # Used for logging and error reporting, so that generic code can record the name of the currently running function.
69
+
70
+ def self.current_function_name
71
+ return caller()[0] =~ /in `([^']+)'/ ? $1 : '(anonymous)'
72
+ end
73
+
74
+ # Returns the name of the function two levels down in the call stack. If call stack
75
+ # has insufficient depth, returns "(anonymous)"
76
+ #
77
+ # def foo
78
+ # puts previous_function_name
79
+ # end
80
+ #
81
+ # def bar
82
+ # foo
83
+ # end
84
+ #
85
+ # bar -> "bar"
86
+ #
87
+ # foo -> "(anonymous)"
88
+ #
89
+ # previous_function_name => "(anonymous)"
90
+ #
91
+ # Used for setting up a centralized error handler that calls a centralized logger.
92
+
93
+ def self.previous_function_name
94
+ if caller().length < 2
95
+ return '(anonymous)'
96
+ else
97
+ return caller()[1] =~ /in `([^']+)'/ ? $1 : '(anonymous)'
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,73 @@
1
+ # Gree Ruby Extensions
2
+ # This file provides various convenient extensions to Ruby's built-in objects and libraries
3
+
4
+ unless defined? "INFINITY"
5
+ INFINITY = 1.0/0
6
+ end
7
+
8
+ unless defined? "NaN"
9
+ NaN = 0.0/0
10
+ end
11
+
12
+ class Array
13
+ # Same as <tt>Array.detect</tt>, but scans from end of array to beginning.
14
+ def reverse_detect(&block)
15
+ self.reverse_each {|_element|
16
+ if block.call(_element)
17
+ return _element
18
+ end
19
+ }
20
+ return nil
21
+ end
22
+ end
23
+
24
+ class Hash
25
+ def hash_value_missing?(key)
26
+ # test if key is missing, or key value is nil or empty string
27
+ return !self.has_key?(key) || self[key]=="" || self[key].nil?
28
+ end
29
+ end
30
+
31
+ # Returns the name of the function from which this method was called, by looking at the call stack. If call stack
32
+ # is empty, returns "(anonymous)"
33
+ #
34
+ # def foo
35
+ # puts current_function_name
36
+ # end
37
+ #
38
+ # foo -> "foo"
39
+ #
40
+ # current_function_name -> "(anonymous)"
41
+ #
42
+ # Used for logging and error reporting, so that generic code can record the name of the currently running function.
43
+
44
+ def current_function_name
45
+ return caller()[0] =~ /in `([^']+)'/ ? $1 : '(anonymous)'
46
+ end
47
+
48
+ # Returns the name of the function two levels down in the call stack. If call stack
49
+ # has insufficient depth, returns "(anonymous)"
50
+ #
51
+ # def foo
52
+ # puts previous_function_name
53
+ # end
54
+ #
55
+ # def bar
56
+ # foo
57
+ # end
58
+ #
59
+ # bar -> "bar"
60
+ #
61
+ # foo -> "(anonymous)"
62
+ #
63
+ # previous_function_name => "(anonymous)"
64
+ #
65
+ # Used for setting up a centralized error handler that calls a centralized logger.
66
+
67
+ def previous_function_name
68
+ if caller().length < 2
69
+ return '(anonymous)'
70
+ else
71
+ return caller()[1] =~ /in `([^']+)'/ ? $1 : '(anonymous)'
72
+ end
73
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rest-object
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chaoyi Chen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-27 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: REST API Object DSL for RESTful API testing
15
+ email: chaoyi.chen@gree.net
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/rest-object.rb
21
+ - lib/rest-object/gree_logger.rb
22
+ - lib/rest-object/gree_ruby_extensions.rb
23
+ - lib/rest-object/gree_json.rb
24
+ - lib/rest-object/gree_err.rb
25
+ homepage: http://rubygems.org/gems/hola
26
+ licenses: []
27
+ post_install_message:
28
+ rdoc_options: []
29
+ require_paths:
30
+ - lib
31
+ required_ruby_version: !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 1.8.24
46
+ signing_key:
47
+ specification_version: 3
48
+ summary: REST API Object DSL for RESTful API testing
49
+ test_files: []