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.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/bin/hoodoo +5 -0
  3. data/lib/hoodoo.rb +27 -0
  4. data/lib/hoodoo/active.rb +32 -0
  5. data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
  6. data/lib/hoodoo/active/active_record/base.rb +81 -0
  7. data/lib/hoodoo/active/active_record/creator.rb +134 -0
  8. data/lib/hoodoo/active/active_record/dated.rb +343 -0
  9. data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
  10. data/lib/hoodoo/active/active_record/finder.rb +606 -0
  11. data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
  12. data/lib/hoodoo/active/active_record/secure.rb +431 -0
  13. data/lib/hoodoo/active/active_record/support.rb +106 -0
  14. data/lib/hoodoo/active/active_record/translated.rb +87 -0
  15. data/lib/hoodoo/active/active_record/uuid.rb +80 -0
  16. data/lib/hoodoo/active/active_record/writer.rb +321 -0
  17. data/lib/hoodoo/client.rb +23 -0
  18. data/lib/hoodoo/client/augmented_array.rb +29 -0
  19. data/lib/hoodoo/client/augmented_base.rb +168 -0
  20. data/lib/hoodoo/client/augmented_hash.rb +23 -0
  21. data/lib/hoodoo/client/client.rb +354 -0
  22. data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
  23. data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
  24. data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
  25. data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
  26. data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
  27. data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
  28. data/lib/hoodoo/client/headers.rb +269 -0
  29. data/lib/hoodoo/communicators.rb +23 -0
  30. data/lib/hoodoo/communicators/fast.rb +44 -0
  31. data/lib/hoodoo/communicators/pool.rb +601 -0
  32. data/lib/hoodoo/communicators/slow.rb +84 -0
  33. data/lib/hoodoo/data.rb +51 -0
  34. data/lib/hoodoo/data/resources/caller.rb +39 -0
  35. data/lib/hoodoo/data/resources/errors.rb +28 -0
  36. data/lib/hoodoo/data/resources/log.rb +31 -0
  37. data/lib/hoodoo/data/resources/session.rb +26 -0
  38. data/lib/hoodoo/data/types/error_primitive.rb +27 -0
  39. data/lib/hoodoo/data/types/permissions.rb +40 -0
  40. data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
  41. data/lib/hoodoo/data/types/permissions_full.rb +28 -0
  42. data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
  43. data/lib/hoodoo/discovery.rb +20 -0
  44. data/lib/hoodoo/errors.rb +19 -0
  45. data/lib/hoodoo/errors/error_descriptions.rb +229 -0
  46. data/lib/hoodoo/errors/errors.rb +322 -0
  47. data/lib/hoodoo/generator.rb +139 -0
  48. data/lib/hoodoo/logger.rb +23 -0
  49. data/lib/hoodoo/logger/fast_writer.rb +27 -0
  50. data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
  51. data/lib/hoodoo/logger/logger.rb +387 -0
  52. data/lib/hoodoo/logger/slow_writer.rb +49 -0
  53. data/lib/hoodoo/logger/writer_mixin.rb +52 -0
  54. data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
  55. data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
  56. data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
  57. data/lib/hoodoo/middleware.rb +33 -0
  58. data/lib/hoodoo/presenters.rb +45 -0
  59. data/lib/hoodoo/presenters/base.rb +281 -0
  60. data/lib/hoodoo/presenters/base_dsl.rb +519 -0
  61. data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
  62. data/lib/hoodoo/presenters/embedding.rb +232 -0
  63. data/lib/hoodoo/presenters/types/array.rb +118 -0
  64. data/lib/hoodoo/presenters/types/boolean.rb +26 -0
  65. data/lib/hoodoo/presenters/types/date.rb +26 -0
  66. data/lib/hoodoo/presenters/types/date_time.rb +26 -0
  67. data/lib/hoodoo/presenters/types/decimal.rb +47 -0
  68. data/lib/hoodoo/presenters/types/enum.rb +55 -0
  69. data/lib/hoodoo/presenters/types/field.rb +158 -0
  70. data/lib/hoodoo/presenters/types/float.rb +26 -0
  71. data/lib/hoodoo/presenters/types/hash.rb +361 -0
  72. data/lib/hoodoo/presenters/types/integer.rb +26 -0
  73. data/lib/hoodoo/presenters/types/object.rb +117 -0
  74. data/lib/hoodoo/presenters/types/string.rb +53 -0
  75. data/lib/hoodoo/presenters/types/tags.rb +24 -0
  76. data/lib/hoodoo/presenters/types/text.rb +26 -0
  77. data/lib/hoodoo/presenters/types/uuid.rb +54 -0
  78. data/lib/hoodoo/services.rb +34 -0
  79. data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
  80. data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
  81. data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
  82. data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
  83. data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
  84. data/lib/hoodoo/services/discovery/discovery.rb +186 -0
  85. data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
  86. data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
  87. data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
  88. data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
  89. data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
  90. data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
  91. data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
  92. data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
  93. data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
  94. data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
  95. data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
  96. data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
  97. data/lib/hoodoo/services/middleware/interaction.rb +127 -0
  98. data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
  99. data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
  100. data/lib/hoodoo/services/services/context.rb +153 -0
  101. data/lib/hoodoo/services/services/implementation.rb +132 -0
  102. data/lib/hoodoo/services/services/interface.rb +934 -0
  103. data/lib/hoodoo/services/services/permissions.rb +250 -0
  104. data/lib/hoodoo/services/services/request.rb +189 -0
  105. data/lib/hoodoo/services/services/response.rb +316 -0
  106. data/lib/hoodoo/services/services/service.rb +141 -0
  107. data/lib/hoodoo/services/services/session.rb +729 -0
  108. data/lib/hoodoo/utilities.rb +12 -0
  109. data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
  110. data/lib/hoodoo/utilities/utilities.rb +380 -0
  111. data/lib/hoodoo/utilities/uuid.rb +44 -0
  112. data/lib/hoodoo/version.rb +17 -0
  113. data/spec/active/active_record/base_spec.rb +57 -0
  114. data/spec/active/active_record/creator_spec.rb +88 -0
  115. data/spec/active/active_record/dated_spec.rb +248 -0
  116. data/spec/active/active_record/error_mapping_spec.rb +360 -0
  117. data/spec/active/active_record/finder_spec.rb +744 -0
  118. data/spec/active/active_record/search_helper_spec.rb +384 -0
  119. data/spec/active/active_record/secure_spec.rb +435 -0
  120. data/spec/active/active_record/support_spec.rb +225 -0
  121. data/spec/active/active_record/translated_spec.rb +19 -0
  122. data/spec/active/active_record/uuid_spec.rb +72 -0
  123. data/spec/active/active_record/writer_spec.rb +272 -0
  124. data/spec/alchemy/alchemy-amq.rb +33 -0
  125. data/spec/client/augmented_array_spec.rb +15 -0
  126. data/spec/client/augmented_base_spec.rb +50 -0
  127. data/spec/client/augmented_hash_spec.rb +15 -0
  128. data/spec/client/client_spec.rb +955 -0
  129. data/spec/client/endpoint/endpoint_spec.rb +70 -0
  130. data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
  131. data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
  132. data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
  133. data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
  134. data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
  135. data/spec/client/headers_spec.rb +172 -0
  136. data/spec/communicators/fast_spec.rb +9 -0
  137. data/spec/communicators/pool_spec.rb +339 -0
  138. data/spec/communicators/slow_spec.rb +15 -0
  139. data/spec/data/resources/caller_spec.rb +156 -0
  140. data/spec/data/resources/errors_spec.rb +22 -0
  141. data/spec/data/resources/log_spec.rb +20 -0
  142. data/spec/data/resources/session_spec.rb +15 -0
  143. data/spec/data/types/error_primitive_spec.rb +15 -0
  144. data/spec/data/types/permissions_defaults_spec.rb +25 -0
  145. data/spec/data/types/permissions_full_spec.rb +44 -0
  146. data/spec/data/types/permissions_resources_spec.rb +34 -0
  147. data/spec/data/types/permissions_spec.rb +37 -0
  148. data/spec/errors/error_descriptions_spec.rb +98 -0
  149. data/spec/errors/errors_spec.rb +346 -0
  150. data/spec/integration/service_actions_spec.rb +112 -0
  151. data/spec/logger/fast_writer_spec.rb +18 -0
  152. data/spec/logger/logger_spec.rb +259 -0
  153. data/spec/logger/slow_writer_spec.rb +144 -0
  154. data/spec/logger/writers/file_writer_spec.rb +37 -0
  155. data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
  156. data/spec/logger/writers/stream_writer_spec.rb +38 -0
  157. data/spec/presenters/base_dsl_spec.rb +111 -0
  158. data/spec/presenters/base_spec.rb +871 -0
  159. data/spec/presenters/common_resource_fields_spec.rb +30 -0
  160. data/spec/presenters/embedding_spec.rb +87 -0
  161. data/spec/presenters/types/array_spec.rb +249 -0
  162. data/spec/presenters/types/boolean_spec.rb +51 -0
  163. data/spec/presenters/types/date_spec.rb +57 -0
  164. data/spec/presenters/types/date_time_spec.rb +59 -0
  165. data/spec/presenters/types/decimal_spec.rb +58 -0
  166. data/spec/presenters/types/enum_spec.rb +71 -0
  167. data/spec/presenters/types/field_spec.rb +77 -0
  168. data/spec/presenters/types/float_spec.rb +50 -0
  169. data/spec/presenters/types/hash_spec.rb +1069 -0
  170. data/spec/presenters/types/integer_spec.rb +50 -0
  171. data/spec/presenters/types/object_spec.rb +177 -0
  172. data/spec/presenters/types/string_spec.rb +65 -0
  173. data/spec/presenters/types/tags_spec.rb +56 -0
  174. data/spec/presenters/types/text_spec.rb +50 -0
  175. data/spec/presenters/types/uuid_spec.rb +46 -0
  176. data/spec/presenters/walk_spec.rb +198 -0
  177. data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
  178. data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
  179. data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
  180. data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
  181. data/spec/services/discovery/discovery_spec.rb +73 -0
  182. data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
  183. data/spec/services/discovery/results/for_http_spec.rb +37 -0
  184. data/spec/services/discovery/results/for_local_spec.rb +21 -0
  185. data/spec/services/discovery/results/for_remote_spec.rb +15 -0
  186. data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
  187. data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
  188. data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
  189. data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
  190. data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
  191. data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
  192. data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
  193. data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
  194. data/spec/services/middleware/middleware_cors_spec.rb +93 -0
  195. data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
  196. data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
  197. data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
  198. data/spec/services/middleware/middleware_logging_spec.rb +356 -0
  199. data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
  200. data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
  201. data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
  202. data/spec/services/middleware/middleware_public_spec.rb +238 -0
  203. data/spec/services/middleware/middleware_spec.rb +1569 -0
  204. data/spec/services/middleware/string_inquirer_spec.rb +30 -0
  205. data/spec/services/services/application_spec.rb +74 -0
  206. data/spec/services/services/context_spec.rb +48 -0
  207. data/spec/services/services/implementation_spec.rb +45 -0
  208. data/spec/services/services/interface_spec.rb +262 -0
  209. data/spec/services/services/permissions_spec.rb +249 -0
  210. data/spec/services/services/request_spec.rb +95 -0
  211. data/spec/services/services/response_spec.rb +250 -0
  212. data/spec/services/services/session_spec.rb +432 -0
  213. data/spec/spec_helper.rb +298 -0
  214. data/spec/utilities/utilities_spec.rb +537 -0
  215. data/spec/utilities/uuid_spec.rb +20 -0
  216. metadata +615 -0
