PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/parser_test.rb

http://mongrel-esi.googlecode.com/
Ruby | 515 lines | 461 code | 42 blank | 12 comment | 12 complexity | e18631ceafd1b6f55ebb1dd4fb533d7e MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception
  1. require File.join(File.dirname(__FILE__),'help.rb')
  2. require 'esi/response'
  3. $run_sample_once = false
  4. class ParseOutputTest < Test::Unit::TestCase
  5. include TestServer
  6. def setup_extra
  7. @sample_file = File.join(File.dirname(__FILE__),'esi-sample.html')
  8. if !$run_sample_once
  9. File.open('out-sample.html','w') do|output|
  10. @cache = ESI::RubyCache.new
  11. @parser = ESI::CParser.new
  12. @parser.output = output
  13. @parser.start_tag_handler do|tag_name,attrs|
  14. tag = ESI::Tag::Base.create(@test_router, {}, {}, tag_name.gsub(/esi:/,''), attrs, @cache)
  15. if @parser.esi_tag
  16. @parser.esi_tag.add_child(tag)
  17. else
  18. @parser.esi_tag = tag
  19. end
  20. end
  21. @parser.end_tag_handler do|tag_name|
  22. #puts "match: '#{@parser.esi_tag.name}' with '#{tag_name.gsub(/esi:/,'')}'"
  23. if @parser.esi_tag.name == tag_name.gsub(/esi:/,'')
  24. begin
  25. @parser.esi_tag.close(@parser.output)
  26. rescue Object => e
  27. puts @parser.esi_tag.name
  28. puts e.message, e.backtrace.join("\n")
  29. end
  30. @parser.esi_tag = nil
  31. else
  32. @parser.esi_tag.close_child(@parser.output,tag_name)
  33. end
  34. end
  35. File.open( @sample_file,'r') do|input|
  36. while( (buf=input.read(128)) and !input.eof? and buf.size != 0 )
  37. @parser.process buf
  38. end
  39. @parser.process buf
  40. end
  41. @parser.finish
  42. end
  43. $run_sample_once = true
  44. end
  45. @output=File.read('out-sample.html')
  46. end
  47. def test_ouput_body
  48. assert_match(/ <div class="body">/, @output)
  49. end
  50. def test_ouput_some_content
  51. assert_match(/ <div>some content<\/div>/, @output)
  52. end
  53. def test_output_comments
  54. assert_match(/ <!-- a little commentary -->/, @output)
  55. assert_match(%q(<!-- a
  56. multiline comment -->),@output)
  57. end
  58. def test_output_cdata
  59. assert_match(%q(<![CDATA[
  60. Some cdata fun fun fun
  61. ]]>), @output)
  62. end
  63. def test_output_doctype
  64. assert_match(/<!DOCTYPE html PUBLIC "-\/\/W3C\/\/DTD XHTML 1.0 Strict\/\/EN" "http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-strict.dtd">/, @output)
  65. end
  66. def test_output_complete
  67. assert_match(/<\/html>/, @output)
  68. end
  69. def test_output_no_esi_tags
  70. assert_no_match(/<esi:/, @output)
  71. end
  72. def test_includes_appeared
  73. assert_match(/<div id='1'>id string<\/div>/, @output)
  74. assert_match(/<div id='3'>id string<\/div>/, @output)
  75. assert_no_match(/<p>it failed<\/p>/, @output)
  76. assert_match(/<div id='2'>id string<\/div>/, @output)
  77. assert_match(/<div id='4'>id string<\/div>/, @output)
  78. assert_match(/<p>We should get this or not\?<\/p>/, @output)
  79. assert_match(/<p>Now maybe we shouldn't see this\?<\/p>/, @output)
  80. assert_match(/<p>except worked1<\/p>/, @output)
  81. assert_match(/<p>except worked2<\/p>/, @output)
  82. assert_match(/<em>Support for em tags since they have an initial start sequence similar to and &lt;esi: start\/end sequence<\/em>/, @output )
  83. end
  84. def test_content_echoing
  85. output = ""
  86. parser = ESI::CParser.new
  87. input = "<em>Support for em tags since they have an initial start sequence similar to and &lt;esi: start/end sequence</em>"
  88. parser.output_handler {|s| output << s }
  89. parser.process input
  90. parser.finish
  91. assert_equal input, output
  92. end
  93. class OutputAdapter
  94. def initialize(output)
  95. @output = output
  96. end
  97. def << (msg)
  98. @output.call msg
  99. end
  100. end
  101. def test_with_tags
  102. sample = @sample_file
  103. cache = ESI::RubyCache.new
  104. File.open('out-sample.html','w') do|output|
  105. parser = ESI::CParser.new
  106. parser.output_handler {|s| output << s }
  107. parser.start_tag_handler do|tag_name,attrs|
  108. tag = ESI::Tag::Base.create(@test_router, {}, {}, tag_name.gsub(/esi:/,''), attrs, cache)
  109. if parser.esi_tag
  110. parser.esi_tag.add_child(tag)
  111. else
  112. parser.esi_tag = tag
  113. end
  114. end
  115. parser.end_tag_handler do|tag_name|
  116. if parser.esi_tag.name == tag_name.gsub(/esi:/,'')
  117. parser.esi_tag.close(OutputAdapter.new(parser.output))
  118. parser.esi_tag = nil
  119. else
  120. parser.esi_tag.close_child(OutputAdapter.new(parser.output),tag_name)
  121. end
  122. end
  123. File.open(sample,'r') do|input|
  124. while( (buf=input.read(128)) and !input.eof? and buf.size != 0 )
  125. parser.process buf
  126. end
  127. parser.process buf
  128. end
  129. parser.finish
  130. end
  131. output = File.read("out-sample.html")
  132. assert_match(/ <div class="body">/, output)
  133. assert_match(/ <div>some content<\/div>/, output)
  134. assert_match(/ <!-- a little commentary -->/, output)
  135. assert_match(%q(<!-- a
  136. multiline comment -->),output)
  137. assert_match(%q(<![CDATA[
  138. Some cdata fun fun fun
  139. ]]>), output)
  140. assert_match(/<!DOCTYPE html PUBLIC "-\/\/W3C\/\/DTD XHTML 1.0 Strict\/\/EN" "http:\/\/www.w3.org\/TR\/xhtml1\/DTD\/xhtml1-strict.dtd">/, output)
  141. assert_no_match(/<esi:/, output)
  142. assert_match(/<div id='1'>id string<\/div>/, output)
  143. assert_match(/<div id='3'>id string<\/div>/, output)
  144. assert_no_match(/<p>it failed<\/p>/, output)
  145. assert_match(/<div id='2'>id string<\/div>/, output)
  146. assert_match(/<div id='4'>id string<\/div>/, output)
  147. assert_match(/<p>We should get this or not\?<\/p>/, output)
  148. assert_match(/<p>Now maybe we shouldn't see this\?<\/p>/, output)
  149. assert_match(/<p>except worked1<\/p>/, output)
  150. assert_match(/<p>except worked2<\/p>/, output)
  151. assert_match(/<\/html>/, output)
  152. end
  153. def test_inline_parse_basics
  154. output = ""
  155. parser = ESI::CParser.new
  156. parser.output_handler {|s| output << s }
  157. tags = []
  158. parser.start_tag_handler do|tag_name, attrs|
  159. tags << {:name => tag_name, :attributes => attrs}
  160. end
  161. parser.process "<html><head><body><esi:include timeout='1' max-age='600+600' src=\"hello\"/>some more input"
  162. parser.process "some input<esi:include \nsrc='hello'/>some more input\nsome input<esi:include src=\"hello\"/>some more input"
  163. parser.process "some input<esi:inline src='hello'/>some more input\nsome input<esi:comment text='hello'/>some more input"
  164. parser.process "<p>some input</p><esi:include src='hello'/>some more input\nsome input<esi:include src='hello'/>some more input"
  165. parser.process "</body></html>"
  166. parser.finish
  167. assert_equal %Q(<html><head><body>some more inputsome inputsome more input
  168. some inputsome more inputsome inputsome more input
  169. some inputsome more input<p>some input</p>some more input
  170. some inputsome more input</body></html>), output
  171. assert_equal 7, tags.size
  172. include_tags = tags.select {|tag| tag[:name] == 'esi:include'}
  173. assert_equal 5, include_tags.size
  174. include_tags.each do|tag|
  175. assert_equal 'hello', tag[:attributes]['src']
  176. end
  177. inline_tags = tags.select {|tag| tag[:name] == 'esi:inline'}
  178. assert_equal 1, inline_tags.size
  179. comment_tags = tags.select {|tag| tag[:name] == 'esi:comment'}
  180. assert_equal 1, comment_tags.size
  181. end
  182. def test_block_parser_basics
  183. output = ""
  184. parser = ESI::CParser.new
  185. parser.output_handler {|s| output << s }
  186. tags = []
  187. parser.start_tag_handler do|tag_name, attrs|
  188. tags << {:name => tag_name, :attributes => attrs}
  189. end
  190. parser.process "<html><head><body><esi:include timeout='1' max-age='600+600' src=\"hello\"/>some more input<br/>\n"
  191. parser.process "some input<esi:try><esi:attempt><span>some more input</span></esi:attempt><esi:except><span>\n"
  192. parser.process "some input</span></esi:except></esi:try>some more input<br/>\n"
  193. parser.process "some input<esi:inline src='hello'/>some more input\nsome input<esi:comment text='hello'/>some more input<br/>\n"
  194. parser.process "<p>some input</p><esi:include src='hello'/>some more input\nsome input<esi:include src='hello'/>some more input<br/>\n"
  195. parser.process "</body></html>"
  196. parser.finish
  197. # assert_equal %Q(some input<span>some more input</span><span>
  198. #some input</span>some more input<br/>
  199. #), output
  200. assert_equal %Q(<html><head><body>some more input<br/>
  201. some input<span>some more input</span><span>
  202. some input</span>some more input<br/>
  203. some inputsome more input
  204. some inputsome more input<br/>
  205. <p>some input</p>some more input
  206. some inputsome more input<br/>
  207. </body></html>), output
  208. end
  209. def test_empty_parse
  210. output = ""
  211. parser = ESI::CParser.new
  212. parser.output_handler {|s| output << s }
  213. tags = []
  214. parser.start_tag_handler do|tag_name, attrs|
  215. tags << {:name => tag_name, :attributes => attrs}
  216. end
  217. assert_nothing_raised do
  218. parser.process ""
  219. end
  220. parser.finish
  221. end
  222. # it's a strange case but, we should still recongize the tag so that it can be pruned from the input stream
  223. def test_parser_accepts_empty_tag
  224. output = ""
  225. parser = ESI::CParser.new
  226. parser.output_handler {|s| output << s }
  227. tags = []
  228. parser.start_tag_handler do|tag_name, attrs|
  229. tags << {:name => tag_name, :attributes => attrs}
  230. end
  231. parser.process "<p>some input</p><esi:include />some more input\nsome input<esi:include src='hello'/>some more input"
  232. parser.finish
  233. assert_equal %Q(<p>some input</p>some more input
  234. some inputsome more input), output
  235. assert_equal 2, tags.size
  236. assert_equal 'hello', tags.last[:attributes]['src']
  237. end
  238. def test_can_parse_in_chunks
  239. output = ""
  240. parser = ESI::CParser.new
  241. parser.output_handler {|s| output << s }
  242. tags = []
  243. parser.start_tag_handler do|tag_name, attrs|
  244. tags << {:name => tag_name, :attributes => attrs}
  245. end
  246. parser.process "some input<esi:in"
  247. parser.process "line src='hel"
  248. parser.process "lo'"
  249. parser.process "/>some more input\nsome input<esi:comment text='hello'/>some more input"
  250. parser.finish
  251. assert_equal "some inputsome more input\nsome inputsome more input", output
  252. assert_equal 2, tags.size
  253. assert_equal 'hello', tags.first[:attributes]['src']
  254. output = ""
  255. parser = ESI::CParser.new
  256. parser.output_handler {|s| output << s }
  257. tags = []
  258. parser.start_tag_handler do|tag_name, attrs|
  259. tags << {:name => tag_name, :attributes => attrs}
  260. end
  261. parser.process "some input<"
  262. parser.process "e"
  263. parser.process "s"
  264. parser.process "i"
  265. parser.process ":"
  266. parser.process "i"
  267. parser.process "n"
  268. parser.process "lin"
  269. parser.process "e"
  270. parser.process " "
  271. parser.process "s"
  272. parser.process "rc"
  273. parser.process "="
  274. parser.process "'hel"
  275. parser.process "lo'"
  276. parser.process "/"
  277. parser.process ">some more input\nsome input"
  278. parser.process "<esi:comment text="
  279. parser.process "'hello'/>some more input"
  280. parser.finish
  281. assert_equal "some inputsome more input\nsome inputsome more input", output
  282. assert_equal 2, tags.size
  283. assert_equal 1, tags.select{|tag| tag[:name] == 'esi:inline'}.size, "Failed to parse esi:inline"
  284. assert_equal 1, tags.select{|tag| tag[:name] == 'esi:comment'}.size, "Failed to parse esi:comment"
  285. assert_equal 'hello', tags.select{|tag| tag[:name] == 'esi:inline'}.first[:attributes]['src'], "Failed to parse esi:inline attributes"
  286. end
  287. def assert_totals_from_parse(parser)
  288. start_trys = 0
  289. start_attempts = 0
  290. start_includes = 0
  291. start_excepts = 0
  292. start_invalidates = 0
  293. parser.start_tag_handler do|tag_name,attrs|
  294. # puts "\tstart: #{tag_name.inspect}#{attrs.inspect}"
  295. case tag_name
  296. when "esi:try" then start_trys += 1
  297. when "esi:attempt" then start_attempts += 1
  298. when "esi:include" then start_includes += 1
  299. when "esi:except" then start_excepts += 1
  300. when "esi:invalidate" then start_invalidates += 1
  301. else
  302. raise "Unverified start: #{tag_name.inspect}#{attrs.inspect}"
  303. end
  304. end
  305. end_trys = 0
  306. end_attempts = 0
  307. end_includes = 0
  308. end_excepts = 0
  309. end_invalidates = 0
  310. parser.end_tag_handler do|tag_name|
  311. #puts "\tend: #{tag_name.inspect}"
  312. case tag_name
  313. when "esi:try" then end_trys += 1
  314. when "esi:attempt" then end_attempts += 1
  315. when "esi:include" then end_includes += 1
  316. when "esi:except" then end_excepts += 1
  317. when "esi:invalidate" then end_invalidates += 1
  318. else
  319. raise "Unverified start: #{tag_name.inspect}"
  320. end
  321. end
  322. yield
  323. assert_equal 2, start_trys, "More or less esi:try tags detected #{start_trys.inspect}"
  324. assert_equal 2, start_attempts, "More or less esi:attempt tags detected #{start_attempts.inspect}"
  325. assert_equal 6, start_includes, "More or less esi:include tags detected #{start_includes.inspect}"
  326. assert_equal 2, start_excepts, "More or less esi:except tags detected #{start_excepts.inspect}"
  327. assert_equal 1, start_invalidates, "More or less esi:invalidate tags detected #{start_invalidates.inspect}"
  328. assert_equal 2, end_trys, "More or less esi:try tags detected #{end_trys.inspect}"
  329. assert_equal 2, end_attempts, "More or less esi:attempt tags detected #{end_attempts.inspect}"
  330. assert_equal 6, end_includes, "More or less esi:include tags detected #{end_includes.inspect}"
  331. assert_equal 2, end_excepts, "More or less esi:except tags detected #{end_excepts.inspect}"
  332. assert_equal 1, end_invalidates, "More or less esi:invalidate tags detected #{end_invalidates.inspect}"
  333. end
  334. def test_sample
  335. sample = @sample_file
  336. output = ""
  337. parser = ESI::CParser.new
  338. parser.output_handler {|s| output << s }
  339. assert_totals_from_parse( parser ) do
  340. parser.process File.read(sample)
  341. parser.finish
  342. end
  343. assert_no_match /<esi:/, output
  344. #8.times do|i|
  345. i = 4
  346. File.open(sample,'r') do|input|
  347. output = ""
  348. parser = ESI::CParser.new
  349. parser.output_handler {|s| output << s }
  350. assert_totals_from_parse( parser ) do
  351. while( (buf=input.read((i+1)*2)) and !input.eof? and buf.size != 0 )
  352. parser.process buf
  353. end
  354. parser.process buf
  355. parser.finish
  356. end
  357. assert_no_match /<esi:/, output
  358. end
  359. # end
  360. end
  361. def test_embedded_content
  362. input = %Q(
  363. <html>
  364. <head>
  365. </head>
  366. <body>
  367. <h1>This is a test document</h1>
  368. <esi:try>
  369. <esi:attempt>
  370. <div>Some content before</div><esi:include src="/fragments/test1.html" max-age="600+600"/>
  371. </esi:attempt>
  372. <esi:except>
  373. <esi:include src="/fragments/test_failover.html"/>
  374. </esi:except>
  375. </esi:try>
  376. </body>
  377. </html>)
  378. output = ""
  379. parser = ESI::CParser.new
  380. parser.output_handler {|s| output << s }
  381. starts = 0
  382. ends = 0
  383. parser.start_tag_handler do|tag_name, attrs|
  384. starts += 1
  385. end
  386. parser.end_tag_handler do|tag_name|
  387. ends += 1
  388. end
  389. parser.process input
  390. parser.finish
  391. assert_equal 5, starts, "Start tags"
  392. assert_equal 5, ends, "End tags"
  393. end
  394. def test_basic_invalidate_tag
  395. parser_input = %Q(<html><body>
  396. <esi:invalidate output="no">
  397. <?xml version="1.0"?>
  398. <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
  399. <INVALIDATION VERSION="WCS-1.1">
  400. <OBJECT>
  401. <BASICSELECTOR URI="/foo/bar"/>
  402. <ACTION REMOVALTTL="0"/>
  403. <INFO VALUE="invalidating fragment test 1"/>
  404. </OBJECT>
  405. </INVALIDATION>
  406. </esi:invalidate>
  407. <esi:invalidate output="no">
  408. <?xml version="1.0"?>
  409. <!DOCTYPE INVALIDATION SYSTEM "internal:///WCSinvalidation.dtd">
  410. <INVALIDATION VERSION="WCS-1.1">
  411. <OBJECT>
  412. <BASICSELECTOR URI="/foo/bar"/>
  413. <ACTION REMOVALTTL="0"/>
  414. <INFO VALUE="invalidating fragment test 2"/>
  415. </OBJECT>
  416. </INVALIDATION>
  417. </esi:invalidate>
  418. </body></html>)
  419. output = ""
  420. parser = ESI::CParser.new
  421. parser.output_handler {|s| output << s }
  422. start_called = false
  423. end_called = false
  424. parser.start_tag_handler do|tag_name, attrs|
  425. start_called = true
  426. end
  427. parser.end_tag_handler do|tag_name|
  428. end_called = true
  429. end
  430. parser.process parser_input
  431. parser.finish
  432. assert start_called
  433. assert end_called
  434. end
  435. def test_attribute_values
  436. output = ""
  437. parser = ESI::CParser.new
  438. parser.output_handler {|s| output << s }
  439. parser.process 'start:<esi:include src="foobar?hi=cool"/>:finish'
  440. parser.finish
  441. assert_equal "start::finish", output
  442. output = ""
  443. parser.process 'start:<esi:include src="foo bar"/>:finish'
  444. parser.finish
  445. assert_equal "start::finish", output
  446. output = ""
  447. parser.process 'start:<esi:include src="foobar?hi=!@#$%^&*()-+~`"/>:finish'
  448. parser.finish
  449. assert_equal "start::finish", output
  450. output = ""
  451. parser.process 'start:<esi:try src="foobar?hi=!@#$%^&*()-+~`">cool</esi:try>:finish'
  452. parser.finish
  453. assert_equal "start:cool:finish", output
  454. output = ""
  455. parser.process 'start:<esi:try>cool</esi:try>:finish'
  456. parser.finish
  457. assert_equal "start:cool:finish", output
  458. end
  459. # def test_setup
  460. # puts @output
  461. # end
  462. end