serf 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,10 +1,18 @@
1
- # Gemfile.lock because this is a library, not a deployable application.
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
2
6
  Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
3
9
  coverage
4
- rdoc
5
- doc
6
- .yardoc
7
- .bundle
8
- vendor
10
+ doc/
11
+ lib/bundler/man
9
12
  pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
10
17
  tmp
18
+ vendor
@@ -2,6 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - "1.9.2"
4
4
  - "1.9.3"
5
- - jruby-19mode # JRuby in 1.9 mode
6
- - rbx-19mode
5
+ - "jruby-19mode"
6
+ - "rbx-19mode"
7
+ - "ruby-head"
8
+ - "jruby-head"
7
9
  script: bundle exec rake spec
data/README.md CHANGED
@@ -31,13 +31,20 @@ the Domain Layer's Model (Entities, Value Objects and Entity Gateways).
31
31
 
32
32
  1. Include the "Serf::Interactor" module in your class.
33
33
  2. Implement the 'call(parcel)' method.
34
- 3. Return the tuple: (kind, message)
34
+ 3. Return the tuple: (kind, message, headers)
35
35
  a. The kind is the string representation of the message type,
36
36
  This field is RECOMMENDED.
37
37
  b. The message field provides detailed return data about the
38
- interactor's processing.
38
+ interactor's processing. The main meat of the Domain Object.
39
39
  Hashie::Mash is suggested for the message, nil is acceptable.
40
- c. By default, returning nil for both kind and message will still
40
+ c. The headers are OPTIONAL. The headers are there primarily to return
41
+ out of band data about the processing of the request. For example,
42
+ the Interactor can return debug tags about connections to external
43
+ databases.
44
+ The *ONE* semantic relevant piece of information is that the
45
+ Interactor may specify the version the domain object, as represented
46
+ by the message of type 'kind', in the 'version' header field.
47
+ d. By default, returning nil for both kind and message will still
41
48
  result in a response parcel signifying that some Interactor received
42
49
  the inbound parcel. But that is just a almost worthless piece of
43
50
  information for the observer.
@@ -106,6 +113,7 @@ For example,
106
113
  Serf *RESERVES* the following set of header names:
107
114
 
108
115
  * kind
116
+ * version
109
117
  * message
110
118
  * uuid
111
119
  * parent_uuid
@@ -134,6 +142,13 @@ may be used to route messages over messaging channels to Interactors.
134
142
  The convention is 'mymodule/requests/my_business_request' for Requests,
135
143
  and 'mymodule/events/my_business_event' for Events.
136
144
 
145
+ *version* field MAY be used to identify the semantic version of the
146
+ message of the given 'kind'. The triplet of (kind, version, message)
147
+ constitutes the prime parts of domain object as represented by the
148
+ parcel. All other header fields are incidental data that pertain to
149
+ the processing. This field is optional, and is returned in the
150
+ headers portion of the interactor's return results.
151
+
137
152
  *UUIDs* are used to track request and events, providing a sequential
138
153
  order of execution of commands. Already Implemented by Serf middleware.
139
154
 
@@ -320,7 +335,9 @@ Serf Builder Example
320
335
  raise 'Error' if parcel.message.raise_an_error
321
336
 
322
337
  # And return a message as result. Nil is valid response.
323
- return 'my_lib/events/success_event', { success: true }
338
+ return 'my_lib/events/success_event',
339
+ { success: true },
340
+ { version: "1.2.3" }
324
341
 
325
342
  # Optionally just return the kind
326
343
  # return 'my_lib/events/success_event'
@@ -28,19 +28,38 @@ module Serf
28
28
  ##
29
29
  # Set a default chain of the following:
30
30
  #
31
+ # use_default_middleware
32
+ # use_default_serfer_stage
33
+ #
34
+ def use_defaults
35
+ use_default_middleware
36
+ use_default_serfer_stage
37
+ end
38
+
39
+ ##
40
+ # Add the following middleware to the chain:
41
+ #
42
+ # use Serf::Middleware::RequestTimer
31
43
  # use Serf::Middleware::ParcelMasher
