mongrel_esi 0.4.1 → 0.5.0

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 (184) hide show
  1. data/Rakefile +15 -8
  2. data/bin/mongrel_esi +0 -0
  3. data/ext/esi/common.rl +32 -27
  4. data/ext/esi/esi_parser.c +11 -4
  5. data/ext/esi/parser.c +4536 -901
  6. data/ext/esi/parser.h +7 -0
  7. data/ext/esi/parser.rl +171 -53
  8. data/ext/esi/run-test.rb +0 -0
  9. data/ext/esi/test/common.rl +32 -27
  10. data/ext/esi/test/parser.c +322 -1342
  11. data/ext/esi/test/parser.h +7 -0
  12. data/ext/esi/test/parser.rl +171 -53
  13. data/ext/esi/test/test.c +13 -4
  14. data/ext/esi/test1.rb +35 -3
  15. data/lib/esi/cache.rb +2 -1
  16. data/lib/esi/config.rb +37 -0
  17. data/lib/esi/dispatcher.rb +3 -5
  18. data/lib/esi/invalidator.rb +3 -0
  19. data/lib/esi/logger.rb +0 -7
  20. data/lib/esi/parser.rb +70 -0
  21. data/lib/esi/processor.rb +88 -0
  22. data/lib/esi/proxy.rb +104 -0
  23. data/lib/esi/response.rb +106 -0
  24. data/lib/esi/router.rb +3 -0
  25. data/lib/esi/tag/attempt.rb +3 -0
  26. data/lib/esi/tag/base.rb +3 -1
  27. data/lib/esi/tag/except.rb +2 -0
  28. data/lib/esi/tag/include.rb +131 -132
  29. data/lib/esi/tag/invalidate.rb +2 -0
  30. data/lib/esi/tag/try.rb +3 -0
  31. data/test/integration/basic_test.rb +0 -1
  32. data/test/integration/docs/esi_max_age_varies.html +10 -0
  33. data/test/integration/handler_test.rb +31 -5
  34. data/test/integration/help.rb +13 -1
  35. data/test/load_test.rb +133 -0
  36. data/test/unit/include_request_test.rb +1 -1
  37. data/test/unit/parser_test.rb +41 -5
  38. data/test/unit/response_test.rb +184 -0
  39. metadata +50 -224
  40. data/doc/rdoc/classes/ESI/Cache.html +0 -178
  41. data/doc/rdoc/classes/ESI/Cache.src/M000060.html +0 -17
  42. data/doc/rdoc/classes/ESI/Cache.src/M000061.html +0 -20
  43. data/doc/rdoc/classes/ESI/Config/CacheConfig.html +0 -212
  44. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000055.html +0 -19
  45. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000056.html +0 -19
  46. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000057.html +0 -18
  47. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000058.html +0 -18
  48. data/doc/rdoc/classes/ESI/Config/CacheConfig.src/M000059.html +0 -18
  49. data/doc/rdoc/classes/ESI/Config/ConfigRouter.html +0 -187
  50. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000052.html +0 -19
  51. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000053.html +0 -21
  52. data/doc/rdoc/classes/ESI/Config/ConfigRouter.src/M000054.html +0 -21
  53. data/doc/rdoc/classes/ESI/Config.html +0 -291
  54. data/doc/rdoc/classes/ESI/Config.src/M000043.html +0 -18
  55. data/doc/rdoc/classes/ESI/Config.src/M000044.html +0 -18
  56. data/doc/rdoc/classes/ESI/Config.src/M000045.html +0 -35
  57. data/doc/rdoc/classes/ESI/Config.src/M000046.html +0 -38
  58. data/doc/rdoc/classes/ESI/Config.src/M000047.html +0 -23
  59. data/doc/rdoc/classes/ESI/Config.src/M000048.html +0 -18
  60. data/doc/rdoc/classes/ESI/Config.src/M000049.html +0 -20
  61. data/doc/rdoc/classes/ESI/Config.src/M000050.html +0 -18
  62. data/doc/rdoc/classes/ESI/Config.src/M000051.html +0 -24
  63. data/doc/rdoc/classes/ESI/Dispatcher.html +0 -172
  64. data/doc/rdoc/classes/ESI/Dispatcher.src/M000062.html +0 -23
  65. data/doc/rdoc/classes/ESI/Dispatcher.src/M000063.html +0 -20
  66. data/doc/rdoc/classes/ESI/Fragment.html +0 -218
  67. data/doc/rdoc/classes/ESI/Fragment.src/M000076.html +0 -21
  68. data/doc/rdoc/classes/ESI/Fragment.src/M000077.html +0 -18
  69. data/doc/rdoc/classes/ESI/Fragment.src/M000078.html +0 -18
  70. data/doc/rdoc/classes/ESI/Handler.html +0 -236
  71. data/doc/rdoc/classes/ESI/Handler.src/M000079.html +0 -19
  72. data/doc/rdoc/classes/ESI/Handler.src/M000080.html +0 -161
  73. data/doc/rdoc/classes/ESI/Handler.src/M000081.html +0 -24
  74. data/doc/rdoc/classes/ESI/Handler.src/M000082.html +0 -18
  75. data/doc/rdoc/classes/ESI/Handler.src/M000083.html +0 -26
  76. data/doc/rdoc/classes/ESI/Handler.src/M000084.html +0 -30
  77. data/doc/rdoc/classes/ESI/Invalidator.html +0 -131
  78. data/doc/rdoc/classes/ESI/Invalidator.src/M000004.html +0 -41
  79. data/doc/rdoc/classes/ESI/Log.html +0 -251
  80. data/doc/rdoc/classes/ESI/Log.src/M000005.html +0 -18
  81. data/doc/rdoc/classes/ESI/Log.src/M000006.html +0 -18
  82. data/doc/rdoc/classes/ESI/Log.src/M000007.html +0 -18
  83. data/doc/rdoc/classes/ESI/Log.src/M000008.html +0 -18
  84. data/doc/rdoc/classes/ESI/Log.src/M000009.html +0 -18
  85. data/doc/rdoc/classes/ESI/Log.src/M000010.html +0 -18
  86. data/doc/rdoc/classes/ESI/Log.src/M000011.html +0 -18
  87. data/doc/rdoc/classes/ESI/Log.src/M000012.html +0 -18
  88. data/doc/rdoc/classes/ESI/Log.src/M000013.html +0 -18
  89. data/doc/rdoc/classes/ESI/MemcachedCache.html +0 -314
  90. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000034.html +0 -24
  91. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000035.html +0 -22
  92. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000036.html +0 -19
  93. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000037.html +0 -23
  94. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000038.html +0 -18
  95. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000039.html +0 -19
  96. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000040.html +0 -18
  97. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000041.html +0 -18
  98. data/doc/rdoc/classes/ESI/MemcachedCache.src/M000042.html +0 -17
  99. data/doc/rdoc/classes/ESI/Router.html +0 -229
  100. data/doc/rdoc/classes/ESI/Router.src/M000073.html +0 -36
  101. data/doc/rdoc/classes/ESI/Router.src/M000074.html +0 -25
  102. data/doc/rdoc/classes/ESI/Router.src/M000075.html +0 -24
  103. data/doc/rdoc/classes/ESI/RubyCache.html +0 -278
  104. data/doc/rdoc/classes/ESI/RubyCache.src/M000064.html +0 -20
  105. data/doc/rdoc/classes/ESI/RubyCache.src/M000065.html +0 -22
  106. data/doc/rdoc/classes/ESI/RubyCache.src/M000066.html +0 -21
  107. data/doc/rdoc/classes/ESI/RubyCache.src/M000067.html +0 -22
  108. data/doc/rdoc/classes/ESI/RubyCache.src/M000068.html +0 -18
  109. data/doc/rdoc/classes/ESI/RubyCache.src/M000069.html +0 -22
  110. data/doc/rdoc/classes/ESI/RubyCache.src/M000070.html +0 -18
  111. data/doc/rdoc/classes/ESI/RubyCache.src/M000071.html +0 -18
  112. data/doc/rdoc/classes/ESI/RubyCache.src/M000072.html +0 -18
  113. data/doc/rdoc/classes/ESI/Tag/Attempt.html +0 -113
  114. data/doc/rdoc/classes/ESI/Tag/Base.html +0 -267
  115. data/doc/rdoc/classes/ESI/Tag/Base.src/M000028.html +0 -26
  116. data/doc/rdoc/classes/ESI/Tag/Base.src/M000029.html +0 -23
  117. data/doc/rdoc/classes/ESI/Tag/Base.src/M000030.html +0 -22
  118. data/doc/rdoc/classes/ESI/Tag/Base.src/M000031.html +0 -18
  119. data/doc/rdoc/classes/ESI/Tag/Base.src/M000032.html +0 -22
  120. data/doc/rdoc/classes/ESI/Tag/Base.src/M000033.html +0 -23
  121. data/doc/rdoc/classes/ESI/Tag/Except.html +0 -184
  122. data/doc/rdoc/classes/ESI/Tag/Except.src/M000020.html +0 -21
  123. data/doc/rdoc/classes/ESI/Tag/Except.src/M000021.html +0 -20
  124. data/doc/rdoc/classes/ESI/Tag/Except.src/M000022.html +0 -18
  125. data/doc/rdoc/classes/ESI/Tag/Include.html +0 -189
  126. data/doc/rdoc/classes/ESI/Tag/Include.src/M000017.html +0 -20
  127. data/doc/rdoc/classes/ESI/Tag/Include.src/M000018.html +0 -18
  128. data/doc/rdoc/classes/ESI/Tag/Include.src/M000019.html +0 -125
  129. data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.html +0 -155
  130. data/doc/rdoc/classes/ESI/Tag/IncludeRequest/Error.src/M000016.html +0 -19
  131. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.html +0 -199
  132. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000014.html +0 -18
  133. data/doc/rdoc/classes/ESI/Tag/IncludeRequest.src/M000015.html +0 -42
  134. data/doc/rdoc/classes/ESI/Tag/Invalidate.html +0 -171
  135. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000025.html +0 -19
  136. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000026.html +0 -51
  137. data/doc/rdoc/classes/ESI/Tag/Invalidate.src/M000027.html +0 -19
  138. data/doc/rdoc/classes/ESI/Tag/Try.html +0 -161
  139. data/doc/rdoc/classes/ESI/Tag/Try.src/M000023.html +0 -40
  140. data/doc/rdoc/classes/ESI/Tag/Try.src/M000024.html +0 -18
  141. data/doc/rdoc/classes/ESI/Tag.html +0 -137
  142. data/doc/rdoc/classes/ESI.html +0 -169
  143. data/doc/rdoc/classes/MultiDirHandler.html +0 -198
  144. data/doc/rdoc/classes/MultiDirHandler.src/M000001.html +0 -20
  145. data/doc/rdoc/classes/MultiDirHandler.src/M000002.html +0 -28
  146. data/doc/rdoc/classes/MultiDirHandler.src/M000003.html +0 -22
  147. data/doc/rdoc/classes/Net/An/HTTP.html +0 -137
  148. data/doc/rdoc/classes/Net/An/HTTP.src/M000087.html +0 -17
  149. data/doc/rdoc/classes/Net/An/IORequest.html +0 -139
  150. data/doc/rdoc/classes/Net/An/IORequest.src/M000088.html +0 -17
  151. data/doc/rdoc/classes/Net/An/IOResponse.html +0 -139
  152. data/doc/rdoc/classes/Net/An/IOResponse.src/M000085.html +0 -17
  153. data/doc/rdoc/classes/Net/An/IOSocket.html +0 -137
  154. data/doc/rdoc/classes/Net/An/IOSocket.src/M000086.html +0 -17
  155. data/doc/rdoc/classes/Net/An.html +0 -114
  156. data/doc/rdoc/classes/Net.html +0 -119
  157. data/doc/rdoc/created.rid +0 -1
  158. data/doc/rdoc/files/COPYING.html +0 -168
  159. data/doc/rdoc/files/LICENSE.html +0 -605
  160. data/doc/rdoc/files/README.html +0 -361
  161. data/doc/rdoc/files/lib/esi/cache_rb.html +0 -113
  162. data/doc/rdoc/files/lib/esi/config_rb.html +0 -108
  163. data/doc/rdoc/files/lib/esi/dispatcher_rb.html +0 -109
  164. data/doc/rdoc/files/lib/esi/handler_rb.html +0 -121
  165. data/doc/rdoc/files/lib/esi/invalidator_rb.html +0 -117
  166. data/doc/rdoc/files/lib/esi/logger_rb.html +0 -108
  167. data/doc/rdoc/files/lib/esi/router_rb.html +0 -101
  168. data/doc/rdoc/files/lib/esi/tag/attempt_rb.html +0 -101
  169. data/doc/rdoc/files/lib/esi/tag/base_rb.html +0 -108
  170. data/doc/rdoc/files/lib/esi/tag/except_rb.html +0 -101
  171. data/doc/rdoc/files/lib/esi/tag/include_rb.html +0 -109
  172. data/doc/rdoc/files/lib/esi/tag/invalidate_rb.html +0 -109
  173. data/doc/rdoc/files/lib/esi/tag/try_rb.html +0 -108
  174. data/doc/rdoc/files/lib/multi_dirhandler_rb.html +0 -109
  175. data/doc/rdoc/files/lib/net/ahttp_rb.html +0 -109
  176. data/doc/rdoc/fr_class_index.html +0 -55
  177. data/doc/rdoc/fr_file_index.html +0 -44
  178. data/doc/rdoc/fr_method_index.html +0 -114
  179. data/doc/rdoc/index.html +0 -24
  180. data/doc/rdoc/rdoc-style.css +0 -208
  181. data/ext/esi/parser.rb +0 -49
  182. data/ext/esi/ruby_esi.rl +0 -135
  183. data/lib/esi/handler.rb +0 -221
  184. data/lib/net/ahttp.rb +0 -36
