hoodoo 1.11.0 → 1.12.0

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.
@@ -1,6 +1,28 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe Hoodoo::ActiveRecord::Support do
4
+ context '#framework_search_and_filter_data' do
5
+ it 'returns the expected number of keys' do
6
+ hash = described_class.framework_search_and_filter_data()
7
+ expect( hash.keys.count ).to eq( Hoodoo::Services::Middleware::FRAMEWORK_QUERY_DATA.keys.count )
8
+ end
9
+
10
+ it 'complains if there is a mismatch' do
11
+ middleware = Hoodoo::Services::Middleware
12
+ old_value = middleware.const_get( 'FRAMEWORK_QUERY_DATA' )
13
+
14
+ middleware.send( :remove_const, 'FRAMEWORK_QUERY_DATA' )
15
+ middleware.const_set( 'FRAMEWORK_QUERY_DATA', old_value.merge( { Hoodoo::UUID.generate() => 1 } ) )
16
+
17
+ expect {
18
+ described_class.framework_search_and_filter_data()
19
+ }.to raise_error( RuntimeError, 'Hoodoo::ActiveRecord::Support#framework_search_and_filter_data: Mismatch between internal mapping and Hoodoo::Services::Middleware::FRAMEWORK_QUERY_DATA' )
20
+
21
+ middleware.send( :remove_const, 'FRAMEWORK_QUERY_DATA' )
22
+ middleware.const_set( 'FRAMEWORK_QUERY_DATA', old_value )
23
+ end
24
+ end
25
+
4
26
  context '#self.process_to_map' do
5
27
  it 'processes as expected' do
6
28
  proc1 = Proc.new { puts "hello" }
@@ -1,37 +1,34 @@
1
1
  require 'securerandom'
2
2
  require 'spec_helper.rb'
3
3
 
4
- #
5
4
  # These tests define the following Services.
6
5
  #
7
6
  # Clients can call into any of them to invoke the different calling semantics
8
7
  # between them.
9
8
  #
10
- #
11
- # ┌──────────────────────────────────────────────┐ ┌──────────────────────────┐
12
- # │ │ │ │
13
- # │ RSpecNumberService │ │ RSpecRemoteNumberService │
14
- #
15
- # │ │ │ │
16
- # ┌──────────────┐ ┌────────────────┐│ ┌───────────────────┐
17
- # │ │ inter │ ││ │ │
18
- # │ RSpecNumber │◀resource ─│RSpecEvenNumber ││ │ │ RSpecOddNumber │ │
19
- # │ │ local │ ││ │ │
20
- # └──────────────┘ └────────────────┘│ │ └───────────────────┘ │
21
- # ▲ │
22
- # │ inter │ │ │
23
- # │ └───────────────────────────resource ┼─┼────────────┘ │
24
- # │ remote │ │ │
25
- # └──────────────────────────────────────────────┘ └──────────────────────────┘
9
+ # +----------------------------------------------+ +--------------------------+
10
+ # | | | |
11
+ # | RSpecNumberService | | RSpecRemoteNumberService |
12
+ # | | | |
13
+ # | | | |
14
+ # | +--------------+ +----------------+ | | +-------------------+ |
15
+ # | | | inter | | | | | | |
16
+ # | | RSpecNumber |<resource-|RSpecEvenNumber | | | | RSpecOddNumber | |
17
+ # | | | local | | | | | | |
18
+ # | +--------------+ +----------------+ | | +-------------------+ |
19
+ # | ^ | | | |
20
+ # | | inter | | | |
21
+ # | +------------------------ resource --+-+------------+ |
22
+ # | remote | | |
23
+ # +----------------------------------------------+ +--------------------------+
26
24
  #
27
25
  # To start the services in your specs do:
28
26
  #
29
27
  # spec_helper_start_svc_app_in_thread_for( RSpecNumberService )
30
- # spec_helper_start_svc_app_in_thread_for( RSpecRemoteNumberService)
31
- #
28
+ # spec_helper_start_svc_app_in_thread_for( RSpecRemoteNumberService )
29
+
30
+ ###############################################################################
32
31
 
33
- ################################################################################
34
- #
35
32
  # Create a 'RSpecNumber' Resource with the following properties:
36
33
  #
37
34
  # - manages 'Number' resources ie: { 'number': 3 }, for numbers between 0 & 999
@@ -51,11 +48,11 @@ class RSpecNumberImplementation < Hoodoo::Services::Implementation
51
48
  ERROR_RANGE = 500..999
52
49
 
53
50
  def list( context )
54
- request = context.request
55
-
51
+ request = context.request
56
52
  resources = []
