rfuzz 0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>