@@ -1,3 +1,5 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
1
3
  require 'rubygems'
2
4
  gem 'hpricot'
3
5
  require 'hpricot'
data/lib/esi/tag/try.rb CHANGED
@@ -1,3 +1,6 @@
1
+ # Copyright (c) 2008 Todd A. Fisher
2
+ # see LICENSE
3
+
1
4
  require 'esi/logger'
2
5
 
3
6
  module ESI
@@ -25,7 +25,6 @@ class BasicTest < Test::Unit::TestCase
25
25
  :enable_for_surrogate_only => false,
26
26
  :invalidator => false
27
27
  )
28
- handler = ESI::Handler.new(dispatcher)
29
28
  end
30
29
  end
31
30
 
@@ -0,0 +1,10 @@
1
+ <html>
2
+ <head>
3
+ </head>
4
+ <body>
5
+ <h1>This is a test document</h1>
6
+ <div>Some content before</div><esi:include src="/fragments/test1.html" max-age="600+600"/>
7
+ <div>Some content before</div><esi:include src="/content/test2.html" max-age="0+0"/>
8
+ <div>Some content before</div><esi:include src="/content/test2.html" max-age="0"/>
9
+ </body>
10
+ </html>
@@ -177,6 +177,17 @@ class HandlerTest < Test::Unit::TestCase
177
177
  end