32
44
  # use Serf::Middleware::UuidTagger
33
- # use Serf::Middleware::ParcelFreezer
34
45
  # use Serf::Middleware::ErrorHandler
35
- # use Serf::Middleware::PolicyChecker, @policy_chain
36
- # use Serf::Serfer
37
46
  #
38
- def use_defaults
47
+ def use_default_middleware
39
48
  use Serf::Middleware::RequestTimer
40
49
  use Serf::Middleware::ParcelMasher
41
50
  use Serf::Middleware::UuidTagger
42
- use Serf::Middleware::ParcelFreezer
43
51
  use Serf::Middleware::ErrorHandler
52
+ end
53
+
54
+ ##
55
+ # Add the following middleware to the chain:
56
+ #
57
+ # use Serf::Middleware::ParcelFreezer
58
+ # use Serf::Middleware::PolicyChecker, @policy_chain
59
+ # use Serf::Serfer
60
+ #
61
+ def use_default_serfer_stage
62
+ use Serf::Middleware::ParcelFreezer
44
63
  use Serf::Middleware::PolicyChecker, policy_chain: @policy_chain
45
64
  use Serf::Serfer
46
65
  end
@@ -0,0 +1,17 @@
1
+ module Serf
2
+ module Errors
3
+
4
+ ##
5
+ # An error occurred while loading serfs.
6
+ #
7
+ class LoadFailure < RuntimeError
8
+ attr_accessor :cause
9
+
10
+ def initialize(message=nil, cause=nil)
11
+ @cause = cause
12
+ super(message)
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -2,6 +2,7 @@ require 'hashie'
2
2
  require 'optser'
3
3
 
4
4
  require 'serf/builder'
5
+ require 'serf/errors/load_failure'
5
6
  require 'serf/loader/registry'
6
7
 
7
8
  module Serf
@@ -63,9 +64,13 @@ module Loader
63
64
  globs.each do |glob_pattern|
64
65
  globs = Dir.glob File.join(base_path, glob_pattern)
65
66
  globs.each do |filename|
66
- File.open filename do |file|
67
- contents = file.read
68
- instance_eval(contents)
67
+ begin
68
+ File.open filename do |file|
69
+ contents = file.read
70
+ instance_eval(contents)
71
+ end
72
+ rescue => e
73
+ raise Serf::Errors::LoadFailure.new "File: #{filename}", e
69
74
  end
70
75
  end
71
76
  end
@@ -73,7 +78,11 @@ module Loader
73
78
  # Construct all the "serfs"
74
79
  map = Hashie::Mash.new
75
80
  serfs.each do |serf|
76
- map[serf] = @registry[serf]
81
+ begin
82
+ map[serf] = @registry[serf]
83
+ rescue => e
84
+ raise Serf::Errors::LoadFailure.new "Kind: #{serf}", e
85
+ end
77
86
  raise "Missing Serf: #{serf}" if map[serf].nil?
78
87
  end
79
88
 
@@ -1,6 +1,8 @@
1
1
  require 'hashie'
2
2
  require 'optser'
3
3
 
4
+ require 'serf/errors/load_failure'
5
+
4
6
  module Serf
5
7
  module Loader
6
8
 
@@ -47,6 +49,7 @@ module Loader
47
49
  class Registry
48
50
  attr_reader :blocks
49
51
  attr_reader :values
52
+ attr_reader :env
50
53
 
51
54
  def initialize(*args)
52
55
  opts = Optser.extract_options! args
@@ -62,7 +65,7 @@ module Loader
62
65
  # @params &block the proc that generates the component instance.
63
66
  #
64
67
  def add(name, &block)
65
- @blocks[name.to_sym] = block
68
+ blocks[name.to_sym] = block
66
69
  end
67
70
 
68
71
  ##
@@ -73,11 +76,18 @@ module Loader
73
76
  #
74
77
  def [](name)
75
78
  name = name.to_sym
76
- return @values[name] if @values.has_key? name
79
+ return values[name] if values.has_key? name
77
80
  # No memoized value, so grab the block, call it and memoize it
