vayacondios-server 0.2.11 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. data/.gitignore +3 -1
  2. data/.travis.yml +2 -0
  3. data/Gemfile +15 -9
  4. data/LICENSE.md +2 -6
  5. data/Procfile +1 -1
  6. data/README.md +656 -111
  7. data/Rakefile +89 -6
  8. data/bin/vcd +10 -0
  9. data/bin/vcd-server +8 -0
  10. data/config/database.yml +6 -0
  11. data/config/spec.example.yml +18 -0
  12. data/config/vayacondios.example.yml +15 -0
  13. data/config/vcd-server.rb +37 -0
  14. data/examples/configuration.rb +56 -0
  15. data/examples/event_stream.rb +19 -0
  16. data/examples/simple.rb +61 -0
  17. data/features/event.feature +319 -0
  18. data/features/events.feature +208 -0
  19. data/features/stash.feature +840 -0
  20. data/features/stashes.feature +492 -0
  21. data/features/step_definitions/stash_steps.rb +113 -0
  22. data/features/stream.feature +30 -0
  23. data/features/support/em.rb +14 -0
  24. data/features/support/env.rb +13 -0
  25. data/lib/vayacondios/configuration.rb +63 -0
  26. data/lib/vayacondios/server/api.rb +126 -0
  27. data/lib/vayacondios/server/api_options.rb +56 -0
  28. data/lib/vayacondios/server/configuration.rb +23 -0
  29. data/lib/vayacondios/server/driver.rb +71 -0
  30. data/lib/vayacondios/server/drivers/mongo.rb +126 -0
  31. data/lib/vayacondios/server/handlers/document_handler.rb +81 -0
  32. data/lib/vayacondios/server/handlers/event_handler.rb +31 -26
  33. data/lib/vayacondios/server/handlers/events_handler.rb +31 -0
  34. data/lib/vayacondios/server/handlers/stash_handler.rb +69 -0
  35. data/lib/vayacondios/server/handlers/stashes_handler.rb +49 -0
  36. data/lib/vayacondios/server/handlers/stream_handler.rb +39 -0
  37. data/lib/vayacondios/server/models/document.rb +87 -0
  38. data/lib/vayacondios/server/models/event.rb +198 -0
  39. data/lib/vayacondios/server/models/stash.rb +100 -0
  40. data/lib/vayacondios/server.rb +35 -0
  41. data/lib/vayacondios-server.rb +19 -13
  42. data/lib/vayacondios.rb +22 -0
  43. data/pom.xml +124 -4
  44. data/spec/configuration_spec.rb +41 -0
  45. data/spec/server/api_options_spec.rb +32 -0
  46. data/spec/server/api_spec.rb +279 -0
  47. data/spec/server/configuration_spec.rb +27 -0
  48. data/spec/server/drivers/mongo_spec.rb +107 -0
  49. data/spec/server/handlers/event_handler_spec.rb +62 -0
  50. data/spec/server/handlers/events_handler_spec.rb +51 -0
  51. data/spec/server/handlers/stash_handler_spec.rb +68 -0
  52. data/spec/server/handlers/stashes_handler_spec.rb +50 -0
  53. data/spec/server/handlers/stream_handler_spec.rb +5 -0
  54. data/spec/server/models/document_spec.rb +9 -0
  55. data/spec/server/models/event_spec.rb +185 -0
  56. data/spec/server/models/stash_spec.rb +95 -0
  57. data/spec/spec_helper.rb +23 -3
  58. data/spec/support/database_helper.rb +42 -0
  59. data/spec/support/log_helper.rb +19 -0
  60. data/spec/support/shared_context_for_events.rb +22 -0
  61. data/spec/support/shared_context_for_stashes.rb +24 -0
  62. data/spec/support/shared_examples_for_handlers.rb +32 -0
  63. data/src/main/java/com/infochimps/vayacondios/BaseClient.java +342 -0
  64. data/src/main/java/com/infochimps/vayacondios/HTTPClient.java +426 -0
  65. data/src/main/java/com/infochimps/vayacondios/VayacondiosClient.java +487 -65
  66. data/src/main/java/com/infochimps/vayacondios/test/IntegrationTest.java +3 -0
  67. data/src/test/java/com/infochimps/vayacondios/BaseClientTest.java +50 -0
  68. data/src/test/java/com/infochimps/vayacondios/HTTPClientIT.java +267 -0
  69. data/vayacondios-server.gemspec +9 -9
  70. metadata +127 -122
  71. checksums.yaml +0 -15
  72. data/.rspec +0 -2
  73. data/.yardopts +0 -10
  74. data/Guardfile +0 -41
  75. data/app/http_shim.rb +0 -71
  76. data/bin/vcd.sh +0 -27
  77. data/config/http_shim.rb +0 -43
  78. data/config/vayacondios.example.yaml +0 -7
  79. data/config/vayacondios.yaml +0 -7
  80. data/examples/java/ItemSetTest.java +0 -76
  81. data/lib/tasks/publish.rake +0 -23
  82. data/lib/tasks/spec.rake +0 -11
  83. data/lib/tasks/yard.rake +0 -2
  84. data/lib/vayacondios/client/config.rb +0 -7
  85. data/lib/vayacondios/client/configliere.rb +0 -38
  86. data/lib/vayacondios/client/cube_client.rb +0 -39
  87. data/lib/vayacondios/client/http_client.rb +0 -49
  88. data/lib/vayacondios/client/itemset.rb +0 -130
  89. data/lib/vayacondios/client/legacy_switch.rb +0 -43
  90. data/lib/vayacondios/client/notifier.rb +0 -123
  91. data/lib/vayacondios/client/zabbix_client.rb +0 -148
  92. data/lib/vayacondios/legacy_switch.rb +0 -43
  93. data/lib/vayacondios/server/errors/bad_request.rb +0 -6
  94. data/lib/vayacondios/server/errors/not_found.rb +0 -6
  95. data/lib/vayacondios/server/handlers/config_handler.rb +0 -32
  96. data/lib/vayacondios/server/handlers/itemset_handler.rb +0 -60
  97. data/lib/vayacondios/server/legacy_switch.rb +0 -43
  98. data/lib/vayacondios/server/model/config_document.rb +0 -89
  99. data/lib/vayacondios/server/model/document.rb +0 -25
  100. data/lib/vayacondios/server/model/event_document.rb +0 -94
  101. data/lib/vayacondios/server/model/itemset_document.rb +0 -126
  102. data/lib/vayacondios/server/rack/extract_methods.rb +0 -35
  103. data/lib/vayacondios/server/rack/jsonize.rb +0 -43
  104. data/lib/vayacondios/server/rack/params.rb +0 -50
  105. data/lib/vayacondios/server/rack/path.rb +0 -23
  106. data/lib/vayacondios/server/rack/path_validation.rb +0 -22
  107. data/lib/vayacondios/version.rb +0 -3
  108. data/lib/vayacondios-client.rb +0 -22
  109. data/scripts/hadoop_monitor/configurable.rb +0 -66
  110. data/scripts/hadoop_monitor/hadoop_attempt_scraper.rb +0 -45
  111. data/scripts/hadoop_monitor/hadoop_client.rb +0 -273
  112. data/scripts/hadoop_monitor/hadoop_monitor.rb +0 -101
  113. data/scripts/hadoop_monitor/hadoopable.rb +0 -65
  114. data/scripts/hadoop_monitor/machine_monitor.rb +0 -115
  115. data/scripts/s3_cataloger/buckets +0 -33
  116. data/scripts/s3_cataloger/foreach_bucket +0 -88
  117. data/scripts/s3_cataloger/parse_ls.py +0 -391
  118. data/spec/client/itemset_legacy_spec.rb +0 -55
  119. data/spec/client/itemset_spec.rb +0 -60
  120. data/spec/client/notifier_spec.rb +0 -120
  121. data/spec/server/config_spec.rb +0 -113
  122. data/spec/server/event_spec.rb +0 -103
  123. data/spec/server/itemset_legacy_spec.rb +0 -320
  124. data/spec/server/itemset_spec.rb +0 -317
  125. data/spec/server/rack/extract_methods_spec.rb +0 -60
  126. data/spec/server/rack/path_spec.rb +0 -36
  127. data/spec/server/rack/path_validation_spec.rb +0 -22
  128. data/spec/server/server_spec.rb +0 -20
  129. data/spec/support/mongo_cleaner.rb +0 -32
  130. data/src/main/java/ItemSetTest.java +0 -76
  131. data/src/main/java/com/infochimps/util/CurrentClass.java +0 -26
  132. data/src/main/java/com/infochimps/util/DebugUtil.java +0 -38
  133. data/src/main/java/com/infochimps/util/HttpHelper.java +0 -181
  134. data/src/main/java/com/infochimps/vayacondios/ItemSets.java +0 -373
  135. data/src/main/java/com/infochimps/vayacondios/LinkToVCD.java +0 -18
  136. data/src/main/java/com/infochimps/vayacondios/MemoryVCDShim.java +0 -84
  137. data/src/main/java/com/infochimps/vayacondios/Organization.java +0 -62
  138. data/src/main/java/com/infochimps/vayacondios/PathBuilder.java +0 -13
  139. data/src/main/java/com/infochimps/vayacondios/StandardVCDLink.java +0 -218
  140. data/src/main/java/com/infochimps/vayacondios/VCDIntegrationTest.java +0 -108
  141. data/src/test/java/com/infochimps/vayacondios/TestVayacondiosInMemory.java +0 -78
  142. data/vayacondios-client.gemspec +0 -25