57
- implode = false
58
- 0.upto( request.list.limit - 1 ) do |i|
53
+ implode = false
54
+
55
+ 0.upto( request.list.limit - 1 ) do | i |
59
56
  num = request.list.offset + i
60
57
  implode = implode || ERROR_RANGE.include?( num )
61
58
  if NUMBER_RANGE.include?( num )
@@ -66,19 +63,18 @@ class RSpecNumberImplementation < Hoodoo::Services::Implementation
66
63
  end
67
64
 
68
65
  context.response.set_resources( resources, resources.count )
66
+
69
67
  if implode && request.list.filter_data[ 'force_error' ]
70
68
  context.response.add_error( 'platform.malformed' )
71
69
  end
72
70
  end
73
-
74
71
  end
75
72
 
76
- #
77
73
  # Interface for our implementation
78
74
  #
79
75
  class RSpecNumberInterface < Hoodoo::Services::Interface
80
76
  interface :RSpecNumber do
81
- endpoint :numbers, RSpecNumberImplementation
77
+ endpoint :numbers, RSpecNumberImplementation
82
78
  to_list do
83
79
  filter :force_error
84
80
  end
@@ -86,9 +82,8 @@ class RSpecNumberInterface < Hoodoo::Services::Interface
86
82
  end
87
83
  end
88
84
 
85
+ ###############################################################################
89
86
 
90
- ################################################################################
91
- #
92
87
  # Create a 'RSpecEvenNumber' Resource with the following properties:
93
88
  #
94
89
  # - Calls RSpecNumber via the 'inter_resource_local' calling mechanism
@@ -129,7 +124,6 @@ class RSpecEvenNumberImplementation < Hoodoo::Services::Implementation
129
124
 
130
125
  end
131
126
 
132
- #
133
127
  # Interface for our implementation
134
128
  #
135
129
  class RSpecEvenNumberInterface < Hoodoo::Services::Interface
@@ -142,8 +136,8 @@ class RSpecEvenNumberInterface < Hoodoo::Services::Interface
142
136
  end
143
137
  end
144
138
 
145
- ################################################################################
146
- #
139
+ ###############################################################################
140
+
147
141
  # Define our service, that implements both resources
148
142
  #
149
143
  class RSpecNumberService < Hoodoo::Services::Service
@@ -151,9 +145,8 @@ class RSpecNumberService < Hoodoo::Services::Service
151
145
  RSpecEvenNumberInterface
152
146
  end
153
147
 
148
+ ###############################################################################
154
149
 
155
- ################################################################################
156
- #
157
150
  # Create a 'RSpecOddNumber' Resource with the following properties:
158
151
  #
159
152
  # - Calls RSpecNumber via the 'inter_resource_remote' calling mechanism
@@ -194,7 +187,6 @@ class RSpecOddNumberImplementation < Hoodoo::Services::Implementation
194
187
 
195
188
  end
196
189
 
197
- #
198
190
  # Interface for our implementation
199
191
  #
200
192
  class RSpecOddNumberInterface < Hoodoo::Services::Interface
@@ -207,19 +199,17 @@ class RSpecOddNumberInterface < Hoodoo::Services::Interface
207
199
  end
208
200
  end
209
201
 
210
- ################################################################################
211
- #
202
+ ###############################################################################
203
+
212
204
  # Define our service, that implements both resources
213
205
  #
214
206
  class RSpecRemoteNumberService < Hoodoo::Services::Service
215
207
  comprised_of RSpecOddNumberInterface
216
208
  end
217
209
 
218
-
219
-
220
- ##############################################################################
210
+ ###############################################################################
221
211
  # Tests
222
- ##############################################################################
212
+ ###############################################################################
223
213
 
224
214
  describe Hoodoo::Client do
225
215
 
@@ -273,6 +263,15 @@ describe Hoodoo::Client do
273
263
 
274
264
  end
275
265
 
266
+ it 'detects internal inconsistencies' do
267
+ items = resources.first[ :endpoint ].list()
268
+ items.platform_errors.add_error( 'platform.timeout' )
269
+
270
+ expect {
271
+ items.enumerate_all { | item | }
272
+ }.to raise_error( RuntimeError, 'Hoodoo::Client::PaginatedEnumeration#enumerate_all: Unexpected internal state combination of results set and results error indication' )
273
+ end
274
+
276
275
  context 'different "limit" sizes' do
277
276
 
