rfuzz 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/COPYING +55 -0
  2. data/LICENSE +55 -0
  3. data/README +252 -0
  4. data/Rakefile +48 -0
  5. data/doc/rdoc/classes/RFuzz.html +146 -0
  6. data/doc/rdoc/classes/RFuzz/HttpClient.html +481 -0
  7. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000010.html +24 -0
  8. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000011.html +34 -0
  9. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000012.html +49 -0
  10. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000013.html +49 -0
  11. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000014.html +57 -0
  12. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000015.html +37 -0
  13. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000016.html +26 -0
  14. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000017.html +34 -0
  15. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000018.html +18 -0
  16. data/doc/rdoc/classes/RFuzz/HttpClient.src/M000019.html +26 -0
  17. data/doc/rdoc/classes/RFuzz/HttpEncoding.html +294 -0
  18. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000001.html +26 -0
  19. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000002.html +18 -0
  20. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000003.html +26 -0
  21. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000004.html +18 -0
  22. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000005.html +32 -0
  23. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000006.html +18 -0
  24. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000007.html +20 -0
  25. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000008.html +20 -0
  26. data/doc/rdoc/classes/RFuzz/HttpEncoding.src/M000009.html +32 -0
  27. data/doc/rdoc/classes/RFuzz/HttpResponse.html +180 -0
  28. data/doc/rdoc/classes/RFuzz/Notifier.html +252 -0
  29. data/doc/rdoc/classes/RFuzz/Notifier.src/M000044.html +17 -0
  30. data/doc/rdoc/classes/RFuzz/Notifier.src/M000045.html +17 -0
  31. data/doc/rdoc/classes/RFuzz/Notifier.src/M000046.html +17 -0
  32. data/doc/rdoc/classes/RFuzz/Notifier.src/M000047.html +17 -0
  33. data/doc/rdoc/classes/RFuzz/Notifier.src/M000048.html +17 -0
  34. data/doc/rdoc/classes/RFuzz/Notifier.src/M000049.html +17 -0
  35. data/doc/rdoc/classes/RFuzz/RandomGenerator.html +362 -0
  36. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000032.html +21 -0
  37. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000033.html +23 -0
  38. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000036.html +22 -0
  39. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000037.html +20 -0
  40. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000038.html +22 -0
  41. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000039.html +20 -0
  42. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000040.html +18 -0
  43. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000041.html +18 -0
  44. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000042.html +22 -0
  45. data/doc/rdoc/classes/RFuzz/RandomGenerator.src/M000043.html +18 -0
  46. data/doc/rdoc/classes/RFuzz/Sampler.html +383 -0
  47. data/doc/rdoc/classes/RFuzz/Sampler.src/M000056.html +19 -0
  48. data/doc/rdoc/classes/RFuzz/Sampler.src/M000057.html +23 -0
  49. data/doc/rdoc/classes/RFuzz/Sampler.src/M000058.html +26 -0
  50. data/doc/rdoc/classes/RFuzz/Sampler.src/M000059.html +18 -0
  51. data/doc/rdoc/classes/RFuzz/Sampler.src/M000060.html +18 -0
  52. data/doc/rdoc/classes/RFuzz/Sampler.src/M000061.html +18 -0
  53. data/doc/rdoc/classes/RFuzz/Sampler.src/M000062.html +18 -0
  54. data/doc/rdoc/classes/RFuzz/Sampler.src/M000063.html +19 -0
  55. data/doc/rdoc/classes/RFuzz/Sampler.src/M000064.html +18 -0
  56. data/doc/rdoc/classes/RFuzz/Sampler.src/M000065.html +23 -0
  57. data/doc/rdoc/classes/RFuzz/Sampler.src/M000066.html +18 -0
  58. data/doc/rdoc/classes/RFuzz/Sampler.src/M000067.html +20 -0
  59. data/doc/rdoc/classes/RFuzz/Session.html +415 -0
  60. data/doc/rdoc/classes/RFuzz/Session.src/M000020.html +31 -0
  61. data/doc/rdoc/classes/RFuzz/Session.src/M000021.html +18 -0
  62. data/doc/rdoc/classes/RFuzz/Session.src/M000022.html +18 -0
  63. data/doc/rdoc/classes/RFuzz/Session.src/M000023.html +34 -0
  64. data/doc/rdoc/classes/RFuzz/Session.src/M000024.html +19 -0
  65. data/doc/rdoc/classes/RFuzz/Session.src/M000025.html +19 -0
  66. data/doc/rdoc/classes/RFuzz/Session.src/M000026.html +26 -0
  67. data/doc/rdoc/classes/RFuzz/Session.src/M000027.html +29 -0
  68. data/doc/rdoc/classes/RFuzz/Session.src/M000028.html +19 -0
  69. data/doc/rdoc/classes/RFuzz/Session.src/M000029.html +18 -0
  70. data/doc/rdoc/classes/RFuzz/Session.src/M000030.html +18 -0
  71. data/doc/rdoc/classes/RFuzz/Session.src/M000031.html +23 -0
  72. data/doc/rdoc/classes/RFuzz/StatsTracker.html +242 -0
  73. data/doc/rdoc/classes/RFuzz/StatsTracker.src/M000050.html +19 -0
  74. data/doc/rdoc/classes/RFuzz/StatsTracker.src/M000051.html +19 -0
  75. data/doc/rdoc/classes/RFuzz/StatsTracker.src/M000052.html +18 -0
  76. data/doc/rdoc/classes/RFuzz/StatsTracker.src/M000053.html +18 -0
  77. data/doc/rdoc/classes/RFuzz/StatsTracker.src/M000054.html +28 -0
  78. data/doc/rdoc/classes/RFuzz/StatsTracker.src/M000055.html +18 -0
  79. data/doc/rdoc/created.rid +1 -0
  80. data/doc/rdoc/files/COPYING.html +168 -0
  81. data/doc/rdoc/files/LICENSE.html +168 -0
  82. data/doc/rdoc/files/README.html +473 -0
  83. data/doc/rdoc/files/lib/rfuzz/client_rb.html +111 -0
  84. data/doc/rdoc/files/lib/rfuzz/random_rb.html +116 -0
  85. data/doc/rdoc/files/lib/rfuzz/rfuzz_rb.html +109 -0
  86. data/doc/rdoc/files/lib/rfuzz/session_rb.html +111 -0
  87. data/doc/rdoc/files/lib/rfuzz/stats_rb.html +113 -0
  88. data/doc/rdoc/fr_class_index.html +35 -0
  89. data/doc/rdoc/fr_file_index.html +34 -0
  90. data/doc/rdoc/fr_method_index.html +93 -0
  91. data/doc/rdoc/index.html +24 -0
  92. data/doc/rdoc/rdoc-style.css +208 -0
  93. data/examples/amazon_headers.rb +38 -0
  94. data/examples/hpricot_pudding.rb +22 -0
  95. data/examples/kill_routes.rb +26 -0
  96. data/examples/mongrel_test_suite/lib/gen.rb +24 -0
  97. data/examples/mongrel_test_suite/test/camping/static_files.rb +9 -0
  98. data/examples/mongrel_test_suite/test/camping/upload_file.rb +9 -0
  99. data/examples/mongrel_test_suite/test/camping/upload_progress.rb +9 -0
  100. data/examples/mongrel_test_suite/test/http/base_protocol.rb +23 -0
  101. data/examples/mongrel_test_suite/test/nitro/upload_file.rb +9 -0
  102. data/examples/mongrel_test_suite/test/nitro/upload_progress.rb +9 -0
  103. data/examples/mongrel_test_suite/test/rails/static_files.rb +9 -0
  104. data/examples/mongrel_test_suite/test/rails/upload_file.rb +9 -0
  105. data/examples/mongrel_test_suite/test/rails/upload_progress.rb +9 -0
  106. data/examples/perftest.rb +30 -0
  107. data/ext/fuzzrnd/ext_help.h +14 -0
  108. data/ext/fuzzrnd/extconf.rb +6 -0
  109. data/ext/fuzzrnd/fuzzrnd.c +149 -0
  110. data/ext/http11_client/ext_help.h +14 -0
  111. data/ext/http11_client/extconf.rb +6 -0
  112. data/ext/http11_client/http11_client.c +288 -0
  113. data/ext/http11_client/http11_parser.c +629 -0
  114. data/ext/http11_client/http11_parser.h +46 -0
  115. data/ext/http11_client/http11_parser.rl +169 -0
  116. data/lib/rfuzz/client.rb +498 -0
  117. data/lib/rfuzz/random.rb +110 -0
  118. data/lib/rfuzz/rfuzz.rb +12 -0
  119. data/lib/rfuzz/session.rb +154 -0
  120. data/lib/rfuzz/stats.rb +159 -0
  121. data/resources/defaults.yaml +2 -0
  122. data/resources/words.txt +3310 -0
  123. data/test/coverage/index.html +388 -0
  124. data/test/coverage/lib-rfuzz-client_rb.html +1127 -0
  125. data/test/coverage/lib-rfuzz-random_rb.html +739 -0
  126. data/test/coverage/lib-rfuzz-session_rb.html +783 -0
  127. data/test/coverage/lib-rfuzz-stats_rb.html +788 -0
  128. data/test/server.rb +101 -0
  129. data/test/test_client.rb +164 -0
  130. data/test/test_fuzzrnd.rb +31 -0
  131. data/test/test_httpparser.rb +48 -0
  132. data/test/test_random.rb +75 -0
  133. data/test/test_session.rb +33 -0
  134. data/test/test_stats.rb +45 -0
  135. data/tools/rakehelp.rb +119 -0
  136. metadata +201 -0
