right_support 2.11.3 → 2.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -0
  3. data/VERSION +1 -1
  4. data/lib/right_support/notifiers/airbrake.rb +194 -0
  5. data/lib/right_support/notifiers/base.rb +73 -0
  6. data/lib/right_support/notifiers/blacklisters/base.rb +48 -0
  7. data/lib/right_support/notifiers/blacklisters/canonical.rb +60 -0
  8. data/lib/right_support/notifiers/blacklisters/regular_expression.rb +86 -0
  9. data/{features/support/file_utils_bundler_mixin.rb → lib/right_support/notifiers/blacklisters/simple.rb} +21 -20
  10. data/lib/right_support/notifiers/blacklisters/snake_case.rb +60 -0
  11. data/lib/right_support/notifiers/blacklisters/wildcard.rb +65 -0
  12. data/lib/right_support/notifiers/blacklisters.rb +34 -0
  13. data/lib/right_support/notifiers/logger.rb +94 -0
  14. data/lib/right_support/notifiers/notification.rb +57 -0
  15. data/lib/right_support/notifiers/utilities/backtrace_decoder.rb +234 -0
  16. data/lib/right_support/notifiers/utilities.rb +29 -0
  17. data/lib/right_support/notifiers.rb +32 -0
  18. data/lib/right_support/rack/request_logger.rb +13 -9
  19. data/lib/right_support.rb +1 -0
  20. data/right_support.gemspec +19 -70
  21. metadata +17 -69
  22. data/.coveralls.yml +0 -2
  23. data/.rspec +0 -3
  24. data/.simplecov +0 -6
  25. data/.travis.yml +0 -13
  26. data/Gemfile +0 -51
  27. data/Gemfile.lock +0 -153
  28. data/features/balancer_error_handling.feature +0 -34
  29. data/features/balancer_health_check.feature +0 -33
  30. data/features/hash_tools.feature +0 -27
  31. data/features/http_client_timeout.feature +0 -19
  32. data/features/serialization.feature +0 -113
  33. data/features/step_definitions/hash_tools_steps.rb +0 -41
  34. data/features/step_definitions/http_client_steps.rb +0 -27
  35. data/features/step_definitions/request_balancer_steps.rb +0 -93
  36. data/features/step_definitions/ruby_steps.rb +0 -176
  37. data/features/step_definitions/serialization_steps.rb +0 -133
  38. data/features/step_definitions/server_steps.rb +0 -134
  39. data/features/support/env.rb +0 -148
  40. data/right_support.rconf +0 -9
  41. data/spec/config/feature_set_spec.rb +0 -83
  42. data/spec/crypto/signed_hash_spec.rb +0 -73
  43. data/spec/data/hash_tools_spec.rb +0 -602
  44. data/spec/data/mash_spec.rb +0 -313
  45. data/spec/data/token_spec.rb +0 -21
  46. data/spec/data/uuid_spec.rb +0 -45
  47. data/spec/db/cassandra_model_part1_spec.rb +0 -84
  48. data/spec/db/cassandra_model_part2_spec.rb +0 -73
  49. data/spec/db/cassandra_model_spec.rb +0 -375
  50. data/spec/fixtures/encrypted_priv_rsa.pem +0 -30
  51. data/spec/fixtures/good_priv_dsa.pem +0 -12
  52. data/spec/fixtures/good_priv_rsa.pem +0 -15
  53. data/spec/fixtures/good_pub_dsa.ssh +0 -1
  54. data/spec/fixtures/good_pub_rsa.pem +0 -5
  55. data/spec/fixtures/good_pub_rsa.ssh +0 -1
  56. data/spec/log/exception_logger_spec.rb +0 -76
  57. data/spec/log/filter_logger_spec.rb +0 -66
  58. data/spec/log/mixin_spec.rb +0 -141
  59. data/spec/log/multiplexer_spec.rb +0 -54
  60. data/spec/log/null_logger_spec.rb +0 -36
  61. data/spec/log/step_level_logger_spec.rb +0 -49
  62. data/spec/log/system_logger_spec.rb +0 -172
  63. data/spec/net/address_helper_spec.rb +0 -57
  64. data/spec/net/dns_spec.rb +0 -187
  65. data/spec/net/http_client_spec.rb +0 -181
  66. data/spec/net/lb/health_check_spec.rb +0 -417
  67. data/spec/net/lb/round_robin_spec.rb +0 -15
  68. data/spec/net/lb/sticky_spec.rb +0 -92
  69. data/spec/net/request_balancer_spec.rb +0 -690
  70. data/spec/net/s3_helper_spec.rb +0 -160
  71. data/spec/net/ssl_spec.rb +0 -42
  72. data/spec/net/string_encoder_spec.rb +0 -58
  73. data/spec/rack/log_setter_spec.rb +0 -5
  74. data/spec/rack/request_logger_spec.rb +0 -225
  75. data/spec/rack/request_tracker_spec.rb +0 -115
  76. data/spec/rack/runtime_spec.rb +0 -49
  77. data/spec/ruby/easy_singleton_spec.rb +0 -72
  78. data/spec/ruby/object_extensions_spec.rb +0 -27
  79. data/spec/ruby/string_extensions_spec.rb +0 -98
  80. data/spec/spec_helper.rb +0 -188
  81. data/spec/stats/activity_spec.rb +0 -425
  82. data/spec/stats/exceptions_spec.rb +0 -247
  83. data/spec/stats/helpers_spec.rb +0 -685
  84. data/spec/validation/openssl_spec.rb +0 -37
  85. data/spec/validation/ssh_spec.rb +0 -39