178
178
  end
179
179
 
180
+ def test_failing_response_from_surrogate
181
+ Net::HTTP.start("localhost", 9997) do |h|
182
+ res = h.get("/500")
183
+ assert_not_nil res
184
+ assert_not_nil res.header
185
+ assert_not_nil res.body
186
+ assert_equal "<html><body>Internal Server Error</body></html>", res.body
187
+ assert_equal Net::HTTPInternalServerError, res.header.class, res.body
188
+ end
189
+ end
190
+
180
191
  def test_static_failover
181
192
  Net::HTTP.start("localhost", 9997) do |h|
182
193
  res = h.get("/content/static-failover.html")
@@ -216,10 +227,6 @@ class HandlerTest < Test::Unit::TestCase
216
227
  end
217
228
  end
218
229
 
219
- def test_markup_in_except_passed_through
220
- # TODO
221
- end
222
-
223
230
  def test_surrogate_control_header
224
231
  # first tell the esi handler to use the surrogate control header
225
232
  $esi_dispatcher.config.config.send(:store,:enable_for_surrogate_only, true)
@@ -259,12 +266,31 @@ class HandlerTest < Test::Unit::TestCase
259
266
 
260
267
  Net::HTTP.start("localhost", 9997) do |h|
261
268
  res = h.get("/esi_invalidate.html")
