vayacondios-server 0.2.11 → 0.3.0

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