right_support 2.11.3 → 2.12.1

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