269
+ assert_not_nil res
270
+ assert_not_nil res.header
271
+ assert_not_nil res.body
272
+ assert_equal Net::HTTPOK, res.header.class
262
273
  end
263
-
274
+
264
275
  assert !cached?( FRAGMENT_TEST1_URI ), "Error Fragment 1 should not be cached!"
265
276
  assert !cached?( FRAGMENT_TEST2_URI ), "Error Fragment 2 should not be cached!"
266
277
  end
267
278
 
279
+ def test_max_age_include_attribute_cache_ttl
280
+ Net::HTTP.start("localhost", 9997) do |h|
281
+ res = h.get("/esi_max_age_varies.html")
282
+ assert_not_nil res
283
+ assert_not_nil res.header
284
+ assert_not_nil res.body
285
+ assert_equal Net::HTTPOK, res.header.class
286
+ assert_match $fragment_test1, res.body, "Fragment not found"
287
+ assert_match $fragment_test2, res.body, "Fragment not found"
288
+ end
289
+
290
+ assert cached?( FRAGMENT_TEST1_URI ), "Error Fragment should be cached!"
291
+ assert !cached?( FRAGMENT_TEST2_URI ), "Error Fragment should not be cached!"
292
+ end
293
+
268
294
 
269
295
  end
270
296
 