278
277
  let(:limits) {
@@ -0,0 +1,60 @@
1
+ require 'spec_helper.rb'
2
+
3
+ # This is little more than a coverage exercise.
4
+
5
+ describe Hoodoo::Monkey::Patch::NewRelicMiddlewareAnalytics do
6
+
7
+ class RSpecTestNRMAImplementation < Hoodoo::Services::Implementation
8
+ def list( context ); end
9
+ end
10
+
11
+ class RSpecTestNRMAInterface < Hoodoo::Services::Interface
12
+ interface :RSpecTestNRMA do
13
+ endpoint :rspec_test_nrma, RSpecTestNRMAImplementation
14
+ end
15
+ end
16
+
17
+ class RSpecTestNRMAService < Hoodoo::Services::Service
18
+ comprised_of RSpecTestNRMAInterface
19
+ end
20
+
21
+ def app
22
+ Rack::Builder.new do
23
+ use Hoodoo::Services::Middleware
24
+ run RSpecTestNRMAService.new
25
+ end
26
+ end
27
+
28
+ before :all do
29
+ $endpoint_monkey_log_inbound_request_count = 0
30
+
31
+ module NewRelic
32
+ module Agent
33
+ extend self
34
+ def add_custom_attributes( params )
35
+ $endpoint_monkey_log_inbound_request_count += 1
36
+ end
37
+ end
38
+ end
39
+
40
+ Hoodoo::Monkey.enable( extension_module: Hoodoo::Monkey::Patch::NewRelicMiddlewareAnalytics )
41
+ end
42
+
43
+ after :all do
44
+ Hoodoo::Monkey.disable( extension_module: Hoodoo::Monkey::Patch::NewRelicMiddlewareAnalytics )
45
+ Object.send( :remove_const, :NewRelic )
46
+ end
47
+
48
+ before :each do
49
+ expect( Hoodoo::Services::Middleware.ancestors ).to include( Hoodoo::Monkey::Patch::NewRelicMiddlewareAnalytics::InstanceExtensions )
50
+ end
51
+
52
+ it 'calls the NewRelic patch' do
53
+ get '/v1/rspec_test_nrma', nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
54
+ expect( last_response.status ).to eq( 200 )
55
+
56
+ # We expect two log calls; secure inbound and normal inbound.
57
+ #
58
+ expect( $endpoint_monkey_log_inbound_request_count ).to eq( 2 )
59
+ end
60
+ end
@@ -19,7 +19,7 @@ describe Hoodoo::Monkey::Patch::NewRelicTracedAMQP, :order => :defined do
19
19
  @@newrelic_agent_disable_count = 0
20
20
 
21
21
  module NewRelic
22
- class Agent
22
+ module Agent
23
23
  class CrossAppTracing
24
24
  end
25
25
  end
@@ -127,7 +127,7 @@ describe Hoodoo::Monkey::Patch::NewRelicTracedAMQP::AMQPNewRelicResponseWrapper
127
127
 
128
128
  before :all do
129
129
  module NewRelic
130
- class Agent
130
+ module Agent
131
131
  class CrossAppTracing
132
132
  NR_APPDATA_HEADER = 'X_Foo_AppData'
133
133
  end
@@ -0,0 +1,35 @@
1
+ ########################################################################
2
+ # File:: method_tracer.rb
3
+ # (C):: Loyalty New Zealand 2016
4
+ #
5
+ # Purpose:: Override NewRelic 'new_relic/agent/method_tracer'. See the
6
+ # top level 'spec/newrelic_rpm.rb' file for details.
7
+ # ----------------------------------------------------------------------
8
+ # 02-Dec-2016 (ADH): Created.
9
+ ########################################################################
10
+
11
+ # Note that all of this will be defined when the test suite is starting up, but
12
+ # during test runs, local redefinitions of NewRelic and *undefinitions* of that
13
+ # constant will occur. The code only exists so that other "require"s will work
14
+ # and thus provide coverage, mainly inside "newrelic_middleware_analytics.rb".
15
+ #
16
+ module NewRelic
17
+ module Agent
18
+ module MethodTracer
19
+
20
+ def self.included( klass )
21
+ klass.extend( ClassMethods )
22
+ end
23
+
24
+ module ClassMethods
25
+ module AddMethodTracer
26
+ def add_method_tracer( method_name, metric_name_code = nil, options = {} )
27
+ end
28
+ end
29
+
30
+ include AddMethodTracer
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -33,6 +33,8 @@ class RSpecTestServiceStubInterface < Hoodoo::Services::Interface
33
33
  sort :conventional => [:asc, :desc]
34
34
  search :foo, :bar
35
35
  filter :baz, :boo
36
+ do_not_search :created_before
37
+ do_not_filter :created_after
36
38
  end
37
39
  to_create do
38
40
  text :foo, :required => true
@@ -851,6 +853,42 @@ describe Hoodoo::Services::Middleware do
851
853
  expect(result['errors'][0]['reference']).to eq('search: thing\\, thang')
852
854
  end
853
855
 
856
+ it 'should respond to permitted framework search query parameter' do
857
+ dt = DateTime.parse( Time.now.round.iso8601 )
858
+ str = dt.iso8601
859
+ encstr = CGI.escape( CGI.escape( str ) ) # Remember, search values within the subquery string must be double escaped
860
+
861
+ expect_any_instance_of(RSpecTestServiceStubImplementation).to receive(:list).once do | ignored_rspec_mock_instance, context |
862
+ expect(context.request.list.search_data).to eq({'created_after' => dt})
863
+ end
864
+
865
+ get "/v2/rspec_test_service_stub?search=created_after%3D#{ encstr }", nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
866
+ expect(last_response.status).to eq(200)
867
+ end
868
+
869
+ it 'should reject malformed value in permitted framework search query parameter' do
870
+ expect_any_instance_of(RSpecTestServiceStubImplementation).to_not receive(:list)
871
+ get "/v2/rspec_test_service_stub?search=created_after%3Dthing", nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
872
+ expect(last_response.status).to eq(422)
873
+ result = JSON.parse(last_response.body)
874
+ expect(result['errors'][0]['code']).to eq('platform.malformed')
875
+ expect(result['errors'][0]['message']).to eq('One or more malformed or invalid query string parameters')
876
+ expect(result['errors'][0]['reference']).to eq('search: created_after')
877
+ end
878
+
879
+ it 'should reject prohibited framework search query parameter' do
880
+ str = Time.now.iso8601
881
+ encstr = CGI.escape( CGI.escape( str ) ) # Remember, search values within the subquery string must be double escaped
882
+
883
+ expect_any_instance_of(RSpecTestServiceStubImplementation).to_not receive(:list)
884
+ get "/v2/rspec_test_service_stub?search=created_before%3D#{ encstr }", nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
885
+ expect(last_response.status).to eq(422)
886
+ result = JSON.parse(last_response.body)
887
+ expect(result['errors'][0]['code']).to eq('platform.malformed')
888
+ expect(result['errors'][0]['message']).to eq('One or more malformed or invalid query string parameters')
889
+ expect(result['errors'][0]['reference']).to eq('search: created_before')
890
+ end
891
+
854
892
  it 'should respond to filter query parameter (form 1)' do
855
893
  expect_any_instance_of(RSpecTestServiceStubImplementation).to receive(:list).once do | ignored_rspec_mock_instance, context |
856
894
  expect(context.request.list.filter_data).to eq({'baz' => 'more', 'boo' => 'val'})
@@ -908,6 +946,42 @@ describe Hoodoo::Services::Middleware do
908
946
  expect(result['errors'][0]['reference']).to eq('filter: thung\\, theng')
909
947
  end
910
948
 
949
+ it 'should respond to permitted framework filter query parameter' do
950
+ dt = DateTime.parse( Time.now.round.iso8601 )
951
+ str = dt.iso8601
952
+ encstr = CGI.escape( CGI.escape( str ) ) # Remember, search values within the subquery string must be double escaped
953
+
954
+ expect_any_instance_of(RSpecTestServiceStubImplementation).to receive(:list).once do | ignored_rspec_mock_instance, context |
955
+ expect(context.request.list.filter_data).to eq({'created_before' => dt})
956
+ end
957
+
958
+ get "/v2/rspec_test_service_stub?filter=created_before%3D#{ encstr }", nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
959
+ expect(last_response.status).to eq(200)
960
+ end
961
+
962
+ it 'should reject malformed value in permitted framework filter query parameter' do
963
+ expect_any_instance_of(RSpecTestServiceStubImplementation).to_not receive(:list)
964
+ get "/v2/rspec_test_service_stub?filter=created_before%3Dthing", nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
965
+ expect(last_response.status).to eq(422)
966
+ result = JSON.parse(last_response.body)
967
+ expect(result['errors'][0]['code']).to eq('platform.malformed')
968
+ expect(result['errors'][0]['message']).to eq('One or more malformed or invalid query string parameters')
969
+ expect(result['errors'][0]['reference']).to eq('filter: created_before')
970
+ end
971
+
972
+ it 'should reject prohibited framework filter query parameter' do
973
+ str = Time.now.iso8601
974
+ encstr = CGI.escape( CGI.escape( str ) ) # Remember, search values within the subquery string must be double escaped
975
+
976
+ expect_any_instance_of(RSpecTestServiceStubImplementation).to_not receive(:list)
977
+ get "/v2/rspec_test_service_stub?filter=created_after%3D#{ encstr }", nil, { 'CONTENT_TYPE' => 'application/json; charset=utf-8' }
978
+ expect(last_response.status).to eq(422)
979
+ result = JSON.parse(last_response.body)
980
+ expect(result['errors'][0]['code']).to eq('platform.malformed')
981
+ expect(result['errors'][0]['message']).to eq('One or more malformed or invalid query string parameters')
982
+ expect(result['errors'][0]['reference']).to eq('filter: created_after')
983
+ end
984
+
911
985
  it 'should respond to embed query parameter' do
912
986
  expect_any_instance_of(RSpecTestServiceStubImplementation).to receive(:list).once do | ignored_rspec_mock_instance, context |
913
987
  expect(context.request.embeds).to eq(['embs', 'emb'])
@@ -18,6 +18,8 @@ class RSpecTestInterfaceInterfaceA < Hoodoo::Services::Interface
18
18
  sort :sort_one => [ :left, :right ], default( :sort_two ) => [ :up, :down ]
19
19
  search :search_one, :search_two, :search_three
20
20
  filter :filter_one, :filter_two, :filter_three
21
+ do_not_search :created_after, :created_before
22
+ do_not_filter :created_after
21
23
  end
22
24
 
23
25
  to_create do
@@ -74,6 +76,8 @@ describe Hoodoo::Services::Interface do
74
76
  expect(RSpecTestInterfaceInterfaceDefault.to_list.default_sort_direction).to eq('desc')
75
77
  expect(RSpecTestInterfaceInterfaceDefault.to_list.search).to be_empty
76
78
  expect(RSpecTestInterfaceInterfaceDefault.to_list.filter).to be_empty
79
+ expect(RSpecTestInterfaceInterfaceDefault.to_list.do_not_search).to be_empty
80
+ expect(RSpecTestInterfaceInterfaceDefault.to_list.do_not_filter).to be_empty
77
81
  expect(RSpecTestInterfaceInterfaceDefault.to_create).to be_nil
78
82
  expect(RSpecTestInterfaceInterfaceDefault.to_update).to be_nil
79
83
  end
@@ -94,6 +98,8 @@ describe Hoodoo::Services::Interface do
94
98
  expect(RSpecTestInterfaceInterfaceA.to_list.default_sort_direction).to eq('up')
95
99
  expect(RSpecTestInterfaceInterfaceA.to_list.search).to eq(['search_one', 'search_two', 'search_three'])
96
100
  expect(RSpecTestInterfaceInterfaceA.to_list.filter).to eq(['filter_one', 'filter_two', 'filter_three'])
101
+ expect(RSpecTestInterfaceInterfaceA.to_list.do_not_search).to eq(['created_after', 'created_before'])
102
+ expect(RSpecTestInterfaceInterfaceA.to_list.do_not_filter).to eq(['created_after'])
97
103
  expect(RSpecTestInterfaceInterfaceA.to_create).to_not be_nil
98
104
  expect(RSpecTestInterfaceInterfaceA.to_create.get_schema().properties['foo']).to be_a(Hoodoo::Presenters::Text)
99
105
  expect(RSpecTestInterfaceInterfaceA.to_create.get_schema().properties['bar']).to be_a(Hoodoo::Presenters::Enum)
@@ -258,5 +264,25 @@ describe Hoodoo::Services::Interface do
258
264
  }.to raise_error(RuntimeError, "Hoodoo::Services::Interface::ToListDSL\#default requires a String or Symbol - got 'Fixnum'")
259
265
  end
260
266
  end
267
+
268
+ context 'in #do_not_search' do
269
+ it 'should complain about unknown keys' do
270
+ expect {
271
+ Hoodoo::Services::Interface::ToListDSL.new( Hoodoo::Services::Interface::ToList.new ) do
272
+ do_not_search 'foo', 'bar'
273
+ end
274
+ }.to raise_error(RuntimeError, "Hoodoo::Services::Interface::ToListDSL\#do_not_search was given one or more unknown keys: foo, bar")
275
+ end
276
+ end
277
+
278
+ context 'in #do_not_filter' do
279
+ it 'should complain about unknown keys' do
280
+ expect {
281
+ Hoodoo::Services::Interface::ToListDSL.new( Hoodoo::Services::Interface::ToList.new ) do
282
+ do_not_filter 'baz', 'boo'
283
+ end
284
+ }.to raise_error(RuntimeError, "Hoodoo::Services::Interface::ToListDSL\#do_not_filter was given one or more unknown keys: baz, boo")
285
+ end
286
+ end
261
287
  end
262
288
  end