78
81
  # return the block's return value, or nil.
79
- if block = @blocks.delete(name)
80
- @values[name] = block.call self, @env
82
+ if block = blocks[name]
83
+ begin
84
+ value = block.call self, env
85
+ values[name] = value
86
+ blocks.delete name
87
+ return value
88
+ rescue => e
89
+ raise Serf::Errors::LoadFailure.new("Name: #{name}", e)
90
+ end
81
91
  end
82
92
  end
83
93
 
@@ -26,16 +26,29 @@ module Serf
26
26
  #
27
27
  def call(parcel)
28
28
  # 1. Execute interactor
29
- response_kind, response_message = interactor.call parcel
30
-
31
- # 2. Return a new response parcel with:
29
+ response_kind, response_message, response_headers = interactor.call parcel
30
+
31
+ # 2. Extract a possible version embedded in the response_kind.
32
+ # This is sugar syntax for kind and version.
33
+ if response_kind
34
+ kind_part, version_part = response_kind.split '#', 2
35
+ response_kind = kind_part if version_part
36
+ if version_part
37
+ response_headers ||= {}
38
+ response_headers[:version] = version_part
39
+ end
40
+ end
41
+
42
+ # 3. Return a new response parcel with:
32
43
  # a. uuids set from parent parcel
33
44
  # b. kind set to response kind
34
45
  # c. the message set to response_message
46
+ # d. add extra headers to the parcel
35
47
  return parcel_factory.create(
36
48
  parent: parcel,
37
49
  kind: response_kind,
38
- message: response_message)
50
+ message: response_message,
51
+ headers: response_headers)
39
52
  end
40
53
 
41
54
  end
@@ -1,3 +1,5 @@
1
+ require 'socket'
2
+
1
3
  require 'serf/util/protected_call'
2
4
 
3
5
  module Serf
@@ -31,6 +33,7 @@ module Util
31
33
  error: e.class.to_s,
32
34
  message: e.message,
33
35
  process_env: ENV.to_hash,
36
+ hostname: Socket.gethostname,
34
37
  backtrace: e.backtrace.join("\n")
35
38
  }
36
39
  end
@@ -42,6 +42,18 @@ module Util
42
42
  uuid_tool.parse_raw Base64.urlsafe_decode64("#{coded_uuid}==")
43
43
  end
44
44
 
45
+ ##
46
+ # Parses a coded_uuid and returns a time object for the Timestamped UUID.
47
+ #
48
+ # @param coded_uuid the coded uuid from which to get a time.
49
+ #
50
+ # @return ruby time object for which the coded_uuid was timestamped.
51
+ #
52
+ def coded_uuid_time(coded_uuid)
53
+ uuid = parse_coded_uuid coded_uuid
54
+ uuid.timestamp.utc
55
+ end
56
+
45
57
  ##
46
58
  # Create a new set of uuids.
47
59
  #
@@ -1,11 +1,3 @@
1
1
  module Serf
2
-
3
- module Version
4
- MAJOR = 0
5
- MINOR = 14
6
- PATCH = 0
7
- BUILD = nil
8
- STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join '.'
9
- end
10
-
2
+ VERSION = '0.15.0'
11
3
  end
@@ -3,16 +3,29 @@
3
3
  "type": "object",
4
4
  "properties": {
5
5
  "error": {
6
- "type": "string"
6
+ "description": "The error class",
7
+ "type": "string",
8
+ "required": true
7
9
  },
8
10
  "message": {
9
- "type": "string"
11
+ "description": "The description of the error",
12
+ "type": "string",
13
+ "required": true
10
14
  },
11
15
  "process_env": {
12
- "type": "object"
16
+ "description": "The ENV context of the error",
17
+ "type": "object",
18
+ "required": true
19
+ },
20
+ "hostname": {
21
+ "description": "The hostname of the process of the error",
22
+ "type": "string",
23
+ "required": true
13
24
  },
14
25
  "backtrace": {
15
- "type": "string"
26
+ "description": "The backtrace of the error",
27
+ "type": "string",
28
+ "required": true
16
29
  }
17
30
  }
