hoodoo 1.11.0 → 1.12.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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