@@ -1,113 +0,0 @@
1
- Feature: JSON serialization
2
- In order to facilitate Ruby apps' use of external JSON data stores
3
- RightSupport should cleanly serialize arbitrary Ruby objects to JSON without data loss or semantic ambiguity
4
- So app code can be idiomatic and focus on the business problem, not the encoding details
5
-
6
- Background:
7
- Given a serializer named 'RightSupport::Data::Serializer'
8
- And a stateful Ruby class named 'GotState'
9
-
10
- Scenario Outline: Ruby types with a native JSON representation
11
- When I serialize the Ruby value: <ruby>
12
- Then the serialized value should be: <json>
13
- And the serialized value should round-trip cleanly
14
-
15
- Examples:
16
- | ruby | json |
17
- | true | true |
18
- | false | false |
19
- | nil | null |
20
- | 0 | 0 |
21
- | 42 | 42 |
22
- | -32 | -32 |
23
- | 3.1415926535 | 3.1415926535 |
24
- | 0xFFFFFFFFFFFFFFFFFFFFFFFF | 79228162514264337593543950335 |
25
- | "hello, world!" | "hello, world!" |
26
- | [0,true,nil,['a',false]] | [0,true,null,["a",false]] |
27
- | {"one"=>2} | {"one":2} |
28
- | {"hash"=>{"lucky"=>777,"seq"=>[2,3]}} | {"hash":{"lucky":777,"seq":[2,3]}} |
29
-
30
- Scenario: complex Ruby structures with a native JSON representation
31
- When I serialize a complex random data structure
32
- Then the serialized value should round-trip cleanly
33
-
34
- Scenario: invalid UTF-8 characters
35
- When I serialize the Ruby value: "\xC0\xBCscript>\xC0\xBC/script>"
36
- Then the serialized value should have no invalid characters
37
-
38
- Scenario: valid UTF-8 characters
39
- When I serialize the Ruby value: "onê"
40
- Then the serialized value should be: "onê"
41
- And the serialized value should round-trip cleanly
42
-
43
- Scenario Outline: object-escaped Symbol
44
- When I serialize the Ruby value: <ruby>
45
- Then the serialized value should be: <json>
46
- And the serialized value should round-trip cleanly
47
-
48
- Examples:
49
- | ruby | json |
50
- | :my_symbol | ":my_symbol" |
51
- | :'weird symbol' | ":weird symbol" |
52
-
53
- Scenario Outline: object-escaped Time
54
- When I serialize the Ruby value: <ruby>
55
- Then the serialized value should be: <json>
56
- And the serialized value should round-trip cleanly
57
-
58
- Examples:
59
- | ruby | json |
60
- | Time.at(1234567890) | "2009-02-13T23:31:30Z" |
61
- | Time.at(1234567890).utc | "2009-02-13T23:31:30Z" |
62
-
63
- Scenario Outline: object-escaped String
64
- When I serialize the Ruby value: <ruby>
65
- Then the serialized value should be: <json>
66
- And the serialized value should round-trip cleanly
67
-
68
- Examples:
69
- | ruby | json |
70
- | ":not_a_symbol" | {"_ruby_class":"String","value":":not_a_symbol"} |
71
-
72
- Scenario Outline: Ruby Class and Module types
73
-
74
- Scenario Outline: Ruby Class and Module types
75
- When I serialize the Ruby value: <ruby>
76
- Then the serialized value should be a JSON object
77
- And the serialized value should round-trip cleanly
78
-
79
- Examples:
80
- | ruby |
81
- | String |
82
- | RightSupport::Ruby::EasySingleton |
83
- | RightSupport::Net::HTTPClient |
84
- | Hash |
85
- | Kernel |
86
-
87
- Scenario Outline: arbitrary Ruby objects
88
- When I serialize the Ruby value: <ruby>
89
- Then the serialized value should be a JSON object
90
- And the serialized value should have a suitable _ruby_class
91
-
92
- Examples:
93
- | ruby |
94
- | RightSupport::Crypto::SignedHash.new() |
95
- | GotState.new |
96
-
97
- Scenario: arbitrary Ruby object round-trip, happy path
98
- When I serialize the Ruby value: GotState.new
99
- Then the serialized value should round-trip cleanly
100
-
101
- Scenario: arbitrary Ruby object round-trip, sad path
102
- When I serialize the Ruby value: GotState.new
103
- And an eldritch force deletes a key from the serialized value
104
- And the serialized value should fail to round-trip
105
-
106
- Scenario: unrecognized Ruby object class
107
- When I unserialize the JSON value: {"_ruby_class":"DoesNotExist","hello":"world"}
108
- Then the unserialized object should be an RightSupport::Data::UnknownType
109
- And the unserialized object should have a "hello" attribute with value: "world"
110
-
111
- Scenario: unrecognized Ruby object class
112
- When I serialize the Ruby value: RightSupport::Data::UnknownType.new("DoesNotExist", {"hello" => "world"})
113
- Then the serialized value should be: {"_ruby_class":"DoesNotExist","hello":"world"}
@@ -1,41 +0,0 @@
1
- require 'json'
2
-
3
- Given /^a hash map with the form (.*)$/ do |hash|
4
- @hash = JSON.parse(hash)
5
- end
6
-
7
- Given /^a path array (.*)$/ do |path|
8
- @path = JSON.parse(path)
9
- end
10
-
11
- Given /^a value (.*)$/ do |value|
12
- @value = value
13
- end
14
-
15
- When /^I call the deep_get method$/ do
16
- @deep_get_value = RightSupport::Data::HashTools.deep_get(@hash, @path)
17
- end
18
-
19
- When /^I call the deep_set! method$/ do
20
- RightSupport::Data::HashTools.deep_set!(@hash, @path, @value)
21
- end
22
-
23
- When /^I call the deep_merge! method with the source: (.*)$/ do |source|
24
- RightSupport::Data::HashTools.deep_merge!(@hash, JSON.parse(source))
25
- end
26
-
27
- When /^I call the deep_remove! method with the source: (.*)$/ do |source|
28
- RightSupport::Data::HashTools.deep_remove!(@hash, JSON.parse(source))
29
- end
30
-
31
- Then /^The hash should be: (.*)$/ do |hash|
32
- @hash == JSON.parse(hash)
33
- end
34
-
35
- Then /^The deep_get method response should be: (.*)$/ do |expression|
36
- @deep_get_value == expression
37
- end
38
-
39
- Then /^The generate method response should be: (.*)$/ do |expression|
40
- @generated_value == expression
41
- end
@@ -1,27 +0,0 @@
1
- When /^a client makes a (buggy )?request to '(.*)'$/ do |buggy, path|
2
- t = RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:timeout]
3
- o = RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:open_timeout]
4
- When "a client makes a #{buggy}request to '#{path}' with timeout #{t} and open_timeout #{o}"
5
- end
6
-
7
-
8
- When /^a client makes a (buggy )?request to '(.*)' with timeout (\d+) and open_timeout (\d+)$/ do |buggy, path, timeout, open_timeout|
9
- buggy = !(buggy.nil? || buggy.empty?)
10
-
11
- @mock_servers.should_not be_nil
12
- @mock_servers.size.should == 1
13
-
14
- timeout = timeout.to_i
15
- open_timeout = open_timeout.to_i
16
- url = @mock_servers.first.url
17
-
18
- @http_client = RightSupport::Net::HTTPClient.new(:timeout=>timeout, :open_timeout=>open_timeout)
19
- @request_t0 = Time.now
20
- begin
21
- raise ArgumentError, "Fall down go boom!" if buggy
22
- @http_client.get("#{url}#{path}", {:timeout => timeout, :open_timeout => open_timeout})
23
- rescue Exception => e
24
- @request_error = e
25
- end
26
- @request_t1 = Time.now
27
- end
@@ -1,93 +0,0 @@
1
- # Rails' constantize method to convert passed in policy to the actual class
2
- def constantize(camel_cased_word)
3
- names = camel_cased_word.split('::')
4
- names.shift if names.empty? || names.first.empty?
5
-
6
- constant = Object
7
- names.each do |name|
8
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
9
- end
10
- constant
11
- end
12
-
13
- Given /^(\w+) balancing policy$/ do |policy|
14
- @health_check = Proc.new do |endpoint|
15
- begin
16
- RightSupport::Net::HTTPClient.new.get(endpoint, {:timeout => 1, :open_timeout => 1})
17
- true
18
- rescue Exception => e
19
- false
20
- end
21
- end
22
-
23
- @options ||= { :policy => constantize("RightSupport::Net::LB::" + policy), :health_check => @health_check }
24
- end
25
-
26
- When /^a client makes a (buggy )?load-balanced request to '(.*)'$/ do |buggy, path|
27
- t = RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:timeout]
28
- o = RightSupport::Net::HTTPClient::DEFAULT_OPTIONS[:open_timeout]
29
- step "a client makes a #{buggy}load-balanced request to '#{path}' with timeout #{t} and open_timeout #{o}"
30
- end
31
-
32
- When /^a client makes a (buggy )?load-balanced request to '(.*)' with timeout (\d+) and open_timeout (\d+)$/ do |buggy, path, timeout, open_timeout|
33
- buggy = !(buggy.nil? || buggy.empty?)
34
-
35
- @mock_servers.should_not be_nil
36
- @mock_servers.empty?.should be_false
37
-
38
- timeout = timeout.to_i
39
- open_timeout = open_timeout.to_i
40
- urls = @mock_servers.map { |s| s.url }
41
- @request_balancer = RightSupport::Net::RequestBalancer.new(urls)
42
- @request_attempts = 0
43
- @request_t0 = Time.now
44
- @http_client = RightSupport::Net::HTTPClient.new
45
- begin
46
- @request_balancer.request do |url|
47
- @request_attempts += 1
48
- raise ArgumentError, "Fall down go boom!" if buggy
49
- @http_client.get("#{url}#{path}", {:timeout => timeout, :open_timeout => open_timeout})
50
- end
51
- rescue Exception => e
52
- @request_error = e
53
- end
54
- @request_t1 = Time.now
55
- end
56
-
57
- Then /^the request should (\w+ ?\w*)$/ do |behavior|
58
- case behavior
59
- when 'complete'
60
- error_expected = false
61
- when 'raise'
62
- error_expected = true
63
- when /raise (\w+)/
64
- error_expected = true
65
- error_class_expected = /raise (\w+)/.match(behavior)[1]
66
- else
67
- raise ArgumentError, "Unknown request behavior #{behavior}"
68
- end
69
-
70
- if !error_expected && @request_error
71
- puts '!' * 80
72
- puts @request_error.class.inspect
73
- puts @request_error.class.superclass.inspect
74
- puts '!' * 80
75
- end
76
- @request_error.should be_nil unless error_expected
77
- @request_error.should_not be_nil if error_expected
78
- @request_error.class.name.should =~ Regexp.new(error_class_expected) if error_class_expected
79
- end
80
-
81
- Then /^the request should (\w+ ?\w*) in less than (\d+) seconds?$/ do |behavior, time|
82
- step "the request should #{behavior}"
83
- #allow 10% margin of error due to Ruby/OS scheduler variance
84
- (@request_t1.to_f - @request_t0.to_f).should <= (time.to_f * 1.10)
85
- end
86
-
87
- Then /^the request should be attempted once$/ do
88
- @request_attempts.should == 1
89
- end
90
-
91
- Then /^the request should be attempted ([0-9]+) times$/ do |n|
92
- @request_attempts.should == n.to_i
93
- end
@@ -1,176 +0,0 @@
1
- require 'nokogiri'
2
-
3
- Given /^a Ruby application$/ do
4
- ruby_app_root.should_not be_nil
5
- end
6
-
7
- Given /^a Gemfile$/ do
8
- gemfile = ruby_app_path('Gemfile')
9
- unless File.exist?(gemfile)
10
- basedir = File.expand_path('../../..', __FILE__)
11
- File.open(gemfile, 'w') do |file|
12
- file.puts "gem 'right_support', :path=>'#{basedir}'"
13
- end
14
- end
15
- end
16
-
17
- Given /^a gem dependency on '(.*)'$/ do |dependency|
18
- step 'a Gemfile'
19
- gem, version = dependency.split(/\s+/, 2)
20
- gemfile = ruby_app_path('Gemfile')
21
- File.open(gemfile, 'a') do |file|
22
- file.puts "gem '#{gem}', '#{version}'"
23
- end
24
- end
25
-
26
- Given /^a Rakefile$/ do
27
- rakefile = ruby_app_path('Rakefile')
28
- unless File.exist?(rakefile)
29
- File.open(rakefile, 'w') do |file|
30
- file.puts "# Auto-generated by #{__FILE__}"
31
- end
32
- end
33
- end
34
-
35
- Given /^the Rakefile contains a RightSupport::CI::RakeTask$/ do
36
- step 'a Rakefile'
37
- rakefile = ruby_app_path('Rakefile')
38
- File.open(rakefile, 'w') do |file|
39
- file.puts "require 'right_support/ci/rake_task'"
40
- file.puts "RightSupport::CI::RakeTask.new"
41
- end
42
- end
43
-
44
- Given /^the Rakefile contains a RightSupport::CI::RakeTask with parameter '(.*)'$/ do |ns|
45
- step 'a Rakefile'
46
- rakefile = ruby_app_path('Rakefile')
47
- File.open(rakefile, 'w') do |file|
48
- file.puts "require 'right_support/ci/rake_task'"
49
- file.puts "RightSupport::CI::RakeTask.new(#{ns})"
50
- end
51
- end
52
-
53
- Given /^a trivial (failing )?RSpec spec$/ do |failing|
54
- spec_dir = ruby_app_path('spec')
55
- spec = ruby_app_path('spec', 'trivial_spec.rb')
56
- FileUtils.mkdir_p(spec_dir)
57
- unless File.exist?(spec)
58
- File.open(spec, 'w') do |file|
59
- file.puts "describe String do"
60
- file.puts " it 'has a size' do"
61
- file.puts " 'joe'.size.should == 3"
62
- file.puts " end"
63
- file.puts
64
- file.puts " it 'is stringy' do"
65
- file.puts " pending"
66
- file.puts " end"
67
- unless failing.nil?
68
- file.puts
69
- file.puts "it 'meets an impossible ideal' do"
70
- file.puts " raise NotImplementedError, 'inconceivable!'"
71
- file.puts "end"
72
- end
73
- file.puts "end"
74
- end
75
- end
76
- end
77
-
78
- Given /^a trivial (failing )?Cucumber feature$/ do |failing|
79
- features_dir = ruby_app_path('features')
80
- steps_dir = ruby_app_path('features', 'step_definitions')
81
- feature = ruby_app_path('features', 'trivial.feature')
82
- steps = ruby_app_path('features', 'step_definitions', 'trivial_steps.rb')
83
- FileUtils.mkdir_p(features_dir)
84
- FileUtils.mkdir_p(steps_dir)
85
-
86
- unless File.exist?(steps)
87
- File.open(steps, 'w') do |file|
88
- file.puts "When /^the night has come and the land is dark$/ do; end"
89
- file.puts "When /^the moon is the only light we see$/ do; end"
90
- file.puts "Then /^I won't be afraid.*$/ do; end"
91
- file.puts "Then /^as long as you stand.*by me$/ do; end"
92
- file.puts "Then /^you run away as fast as you can$/ do; raise NotImplementedError; end"
93
- end
94
- end
95
- unless File.exist?(feature)
96
- File.open(feature, 'w') do |file|
97
- file.puts "Feature: Song Lyrics from the 1950s"
98
- file.puts
99
- file.puts " Scenario: Stand By Me"
100
- file.puts " When the night has come and the land is dark"
101
- file.puts " And the moon is the only light we see"
102
- file.puts " Then I won't be afraid, oh, I won't be afraid"
103
- if failing.nil?
104
- file.puts " And as long as you stand, stand by me"
105
- else
106
- file.puts " And you run away as fast as you can"
107
- end
108
- end
109
- end
110
- end
111
-
112
- When /^I install the bundle$/ do
113
- ruby_app_shell('bundle install')
114
- end
115
-
116
- When /^I rake '(.*)'$/ do |task|
117
- @ruby_app_output = ruby_app_shell("bundle exec rake #{task} --trace ", :ignore_errors => true)
118
- end
119
-
120
- When /^I debug the app shell$/ do
121
- STDOUT.puts "Opening shell in a separate window."
122
- if RUBY_PLATFORM =~ /darwin/
123
- ruby_app_shell("open -a Terminal .")
124
- else
125
- raise "Don't know how to open an app shell for #{RUBY_PLATFORM}; please contribute your knowledge to #{__FILE__}"
126
- end
127
- STDOUT.puts "Press Enter to continue Cucumber execution..."
128
- STDOUT.flush
129
- STDIN.readline
130
- end
131
-
132
- Then /^the output should contain '(.*)'$/ do |expected_output|
133
- @ruby_app_output.should include(expected_output)
134
- end
135
-
136
- Then /^the output should not contain '(.*)'$/ do |expected_output|
137
- @ruby_app_output.should_not include(expected_output)
138
- end
139
-
140
- Then /^the directory '(.*)' should contain files/ do |dir|
141
- dir = ruby_app_path(dir)
142
- File.directory?(dir).should be_true
143
- Dir[File.join(dir, '*')].should_not be_empty
144
- end
145
-
146
- Then /^the file '(.*)' should mention ([0-9]) (passing|failing) test cases?$/ do |file, n, pass_fail|
147
- file = ruby_app_path(file)
148
- n = Integer(n)
149
-
150
- Pathname.new(file).should exist
151
-
152
- doc = Nokogiri.XML(File.open(file, 'r'))
153
-
154
- all_testcases = doc.css('testcase').size
155
- failing_testcases = doc.css('testcase failure').size
156
- passing_testcases = all_testcases - failing_testcases
157
-
158
- case pass_fail
159
- when 'passing'
160
- passing_testcases.should == n
161
- when 'failing'
162
- failing_testcases.should == n
163
- else
164
- raise NotImplementedError, "WTF #{pass_fail}"
165
- end
166
- end
167
-
168
- Then /^the command should (succeed|fail)$/ do |success|
169
- if success == 'succeed'
170
- $?.exitstatus.should == 0
171
- elsif success == 'fail'
172
- $?.exitstatus.should_not == 0
173
- else
174
- raise NotImplementedError, "Unknown expectation #{success}"
175
- end
176
- end
@@ -1,133 +0,0 @@
1
- Given /^a serializer named '(.+)'$/ do |klass|
2
- @serializer = klass.to_const
3
- end
4
-
5
- Given /^a stateful Ruby class named '(.*)'$/ do |name|
6
- name = name.to_sym
7
- ivars = 1 + rand(10)
8
-
9
-
10
- Kernel.__send__(:remove_const, name) if Kernel.const_defined?(name)
11
-
12
- @stateful_ruby_class = Class.new(Object)
13
- Kernel.__send__(:const_set, name, @stateful_ruby_class)
14
-
15
- @stateful_ruby_class.instance_eval do
16
- define_method(:initialize) do
17
- ivars.times do
18
- self.instance_variable_set("@instance_variable_#{random_value(Integer)}", random_value(nil, [String]))
19
- end
20
- end
21
-
22
- define_method(:==) do |other|
23
- result = (Set.new(self.instance_variables) == Set.new(other.instance_variables))
24
-
25
- self.instance_variables.each do |ivar|
26
- result &&= (self.instance_variable_get(ivar) == other.instance_variable_get(ivar))
27
- end
28
-
29
- result
30
- end
31
- end
32
- end
33
-
34
- When /^I serialize the Ruby value: (.*)$/ do |expression|
35
- @ruby_value = eval(expression)
36
- @serialized_value = @serializer.dump(@ruby_value)
37
- end
38
-
39
- When /^I unserialize the JSON value: (.*)$/ do |value|
40
- @serialized_value = value
41
- @ruby_value = @serializer.load(@serialized_value)
42
- end
43
-
44
- When /^I serialize a complex random data structure$/ do
45
- @ruby_value = random_value(nil, [String])
46
- @serialized_value = @serializer.dump(@ruby_value)
47
- end
48
-
49
- When /^an eldritch force deletes a key from the serialized value$/ do
50
- hash = RightSupport::Data::Serializer::Encoder.load(@serialized_value)
51
- hash.delete(hash.keys[rand(hash.keys.size)])
52
- @serialized_value = @serializer.dump(hash)
53
- end
54
-
55
- Then /^the serialized value should be: (.*)$/ do |expression|
56
- if (@serialized_value =~ /^\{/) || (expression =~ /^\{/)
57
- # Hash: ordering of JSON representation is unimportant; load as pure JSON and compare values
58
- RightSupport::Data::Serializer::Encoder.load(@serialized_value).should ==
59
- RightSupport::Data::Serializer::Encoder.load(expression)
60
- else
61
- # Any other data: exact comparison
62
- @serialized_value.should == expression
63
- end
64
- end
65
-
66
- Then /^the serialized value should round-trip cleanly$/ do
67
- case @ruby_value
68
- when Float
69
- # Floating-point numbers lose some precision due to truncation
70
- @serializer.load(@serialized_value).should be_within(0.000001).of(@ruby_value)
71
- when Time
72
- # Times are stored with accuracy ~ 1 sec
73
- @serializer.load(@serialized_value).to_i.should == @ruby_value.to_i
74
- else
75
- # Everything else should compare identical
76
- @serializer.load(@serialized_value).should == @ruby_value
77
- end
78
- end
79
-
80
- Then /^the serialized value should have no invalid characters$/ do
81
- if @serialized_value.respond_to?(:valid_encoding?)
82
- # modern Rubies
83
- @serialized_value.valid_encoding?.should be_true
84
- else
85
- # Ruby 1.8
86
- raised = false
87
- begin
88
- iconv = Iconv.new('UTF-8', 'UTF-8')
89
- iconv.iconv(@serialized_value)
90
- rescue Exception => e
91
- raised = true
92
- end
93
-
94
- raised.should be_false
95
- end
96
- end
97
-
98
- When /^the serialized value should fail to round\-trip$/ do
99
- @serializer.load(@serialized_value).should_not == @ruby_value
100
- end
101
-
102
- Then /^the serialized value should be a JSON (.*)$/ do |json_type|
103
- case json_type
104
- when 'object'
105
- @serialized_value.should =~ /^\{.*\}$/
106
- when 'string'
107
- @serialized_value.should =~ /^".*"$/
108
- when 'number'
109
- @serialized_value.should =~ /^".*"$/
110
- when 'true', 'false', 'null'
111
- @serialized_value.should == json_type
112
- else
113
- raise NotImplementedError, "Unknown JSON type"
114
- end
115
- end
116
-
117
- Then /^the serialized value should have a suitable _ruby_class$/ do
118
- @serialized_value.should =~ /"_ruby_class":"#{Regexp.escape(@ruby_value.class.name)}"/
119
- end
120
-
121
- Then /^the unserialized object should be an? (.*)$/ do |class_name|
122
- klass = class_name.to_const
123
- klass.should_not be_nil
124
- @ruby_value.should be_a(klass)
125
- end
126
-
127
- Then /^the unserialized object should have a "(.*)" attribute with value: (.*)$/ do |attr, value|
128
- attr = attr.to_sym
129
- value = eval(value)
130
-
131
- @ruby_value.should respond_to(attr)
132
- @ruby_value.__send__(attr).should == value
133
- end