hoodoo 1.0.2
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.
- checksums.yaml +7 -0
- data/bin/hoodoo +5 -0
- data/lib/hoodoo.rb +27 -0
- data/lib/hoodoo/active.rb +32 -0
- data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
- data/lib/hoodoo/active/active_record/base.rb +81 -0
- data/lib/hoodoo/active/active_record/creator.rb +134 -0
- data/lib/hoodoo/active/active_record/dated.rb +343 -0
- data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
- data/lib/hoodoo/active/active_record/finder.rb +606 -0
- data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
- data/lib/hoodoo/active/active_record/secure.rb +431 -0
- data/lib/hoodoo/active/active_record/support.rb +106 -0
- data/lib/hoodoo/active/active_record/translated.rb +87 -0
- data/lib/hoodoo/active/active_record/uuid.rb +80 -0
- data/lib/hoodoo/active/active_record/writer.rb +321 -0
- data/lib/hoodoo/client.rb +23 -0
- data/lib/hoodoo/client/augmented_array.rb +29 -0
- data/lib/hoodoo/client/augmented_base.rb +168 -0
- data/lib/hoodoo/client/augmented_hash.rb +23 -0
- data/lib/hoodoo/client/client.rb +354 -0
- data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
- data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
- data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
- data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
- data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
- data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
- data/lib/hoodoo/client/headers.rb +269 -0
- data/lib/hoodoo/communicators.rb +23 -0
- data/lib/hoodoo/communicators/fast.rb +44 -0
- data/lib/hoodoo/communicators/pool.rb +601 -0
- data/lib/hoodoo/communicators/slow.rb +84 -0
- data/lib/hoodoo/data.rb +51 -0
- data/lib/hoodoo/data/resources/caller.rb +39 -0
- data/lib/hoodoo/data/resources/errors.rb +28 -0
- data/lib/hoodoo/data/resources/log.rb +31 -0
- data/lib/hoodoo/data/resources/session.rb +26 -0
- data/lib/hoodoo/data/types/error_primitive.rb +27 -0
- data/lib/hoodoo/data/types/permissions.rb +40 -0
- data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
- data/lib/hoodoo/data/types/permissions_full.rb +28 -0
- data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
- data/lib/hoodoo/discovery.rb +20 -0
- data/lib/hoodoo/errors.rb +19 -0
- data/lib/hoodoo/errors/error_descriptions.rb +229 -0
- data/lib/hoodoo/errors/errors.rb +322 -0
- data/lib/hoodoo/generator.rb +139 -0
- data/lib/hoodoo/logger.rb +23 -0
- data/lib/hoodoo/logger/fast_writer.rb +27 -0
- data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
- data/lib/hoodoo/logger/logger.rb +387 -0
- data/lib/hoodoo/logger/slow_writer.rb +49 -0
- data/lib/hoodoo/logger/writer_mixin.rb +52 -0
- data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
- data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
- data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
- data/lib/hoodoo/middleware.rb +33 -0
- data/lib/hoodoo/presenters.rb +45 -0
- data/lib/hoodoo/presenters/base.rb +281 -0
- data/lib/hoodoo/presenters/base_dsl.rb +519 -0
- data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
- data/lib/hoodoo/presenters/embedding.rb +232 -0
- data/lib/hoodoo/presenters/types/array.rb +118 -0
- data/lib/hoodoo/presenters/types/boolean.rb +26 -0
- data/lib/hoodoo/presenters/types/date.rb +26 -0
- data/lib/hoodoo/presenters/types/date_time.rb +26 -0
- data/lib/hoodoo/presenters/types/decimal.rb +47 -0
- data/lib/hoodoo/presenters/types/enum.rb +55 -0
- data/lib/hoodoo/presenters/types/field.rb +158 -0
- data/lib/hoodoo/presenters/types/float.rb +26 -0
- data/lib/hoodoo/presenters/types/hash.rb +361 -0
- data/lib/hoodoo/presenters/types/integer.rb +26 -0
- data/lib/hoodoo/presenters/types/object.rb +117 -0
- data/lib/hoodoo/presenters/types/string.rb +53 -0
- data/lib/hoodoo/presenters/types/tags.rb +24 -0
- data/lib/hoodoo/presenters/types/text.rb +26 -0
- data/lib/hoodoo/presenters/types/uuid.rb +54 -0
- data/lib/hoodoo/services.rb +34 -0
- data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
- data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
- data/lib/hoodoo/services/discovery/discovery.rb +186 -0
- data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
- data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
- data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
- data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
- data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
- data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
- data/lib/hoodoo/services/middleware/interaction.rb +127 -0
- data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
- data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
- data/lib/hoodoo/services/services/context.rb +153 -0
- data/lib/hoodoo/services/services/implementation.rb +132 -0
- data/lib/hoodoo/services/services/interface.rb +934 -0
- data/lib/hoodoo/services/services/permissions.rb +250 -0
- data/lib/hoodoo/services/services/request.rb +189 -0
- data/lib/hoodoo/services/services/response.rb +316 -0
- data/lib/hoodoo/services/services/service.rb +141 -0
- data/lib/hoodoo/services/services/session.rb +729 -0
- data/lib/hoodoo/utilities.rb +12 -0
- data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
- data/lib/hoodoo/utilities/utilities.rb +380 -0
- data/lib/hoodoo/utilities/uuid.rb +44 -0
- data/lib/hoodoo/version.rb +17 -0
- data/spec/active/active_record/base_spec.rb +57 -0
- data/spec/active/active_record/creator_spec.rb +88 -0
- data/spec/active/active_record/dated_spec.rb +248 -0
- data/spec/active/active_record/error_mapping_spec.rb +360 -0
- data/spec/active/active_record/finder_spec.rb +744 -0
- data/spec/active/active_record/search_helper_spec.rb +384 -0
- data/spec/active/active_record/secure_spec.rb +435 -0
- data/spec/active/active_record/support_spec.rb +225 -0
- data/spec/active/active_record/translated_spec.rb +19 -0
- data/spec/active/active_record/uuid_spec.rb +72 -0
- data/spec/active/active_record/writer_spec.rb +272 -0
- data/spec/alchemy/alchemy-amq.rb +33 -0
- data/spec/client/augmented_array_spec.rb +15 -0
- data/spec/client/augmented_base_spec.rb +50 -0
- data/spec/client/augmented_hash_spec.rb +15 -0
- data/spec/client/client_spec.rb +955 -0
- data/spec/client/endpoint/endpoint_spec.rb +70 -0
- data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
- data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
- data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
- data/spec/client/headers_spec.rb +172 -0
- data/spec/communicators/fast_spec.rb +9 -0
- data/spec/communicators/pool_spec.rb +339 -0
- data/spec/communicators/slow_spec.rb +15 -0
- data/spec/data/resources/caller_spec.rb +156 -0
- data/spec/data/resources/errors_spec.rb +22 -0
- data/spec/data/resources/log_spec.rb +20 -0
- data/spec/data/resources/session_spec.rb +15 -0
- data/spec/data/types/error_primitive_spec.rb +15 -0
- data/spec/data/types/permissions_defaults_spec.rb +25 -0
- data/spec/data/types/permissions_full_spec.rb +44 -0
- data/spec/data/types/permissions_resources_spec.rb +34 -0
- data/spec/data/types/permissions_spec.rb +37 -0
- data/spec/errors/error_descriptions_spec.rb +98 -0
- data/spec/errors/errors_spec.rb +346 -0
- data/spec/integration/service_actions_spec.rb +112 -0
- data/spec/logger/fast_writer_spec.rb +18 -0
- data/spec/logger/logger_spec.rb +259 -0
- data/spec/logger/slow_writer_spec.rb +144 -0
- data/spec/logger/writers/file_writer_spec.rb +37 -0
- data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
- data/spec/logger/writers/stream_writer_spec.rb +38 -0
- data/spec/presenters/base_dsl_spec.rb +111 -0
- data/spec/presenters/base_spec.rb +871 -0
- data/spec/presenters/common_resource_fields_spec.rb +30 -0
- data/spec/presenters/embedding_spec.rb +87 -0
- data/spec/presenters/types/array_spec.rb +249 -0
- data/spec/presenters/types/boolean_spec.rb +51 -0
- data/spec/presenters/types/date_spec.rb +57 -0
- data/spec/presenters/types/date_time_spec.rb +59 -0
- data/spec/presenters/types/decimal_spec.rb +58 -0
- data/spec/presenters/types/enum_spec.rb +71 -0
- data/spec/presenters/types/field_spec.rb +77 -0
- data/spec/presenters/types/float_spec.rb +50 -0
- data/spec/presenters/types/hash_spec.rb +1069 -0
- data/spec/presenters/types/integer_spec.rb +50 -0
- data/spec/presenters/types/object_spec.rb +177 -0
- data/spec/presenters/types/string_spec.rb +65 -0
- data/spec/presenters/types/tags_spec.rb +56 -0
- data/spec/presenters/types/text_spec.rb +50 -0
- data/spec/presenters/types/uuid_spec.rb +46 -0
- data/spec/presenters/walk_spec.rb +198 -0
- data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
- data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
- data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
- data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
- data/spec/services/discovery/discovery_spec.rb +73 -0
- data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
- data/spec/services/discovery/results/for_http_spec.rb +37 -0
- data/spec/services/discovery/results/for_local_spec.rb +21 -0
- data/spec/services/discovery/results/for_remote_spec.rb +15 -0
- data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
- data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
- data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
- data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
- data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
- data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
- data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
- data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
- data/spec/services/middleware/middleware_cors_spec.rb +93 -0
- data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
- data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
- data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
- data/spec/services/middleware/middleware_logging_spec.rb +356 -0
- data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
- data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
- data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
- data/spec/services/middleware/middleware_public_spec.rb +238 -0
- data/spec/services/middleware/middleware_spec.rb +1569 -0
- data/spec/services/middleware/string_inquirer_spec.rb +30 -0
- data/spec/services/services/application_spec.rb +74 -0
- data/spec/services/services/context_spec.rb +48 -0
- data/spec/services/services/implementation_spec.rb +45 -0
- data/spec/services/services/interface_spec.rb +262 -0
- data/spec/services/services/permissions_spec.rb +249 -0
- data/spec/services/services/request_spec.rb +95 -0
- data/spec/services/services/response_spec.rb +250 -0
- data/spec/services/services/session_spec.rb +432 -0
- data/spec/spec_helper.rb +298 -0
- data/spec/utilities/utilities_spec.rb +537 -0
- data/spec/utilities/uuid_spec.rb +20 -0
- metadata +615 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# Hoodoo is going open source before AlchemyAMQ, but the test suite has
|
2
|
+
# Alchemy dependencies. The Gemfile even used to require Alchemy in test
|
3
|
+
# mode directly from the private GitHub repository.
|
4
|
+
#
|
5
|
+
# That doesn't work for a public gem, so this file is a temporary mock
|
6
|
+
# of relevant Alchemy namespaces to get tests to pass until Alchemy AMQ
|
7
|
+
# is released.
|
8
|
+
#
|
9
|
+
# Without being able to see bits of Alchemy code that this minimally
|
10
|
+
# mocks, neither this file nor the tests that run through it will make
|
11
|
+
# much sense unfortunately.
|
12
|
+
|
13
|
+
require 'ostruct'
|
14
|
+
require 'msgpack'
|
15
|
+
|
16
|
+
module AlchemyAMQ
|
17
|
+
class HTTPResponse < OpenStruct
|
18
|
+
end
|
19
|
+
|
20
|
+
class Message < OpenStruct
|
21
|
+
def serialize
|
22
|
+
self.payload = MessagePack.pack(@content)
|
23
|
+
end
|
24
|
+
|
25
|
+
def deserialize
|
26
|
+
@content = MessagePack.unpack(self.payload, :symbolize_keys => true)
|
27
|
+
end
|
28
|
+
|
29
|
+
def send_message; end
|
30
|
+
|
31
|
+
def self.register_type( *args ); end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hoodoo::Client::AugmentedArray do
|
4
|
+
|
5
|
+
# However much the class arrangement might change in future, ultimately the
|
6
|
+
# class must inherit from Array and support a basic interface expected by
|
7
|
+
# any AugmentedBase "client".
|
8
|
+
#
|
9
|
+
it 'instantiates correctly' do
|
10
|
+
expect( described_class.new ).to be_a( Array )
|
11
|
+
expect( described_class.new.respond_to?( :adds_errors_to? ) ).to eq( true )
|
12
|
+
expect( described_class.new.respond_to?( :set_platform_errors ) ).to eq( true )
|
13
|
+
expect( described_class.new.respond_to?( :platform_errors ) ).to eq( true )
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hoodoo::Client::AugmentedBase do
|
4
|
+
|
5
|
+
class AugmentedBaseTest
|
6
|
+
include Hoodoo::Client::AugmentedBase
|
7
|
+
end
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
@abt = AugmentedBaseTest.new
|
11
|
+
@fof = Hoodoo::Errors.new
|
12
|
+
@fof.add_error( 'platform.timeout' )
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'without externally set collection' do
|
16
|
+
it 'generates its own collection' do
|
17
|
+
e = @abt.platform_errors
|
18
|
+
expect( e ).to be_a( Hoodoo::Errors )
|
19
|
+
expect( e.has_errors? ).to eq( false )
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'merges properly' do
|
23
|
+
# There are no errors inside @abt to add to @fof, so should return 'false'
|
24
|
+
expect( @abt.adds_errors_to?( @fof ) ).to eq( false )
|
25
|
+
data = @fof.render( Hoodoo::UUID.generate() )
|
26
|
+
expect( data[ 'errors' ] ).to be_a( Array )
|
27
|
+
expect( data[ 'errors' ].size ).to eq( 1 )
|
28
|
+
expect( data[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.timeout' )
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'with externally set collection' do
|
33
|
+
|
34
|
+
it 'sets and returns errors collections' do
|
35
|
+
@abt.set_platform_errors( @fof )
|
36
|
+
expect( @abt.platform_errors ).to eq( @fof )
|
37
|
+
expect( @abt.platform_errors.has_errors? ).to eq( true )
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'merges properly' do
|
41
|
+
col = Hoodoo::Errors.new
|
42
|
+
@abt.set_platform_errors( @fof )
|
43
|
+
expect( @abt.adds_errors_to?( col ) ).to eq( true )
|
44
|
+
data = col.render( Hoodoo::UUID.generate() )
|
45
|
+
expect( data[ 'errors' ] ).to be_a( Array )
|
46
|
+
expect( data[ 'errors' ].size ).to eq( 1 )
|
47
|
+
expect( data[ 'errors' ][ 0 ][ 'code' ] ).to eq( 'platform.timeout' )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hoodoo::Client::AugmentedHash do
|
4
|
+
|
5
|
+
# However much the class arrangement might change in future, ultimately the
|
6
|
+
# class must inherit from Hash and support a basic interface expected by
|
7
|
+
# any AugmentedBase "client".
|
8
|
+
#
|
9
|
+
it 'instantiates correctly' do
|
10
|
+
expect( described_class.new ).to be_a( Hash )
|
11
|
+
expect( described_class.new.respond_to?( :adds_errors_to? ) ).to eq( true )
|
12
|
+
expect( described_class.new.respond_to?( :set_platform_errors ) ).to eq( true )
|
13
|
+
expect( described_class.new.respond_to?( :platform_errors ) ).to eq( true )
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,955 @@
|
|
1
|
+
# So this is heavy... We need:
|
2
|
+
#
|
3
|
+
# - A real resource endpoint that implements the Session API
|
4
|
+
# - Another endpoint with public actions to test without a session
|
5
|
+
# - Some of that enpoint which requires a session
|
6
|
+
# - The endpoint to be available by convention or DRb
|
7
|
+
#
|
8
|
+
# In passing we necessarily end up with quite a lot of test coverage for
|
9
|
+
# some of the endpoint and discovery code.
|
10
|
+
|
11
|
+
require 'securerandom'
|
12
|
+
require 'spec_helper.rb'
|
13
|
+
|
14
|
+
##############################################################################
|
15
|
+
# Session resource
|
16
|
+
##############################################################################
|
17
|
+
|
18
|
+
class RSpecClientTestSessionImplementation < Hoodoo::Services::Implementation
|
19
|
+
def create( context )
|
20
|
+
|
21
|
+
session_id = Hoodoo::UUID.generate()
|
22
|
+
test_session = Hoodoo::Services::Middleware::DEFAULT_TEST_SESSION.dup
|
23
|
+
test_session.session_id = session_id
|
24
|
+
Hoodoo::Services::Middleware.set_test_session( test_session )
|
25
|
+
|
26
|
+
# All the session reading code really cares about is 'id', but let's
|
27
|
+
# return something that looks very like a documented Session anyway.
|
28
|
+
#
|
29
|
+
context.response.set_resource(
|
30
|
+
'id' => session_id,
|
31
|
+
'created_at' => Time.now.utc.iso8601,
|
32
|
+
'kind' => 'RSpecClientTestSession',
|
33
|
+
'caller_id' => context.request.body[ 'caller_id' ],
|
34
|
+
'expires_at' => ( Time.now.utc + 24*60*60 ).iso8601
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class RSpecClientTestSessionInterface < Hoodoo::Services::Interface
|
40
|
+
interface :RSpecClientTestSession do
|
41
|
+
endpoint :r_spec_client_test_sessions, RSpecClientTestSessionImplementation
|
42
|
+
public_actions :create
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##############################################################################
|
47
|
+
# Target resource
|
48
|
+
##############################################################################
|
49
|
+
|
50
|
+
# This resource 'echoes back' some of the query and body data in its
|
51
|
+
# responses so we can check to see if things seem to be passed through
|
52
|
+
# the layers properly. It's not exhaustive.
|
53
|
+
#
|
54
|
+
class RSpecClientTestTargetImplementation < Hoodoo::Services::Implementation
|
55
|
+
|
56
|
+
public
|
57
|
+
|
58
|
+
# This will be a public action
|
59
|
+
|
60
|
+
def show( context )
|
61
|
+
|
62
|
+
# Deliberate error generation hook.
|
63
|
+
#
|
64
|
+
if context.request.ident == 'return_error'
|
65
|
+
context.response.add_error( 'platform.malformed' )
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
context.response.set_resource( mock( context ) )
|
70
|
+
end
|
71
|
+
|
72
|
+
# The rest will be protected actions
|
73
|
+
|
74
|
+
def list( context )
|
75
|
+
|
76
|
+
# Deliberate error generation hook.
|
77
|
+
#
|
78
|
+
if context.request.list.offset == 42
|
79
|
+
context.response.add_error( 'platform.malformed' )
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
context.response.set_resources(
|
84
|
+
[ mock( context ), mock( context ), mock( context ) ],
|
85
|
+
3
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
def create( context )
|
90
|
+
|
91
|
+
# Deliberate error generation hook.
|
92
|
+
#
|
93
|
+
if context.request.body.has_key?( 'return_error' )
|
94
|
+
context.response.add_error( 'platform.malformed' )
|
95
|
+
return
|
96
|
+
end
|
97
|
+
|
98
|
+
# If expecting deja-vu, cause deja-vu.
|
99
|
+
#
|
100
|
+
if context.request.deja_vu
|
101
|
+
context.response.add_error(
|
102
|
+
'generic.invalid_duplication',
|
103
|
+
:reference => { :field_name => 'hello' }
|
104
|
+
)
|
105
|
+
|
106
|
+
else
|
107
|
+
context.response.set_resource( mock( context ) )
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def update( context )
|
113
|
+
|
114
|
+
# Deliberate error generation hook.
|
115
|
+
#
|
116
|
+
if context.request.ident == 'return_error'
|
117
|
+
context.response.add_error( 'platform.malformed' )
|
118
|
+
return
|
119
|
+
end
|
120
|
+
|
121
|
+
context.response.set_resource( mock( context ) )
|
122
|
+
context.response.add_header( 'X-Example-Header', 'example' )
|
123
|
+
end
|
124
|
+
|
125
|
+
def delete( context )
|
126
|
+
|
127
|
+
# Deliberate error generation hook.
|
128
|
+
#
|
129
|
+
if context.request.ident == 'return_error'
|
130
|
+
context.response.add_error( 'platform.malformed' )
|
131
|
+
return
|
132
|
+
end
|
133
|
+
|
134
|
+
context.response.set_resource( mock( context ) )
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
def mock( context )
|
139
|
+
|
140
|
+
# Part of this could be automatic via HEADER_TO_PROPERTY but then
|
141
|
+
# any errors in that mapping which don't match our requirements in
|
142
|
+
# the test would be hidden, by the test using the same broken map.
|
143
|
+
#
|
144
|
+
# See also "def set_vars_for" and "def option_based_expectations"
|
145
|
+
# below. Be careful to follow the naming convention evident below
|
146
|
+
# if adding things.
|
147
|
+
|
148
|
+
{
|
149
|
+
'id' => context.request.ident ||
|
150
|
+
context.request.body.try( :[], 'id' ) ||
|
151
|
+
Hoodoo::UUID.generate(),
|
152
|
+
|
153
|
+
'created_at' => Time.now.utc.iso8601,
|
154
|
+
'kind' => 'RSpecClientTestTarget',
|
155
|
+
'language' => context.request.locale,
|
156
|
+
|
157
|
+
'embeds' => context.request.embeds,
|
158
|
+
'body_hash' => context.request.body,
|
159
|
+
'dated_at' => context.request.dated_at.nil? ? nil : Hoodoo::Utilities.nanosecond_iso8601( context.request.dated_at ),
|
160
|
+
'dated_from' => context.request.dated_from.nil? ? nil : Hoodoo::Utilities.nanosecond_iso8601( context.request.dated_from ),
|
161
|
+
'resource_uuid' => context.request.resource_uuid,
|
162
|
+
'deja_vu' => context.request.deja_vu,
|
163
|
+
}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class RSpecClientTestTargetInterface < Hoodoo::Services::Interface
|
168
|
+
interface :RSpecClientTestTarget do
|
169
|
+
endpoint :r_spec_client_test_targets, RSpecClientTestTargetImplementation
|
170
|
+
public_actions :show
|
171
|
+
actions :list, :create, :update, :delete
|
172
|
+
embeds :foo, :bar, :baz
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# This resource is just here for the custom routing tests.
|
177
|
+
#
|
178
|
+
class RSpecClientTestTargetCustomRoutingImplementation < Hoodoo::Services::Implementation
|
179
|
+
def show( context )
|
180
|
+
context.response.set_resource( { 'id' => context.request.ident } )
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
class RSpecClientTestTargetCustomRoutingInterface < Hoodoo::Services::Interface
|
185
|
+
interface :RSpecClientTestTargetCustomRouting do
|
186
|
+
endpoint :r_spec_client_test_targets_with_custom_route, RSpecClientTestTargetCustomRoutingImplementation
|
187
|
+
public_actions :show
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
##############################################################################
|
192
|
+
# One endpoint for both resources
|
193
|
+
#
|
194
|
+
# When we use by-convention discovery, a single base host is assumed. If we
|
195
|
+
# were to try and start multiple resource endpoints in their own HTTP threads
|
196
|
+
# on localhost, you'd have different port numbers and thus a different base
|
197
|
+
# URI, which by-convention discovery can't find (even though by-DRb can).
|
198
|
+
##############################################################################
|
199
|
+
|
200
|
+
class RSpecClientTestService < Hoodoo::Services::Service
|
201
|
+
comprised_of RSpecClientTestSessionInterface,
|
202
|
+
RSpecClientTestTargetInterface,
|
203
|
+
RSpecClientTestTargetCustomRoutingInterface
|
204
|
+
end
|
205
|
+
|
206
|
+
##############################################################################
|
207
|
+
# Tests
|
208
|
+
##############################################################################
|
209
|
+
|
210
|
+
describe Hoodoo::Client do
|
211
|
+
|
212
|
+
before :all do
|
213
|
+
@old_test_session = Hoodoo::Services::Middleware.test_session()
|
214
|
+
@port = spec_helper_start_svc_app_in_thread_for( RSpecClientTestService )
|
215
|
+
@https_port = spec_helper_start_svc_app_in_thread_for( RSpecClientTestService, true )
|
216
|
+
end
|
217
|
+
|
218
|
+
after :all do
|
219
|
+
Hoodoo::Services::Middleware.set_test_session( @old_test_session )
|
220
|
+
end
|
221
|
+
|
222
|
+
# Set @locale, @expected_locale (latter for 'to eq(...)' matching),
|
223
|
+
# @dated_at/from, @expected_data_at/from (same deal), @client and callable
|
224
|
+
# @endpoint up, passing the given options to the Hoodoo::Client constructor,
|
225
|
+
# with randomised locale merged in. Conversion to lower case is checked
|
226
|
+
# implicitly, with a mixed case locale generated (potentially) by random
|
227
|
+
# but the 'downcase' version being used for 'expect's.
|
228
|
+
#
|
229
|
+
# Similar instance variables are used for UUID and déjà-vu specifiers. This
|
230
|
+
# method will probably get expanded over time with other properties derived
|
231
|
+
# from Hoodoo::Client::Headers' HEADER_TO_PROPERTY map too.
|
232
|
+
#
|
233
|
+
# Through the use of random switches, we (eventually!) get test coverage
|
234
|
+
# on locale specified (or not) given to the Client, plus override locale
|
235
|
+
# (or not) and a dated-at date/time (or not) given to the Endpoint.
|
236
|
+
#
|
237
|
+
def set_vars_for( opts )
|
238
|
+
@locale = rand( 2 ) == 0 ? nil : SecureRandom.urlsafe_base64(2)
|
239
|
+
@expected_locale = @locale.nil? ? 'en-nz' : @locale.downcase
|
240
|
+
@client = Hoodoo::Client.new( opts.merge( :locale => @locale ) )
|
241
|
+
|
242
|
+
endpoint_opts = {}
|
243
|
+
|
244
|
+
# Part of this could be automatic via HEADER_TO_PROPERTY but then
|
245
|
+
# any errors in that mapping which don't match our requirements in
|
246
|
+
# the test would be hidden, by the test using the same broken map.
|
247
|
+
#
|
248
|
+
# See also "def mock" earlier in this file and
|
249
|
+
# "def option_based_expectations" later in this file. Be careful
|
250
|
+
# to follow the naming convention evident below if adding things.
|
251
|
+
|
252
|
+
@expected_dated_at = @dated_at.nil? ? nil : Hoodoo::Utilities.nanosecond_iso8601( @dated_at )
|
253
|
+
@expected_dated_from = @dated_from.nil? ? nil : Hoodoo::Utilities.nanosecond_iso8601( @dated_from )
|
254
|
+
@expected_resource_uuid = @resource_uuid
|
255
|
+
@expected_deja_vu = @deja_vu != true ? nil : true
|
256
|
+
|
257
|
+
endpoint_opts[ :dated_at ] = @dated_at unless @dated_at.nil?
|
258
|
+
endpoint_opts[ :dated_from ] = @dated_from unless @dated_from.nil?
|
259
|
+
endpoint_opts[ :resource_uuid ] = @resource_uuid unless @resource_uuid.nil?
|
260
|
+
endpoint_opts[ :deja_vu ] = @deja_vu if @deja_vu == true
|
261
|
+
|
262
|
+
if rand( 2 ) == 0
|
263
|
+
override_locale = SecureRandom.urlsafe_base64( 2 )
|
264
|
+
endpoint_opts[ :locale ] = override_locale
|
265
|
+
@expected_locale = override_locale.downcase
|
266
|
+
end
|
267
|
+
|
268
|
+
@endpoint = @client.resource( :RSpecClientTestTarget, 1, endpoint_opts )
|
269
|
+
end
|
270
|
+
|
271
|
+
# Automatic expectations based on HEADER_TO_PROPERTY are fine here as they
|
272
|
+
# are just working off the properties and the associated variable naming
|
273
|
+
# conventions within this test file.
|
274
|
+
#
|
275
|
+
# See also "def mock" and "def set_vars_for" earlier in this file.
|
276
|
+
#
|
277
|
+
def option_based_expectations( result )
|
278
|
+
|
279
|
+
if result.is_a?( Hoodoo::Client::AugmentedArray )
|
280
|
+
resource = result[ 0 ]
|
281
|
+
else
|
282
|
+
resource = result
|
283
|
+
end
|
284
|
+
|
285
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
286
|
+
property = description[ :property ]
|
287
|
+
expect( resource[ property.to_s ] ).to eq( instance_variable_get( "@expected_#{ property }" ) )
|
288
|
+
end
|
289
|
+
|
290
|
+
# We also always expect some standard response headers to have been included
|
291
|
+
# in the result out-of-band options payload.
|
292
|
+
|
293
|
+
expect( result.response_options[ 'interaction_id' ] ).to be_present
|
294
|
+
expect( Hoodoo::UUID.valid?( result.response_options[ 'interaction_id' ] ) ).to eq( true )
|
295
|
+
expect( result.response_options[ 'service_response_time' ] ).to be_present
|
296
|
+
|
297
|
+
end
|
298
|
+
|
299
|
+
##############################################################################
|
300
|
+
# No automatic session acquisition and no session
|
301
|
+
##############################################################################
|
302
|
+
|
303
|
+
context 'without any session' do
|
304
|
+
shared_examples Hoodoo::Client do
|
305
|
+
it '(public actions allowed)' do
|
306
|
+
mock_ident = Hoodoo::UUID.generate()
|
307
|
+
embeds = [ 'foo', 'baz' ]
|
308
|
+
query_hash = { '_embed' => embeds }
|
309
|
+
|
310
|
+
result = @endpoint.show( mock_ident )
|
311
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
312
|
+
|
313
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
314
|
+
expect( result[ 'embeds' ] ).to eq( [] )
|
315
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
316
|
+
|
317
|
+
option_based_expectations( result )
|
318
|
+
|
319
|
+
result = @endpoint.show( mock_ident, query_hash )
|
320
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
321
|
+
|
322
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
323
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
324
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
325
|
+
|
326
|
+
option_based_expectations( result )
|
327
|
+
end
|
328
|
+
|
329
|
+
it '(protected actions prohibited)' do
|
330
|
+
result = @endpoint.list()
|
331
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
332
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.invalid_session' )
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
before :each do
|
337
|
+
Hoodoo::Services::Middleware.set_test_session( nil )
|
338
|
+
end
|
339
|
+
|
340
|
+
context 'and by DRb' do
|
341
|
+
before :each do
|
342
|
+
set_vars_for(
|
343
|
+
drb_port: URI.parse( Hoodoo::Services::Discovery::ByDRb::DRbServer.uri() ).port,
|
344
|
+
auto_session: false
|
345
|
+
)
|
346
|
+
end
|
347
|
+
|
348
|
+
it_behaves_like Hoodoo::Client
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'and by DRb with custom discoverer' do
|
352
|
+
before :each do
|
353
|
+
drb_port = URI.parse( Hoodoo::Services::Discovery::ByDRb::DRbServer.uri() ).port
|
354
|
+
discoverer = Hoodoo::Services::Discovery::ByDRb.new( drb_port: drb_port )
|
355
|
+
|
356
|
+
expect( discoverer ).to receive( :discover ).at_least( :once ).and_call_original
|
357
|
+
|
358
|
+
set_vars_for(
|
359
|
+
auto_session: false,
|
360
|
+
discoverer: discoverer
|
361
|
+
)
|
362
|
+
end
|
363
|
+
|
364
|
+
it_behaves_like Hoodoo::Client
|
365
|
+
end
|
366
|
+
|
367
|
+
context 'and by convention' do
|
368
|
+
before :each do
|
369
|
+
set_vars_for(
|
370
|
+
base_uri: "http://localhost:#{ @port }",
|
371
|
+
auto_session: false
|
372
|
+
)
|
373
|
+
end
|
374
|
+
|
375
|
+
it_behaves_like Hoodoo::Client
|
376
|
+
end
|
377
|
+
|
378
|
+
context 'and by convention with custom discoverer' do
|
379
|
+
before :each do
|
380
|
+
base_uri = "http://localhost:#{ @port }"
|
381
|
+
discoverer = Hoodoo::Services::Discovery::ByConvention.new( base_uri: base_uri )
|
382
|
+
|
383
|
+
expect( discoverer ).to receive( :discover ).at_least( :once ).and_call_original
|
384
|
+
|
385
|
+
set_vars_for(
|
386
|
+
base_uri: base_uri,
|
387
|
+
auto_session: false,
|
388
|
+
session_id: @old_test_session.session_id,
|
389
|
+
discoverer: discoverer
|
390
|
+
)
|
391
|
+
end
|
392
|
+
|
393
|
+
it_behaves_like Hoodoo::Client
|
394
|
+
end
|
395
|
+
|
396
|
+
context 'and with an HTTP proxy via custom discoverer' do
|
397
|
+
before :each do
|
398
|
+
base_uri = "http://localhost:#{ @port }"
|
399
|
+
proxy_uri = 'http://foo:bar@proxyhost:1234'
|
400
|
+
discoverer = Hoodoo::Services::Discovery::ByConvention.new(
|
401
|
+
base_uri: base_uri,
|
402
|
+
proxy_uri: proxy_uri
|
403
|
+
)
|
404
|
+
|
405
|
+
original_new = Net::HTTP.method( :new )
|
406
|
+
|
407
|
+
expect( Net::HTTP ).to receive( :new ).at_least( :once ) do | host, port, proxy_host, proxy_port, proxy_user, proxy_pass |
|
408
|
+
expect( host ).to eq( 'localhost' )
|
409
|
+
expect( port ).to eq( @port )
|
410
|
+
expect( proxy_host ).to eq( 'proxyhost' )
|
411
|
+
expect( proxy_port ).to eq( 1234 )
|
412
|
+
expect( proxy_user ).to eq( 'foo' )
|
413
|
+
expect( proxy_pass ).to eq( 'bar' )
|
414
|
+
|
415
|
+
original_new.call( host, port )
|
416
|
+
end
|
417
|
+
|
418
|
+
set_vars_for(
|
419
|
+
auto_session: false,
|
420
|
+
session_id: @old_test_session.session_id,
|
421
|
+
discoverer: discoverer
|
422
|
+
)
|
423
|
+
end
|
424
|
+
|
425
|
+
it_behaves_like Hoodoo::Client
|
426
|
+
end
|
427
|
+
|
428
|
+
context 'and with a custom ca_file' do
|
429
|
+
before :each do
|
430
|
+
# Note: the ssl-cert is for 127.0.0.1, localhost doesn't match it
|
431
|
+
base_uri = "https://127.0.0.1:#{ @https_port }"
|
432
|
+
ca_file = 'spec/files/ca/ca-cert.pem'
|
433
|
+
discoverer = Hoodoo::Services::Discovery::ByConvention.new(
|
434
|
+
base_uri: base_uri,
|
435
|
+
ca_file: ca_file
|
436
|
+
)
|
437
|
+
|
438
|
+
set_vars_for(
|
439
|
+
base_uri: base_uri,
|
440
|
+
auto_session: false,
|
441
|
+
session_id: @old_test_session.session_id,
|
442
|
+
discoverer: discoverer
|
443
|
+
)
|
444
|
+
end
|
445
|
+
|
446
|
+
it_behaves_like Hoodoo::Client
|
447
|
+
end
|
448
|
+
|
449
|
+
context 'and with a custom HTTP read timeout' do
|
450
|
+
before :each do
|
451
|
+
base_uri = "http://localhost:#{ @port }"
|
452
|
+
discoverer = Hoodoo::Services::Discovery::ByConvention.new(
|
453
|
+
base_uri: base_uri,
|
454
|
+
http_timeout: 0.0000001
|
455
|
+
)
|
456
|
+
|
457
|
+
set_vars_for(
|
458
|
+
base_uri: base_uri,
|
459
|
+
auto_session: false,
|
460
|
+
session_id: @old_test_session.session_id,
|
461
|
+
discoverer: discoverer
|
462
|
+
)
|
463
|
+
end
|
464
|
+
|
465
|
+
it 'times out elegantly' do
|
466
|
+
mock_ident = Hoodoo::UUID.generate()
|
467
|
+
result = @endpoint.show( mock_ident )
|
468
|
+
|
469
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
470
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.timeout' )
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
context 'and with custom routing' do
|
475
|
+
it 'obeys the routes' do
|
476
|
+
base_uri = "http://localhost:#{ @port }"
|
477
|
+
discoverer = Hoodoo::Services::Discovery::ByConvention.new(
|
478
|
+
:base_uri => base_uri,
|
479
|
+
:routing => {
|
480
|
+
:RSpecClientTestTargetCustomRouting => {
|
481
|
+
1 => '/v1/r_spec_client_test_targets_with_custom_route'
|
482
|
+
}
|
483
|
+
}
|
484
|
+
)
|
485
|
+
|
486
|
+
set_vars_for(
|
487
|
+
base_uri: base_uri,
|
488
|
+
auto_session: false,
|
489
|
+
session_id: @old_test_session.session_id,
|
490
|
+
discoverer: discoverer
|
491
|
+
)
|
492
|
+
|
493
|
+
mock_ident = Hoodoo::UUID.generate()
|
494
|
+
result = @client.resource( :RSpecClientTestTargetCustomRouting, 1 ).show( mock_ident )
|
495
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
496
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
context 'rejects a request with secured option' do
|
501
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
502
|
+
property = description[ :property ]
|
503
|
+
secured = description[ :secured ]
|
504
|
+
|
505
|
+
next unless secured == true
|
506
|
+
|
507
|
+
it "'#{ property }' present" do
|
508
|
+
case property
|
509
|
+
when :resource_uuid
|
510
|
+
@resource_uuid = Hoodoo::UUID.generate
|
511
|
+
else
|
512
|
+
raise "Update client_spec.rb with new secured properties for test"
|
513
|
+
end
|
514
|
+
|
515
|
+
set_vars_for(
|
516
|
+
base_uri: "http://localhost:#{ @port }",
|
517
|
+
auto_session: false
|
518
|
+
)
|
519
|
+
|
520
|
+
mock_ident = Hoodoo::UUID.generate()
|
521
|
+
result = @endpoint.show( mock_ident )
|
522
|
+
|
523
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
524
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.forbidden' )
|
525
|
+
end
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
context 'accepts a request with non-secured option' do
|
530
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
531
|
+
property = description[ :property ]
|
532
|
+
secured = description[ :secured ]
|
533
|
+
|
534
|
+
next if secured == true
|
535
|
+
|
536
|
+
context "'#{ property }' present" do
|
537
|
+
before :each do
|
538
|
+
case property
|
539
|
+
when :dated_at
|
540
|
+
@dated_at = Time.now - 1.year
|
541
|
+
when :dated_from
|
542
|
+
@dated_from = Time.now - 2.years
|
543
|
+
when :deja_vu
|
544
|
+
@deja_vu = true
|
545
|
+
else
|
546
|
+
raise "Update client_spec.rb with new non-secured properties for test"
|
547
|
+
end
|
548
|
+
|
549
|
+
set_vars_for(
|
550
|
+
base_uri: "http://localhost:#{ @port }",
|
551
|
+
auto_session: false
|
552
|
+
)
|
553
|
+
end
|
554
|
+
|
555
|
+
it_behaves_like Hoodoo::Client
|
556
|
+
end
|
557
|
+
end
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
##############################################################################
|
562
|
+
# No automatic session acquisition with manual session
|
563
|
+
##############################################################################
|
564
|
+
|
565
|
+
context 'with a manual session' do
|
566
|
+
shared_examples Hoodoo::Client do
|
567
|
+
it '(public actions allowed)' do
|
568
|
+
mock_ident = Hoodoo::UUID.generate()
|
569
|
+
|
570
|
+
result = @endpoint.show( mock_ident )
|
571
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
572
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
573
|
+
end
|
574
|
+
|
575
|
+
it '(protected actions prohibited)' do
|
576
|
+
mock_ident = Hoodoo::UUID.generate()
|
577
|
+
embeds = [ 'bar' ]
|
578
|
+
query_hash = { '_embed' => embeds }
|
579
|
+
|
580
|
+
result = @endpoint.list( query_hash )
|
581
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
582
|
+
expect( result.dataset_size ).to eq( result.size )
|
583
|
+
|
584
|
+
expect( result[ 0 ][ 'embeds' ] ).to eq( embeds )
|
585
|
+
expect( result[ 0 ][ 'language' ] ).to eq( @expected_locale )
|
586
|
+
|
587
|
+
option_based_expectations( result )
|
588
|
+
|
589
|
+
embeds = [ 'baz' ]
|
590
|
+
query_hash = { '_embed' => embeds }
|
591
|
+
body_hash = { 'hello' => 'world' }
|
592
|
+
|
593
|
+
result = @endpoint.create( body_hash, query_hash )
|
594
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
595
|
+
|
596
|
+
expect( result[ 'body_hash' ] ).to eq( body_hash )
|
597
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
598
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
599
|
+
|
600
|
+
option_based_expectations( result )
|
601
|
+
|
602
|
+
mock_ident = Hoodoo::UUID.generate()
|
603
|
+
embeds = [ 'foo' ]
|
604
|
+
query_hash = { '_embed' => embeds }
|
605
|
+
body_hash = { 'left' => 'right' }
|
606
|
+
|
607
|
+
result = @endpoint.update( mock_ident, body_hash, query_hash )
|
608
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
609
|
+
expect( result.response_options[ 'example_header' ] ).to eq( 'example' )
|
610
|
+
|
611
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
612
|
+
expect( result[ 'body_hash' ] ).to eq( body_hash )
|
613
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
614
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
615
|
+
|
616
|
+
option_based_expectations( result )
|
617
|
+
|
618
|
+
mock_ident = Hoodoo::UUID.generate()
|
619
|
+
embeds = [ 'baz', 'bar' ]
|
620
|
+
query_hash = { '_embed' => embeds }
|
621
|
+
|
622
|
+
result = @endpoint.delete( mock_ident, query_hash )
|
623
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
624
|
+
|
625
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
626
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
627
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
628
|
+
|
629
|
+
option_based_expectations( result )
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
before :each do
|
634
|
+
Hoodoo::Services::Middleware.set_test_session( @old_test_session )
|
635
|
+
end
|
636
|
+
|
637
|
+
context 'and by DRb' do
|
638
|
+
before :each do
|
639
|
+
set_vars_for(
|
640
|
+
drb_port: URI.parse( Hoodoo::Services::Discovery::ByDRb::DRbServer.uri() ).port,
|
641
|
+
auto_session: false,
|
642
|
+
session_id: @old_test_session.session_id
|
643
|
+
)
|
644
|
+
end
|
645
|
+
|
646
|
+
it_behaves_like Hoodoo::Client
|
647
|
+
end
|
648
|
+
|
649
|
+
context 'and by convention' do
|
650
|
+
before :each do
|
651
|
+
set_vars_for(
|
652
|
+
base_uri: "http://localhost:#{ @port }",
|
653
|
+
auto_session: false,
|
654
|
+
session_id: @old_test_session.session_id
|
655
|
+
)
|
656
|
+
end
|
657
|
+
|
658
|
+
it_behaves_like Hoodoo::Client
|
659
|
+
end
|
660
|
+
|
661
|
+
context 'and when endpoints return errors' do
|
662
|
+
before :each do
|
663
|
+
set_vars_for(
|
664
|
+
base_uri: "http://localhost:#{ @port }",
|
665
|
+
auto_session: false,
|
666
|
+
session_id: @old_test_session.session_id
|
667
|
+
)
|
668
|
+
end
|
669
|
+
|
670
|
+
it 'returns an AugmentedArray for #list' do
|
671
|
+
result = @endpoint.list( { :offset => 42 } ) # 42 -> magic -> service adds error
|
672
|
+
|
673
|
+
expect( result ).to be_a( Hoodoo::Client::AugmentedArray )
|
674
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
675
|
+
end
|
676
|
+
|
677
|
+
it 'returns an AugmentedHash for #show' do
|
678
|
+
result = @endpoint.show( 'return_error' )
|
679
|
+
|
680
|
+
expect( result ).to be_a( Hoodoo::Client::AugmentedHash )
|
681
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
682
|
+
end
|
683
|
+
|
684
|
+
it 'returns an AugmentedHash for #create' do
|
685
|
+
result = @endpoint.create( { 'return_error' => true } )
|
686
|
+
|
687
|
+
expect( result ).to be_a( Hoodoo::Client::AugmentedHash )
|
688
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
689
|
+
end
|
690
|
+
|
691
|
+
it 'returns an AugmentedHash for #update' do
|
692
|
+
result = @endpoint.update( 'return_error', {} )
|
693
|
+
|
694
|
+
expect( result ).to be_a( Hoodoo::Client::AugmentedHash )
|
695
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
696
|
+
end
|
697
|
+
|
698
|
+
it 'returns an AugmentedHash for #delete' do
|
699
|
+
result = @endpoint.delete( 'return_error' )
|
700
|
+
|
701
|
+
expect( result ).to be_a( Hoodoo::Client::AugmentedHash )
|
702
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
context 'and with non-secured option' do
|
707
|
+
|
708
|
+
# Specific functional tests
|
709
|
+
|
710
|
+
it "'deja_vu' in use" do
|
711
|
+
@deja_vu = true
|
712
|
+
|
713
|
+
set_vars_for(
|
714
|
+
base_uri: "http://localhost:#{ @port }",
|
715
|
+
auto_session: false
|
716
|
+
)
|
717
|
+
|
718
|
+
result = @endpoint.create( { 'hello' => 'world' } )
|
719
|
+
|
720
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
721
|
+
expect( result.response_options[ 'deja_vu' ] ).to eq( 'confirmed' )
|
722
|
+
end
|
723
|
+
end
|
724
|
+
|
725
|
+
context 'and with secured option' do
|
726
|
+
before :each do
|
727
|
+
test_session = @old_test_session.dup
|
728
|
+
test_session.scoping = @old_test_session.scoping.dup
|
729
|
+
test_session.scoping.authorised_http_headers = []
|
730
|
+
|
731
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
732
|
+
next unless description[ :secured ] == true
|
733
|
+
test_session.scoping.authorised_http_headers << rack_header
|
734
|
+
end
|
735
|
+
|
736
|
+
Hoodoo::Services::Middleware.set_test_session( test_session )
|
737
|
+
end
|
738
|
+
|
739
|
+
after :each do
|
740
|
+
Hoodoo::Services::Middleware.set_test_session( @old_test_session )
|
741
|
+
end
|
742
|
+
|
743
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
744
|
+
property = description[ :property ]
|
745
|
+
secured = description[ :secured ]
|
746
|
+
|
747
|
+
next unless secured == true
|
748
|
+
|
749
|
+
it "'#{ property }' present" do
|
750
|
+
case property
|
751
|
+
when :resource_uuid
|
752
|
+
@resource_uuid = Hoodoo::UUID.generate
|
753
|
+
else
|
754
|
+
raise "Update client_spec.rb with new secured properties for test"
|
755
|
+
end
|
756
|
+
|
757
|
+
set_vars_for(
|
758
|
+
base_uri: "http://localhost:#{ @port }",
|
759
|
+
auto_session: false
|
760
|
+
)
|
761
|
+
|
762
|
+
mock_ident = Hoodoo::UUID.generate()
|
763
|
+
result = @endpoint.show( mock_ident )
|
764
|
+
|
765
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
# Specific functional tests
|
770
|
+
|
771
|
+
it "'resource_uuid' in use" do
|
772
|
+
@resource_uuid = Hoodoo::UUID.generate
|
773
|
+
|
774
|
+
set_vars_for(
|
775
|
+
base_uri: "http://localhost:#{ @port }",
|
776
|
+
auto_session: false
|
777
|
+
)
|
778
|
+
|
779
|
+
result = @endpoint.create( { 'hello' => 'world' } )
|
780
|
+
|
781
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
782
|
+
expect( result[ 'id' ] ).to eq( @resource_uuid )
|
783
|
+
end
|
784
|
+
end
|
785
|
+
end
|
786
|
+
|
787
|
+
##############################################################################
|
788
|
+
# Automatic session acquisition
|
789
|
+
##############################################################################
|
790
|
+
|
791
|
+
context 'with auto-session' do
|
792
|
+
shared_examples Hoodoo::Client do
|
793
|
+
it '(public actions allowed)' do
|
794
|
+
mock_ident = Hoodoo::UUID.generate()
|
795
|
+
|
796
|
+
result = @endpoint.show( mock_ident )
|
797
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
798
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
799
|
+
end
|
800
|
+
|
801
|
+
it '(protected actions allowed)' do
|
802
|
+
mock_ident = Hoodoo::UUID.generate()
|
803
|
+
embeds = [ 'bar' ]
|
804
|
+
query_hash = { '_embed' => embeds }
|
805
|
+
|
806
|
+
result = @endpoint.list( query_hash )
|
807
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
808
|
+
expect( result.dataset_size ).to eq( result.size )
|
809
|
+
|
810
|
+
expect( result[ 0 ][ 'embeds' ] ).to eq( embeds )
|
811
|
+
expect( result[ 0 ][ 'language' ] ).to eq( @expected_locale )
|
812
|
+
|
813
|
+
option_based_expectations( result )
|
814
|
+
|
815
|
+
embeds = [ 'baz' ]
|
816
|
+
query_hash = { '_embed' => embeds }
|
817
|
+
body_hash = { 'hello' => 'world' }
|
818
|
+
|
819
|
+
result = @endpoint.create( body_hash, query_hash )
|
820
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
821
|
+
|
822
|
+
expect( result[ 'body_hash' ] ).to eq( body_hash )
|
823
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
824
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
825
|
+
|
826
|
+
option_based_expectations( result )
|
827
|
+
|
828
|
+
mock_ident = Hoodoo::UUID.generate()
|
829
|
+
embeds = [ 'foo' ]
|
830
|
+
query_hash = { '_embed' => embeds }
|
831
|
+
body_hash = { 'left' => 'right' }
|
832
|
+
|
833
|
+
result = @endpoint.update( mock_ident, body_hash, query_hash )
|
834
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
835
|
+
expect( result.response_options[ 'example_header' ] ).to eq( 'example' )
|
836
|
+
|
837
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
838
|
+
expect( result[ 'body_hash' ] ).to eq( body_hash )
|
839
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
840
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
841
|
+
|
842
|
+
option_based_expectations( result )
|
843
|
+
|
844
|
+
mock_ident = Hoodoo::UUID.generate()
|
845
|
+
embeds = [ 'baz', 'bar' ]
|
846
|
+
query_hash = { '_embed' => embeds }
|
847
|
+
|
848
|
+
result = @endpoint.delete( mock_ident, query_hash )
|
849
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
850
|
+
|
851
|
+
expect( result[ 'id' ] ).to eq( mock_ident )
|
852
|
+
expect( result[ 'embeds' ] ).to eq( embeds )
|
853
|
+
expect( result[ 'language' ] ).to eq( @expected_locale )
|
854
|
+
|
855
|
+
option_based_expectations( result )
|
856
|
+
end
|
857
|
+
|
858
|
+
it 'automatically retries' do
|
859
|
+
result = @endpoint.list()
|
860
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
861
|
+
|
862
|
+
expect_any_instance_of( RSpecClientTestSessionImplementation ).to receive( :create ).once.and_call_original
|
863
|
+
Hoodoo::Services::Middleware.set_test_session( nil )
|
864
|
+
|
865
|
+
result = @endpoint.list()
|
866
|
+
expect( result.platform_errors.has_errors? ).to eq( false )
|
867
|
+
end
|
868
|
+
|
869
|
+
it 'handles errors from the session resource' do
|
870
|
+
expect_any_instance_of( RSpecClientTestSessionImplementation ).to receive( :create ).and_raise( "boo!" )
|
871
|
+
|
872
|
+
Hoodoo::Services::Middleware.set_test_session( nil )
|
873
|
+
|
874
|
+
result = @endpoint.list()
|
875
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
876
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.fault' )
|
877
|
+
end
|
878
|
+
|
879
|
+
it 'handles malformed sessions' do
|
880
|
+
expect_any_instance_of( RSpecClientTestSessionImplementation ).to receive( :create ) { | ignored, context |
|
881
|
+
context.response.body = { 'not' => 'a session' }
|
882
|
+
}
|
883
|
+
|
884
|
+
Hoodoo::Services::Middleware.set_test_session( nil )
|
885
|
+
|
886
|
+
result = @endpoint.list()
|
887
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
888
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'generic.malformed' )
|
889
|
+
end
|
890
|
+
|
891
|
+
# This is a fragile test due to the way it is forced to simulate a
|
892
|
+
# connection fault; see similar test in middleware_multi_spec.rb
|
893
|
+
# for details.
|
894
|
+
#
|
895
|
+
it 'handles explicit connection errors as 404' do
|
896
|
+
expect_any_instance_of( Net::HTTP ).to receive( :request ).once.and_raise( Errno::ECONNREFUSED )
|
897
|
+
result = @endpoint.list()
|
898
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
899
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.not_found' )
|
900
|
+
end
|
901
|
+
|
902
|
+
# As above, this is a fragile test.
|
903
|
+
#
|
904
|
+
it 'handles arbitrary communication errors as 500' do
|
905
|
+
expect_any_instance_of( Net::HTTP ).to receive( :request ).once.and_raise( 'some connection error' )
|
906
|
+
result = @endpoint.list()
|
907
|
+
expect( result.platform_errors.has_errors? ).to eq( true )
|
908
|
+
expect( result.platform_errors.errors[ 0 ][ 'code' ] ).to eq( 'platform.fault' )
|
909
|
+
expect( result.platform_errors.errors[ 0 ][ 'reference' ] ).to include( 'some connection error' )
|
910
|
+
end
|
911
|
+
end
|
912
|
+
|
913
|
+
before :each do
|
914
|
+
Hoodoo::Services::Middleware.set_test_session( nil )
|
915
|
+
end
|
916
|
+
|
917
|
+
context 'and by DRb' do
|
918
|
+
before :each do
|
919
|
+
set_vars_for(
|
920
|
+
drb_port: URI.parse( Hoodoo::Services::Discovery::ByDRb::DRbServer.uri() ).port,
|
921
|
+
caller_id: Hoodoo::UUID.generate,
|
922
|
+
caller_secret: Hoodoo::UUID.generate,
|
923
|
+
auto_session_resource: 'RSpecClientTestSession'
|
924
|
+
)
|
925
|
+
end
|
926
|
+
|
927
|
+
it_behaves_like Hoodoo::Client
|
928
|
+
end
|
929
|
+
|
930
|
+
context 'and by convention' do
|
931
|
+
before :each do
|
932
|
+
set_vars_for(
|
933
|
+
base_uri: "http://localhost:#{ @port }",
|
934
|
+
caller_id: Hoodoo::UUID.generate,
|
935
|
+
caller_secret: Hoodoo::UUID.generate,
|
936
|
+
auto_session_resource: 'RSpecClientTestSession'
|
937
|
+
)
|
938
|
+
end
|
939
|
+
|
940
|
+
it_behaves_like Hoodoo::Client
|
941
|
+
end
|
942
|
+
end
|
943
|
+
|
944
|
+
##############################################################################
|
945
|
+
# Code coverage
|
946
|
+
##############################################################################
|
947
|
+
|
948
|
+
context 'code coverage' do
|
949
|
+
it 'complains about missing options in the constructor' do
|
950
|
+
expect {
|
951
|
+
Hoodoo::Client.new
|
952
|
+
}.to raise_error( RuntimeError, 'Hoodoo::Client: Please pass one of the "discoverer", "base_uri", "drb_uri" or "drb_port" parameters.' )
|
953
|
+
end
|
954
|
+
end
|
955
|
+
end
|