net-ldap 0.8.0 → 0.9.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.
Potentially problematic release.
This version of net-ldap might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +7 -0
- data/.travis.yml +19 -1
- data/CONTRIBUTING.md +54 -0
- data/Hacking.rdoc +2 -4
- data/History.rdoc +37 -0
- data/Manifest.txt +0 -4
- data/README.rdoc +8 -0
- data/Rakefile +1 -3
- data/lib/net/ber/core_ext.rb +5 -5
- data/lib/net/ber/core_ext/string.rb +7 -7
- data/lib/net/ber/core_ext/true_class.rb +2 -3
- data/lib/net/ldap.rb +134 -620
- data/lib/net/ldap/connection.rb +692 -0
- data/lib/net/ldap/dataset.rb +18 -4
- data/lib/net/ldap/entry.rb +1 -1
- data/lib/net/ldap/filter.rb +7 -7
- data/lib/net/ldap/password.rb +11 -11
- data/lib/net/ldap/pdu.rb +28 -4
- data/lib/net/ldap/version.rb +1 -1
- data/lib/net/snmp.rb +235 -241
- data/net-ldap.gemspec +7 -33
- data/script/install-openldap +47 -0
- data/script/package +7 -0
- data/script/release +16 -0
- data/test/ber/core_ext/test_array.rb +22 -0
- data/test/ber/core_ext/test_string.rb +25 -0
- data/test/ber/test_ber.rb +126 -0
- data/test/fixtures/openldap/memberof.ldif +33 -0
- data/test/fixtures/openldap/retcode.ldif +76 -0
- data/test/fixtures/openldap/slapd.conf.ldif +67 -0
- data/test/fixtures/seed.ldif +374 -0
- data/test/integration/test_add.rb +28 -0
- data/test/integration/test_ber.rb +30 -0
- data/test/integration/test_bind.rb +22 -0
- data/test/integration/test_delete.rb +31 -0
- data/test/integration/test_open.rb +88 -0
- data/test/integration/test_return_codes.rb +38 -0
- data/test/integration/test_search.rb +77 -0
- data/test/support/vm/openldap/.gitignore +1 -0
- data/test/support/vm/openldap/README.md +32 -0
- data/test/support/vm/openldap/Vagrantfile +33 -0
- data/test/test_dn.rb +44 -0
- data/test/test_entry.rb +62 -56
- data/test/test_filter.rb +98 -2
- data/test/test_filter_parser.rb +16 -0
- data/test/test_helper.rb +54 -0
- data/test/test_ldap.rb +60 -0
- data/test/test_ldap_connection.rb +382 -2
- data/test/test_ldif.rb +26 -1
- data/test/test_password.rb +3 -10
- data/test/test_rename.rb +2 -2
- data/test/test_search.rb +39 -0
- data/test/test_snmp.rb +1 -1
- data/test/test_ssl_ber.rb +40 -0
- metadata +70 -75
- data/.autotest +0 -11
- data/.gemtest +0 -0
- data/.rspec +0 -2
- data/autotest/discover.rb +0 -1
- data/spec/integration/ssl_ber_spec.rb +0 -39
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -28
- data/spec/unit/ber/ber_spec.rb +0 -141
- data/spec/unit/ber/core_ext/array_spec.rb +0 -24
- data/spec/unit/ber/core_ext/string_spec.rb +0 -51
- data/spec/unit/ldap/dn_spec.rb +0 -80
- data/spec/unit/ldap/entry_spec.rb +0 -51
- data/spec/unit/ldap/filter_parser_spec.rb +0 -26
- data/spec/unit/ldap/filter_spec.rb +0 -115
- data/spec/unit/ldap/search_spec.rb +0 -49
- data/spec/unit/ldap_spec.rb +0 -223
- data/test/common.rb +0 -3
@@ -1,26 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require 'spec_helper'
|
3
|
-
|
4
|
-
describe Net::LDAP::Filter::FilterParser do
|
5
|
-
|
6
|
-
describe "#parse" do
|
7
|
-
context "Given ASCIIs as filter string" do
|
8
|
-
let(:filter_string) { "(cn=name)" }
|
9
|
-
specify "should generate filter object" do
|
10
|
-
expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter
|
11
|
-
end
|
12
|
-
end
|
13
|
-
context "Given string including multibyte chars as filter string" do
|
14
|
-
let(:filter_string) { "(cn=名前)" }
|
15
|
-
specify "should generate filter object" do
|
16
|
-
expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter
|
17
|
-
end
|
18
|
-
end
|
19
|
-
context "Given string including colons ':'" do
|
20
|
-
let(:filter_string) { "(ismemberof=cn=edu:berkeley:app:calmessages:deans,ou=campus groups,dc=berkeley,dc=edu)" }
|
21
|
-
specify "should generate filter object" do
|
22
|
-
expect(Net::LDAP::Filter::FilterParser.parse(filter_string)).to be_a Net::LDAP::Filter
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Net::LDAP::Filter do
|
4
|
-
describe "<- .ex(attr, value)" do
|
5
|
-
context "('foo', 'bar')" do
|
6
|
-
attr_reader :filter
|
7
|
-
before(:each) do
|
8
|
-
@filter = Net::LDAP::Filter.ex('foo', 'bar')
|
9
|
-
end
|
10
|
-
it "should convert to 'foo:=bar'" do
|
11
|
-
filter.to_s.should == '(foo:=bar)'
|
12
|
-
end
|
13
|
-
it "should survive roundtrip via to_s/from_rfc2254" do
|
14
|
-
Net::LDAP::Filter.from_rfc2254(filter.to_s).should == filter
|
15
|
-
end
|
16
|
-
it "should survive roundtrip conversion to/from ber" do
|
17
|
-
ber = filter.to_ber
|
18
|
-
Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
|
19
|
-
filter
|
20
|
-
end
|
21
|
-
end
|
22
|
-
context "various legal inputs" do
|
23
|
-
[
|
24
|
-
'(o:dn:=Ace Industry)',
|
25
|
-
'(:dn:2.4.8.10:=Dino)',
|
26
|
-
'(cn:dn:1.2.3.4.5:=John Smith)',
|
27
|
-
'(sn:dn:2.4.6.8.10:=Barbara Jones)',
|
28
|
-
'(&(sn:dn:2.4.6.8.10:=Barbara Jones))'
|
29
|
-
].each do |filter_str|
|
30
|
-
context "from_rfc2254(#{filter_str.inspect})" do
|
31
|
-
attr_reader :filter
|
32
|
-
before(:each) do
|
33
|
-
@filter = Net::LDAP::Filter.from_rfc2254(filter_str)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should decode into a Net::LDAP::Filter" do
|
37
|
-
filter.should be_an_instance_of(Net::LDAP::Filter)
|
38
|
-
end
|
39
|
-
it "should survive roundtrip conversion to/from ber" do
|
40
|
-
ber = filter.to_ber
|
41
|
-
Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax)).should ==
|
42
|
-
filter
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
describe "<- .construct" do
|
49
|
-
it "should accept apostrophes in filters (regression)" do
|
50
|
-
Net::LDAP::Filter.construct("uid=O'Keefe").to_rfc2254.should == "(uid=O'Keefe)"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "convenience filter constructors" do
|
55
|
-
def eq(attribute, value)
|
56
|
-
described_class.eq(attribute, value)
|
57
|
-
end
|
58
|
-
describe "<- .equals(attr, val)" do
|
59
|
-
it "should delegate to .eq with escaping" do
|
60
|
-
described_class.equals('dn', 'f*oo').should == eq('dn', 'f\2Aoo')
|
61
|
-
end
|
62
|
-
end
|
63
|
-
describe "<- .begins(attr, val)" do
|
64
|
-
it "should delegate to .eq with escaping" do
|
65
|
-
described_class.begins('dn', 'f*oo').should == eq('dn', 'f\2Aoo*')
|
66
|
-
end
|
67
|
-
end
|
68
|
-
describe "<- .ends(attr, val)" do
|
69
|
-
it "should delegate to .eq with escaping" do
|
70
|
-
described_class.ends('dn', 'f*oo').should == eq('dn', '*f\2Aoo')
|
71
|
-
end
|
72
|
-
end
|
73
|
-
describe "<- .contains(attr, val)" do
|
74
|
-
it "should delegate to .eq with escaping" do
|
75
|
-
described_class.contains('dn', 'f*oo').should == eq('dn', '*f\2Aoo*')
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
describe "<- .escape(str)" do
|
80
|
-
it "should escape nul, *, (, ) and \\" do
|
81
|
-
Net::LDAP::Filter.escape("\0*()\\").should == "\\00\\2A\\28\\29\\5C"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'with a well-known BER string' do
|
86
|
-
ber = raw_string("\xa4\x2d" \
|
87
|
-
"\x04\x0b" "objectclass" \
|
88
|
-
"\x30\x1e" \
|
89
|
-
"\x80\x08" "foo" "*\\" "bar" \
|
90
|
-
"\x81\x08" "foo" "*\\" "bar" \
|
91
|
-
"\x82\x08" "foo" "*\\" "bar")
|
92
|
-
|
93
|
-
describe "<- .to_ber" do
|
94
|
-
[
|
95
|
-
"foo" "\\2A\\5C" "bar",
|
96
|
-
"foo" "\\2a\\5c" "bar",
|
97
|
-
"foo" "\\2A\\5c" "bar",
|
98
|
-
"foo" "\\2a\\5C" "bar"
|
99
|
-
].each do |escaped|
|
100
|
-
it 'unescapes escaped characters' do
|
101
|
-
filter = Net::LDAP::Filter.eq("objectclass", "#{escaped}*#{escaped}*#{escaped}")
|
102
|
-
filter.to_ber.should == ber
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe '<- .parse_ber' do
|
108
|
-
it 'escapes characters' do
|
109
|
-
escaped = Net::LDAP::Filter.escape("foo" "*\\" "bar")
|
110
|
-
filter = Net::LDAP::Filter.parse_ber(ber.read_ber(Net::LDAP::AsnSyntax))
|
111
|
-
filter.to_s.should == "(objectclass=#{escaped}*#{escaped}*#{escaped})"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# -*- ruby encoding: utf-8 -*-
|
2
|
-
|
3
|
-
describe Net::LDAP, "search method" do
|
4
|
-
class FakeConnection
|
5
|
-
def search(args)
|
6
|
-
OpenStruct.new(:result_code => 1, :message => "error", :success? => false)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
before(:each) do
|
11
|
-
@service = MockInstrumentationService.new
|
12
|
-
@connection = Net::LDAP.new :instrumentation_service => @service
|
13
|
-
@connection.instance_variable_set(:@open_connection, FakeConnection.new)
|
14
|
-
end
|
15
|
-
|
16
|
-
context "when :return_result => true" do
|
17
|
-
it "should return nil upon error" do
|
18
|
-
result_set = @connection.search(:return_result => true)
|
19
|
-
result_set.should be_nil
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
context "when :return_result => false" do
|
24
|
-
it "should return false upon error" do
|
25
|
-
result = @connection.search(:return_result => false)
|
26
|
-
result.should be_false
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context "When :return_result is not given" do
|
31
|
-
it "should return nil upon error" do
|
32
|
-
result_set = @connection.search
|
33
|
-
result_set.should be_nil
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
context "when instrumentation_service is configured" do
|
38
|
-
it "should publish a search.net_ldap event" do
|
39
|
-
events = @service.subscribe "search.net_ldap"
|
40
|
-
|
41
|
-
@connection.search :filter => "test"
|
42
|
-
|
43
|
-
payload, result = events.pop
|
44
|
-
payload.should have_key(:result)
|
45
|
-
payload.should have_key(:filter)
|
46
|
-
payload[:filter].should == "test"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
data/spec/unit/ldap_spec.rb
DELETED
@@ -1,223 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Net::LDAP do
|
4
|
-
describe "initialize" do
|
5
|
-
context "when instrumentation is configured" do
|
6
|
-
before do
|
7
|
-
@connection = flexmock(:connection, :close => true)
|
8
|
-
flexmock(Net::LDAP::Connection).should_receive(:new).and_return(@connection)
|
9
|
-
|
10
|
-
@service = MockInstrumentationService.new
|
11
|
-
end
|
12
|
-
|
13
|
-
subject do
|
14
|
-
Net::LDAP.new \
|
15
|
-
:server => "test.mocked.com", :port => 636,
|
16
|
-
:force_no_page => true, # so server capabilities are not queried
|
17
|
-
:instrumentation_service => @service
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should instrument bind" do
|
21
|
-
events = @service.subscribe "bind.net_ldap"
|
22
|
-
|
23
|
-
bind_result = flexmock(:bind_result, :success? => true)
|
24
|
-
@connection.should_receive(:bind).with(Hash).and_return(bind_result)
|
25
|
-
|
26
|
-
subject.bind.should be_true
|
27
|
-
|
28
|
-
payload, result = events.pop
|
29
|
-
result.should be_true
|
30
|
-
payload[:bind].should == bind_result
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should instrument search" do
|
34
|
-
events = @service.subscribe "search.net_ldap"
|
35
|
-
|
36
|
-
@connection.should_receive(:bind).and_return(flexmock(:bind_result, :result_code => 0))
|
37
|
-
@connection.should_receive(:search).with(Hash, Proc).
|
38
|
-
yields(entry = Net::LDAP::Entry.new("uid=user1,ou=users,dc=example,dc=com")).
|
39
|
-
and_return(flexmock(:search_result, :success? => true, :result_code => 0))
|
40
|
-
|
41
|
-
subject.search(:filter => "(uid=user1)").should be_true
|
42
|
-
|
43
|
-
payload, result = events.pop
|
44
|
-
result.should == [entry]
|
45
|
-
payload[:result].should == [entry]
|
46
|
-
payload[:filter].should == "(uid=user1)"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe Net::LDAP::Connection do
|
53
|
-
describe "initialize" do
|
54
|
-
context "when host is not responding" do
|
55
|
-
before(:each) do
|
56
|
-
flexmock(TCPSocket).
|
57
|
-
should_receive(:new).and_raise(Errno::ECONNREFUSED)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should raise LdapError" do
|
61
|
-
lambda {
|
62
|
-
Net::LDAP::Connection.new(
|
63
|
-
:server => 'test.mocked.com',
|
64
|
-
:port => 636)
|
65
|
-
}.should raise_error(Net::LDAP::LdapError)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
context "when host is blocking the port" do
|
69
|
-
before(:each) do
|
70
|
-
flexmock(TCPSocket).
|
71
|
-
should_receive(:new).and_raise(SocketError)
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should raise LdapError" do
|
75
|
-
lambda {
|
76
|
-
Net::LDAP::Connection.new(
|
77
|
-
:server => 'test.mocked.com',
|
78
|
-
:port => 636)
|
79
|
-
}.should raise_error(Net::LDAP::LdapError)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
context "on other exceptions" do
|
83
|
-
before(:each) do
|
84
|
-
flexmock(TCPSocket).
|
85
|
-
should_receive(:new).and_raise(NameError)
|
86
|
-
end
|
87
|
-
|
88
|
-
it "should rethrow the exception" do
|
89
|
-
lambda {
|
90
|
-
Net::LDAP::Connection.new(
|
91
|
-
:server => 'test.mocked.com',
|
92
|
-
:port => 636)
|
93
|
-
}.should raise_error(NameError)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context "populate error messages" do
|
99
|
-
before do
|
100
|
-
@tcp_socket = flexmock(:connection)
|
101
|
-
@tcp_socket.should_receive(:write)
|
102
|
-
flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket)
|
103
|
-
end
|
104
|
-
|
105
|
-
subject { Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636) }
|
106
|
-
|
107
|
-
it "should get back error messages if operation fails" do
|
108
|
-
ber = Net::BER::BerIdentifiedArray.new([53, "", "The provided password value was rejected by a password validator: The provided password did not contain enough characters from the character set 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. The minimum number of characters from that set that must be present in user passwords is 1"])
|
109
|
-
ber.ber_identifier = Net::LDAP::PDU::ModifyResponse
|
110
|
-
@tcp_socket.should_receive(:read_ber).and_return([2, ber])
|
111
|
-
|
112
|
-
result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]])
|
113
|
-
result.should be_failure
|
114
|
-
result.error_message.should == "The provided password value was rejected by a password validator: The provided password did not contain enough characters from the character set 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. The minimum number of characters from that set that must be present in user passwords is 1"
|
115
|
-
end
|
116
|
-
|
117
|
-
it "shouldn't get back error messages if operation succeeds" do
|
118
|
-
ber = Net::BER::BerIdentifiedArray.new([0, "", ""])
|
119
|
-
ber.ber_identifier = Net::LDAP::PDU::ModifyResponse
|
120
|
-
@tcp_socket.should_receive(:read_ber).and_return([2, ber])
|
121
|
-
|
122
|
-
result = subject.modify(:dn => "1", :operations => [[:replace, "mail", "something@sothsdkf.com"]])
|
123
|
-
result.should be_success
|
124
|
-
result.error_message.should == ""
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
context "instrumentation" do
|
129
|
-
before do
|
130
|
-
@tcp_socket = flexmock(:connection)
|
131
|
-
# handle write
|
132
|
-
@tcp_socket.should_receive(:write)
|
133
|
-
# return this mock
|
134
|
-
flexmock(TCPSocket).should_receive(:new).and_return(@tcp_socket)
|
135
|
-
|
136
|
-
@service = MockInstrumentationService.new
|
137
|
-
end
|
138
|
-
|
139
|
-
subject do
|
140
|
-
Net::LDAP::Connection.new(:server => 'test.mocked.com', :port => 636,
|
141
|
-
:instrumentation_service => @service)
|
142
|
-
end
|
143
|
-
|
144
|
-
it "should publish a write.net_ldap_connection event" do
|
145
|
-
ber = Net::BER::BerIdentifiedArray.new([0, "", ""])
|
146
|
-
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
147
|
-
read_result = [2, ber]
|
148
|
-
@tcp_socket.should_receive(:read_ber).and_return(read_result)
|
149
|
-
|
150
|
-
events = @service.subscribe "write.net_ldap_connection"
|
151
|
-
|
152
|
-
result = subject.bind(method: :anon)
|
153
|
-
result.should be_success
|
154
|
-
|
155
|
-
# a write event
|
156
|
-
payload, result = events.pop
|
157
|
-
payload.should have_key(:result)
|
158
|
-
payload.should have_key(:content_length)
|
159
|
-
end
|
160
|
-
|
161
|
-
it "should publish a read.net_ldap_connection event" do
|
162
|
-
ber = Net::BER::BerIdentifiedArray.new([0, "", ""])
|
163
|
-
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
164
|
-
read_result = [2, ber]
|
165
|
-
@tcp_socket.should_receive(:read_ber).and_return(read_result)
|
166
|
-
|
167
|
-
events = @service.subscribe "read.net_ldap_connection"
|
168
|
-
|
169
|
-
result = subject.bind(method: :anon)
|
170
|
-
result.should be_success
|
171
|
-
|
172
|
-
# a read event
|
173
|
-
payload, result = events.pop
|
174
|
-
payload.should have_key(:result)
|
175
|
-
result.should == read_result
|
176
|
-
end
|
177
|
-
|
178
|
-
it "should publish a bind.net_ldap_connection event" do
|
179
|
-
ber = Net::BER::BerIdentifiedArray.new([0, "", ""])
|
180
|
-
ber.ber_identifier = Net::LDAP::PDU::BindResult
|
181
|
-
bind_result = [2, ber]
|
182
|
-
@tcp_socket.should_receive(:read_ber).and_return(bind_result)
|
183
|
-
|
184
|
-
events = @service.subscribe "bind.net_ldap_connection"
|
185
|
-
|
186
|
-
result = subject.bind(method: :anon)
|
187
|
-
result.should be_success
|
188
|
-
|
189
|
-
# a read event
|
190
|
-
payload, result = events.pop
|
191
|
-
payload.should have_key(:result)
|
192
|
-
result.should be_success
|
193
|
-
end
|
194
|
-
|
195
|
-
it "should publish a search.net_ldap_connection event" do
|
196
|
-
# search data
|
197
|
-
search_data_ber = Net::BER::BerIdentifiedArray.new([2, [
|
198
|
-
"uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local",
|
199
|
-
[ ["uid", ["user1"]] ]
|
200
|
-
]])
|
201
|
-
search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData
|
202
|
-
search_data = [2, search_data_ber]
|
203
|
-
# search result (end of results)
|
204
|
-
search_result_ber = Net::BER::BerIdentifiedArray.new([0, "", ""])
|
205
|
-
search_result_ber.ber_identifier = Net::LDAP::PDU::SearchResult
|
206
|
-
search_result = [2, search_result_ber]
|
207
|
-
@tcp_socket.should_receive(:read_ber).and_return(search_data).
|
208
|
-
and_return(search_result)
|
209
|
-
|
210
|
-
events = @service.subscribe "search.net_ldap_connection"
|
211
|
-
|
212
|
-
result = subject.search(filter: "(uid=user1)")
|
213
|
-
result.should be_success
|
214
|
-
|
215
|
-
# a search event
|
216
|
-
payload, result = events.pop
|
217
|
-
payload.should have_key(:result)
|
218
|
-
payload.should have_key(:filter)
|
219
|
-
payload[:filter].to_s.should == "(uid=user1)"
|
220
|
-
result.should be_truthy
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
data/test/common.rb
DELETED