@@ -0,0 +1,198 @@
1
+ require "spec_helper"
2
+
3
+
4
+ # This specific file just tests the presenter layer "#walk" method. It
5
+ # uses (at the time of writing) every single kind of schema field to
6
+ # varying degrees (where possible, e.g. "object") of complexity and
7
+ # then runs one "walk" call over the whole thing to verify that it does
8
+ # get called on every node.
9
+
10
+ describe Hoodoo::Presenters::Base do
11
+ before do
12
+ class TestWalkPresenterA < Hoodoo::Presenters::Base
13
+ schema do
14
+
15
+ # Simple fields
16
+
17
+ boolean :test_boolean
18
+ datetime :test_datetime
19
+ date :test_date
20
+ decimal :test_decimal, :precision => 2
21
+ enum :test_enum, :from => [ :one, :two ]
22
+ float :test_float
23
+ integer :test_integer
24
+ string :test_string, :length => 8
25
+ tags :test_tags
26
+ text :test_text
27
+ uuid :test_uuid
28
+
29
+ # Objects, in their various permitted forms
30
+
31
+ object :test_object_2 do
32
+ text :test_object_2_text_1
33
+ text :test_object_2_text_2
34
+ end
35
+
36
+ object :test_object_3 do
37
+ text :test_object_3_text_1
38
+ object :test_object_3_object_1 do
39
+ text :test_object_3_object_1_text_1
40
+ end
41
+ array :test_object_3_array_1 do
42
+ text :test_object_3_array_1_text_1
43
+ text :test_object_3_array_1_text_2
44
+ end
45
+ text :test_object_3_text_2
46
+ end
47
+
48
+ # Arrays, in their various permitted forms
49
+
50
+ array :text_array_1
51
+
52
+ array :test_array_2 do
53
+ text :test_array_2_text_1
54
+ text :test_array_2_text_2
55
+ end
56
+
57
+ array :test_array_3 do
58
+ text :test_array_3_text_1
59
+ object :test_array_3_object_1 do
60
+ text :test_array_3_object_1_text_1
61
+ text :test_array_3_object_1_text_2
62
+ end
63
+ text :test_array_3_text_2
64
+ end
65
+
66
+ # Hashes, in their various complex permitted forms
67
+
68
+ hash :test_hash_1
69
+
70
+ hash :test_hash_2 do
71
+ key :test_hash_2_key_1 do
72
+ text :test_hash_2_key_1_text_1
73
+ object :test_hash_2_key_1_object_1 do
74
+ text :test_hash_2_key_1_object_1_text_1
75
+ end
76
+ end
77
+ key :test_hash_2_key_2 do
78
+ array :test_hash_2_key_2_array_1 do
79
+ text :test_hash_2_key_2_array_1_text_1
80
+ end
81
+ end
82
+ end
83
+
84
+ hash :test_hash_3 do
85
+ keys do
86
+ text :test_hash_3_keys_text_1
87
+ object :test_hash_3_keys_object_1 do
88
+ text :test_hash_3_keys_object_1_text_1
89
+ end
90
+ array :test_hash_3_keys_array_1 do
91
+ text :test_hash_3_keys_array_1_text_1
92
+ end
93
+ end
94
+ end
95
+
96
+ hash :test_hash_4 do
97
+ keys :length => 4
98
+ end
99
+
100
+ end # 'schema do'
101
+ end # 'class TestWalkPresenter < Hoodoo::Presenters::Base'
102
+
103
+ class TestWalkPresenterB < Hoodoo::Presenters::Base
104
+ schema do
105
+ text :simple_text
106
+ end
107
+ end
108
+
109
+ class TestWalkPresenterC < Hoodoo::Presenters::Base
110
+ schema do
111
+ end
112
+ end
113
+
114
+ end # 'before do'
115
+
116
+ context '#walk' do
117
+ it 'handles complex tree' do
118
+ names = []
119
+
120
+ TestWalkPresenterA.walk do | property |
121
+ names << property.name
122
+ end
123
+
124
+ expected_names = [ '' ] + %w{
125
+ test_boolean
126
+ test_datetime
127
+ test_date
128
+ test_decimal
129
+ test_enum
130
+ test_float
131
+ test_integer
132
+ test_string
133
+ test_tags
134
+ test_text
135
+ test_uuid
136
+ test_object_2
137
+ test_object_2_text_1
138
+ test_object_2_text_2
139
+ test_object_3
140
+ test_object_3_text_1
141
+ test_object_3_object_1
142
+ test_object_3_object_1_text_1
143
+ test_object_3_array_1
144
+ test_object_3_array_1_text_1
145
+ test_object_3_array_1_text_2
146
+ test_object_3_text_2
147
+ text_array_1
148
+ test_array_2
149
+ test_array_2_text_1
150
+ test_array_2_text_2
151
+ test_array_3
152
+ test_array_3_text_1
153
+ test_array_3_object_1
154
+ test_array_3_object_1_text_1
155
+ test_array_3_object_1_text_2
156
+ test_array_3_text_2
157
+ test_hash_1
158
+ test_hash_2
159
+ test_hash_2_key_1
160
+ test_hash_2_key_1_text_1
161
+ test_hash_2_key_1_object_1
162
+ test_hash_2_key_1_object_1_text_1
163
+ test_hash_2_key_2
164
+ test_hash_2_key_2_array_1
165
+ test_hash_2_key_2_array_1_text_1
166
+ test_hash_3
167
+ test_hash_3_keys_text_1
168
+ test_hash_3_keys_object_1
169
+ test_hash_3_keys_object_1_text_1
170
+ test_hash_3_keys_array_1
171
+ test_hash_3_keys_array_1_text_1
172
+ test_hash_4
173
+ }
174
+
175
+ expect( names ).to eq( expected_names )
176
+ end
177
+
178
+ it 'handles simple tree' do
179
+ names = []
180
+
181
+ TestWalkPresenterB.walk do | property |
182
+ names << property.name
183
+ end
184
+
185
+ expect( names ).to eq( [ '', 'simple_text' ] )
186
+ end
187
+
188
+ it 'handles empty tree' do
189
+ names = []
190
+
191
+ TestWalkPresenterC.walk do | property |
192
+ names << property.name
193
+ end
194
+
195
+ expect( names ).to eq( [ '' ] )
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hoodoo::Services::Discovery::ByConsul do
4
+ before :each do
5
+ @d = described_class.new
6
+ end
7
+
8
+ # TODO: Assume static mapping and no Consul communication to mock out.
9
+
10
+ it 'announces' do
11
+ result = @d.announce( 'Version', '2' ) # Intentional string use
12
+ expect( result ).to be_a( Hoodoo::Services::Discovery::ForAMQP )
13
+ expect( result.resource ).to eq( :Version )
14
+ expect( result.version ).to eq( 2 )
15
+ expect( result.queue_name ).to eq( 'service.version' )
16
+ expect( result.equivalent_path ).to eq( '/v2/versions')
17
+ end
18
+
19
+ it 'discovers' do
20
+ result = @d.announce( 'Version', 2 )
21
+ @d.instance_variable_set( '@known_local_resources', {} ) # Hack for test!
22
+
23
+ result = @d.discover( :Version, 2 )
24
+ expect( result.resource ).to eq( :Version )
25
+ expect( result.version ).to eq( 2 )
26
+ expect( result.queue_name ).to eq( 'service.version' )
27
+ expect( result.equivalent_path ).to eq( '/v2/versions')
28
+ end
29
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hoodoo::Services::Discovery::ByConvention do
4
+ context 'with default routing' do
5
+ before :each do
6
+ @d = described_class.new( :base_uri => 'http://pond.org.uk' )
7
+ end
8
+
9
+ it 'announces' do
10
+ result = @d.announce( 'Apple', '3' ) # Intentional string use
11
+ expect( result ).to be_a( Hoodoo::Services::Discovery::ForHTTP )
12
+ expect( result.resource ).to eq( :Apple )
13
+ expect( result.version ).to eq( 3 )
14
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v3/apples')
15
+
16
+ result = @d.announce( 'Sheep', 2 )
17
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v2/sheep')
18
+ end
19
+
20
+ it 'discovers' do
21
+ @d.announce( 'Apple', 3 )
22
+ @d.instance_variable_set( '@known_local_resources', {} ) # Hack for test!
23
+
24
+ result = @d.discover( :Apple, 3 )
25
+ expect( result ).to be_a( Hoodoo::Services::Discovery::ForHTTP )
26
+ expect( result.resource ).to eq( :Apple )
27
+ expect( result.version ).to eq( 3 )
28
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v3/apples')
29
+ end
30
+ end
31
+
32
+ context 'with overridden routing' do
33
+ before :each do
34
+ @d = described_class.new(
35
+ :base_uri => 'http://pond.org.uk',
36
+ :routing => {
37
+ :Version => { 1 => '/v1/version', 2 => '/version_2/version_singleton' },
38
+ :Health => { 2 => '/v2/health' }
39
+ }
40
+ )
41
+ end
42
+
43
+ it 'discovers' do
44
+ @d.announce( :Version, 1 )
45
+ @d.announce( 'Version', 2 ) # Intentional string use
46
+ @d.announce( :Version, 3 )
47
+ @d.announce( :Apple, 3 )
48
+ @d.announce( :Health, 1 )
49
+ @d.announce( :Health, 2 )
50
+
51
+ @d.instance_variable_set( '@known_local_resources', {} ) # Hack for test!
52
+
53
+ result = @d.discover( :Version, 1 )
54
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v1/version')
55
+ result = @d.discover( :Version, 2 )
56
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/version_2/version_singleton')
57
+ result = @d.discover( :Version, 3 )
58
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v3/versions')
59
+ result = @d.discover( :Apple, 3 )
60
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v3/apples')
61
+ result = @d.discover( :Health, 1 )
62
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v1/healths')
63
+ result = @d.discover( :Health, 2 )
64
+ expect( result.endpoint_uri.to_s ).to eq( 'http://pond.org.uk/v2/health')
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ # A lot of this class is already covered by tests elsewhere, e.g. the
4
+ # drb_server_spec.rb stuff (via the middleware integration test part).
5
+
6
+ describe Hoodoo::Services::Discovery::ByDRb do
7
+
8
+ # Shut down a DRb service expected to be running (in a thread) on
9
+ # the given port.
10
+ #
11
+ def shut_down_drb_service_on( port )
12
+ begin
13
+ Timeout::timeout( 10 ) do
14
+ loop do
15
+ begin
16
+ client = DRbObject.new_with_uri( Hoodoo::Services::Discovery::ByDRb::DRbServer.uri( port ) )
17
+ client.ping()
18
+ client.stop()
19
+ break
20
+ rescue DRb::DRbConnError
21
+ sleep 0.1
22
+ end
23
+ end
24
+ end
25
+ rescue Timeout::Error
26
+ raise "Timed out while waiting for DRb service to communicate"
27
+ end
28
+ end
29
+
30
+ # This also tests in passing specifying a port number right through
31
+ # the discoverer to the CLI script that starts a DRb server up.
32
+ #
33
+ # If you get timeouts from the test, it's likely that the port number
34
+ # hasn't reached the server startup script and the server has come up
35
+ # on a different port.
36
+ #
37
+ it 'runs a DRb service which can be pinged and shuts down' do
38
+ expect {
39
+ port = Hoodoo::Utilities.spare_port().to_s
40
+
41
+ discoverer = Hoodoo::Services::Discovery::ByDRb.new( :drb_port => port )
42
+ discoverer.announce( :Foo, 1, :host => '127.0.0.1', :port => '9292' )
43
+
44
+ shut_down_drb_service_on( port )
45
+ }.to_not raise_error
46
+ end
47
+
48
+ # Similar to the above, but this tests passing in a full URI and assuming
49
+ # that the service is already running.
50
+ #
51
+ it 'can contact an existing DRb server' do
52
+ expect {
53
+ port = Hoodoo::Utilities.spare_port().to_s
54
+
55
+ discoverer = Hoodoo::Services::Discovery::ByDRb.new( :drb_port => port )
56
+ discoverer.announce( :Foo, 1, :host => '127.0.0.1', :port => '9292' )
57
+
58
+ discoverer = Hoodoo::Services::Discovery::ByDRb.new(
59
+ :drb_uri => Hoodoo::Services::Discovery::ByDRb::DRbServer.uri( port )
60
+ )
61
+
62
+ expect( discoverer.discover( :Foo, 1 ) ).to be_a( Hoodoo::Services::Discovery::ForHTTP )
63
+
64
+ shut_down_drb_service_on( port )
65
+ }.to_not raise_error
66
+ end
67
+
68
+ it 'complains if it cannot contact an existing DRb server' do
69
+ port = Hoodoo::Utilities.spare_port().to_s
70
+ uri = Hoodoo::Services::Discovery::ByDRb::DRbServer.uri( port )
71
+
72
+ expect {
73
+ discoverer = Hoodoo::Services::Discovery::ByDRb.new( :drb_uri => uri )
74
+ discoverer.discover( :Foo, 1 )
75
+ }.to raise_error(
76
+ RuntimeError,
77
+ "Hoodoo::Services::Discovery::ByDRb could not contact a DRb service registry at #{ uri }"
78
+ )
79
+ end
80
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe Hoodoo::Services::Discovery::ByDRb::DRbServer do
4
+
5
+ # When running tests we can't assume any particular static port is free
6
+ # on the test machine, so we must get a port dynamically. Since it might
7
+ # take a little while for a DRb server to fully shut down "behind the
8
+ # scenes" when we ask it to stop, its claimed port might not be free by
9
+ # the time the 'next test' runs, so we ask for a spare port for each
10
+ # test that runs.
11
+ #
12
+ before :each do
13
+ @drb_uri = "druby://127.0.0.1:#{ Hoodoo::Utilities.spare_port() }"
14
+ end
15
+
16
+ context "class instance" do
17
+ before do
18
+ @inst = described_class.new
19
+ end
20
+
21
+ it 'adds and reads endpoints' do
22
+ @inst.add( :Foo, 2, 'http://localhost:3030/v2/foo' )
23
+ @inst.add( :Foo, 1, 'http://127.0.0.1:3031/v1/foo' )
24
+ @inst.add( :Bar, 1, 'http://0.0.0.0:3032/v1/bar' )
25
+
26
+ expect( @inst.find( :Foo, 1 ) ).to eq( 'http://127.0.0.1:3031/v1/foo' )
27
+ expect( @inst.find( :Bar, 1 ) ).to eq( 'http://0.0.0.0:3032/v1/bar' )
28
+ expect( @inst.find( :Foo, 2 ) ).to eq( 'http://localhost:3030/v2/foo' )
29
+ expect( @inst.find( :Bar, 2 ) ).to be_nil
30
+ end
31
+
32
+ # RCov report coverage only; tests elsewhere call these but code runs
33
+ # in unusual execution contexts and doesn't get reported as covered.
34
+ #
35
+ it '#ping' do
36
+ expect( @inst.ping() ).to eq( true )
37
+ end
38
+ end
39
+
40
+ context "via DRb" do
41
+ it 'starts as a server' do
42
+ DRb.start_service( @drb_uri, Hoodoo::Services::Discovery::ByDRb::FRONT_OBJECT )
43
+ @drb_server = DRbObject.new_with_uri( @drb_uri )
44
+
45
+ expect do
46
+ @drb_server.add( :FooS, 2, 'http://localhost:3030/v2/foo_s' )
47
+ end.to_not raise_error
48
+
49
+ DRb.stop_service
50
+ end
51
+
52
+ it 'runs in a thread, can be pinged and shuts down' do
53
+ expect {
54
+ port = Hoodoo::Utilities.spare_port().to_s
55
+
56
+ thread = Thread.new do
57
+ ENV[ 'HOODOO_DISCOVERY_BY_DRB_PORT_OVERRIDE' ] = port
58
+ described_class.start()
59
+ ENV.delete( 'HOODOO_DISCOVERY_BY_DRB_PORT_OVERRIDE' )
60
+ end
61
+
62
+ client = nil
63
+
64
+ begin
65
+ Timeout::timeout( 5 ) do
66
+ loop do
67
+ begin
68
+ drb_service = DRbObject.new_with_uri( described_class.uri() )
69
+ drb_service.ping()
70
+ drb_service.stop()
71
+ break
72
+ rescue DRb::DRbConnError
73
+ sleep 0.1
74
+ end
75
+ end
76
+ end
77
+ rescue Timeout::Error
78
+ raise "Timed out while waiting for DRb service to communicat"
79
+ end
80
+
81
+ # For good measure...
82
+ #
83
+ ENV.delete( 'HOODOO_DISCOVERY_BY_DRB_PORT_OVERRIDE' )
84
+
85
+ }.to_not raise_error
86
+ end
87
+
88
+ it 'starts as a client' do
89
+ expect {
90
+ DRb.start_service( @drb_uri, Hoodoo::Services::Discovery::ByDRb::FRONT_OBJECT )
91
+ @drb_server = DRbObject.new_with_uri( @drb_uri )
92
+ @drb_server.add( :FooS2, 2, 'http://localhost:3030/v2/foo_s2' )
93
+
94
+ Thread.new do
95
+ @drb_client = DRbObject.new_with_uri( @drb_uri )
96
+ @drb_client.add( :FooC, 2, 'http://localhost:3030/v2/foo_c' )
97
+ end.join
98
+
99
+ DRb.stop_service
100
+
101
+ }.to_not raise_error
102
+ end
103
+
104
+ it 'synchronises data' do
105
+ DRb.start_service( @drb_uri, Hoodoo::Services::Discovery::ByDRb::FRONT_OBJECT )
106
+ @drb_server = DRbObject.new_with_uri( @drb_uri )
107
+
108
+ @drb_server.add( :Foo1, 2, 'http://localhost:3030/v2/foo_1' )
109
+ @drb_server.add( :Foo1, 1, 'http://127.0.0.1:3031/v1/foo_1' )
110
+
111
+ one = Thread.new do
112
+ @drb_client = DRbObject.new_with_uri( @drb_uri )
113
+ @drb_client.add( :Bar1, 1, 'http://0.0.0.0:3032/v1/bar_1' )
114
+
115
+ expect( @drb_client.find( :Foo1, 1 ) ).to eq( 'http://127.0.0.1:3031/v1/foo_1' )
116
+ expect( @drb_client.find( :Foo1, 2 ) ).to eq( 'http://localhost:3030/v2/foo_1' )
117
+ expect( @drb_client.find( :Foo1, 3 ) ).to be_nil
118
+
119
+ @drb_client.add( :Bar1, 1, 'http://0.0.0.0:3032/v1/bar_1' )
120
+ end.join
121
+
122
+ expect( @drb_server.find( :Bar1, 1 ) ).to eq( 'http://0.0.0.0:3032/v1/bar_1' )
123
+
124
+ DRb.stop_service
125
+ end
126
+
127
+ it 'flushes' do
128
+ DRb.start_service( @drb_uri, Hoodoo::Services::Discovery::ByDRb::FRONT_OBJECT )
129
+ @drb_server = DRbObject.new_with_uri( @drb_uri )
130
+
131
+ @drb_server.add( :Foo1, 2, 'http://localhost:3030/v2/foo_1' )
132
+ @drb_server.add( :Foo1, 1, 'http://127.0.0.1:3031/v1/foo_1' )
133
+
134
+ expect( @drb_server.find( :Foo1, 2 ) ).to_not be_nil
135
+ expect( @drb_server.find( :Foo1, 1 ) ).to_not be_nil
136
+
137
+ @drb_server.flush
138
+
139
+ expect( @drb_server.find( :Foo1, 2 ) ).to be_nil
140
+ expect( @drb_server.find( :Foo1, 1 ) ).to be_nil
141
+
142
+ DRb.stop_service
143
+ end
144
+ end
145
+
146
+ # A lot of this is copied from service_middleware_multi_spec.rb and
147
+ # it'd be cleaner if all these tests were in that one file, but it
148
+ # is nice to keep the tests specifically aimed at DRb here (even if
149
+ # a whole bunch of other stuff gets caught in the integration test).
150
+
151
+ @time_now = Time.now.to_s
152
+
153
+ class RSpecTestTimeImplementation < Hoodoo::Services::Implementation
154
+ def list( context )
155
+ context.response.set_resources( [ { 'time' => @time_now } ] )
156
+ end
157
+ end
158
+
159
+ class RSpecTestTimeInterface < Hoodoo::Services::Interface
160
+ interface( :RSpecDRbTestTime ) { endpoint :rspec_drb_test_time, RSpecTestTimeImplementation }
161
+ end
162
+
163
+ class RSpecTestTime < Hoodoo::Services::Service
164
+ comprised_of RSpecTestTimeInterface
165
+ end
166
+
167
+ class RSpecTestClockImplementation < Hoodoo::Services::Implementation
168
+ def list( context )
169
+ context.response.set_resources( context.resource( :RSpecDRbTestTime ).list() + [ { 'clock' => 'responded' } ] )
170
+ end
171
+ end
172
+
173
+ class RSpecTestClockInterface < Hoodoo::Services::Interface
174
+ interface( :RSpecDRbTestClock ) { endpoint :rspec_drb_test_clock, RSpecTestClockImplementation }
175
+ end
176
+
177
+ class RSpecTestClock < Hoodoo::Services::Service
178
+ comprised_of RSpecTestClockInterface
179
+ end
180
+
181
+ context 'via middleware' do
182
+
183
+ before :all do
184
+ @port1 = spec_helper_start_svc_app_in_thread_for( RSpecTestClock )
185
+ @port2 = spec_helper_start_svc_app_in_thread_for( RSpecTestTime )
186
+ end
187
+
188
+ # This is a significant integration test; two real Webrick instances
189
+ # each with its own service on a free HTTP port; one talks to the other
190
+ # over local machine HTTP via the DRb service for discovery.
191
+ #
192
+ it 'properly supports service discovery' do
193
+ response = spec_helper_http( path: '/v1/rspec_drb_test_clock', port: @port1 )
194
+ expect( response.code ).to eq( '200' )
195
+
196
+ parsed = JSON.parse( response.body )
197
+ expect( parsed ).to eq( {
198
+ '_data' => [
199
+ { 'time' => @time_now },
200
+ { 'clock' => 'responded' }
201
+ ]
202
+ } )
203
+ end
204
+ end
205
+ end