cudan 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +3 -0
- data/README +1 -0
- data/bin/cudan +9 -0
- data/lib/cudan/base_cudan.rb +79 -0
- data/lib/cudan/logger.rb +11 -0
- data/lib/cudan/main.rb +40 -0
- data/lib/cudan/regexp_cudan.rb +19 -0
- data/lib/cudan/xpath_cudan.rb +20 -0
- data/lib/cudan.rb +8 -0
- data/test/cudanspec.rb +59 -0
- data/test/wwutil.rb +69 -0
- metadata +76 -0
data/CHANGES
ADDED
data/README
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
simple functional test tool.
|
data/bin/cudan
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
module Cudan
|
3
|
+
GET="GET"
|
4
|
+
POST="POST"
|
5
|
+
PUT="PUT"
|
6
|
+
DELETE="DELETE"
|
7
|
+
class BaseCudan
|
8
|
+
def initialize
|
9
|
+
@headers = {}
|
10
|
+
@showbody = false
|
11
|
+
end
|
12
|
+
attr_accessor :showbody
|
13
|
+
def set_header key, value
|
14
|
+
@headers[key] = value
|
15
|
+
end
|
16
|
+
def fetch url, method=GET, body=nil
|
17
|
+
host, port, path = Util::parse_url(url)
|
18
|
+
@post_string = body
|
19
|
+
if method == GET
|
20
|
+
req = Net::HTTP::Get::new(path, @headers)
|
21
|
+
elsif method == POST
|
22
|
+
req = Net::HTTP::Post::new(path, @headers)
|
23
|
+
end
|
24
|
+
response = nil
|
25
|
+
Net::HTTP.start(host, port) do |http|
|
26
|
+
@starttime = Time::now
|
27
|
+
response = http.request(req, @post_string)
|
28
|
+
@response_time = Time::now - @starttime
|
29
|
+
end
|
30
|
+
if response
|
31
|
+
@response = response.body.to_s
|
32
|
+
else
|
33
|
+
@response = ''
|
34
|
+
end
|
35
|
+
if @showbody
|
36
|
+
Logger.log(@response, 2)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
def execute query, expect, url, method=GET, body=nil
|
40
|
+
fetch(url, method, body)
|
41
|
+
@query_result = do_query(query)
|
42
|
+
r = do_expect(expect)
|
43
|
+
unless r
|
44
|
+
do_message
|
45
|
+
exit 1
|
46
|
+
else
|
47
|
+
end
|
48
|
+
end
|
49
|
+
def do_message
|
50
|
+
Logger.log 'failure:'
|
51
|
+
Logger.log @query_result.gsub(/^(.*)$/){|r| "\t" + r}
|
52
|
+
end
|
53
|
+
def do_query query
|
54
|
+
@response.include? query ? query : ''
|
55
|
+
end
|
56
|
+
def do_expect expect
|
57
|
+
@query_result.include? expect
|
58
|
+
end
|
59
|
+
end
|
60
|
+
class Util
|
61
|
+
def self::parse_url url
|
62
|
+
hostpath = url.slice(url.index('://')+3, url.size)
|
63
|
+
if pathstart = hostpath.index('/')
|
64
|
+
host = hostpath.slice(0, pathstart)
|
65
|
+
path = hostpath.slice(pathstart, hostpath.size)
|
66
|
+
else
|
67
|
+
host = hostpath
|
68
|
+
path = '/'
|
69
|
+
end
|
70
|
+
if portstart = host.index(':')
|
71
|
+
host, port = host.split(':')
|
72
|
+
port = port.to_i
|
73
|
+
else
|
74
|
+
port = 80
|
75
|
+
end
|
76
|
+
[host, port, path]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/cudan/logger.rb
ADDED
data/lib/cudan/main.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class Cudan::Main
|
2
|
+
require 'optparse'
|
3
|
+
def main
|
4
|
+
opts = OptionParser.new("Usage: #{File::basename($0)} [OPTIONS] URL")
|
5
|
+
opts.on("-v", "--version", "show version") do
|
6
|
+
puts "%s %s" %[File.basename($0), Cudan::VERSION]
|
7
|
+
puts "ruby %s" % RUBY_VERSION
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
opts.on('-q QUERY', '--query QUERY', 'query') do |q|
|
11
|
+
@query = q
|
12
|
+
end
|
13
|
+
opts.on('-e EXPECT_STRING', '--expects EXPECT_STRING', 'expect string') do |ex|
|
14
|
+
@expects = ex
|
15
|
+
end
|
16
|
+
opts.on('-u USER_AGENT', '--user-agent USER_AGENT', 'set user agent') do |ua|
|
17
|
+
@ua = ua
|
18
|
+
end
|
19
|
+
opts.on('--show-body', 'show body') do |b|
|
20
|
+
@showbody = b
|
21
|
+
end
|
22
|
+
opts.version = Cudan::VERSION
|
23
|
+
opts.parse!(ARGV)
|
24
|
+
@url = ARGV[0]
|
25
|
+
unless @url
|
26
|
+
puts opts.to_s
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
if /\/(.*)\// =~ @query
|
30
|
+
klass = Cudan::RegexpCudan
|
31
|
+
@query = $~[1]
|
32
|
+
else
|
33
|
+
klass = Cudan::XpathCudan
|
34
|
+
end
|
35
|
+
instance = klass::new
|
36
|
+
instance.set_header('UserAgent', @ua) if @ua
|
37
|
+
instance.showbody = @showbody
|
38
|
+
instance.execute(@query, @expects, @url)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Cudan
|
2
|
+
class RegexpCudan < BaseCudan
|
3
|
+
def do_query query
|
4
|
+
regexp = Regexp::new(query)
|
5
|
+
@matched = regexp.match(@response)
|
6
|
+
if @matched
|
7
|
+
@matched[0]
|
8
|
+
else
|
9
|
+
''
|
10
|
+
end
|
11
|
+
end
|
12
|
+
def do_expect expect
|
13
|
+
nexpect = expect.gsub(/\\\d/){|m|
|
14
|
+
@matched[m.to_i].to_s
|
15
|
+
}
|
16
|
+
@query_result.include? nexpect
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Cudan
|
2
|
+
class XpathCudan < BaseCudan
|
3
|
+
require 'nokogiri'
|
4
|
+
def do_query query
|
5
|
+
@doc = Nokogiri::HTML(@response)
|
6
|
+
@result = @doc.search(query)
|
7
|
+
@result = @result[0]
|
8
|
+
if @result.is_a? Nokogiri::XML::Text
|
9
|
+
return @result.content.to_s
|
10
|
+
elsif @result
|
11
|
+
return @result.inner_html.to_s
|
12
|
+
else
|
13
|
+
return ''
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def do_expect expect
|
17
|
+
@query_result.include? expect
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/cudan.rb
ADDED
data/test/cudanspec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ww'
|
3
|
+
require 'lib/cudan'
|
4
|
+
require File::dirname(__FILE__) + '/wwutil'
|
5
|
+
|
6
|
+
|
7
|
+
port = 3080 + rand(10)
|
8
|
+
baseurl = "http://localhost:#{port}"
|
9
|
+
html = <<EOS
|
10
|
+
<html>
|
11
|
+
<body>
|
12
|
+
<p class='hoge'>abcdefg</p>
|
13
|
+
</body>
|
14
|
+
</html>
|
15
|
+
EOS
|
16
|
+
##
|
17
|
+
WW::Server[:server] ||= WW::Server::build_double(port) do
|
18
|
+
spy.get('/regexp'){
|
19
|
+
body = html
|
20
|
+
}
|
21
|
+
spy.get('/xpath'){
|
22
|
+
body = html
|
23
|
+
}
|
24
|
+
end
|
25
|
+
WW::Server.start_once
|
26
|
+
RSpec.configure {|c| c.mock_with :mocha}
|
27
|
+
|
28
|
+
describe Cudan::RegexpCudan, 'request for localhost' do
|
29
|
+
before(:each) do
|
30
|
+
Cudan::Logger::stubs(:log).returns nil
|
31
|
+
end
|
32
|
+
it 'should raise no error with regexp' do
|
33
|
+
url = baseurl + '/regexp'
|
34
|
+
o = Cudan::RegexpCudan::new
|
35
|
+
expect{
|
36
|
+
o.execute('<p class=\'hoge\'>(.*)</p>', 'abcdefg', url)
|
37
|
+
}.to_not raise_error(nil)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
describe Cudan::XpathCudan, 'request for localhost' do
|
41
|
+
before(:each) do
|
42
|
+
Cudan::Logger::stubs(:log).returns nil
|
43
|
+
end
|
44
|
+
it 'should raise no error with xpath' do
|
45
|
+
url = baseurl + '/xpath'
|
46
|
+
o = Cudan::XpathCudan::new
|
47
|
+
expect{
|
48
|
+
o.execute('//p[@class="hoge"]/text()', 'abcdefg', url)
|
49
|
+
}.to_not raise_error(nil)
|
50
|
+
expect{
|
51
|
+
o.execute('//p[@class="hoge"]', 'abcdefg', url)
|
52
|
+
}.to_not raise_error(nil)
|
53
|
+
end
|
54
|
+
it 'should raise error with xpath' do
|
55
|
+
url = baseurl + '/xpath'
|
56
|
+
o = Cudan::XpathCudan::new
|
57
|
+
expect{ o.execute('//p[@class="fuga"]', 'hoge', url) }.to raise_error(SystemExit)
|
58
|
+
end
|
59
|
+
end
|
data/test/wwutil.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ww'
|
3
|
+
|
4
|
+
class Requests < Array
|
5
|
+
def self::from_a(ar)
|
6
|
+
is = self.new
|
7
|
+
ar.each do |i|
|
8
|
+
is << i
|
9
|
+
end
|
10
|
+
is
|
11
|
+
end
|
12
|
+
def filter &pred
|
13
|
+
Requests::from_a(find_all(&pred))
|
14
|
+
end
|
15
|
+
def params p
|
16
|
+
filter do |rq|
|
17
|
+
p.any?{|k,v| rq.params[k] == v}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
def request_method method
|
21
|
+
filter {|rq|
|
22
|
+
rq.request_method == method
|
23
|
+
}
|
24
|
+
end
|
25
|
+
def filter_opt p
|
26
|
+
filter do |rq|
|
27
|
+
p.any?{|k,v| rq[k] == v}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
class Ww::Server
|
32
|
+
def compile(path)
|
33
|
+
keys = []
|
34
|
+
if path.respond_to? :to_str
|
35
|
+
special_chars = %w{. + ( )}
|
36
|
+
pattern =
|
37
|
+
path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
|
38
|
+
case match
|
39
|
+
when "*"
|
40
|
+
keys << 'splat'
|
41
|
+
"(.*?)"
|
42
|
+
when *special_chars
|
43
|
+
Regexp.escape(match)
|
44
|
+
else
|
45
|
+
keys << $2[1..-1]
|
46
|
+
"([^/?&#]+)"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
[/^#{pattern}$/, keys]
|
50
|
+
elsif path.respond_to?(:keys) && path.respond_to?(:match)
|
51
|
+
[path, path.keys]
|
52
|
+
elsif path.respond_to? :match
|
53
|
+
[path, keys]
|
54
|
+
else
|
55
|
+
raise TypeError, path
|
56
|
+
end
|
57
|
+
end
|
58
|
+
def filter &pred
|
59
|
+
Requests::from_a(requests).reverse.filter &pred
|
60
|
+
end
|
61
|
+
def path path, opt=nil
|
62
|
+
reg,p = compile(path)
|
63
|
+
r = filter do |rq|
|
64
|
+
rq.path =~ reg
|
65
|
+
end
|
66
|
+
r = r.params(opt) if opt
|
67
|
+
r
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cudan
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- takada-at
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-13 00:00:00 +09:00
|
18
|
+
default_executable: cudan
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: |
|
22
|
+
simple functinal test tool
|
23
|
+
|
24
|
+
email: nightly at at-akada dot org
|
25
|
+
executables:
|
26
|
+
- cudan
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- lib/cudan/xpath_cudan.rb
|
33
|
+
- lib/cudan/logger.rb
|
34
|
+
- lib/cudan/base_cudan.rb
|
35
|
+
- lib/cudan/regexp_cudan.rb
|
36
|
+
- lib/cudan/main.rb
|
37
|
+
- lib/cudan.rb
|
38
|
+
- bin/cudan
|
39
|
+
- test/cudanspec.rb
|
40
|
+
- test/wwutil.rb
|
41
|
+
- README
|
42
|
+
- CHANGES
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/takada-at/cudan
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 1
|
58
|
+
- 8
|
59
|
+
- 6
|
60
|
+
version: 1.8.6
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project: ""
|
71
|
+
rubygems_version: 1.3.6
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: functional test tool
|
75
|
+
test_files: []
|
76
|
+
|