@@ -1,4 +1,5 @@
1
1
  # modified version from mongrel
2
+ require 'rubygems'
2
3
  # This code is moving into integration test folder
3
4
  $:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib")
4
5
  $:.unshift File.join(File.dirname(__FILE__), "..", "..", "ext")
@@ -101,6 +102,16 @@ class Basic404HandlerWithoutHeader < Mongrel::HttpHandler
101
102
  end
102
103
  end
103
104
 
105
+ class Basic500Handler < Mongrel::HttpHandler
106
+ include Mongrel::HttpHandlerPlugin
107
+ def process(request, response)
108
+ response.start(500,true) do |head,out|
109
+ head["Surrogate-Control"] = %q(max-age=0, content="ESI/1.0 ESI-INV/1.0")
110
+ out << %q(<html><body>Internal Server Error</body></html>)
111
+ end
112
+ end
113
+ end
114
+
104
115
  class AjaxCacheHandler < Mongrel::HttpHandler
105
116
  include Mongrel::HttpHandlerPlugin
106
117
  def process(request, response)
@@ -200,7 +211,8 @@ module ESI
200
211
  { :uri => '/post_redirect_test', :handler => PostRedirectHandler.new },
201
212
  { :uri => '/404', :handler => Basic404Handler.new },
202
213
  { :uri => '/404-no-surrogate', :handler => Basic404HandlerWithoutHeader.new },
203
- { :uri => '/invalidate', :handler => InvalidateHandler.new }
214
+ { :uri => '/invalidate', :handler => InvalidateHandler.new },
215
+ { :uri => '/500', :handler => Basic500Handler.new }
204
216
  ]
205
217
  },
