C0 code coverage information
Generated on Wed Jul 19 17:39:34 EDT 2006 with rcov 0.6.0
Code reported as executed by Ruby looks like this...
and this: this line is also marked as covered.
Lines considered as run by rcov, but not reported by Ruby, look like this,
and this: these lines were inferred by rcov (using simple heuristics).
Finally, here's a line marked as not executed.
1 require 'csv'
2 require 'rfuzz/random'
3 require 'rfuzz/client'
4 require 'rfuzz/stats'
5
6 module RFuzz
7 # Creates a small light DSL for running RFuzz sessions against a
8 # web server. It configures a basic client and randomizer that you
9 # then use to conduct sessions and record statistics about the activity.
10 class Session
11
12 attr_accessor :counts
13 attr_accessor :runs
14 attr_accessor :tracking
15
16 # Sets up a session that you then operate by calling Session#run. Most of the
17 # functions do not work unless they are inside a Session#run call.
18 #
19 # Available options are:
20 #
21 # * :host => Required. Which host.
22 # * :port => Required. Which port.
23 # * :words => Dictionary to load for the words passed to RandomGenerator.
24 #
25 # You can then pass any options you need to pass to the created RFuzz::HttpClient.
26 def initialize(options={})
27 @host = options[:host]
28 @port = options[:port]
29 options.delete(:host)
30 options.delete(:port)
31 options[:notifier] = StatsTracker.new
32
33 @word_file = options[:words] || File.join(File.dirname(__FILE__), "..", "..", "resources","words.txt")
34
35 @client = HttpClient.new(@host, @port, options)
36 @rand = RandomGenerator.new(open(@word_file).read.split("\n"))
37
38 @runs = []
39 @counts = []
40 @tracking = []
41 end
42
43 def cur_run
44 @runs.last
45 end
46
47 def cur_count
48 @counts.last
49 end
50
51 # Begin a run of count length wher a block is run once and statistics are collected
52 # from the client passed to the block. When calls you can pass in the following options:
53 #
54 # * :sample => Defaults to [:request], but will record any of [:request, :connect, :send_request, :read_header, :read_body, :close]
55 # * :save_as => A tuple of ["runs.csv", "counts.csv"] (or whatever you want to call them).
56 #
57 # Once you call run, the block you pass it is given an HttpClient and a RandomGenerator. Each run will reset the HttpClient so you can pretend it is brand new.
58 #
59 def run(count, options={})
60 sample = options[:sample] || [:request]
61 count.times do |i|
62 # setup for this latest sample run
63 @runs << {}
64 @counts << {}
65 @tracking << {}
66 yield @client, @rand
67
68 # record the request stats then reset them
69 sample.each {|s| cur_run[s] = @client.notifier.stats[s].clone }
70 @client.notifier.reset
71 end
72
73 if options[:save_as]
74 write_runs(options[:save_as][0])
75 write_counts(options[:save_as][1])
76 end
77 end
78
79 # Called inside a run to collect a stat you want with the given count.
80 # The stat should be a string or symbol, and count should be a number (or float).
81 def sample(stat,count)
82 cur_run[stat] ||= Sampler.new(stat)
83 cur_run[stat].sample(count)
84 end
85
86 # Called inside a run to do a count of a measurement.
87 def count(stat,count=1)
88 cur_count[stat] ||= 0
89 cur_count[stat] += count
90 end
91
92 # Takes the samples for all runs and returns an array suitable for passing
93 # to CSV or some other table output. If you want to access the runs
94 # directly then just use the Session#runs attribute.
95 def runs_to_a(headers=false)
96 keys = ["run"] + Sampler.keys
97 results = []
98 results << keys if headers
99
100 @runs.length.times do |run|
101 @runs[run].values.each {|stats| results << [run] + stats.values }
102 end
103
104 return results
105 end
106
107 # Takes the counts for all the runs and produces an array suitable
108 # for CSV output. Use Session#counts to access the counts directly.
109 def counts_to_a(headers=false)
110 keys = @counts[0].keys
111 results = []
112 results << ["run"] + keys if headers
113
114 @counts.length.times do |run|
115 results << [run]
116 keys.each do |k|
117 results.last << @counts[run][k]
118 end
119 end
120
121 return results
122 end
123
124 # Lets you track some value you need to report on later. Doesn't
125 # do any calculations and is matched for each run. You then access
126 # Session#tracking which is an Array of runs, each run being a Hash.
127 # Inside the hash is the tracking you registerd by {name => [val1, val2]}.
128 def track(name,value)
129 @tracking.last[name] ||= []
130 @tracking.last[name] << value
131 end
132
133 # Writes the runs to the given file as a CSV.
134 def write_runs(file)
135 CSV.open(file,"w") {|out| runs_to_a(headers=true).each {|r| out << r } }
136 end
137
138 # Writes the counts to the given file as a CSV.
139 def write_counts(file)
140 CSV.open(file,"w") {|out| counts_to_a(headers=true).each {|c| out << c } }
141 end
142
143 # Used inside Session#run to wrap an attempted request or potentially
144 # failing action and then count the exceptions thrown.
145 def count_errors(as)
146 begin
147 yield
148 rescue
149 count as
150 count $!.class.to_s.tr(":","")
151 end
152 end
153 end
154 end
Generated using the rcov code coverage analysis tool for Ruby version 0.6.0.