turd 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +13 -0
- data/lib/turd.rb +36 -0
- data/lib/turd/assert.rb +69 -0
- data/lib/turd/http.rb +16 -0
- data/lib/turd/tcp.rb +24 -0
- data/lib/turd/version.rb +3 -0
- metadata +67 -0
data/README.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
### turd
|
2
|
+
|
3
|
+
Turd is a little wrapper around typhoeus which is a wrapper around curb which is a wrapper around libcurl which is a wrapper around tcp which is a wrapper around electrons and shit. You can use turd to test http requests and responses. We use it at GitHub to validate responses from various services and alert us if they do not conform to the expected responses. http integration tests if you will. It can be also used for basic telnet-like plain text request validations. Lastly, it also produces some basic diagnostic data like various timings from libcurl.
|
4
|
+
|
5
|
+
It is called "turd" because my cat pooped on the floor while I was writing it.
|
6
|
+
|
7
|
+
#### Usage
|
8
|
+
|
9
|
+
Check out the examples directory for usage details. The basic idea is you define a request and response. turd performs the request and compares the actual response with the expected response. You can use any data that a typhoeus response object supplies to validate responses (header and body substrings, status codes, etc).
|
10
|
+
|
11
|
+
#### License
|
12
|
+
|
13
|
+
turd is open source software available under the MIT License
|
data/lib/turd.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'typhoeus'
|
4
|
+
require 'socket'
|
5
|
+
require 'timeout'
|
6
|
+
|
7
|
+
__DIR__ = File.dirname(__FILE__)
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift __DIR__ unless
|
10
|
+
$LOAD_PATH.include?(__DIR__) ||
|
11
|
+
$LOAD_PATH.include?(File.expand_path(__DIR__))
|
12
|
+
|
13
|
+
require 'turd/assert'
|
14
|
+
require 'turd/http'
|
15
|
+
require 'turd/tcp'
|
16
|
+
require 'turd/version'
|
17
|
+
|
18
|
+
module Turd
|
19
|
+
class << self
|
20
|
+
|
21
|
+
def run(request_definition, response_definition)
|
22
|
+
|
23
|
+
case request_definition[:type]
|
24
|
+
when "http"
|
25
|
+
response = Turd::Http.request(request_definition)
|
26
|
+
when "tcp"
|
27
|
+
response = Turd::Tcp.connect(request_definition)
|
28
|
+
else
|
29
|
+
raise "No request type defined!"
|
30
|
+
end
|
31
|
+
|
32
|
+
Turd::Assert.assert(request_definition, response, response_definition)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/turd/assert.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Turd
|
2
|
+
class Assert
|
3
|
+
|
4
|
+
def self.assert(request_definition, response, response_definition)
|
5
|
+
|
6
|
+
case request_definition[:type]
|
7
|
+
|
8
|
+
when "tcp"
|
9
|
+
response_definition.each do |option, value|
|
10
|
+
if option == :response
|
11
|
+
value.each do |v|
|
12
|
+
if response[:response].include?(v)
|
13
|
+
return response
|
14
|
+
else
|
15
|
+
raise AssertionFailure.new(response), "#{option} substring failure. expected #{v}, got #{response}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
elsif option == :total_time
|
19
|
+
if response[:total_time] > value
|
20
|
+
raise AssertionFailure.new(response), "#{option} timing value was greater than allowed. expected #{value}, got #{response[:total_time]}"
|
21
|
+
else
|
22
|
+
return response
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
when "http"
|
28
|
+
response_definition.each do |option, value|
|
29
|
+
|
30
|
+
if option == :response_headers || option == :response_body
|
31
|
+
value.each do |v|
|
32
|
+
if response.options[option].include?(v)
|
33
|
+
return return_http_response(response)
|
34
|
+
else
|
35
|
+
raise AssertionFailure.new(return_http_response(response)), "#{option} substring failure. expected #{v}, got #{response.options[option]}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
elsif option.to_s.include?("_time")
|
39
|
+
if response.options[option] > value
|
40
|
+
raise AssertionFailure.new(return_http_response(response)), "#{option} timing value was greater than allowed. expected #{value}, got #{response.options[option]}"
|
41
|
+
else
|
42
|
+
return return_http_response(response)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
if response.options[option] == value
|
46
|
+
return return_http_response(response)
|
47
|
+
else
|
48
|
+
raise AssertionFailure.new(return_http_response(response)), "#{option} did not match response definition. expected #{value}, got #{response.options[option]}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.return_http_response(response)
|
57
|
+
response.options.delete(:debug_info)
|
58
|
+
response.options
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class AssertionFailure < RuntimeError
|
63
|
+
attr :response
|
64
|
+
|
65
|
+
def initialize(response)
|
66
|
+
@response = response
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/turd/http.rb
ADDED
data/lib/turd/tcp.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Turd
|
2
|
+
class Tcp
|
3
|
+
|
4
|
+
def self.connect(request_definition)
|
5
|
+
|
6
|
+
response = String.new
|
7
|
+
before = Time.now.to_f
|
8
|
+
|
9
|
+
begin
|
10
|
+
TCPSocket.open(request_definition[:options][:host], request_definition[:options][:port]) do |socket|
|
11
|
+
response = socket.gets
|
12
|
+
end
|
13
|
+
rescue Errno::ETIMEDOUT
|
14
|
+
# timeout
|
15
|
+
end
|
16
|
+
|
17
|
+
after = Time.now.to_f
|
18
|
+
|
19
|
+
{:response => response, :total_time => after - before}
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/lib/turd/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: turd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- joe williams
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: typhoeus
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description:
|
31
|
+
email: joe@joetify.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files:
|
35
|
+
- README.md
|
36
|
+
files:
|
37
|
+
- lib/turd/assert.rb
|
38
|
+
- lib/turd/http.rb
|
39
|
+
- lib/turd/tcp.rb
|
40
|
+
- lib/turd/version.rb
|
41
|
+
- lib/turd.rb
|
42
|
+
- README.md
|
43
|
+
homepage: http://github.com/joewilliams/turd
|
44
|
+
licenses: []
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.8.23
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: a http and tcp testing lib
|
67
|
+
test_files: []
|