@@ -0,0 +1,473 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5
+
6
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
7
+ <head>
8
+ <title>File: README</title>
9
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
10
+ <meta http-equiv="Content-Script-Type" content="text/javascript" />
11
+ <link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
12
+ <script type="text/javascript">
13
+ // <![CDATA[
14
+
15
+ function popupCode( url ) {
16
+ window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
17
+ }
18
+
19
+ function toggleCode( id ) {
20
+ if ( document.getElementById )
21
+ elem = document.getElementById( id );
22
+ else if ( document.all )
23
+ elem = eval( "document.all." + id );
24
+ else
25
+ return false;
26
+
27
+ elemStyle = elem.style;
28
+
29
+ if ( elemStyle.display != "block" ) {
30
+ elemStyle.display = "block"
31
+ } else {
32
+ elemStyle.display = "none"
33
+ }
34
+
35
+ return true;
36
+ }
37
+
38
+ // Make codeblocks hidden by default
39
+ document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
40
+
41
+ // ]]>
42
+ </script>
43
+
44
+ </head>
45
+ <body>
46
+
47
+
48
+
49
+ <div id="fileHeader">
50
+ <h1>README</h1>
51
+ <table class="header-table">
52
+ <tr class="top-aligned-row">
53
+ <td><strong>Path:</strong></td>
54
+ <td>README
55
+ </td>
56
+ </tr>
57
+ <tr class="top-aligned-row">
58
+ <td><strong>Last Update:</strong></td>
59
+ <td>Wed Jul 19 17:15:09 EDT 2006</td>
60
+ </tr>
61
+ </table>
62
+ </div>
63
+ <!-- banner header -->
64
+
65
+ <div id="bodyContent">
66
+
67
+
68
+
69
+ <div id="contextContent">
70
+
71
+ <div id="description">
72
+ <h1><a href="../classes/RFuzz.html">RFuzz</a> HTTP Destroyer</h1>
73
+ <p>
74
+ <a href="../classes/RFuzz.html">RFuzz</a> is the start of a Ruby based HTTP
75
+ thrasher, destroyer, fuzzer, and client based on the Mongrel
76
+ project&#8217;s HTTP parser and the statistical analysis of being very mean
77
+ to a web server.
78
+ </p>
79
+ <p>
80
+ At the moment is has a working and fairly extensive HTTP 1.1 client and
81
+ some basic statistics math borrowed from the Mongrel project.
82
+ </p>
83
+ <p>
84
+ In order for the test cases to run you need to start any Rails project on
85
+ port 3000. Future releases will have tests starting built-in Mongrel
86
+ servers to validate client functionality.
87
+ </p>
88
+ <h2>Motivation</h2>
89
+ <p>
90
+ The motivation for <a href="../classes/RFuzz.html">RFuzz</a> comes from
91
+ little scripts I&#8217;ve written during Mongrel development to
92
+ &quot;fuzz&quot; or attack the Mongrel code.
93
+ </p>
94
+ <p>
95
+ <a href="../classes/RFuzz.html">RFuzz</a> will simply use the built-in
96
+ ultra-correct HTTP client and a Ruby DSL to let you write scripts that
97
+ exploit servers, thrash them with random data, or simply run simple test
98
+ suites.
99
+ </p>
100
+ <p>
101
+ It may also perform analysis of performance data and work as a simply load
102
+ or pen testing tool. This is only a secondary goal though since
103
+ there&#8217;s plenty of good tools for that.
104
+ </p>
105
+ <h2>Downloading</h2>
106
+ <p>
107
+ Right now <a href="../classes/RFuzz.html">RFuzz</a> just sits on my server,
108
+ so you can download <a
109
+ href="http://www.zedshaw.com/projects/rfuzz/rfuzz-0.4.gem">www.zedshaw.com/projects/rfuzz/rfuzz-0.4.gem</a>
110
+ or <a
111
+ href="http://www.zedshaw.com/projects/rfuzz/rfuzz-0.4.tgz">www.zedshaw.com/projects/rfuzz/rfuzz-0.4.tgz</a>
112
+ for the 0.4 version.
113
+ </p>
114
+ <p>
115
+ Once it can actually be used to fuzz a system I&#8217;ll make a RubyForge
116
+ project.
117
+ </p>
118
+ <h2><a href="../classes/RFuzz.html">RFuzz</a> HTTP Client</h2>
119
+ <p>
120
+ It also comes from not being satisfied with the stock net/http library.
121
+ While this library is good for high-level HTTP access to resources, it is
122
+ much too abstract and protective to be used in a fuzzing tool.
123
+ </p>
124
+ <p>
125
+ In a tool such as <a href="../classes/RFuzz.html">RFuzz</a> you need to
126
+ have the following features in an HTTP client library:
127
+ </p>
128
+ <ol>
129
+ <li>No protection from exceptions to analyze exactly what&#8217;s happening.
130
+
131
+ </li>
132
+ <li>Ability to &quot;throttle&quot; the client to simulate different kinds of
133
+ request loads.
134
+
135
+ </li>
136
+ <li>No threading or additional overhead to test the impact of threads, but
137
+ thread safe.
138
+
139
+ </li>
140
+ <li>Ability to encode the majority of the request as data elements for loading.
141
+
142
+ </li>
143
+ <li>Fast and exact HTTP parser to validate the server&#8217;s response is
144
+ correct.
145
+
146
+ </li>
147
+ <li>Tracks cookies between requests to keep session data going.
148
+
149
+ </li>
150
+ </ol>
151
+ <p>
152
+ <a href="../classes/RFuzz/HttpClient.html">RFuzz::HttpClient</a> supports
153
+ all of these features already, with cookies being the weakest right now.
154
+ </p>
155
+ <h3>Using The Client</h3>
156
+ <p>
157
+ The client is designed that you create an <a
158
+ href="../classes/RFuzz/HttpClient.html">RFuzz::HttpClient</a> object once
159
+ with all the common parameters and the host you want to talk with, and then
160
+ you call a series of methods on the client object that match the HTTP
161
+ methods GET, POST, PUT, DELETE, and HEAD. You can add more methods if you
162
+ like (see the documentation).
163
+ </p>
164
+ <p>
165
+ Here&#8217;s a simple example:
166
+ </p>
167
+ <pre>
168
+ require 'rfuzz/client'
169
+
170
+ cl = RFuzz::HttpClient.new(&quot;www.google.com&quot;, 80, :query =&gt; {&quot;q&quot; =&gt; &quot;zed shaw&quot;})
171
+
172
+ resp = cl.get(&quot;/search&quot;)
173
+ resp.http_body.grep(/zed/)
174
+ =&gt; [&quot;&lt;html&gt;&lt;head&gt;&lt;meta HTTP-EQUIV=\&quot;content-type\&quot; CONTENT=\&quot;text/html;
175
+ charset=ISO-8859-1\&quot;&gt;&lt;title&gt;zed shaw - Google Search&lt;/title&gt;&lt;style&gt;&lt;!--\n&quot;]
176
+
177
+ resp = cl.get(&quot;/search&quot;, :query =&gt; {&quot;q&quot; =&gt; &quot;frank&quot;})
178
+ =&gt; [&quot;&lt;html&gt;&lt;head&gt;&lt;meta HTTP-EQUIV=\&quot;content-type\&quot; CONTENT=\&quot;text/html;
179
+ charset=ISO-8859-1\&quot;&gt;&lt;title&gt;frank - Google Search&lt;/title&gt;&lt;style&gt;&lt;!--\n&quot;]
180
+ </pre>
181
+ <p>
182
+ Notice that we made a client that actually had a default :query to just
183
+ search for my name (Zed Shaw) and then we only had to
184
+ cl.get(&quot;/search&quot;). In the second query though we just set :query
185
+ to something else (a search for &quot;frank&quot;) and it automatically
186
+ overrides the parameters. This makes it possible to set common parameters,
187
+ cookies, and headers in blocks of requests to reduce repetition.
188
+ </p>
189
+ <h3>Client Limitations</h3>
190
+ <p>
191
+ You can use the HTTP client right now to do HTTP requests and it is
192
+ probably a lot easier than net/http for most requests that don&#8217;t
193
+ require complex POST bodies encoding. It also contains full documentation
194
+ and has a full suite of encoding and decoding libraries. It can&#8217;t
195
+ handle large HTTP bodies yet.
196
+ </p>
197
+ <p>
198
+ It can&#8217;t also parse cookies properly yet, so the above example kind
199
+ of works, but the cookie isn&#8217;t returned right.
200
+ </p>
201
+ <h2>Randomness Generator</h2>
202
+ <p>
203
+ <a href="../classes/RFuzz.html">RFuzz</a> features a RandomGenerator class
204
+ that uses the ArcFour random number generation algorithm to generate lots
205
+ of random garbage very fast in various formats. <a
206
+ href="../classes/RFuzz.html">RFuzz</a> will use this to send the garbage it
207
+ needs to the application in an attempt to find forms that can&#8217;t
208
+ handle nastiness, badly implemented servers, etc. It&#8217;s amazing how
209
+ many bugs you actually can find by sending junk to an application.
210
+ </p>
211
+ <p>
212
+ The types of randomness you can generate are:
213
+ </p>
214
+ <ul>
215
+ <li>words &#8212; <a href="../classes/RFuzz.html">RFuzz</a> includes a simple
216
+ word list, but you can add your own.
217
+
218
+ </li>
219
+ <li>base64 &#8212; Arrays of base64 encoded junk.
220
+
221
+ </li>
222
+ <li>byte_array &#8212; Arrays of just junk.
223
+
224
+ </li>
225
+ <li>uris &#8212; Arrays of URIs composed of words strung together with /.
226
+
227
+ </li>
228
+ <li>ints &#8212; Random integers (with an allowed maximum).
229
+
230
+ </li>
231
+ <li>floats &#8212; Random floats.
232
+
233
+ </li>
234
+ <li>headers,queries &#8212; Hashes of key=value where the keys and values can
235
+ be any of the above.
236
+
237
+ </li>
238
+ </ul>
239
+ <p>
240
+ The ArcFour fuzzrnd random generator is in a C extension so it&#8217;s
241
+ small and fast. A big advantage of fuzzrnd is that it generates the same
242
+ stream of random bytes for the same input seeds. This lets you set a seed
243
+ and then if you find an error replay the same attack but still have random
244
+ data.
245
+ </p>
246
+ <p>
247
+ An example of using RandomGenerator is:
248
+ </p>
249
+ <pre>
250
+ g = RFuzz::RandomGenerator.new(open(&quot;resources/words.txt&quot;).read.split(&quot;\n&quot;))
251
+ h = g.headers(2,4,type=:ints)
252
+ =&gt; [{1398667391=&gt;2615968266, 465122870=&gt;2683411899, 2100652296=&gt;4131806743,
253
+ 158954822=&gt;2544978312}, {3126281447=&gt;2247028995, 269763016=&gt;1444943723,
254
+ 2401569363=&gt;1661839605, 2811294153=&gt;400252371}]
255
+ </pre>
256
+ <p>
257
+ As you can see this produces 2 hashes consisting of 4 key=value pairs with
258
+ integers in them. You can quickly replace type=:ints with type=:words and
259
+ get:
260
+ </p>
261
+ <pre>
262
+ =&gt; [{&quot;Europeanizes&quot;=&gt;&quot;Byronize's&quot;, &quot;royalization's&quot;=&gt;&quot;Americanizer's&quot;,
263
+ &quot;celiorrhea&quot;=&gt;&quot;unliteralized&quot;, &quot;unvictimized&quot;=&gt;&quot;doctrinize&quot;},
264
+ {&quot;pouder&quot;=&gt;&quot;unchloridized&quot;, &quot;chattelize&quot;=&gt;&quot;unmodernize&quot;,
265
+ &quot;uncrystallizability&quot;=&gt;&quot;uncenter&quot;, &quot;Egyptianization's&quot;=&gt;&quot;ostracization's&quot;}]
266
+ </pre>
267
+ <p>
268
+ Using the included dictionary of words.
269
+ </p>
270
+ <h1>Fuzzing Sessions And Statistics</h1>
271
+ <p>
272
+ The main way that you&#8217;ll use <a
273
+ href="../classes/RFuzz.html">RFuzz</a> is to use the <a
274
+ href="../classes/RFuzz/Session.html">RFuzz::Session</a> class to perform <a
275
+ href="../classes/RFuzz.html">RFuzz</a> runs and store the results in
276
+ various .csv files for analysis later. <a
277
+ href="../classes/RFuzz.html">RFuzz</a> makes the stance that it
278
+ shouldn&#8217;t be used for analyzing the data, but rather it should
279
+ generate information that you can put through a better tool. Examples of
280
+ such tools are R, gnuplot, ploticus, or a spreadsheet.
281
+ </p>
282
+ <p>
283
+ The Session class is initialized in a similar fashion to the HttpClient,
284
+ except you can&#8217;t set the :notifier (it&#8217;s used to collect
285
+ statistics about the requests). Once you have a Session object you call
286
+ it&#8217;s Session#run method to do a run of a set of samples and then put
287
+ your tests inside a block.
288
+ </p>
289
+ <p>
290
+ When a run is done it saves the results to two CSV files so you can analyze
291
+ them.
292
+ </p>
293
+ <p>
294
+ Here&#8217;s a small sample of how Session is used:
295
+ </p>
296
+ <pre>
297
+ require 'rfuzz/session'
298
+ include RFuzz
299
+ s = Session.new :host =&gt; &quot;localhost&quot;, :port =&gt; 3000
300
+ s.run 5, :save_as =&gt; [&quot;runs.csv&quot;,&quot;counts.csv&quot;] do |c,r|
301
+ uris = r.uris(50,r.num(30))
302
+ uris.each do |u|
303
+ s.count_errors(:words) do
304
+ resp = c.get(u)
305
+ s.count resp.http_status
306
+ end
307
+ end
308
+ end
309
+ </pre>
310
+ <p>
311
+ If you run this (having a server at localhost:3000) you&#8217;ll find two
312
+ files in the current directory: runs.csv and counts.csv. These files might
313
+ look like this:
314
+ </p>
315
+ <pre>
316
+ -- runs.csv --
317
+ run,name,sum,sumsq,n,mean,sd,min,max
318
+ 0,request,0.517807,0.010310748693,50.0,0.01035614,0.0100491312529583,0.001729,0.074479
319
+ 1,request,0.48696,0.010552774434,50.0,0.0097392,0.0108892135376889,0.001667,0.081887
320
+ 2,request,0.322049,0.004898592637,50.0,0.00644098,0.00759199560893725,0.000806,0.057761
321
+ 3,request,0.271233,0.004324191489,50.0,0.00542466,0.00763028964494234,0.000828,0.057182
322
+ 4,request,0.27697,0.001659079814,50.0,0.0055394,0.00159611899203497,0.000791,0.010722
323
+
324
+ -- counts.csv --
325
+ run,404,200
326
+ 0,46,4
327
+ 1,41,9
328
+ 2,48,2
329
+ 3,42,8
330
+ 4,49,1
331
+ </pre>
332
+ <p>
333
+ You can then easily load these two files into any tool you want to analyze
334
+ the results.
335
+ </p>
336
+ <h3>Counts vs. Samples vs. Runs</h3>
337
+ <p>
338
+ Something many people don&#8217;t do correctly which <a
339
+ href="../classes/RFuzz.html">RFuzz</a> tries to implicitly enforce is that
340
+ doing just one run isn&#8217;t as useful as doing a set of runs. You might
341
+ not be familiar with the terminology, so let&#8217;s cover that first.
342
+ </p>
343
+ <ul>
344
+ <li>count &#8212; Just a simple count of some variable during a run.
345
+
346
+ </li>
347
+ <li>sample &#8212; A sample is the result of taking a measurement during a run.
348
+
349
+ </li>
350
+ <li>run &#8212; This is a test that you perform and then collect counts and
351
+ samples for.
352
+
353
+ </li>
354
+ </ul>
355
+ <p>
356
+ In the above sample script, we are doing the following:
357
+ </p>
358
+ <ul>
359
+ <li>5 runs.
360
+
361
+ </li>
362
+ <li>That do GET requests for up to 50 randomly selected URIs.
363
+
364
+ </li>
365
+ <li>Counting errors, HTTP status codes.
366
+
367
+ </li>
368
+ <li>And gathers stats on the request timing (Session does this automatically).
369
+
370
+ </li>
371
+ </ul>
372
+ <p>
373
+ If you were to structure this into a data structure it would like this:
374
+ </p>
375
+ <pre>
376
+ [
377
+ [&quot;run&quot;, &quot;name&quot;, &quot;sum&quot;, &quot;sumsq&quot;, &quot;n&quot;, &quot;mean&quot;, &quot;sd&quot;, &quot;min&quot;, &quot;max&quot;],
378
+ [0, :request, 0.605363, 0.0149, 50.0, 0.0121, 0.0124, 0.00851, 0.095579],
379
+ [1, :request, 0.520827, 0.0116, 50.0, 0.0104, 0.0112, 0.00189, 0.088004],
380
+ ...
381
+ ]
382
+ </pre>
383
+ <p>
384
+ Taking a look at this, we have run 0, run 1, &#8230; and then each
385
+ &quot;row&quot; has a set of satistics we&#8217;ve gathered on the HTTP
386
+ request (shown as &quot;name&quot;). These statistics are actually
387
+ generated from the random 50 URI requests we built with this set of code:
388
+ </p>
389
+ <pre>
390
+ uris = r.uris(50,r.num(30))
391
+ </pre>
392
+ <p>
393
+ Which means that each row is the statistics collected as each request is
394
+ made from the 50 randomly generated URIs. If I were to write this out
395
+ it&#8217;d be:
396
+ </p>
397
+ <ol>
398
+ <li>Generate 50 random URIs.
399
+
400
+ </li>
401
+ <li>Request URIs 1-50, record how long each one takes.
402
+
403
+ </li>
404
+ <li>Average (with standard deviation) the times for each request.
405
+
406
+ </li>
407
+ <li>Store this as one &quot;run&quot;.
408
+
409
+ </li>
410
+ <li>Repeat until all the runs are done.
411
+
412
+ </li>
413
+ </ol>
414
+ <p>
415
+ By doing this you cut down on the amount of information you need to analyze
416
+ to figure out if a server is behaving correctly. Instead of wading through
417
+ tons of data about each request, you just analyze the
418
+ &quot;meta-statistics&quot; about the runs.
419
+ </p>
420
+ <h3>Sample Runs Reduce Error</h3>
421
+ <p>
422
+ The reason for doing a series of runs and analyzing their standard
423
+ deviation (sd) and means is that it reduces the chance that one long run
424
+ was just done at the wrong time or in the wrong situation. If you just ran
425
+ a test once with the same settings every time you might not find out until
426
+ later that there was some confounding element which made the test invalid.
427
+ </p>
428
+ <h2>Source Code</h2>
429
+ <p>
430
+ The .tgz file (mentioned Downloading) has the source if you&#8217;re
431
+ interested. Remember that *you must have a rails app on 3000* for the tests
432
+ to run. Just a limitation right now until I hook Mongrel into the test
433
+ framework as the feedback loop.
434
+ </p>
435
+ <p>
436
+ You can also view <a
437
+ href="http://www.zedshaw.com/projects/rfuzz/coverage">www.zedshaw.com/projects/rfuzz/coverage</a>/
438
+ for the rcov generated coverage report which is also a decent source
439
+ browser.
440
+ </p>
441
+
442
+ </div>
443
+
444
+
445
+ </div>
446
+
447
+
448
+ </div>
449
+
450
+
451
+ <!-- if includes -->
452
+
453
+ <div id="section">
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+
462
+ <!-- if method_list -->
463
+
464
+
465
+ </div>
466
+
467
+
468
+ <div id="validator-badges">
469
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
470
+ </div>
471
+
472
+ </body>
473
+ </html>