206
218
  { :host_port => { :host => '127.0.0.1', :port => 9997 },
data/test/load_test.rb ADDED
@@ -0,0 +1,133 @@
1
+ require 'net/http'
2
+ require 'open-uri'
3
+
4
+ # test the currency load
5
+ class LoadTest
6
+ TEST_HOST='http://127.0.0.1:8000'
7
+ TEST_PATH='/'
8
+ EXPECTED_RESPONSE=File.read(File.join(File.dirname(__FILE__),'sample.html'))
9
+
10
+ def initialize(trials)
11
+ @trials = trials
12
+ @trial = 0
13
+ @reports = {}
14
+ end
15
+
16
+ def request_url
17
+ TEST_HOST + TEST_PATH
18
+ end
19
+
20
+ # see: http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/
21
+ def variance(population)
22
+ n = 0
23
+ mean = 0.0
24
+ s = 0.0
25
+ population.each { |x|
26
+ n = n + 1
27
+ delta = x - mean
28
+ mean = mean + (delta / n)
29
+ s = s + delta * (x - mean)
30
+ }
31
+ # if you want to calculate std deviation
32
+ # of a sample change this to "s / (n-1)"
33
+ return s / (n-1)
34
+ end
35
+
36
+ # calculate the standard deviation of a population
37
+ # accepts: an array, the population
38
+ # returns: the standard deviation
39
+ def standard_deviation(population)
40
+ Math.sqrt(variance(population).abs)
41
+ end
42
+
43
+ def report( type, image_path = "benchmark100.png", font_path="/usr/share/fonts/bitstream-vera/Vera.ttf" )
44
+ require 'rubygems'
45
+ require 'gruff'
46
+ extras = {}
47
+ g = Gruff::Line.new(2048)
48
+ g.title = "MongrelESI Serial vs Parallel"
49
+ g.font = font_path if font_path # my linux system's font
50
+ @reports[type].each do|key,values|
51
+ total = 0
52
+ values.each {|t| total += t }
53
+ # average = total / values.size
54
+ # std = standard_deviation(values)
55
+ g.data(key,values)
56
+ # puts "#{key}: #{average} seconds (#{std})"
57
+ # extras[key] = {:std => std, :average => average}
58
+ end
59
+ labels = {}
60
+ @trials.each_with_index do|t,index|
61
+ labels[index] = t.to_s
62
+ end
63
+ g.labels = labels
64
+ g.write(image_path)
65
+ end
66
+
67
+ def assert_equal( s1, s2 )
68
+ if s1 != s2
69
+ File.open("s1.html","w") do|f|
70
+ f << s1
71
+ end
72
+ File.open("s2.html","w") do|f|
73
+ f << s2
74
+ end
75
+ raise "Error response not matching expected library failure! 's1.html' Not equal to 's2.html'"
76
+ end
77
+ end
78
+
79
+ def assert_not_nil( v )
80
+ raise "Error: value should not be nil!" if v.nil?
81
+ end
82
+
83
+ def test_trial(trials,report_tag,url)
84
+ require 'net/http'
85
+ require 'open-uri'
86
+
87
+ timer = Time.now
88
+ threads = []
89
+
90
+ trials.times do
91
+ threads << Thread.new do
92
+ t = Time.now
93
+ assert_equal( EXPECTED_RESPONSE, open(url).read )
94
+ (Time.now - t)
95
+ end
96
+ end
97
+
98
+ times = []
99
+ threads.each do|t|
100
+ times << t.value
101
+ end
102
+
103
+ duration = Time.now - timer
104
+ #average = (duration / trials)
105
+ average = 0
106
+ times.each { |t| average += t }
107
+ average /= times.size
108
+
109
+ std = standard_deviation(times)
110
+
111
+ puts "Running net/http(#{report_tag}): #{trials} in #{average} seconds (#{std}), #{times.inspect}"
112
+ @reports[:avg]["#{report_tag}"] ||= []
113
+ @reports[:avg]["#{report_tag}"] << average
114
+ @reports[:std]["#{report_tag}"] ||= []
115
+ @reports[:std]["#{report_tag}"] << std
116
+ @reports[:raw]["#{report_tag}-#{trials}"] ||= []
117
+ @reports[:raw]["#{report_tag}-#{trials}"] += times
118
+ end
119
+
120
+ def run
121
+ @reports = {:avg => {}, :std => {}, :raw => {}}
122
+ @trials.each do|trial|
123
+ test_trial(trial,:piped,'http://127.0.0.1:8000/')
124
+ test_trial(trial,:serial,'http://127.0.0.1:8001/')
125
+ end
126
+ end
127
+ end
128
+
129
+ test = LoadTest.new([2,5,10]) #,80,100,200,300,400])
130
+ test.run
131
+ test.report(:avg, 'benchmark-averages-50.png')
132
+ test.report(:std, 'benchmark-std-50.png')
133
+ test.report(:raw, 'benchmark-times-50.png')
@@ -4,7 +4,7 @@ class IncludeRequestTest < Test::Unit::TestCase
4
4
  include TestServer
5
5
 
6
6
  def request(path,alt=nil,headers={})
7
- ir = ESI::Tag::IncludeRequest.new(headers)
7
+ ir = ESI::Tag::Include::Request.new(headers)
8
8
  buffer = ""
9
9
  status = 0
10
10
  info = nil
@@ -1,9 +1,10 @@
1
1
  require File.join(File.dirname(__FILE__),'help.rb')
2
+ require 'esi/response'
2
3
 
3
4
  $run_sample_once = false
4
5
  class ParseOutputTest < Test::Unit::TestCase
5
6
  include TestServer
6
-
7
+
7
8
  def setup_extra
8
9
  @sample_file = File.join(File.dirname(__FILE__),'esi-sample.html')
9
10
  if !$run_sample_once
@@ -28,7 +29,7 @@ class ParseOutputTest < Test::Unit::TestCase
28
29
  @parser.esi_tag.close(@parser.output)
29
30
  rescue Object => e
30
31
  puts @parser.esi_tag.name
31
- puts e.message
32
+ puts e.message, e.backtrace.join("\n")
32
33
  end
33
34
  @parser.esi_tag = nil
34
35
  else
@@ -102,9 +103,19 @@ class ParseOutputTest < Test::Unit::TestCase
102
103
  assert_equal input, output
103
104
  end
104
105
 
106
+ class OutputAdapter
107
+ def initialize(output)
108
+ @output = output
109
+ end
110
+ def << (msg)
111
+ @output.call msg
112
+ end
113
+ end
114
+
105
115
  def test_with_tags
106
116
  sample = @sample_file
107
117
  cache = ESI::RubyCache.new
118
+
108
119
  File.open('out-sample.html','w') do|output|
109
120
  parser = ESI::CParser.new
110
121
  parser.output_handler {|s| output << s }
@@ -120,10 +131,10 @@ class ParseOutputTest < Test::Unit::TestCase
120
131
 
121
132
  parser.end_tag_handler do|tag_name|
122
133
  if parser.esi_tag.name == tag_name.gsub(/esi:/,'')
123
- parser.esi_tag.close(parser.output)
134
+ parser.esi_tag.close(OutputAdapter.new(parser.output))
124
135
  parser.esi_tag = nil
125
136
  else
126
- parser.esi_tag.close_child(parser.output,tag_name)
137
+ parser.esi_tag.close_child(OutputAdapter.new(parser.output),tag_name)
127
138
  end
128
139
  end
129
140
  File.open(sample,'r') do|input|
@@ -245,7 +256,7 @@ some inputsome more input<br/>
245
256
  parser.start_tag_handler do|tag_name, attrs|
246
257
  tags << {:name => tag_name, :attributes => attrs}
247
258
  end
248
- parser.process "<p>some input</p><esi:include/>some more input\nsome input<esi:include src='hello'/>some more input"
259
+ parser.process "<p>some input</p><esi:include />some more input\nsome input<esi:include src='hello'/>some more input"
249
260
  parser.finish
250
261
  assert_equal %Q(<p>some input</p>some more input
251
262
  some inputsome more input), output
@@ -471,6 +482,31 @@ input = %Q(
471
482
  assert end_called
472
483
  end
473
484
 
485
+ def test_attribute_values
486
+ output = ""
487
+ parser = ESI::CParser.new
488
+ parser.output_handler {|s| output << s }
489
+ parser.process 'start:<esi:include src="foobar?hi=cool"/>:finish'
490
+ parser.finish
491
+ assert_equal "start::finish", output
492
+ output = ""
493
+ parser.process 'start:<esi:include src="foo bar"/>:finish'
494
+ parser.finish
495
+ assert_equal "start::finish", output
496
+ output = ""
497
+ parser.process 'start:<esi:include src="foobar?hi=!@#$%^&*()-+~`"/>:finish'
498
+ parser.finish
499
+ assert_equal "start::finish", output
500
+ output = ""
501
+ parser.process 'start:<esi:try src="foobar?hi=!@#$%^&*()-+~`">cool</esi:try>:finish'
502
+ parser.finish
503
+ assert_equal "start:cool:finish", output
504
+ output = ""
505
+ parser.process 'start:<esi:try>cool</esi:try>:finish'
506
+ parser.finish
507
+ assert_equal "start:cool:finish", output
508
+ end
509
+
474
510
  # def test_setup
475
511
  # puts @output
476
512
  # end
@@ -0,0 +1,184 @@
1
+ require File.join(File.dirname(__FILE__),'help.rb')
2
+
3
+ require 'esi/response'
4
+ require 'esi/esi'
5
+
6
+ class ResponseTest < Test::Unit::TestCase
7
+
8
+ def test_response_to_response
9
+ output = StringIO.new
10
+
11
+ r1 = ESI::Response.new( output )
12
+ r2 = ESI::Response.new( r1.active_buffer )
13
+
14
+ buffer = r2.reserve_buffer
15
+ t = Thread.new do
16
+ buffer << "hello"
17
+ sleep(0.01) # make it count
18
+ buffer.close_write
19
+ end
20
+
21
+ r2.wait_thread(t)
22
+
23
+ r2.flush
24
+
25
+ r1.flush
26
+
27
+ output.rewind
28
+
29
+ assert_equal "hello", output.read
30
+
31
+ end
32
+
33
+ def test_esi_parser
34
+ output = []
35
+ @response = ESI::Response.new( output )
36
+ @parser = ESI::CParser.new
37
+ @count = 0
38
+
39
+ @parser.end_tag_handler do|tag_name|
40
+ @response.close_active_buffer
41
+ tag_buffer = @response.reserve_buffer
42
+ thread = Thread.new(tag_buffer,@count) do|buffer,count|
43
+ buffer << "#{count}: sample"
44
+ buffer.close_write
45
+ end
46
+ @response.wait_thread( thread )
47
+ end
48
+
49
+ input = StringIO.new(INPUT_STREAM)
50
+ lines = input.readlines
51
+
52
+ @parser.output_handler do|chars|
53
+ @response.open_active_buffer
54
+ @response.active_buffer << chars
55
+ @response.send if @response.back_buffer_ready? or @response.active_buffer.size > 1024
56
+ end
57
+
58
+ for line in lines do
59
+ @parser.process line
60
+ @count += 1
61
+ end
62
+
63
+ @parser.finish
64
+ @response.flush
65
+ # puts output.join("")
66
+ # puts output.join("").split("\n").size
67
+
68
+ # break it back up into lines
69
+ lines = output.join("").split("\n")
70
+ assert_equal 35, lines.size
71
+
72
+ assert_match(/hello there world/,lines[1])
73
+ assert_match(/sample/,lines[3])
74
+ assert_match(/sample/,lines[7])
75
+ assert_match(/sample/,lines[13])
76
+ assert_match(/and some more here/,lines[15])
77
+ assert_match(/sample/,lines[19])
78
+ assert_match(/sample/,lines[20])
79
+ assert_match(/sample/,lines[21])
80
+ assert_match(/sample/,lines[22])
81
+ assert_match(/and some more here/,lines[24])
82
+ assert_match(/sample/,lines[25])
83
+ assert_match(/sample/,lines[31])
84
+
85
+ end
86
+
87
+ def test_sample
88
+ lines = INPUT_STREAM.split("\n")
89
+
90
+ timer = Time.now
91
+ request_delay = 0.01 # each request takes
92
+ request_vary = 0.0005 # the request delay varies
93
+ response_delay = 0.00005 # the delay in reading the surrogate request
94
+ output = []
95
+ response = ESI::Response.new( output )
96
+
97
+ count = 0
98
+
99
+ lines.each do|line|
100
+ line += "\n"
101
+
102
+ sleep response_delay
103
+
104
+ if line.match(/<esi:/)
105
+ response.close_active_buffer
106
+ msg_buffer = response.reserve_buffer
107
+
108
+ thread = Thread.new(msg_buffer,count) do|buffer,count|
109
+ sleep( (request_delay + (rand > 0.5 ? (-1* request_vary) : request_vary)).abs) # some busy work
110
+ message = "#{count}: sample\n"
111
+ buffer << message
112
+ buffer.close_write
113
+ end
114
+
115
+ response.wait_thread( thread )
116
+ else
117
+ response.open_active_buffer
118
+ response.active_buffer << "#{count}: #{line}"
119
+ end
120
+ count += 1
121
+ response.send if response.back_buffer_ready? or response.active_buffer.size > 1024
122
+ end
123
+
124
+ response.flush
125
+
126
+ output = output.join("").split("\n")
127
+
128
+ assert_equal 35, output.size
129
+ assert_match(/\s/,output[0])
130
+ assert_match(/hello there world/,output[1])
131
+ assert_match(/sample/,output[3])
132
+ assert_match(/sample/,output[7])
133
+ assert_match(/sample/,output[13])
134
+ assert_match(/and some more here/,output[15])
135
+ assert_match(/sample/,output[19])
136
+ assert_match(/sample/,output[20])
137
+ assert_match(/sample/,output[21])
138
+ assert_match(/sample/,output[22])
139
+ assert_match(/and some more here/,output[24])
140
+ assert_match(/sample/,output[25])
141
+ assert_match(/sample/,output[31])
142
+ assert_match(/\s/,output[34])
143
+
144
+ #puts output.join("\n")
145
+ #puts "total time: #{Time.now - timer} seconds, with a request delay of #{request_delay} seconds with variance of #{request_vary} and total of #{count} lines taking #{response_delay} seconds each to read."
146
+ end
147
+
148
+ # define a sample buffer here:
149
+ INPUT_STREAM = %Q(
150
+ hello there world
151
+
152
+ <esi:include src='/foo/'/>
153
+
154
+ some more bytes here
155
+
156
+ <esi:include src='/bar/'/>
157
+
158
+ and some more here
159
+
160
+ some more bytes here
161
+
162
+ <esi:include src='/bar/'/>
163
+
164
+ and some more here
165
+
166
+ some more bytes here
167
+
168
+ <esi:include src='/bar/'/>
169
+ <esi:include src='/bar/'/>
170
+ <esi:include src='/bar/'/>
171
+ <esi:include src='/bar/'/>
172
+
173
+ and some more here
174
+ <esi:include src='/bar/'/>
175
+
176
+ and some more here
177
+
178
+ some more bytes here
179
+
180
+ <esi:include src='/bar/'/>
181
+
182
+ and some more here
183
+ )
184
+ end