data/pom.xml CHANGED
@@ -4,17 +4,99 @@
4
4
  <groupId>com.infochimps</groupId>
5
5
  <artifactId>vayacondios</artifactId>
6
6
  <packaging>jar</packaging>
7
- <!-- ICSVERS --><version>1.7.0-SNAPSHOT</version>
8
- <name>java-common</name>
7
+ <version>2.0.0-LESLIE</version>
8
+ <name>Vayacondios</name>
9
9
  <url>http://maven.apache.org</url>
10
10
 
11
11
  <parent>
12
12
  <groupId>com.infochimps</groupId>
13
13
  <artifactId>parent-pom</artifactId>
14
- <!-- ICSVERS --><version>1.7.0-SNAPSHOT</version>
15
- <relativePath></relativePath>
14
+ <version>1.0.0-SNAPSHOT</version>
16
15
  </parent>
17
16
 
17
+ <reporting>
18
+ <plugins>
19
+ <plugin>
20
+ <groupId>org.apache.maven.plugins</groupId>
21
+ <artifactId>maven-javadoc-plugin</artifactId>
22
+ <version>2.9</version>
23
+ <configuration>
24
+ <show>public</show>
25
+ </configuration>
26
+ </plugin>
27
+ </plugins>
28
+ </reporting>
29
+
30
+ <build>
31
+ <plugins>
32
+ <plugin>
33
+ <artifactId>maven-failsafe-plugin</artifactId>
34
+ <version>2.6</version>
35
+ <executions>
36
+ <execution>
37
+ <goals>
38
+ <goal>integration-test</goal>
39
+ <goal>verify</goal>
40
+ </goals>
41
+ </execution>
42
+ </executions>
43
+ </plugin>
44
+ <plugin>
45
+ <groupId>org.apache.maven.plugins</groupId>
46
+ <artifactId>maven-surefire-plugin</artifactId>
47
+ <version>2.11</version>
48
+ <dependencies>
49
+ <dependency>
50
+ <groupId>org.apache.maven.surefire</groupId>
51
+ <artifactId>surefire-junit47</artifactId>
52
+ <version>2.12</version>
53
+ </dependency>
54
+ </dependencies>
55
+ <configuration>
56
+ <includes>
57
+ <include>**/*.class</include>
58
+ </includes>
59
+ <excludedGroups>com.infochimps.vayacondios.test.IntegrationTest</excludedGroups>
60
+ </configuration>
61
+ </plugin>
62
+
63
+ <!-- <plugin> -->
64
+ <!-- <groupId>org.apache.maven.plugins</groupId> -->
65
+ <!-- <artifactId>maven-shade-plugin</artifactId> -->
66
+ <!-- <version>2.0</version> -->
67
+ <!-- <executions> -->
68
+ <!-- <execution> -->
69
+ <!-- <phase>package</phase> -->
70
+ <!-- <goals> -->
71
+ <!-- <goal>shade</goal> -->
72
+ <!-- </goals> -->
73
+ <!-- <configuration> -->
74
+ <!-- <transformers> -->
75
+ <!-- <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> -->
76
+ <!-- <mainClass>com.infochimps.vayacondios.VCDIntegrationTest</mainClass> -->
77
+ <!-- </transformer> -->
78
+ <!-- </transformers> -->
79
+ <!-- </configuration> -->
80
+ <!-- </execution> -->
81
+ <!-- </executions> -->
82
+ <!-- </plugin> -->
83
+ <plugin>
84
+ <groupId>org.codehaus.mojo</groupId>
85
+ <artifactId>exec-maven-plugin</artifactId>
86
+ <version>1.2.1</version>
87
+ <configuration>
88
+ <executable>java</executable>
89
+ <arguments>
90
+ <argument>-cp</argument>
91
+ <classpath/>
92
+ <argument>-jar</argument>
93
+ <argument>target/${project.artifactId}-${project.version}.jar</argument>
94
+ </arguments>
95
+ </configuration>
96
+ </plugin>
97
+ </plugins>
98
+ </build>
99
+
18
100
  <repositories>
19
101
  <!-- Infochimps Repositories -->
20
102
  <repository>
@@ -44,5 +126,43 @@
44
126
  <artifactId>commons-codec</artifactId>
45
127
  <version>1.2</version>
46
128
  </dependency>
129
+ <dependency>
130
+ <groupId>org.slf4j</groupId>
131
+ <artifactId>slf4j-api</artifactId>
132
+ <version>1.7.2</version>
133
+ </dependency>
134
+ <dependency>
135
+ <groupId>org.slf4j</groupId>
136
+ <artifactId>slf4j-simple</artifactId>
137
+ <version>1.7.2</version>
138
+ </dependency>
139
+ <dependency>
140
+ <groupId>junit</groupId>
141
+ <artifactId>junit</artifactId>
142
+ <version>4.8.1</version>
143
+ <scope>test</scope>
144
+ </dependency>
145
+ <dependency>
146
+ <groupId>com.ning</groupId>
147
+ <artifactId>async-http-client</artifactId>
148
+ <version>1.7.16</version>
149
+ </dependency>
150
+ <dependency>
151
+ <groupId>org.apache.commons</groupId>
152
+ <artifactId>commons-lang3</artifactId>
153
+ <version>3.1</version>
154
+ </dependency>
155
+ <dependency>
156
+ <groupId>org.apache.httpcomponents</groupId>
157
+ <artifactId>httpclient</artifactId>
158
+ <version>4.2.5</version>
159
+ </dependency>
160
+ <dependency>
161
+ <groupId>org.mongodb</groupId>
162
+ <artifactId>mongo-java-driver</artifactId>
163
+ <version>2.11.1</version>
164
+ <scope>verify</scope>
165
+ </dependency>
166
+
47
167
  </dependencies>
48
168
  </project>
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vayacondios::Configuration do
4
+
5
+ def change_defaults new_defaults
6
+ subject.define_singleton_method(:defaults) do
7
+ new_defaults
8
+ end
9
+ end
10
+
11
+ context '#defaults' do
12
+ it 'defines defaults' do
13
+ subject.defaults.should eq(Hash.new)
14
+ end
15
+ end
16
+
17
+ context '#resolved_settings' do
18
+ it 'resolves settings automatically when accessed' do
19
+ subject.should_not be_resolved
20
+ subject.resolved_settings.should eq(Hash.new)
21
+ subject.should be_resolved
22
+ end
23
+ end
24
+
25
+ context '#overlay' do
26
+ before{ change_defaults(foo: 'bar', baz: 'qix') }
27
+
28
+ it 'allows a top-level override of settings' do
29
+ subject.overlay(foo: 'override')
30
+ subject.resolved_settings.should eq(foo: 'override', baz: 'qix')
31
+ end
32
+ end
33
+
34
+ context '#[]' do
35
+ before{ change_defaults(foo: 'bar') }
36
+
37
+ it 'allows access to the resolved_settings' do
38
+ subject[:foo].should eq('bar')
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vayacondios::Server::ApiOptions do
4
+
5
+ let(:api) do
6
+ api_options = described_class
7
+ Class.new{ include api_options }.new
8
+ end
9
+ let(:settings){ Hash.new }
10
+ let(:parser) { OptionParser.new }
11
+
12
+ it 'sets the default config file location' do
13
+ api.options_parser(parser, settings)
14
+ settings[:config].should eq(File.join(Vayacondios.library_dir, 'config/vcd-server.rb'))
15
+ end
16
+
17
+ it 'sets the default server port' do
18
+ api.options_parser(parser, settings)
19
+ settings[:port].should eq(3467)
20
+ end
21
+
22
+ it 'allows commandline overrides for database options' do
23
+ ARGV.replace %w[-d foo -h foo.com -D bar -o 1234 -n 10]
24
+ api.options_parser(parser, settings)
25
+ parser.parse!
26
+ settings[:database].should eq(driver: 'foo',
27
+ connections: 10,
28
+ host: 'foo.com',
29
+ name: 'bar',
30
+ port: 1234)
31
+ end
32
+ end
@@ -0,0 +1,279 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vayacondios::Server::Api do
4
+ include Goliath::TestHelper
5
+
6
+ TestResponse = Struct.new(:status, :body, :headers) do
7
+ def parsed_body
8
+ MultiJson.load body
9
+ end
10
+ end
11
+
12
+ def build_request(verb, path, options = {})
13
+ options[:path] = path
14
+ proc{ |&callback| send("#{verb}_request", options, &callback) }
15
+ end
16
+
17
+ let(:captured_assertions){ Array.new }
18
+
19
+ def perform(request, &blk)
20
+ response = nil
21
+ with_api(described_class) do |server|
22
+ yield server.api if block_given?
23
+ request.call do |client|
24
+ response = TestResponse.new(client.response_header.status.to_i, client.response, client.response_header)
25
+ end
26
+ captured_assertions.each{ |a| raise a if a.is_a?(Exception) }
27
+ end
28
+ response
29
+ end
30
+
31
+ def capture_assertions(&code)
32
+ code.call
33
+ rescue RSpec::Expectations::ExpectationNotMetError => e
34
+ captured_assertions << e
35
+ end
36
+
37
+ def stub_response(api, result = nil, &blk)
38
+ api.stub(:response) do |env|
39
+ capture_assertions do
40
+ blk.call(api, env)
41
+ end
42
+ result || success_response
43
+ end
44
+ end
45
+
46
+ def success_response
47
+ [200, {}, {}]
48
+ end
49
+
50
+ def stub_handler(api, result = {}, &blk)
51
+ handler = double(:handle, call: result)
52
+ handler_class = double(:handler_class, new: handler)
53
+ api.stub(:handler).and_return handler_class
54
+ if block_given?
55
+ handler.should_receive(:call) do |action, routes, document|
56
+ capture_assertions{ blk.call(action, routes, document) }
57
+ result
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'Rack', 'Heartbeat' do
63
+ subject(:response){ perform build_request(:get, '/status') }
64
+
65
+ it 'returns a heartbeat message' do
66
+ response.body.should eq('OK')
67
+ end
68
+ end
69
+
70
+ context 'Rack', 'ApiVersion' do
71
+ subject(:response){ perform build_request(:get, '/version') }
72
+
73
+ it 'returns the server api version' do
74
+ response.parsed_body.should eq(Vayacondios::GEM_VERSION)
75
+ end
76
+
77
+ it 'attaches a version header to every response' do
78
+ response = perform build_request(:get, '/v3/org/event/topic')
79
+ response.headers['X_VAYACONDIOS_VERSION'].should eq(Vayacondios::GEM_VERSION)
80
+ end
81
+ end
82
+
83
+ context 'Rack', 'ForceContentType' do
84
+ let(:request) { build_request(:post, '/v3/org/event/topic', body: '{"foo":"bar"}') }
85
+ let(:response){ perform request }
86
+
87
+ it 'accepts a JSON body with no header' do
88
+ perform(request) do |server|
89
+ stub_handler(server, {}) do |action, routes, document|
90
+ document.should eq('foo' => 'bar')
91
+ end
92
+ end
93
+ end
94
+
95
+ it 'attaches a JSON content header to every response' do
96
+ response.headers['CONTENT_TYPE'].should match('application/json')
97
+ end
98
+ end
99
+
100
+ context 'Rack', 'Formatters::JSON' do
101
+ subject(:response) do
102
+ perform build_request(:get, '/v3/org/event/topic') do |server|
103
+ stub_handler(server, { foo: 'bar' })
104
+ end
105
+ end
106
+
107
+ it 'serializes all response bodies as JSON' do
108
+ response.parsed_body.should eq('foo' => 'bar')
109
+ end
110
+ end
111
+
112
+ context 'Rack', 'Params' do
113
+ it 'provides parsed params to the response method' do
114
+ request = build_request(:post, '/v3/org/event/topic', body: '{"foo":"bar"}')
115
+ perform(request) do |server|
116
+ stub_response(server, success_response) do |api|
117
+ api.should respond_to(:document)
118
+ api.document.should eq('foo' => 'bar')
119
+ end
120
+ end
121
+ end
122
+
123
+ it 'handles non-Hash JSON values' do
124
+ request = build_request(:post, '/v3/org/event/topic', body: '["foo","bar"]')
125
+ perform(request) do |server|
126
+ stub_response(server, success_response) do |api|
127
+ api.document.should eq(%w[ foo bar ])
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ context 'Rack', 'Validation::RequestMethod' do
134
+ %w[ HEAD OPTIONS ].each do |method|
135
+ it "returns a validation error on #{method} requests" do
136
+ response = perform build_request(method.downcase.to_sym, '/v3/org/event/topic')
137
+ response.status.should eq(405)
138
+ end
139
+ end
140
+ end
141
+
142
+ context 'Rack', 'ControlMethods' do
143
+ {
144
+ post: :create,
145
+ get: :retrieve,
146
+ patch: :update,
147
+ patch: :update,
148
+ delete: :delete,
149
+ }.each_pair do |http_verb, handler_action|
150
+ it "maps #{http_verb.to_s.upcase} verbs to handler method #{handler_action}" do
151
+ perform build_request(http_verb, '/v3/org/event/topic') do |server|
152
+ stub_handler(server) do |action, routes, document|
153
+ action.should eq(handler_action)
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ context 'Rack', 'Validation::Routes' do
161
+ it 'returns a validation error when the route is not valid' do
162
+ response = perform build_request(:get, '/invalid/route/fool')
163
+ response.status.should eq(400)
164
+ response.parsed_body['error'].should match('/v3/<organization>/<type>/<topic>/<id>')
165
+ end
166
+
167
+ it 'parses the route pieces' do
168
+ perform build_request(:get, '/v3/twitter/event/hashtag/emoji') do |server|
169
+ stub_response(server) do |api|
170
+ api.should respond_to(:routes)
171
+ api.routes.should eq(organization: 'twitter',
172
+ type: 'event',
173
+ topic: 'hashtag',
174
+ id: 'emoji')
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ context 'Rack', 'Validation::RouteHandler' do
181
+ {
182
+ event: Vayacondios::Server::EventHandler,
183
+ events: Vayacondios::Server::EventsHandler,
184
+ stash: Vayacondios::Server::StashHandler,
185
+ stashes: Vayacondios::Server::StashesHandler,
186
+ stream: Vayacondios::Server::StreamHandler,
187
+ }.each_pair do |type, handler|
188
+ it "maps type #{type} to handler #{handler}" do
189
+ request = build_request(:get, "/v3/infochimps/#{type}/topic")
190
+ perform(request) do |server|
191
+ stub_response(server, success_response) do |api|
192
+ api.handler.should be(handler)
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ it 'returns a validation error when a handler cannot be found' do
199
+ response = perform build_request(:get, '/v3/infochimps/invalid/topic')
200
+ response.status.should eq(400)
201
+ response.parsed_body['error'].should match('No handler found')
202
+ end
203
+ end
204
+
205
+ context 'Rack', 'Validation::RequiredRoutes' do
206
+ it 'returns a validation error when a stash does not have a topic' do
207
+ response = perform build_request(:get, '/v3/infochimps/stash')
208
+ response.status.should eq(400)
209
+ response.parsed_body['error'].should match('A topic route is required')
210
+ end
211
+
212
+ it 'returns a validation error when an event does not have a topic' do
213
+ response = perform build_request(:get, '/v3/infochimps/event')
214
+ response.status.should eq(400)
215
+ response.parsed_body['error'].should match('A topic route is required')
216
+ end
217
+
218
+ it 'returns a validation error when events do not have a topic' do
219
+ response = perform build_request(:get, '/v3/infochimps/events')
220
+ response.status.should eq(400)
221
+ response.parsed_body['error'].should match('A topic route is required')
222
+ end
223
+
224
+ it 'returns a validation error when stream do not have a topic' do
225
+ response = perform build_request(:get, '/v3/infochimps/stream')
226
+ response.status.should eq(400)
227
+ response.parsed_body['error'].should match('A topic route is required')
228
+ end
229
+ end
230
+
231
+ context 'Rack', '#response' do
232
+ let(:request){ build_request(:get, '/v3/infochimps/event/topic') }
233
+
234
+ it 'returns a validation error when a handler raises one' do
235
+ response = perform(request) do |server|
236
+ stub_handler(server) do |action, routes, document|
237
+ raise Goliath::Validation::NotFoundError.new("Dude, where's my car?")
238
+ end
239
+ end
240
+ response.status.should eq(404)
241
+ response.parsed_body['error'].should eq("Dude, where's my car?")
242
+ end
243
+
244
+ it 'returns a document error when a handler raises one' do
245
+ response = perform(request) do |server|
246
+ stub_handler(server) do |action, routes, document|
247
+ raise Vayacondios::Server::Document::Error.new('Invalid')
248
+ end
249
+ end
250
+ response.status.should eq(400)
251
+ response.parsed_body['error'].should eq('Invalid')
252
+ end
253
+
254
+ it 'returns a server error when a handler raises one' do
255
+ response = perform(request) do |server|
256
+ stub_handler(server) do |action, routes, document|
257
+ raise ZeroDivisionError.new('infinity')
258
+ end
259
+ end
260
+ response.status.should eq(500)
261
+ response.parsed_body['error'].should match('ZeroDivisionError')
262
+ end
263
+
264
+ it 'returns a successful response on success' do
265
+ response = perform(request) do |server|
266
+ stub_handler(server, { foo: 'bar' })
267
+ end
268
+ response.status.should eq(200)
269
+ response.parsed_body.should eq('foo' => 'bar')
270
+ end
271
+
272
+ it 'returns a streaming response when requested', focus: true do
273
+ request = build_request(:get, '/v3/infochimps/stream/topic', connection_options: { inactivity_timeout: 0.5 })
274
+ response = perform(request)
275
+ response.status.should eq(200)
276
+ response.body.should eq('')
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vayacondios::Server::Configuration do
4
+ its(:defaults) do
5
+ should eq(development: {
6
+ driver: 'mongo',
7
+ host: 'localhost',
8
+ port: 27017,
9
+ name: 'vayacondios_development',
10
+ connections: 20,
11
+ })
12
+ end
13
+
14
+ it 'defines a db config constant' do
15
+ Vayacondios::Server::DbConfig.should be_a(described_class)
16
+ end
17
+
18
+ context '#env' do
19
+ it 'allows hash access scoped by environment' do
20
+ subject.env(:development).should eq(driver: 'mongo',
21
+ host: 'localhost',
22
+ port: 27017,
23
+ name: 'vayacondios_development',
24
+ connections: 20)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vayacondios::Server::MongoDriver, if: WITH_MONGO do
4
+ include LogHelper
5
+
6
+ let!(:settings){ Vayacondios::Server::DbConfig.env :test }
7
+
8
+ subject{ described_class.connect settings.merge(log: log) }
9
+
10
+ def mongo
11
+ Mongo::MongoClient.new(settings[:host], settings[:port])
12
+ end
13
+
14
+ def db
15
+ mongo.db settings[:name]
16
+ end
17
+
18
+ def collection name
19
+ db.collection name
20
+ end
21
+
22
+ def using(location, &blk)
23
+ EM.synchrony do
24
+ subject.set_location location
25
+ blk.call(subject)
26
+ EM::Synchrony.sleep(0.1) # ensure the operation completes
27
+ EM.stop
28
+ end
29
+ end
30
+
31
+ def clean name
32
+ collection(name).drop
33
+ end
34
+
35
+ context '#to_dotted_hash' do
36
+ let(:nested){ { foo: { bar: { baz: 'qix' } }, hey: { you: 'there' } } }
37
+ it 'flattens a nested hash into dotted keys' do
38
+ EM.synchrony do
39
+ subject.to_dotted_hash(nested).should eq('foo.bar.baz' => 'qix', 'hey.you' => 'there')
40
+ EM.stop
41
+ end
42
+ end
43
+ end
44
+
45
+ context '#insert' do
46
+ after do
47
+ clean 'organization.foo.events'
48
+ end
49
+
50
+ it 'returns the id' do
51
+ result = nil
52
+ using('organization.foo.events') do |driver|
53
+ result = driver.insert(foo: 'bar')
54
+ end
55
+ collection('organization.foo.events').find(_id: BSON::ObjectId(result[:_id])).to_a.size.should eq(1)
56
+ end
57
+ end
58
+
59
+ context '#search' do
60
+ after{ clean 'organization.stash' }
61
+
62
+ it 'returns an array of results' do
63
+ collection('organization.stash').insert(_id: 'topic', foo: 'bar')
64
+ result = nil
65
+ using('organization.stash') do |driver|
66
+ result = driver.search({}, { foo: 'bar' }, {})
67
+ end
68
+ result.should eq([{ _id: 'topic', foo: 'bar' }])
69
+ end
70
+ end
71
+
72
+ context '#retrieve' do
73
+ after{ clean 'organization.stash' }
74
+
75
+ it 'returns the record if found' do
76
+ collection('organization.stash').insert(_id: 'topic', foo: 'bar')
77
+ result = nil
78
+ using('organization.stash') do |driver|
79
+ result = driver.retrieve(_id: 'topic')
80
+ end
81
+ result.should eq(_id: 'topic', foo: 'bar')
82
+ end
83
+
84
+ it 'returns nil if the record is not found' do
85
+ collection('organization.stash').insert(_id: 'topic', foo: 'bar')
86
+ result = nil
87
+ using('organization.stash') do |driver|
88
+ result = driver.retrieve(_id: 'invalid')
89
+ end
90
+ result.should be_nil
91
+ end
92
+ end
93
+
94
+ context '#remove' do
95
+ after{ clean 'organization.stash' }
96
+
97
+ it 'returns nil after completion' do
98
+ collection('organization.stash').insert(_id: 'topic', foo: 'bar')
99
+ result = nil
100
+ using('organization.stash') do |driver|
101
+ result = driver.remove({}, foo: 'bar')
102
+ end
103
+ result.should be_nil
104
+ collection('organization.stash').find(_id: 'topic').to_a.should be_empty
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vayacondios::Server::EventHandler, behaves_like: 'handler' do
4
+
5
+ let(:params) { { organization: 'organization', topic: 'topic' } }
6
+ let(:document) { { foo: 'bar', time: '2013-01-01T10:23:10.432Z' } }
7
+ let(:model_class){ Vayacondios::Server::Event }
8
+
9
+ context '#create' do
10
+ it 'returns the created event' do
11
+ model_class.should_receive(:create).with(params, document).and_call_original
12
+ driver.should_receive(:insert).and_return(_id: 'abc123')
13
+ handler.create(params, document).should eq(id: 'abc123',
14
+ foo: 'bar',
15
+ time: '2013-01-01T10:23:10.432Z')
16
+ end
17
+ end
18
+
19
+ context '#retrieve', 'when an event is found' do
20
+ let(:params){ { organization: 'organization', topic: 'topic', id: 'abc123' } }
21
+
22
+ it 'returns the selected event' do
23
+ model_class.should_receive(:find).with(params).and_call_original
24
+ driver.should_receive(:retrieve).and_return(_id: 'abc123', _t: '2013-01-01T10:23:10.432Z', _d: { foo: 'bar' })
25
+ handler.retrieve(params, {}).should eq(id: 'abc123',
26
+ foo: 'bar',
27
+ time: '2013-01-01T10:23:10.432Z')
28
+ end
29
+ end
30
+
31
+ context '#retrieve', 'when an event is not found', focus: true do
32
+ let(:params){ { organization: 'organization', topic: 'topic', id: 'abc123' } }
33
+
34
+ it 'raises a validation error' do
35
+ model_class.should_receive(:find).with(params).and_call_original
36
+ driver.should_receive(:retrieve).and_return(nil)
37
+ expect{ handler.retrieve(params, {}) }.to raise_error(validation_error, /not found/)
38
+ end
39
+ end
40
+
41
+ context '#update' do
42
+ it 'raises a validation error' do
43
+ expect{ handler.update(params, document) }.to raise_error(validation_error, /update/)
44
+ end
45
+ end
46
+
47
+ context '#delete', 'when params have no id' do
48
+ it 'raises a validation error' do
49
+ expect{ handler.delete(params, {}) }.to raise_error(validation_error, /id/i)
50
+ end
51
+ end
52
+
53
+ context '#delete', 'when successful' do
54
+ let(:params){ { organization: 'organization', topic: 'topic', id: 'abc123' } }
55
+
56
+ it 'returns success response' do
57
+ model_class.should_receive(:destroy).with(params, {}).and_call_original
58
+ driver.should_receive(:remove).and_return(true)
59
+ handler.delete(params, {}).should eq(success_response)
60
+ end
61
+ end
62
+ end