Show More
Commit Description:
merge
Commit Description:
merge
References:
File last commit:
Show/Diff file:
Action:
test/load/visitor_curl_cli.rb | 292 lines | 6.7 KiB | text/x-ruby | RubyLexer |
#
# This file is part of a web load testing tool (currently having no name)
# Copyright (C) 2008 Jittat Fakcharoenphol
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
#
require 'rubygems'
require 'uri'
class Visitor
attr_accessor :talkative
class << self
attr_accessor :commands
attr_accessor :base_url
attr_accessor :cookies_stored
end
def get_cookie_fname
"#{@base_dir}/cookies.#{@id}"
end
def get_output_fname
"#{@base_dir}/output.#{@id}"
end
def id
@id
end
def initialize(id=0, base_dir='.')
# initialize nil class variable
self.class.base_url = "" if (self.class.base_url) == nil
self.class.cookies_stored = false if self.class.cookies_stored == nil
@id = id
@base_dir = base_dir
@cookies_fname = get_cookie_fname
@output_fname = get_output_fname
@statistics = Array.new
@talkative = false
@stopped = false
end
def cleanup
trial = 0
while FileTest.exists?(@cookies_fname)
File.delete(@cookies_fname)
if FileTest.exists?(@cookies_fname)
# wait until system returns
puts "STILL HERE"
sleep 1
trial += 1
break if trial>10
end
end
while FileTest.exists?(@output_fname)
File.delete(@output_fname)
if FileTest.exists?(@output_fname)
# wait until system returns
sleep 1
trial += 1
break if trial>10
end
end
end
def self.site_url(url)
self.base_url = url
end
def self.stores_cookies
self.cookies_stored = true
end
def self.preprocess_param_hash(params)
return {} if params==nil
plist = {}
params.each do |key,val|
if key.is_a? Symbol
key_s = key.to_s
else
key_s = key
end
plist[key_s] = val
end
plist
end
def self.get(url,params=nil)
self.commands = [] if self.commands==nil
self.commands << {
:command => :get,
:url => url,
:params => Visitor.preprocess_param_hash(params) }
end
def self.post(url,params=nil,options=nil)
self.commands = [] if self.commands==nil
self.commands << { :command => :post,
:url => url,
:params => Visitor.preprocess_param_hash(params),
:options => options }
end
def self.process_options(options)
if options.has_key? "site_url"
self.base_url = options["site_url"]
end
end
def substitute_id(st)
return st if !(st.is_a? String)
st.gsub(/(()|(\$))\$\{id\}/) do |s|
if s=="${id}"
@id.to_s
else
"${id}"
end
end
end
def encode_params(params)
enc = ""
if params!=nil and params.length!=0
params.each do |key,val|
if enc != ""
enc += '&'
end
val = substitute_id(val)
enc += URI.escape(key) + '=' + URI.escape(val.to_s)
end
end
enc
end
def get(url,params)
#build url
#puts "----------------------cookies-----------"
#system("cat #{@cookies_fname}")
#puts "----------------------cookies-----------"
full_url = "#{self.class.base_url}#{url}"
if params!=nil and params.length!=0
full_url += '?' + encode_params(params)
end
cmd = "curl -k -b #{@cookies_fname} -D #{@cookies_fname} #{full_url} " +
" -s -L -o #{@output_fname}"
#puts ">>>>>>>>>>>>>>>>>> " + cmd
system(cmd)
#system("cat #{@output_fname}")
end
def post(url,params,options)
#puts "----------------------cookies-----------"
#system("cat #{@cookies_fname}")
#puts "----------------------cookies-----------"
full_url = "#{self.class.base_url}#{url}"
params_str = ""
if options!=nil and options[:multipart]==true
params.each do |key,val|
if val.is_a? Hash
case val[:type]
when :file
dval = substitute_id(val[:data])
params_str += " -F \"#{key}=@#{dval.to_s}\""
end
else
val = substitute_id(val)
params_str += " -F \"#{key}=#{URI.escape(val.to_s)}\""
end
end
else
params_str += "-d \"#{encode_params(params)}\""
end
#puts params_str
cmd = "curl -L -k -b #{@cookies_fname} -D #{@cookies_fname} " +
" #{params_str} #{full_url} -s -o #{@output_fname}"
#puts ">>>>>>>>>>>>>>>>>>>>>>>>>>> POST: " + cmd
system(cmd)
#system("cat #{@output_fname}")
end
def stop!
@stopped = true
end
def run(times=nil, options={})
times = 1 if times == :once
@stopped = false
while times!=0
self.class.commands.each do |cmd|
puts "#{@id}: #{cmd[:command]} #{cmd[:url]}" if @talkative
start_time = Time.new
if !options[:dry_run]
case cmd[:command]
when :get
get cmd[:url], cmd[:params]
when :post
post cmd[:url], cmd[:params], cmd[:options]
end
end
finish_time = Time.new
break if @stopped
@statistics << {
:url => "#{cmd[:command]}:#{cmd[:url]}",
:time => finish_time - start_time }
end
times -= 1 if times.is_a? Integer #otherwise, run forever
break if @stopped
end
end
def show_raw_stat
@statistics.each do |stat|
puts "#{stat[:url]} => #{stat[:time]}"
end
end
def statistics
num_requested = @statistics.length
totaltime = 0.0
@statistics.each { |stat| totaltime += stat[:time] }
if num_requested>0
average_request_time = totaltime / num_requested
else
average_request_time = 0
end
sq_sum = 0.0
@statistics.each do |stat|
sq_sum += (stat[:time]-average_request_time) ** 2
end
if num_requested>1
sd = Math.sqrt(sq_sum/(num_requested-1))
else
sd = 0
end
return {
:num_requested => num_requested,
:avg_request_time => average_request_time,
:std_dev => sd
}
end
end
def visitor(cname,options={},&blk)
c = Class.new(Visitor)
begin
Object.const_set(cname,c)
rescue NameError
puts <<ERROR
Error on type #{cname}.
Type name should be capitalized and follow Ruby constant naming rule.
ERROR
exit(0)
end
c.process_options(options)
c.instance_eval(&blk)
end