Skip to content
Browse files

Merge pull request #1 from gorsuch/initial-specs

Initial specs
  • Loading branch information...
2 parents 9a189c2 + 656444f commit da24bff9a6a78666c08246dd3481706f00e15731 @obfuscurity committed Aug 28, 2012
View
2 .rspec
@@ -0,0 +1,2 @@
+--color
+--format progress
View
5 Gemfile
@@ -5,3 +5,8 @@ gem 'thin'
gem 'json'
gem 'yajl-ruby'
gem 'newrelic_rpm'
+
+group :test do
+ gem 'rspec'
+ gem 'rack-test'
+end
View
13 Gemfile.lock
@@ -2,12 +2,23 @@ GEM
remote: http://rubygems.org/
specs:
daemons (1.1.8)
+ diff-lcs (1.1.3)
eventmachine (0.12.10)
json (1.6.1)
newrelic_rpm (3.3.4.1)
rack (1.4.1)
rack-protection (1.2.0)
rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rspec (2.11.0)
+ rspec-core (~> 2.11.0)
+ rspec-expectations (~> 2.11.0)
+ rspec-mocks (~> 2.11.0)
+ rspec-core (2.11.1)
+ rspec-expectations (2.11.2)
+ diff-lcs (~> 1.1.3)
+ rspec-mocks (2.11.2)
sinatra (1.3.2)
rack (~> 1.3, >= 1.3.6)
rack-protection (~> 1.2)
@@ -25,6 +36,8 @@ PLATFORMS
DEPENDENCIES
json
newrelic_rpm
+ rack-test
+ rspec
sinatra
thin
yajl-ruby
View
4 lib/backstop.rb
@@ -0,0 +1,4 @@
+require 'socket'
+require 'uri'
+
+require 'backstop/publisher'
View
14 lib/backstop/publisher.rb
@@ -0,0 +1,14 @@
+module Backstop
+ class Publisher
+ attr_reader :connections
+
+ def initialize(urls)
+ @connections = []
+ @connections = urls.map { |u| URI.parse(u) }.map { |u| TCPSocket.new(u.host, u.port) }
+ end
+
+ def publish(name, value, time=Time.now.to_i)
+ connections.sample.puts("#{name} #{value} #{time}")
+ end
+ end
+end
View
33 lib/backstop/web.rb
@@ -7,28 +7,15 @@
module Backstop
class Application < Sinatra::Base
-
configure do
enable :logging
require 'newrelic_rpm'
- @@sockets = []
+ @@publisher = nil
end
helpers do
- def sockets
- if !@@sockets.empty?
- return @@sockets
- else
- @@sockets = []
- Config.carbon_urls.each do |c|
- if (c =~ /^carbon:\/\//)
- c.gsub!(/carbon:\/\//, "")
- host, port = c.split(":")
- s = TCPSocket.new host, port
- @@sockets.push s
- end
- end
- end
+ def publisher
+ @@publisher ||= Backstop::Publisher.new(Config.carbon_urls)
end
end
@@ -47,9 +34,8 @@ def sockets
results.each do |r|
r["source"] = "collectd"
halt 400, "missing fields" unless (r[:cloud] && r[:slot] && r[:id] && r[:metric] && r[:value] && r[:measure_time])
- s = sockets.sample
r[:cloud].gsub!(/\./, "-")
- s.puts "mitt.#{r[:cloud]}.#{r[:slot]}.#{r[:id]}.#{r[:metric]} #{r[:value]} #{r[:measure_time]}" if s
+ publisher.publish("mitt.#{r[:cloud]}.#{r[:slot]}.#{r[:id]}.#{r[:metric]}", r[:value], r[:measure_time])
end
end
"ok"
@@ -68,8 +54,7 @@ def sockets
repo = data['repository']['name']
author = commit['author']['email'].gsub(/[\.@]/, "-")
measure_time = DateTime.parse(commit["timestamp"]).strftime("%s")
- s = sockets.sample
- s.puts "#{data['source']}.#{repo}.#{data['ref']}.#{author}.#{commit['id']} 1 #{measure_time}"
+ publisher.publish("#{data['source']}.#{repo}.#{data['ref']}.#{author}.#{commit['id']}", 1, measure_time)
end
"ok"
end
@@ -85,21 +70,17 @@ def sockets
data.each do |item|
item["source"] = params[:name]
halt 400, "missing fields" unless (item['metric'] && item['value'] && item['measure_time'])
- s = sockets.sample
- s.puts "#{item['source']}.#{item['metric']} #{item['value']} #{item['measure_time']}"
+ publisher.publish("#{item['source']}.#{item['metric']}", item['value'], item['measure_time'])
end
else
data["source"] = params[:name]
halt 400, "missing fields" unless (data['metric'] && data['value'] && data['measure_time'])
- s = sockets.sample
- s.puts "#{data['source']}.#{data['metric']} #{data['value']} #{data['measure_time']}"
+ publisher.publish("#{data['source']}.#{data['metric']}", data['value'], data['measure_time'])
end
"ok"
else
halt 404, "unknown prefix"
end
end
-
end
end
-
View
13 spec/backstop/bad_collectd_data.json
@@ -0,0 +1,13 @@
+[
+ {
+ "values": [1901474177],
+ "dstypes": ["counter"],
+ "dsnames": ["value"],
+ "interval": 10,
+ "host": "leeloo.octo.it",
+ "plugin": "cpu",
+ "plugin_instance": "0",
+ "type": "cpu",
+ "type_instance": "idle"
+ }
+]
View
28 spec/backstop/bad_github_data.json
@@ -0,0 +1,28 @@
+{
+ "before": "5aef35982fb2d34e9d9d4502f6ede1072793222d",
+ "commits": [
+ {
+ "id": "41a212ee83ca127e3c8cf465891ab7216a705f59",
+ "url": "http://github.com/defunkt/github/commit/41a212ee83ca127e3c8cf465891ab7216a705f59",
+ "author": {
+ "email": "chris@ozmm.org",
+ "name": "Chris Wanstrath"
+ },
+ "message": "okay i give in",
+ "timestamp": "2008-02-15T14:57:17-08:00",
+ "added": ["filepath.rb"]
+ },
+ {
+ "id": "de8251ff97ee194a289832576287d6f8ad74e3d0",
+ "url": "http://github.com/defunkt/github/commit/de8251ff97ee194a289832576287d6f8ad74e3d0",
+ "author": {
+ "email": "chris@ozmm.org",
+ "name": "Chris Wanstrath"
+ },
+ "message": "update pricing a tad",
+ "timestamp": "2008-02-15T14:36:34-08:00"
+ }
+ ],
+ "after": "de8251ff97ee194a289832576287d6f8ad74e3d0",
+ "ref": "refs/heads/master"
+}
View
14 spec/backstop/good_collectd_data.json
@@ -0,0 +1,14 @@
+[
+ {
+ "values": [1901474177],
+ "dstypes": ["counter"],
+ "dsnames": ["value"],
+ "time": 1280959128,
+ "interval": 10,
+ "host": "leeloo.octo.it",
+ "plugin": "cpu",
+ "plugin_instance": "0",
+ "type": "cpu",
+ "type_instance": "idle"
+ }
+]
View
40 spec/backstop/good_github_data.json
@@ -0,0 +1,40 @@
+{
+ "before": "5aef35982fb2d34e9d9d4502f6ede1072793222d",
+ "repository": {
+ "url": "http://github.com/defunkt/github",
+ "name": "github",
+ "description": "You're lookin' at it.",
+ "watchers": 5,
+ "forks": 2,
+ "private": 1,
+ "owner": {
+ "email": "chris@ozmm.org",
+ "name": "defunkt"
+ }
+ },
+ "commits": [
+ {
+ "id": "41a212ee83ca127e3c8cf465891ab7216a705f59",
+ "url": "http://github.com/defunkt/github/commit/41a212ee83ca127e3c8cf465891ab7216a705f59",
+ "author": {
+ "email": "chris@ozmm.org",
+ "name": "Chris Wanstrath"
+ },
+ "message": "okay i give in",
+ "timestamp": "2008-02-15T14:57:17-08:00",
+ "added": ["filepath.rb"]
+ },
+ {
+ "id": "de8251ff97ee194a289832576287d6f8ad74e3d0",
+ "url": "http://github.com/defunkt/github/commit/de8251ff97ee194a289832576287d6f8ad74e3d0",
+ "author": {
+ "email": "chris@ozmm.org",
+ "name": "Chris Wanstrath"
+ },
+ "message": "update pricing a tad",
+ "timestamp": "2008-02-15T14:36:34-08:00"
+ }
+ ],
+ "after": "de8251ff97ee194a289832576287d6f8ad74e3d0",
+ "ref": "refs/heads/master"
+}
View
32 spec/backstop/publisher_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe Backstop::Publisher do
+ it 'should initialize with an array of urls' do
+ urls = ['tcp://10.0.0.1:5000', 'tcp://10.0.0.1:5001']
+ TCPSocket.should_receive(:new).with('10.0.0.1', 5000)
+ TCPSocket.should_receive(:new).with('10.0.0.1', 5001)
+ b = Backstop::Publisher.new(urls)
+ b.connections.count.should eq 2
+ end
+
+ it 'should publish data' do
+ urls = ['tcp://10.0.0.1:5000']
+ socket_double = double('TCPSocket')
+ TCPSocket.should_receive(:new).with('10.0.0.1', 5000) { socket_double }
+ b = Backstop::Publisher.new(urls)
+
+ socket_double.should_receive(:puts).with("foo 1 1")
+ b.publish('foo', 1, 1)
+ end
+
+ it 'should include a timestamp if you do not provide one' do
+ urls = ['tcp://10.0.0.1:5000']
+ socket_double = double('TCPSocket')
+ TCPSocket.should_receive(:new).with('10.0.0.1', 5000) { socket_double }
+ b = Backstop::Publisher.new(urls)
+
+ Time.should_receive(:now) { 12345 }
+ socket_double.should_receive(:puts).with("foo 1 12345")
+ b.publish('foo', 1)
+ end
+end
View
101 spec/backstop/web_spec.rb
@@ -0,0 +1,101 @@
+require 'spec_helper'
+
+require 'backstop/web'
+require 'rack/test'
+
+describe Backstop::Application do
+ include Rack::Test::Methods
+
+ def app
+ Backstop::Application
+ end
+
+ before(:each) do
+ app.class_variable_set :@@publisher, nil
+ end
+
+ context 'GET /health' do
+ it 'should handle GET /health' do
+ get '/health'
+ last_response.should be_ok
+ end
+ end
+
+ context 'POST /publish/:name' do
+ it 'should require JSON' do
+ post '/publish/foo', 'foo'
+ last_response.should_not be_ok
+ last_response.status.should eq(400)
+ end
+
+ it 'should handle a single metric' do
+ p = double('publisher')
+ Backstop::Publisher.should_receive(:new) { p }
+ p.should_receive(:publish).with('test.bar', 12345, 1)
+ post '/publish/test', { :metric => 'bar', :value => 12345, :measure_time => 1 }.to_json
+ last_response.should be_ok
+ end
+
+ it 'should handle an array of metrics' do
+ p = double('publisher')
+ Backstop::Publisher.should_receive(:new) { p }
+ p.should_receive(:publish).with('test.bar', 12345, 1)
+ p.should_receive(:publish).with('test.bar', 12344, 2)
+ post '/publish/test', [{ :metric => 'bar', :value => 12345, :measure_time => 1 }, { :metric => 'bar', :value => 12344, :measure_time => 2} ].to_json
+ last_response.should be_ok
+ end
+ end
+
+ context 'POST /collectd' do
+ let(:good_collectd_data) { File.open(File.dirname(__FILE__) + '/good_collectd_data.json').read }
+ let(:bad_collectd_data) { File.open(File.dirname(__FILE__) + '/bad_collectd_data.json').read }
+
+ it 'should require JSON' do
+ post '/collectd', 'foo'
+ last_response.should_not be_ok
+ last_response.status.should eq(400)
+ end
+
+ it 'should handle a collectd metric' do
+ p = double('publisher')
+ Backstop::Publisher.should_receive(:new) { p }
+ p.should_receive(:publish).with('mitt.leeloo.octo.it.cpu.0.idle', 1901474177, 1280959128)
+ post '/collectd', good_collectd_data
+ last_response.body.should eq('ok')
+ last_response.status.should eq(200)
+ end
+
+ it 'should complain if missing fields' do
+ post '/collectd', bad_collectd_data
+ last_response.status.should eq(400)
+ last_response.body.should eq('missing fields')
+ end
+ end
+
+ context 'POST /github' do
+ let(:good_github_data) { File.open(File.dirname(__FILE__) + '/good_github_data.json').read }
+ let(:bad_github_data) { File.open(File.dirname(__FILE__) + '/bad_github_data.json').read }
+
+ it 'should require JSON' do
+ post '/github', { :payload => 'foo' }
+ last_response.should_not be_ok
+ last_response.status.should eq(400)
+ end
+
+ it 'should take a github push' do
+ p = double('publisher')
+ Backstop::Publisher.should_receive(:new) { p }
+ p.should_receive(:publish).with('github.github.refs.heads.master.chris-ozmm-org.de8251ff97ee194a289832576287d6f8ad74e3d0', 1, '1203114994')
+ p.should_receive(:publish).with('github.github.refs.heads.master.chris-ozmm-org.41a212ee83ca127e3c8cf465891ab7216a705f59', 1, '1203116237')
+ post '/github', { :payload => good_github_data }
+ last_response.should be_ok
+ end
+
+ it 'should complain if missing fields' do
+ post '/github', { :payload => bad_github_data }
+ last_response.should_not be_ok
+ end
+ end
+end
+
+
View
11 spec/spec_helper.rb
@@ -0,0 +1,11 @@
+require 'backstop'
+
+ENV['CARBON_URLS'] = 'carbon://1.1.1.1:5000'
+ENV['PREFIXES'] = 'test'
+
+RSpec.configure do |config|
+ config.treat_symbols_as_metadata_keys_with_true_values = true
+ config.run_all_when_everything_filtered = true
+ config.filter_run :focus
+ config.order = 'random'
+end

0 comments on commit da24bff

Please sign in to comment.
Something went wrong with that request. Please try again.