18
31
  }
@@ -1,9 +1,11 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/serf/version', __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'serf/version'
3
5
 
4
6
  Gem::Specification.new do |gem|
5
7
  gem.name = 'serf'
6
- gem.version = Serf::Version::STRING
8
+ gem.version = Serf::VERSION
7
9
  gem.authors = ['Benjamin Yu']
8
10
  gem.email = 'benjaminlyu@gmail.com'
9
11
  gem.description = 'Interactors with policy protection'
@@ -0,0 +1,3 @@
1
+ registry.add 'spec/data/bad_construction' do |r, env|
2
+ raise 'Intentional Construction Error'
3
+ end
@@ -0,0 +1 @@
1
+ raise 'Intentional Error'
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'serf/errors/load_failure'
3
4
  require 'serf/loader/loader'
4
5
 
5
6
  describe Serf::Loader::Loader do
@@ -14,7 +15,8 @@ describe Serf::Loader::Loader do
14
15
  subject {
15
16
  Serf::Loader::Loader.new.serfup(
16
17
  globs: [
17
- 'example/**/*.serf'
18
+ 'example/components/**/*.serf',
19
+ 'example/serfs/**/*.serf'
18
20
  ],
19
21
  serfs: [
20
22
  'subsystem/requests/create_widget'
@@ -70,4 +72,44 @@ describe Serf::Loader::Loader do
70
72
  end
71
73
  end
72
74
 
75
+ context '#serfup with construction error' do
76
+ let(:serfup_config) {
77
+ Hashie::Mash.new(
78
+ globs: [
79
+ 'spec/data/construction_error.serf'
80
+ ],
81
+ serfs: [
82
+ 'spec/data/bad_construction'
83
+ ])
84
+ }
85
+
86
+ it 'raises an error' do
87
+ expect {
88
+ Serf::Loader::Loader.new.serfup serfup_config
89
+ }.to raise_error { |error|
90
+ expect(error).to be_a(Serf::Errors::LoadFailure)
91
+ expect(error.message).to match(/Kind: .+$/)
92
+ }
93
+ end
94
+ end
95
+
96
+ context '#serfup Serf Map bad serf file' do
97
+ let(:serfup_config) {
98
+ Hashie::Mash.new(
99
+ globs: [
100
+ 'spec/data/raises_error.serf'
101
+ ],
102
+ serfs: [])
103
+ }
104
+
105
+ it 'raises an error' do
106
+ expect {
107
+ Serf::Loader::Loader.new.serfup serfup_config
108
+ }.to raise_error { |error|
109
+ expect(error).to be_a(Serf::Errors::LoadFailure)
110
+ expect(error.message).to match(/^File: .+$/)
111
+ }
112
+ end
113
+ end
114
+
73
115
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
+ require 'serf/errors/load_failure'
3
4
  require 'serf/loader/registry'
4
5
 
5
6
  describe Serf::Loader::Registry do
@@ -59,4 +60,18 @@ describe Serf::Loader::Registry do
59
60
  end
60
61
  end
61
62
 
63
+ context '#[] with error' do
64
+ it 'raises LoadFailure on error' do
65
+ subject.add 'component_name' do
66
+ raise 'Intentional Error'
67
+ end
68
+ expect {
69
+ subject['component_name']
70
+ }.to raise_error { |error|
71
+ expect(error).to be_a(Serf::Errors::LoadFailure)
72
+ expect(error.message).to match(/^Name: .+$/)
73
+ }
74
+ end
75
+ end
76
+
62
77
  end
@@ -14,7 +14,8 @@ describe Serf::Loader do
14
14
  subject {
15
15
  Serf::Loader.serfup(
16
16
  globs: [
17
- 'example/**/*.serf'
17
+ 'example/components/**/*.serf',
18
+ 'example/serfs/**/*.serf'
18
19
  ],
19
20
  serfs: [
20
21
  'subsystem/requests/create_widget'
@@ -11,12 +11,21 @@ describe Serf::Serfer do
11
11
  let(:request_parcel) {
12
12
  FactoryGirl.create :random_parcel
13
13
  }
14
+ let(:versioned_response_kind_version) {
15
+ SecureRandom.hex
16
+ }
17
+ let(:versioned_response_kind) {
18
+ "#{response_kind}\##{versioned_response_kind_version}"
19
+ }
14
20
  let(:response_kind) {
15
21
  SecureRandom.hex
16
22
  }
17
23
  let(:response_message) {
18
24
  FactoryGirl.create :random_hash
19
25
  }
26
+ let(:response_headers) {
27
+ FactoryGirl.create :random_hash
28
+ }
20
29
  let(:disconnected_response_parcel) {
21
30
  FactoryGirl.create :random_parcel
22
31
  }
@@ -49,14 +58,55 @@ describe Serf::Serfer do
49
58
  expect(parcel.message).to eq(response_message)
50
59
  end
51
60
 
52
- it 'uses parcel factory w/ kind, parent and message' do
61
+ it 'uses parcel factory w/ parent (w/ nil kind+message+headers)' do
62
+ mock_parcel_factory = double 'parcel_factory'
63
+ mock_parcel_factory.
64
+ should_receive(:create).
65
+ with({
66
+ parent: request_parcel,
67
+ kind: nil,
68
+ message: nil,
69
+ headers: nil
70
+ }).
71
+ and_return(disconnected_response_parcel)
72
+
73
+ serfer = described_class.new(
74
+ lambda { |obj| },
75
+ parcel_factory: mock_parcel_factory)
76
+ parcel = serfer.call request_parcel
77
+
78
+ expect(parcel).to eq(disconnected_response_parcel)
79
+ end
80
+
81
+ it 'uses parcel factory w/ kind, parent (w/ nil message+headers)' do
82
+ mock_parcel_factory = double 'parcel_factory'
83
+ mock_parcel_factory.
84
+ should_receive(:create).
85
+ with({
86
+ parent: request_parcel,
87
+ kind: response_kind,
88
+ message: nil,
89
+ headers: nil
90
+ }).
91
+ and_return(disconnected_response_parcel)
92
+
93
+ serfer = described_class.new(
94
+ lambda { |obj| return response_kind },
95
+ parcel_factory: mock_parcel_factory)
96
+ parcel = serfer.call request_parcel
97
+
98
+ expect(parcel).to eq(disconnected_response_parcel)
99
+ end
100
+
101
+ it 'uses parcel factory w/ kind, parent and message (w/ nil headers)' do
53
102
  mock_parcel_factory = double 'parcel_factory'
54
103
  mock_parcel_factory.
55
104
  should_receive(:create).
56
105
  with({
57
106
  parent: request_parcel,
58
107
  kind: response_kind,
59
- message: response_message
108
+ message: response_message,
109
+ headers: nil
60
110
  }).
61
111
  and_return(disconnected_response_parcel)
62
112
 
@@ -68,6 +118,52 @@ describe Serf::Serfer do
68
118
  expect(parcel).to eq(disconnected_response_parcel)
69
119
  end
70
120
 
121
+ it 'uses parcel factory w/ kind, parent, message and headers' do
122
+ mock_parcel_factory = double 'parcel_factory'
123
+ mock_parcel_factory.
124
+ should_receive(:create).
125
+ with({
126
+ parent: request_parcel,
127
+ kind: response_kind,
128
+ message: response_message,
129
+ headers: response_headers
130
+ }).
131
+ and_return(disconnected_response_parcel)
132
+
133
+ serfer = described_class.new(
134
+ lambda { |obj|
135
+ return response_kind, response_message, response_headers
136
+ },
137
+ parcel_factory: mock_parcel_factory)
138
+ parcel = serfer.call request_parcel
139
+
140
+ expect(parcel).to eq(disconnected_response_parcel)
141
+ end
142
+
143
+ it 'moves version info from a versioned kind to the headers' do
144
+ mock_parcel_factory = double 'parcel_factory'
145
+ mock_parcel_factory.
146
+ should_receive(:create).
147
+ with({
148
+ parent: request_parcel,
149
+ kind: response_kind,
150
+ message: response_message,
151
+ headers: {
152
+ version: versioned_response_kind_version
153
+ }
154
+ }).
155
+ and_return(disconnected_response_parcel)
156
+
157
+ serfer = described_class.new(
158
+ lambda { |obj|
159
+ return versioned_response_kind, response_message
160
+ },
161
+ parcel_factory: mock_parcel_factory)
162
+ parcel = serfer.call request_parcel
163
+
164
+ expect(parcel).to eq(disconnected_response_parcel)
165
+ end
166
+
71
167
  end
72
168
 
73
169
  end
@@ -12,7 +12,12 @@ describe Serf::Util::ErrorHandling do
12
12
  expect(result).to be_nil
13
13
  JsonSchemaTester.new.validate_for!(
14
14
  'serf/events/caught_error',
15
- error)
15
+ Hashie::Mash.new(error))
16
+ expect(error[:error]).to be_kind_of(String)
17
+ expect(error[:message]).to be_kind_of(String)
18
+ expect(error[:process_env]).to be_kind_of(Hash)
19
+ expect(error[:hostname]).to be_kind_of(String)
20
+ expect(error[:backtrace]).to be_kind_of(String)
16
21
  end
17
22
 
18
23
  end
@@ -21,6 +21,26 @@ describe Serf::Util::Uuidable do
21
21
 
22
22
  end
23
23
 
24
+ describe '#coded_uuid_time' do
25
+ let(:coded_uuid) {
26
+ 'RIEHuF5-EeKLPQQMzuOZ7g'
27
+ }
28
+ let(:time_seconds) {
29
+ 1358190718
30
+ }
31
+ let(:time_usec) {
32
+ 273324
33
+ }
34
+
35
+ it 'returns a valid time object' do
36
+ time = subject.coded_uuid_time coded_uuid
37
+ # Check that we have a good timestamp in seconds and nanoseconds
38
+ expect(time.to_i).to eq(time_seconds)
39
+ expect(time.tv_usec).to eq(time_usec)
40
+ end
41
+
42
+ end
43
+
24
44
  describe '#create_uuids' do
25
45
 
26
46
  it 'works with no parent' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-03 00:00:00.000000000 Z
12
+ date: 2013-02-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hashie
@@ -96,6 +96,7 @@ files:
96
96
  - example/serfs/create_widget.serf
97
97
  - lib/serf.rb
98
98
  - lib/serf/builder.rb
99
+ - lib/serf/errors/load_failure.rb
99
100
  - lib/serf/errors/policy_failure.rb
100
101
  - lib/serf/loader.rb
101
102
  - lib/serf/loader/loader.rb
@@ -115,6 +116,8 @@ files:
115
116
  - lib/serf/version.rb
116
117
  - schemas/serf/events/caught_error.json
117
118
  - serf.gemspec
119
+ - spec/data/construction_error.serf
120
+ - spec/data/raises_error.serf
118
121
  - spec/serf/builder_spec.rb
119
122
  - spec/serf/errors/policy_failure_spec.rb
120
123
  - spec/serf/loader/loader_spec.rb
@@ -155,7 +158,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
158
  version: '0'
156
159
  segments:
157
160
  - 0
158
- hash: -3964117889067138578
161
+ hash: 526665702158101187
159
162
  required_rubygems_version: !ruby/object:Gem::Requirement
160
163
  none: false
161
164
  requirements:
@@ -164,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
167
  version: '0'
165
168
  segments:
166
169
  - 0
167
- hash: -3964117889067138578
170
+ hash: 526665702158101187
168
171
  requirements: []
169
172
  rubyforge_project:
170
173
  rubygems_version: 1.8.23
@@ -172,6 +175,8 @@ signing_key:
172
175
  specification_version: 3
173
176
  summary: Interactors with policy protection
174
177
  test_files:
178
+ - spec/data/construction_error.serf
179
+ - spec/data/raises_error.serf
175
180
  - spec/serf/builder_spec.rb
176
181
  - spec/serf/errors/policy_failure_spec.rb
177
182
  - spec/serf/loader/loader_spec.rb