mongrel_esi 0.4.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.
- data/COPYING +53 -0
- data/LICENSE +471 -0
- data/README +186 -0
- data/Rakefile +141 -0
- data/bin/mongrel_esi +271 -0
- data/ext/esi/common.rl +41 -0
- data/ext/esi/esi_parser.c +387 -0
- data/ext/esi/extconf.rb +6 -0
- data/ext/esi/machine.rb +499 -0
- data/ext/esi/parser.c +1675 -0
- data/ext/esi/parser.h +113 -0
- data/ext/esi/parser.rb +49 -0
- data/ext/esi/parser.rl +398 -0
- data/ext/esi/ruby_esi.rl +135 -0
- data/ext/esi/run-test.rb +3 -0
- data/ext/esi/test/common.rl +41 -0
- data/ext/esi/test/parser.c +1676 -0
- data/ext/esi/test/parser.h +113 -0
- data/ext/esi/test/parser.rl +398 -0
- data/ext/esi/test/test.c +373 -0
- data/ext/esi/test1.rb +56 -0
- data/ext/esi/test2.rb +45 -0
- data/lib/esi/cache.rb +207 -0
- data/lib/esi/config.rb +154 -0
- data/lib/esi/dispatcher.rb +27 -0
- data/lib/esi/handler.rb +236 -0
- data/lib/esi/invalidator.rb +40 -0
- data/lib/esi/logger.rb +46 -0
- data/lib/esi/router.rb +84 -0
- data/lib/esi/tag/attempt.rb +6 -0
- data/lib/esi/tag/base.rb +85 -0
- data/lib/esi/tag/except.rb +24 -0
- data/lib/esi/tag/include.rb +190 -0
- data/lib/esi/tag/invalidate.rb +54 -0
- data/lib/esi/tag/try.rb +40 -0
- data/lib/multi_dirhandler.rb +70 -0
- data/setup.rb +1585 -0
- data/test/integration/basic_test.rb +39 -0
- data/test/integration/cache_test.rb +37 -0
- data/test/integration/docs/content/500.html +16 -0
- data/test/integration/docs/content/500_with_failover.html +16 -0
- data/test/integration/docs/content/500_with_failover_to_alt.html +8 -0
- data/test/integration/docs/content/ajax_test_page.html +15 -0
- data/test/integration/docs/content/cookie_variable.html +3 -0
- data/test/integration/docs/content/foo.html +15 -0
- data/test/integration/docs/content/include_in_include.html +15 -0
- data/test/integration/docs/content/malformed_transforms.html +16 -0
- data/test/integration/docs/content/malformed_transforms.html-correct +11 -0
- data/test/integration/docs/content/static-failover.html +20 -0
- data/test/integration/docs/content/test2.html +1 -0
- data/test/integration/docs/content/test3.html +17 -0
- data/test/integration/docs/esi_invalidate.html +6 -0
- data/test/integration/docs/esi_mixed_content.html +15 -0
- data/test/integration/docs/esi_test_content.html +27 -0
- data/test/integration/docs/index.html +688 -0
- data/test/integration/docs/test1.html +1 -0
- data/test/integration/docs/test3.html +9 -0
- data/test/integration/docs/test_failover.html +1 -0
- data/test/integration/handler_test.rb +270 -0
- data/test/integration/help.rb +234 -0
- data/test/net/get_test.rb +197 -0
- data/test/net/net_helper.rb +16 -0
- data/test/net/server_test.rb +249 -0
- data/test/unit/base_tag_test.rb +44 -0
- data/test/unit/esi-sample.html +56 -0
- data/test/unit/help.rb +77 -0
- data/test/unit/include_request_test.rb +69 -0
- data/test/unit/include_tag_test.rb +14 -0
- data/test/unit/parser_test.rb +478 -0
- data/test/unit/router_test.rb +34 -0
- data/test/unit/sample.html +21 -0
- data/tools/rakehelp.rb +119 -0
- metadata +182 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'help.rb')
|
2
|
+
|
3
|
+
class BaseTagTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def tag_with_request( http_params = {} )
|
6
|
+
ESI::Tag::Base.new(@test_router,http_params, {},'test',{},{})
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_prepare_url_vars
|
10
|
+
# test happy path
|
11
|
+
value = 'foo'
|
12
|
+
url = tag_with_request({'HTTP_COOKIE' => "type=#{value}"}).prepare_url_vars( "http://www.example.com/$(HTTP_COOKIE{type})/hello.gif" )
|
13
|
+
assert_equal "http://www.example.com/#{value}/hello.gif", url
|
14
|
+
# test empty cookie value
|
15
|
+
value = ''
|
16
|
+
url = tag_with_request({'HTTP_COOKIE' => "type=#{value}"}).prepare_url_vars( "http://www.example.com/$(HTTP_COOKIE{type})/hello.gif" )
|
17
|
+
assert_equal "http://www.example.com/#{value}/hello.gif", url
|
18
|
+
# test no cookie http key
|
19
|
+
url = tag_with_request.prepare_url_vars( "http://www.example.com/$(HTTP_COOKIE{type})/hello.gif")
|
20
|
+
assert_equal "http://www.example.com//hello.gif", url
|
21
|
+
|
22
|
+
# test a funky variable that's not supported
|
23
|
+
url = tag_with_request.prepare_url_vars( "http://www.example.com/$(H_COOKIE{type})/hello.gif")
|
24
|
+
assert_equal "http://www.example.com//hello.gif", url
|
25
|
+
|
26
|
+
# test a syntax error
|
27
|
+
url = tag_with_request.prepare_url_vars( "http://www.example.com/$(H_COOKIE{type}/hello.gif")
|
28
|
+
assert_equal "http://www.example.com/$(H_COOKIE{type}/hello.gif", url
|
29
|
+
|
30
|
+
# test multiple variables in the URL
|
31
|
+
v1 = 'foo'
|
32
|
+
v2 = 'bar'
|
33
|
+
url = tag_with_request({'HTTP_COOKIE' => "type=#{v1};type2=#{v2}"}).prepare_url_vars( "http://www.example.com/$(HTTP_COOKIE{type})/$(HTTP_COOKIE{type2}).gif")
|
34
|
+
assert_equal "http://www.example.com/#{v1}/#{v2}.gif", url
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_bug_fix_for_complex_url
|
38
|
+
url = "/content/modules/head/header_contents?pma_module_id=head%2Fheader_contents&cache_ttl=600&display_signin=true&pma_request=true&view=header_contents&display_search=true&q_module_wrap=block&b2bid=$(HTTP_COOKIE{b2bid})"
|
39
|
+
assert_match /b2b_expected/, tag_with_request({"HTTP_COOKIE" => "b2bid=b2b_expected;edn=reg_expected"}).prepare_url_vars(url)
|
40
|
+
url = "/registration/modules/mini_dashboard/show?cache_ttl=600&pma_module_id=mini_dashboard%2Fshow&q_module_wrap=block&pma_request=true&edn=$(HTTP_COOKIE{edn})"
|
41
|
+
assert_match /reg_expected/, tag_with_request({"HTTP_COOKIE" => "b2bid=b2b_expected;edn=reg_expected"}).prepare_url_vars(url)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
2
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
3
|
+
<head>
|
4
|
+
<title>Something else</title>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<![CDATA[
|
8
|
+
Some cdata fun fun fun
|
9
|
+
]]>
|
10
|
+
<h1>hello</h1>
|
11
|
+
<div class="body">
|
12
|
+
<esi:include src="/test/success?id=1"/>
|
13
|
+
<div>some content</div>
|
14
|
+
<!-- a little commentary -->
|
15
|
+
<!-- a
|
16
|
+
multiline comment -->
|
17
|
+
<esi:try>
|
18
|
+
<esi:attempt>
|
19
|
+
<esi:include src="/test/success?id=2"/>
|
20
|
+
</esi:attempt>
|
21
|
+
<esi:except>
|
22
|
+
<p>it failed</p>
|
23
|
+
<esi:include src="/test/success?id=2"/>
|
24
|
+
</esi:except>
|
25
|
+
</esi:try>
|
26
|
+
<esi:include src="/test/success?id=3"/>
|
27
|
+
<esi:try>
|
28
|
+
<esi:attempt>
|
29
|
+
<p>We should get this or not?</p>
|
30
|
+
<esi:include src="/test/error"/>
|
31
|
+
<p>Now maybe we shouldn't see this?</p>
|
32
|
+
</esi:attempt>
|
33
|
+
<esi:except>
|
34
|
+
<p>except worked1</p>
|
35
|
+
<esi:include src="/test/success?id=4"/>
|
36
|
+
<p>except worked2</p>
|
37
|
+
</esi:except>
|
38
|
+
</esi:try>
|
39
|
+
|
40
|
+
<em>Support for em tags since they have an initial start sequence similar to and <esi: start/end sequence</em>
|
41
|
+
|
42
|
+
<esi:invalidate>
|
43
|
+
<?xml version="1.0"?>
|
44
|
+
<!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
|
45
|
+
<INVALIDATION VERSION="WCS-1.1">
|
46
|
+
<OBJECT>
|
47
|
+
<BASICSELECTOR URI="/test/success?id=1"/>
|
48
|
+
<ACTION REMOVALTTL="0"/>
|
49
|
+
<INFO VALUE="invalidating fragment test 1"/>
|
50
|
+
</OBJECT>
|
51
|
+
</INVALIDATION>
|
52
|
+
</esi:invalidate>
|
53
|
+
|
54
|
+
</div>
|
55
|
+
</body>
|
56
|
+
</html>
|
data/test/unit/help.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib")
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "..", "ext")
|
3
|
+
require 'test/unit'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'mongrel'
|
6
|
+
require 'mocha'
|
7
|
+
|
8
|
+
ENV["test"] = 'true'
|
9
|
+
require 'esi/cache'
|
10
|
+
require 'esi/router'
|
11
|
+
require 'esi/esi'
|
12
|
+
require 'esi/tag/base'
|
13
|
+
require 'esi/tag/include'
|
14
|
+
require 'esi/tag/attempt'
|
15
|
+
require 'esi/tag/except'
|
16
|
+
require 'esi/tag/try'
|
17
|
+
require 'esi/tag/invalidate'
|
18
|
+
|
19
|
+
require 'webrick'
|
20
|
+
class ::WEBrick::HTTPServer ; def access_log(config, req, res) ; end ; end
|
21
|
+
class ::WEBrick::BasicLog ; def log(level, data) ; end ; end
|
22
|
+
|
23
|
+
module TestServer
|
24
|
+
def setup
|
25
|
+
@server = WEBrick::HTTPServer.new( :Port => 99999 )
|
26
|
+
|
27
|
+
|
28
|
+
# setup test server (simulates exact target)
|
29
|
+
@server.mount_proc("/test/error") do|req,res|
|
30
|
+
raise "fail"
|
31
|
+
end
|
32
|
+
@server.mount_proc("/test/redirect") do|req,res|
|
33
|
+
res.set_redirect(WEBrick::HTTPStatus::MovedPermanently,"/test/success")
|
34
|
+
end
|
35
|
+
@server.mount_proc("/test/redirect_to_error") do|req,res|
|
36
|
+
res.set_redirect(WEBrick::HTTPStatus::MovedPermanently,"/test/error")
|
37
|
+
end
|
38
|
+
@server.mount_proc("/test/success") do|req,res|
|
39
|
+
id = req.query["id"]
|
40
|
+
if id
|
41
|
+
res.body = "<div id='#{id}'>id string</div>"
|
42
|
+
else
|
43
|
+
res.body = "<div>hello there world</div>"
|
44
|
+
end
|
45
|
+
res['Content-Type'] = "text/html"
|
46
|
+
end
|
47
|
+
@server.mount_proc("/test/timeout") do|req,res|
|
48
|
+
sleep 0.8 # needs to be high for slower machines, like my ppc mac
|
49
|
+
res.body = "<div>We won't get this for a few seconds</div>"
|
50
|
+
res['Content-Type'] = "text/html"
|
51
|
+
end
|
52
|
+
@server.mount_proc("/test/headers") do|req,res|
|
53
|
+
res.body = "<div>hello there world</div>"
|
54
|
+
res['Content-Type'] = "text/html"
|
55
|
+
begin
|
56
|
+
assert_equal ['value1'], req.header['headers1']
|
57
|
+
assert_equal ['value2'], req.header['headers2']
|
58
|
+
rescue Object => e
|
59
|
+
puts e.message
|
60
|
+
raise e
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# start up the server in a background thread
|
65
|
+
@thread = Thread.new(@server) do|server|
|
66
|
+
server.start
|
67
|
+
end
|
68
|
+
|
69
|
+
@test_router = ESI::Router.new([{:host => '127.0.0.1', :port => '99999', :match_url => 'default'}])
|
70
|
+
|
71
|
+
setup_extra if self.respond_to?(:setup_extra)
|
72
|
+
end
|
73
|
+
def teardown
|
74
|
+
@server.shutdown
|
75
|
+
@thread.join
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'help.rb')
|
2
|
+
|
3
|
+
class IncludeRequestTest < Test::Unit::TestCase
|
4
|
+
include TestServer
|
5
|
+
|
6
|
+
def request(path,alt=nil,headers={})
|
7
|
+
ir = ESI::Tag::IncludeRequest.new(headers)
|
8
|
+
buffer = ""
|
9
|
+
status = 0
|
10
|
+
info = nil
|
11
|
+
alt = "http://127.0.0.1:99999#{alt}" if alt
|
12
|
+
ir.request("http://127.0.0.1:99999#{path}",0.5,alt) do|s,r|
|
13
|
+
if s
|
14
|
+
buffer = r.read_body
|
15
|
+
status = 1
|
16
|
+
else
|
17
|
+
info = r.message
|
18
|
+
buffer = r.response.read_body if r.response
|
19
|
+
end
|
20
|
+
end
|
21
|
+
[buffer,info,status]
|
22
|
+
end
|
23
|
+
|
24
|
+
# happy paths
|
25
|
+
def test_success
|
26
|
+
ri = request('/test/success')
|
27
|
+
assert_equal 1, ri[2], "Request failed\n#{ri[0]}"
|
28
|
+
assert_equal %Q(<div>hello there world</div>), ri[0], "Request failed"
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_redirect
|
32
|
+
ri = request('/test/redirect')
|
33
|
+
assert_equal 1, ri[2], "Request failed\n#{ri[0]}"
|
34
|
+
assert_equal %Q(<div>hello there world</div>), ri[0], "Request failed"
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_error_alt
|
38
|
+
ri = request('/test/error','/test/success')
|
39
|
+
assert_equal 1, ri[2], "Request failed\n#{ri[0]}"
|
40
|
+
assert_equal %Q(<div>hello there world</div>), ri[0], "Request failed"
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_error_no_alt
|
44
|
+
ri = request('/test/error')
|
45
|
+
assert_equal 0, ri[2], "Request should have failed\n#{ri[0]}"
|
46
|
+
end
|
47
|
+
|
48
|
+
# not so happy paths
|
49
|
+
def test_error_error_alt
|
50
|
+
ri = request('/test/error','/test/error')
|
51
|
+
assert_equal 0, ri[2], "Request should have failed\n#{ri[0]}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_redirect_failed_to_alt
|
55
|
+
ri = request('/test/redirect_to_error','/test/redirect_to_error')
|
56
|
+
assert_equal 0, ri[2], "Request should have failed\n#{ri[0]}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_request_timesout
|
60
|
+
ri = request('/test/timeout')
|
61
|
+
assert_equal 0, ri[2], "Request should have failed\n#{ri[0]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_headers_forward
|
65
|
+
ri = request('/test/headers',nil,{'Headers1' => 'value1', 'Headers2' => 'value2'})
|
66
|
+
assert_equal 1, ri[2], "Request should not have failed\n#{ri[0]}"
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'help.rb')
|
2
|
+
|
3
|
+
class IncludeTagTest < Test::Unit::TestCase
|
4
|
+
include TestServer
|
5
|
+
def test_close
|
6
|
+
|
7
|
+
output = ""
|
8
|
+
include_tag = ESI::Tag::Base.create(@test_router, {}, {},
|
9
|
+
'include', {'src'=>"/test/success/"},
|
10
|
+
ESI::RubyCache.new)
|
11
|
+
include_tag.close(output)
|
12
|
+
assert_equal("<div>hello there world</div>",output)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,478 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'help.rb')
|
2
|
+
|
3
|
+
$run_sample_once = false
|
4
|
+
class ParseOutputTest < Test::Unit::TestCase
|
5
|
+
include TestServer
|
6
|
+
|
7
|
+
def setup_extra
|
8
|
+
@sample_file = File.join(File.dirname(__FILE__),'esi-sample.html')
|
9
|
+
if !$run_sample_once
|
10
|
+
File.open('out-sample.html','w') do|output|
|
11
|
+
@cache = ESI::RubyCache.new
|
12
|
+
@parser = ESI::CParser.new
|
13
|
+
@parser.output = output
|
14
|
+
|
15
|
+
@parser.start_tag_handler do|tag_name,attrs|
|
16
|
+
tag = ESI::Tag::Base.create(@test_router, {}, {}, tag_name.gsub(/esi:/,''), attrs, @cache)
|
17
|
+
if @parser.esi_tag
|
18
|
+
@parser.esi_tag.add_child(tag)
|
19
|
+
else
|
20
|
+
@parser.esi_tag = tag
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@parser.end_tag_handler do|tag_name|
|
25
|
+
#puts "match: '#{@parser.esi_tag.name}' with '#{tag_name.gsub(/esi:/,'')}'"
|
26
|
+
if @parser.esi_tag.name == tag_name.gsub(/esi:/,'')
|
27
|
+
begin
|
28
|
+
@parser.esi_tag.close(@parser.output)
|
29
|
+
rescue Object => e
|
30
|
+
puts @parser.esi_tag.name
|
31
|
+
puts e.message
|
32
|
+
end
|
33
|
+
@parser.esi_tag = nil
|
34
|
+
else
|
35
|
+
@parser.esi_tag.close_child(@parser.output,tag_name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
File.open( @sample_file,'r') do|input|
|
40
|
+
while( (buf=input.read(128)) and !input.eof? and buf.size != 0 )
|
41
|
+
@parser.process buf
|
42
|
+
end
|
43
|
+
@parser.process buf
|
44
|
+
end
|
45
|
+
@parser.finish
|
46
|
+
end
|
47
|
+
|
48
|
+
$run_sample_once = true
|
49
|
+
end
|
50
|
+
@output=File.read('out-sample.html')
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_ouput_body
|
54
|
+
assert_match(/ <div class="body">/, @output)
|
55
|
+
end
|
56
|
+
def test_ouput_some_content
|
57
|
+
assert_match(/ <div>some content<\/div>/, @output)
|
58
|
+
end
|
59
|
+
def test_output_comments
|
60
|
+
assert_match(/ <!-- a little commentary -->/, @output)
|
61
|
+
assert_match(%q(<!-- a
|
62
|
+
multiline comment -->),@output)
|
63
|
+
end
|
64
|
+
def test_output_cdata
|
65
|
+
assert_match(%q(<![CDATA[
|
66
|
+
Some cdata fun fun fun
|
67
|
+
]]>), @output)
|
68
|
+
end
|
69
|
+
def test_output_doctype
|
70
|
+
assert_match(/<!DOCTYPE html PUBLIC "-\/\/W3C\/\/DTD XHTML 1.0 Strict\/\/EN" "http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-strict.dtd">/, @output)
|
71
|
+
end
|
72
|
+
def test_output_complete
|
73
|
+
assert_match(/<\/html>/, @output)
|
74
|
+
end
|
75
|
+
def test_output_no_esi_tags
|
76
|
+
assert_no_match(/<esi:/, @output)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_includes_appeared
|
80
|
+
assert_match(/<div id='1'>id string<\/div>/, @output)
|
81
|
+
assert_match(/<div id='3'>id string<\/div>/, @output)
|
82
|
+
|
83
|
+
assert_no_match(/<p>it failed<\/p>/, @output)
|
84
|
+
assert_match(/<div id='2'>id string<\/div>/, @output)
|
85
|
+
|
86
|
+
assert_match(/<div id='4'>id string<\/div>/, @output)
|
87
|
+
assert_match(/<p>We should get this or not\?<\/p>/, @output)
|
88
|
+
assert_match(/<p>Now maybe we shouldn't see this\?<\/p>/, @output)
|
89
|
+
assert_match(/<p>except worked1<\/p>/, @output)
|
90
|
+
assert_match(/<p>except worked2<\/p>/, @output)
|
91
|
+
|
92
|
+
assert_match(/<em>Support for em tags since they have an initial start sequence similar to and <esi: start\/end sequence<\/em>/, @output )
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_content_echoing
|
96
|
+
output = ""
|
97
|
+
parser = ESI::CParser.new
|
98
|
+
input = "<em>Support for em tags since they have an initial start sequence similar to and <esi: start/end sequence</em>"
|
99
|
+
parser.output_handler {|s| output << s }
|
100
|
+
parser.process input
|
101
|
+
parser.finish
|
102
|
+
assert_equal input, output
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_with_tags
|
106
|
+
sample = @sample_file
|
107
|
+
cache = ESI::RubyCache.new
|
108
|
+
File.open('out-sample.html','w') do|output|
|
109
|
+
parser = ESI::CParser.new
|
110
|
+
parser.output_handler {|s| output << s }
|
111
|
+
|
112
|
+
parser.start_tag_handler do|tag_name,attrs|
|
113
|
+
tag = ESI::Tag::Base.create(@test_router, {}, {}, tag_name.gsub(/esi:/,''), attrs, cache)
|
114
|
+
if parser.esi_tag
|
115
|
+
parser.esi_tag.add_child(tag)
|
116
|
+
else
|
117
|
+
parser.esi_tag = tag
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
parser.end_tag_handler do|tag_name|
|
122
|
+
if parser.esi_tag.name == tag_name.gsub(/esi:/,'')
|
123
|
+
parser.esi_tag.close(parser.output)
|
124
|
+
parser.esi_tag = nil
|
125
|
+
else
|
126
|
+
parser.esi_tag.close_child(parser.output,tag_name)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
File.open(sample,'r') do|input|
|
130
|
+
while( (buf=input.read(128)) and !input.eof? and buf.size != 0 )
|
131
|
+
parser.process buf
|
132
|
+
end
|
133
|
+
parser.process buf
|
134
|
+
end
|
135
|
+
parser.finish
|
136
|
+
end
|
137
|
+
output = File.read("out-sample.html")
|
138
|
+
|
139
|
+
assert_match(/ <div class="body">/, output)
|
140
|
+
assert_match(/ <div>some content<\/div>/, output)
|
141
|
+
assert_match(/ <!-- a little commentary -->/, output)
|
142
|
+
assert_match(%q(<!-- a
|
143
|
+
multiline comment -->),output)
|
144
|
+
assert_match(%q(<![CDATA[
|
145
|
+
Some cdata fun fun fun
|
146
|
+
]]>), output)
|
147
|
+
assert_match(/<!DOCTYPE html PUBLIC "-\/\/W3C\/\/DTD XHTML 1.0 Strict\/\/EN" "http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-strict.dtd">/, output)
|
148
|
+
assert_no_match(/<esi:/, output)
|
149
|
+
assert_match(/<div id='1'>id string<\/div>/, output)
|
150
|
+
assert_match(/<div id='3'>id string<\/div>/, output)
|
151
|
+
|
152
|
+
assert_no_match(/<p>it failed<\/p>/, output)
|
153
|
+
assert_match(/<div id='2'>id string<\/div>/, output)
|
154
|
+
|
155
|
+
assert_match(/<div id='4'>id string<\/div>/, output)
|
156
|
+
assert_match(/<p>We should get this or not\?<\/p>/, output)
|
157
|
+
assert_match(/<p>Now maybe we shouldn't see this\?<\/p>/, output)
|
158
|
+
assert_match(/<p>except worked1<\/p>/, output)
|
159
|
+
assert_match(/<p>except worked2<\/p>/, output)
|
160
|
+
assert_match(/<\/html>/, output)
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_inline_parse_basics
|
164
|
+
output = ""
|
165
|
+
parser = ESI::CParser.new
|
166
|
+
parser.output_handler {|s| output << s }
|
167
|
+
tags = []
|
168
|
+
parser.start_tag_handler do|tag_name, attrs|
|
169
|
+
tags << {:name => tag_name, :attributes => attrs}
|
170
|
+
end
|
171
|
+
|
172
|
+
parser.process "<html><head><body><esi:include timeout='1' max-age='600+600' src=\"hello\"/>some more input"
|
173
|
+
parser.process "some input<esi:include \nsrc='hello'/>some more input\nsome input<esi:include src=\"hello\"/>some more input"
|
174
|
+
parser.process "some input<esi:inline src='hello'/>some more input\nsome input<esi:comment text='hello'/>some more input"
|
175
|
+
parser.process "<p>some input</p><esi:include src='hello'/>some more input\nsome input<esi:include src='hello'/>some more input"
|
176
|
+
parser.process "</body></html>"
|
177
|
+
parser.finish
|
178
|
+
assert_equal %Q(<html><head><body>some more inputsome inputsome more input
|
179
|
+
some inputsome more inputsome inputsome more input
|
180
|
+
some inputsome more input<p>some input</p>some more input
|
181
|
+
some inputsome more input</body></html>), output
|
182
|
+
|
183
|
+
assert_equal 7, tags.size
|
184
|
+
include_tags = tags.select {|tag| tag[:name] == 'esi:include'}
|
185
|
+
assert_equal 5, include_tags.size
|
186
|
+
include_tags.each do|tag|
|
187
|
+
assert_equal 'hello', tag[:attributes]['src']
|
188
|
+
end
|
189
|
+
|
190
|
+
inline_tags = tags.select {|tag| tag[:name] == 'esi:inline'}
|
191
|
+
assert_equal 1, inline_tags.size
|
192
|
+
comment_tags = tags.select {|tag| tag[:name] == 'esi:comment'}
|
193
|
+
assert_equal 1, comment_tags.size
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_block_parser_basics
|
198
|
+
output = ""
|
199
|
+
parser = ESI::CParser.new
|
200
|
+
parser.output_handler {|s| output << s }
|
201
|
+
tags = []
|
202
|
+
parser.start_tag_handler do|tag_name, attrs|
|
203
|
+
tags << {:name => tag_name, :attributes => attrs}
|
204
|
+
end
|
205
|
+
parser.process "<html><head><body><esi:include timeout='1' max-age='600+600' src=\"hello\"/>some more input<br/>\n"
|
206
|
+
parser.process "some input<esi:try><esi:attempt><span>some more input</span></esi:attempt><esi:except><span>\n"
|
207
|
+
parser.process "some input</span></esi:except></esi:try>some more input<br/>\n"
|
208
|
+
parser.process "some input<esi:inline src='hello'/>some more input\nsome input<esi:comment text='hello'/>some more input<br/>\n"
|
209
|
+
parser.process "<p>some input</p><esi:include src='hello'/>some more input\nsome input<esi:include src='hello'/>some more input<br/>\n"
|
210
|
+
parser.process "</body></html>"
|
211
|
+
parser.finish
|
212
|
+
# assert_equal %Q(some input<span>some more input</span><span>
|
213
|
+
#some input</span>some more input<br/>
|
214
|
+
#), output
|
215
|
+
assert_equal %Q(<html><head><body>some more input<br/>
|
216
|
+
some input<span>some more input</span><span>
|
217
|
+
some input</span>some more input<br/>
|
218
|
+
some inputsome more input
|
219
|
+
some inputsome more input<br/>
|
220
|
+
<p>some input</p>some more input
|
221
|
+
some inputsome more input<br/>
|
222
|
+
</body></html>), output
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_empty_parse
|
226
|
+
output = ""
|
227
|
+
parser = ESI::CParser.new
|
228
|
+
parser.output_handler {|s| output << s }
|
229
|
+
tags = []
|
230
|
+
parser.start_tag_handler do|tag_name, attrs|
|
231
|
+
tags << {:name => tag_name, :attributes => attrs}
|
232
|
+
end
|
233
|
+
assert_nothing_raised do
|
234
|
+
parser.process ""
|
235
|
+
end
|
236
|
+
parser.finish
|
237
|
+
end
|
238
|
+
|
239
|
+
# it's a strange case but, we should still recongize the tag so that it can be pruned from the input stream
|
240
|
+
def test_parser_accepts_empty_tag
|
241
|
+
output = ""
|
242
|
+
parser = ESI::CParser.new
|
243
|
+
parser.output_handler {|s| output << s }
|
244
|
+
tags = []
|
245
|
+
parser.start_tag_handler do|tag_name, attrs|
|
246
|
+
tags << {:name => tag_name, :attributes => attrs}
|
247
|
+
end
|
248
|
+
parser.process "<p>some input</p><esi:include/>some more input\nsome input<esi:include src='hello'/>some more input"
|
249
|
+
parser.finish
|
250
|
+
assert_equal %Q(<p>some input</p>some more input
|
251
|
+
some inputsome more input), output
|
252
|
+
|
253
|
+
assert_equal 2, tags.size
|
254
|
+
assert_equal 'hello', tags.last[:attributes]['src']
|
255
|
+
end
|
256
|
+
|
257
|
+
def test_can_parse_in_chunks
|
258
|
+
|
259
|
+
output = ""
|
260
|
+
parser = ESI::CParser.new
|
261
|
+
parser.output_handler {|s| output << s }
|
262
|
+
tags = []
|
263
|
+
parser.start_tag_handler do|tag_name, attrs|
|
264
|
+
tags << {:name => tag_name, :attributes => attrs}
|
265
|
+
end
|
266
|
+
parser.process "some input<esi:in"
|
267
|
+
parser.process "line src='hel"
|
268
|
+
parser.process "lo'"
|
269
|
+
parser.process "/>some more input\nsome input<esi:comment text='hello'/>some more input"
|
270
|
+
parser.finish
|
271
|
+
|
272
|
+
assert_equal "some inputsome more input\nsome inputsome more input", output
|
273
|
+
|
274
|
+
assert_equal 2, tags.size
|
275
|
+
assert_equal 'hello', tags.first[:attributes]['src']
|
276
|
+
|
277
|
+
output = ""
|
278
|
+
parser = ESI::CParser.new
|
279
|
+
parser.output_handler {|s| output << s }
|
280
|
+
tags = []
|
281
|
+
parser.start_tag_handler do|tag_name, attrs|
|
282
|
+
tags << {:name => tag_name, :attributes => attrs}
|
283
|
+
end
|
284
|
+
parser.process "some input<"
|
285
|
+
parser.process "e"
|
286
|
+
parser.process "s"
|
287
|
+
parser.process "i"
|
288
|
+
parser.process ":"
|
289
|
+
parser.process "i"
|
290
|
+
parser.process "n"
|
291
|
+
parser.process "lin"
|
292
|
+
parser.process "e"
|
293
|
+
parser.process " "
|
294
|
+
parser.process "s"
|
295
|
+
parser.process "rc"
|
296
|
+
parser.process "="
|
297
|
+
parser.process "'hel"
|
298
|
+
parser.process "lo'"
|
299
|
+
parser.process "/"
|
300
|
+
parser.process ">some more input\nsome input"
|
301
|
+
parser.process "<esi:comment text="
|
302
|
+
parser.process "'hello'/>some more input"
|
303
|
+
parser.finish
|
304
|
+
|
305
|
+
assert_equal "some inputsome more input\nsome inputsome more input", output
|
306
|
+
|
307
|
+
assert_equal 2, tags.size
|
308
|
+
assert_equal 1, tags.select{|tag| tag[:name] == 'esi:inline'}.size, "Failed to parse esi:inline"
|
309
|
+
assert_equal 1, tags.select{|tag| tag[:name] == 'esi:comment'}.size, "Failed to parse esi:comment"
|
310
|
+
assert_equal 'hello', tags.select{|tag| tag[:name] == 'esi:inline'}.first[:attributes]['src'], "Failed to parse esi:inline attributes"
|
311
|
+
|
312
|
+
end
|
313
|
+
|
314
|
+
def assert_totals_from_parse(parser)
|
315
|
+
|
316
|
+
start_trys = 0
|
317
|
+
start_attempts = 0
|
318
|
+
start_includes = 0
|
319
|
+
start_excepts = 0
|
320
|
+
start_invalidates = 0
|
321
|
+
|
322
|
+
parser.start_tag_handler do|tag_name,attrs|
|
323
|
+
# puts "\tstart: #{tag_name.inspect}#{attrs.inspect}"
|
324
|
+
case tag_name
|
325
|
+
when "esi:try" then start_trys += 1
|
326
|
+
when "esi:attempt" then start_attempts += 1
|
327
|
+
when "esi:include" then start_includes += 1
|
328
|
+
when "esi:except" then start_excepts += 1
|
329
|
+
when "esi:invalidate" then start_invalidates += 1
|
330
|
+
else
|
331
|
+
raise "Unverified start: #{tag_name.inspect}#{attrs.inspect}"
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
end_trys = 0
|
336
|
+
end_attempts = 0
|
337
|
+
end_includes = 0
|
338
|
+
end_excepts = 0
|
339
|
+
end_invalidates = 0
|
340
|
+
|
341
|
+
parser.end_tag_handler do|tag_name|
|
342
|
+
# puts "\tend: #{tag_name.inspect}"
|
343
|
+
case tag_name
|
344
|
+
when "esi:try" then end_trys += 1
|
345
|
+
when "esi:attempt" then end_attempts += 1
|
346
|
+
when "esi:include" then end_includes += 1
|
347
|
+
when "esi:except" then end_excepts += 1
|
348
|
+
when "esi:invalidate" then end_invalidates += 1
|
349
|
+
else
|
350
|
+
raise "Unverified start: #{tag_name.inspect}"
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
yield
|
355
|
+
|
356
|
+
assert_equal 2, start_trys, "More or less esi:try tags detected #{start_trys.inspect}"
|
357
|
+
assert_equal 2, start_attempts, "More or less esi:attempt tags detected #{start_attempts.inspect}"
|
358
|
+
assert_equal 6, start_includes, "More or less esi:include tags detected #{start_includes.inspect}"
|
359
|
+
assert_equal 2, start_excepts, "More or less esi:except tags detected #{start_excepts.inspect}"
|
360
|
+
assert_equal 1, start_invalidates, "More or less esi:invalidate tags detected #{start_invalidates.inspect}"
|
361
|
+
assert_equal 2, end_trys, "More or less esi:try tags detected #{end_trys.inspect}"
|
362
|
+
assert_equal 2, end_attempts, "More or less esi:attempt tags detected #{end_attempts.inspect}"
|
363
|
+
assert_equal 6, end_includes, "More or less esi:include tags detected #{end_includes.inspect}"
|
364
|
+
assert_equal 2, end_excepts, "More or less esi:except tags detected #{end_excepts.inspect}"
|
365
|
+
assert_equal 1, end_invalidates, "More or less esi:invalidate tags detected #{end_invalidates.inspect}"
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_sample
|
369
|
+
sample = @sample_file
|
370
|
+
output = ""
|
371
|
+
parser = ESI::CParser.new
|
372
|
+
parser.output_handler {|s| output << s }
|
373
|
+
assert_totals_from_parse( parser ) do
|
374
|
+
parser.process File.read(sample)
|
375
|
+
parser.finish
|
376
|
+
end
|
377
|
+
assert_no_match /<esi:/, output
|
378
|
+
|
379
|
+
#8.times do|i|
|
380
|
+
i = 4
|
381
|
+
File.open(sample,'r') do|input|
|
382
|
+
output = ""
|
383
|
+
parser = ESI::CParser.new
|
384
|
+
parser.output_handler {|s| output << s }
|
385
|
+
assert_totals_from_parse( parser ) do
|
386
|
+
while( (buf=input.read((i+1)*2)) and !input.eof? and buf.size != 0 )
|
387
|
+
parser.process buf
|
388
|
+
end
|
389
|
+
parser.process buf
|
390
|
+
parser.finish
|
391
|
+
end
|
392
|
+
assert_no_match /<esi:/, output
|
393
|
+
end
|
394
|
+
# end
|
395
|
+
|
396
|
+
end
|
397
|
+
|
398
|
+
def test_embedded_content
|
399
|
+
input = %Q(
|
400
|
+
<html>
|
401
|
+
<head>
|
402
|
+
</head>
|
403
|
+
<body>
|
404
|
+
<h1>This is a test document</h1>
|
405
|
+
<esi:try>
|
406
|
+
<esi:attempt>
|
407
|
+
<div>Some content before</div><esi:include src="/fragments/test1.html" max-age="600+600"/>
|
408
|
+
</esi:attempt>
|
409
|
+
<esi:except>
|
410
|
+
<esi:include src="/fragments/test_failover.html"/>
|
411
|
+
</esi:except>
|
412
|
+
</esi:try>
|
413
|
+
</body>
|
414
|
+
</html>)
|
415
|
+
output = ""
|
416
|
+
parser = ESI::CParser.new
|
417
|
+
parser.output_handler {|s| output << s }
|
418
|
+
starts = 0
|
419
|
+
ends = 0
|
420
|
+
parser.start_tag_handler do|tag_name, attrs|
|
421
|
+
starts += 1
|
422
|
+
end
|
423
|
+
parser.end_tag_handler do|tag_name|
|
424
|
+
ends += 1
|
425
|
+
end
|
426
|
+
parser.process input
|
427
|
+
parser.finish
|
428
|
+
assert_equal 5, starts, "Start tags"
|
429
|
+
assert_equal 5, ends, "End tags"
|
430
|
+
end
|
431
|
+
|
432
|
+
def test_basic_invalidate_tag
|
433
|
+
parser_input = %Q(<html><body>
|
434
|
+
<esi:invalidate output="no">
|
435
|
+
<?xml version="1.0"?>
|
436
|
+
<!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
|
437
|
+
<INVALIDATION VERSION="WCS-1.1">
|
438
|
+
<OBJECT>
|
439
|
+
<BASICSELECTOR URI="/foo/bar"/>
|
440
|
+
<ACTION REMOVALTTL="0"/>
|
441
|
+
<INFO VALUE="invalidating fragment test 1"/>
|
442
|
+
</OBJECT>
|
443
|
+
</INVALIDATION>
|
444
|
+
</esi:invalidate>
|
445
|
+
<esi:invalidate output="no">
|
446
|
+
<?xml version="1.0"?>
|
447
|
+
<!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
|
448
|
+
<INVALIDATION VERSION="WCS-1.1">
|
449
|
+
<OBJECT>
|
450
|
+
<BASICSELECTOR URI="/foo/bar"/>
|
451
|
+
<ACTION REMOVALTTL="0"/>
|
452
|
+
<INFO VALUE="invalidating fragment test 2"/>
|
453
|
+
</OBJECT>
|
454
|
+
</INVALIDATION>
|
455
|
+
</esi:invalidate>
|
456
|
+
</body></html>)
|
457
|
+
output = ""
|
458
|
+
parser = ESI::CParser.new
|
459
|
+
parser.output_handler {|s| output << s }
|
460
|
+
start_called = false
|
461
|
+
end_called = false
|
462
|
+
parser.start_tag_handler do|tag_name, attrs|
|
463
|
+
start_called = true
|
464
|
+
end
|
465
|
+
parser.end_tag_handler do|tag_name|
|
466
|
+
end_called = true
|
467
|
+
end
|
468
|
+
parser.process parser_input
|
469
|
+
parser.finish
|
470
|
+
assert start_called
|
471
|
+
assert end_called
|
472
|
+
end
|
473
|
+
|
474
|
+
# def test_setup
|
475
|
+
# puts @output
|
476
|
+
# end
|
477
|
+
|
478
|
+
end
|