tidy_ffi 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/lib/tidy_ffi/interface.rb +104 -0
- data/lib/tidy_ffi/lib_tidy.rb +24 -0
- data/lib/tidy_ffi/options_container.rb +18 -2
- data/lib/tidy_ffi/tidy.rb +8 -0
- data/test/test_helper.rb +1 -0
- data/test/test_lowlevel.rb +86 -0
- data/test/test_options.rb +14 -8
- data/test/test_simple.rb +17 -0
- data/tidy_ffi.gemspec +4 -4
- metadata +3 -2
data/CHANGELOG
CHANGED
data/lib/tidy_ffi/interface.rb
CHANGED
@@ -84,4 +84,108 @@ class TidyFFI::Interface
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
private :tidy_buf_object
|
87
|
+
|
88
|
+
class <<self
|
89
|
+
# Returns enumeration for opt.
|
90
|
+
#
|
91
|
+
# Some tidy options might try to trespass as integer, and in order to caught
|
92
|
+
# perpertraitors we need to call tidyOptGetPickList
|
93
|
+
def pic_list_for(opt)
|
94
|
+
iterator = LibTidy.tidyOptGetPickList(opt)
|
95
|
+
|
96
|
+
return nil if iterator.null?
|
97
|
+
|
98
|
+
pic_list = []
|
99
|
+
|
100
|
+
MemoryPointer.new(:pointer) do |pointer|
|
101
|
+
pointer.put_pointer(0, iterator)
|
102
|
+
until iterator.null?
|
103
|
+
pic_list << LibTidy.tidyOptGetNextPick(opt, pointer)
|
104
|
+
iterator = pointer.get_pointer(0)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
pic_list
|
109
|
+
end
|
110
|
+
private :pic_list_for
|
111
|
+
|
112
|
+
# Loads default options.
|
113
|
+
def load_default_options
|
114
|
+
return if @default_options
|
115
|
+
|
116
|
+
doc = LibTidy.tidyCreate
|
117
|
+
iterator = LibTidy.tidyGetOptionList(doc)
|
118
|
+
|
119
|
+
@default_options = {}
|
120
|
+
|
121
|
+
MemoryPointer.new(:pointer) do |pointer|
|
122
|
+
pointer.put_pointer(0, iterator)
|
123
|
+
|
124
|
+
until iterator.null?
|
125
|
+
opt = LibTidy.tidyGetNextOption(doc, pointer)
|
126
|
+
|
127
|
+
option = {}
|
128
|
+
|
129
|
+
option[:name] = LibTidy.tidyOptGetName(opt).gsub('-', '_').intern
|
130
|
+
option[:readonly?] = LibTidy.tidyOptIsReadOnly(opt) != 0
|
131
|
+
option[:type] = LibTidy::TIDY_OPTION_TYPE[LibTidy.tidyOptGetType(opt)]
|
132
|
+
option[:default] = case option[:type]
|
133
|
+
when :string
|
134
|
+
(LibTidy.tidyOptGetDefault(opt) rescue "")
|
135
|
+
when :integer
|
136
|
+
if pic_list = pic_list_for(opt)
|
137
|
+
option[:type] = :enum
|
138
|
+
option[:values] = pic_list
|
139
|
+
pic_list[LibTidy.tidyOptGetDefaultInt(opt)]
|
140
|
+
else
|
141
|
+
LibTidy.tidyOptGetDefaultInt(opt)
|
142
|
+
end
|
143
|
+
when :boolean
|
144
|
+
LibTidy.tidyOptGetDefaultBool(opt) != 0
|
145
|
+
end
|
146
|
+
|
147
|
+
@default_options[option[:name]] = option
|
148
|
+
|
149
|
+
iterator = pointer.get_pointer(0)
|
150
|
+
end
|
151
|
+
|
152
|
+
@default_options.freeze
|
153
|
+
end
|
154
|
+
ensure
|
155
|
+
LibTidy.tidyRelease(doc)
|
156
|
+
end
|
157
|
+
private :load_default_options
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns a hash that represents default options for tidy.
|
161
|
+
# Key for hash is the option name, value is also a hash...
|
162
|
+
# Possible values are:
|
163
|
+
# * :type - either :string, :integer, :boolean or :enum
|
164
|
+
# * :readonly?
|
165
|
+
# * :default - default value of an option
|
166
|
+
# * :values - possible values for :enum
|
167
|
+
# * :name
|
168
|
+
def self.default_options
|
169
|
+
@default_options ||= load_default_options
|
170
|
+
end
|
171
|
+
|
172
|
+
# Returns true if value is valid for +option+ and false otherwise.
|
173
|
+
def self.option_valid?(option, value)
|
174
|
+
return false unless spec = default_options[option]
|
175
|
+
|
176
|
+
case spec[:type]
|
177
|
+
when :boolean
|
178
|
+
true == value || false == value || value == 0 || value == 1 || %w(on off true false 0 1 yes no).include?(value.downcase)
|
179
|
+
when :integer
|
180
|
+
Integer === value || !!(value =~ /^\d+$/)
|
181
|
+
when :enum
|
182
|
+
if Integer === value
|
183
|
+
!!spec[:values][value]
|
184
|
+
else
|
185
|
+
spec[:values].include?(value)
|
186
|
+
end
|
187
|
+
when :string
|
188
|
+
String === value || Symbol === value
|
189
|
+
end
|
190
|
+
end
|
87
191
|
end
|
data/lib/tidy_ffi/lib_tidy.rb
CHANGED
@@ -24,6 +24,30 @@ class TidyFFI::LibTidy #:nodoc:
|
|
24
24
|
attach_function :tidyGetOptionByName, [:pointer, :string], :pointer
|
25
25
|
attach_function :tidyOptGetId, [:pointer], :int
|
26
26
|
attach_function :tidyOptSetValue, [:pointer, :int, :string], :int
|
27
|
+
|
28
|
+
# iterators
|
29
|
+
attach_function :tidyGetOptionList, [:pointer], :pointer
|
30
|
+
attach_function :tidyGetNextOption, [:pointer, :pointer], :pointer
|
31
|
+
attach_function :tidyOptGetName, [:pointer], :string
|
32
|
+
attach_function :tidyOptGetType, [:pointer], :int
|
33
|
+
attach_function :tidyOptGetDefault, [:pointer], :string
|
34
|
+
attach_function :tidyOptGetDefaultInt, [:pointer], :ulong
|
35
|
+
attach_function :tidyOptGetDefaultBool, [:pointer], :int
|
36
|
+
attach_function :tidyOptIsReadOnly, [:pointer], :int
|
37
|
+
attach_function :tidyOptGetPickList, [:pointer], :pointer
|
38
|
+
attach_function :tidyOptGetNextPick, [:pointer, :pointer], :string
|
39
|
+
|
40
|
+
#types
|
41
|
+
# /** Option data types
|
42
|
+
# */
|
43
|
+
# typedef enum
|
44
|
+
# {
|
45
|
+
# TidyString, /**< String */
|
46
|
+
# TidyInteger, /**< Integer or enumeration */
|
47
|
+
# TidyBoolean /**< Boolean flag */
|
48
|
+
# } TidyOptionType;
|
49
|
+
TIDY_OPTION_TYPE = [:string, :integer, :boolean].freeze
|
50
|
+
|
27
51
|
end
|
28
52
|
|
29
53
|
class TidyFFI::LibTidy::TidyBuf < FFI::Struct #:nodoc:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class TidyFFI::OptionsContainer #:nodoc:
|
2
|
+
|
2
3
|
def initialize(ops = nil)
|
3
4
|
if ops
|
4
5
|
@options = ops.to_hash!
|
@@ -14,6 +15,7 @@ class TidyFFI::OptionsContainer #:nodoc:
|
|
14
15
|
def merge_with_options(options)
|
15
16
|
options.each do |key, val|
|
16
17
|
key = key.intern unless Symbol === key
|
18
|
+
validate_option(key, val)
|
17
19
|
@options[key] = val
|
18
20
|
end
|
19
21
|
end
|
@@ -35,12 +37,26 @@ class TidyFFI::OptionsContainer #:nodoc:
|
|
35
37
|
|
36
38
|
def method_missing(method, *args)
|
37
39
|
if method.to_s =~ /=$/
|
38
|
-
|
40
|
+
key, val = method.to_s.sub(/=$/, '').intern, args.first
|
41
|
+
validate_option(key, val)
|
42
|
+
@options[key] = val
|
39
43
|
else
|
40
44
|
@options[method]
|
41
45
|
end
|
42
46
|
end
|
43
|
-
|
47
|
+
|
48
|
+
# It's a kinda bad method: it uses TidyFFI::Interface.option_valid and TidyFFI::Tidy.validate_options?
|
49
|
+
# Also it do second lookup into default options
|
50
|
+
def validate_option(key, value)
|
51
|
+
if TidyFFI::Tidy.validate_options? && !TidyFFI::Interface.option_valid?(key, value)
|
52
|
+
if TidyFFI::Interface.default_options[key]
|
53
|
+
raise TidyFFI::Tidy::InvalidOptionValue, "#{value} is not valid for #{key}"
|
54
|
+
else
|
55
|
+
raise TidyFFI::Tidy::InvalidOptionName, "#{key} is invalid option name"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
44
60
|
class Proxy #:nodoc:
|
45
61
|
attr_reader :options
|
46
62
|
|
data/lib/tidy_ffi/tidy.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Clean and simple interface to Tidy
|
2
2
|
class TidyFFI::Tidy
|
3
3
|
OptionsContainer = TidyFFI::OptionsContainer
|
4
|
+
class InvalidOptionName < ArgumentError; end
|
5
|
+
class InvalidOptionValue < ArgumentError; end
|
4
6
|
|
5
7
|
#Initializing object.
|
6
8
|
#
|
@@ -66,5 +68,11 @@ class TidyFFI::Tidy
|
|
66
68
|
def with_options(options)
|
67
69
|
OptionsContainer::Proxy.new(self, @default_options, options)
|
68
70
|
end
|
71
|
+
|
72
|
+
# When true it validates name and option type (default is true).
|
73
|
+
def validate_options?
|
74
|
+
@validate_options != false
|
75
|
+
end
|
76
|
+
attr_writer :validate_options
|
69
77
|
end
|
70
78
|
end
|
data/test/test_helper.rb
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class TestSimple < Test::Unit::TestCase
|
4
|
+
I = TidyFFI::Interface
|
5
|
+
context "TidyFFI::Interface" do
|
6
|
+
context "default_options" do
|
7
|
+
it "returns a hash" do
|
8
|
+
I.default_options.is_a?(Hash)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "has show force_output option" do
|
12
|
+
I.default_options[:force_output][:name].should == :force_output
|
13
|
+
I.default_options[:force_output][:type].should == :boolean
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "option_valid" do
|
18
|
+
it "returns false when unknown options is specified" do
|
19
|
+
I.option_valid?(:gobbledygook, '1').should == false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "accepts yes, no, 1, 0, true, false as boolean values" do
|
23
|
+
stub(I).default_options { {:gobbledygook => {:type => :boolean}} }
|
24
|
+
|
25
|
+
%w{yes no 1 0 true false on off YeS}.each do |val|
|
26
|
+
I.option_valid?(:gobbledygook, val).should == true
|
27
|
+
end
|
28
|
+
I.option_valid?(:gobbledygook, 1).should == true
|
29
|
+
I.option_valid?(:gobbledygook, 0).should == true
|
30
|
+
I.option_valid?(:gobbledygook, true).should == true
|
31
|
+
I.option_valid?(:gobbledygook, false).should == true
|
32
|
+
|
33
|
+
I.option_valid?(:gobbledygook, "gobbledygook").should == false
|
34
|
+
end
|
35
|
+
|
36
|
+
it "accepts a number as a valid integer value" do
|
37
|
+
stub(I).default_options { {:gobbledygook => {:type => :integer}} }
|
38
|
+
|
39
|
+
I.option_valid?(:gobbledygook, 1).should == true
|
40
|
+
I.option_valid?(:gobbledygook, 0).should == true
|
41
|
+
I.option_valid?(:gobbledygook, "0").should == true
|
42
|
+
I.option_valid?(:gobbledygook, "1").should == true
|
43
|
+
I.option_valid?(:gobbledygook, "42").should == true
|
44
|
+
|
45
|
+
I.option_valid?(:gobbledygook, "gobbledygook").should == false
|
46
|
+
I.option_valid?(:gobbledygook, "true").should == false
|
47
|
+
end
|
48
|
+
|
49
|
+
it "accepts any string as a valid string value" do
|
50
|
+
stub(I).default_options { {:gobbledygook => {:type => :string}} }
|
51
|
+
|
52
|
+
I.option_valid?(:gobbledygook, 1).should == false
|
53
|
+
I.option_valid?(:gobbledygook, 0).should == false
|
54
|
+
|
55
|
+
I.option_valid?(:gobbledygook, "0").should == true
|
56
|
+
I.option_valid?(:gobbledygook, "1").should == true
|
57
|
+
I.option_valid?(:gobbledygook, "42").should == true
|
58
|
+
I.option_valid?(:gobbledygook, "gobbledygook").should == true
|
59
|
+
I.option_valid?(:gobbledygook, "true").should == true
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
it "accepts a symbols as a valid string value" do
|
64
|
+
stub(I).default_options { {:gobbledygook => {:type => :string}} }
|
65
|
+
|
66
|
+
I.option_valid?(:gobbledygook, :test).should == true
|
67
|
+
end
|
68
|
+
|
69
|
+
it "accepts number in range as a valid enum value" do
|
70
|
+
stub(I).default_options { {:gobbledygook => {:type => :enum, :values => ["one", "two"]}} }
|
71
|
+
|
72
|
+
I.option_valid?(:gobbledygook, 1).should == true
|
73
|
+
I.option_valid?(:gobbledygook, 0).should == true
|
74
|
+
I.option_valid?(:gobbledygook, 3).should == false
|
75
|
+
end
|
76
|
+
|
77
|
+
it "accepts string representation of enum value" do
|
78
|
+
stub(I).default_options { {:gobbledygook => {:type => :enum, :values => ["one", "two"]}} }
|
79
|
+
|
80
|
+
I.option_valid?(:gobbledygook, "one").should == true
|
81
|
+
I.option_valid?(:gobbledygook, "two").should == true
|
82
|
+
I.option_valid?(:gobbledygook, "three").should == false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/test/test_options.rb
CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), 'test_helper')
|
|
3
3
|
class TestOptions < Test::Unit::TestCase
|
4
4
|
T = TidyFFI::Tidy
|
5
5
|
context "public interface" do
|
6
|
-
[:default_options, :default_options=, :with_options].each do |method|
|
6
|
+
[:default_options, :default_options=, :with_options, :validate_options].each do |method|
|
7
7
|
it "responds to #{method}" do
|
8
8
|
T.respond_to?(method)
|
9
9
|
end
|
@@ -13,6 +13,7 @@ class TestOptions < Test::Unit::TestCase
|
|
13
13
|
context "default_options method" do
|
14
14
|
before :each do
|
15
15
|
T.default_options.clear!
|
16
|
+
T.validate_options = false
|
16
17
|
end
|
17
18
|
|
18
19
|
context "equals version" do
|
@@ -38,7 +39,7 @@ class TestOptions < Test::Unit::TestCase
|
|
38
39
|
T.default_options.option = 1
|
39
40
|
T.default_options.option.should == 1
|
40
41
|
end
|
41
|
-
|
42
|
+
|
42
43
|
it "sets optons after creation" do
|
43
44
|
T.new('test').options.option.should == nil
|
44
45
|
T.default_options.option = 1
|
@@ -48,6 +49,7 @@ class TestOptions < Test::Unit::TestCase
|
|
48
49
|
|
49
50
|
context "options method" do
|
50
51
|
before :each do
|
52
|
+
T.validate_options = false
|
51
53
|
T.default_options.clear!
|
52
54
|
@t = T.new('test')
|
53
55
|
end
|
@@ -68,7 +70,7 @@ class TestOptions < Test::Unit::TestCase
|
|
68
70
|
@t.options.should == {:test => 1, :test2 => 42, :test3 => 3}
|
69
71
|
end
|
70
72
|
end
|
71
|
-
|
73
|
+
|
72
74
|
context "clear! method" do
|
73
75
|
it "clears options' options" do
|
74
76
|
@t.options.test = 1
|
@@ -89,12 +91,12 @@ class TestOptions < Test::Unit::TestCase
|
|
89
91
|
@t.options.test.should == nil
|
90
92
|
end
|
91
93
|
end
|
92
|
-
|
94
|
+
|
93
95
|
it "saves options" do
|
94
96
|
@t.options.option = 1
|
95
97
|
@t.options.option.should == 1
|
96
98
|
end
|
97
|
-
|
99
|
+
|
98
100
|
it "passes options to libtidy" do
|
99
101
|
@t.options.show_body_only = 1
|
100
102
|
@t.clean.should == "test\n"
|
@@ -102,20 +104,24 @@ class TestOptions < Test::Unit::TestCase
|
|
102
104
|
end
|
103
105
|
|
104
106
|
context "with_options proxy class" do
|
107
|
+
before :each do
|
108
|
+
T.validate_options = false
|
109
|
+
end
|
110
|
+
|
105
111
|
it "has options method" do
|
106
112
|
T.with_options(:test => 1).options.test.should == 1
|
107
113
|
end
|
108
|
-
|
114
|
+
|
109
115
|
it "has clear! method" do
|
110
116
|
T.with_options(:test => 1).clear!.options.test.should == nil
|
111
117
|
end
|
112
|
-
|
118
|
+
|
113
119
|
it "chain methods" do
|
114
120
|
proxy = T.with_options(:test => 1).with_options(:test2 => 2)
|
115
121
|
proxy.options.test.should == 1
|
116
122
|
proxy.options.test2.should == 2
|
117
123
|
end
|
118
|
-
|
124
|
+
|
119
125
|
it "passes options to object" do
|
120
126
|
T.with_options(:test => 1).new('test').options.test.should == 1
|
121
127
|
end
|
data/test/test_simple.rb
CHANGED
@@ -27,5 +27,22 @@ class TestSimple < Test::Unit::TestCase
|
|
27
27
|
t.errors.should == "line 1 column 1 - Warning: missing <!DOCTYPE> declaration\nline 1 column 1 - Warning: plain text isn't allowed in <head> elements\nline 1 column 1 - Warning: inserting missing 'title' element\n"
|
28
28
|
end
|
29
29
|
end
|
30
|
+
|
31
|
+
# Commented out, because of broken upstream matchy gem :(
|
32
|
+
# context "options validation" do
|
33
|
+
# it "raises error on invalid option name" do
|
34
|
+
# TidyFFI::Tidy.validate_options = true
|
35
|
+
# lambda do
|
36
|
+
# TidyFFI::Tidy.default_options = {:complete_garbage => true}
|
37
|
+
# end.should raise_error(TidyFFI::Tidy::InvalidOptionName)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# it "raises error on invalid option value" do
|
41
|
+
# TidyFFI::Tidy.validate_options = true
|
42
|
+
# lambda do
|
43
|
+
# TidyFFI::Tidy.default_options = {:force_output => "utter trash"}
|
44
|
+
# end.should raise_error(TidyFFI::Tidy::InvalidOptionValue)
|
45
|
+
# end
|
46
|
+
# end
|
30
47
|
end
|
31
48
|
end
|
data/tidy_ffi.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{tidy_ffi}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.4"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Eugene Pimenov"]
|
9
|
-
s.date = %q{2009-03-
|
9
|
+
s.date = %q{2009-03-14}
|
10
10
|
s.description = %q{Tidy library interface via FFI}
|
11
11
|
s.email = %q{}
|
12
12
|
s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/tidy_ffi/interface.rb", "lib/tidy_ffi/lib_tidy.rb", "lib/tidy_ffi/options_container.rb", "lib/tidy_ffi/tidy.rb", "lib/tidy_ffi/tidy_ffi_extensions.rb", "lib/tidy_ffi.rb"]
|
13
|
-
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "lib/tidy_ffi/interface.rb", "lib/tidy_ffi/lib_tidy.rb", "lib/tidy_ffi/options_container.rb", "lib/tidy_ffi/tidy.rb", "lib/tidy_ffi/tidy_ffi_extensions.rb", "lib/tidy_ffi.rb", "test/test_helper.rb", "test/test_options.rb", "test/test_simple.rb", "tidy_ffi.gemspec"]
|
13
|
+
s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "lib/tidy_ffi/interface.rb", "lib/tidy_ffi/lib_tidy.rb", "lib/tidy_ffi/options_container.rb", "lib/tidy_ffi/tidy.rb", "lib/tidy_ffi/tidy_ffi_extensions.rb", "lib/tidy_ffi.rb", "test/test_helper.rb", "test/test_options.rb", "test/test_simple.rb", "tidy_ffi.gemspec", "test/test_lowlevel.rb"]
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.homepage = %q{http://github.com/libc/tidy_ffi}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tidy_ffi", "--main", "README"]
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.rubyforge_project = %q{tidy-ffi}
|
19
19
|
s.rubygems_version = %q{1.3.1}
|
20
20
|
s.summary = %q{Tidy library interface via FFI}
|
21
|
-
s.test_files = ["test/test_helper.rb", "test/test_options.rb", "test/test_simple.rb"]
|
21
|
+
s.test_files = ["test/test_helper.rb", "test/test_lowlevel.rb", "test/test_options.rb", "test/test_simple.rb"]
|
22
22
|
|
23
23
|
if s.respond_to? :specification_version then
|
24
24
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tidy_ffi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eugene Pimenov
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-03-
|
12
|
+
date: 2009-03-14 00:00:00 +03:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -90,5 +90,6 @@ specification_version: 2
|
|
90
90
|
summary: Tidy library interface via FFI
|
91
91
|
test_files:
|
92
92
|
- test/test_helper.rb
|
93
|
+
- test/test_lowlevel.rb
|
93
94
|
- test/test_options.rb
|
94
95
|
- test/test_simple.rb
|