ruby-activeldap 0.7.4 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/CHANGES +375 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +58 -0
  4. data/Manifest.txt +33 -0
  5. data/README +63 -0
  6. data/Rakefile +37 -0
  7. data/TODO +31 -0
  8. data/benchmark/bench-al.rb +152 -0
  9. data/lib/{activeldap.rb → active_ldap.rb} +280 -263
  10. data/lib/active_ldap/adaptor/base.rb +29 -0
  11. data/lib/active_ldap/adaptor/ldap.rb +466 -0
  12. data/lib/active_ldap/association/belongs_to.rb +38 -0
  13. data/lib/active_ldap/association/belongs_to_many.rb +40 -0
  14. data/lib/active_ldap/association/collection.rb +80 -0
  15. data/lib/active_ldap/association/has_many.rb +48 -0
  16. data/lib/active_ldap/association/has_many_wrap.rb +56 -0
  17. data/lib/active_ldap/association/proxy.rb +89 -0
  18. data/lib/active_ldap/associations.rb +162 -0
  19. data/lib/active_ldap/attributes.rb +199 -0
  20. data/lib/active_ldap/base.rb +1343 -0
  21. data/lib/active_ldap/callbacks.rb +19 -0
  22. data/lib/active_ldap/command.rb +46 -0
  23. data/lib/active_ldap/configuration.rb +96 -0
  24. data/lib/active_ldap/connection.rb +137 -0
  25. data/lib/{activeldap → active_ldap}/ldap.rb +1 -1
  26. data/lib/active_ldap/object_class.rb +70 -0
  27. data/lib/active_ldap/schema.rb +258 -0
  28. data/lib/{activeldap → active_ldap}/timeout.rb +0 -0
  29. data/lib/{activeldap → active_ldap}/timeout_stub.rb +0 -0
  30. data/lib/active_ldap/user_password.rb +92 -0
  31. data/lib/active_ldap/validations.rb +78 -0
  32. data/rails/plugin/active_ldap/README +54 -0
  33. data/rails/plugin/active_ldap/init.rb +6 -0
  34. data/test/TODO +2 -0
  35. data/test/al-test-utils.rb +337 -0
  36. data/test/command.rb +62 -0
  37. data/test/config.yaml +8 -0
  38. data/test/config.yaml.sample +6 -0
  39. data/test/run-test.rb +17 -0
  40. data/test/test-unit-ext.rb +2 -0
  41. data/test/test_associations.rb +334 -0
  42. data/test/test_attributes.rb +71 -0
  43. data/test/test_base.rb +345 -0
  44. data/test/test_base_per_instance.rb +32 -0
  45. data/test/test_bind.rb +53 -0
  46. data/test/test_callback.rb +35 -0
  47. data/test/test_connection.rb +38 -0
  48. data/test/test_connection_per_class.rb +50 -0
  49. data/test/test_find.rb +36 -0
  50. data/test/test_groupadd.rb +50 -0
  51. data/test/test_groupdel.rb +46 -0
  52. data/test/test_groupls.rb +107 -0
  53. data/test/test_groupmod.rb +51 -0
  54. data/test/test_lpasswd.rb +75 -0
  55. data/test/test_object_class.rb +32 -0
  56. data/test/test_reflection.rb +173 -0
  57. data/test/test_schema.rb +166 -0
  58. data/test/test_user.rb +209 -0
  59. data/test/test_user_password.rb +93 -0
  60. data/test/test_useradd-binary.rb +59 -0
  61. data/test/test_useradd.rb +55 -0
  62. data/test/test_userdel.rb +48 -0
  63. data/test/test_userls.rb +86 -0
  64. data/test/test_usermod-binary-add-time.rb +62 -0
  65. data/test/test_usermod-binary-add.rb +61 -0
  66. data/test/test_usermod-binary-del.rb +64 -0
  67. data/test/test_usermod-lang-add.rb +57 -0
  68. data/test/test_usermod.rb +56 -0
  69. data/test/test_validation.rb +38 -0
  70. metadata +94 -21
  71. data/lib/activeldap/associations.rb +0 -170
  72. data/lib/activeldap/base.rb +0 -1456
  73. data/lib/activeldap/configuration.rb +0 -59
  74. data/lib/activeldap/schema2.rb +0 -217
data/test/command.rb ADDED
@@ -0,0 +1,62 @@
1
+ require "thread"
2
+ require "socket"
3
+ require "shellwords"
4
+
5
+ module Command
6
+ class Error < StandardError
7
+ attr_reader :command, :result
8
+ def initialize(command, result)
9
+ @command = command
10
+ @result = result
11
+ super("#{command}: #{result}")
12
+ end
13
+ end
14
+
15
+ module_function
16
+ def detach_io
17
+ require 'fcntl'
18
+ [TCPSocket, ::File].each do |c|
19
+ ObjectSpace.each_object(c) do |io|
20
+ begin
21
+ unless io.closed?
22
+ io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
23
+ end
24
+ rescue SystemCallError,IOError => e
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def run(cmd, *args)
31
+ raise ArgumentError, "command isn't specified" if cmd.nil?
32
+ if args.any? {|x| x.nil?}
33
+ raise ArgumentError, "args has nil: #{args.inspect}"
34
+ end
35
+ in_r, in_w = IO.pipe
36
+ out_r, out_w = IO.pipe
37
+ pid = exit_status = nil
38
+ Thread.exclusive do
39
+ verbose = $VERBOSE
40
+ # ruby(>=1.8)'s fork terminates other threads with warning messages
41
+ $VERBOSE = nil
42
+ pid = fork do
43
+ $VERBOSE = verbose
44
+ detach_io
45
+ out = STDERR.dup
46
+ STDIN.reopen(in_r)
47
+ in_r.close
48
+ STDOUT.reopen(out_w)
49
+ STDERR.reopen(out_w)
50
+ out_w.close
51
+ exec(cmd, *args.collect {|arg| arg.to_s})
52
+ exit!(-1)
53
+ end
54
+ $VERBOSE = verbose
55
+ end
56
+ yield(out_r, in_w) if block_given?
57
+ in_r.close unless in_r.closed?
58
+ out_w.close unless out_w.closed?
59
+ pid, status = Process.waitpid2(pid)
60
+ [status.exited? && status.exitstatus.zero?, out_r.read]
61
+ end
62
+ end
data/test/config.yaml ADDED
@@ -0,0 +1,8 @@
1
+ test:
2
+ host: 127.0.0.1
3
+ method: :plain
4
+ base: dc=localdomain
5
+ bind_dn: cn=admin,dc=localdomain
6
+ password: password
7
+ retry_limit: 1
8
+ timeout: 0
@@ -0,0 +1,6 @@
1
+ test:
2
+ host: 127.0.0.1
3
+ base: dc=test,dc=localdomain
4
+ method: :tls
5
+ bind_dn: cn=user-name,dc=localdomain
6
+ password: secret
data/test/run-test.rb ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require "test/unit"
5
+
6
+ base_dir = File.expand_path(File.dirname(__FILE__))
7
+ top_dir = File.expand_path(File.join(base_dir, ".."))
8
+ $LOAD_PATH.unshift(File.join(top_dir, "lib"))
9
+ $LOAD_PATH.unshift(File.join(top_dir, "test"))
10
+
11
+ require 'test-unit-ext'
12
+
13
+ if Test::Unit::AutoRunner.respond_to?(:standalone?)
14
+ exit Test::Unit::AutoRunner.run($0, File.dirname($0))
15
+ else
16
+ exit Test::Unit::AutoRunner.run(false, File.dirname($0))
17
+ end
@@ -0,0 +1,2 @@
1
+ require "test-unit-ext/always-show-result"
2
+ require "test-unit-ext/priority"
@@ -0,0 +1,334 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestAssociations < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ priority :must
7
+ def test_belongs_to_many_delete
8
+ make_temporary_group do |group1|
9
+ make_temporary_group do |group2|
10
+ make_temporary_user do |user,|
11
+ user.update_attribute(:cn, "new #{user.cn}")
12
+
13
+ user.groups = [group1, group2]
14
+ assert_equal([group1.id, group2.id].sort,
15
+ user.groups.collect {|g| g.id}.sort)
16
+ assert_equal([user.id].sort, group1.member_uid(true))
17
+ assert_equal([user.id].sort, group2.member_uid(true))
18
+
19
+ user.groups = []
20
+ assert_equal([], user.groups.to_a)
21
+ assert_equal([], group1.member_uid(true))
22
+ assert_equal([], group2.member_uid(true))
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ priority :normal
29
+ def test_belongs_to_before_save
30
+ make_temporary_group do |group1|
31
+ make_temporary_group do |group2|
32
+ ensure_delete_group(group2.cn.succ) do |group3_name|
33
+ group3 = @group_class.new(group3_name)
34
+ group3.gid_number = group2.gid_number.succ
35
+ make_temporary_user(:gid_number => group1.gid_number) do |user,|
36
+ assert_equal(group1.gid_number, user.primary_group.gid_number)
37
+ assert_equal(group1.gid_number, user.gid_number)
38
+
39
+ user.primary_group = group2
40
+ assert_equal(group2.gid_number, user.primary_group.gid_number)
41
+ assert_equal(group2.gid_number, user.gid_number)
42
+
43
+ user_in_ldap = @user_class.find(user.id)
44
+ assert_equal(group1.gid_number,
45
+ user_in_ldap.primary_group.gid_number)
46
+ assert_equal(group1.gid_number, user_in_ldap.gid_number)
47
+
48
+ assert(group3.new_entry?)
49
+ user.primary_group = group3
50
+ assert_equal(group3.gid_number, user.primary_group.gid_number)
51
+ assert_equal(group2.gid_number, user.gid_number)
52
+
53
+ assert(user.save)
54
+ assert_equal(group3.gid_number, user.gid_number)
55
+
56
+ user_in_ldap = @user_class.find(user.id)
57
+ assert(!user_in_ldap.primary_group.exists?)
58
+
59
+ assert(group3.save)
60
+ assert(user_in_ldap.primary_group.exists?)
61
+ assert_equal(group3.gid_number,
62
+ user_in_ldap.primary_group.gid_number)
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ def test_extend
70
+ mod = Module.new
71
+ mod.__send__(:mattr_accessor, :called)
72
+ mod.__send__(:define_method, :replace) do |entries|
73
+ super
74
+ mod.called = true
75
+ end
76
+ mod.called = false
77
+
78
+ @group_class.send(:undef_method, :members, :members=)
79
+ @group_class.has_many :members, :wrap => "memberUid",
80
+ :extend => mod
81
+ @group_class.set_associated_class(:members, @user_class)
82
+
83
+ make_temporary_group do |group|
84
+ gid_number1 = group.gid_number.to_i + 1
85
+ make_temporary_user(:gid_number => gid_number1) do |user1, password1|
86
+ user1.update_attribute(:cn, "new #{user1.cn}")
87
+
88
+ assert(!mod.called)
89
+ group.members = [user1]
90
+ assert(mod.called)
91
+ end
92
+ end
93
+ end
94
+
95
+ def test_has_many_wrap_assign
96
+ make_temporary_group do |group|
97
+ gid_number1 = group.gid_number.to_i + 1
98
+ gid_number2 = group.gid_number.to_i + 2
99
+ make_temporary_user(:gid_number => gid_number1) do |user1, password1|
100
+ make_temporary_user(:gid_number => gid_number2) do |user2, password2|
101
+ user1.update_attribute(:cn, "new #{user1.cn}")
102
+ user2.update_attribute(:cn, "new #{user2.cn}")
103
+
104
+ assert_equal([], group.members.to_a)
105
+ assert_equal([], group.member_uid(true))
106
+
107
+ assert_equal(gid_number1, user1.gid_number.to_i)
108
+ assert_equal(gid_number2, user2.gid_number.to_i)
109
+ group.members = [user1, user2]
110
+ assert_equal([user1.uid, user2.uid].sort,
111
+ group.members.collect {|x| x.uid}.sort)
112
+ assert_equal([user1.uid, user2.uid].sort, group.member_uid.sort)
113
+ assert_equal(gid_number2, user2.gid_number.to_i)
114
+
115
+ group.members = [user1]
116
+ assert_equal([user1.uid].sort,
117
+ group.members.collect {|x| x.uid}.sort)
118
+ assert_equal([user1.uid].sort, group.member_uid.sort)
119
+ assert_equal(gid_number1, user1.gid_number.to_i)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ def test_has_many_validation
126
+ group_class = Class.new(ActiveLdap::Base)
127
+ group_class.ldap_mapping :prefix => "ou=Groups",
128
+ :scope => :sub,
129
+ :classes => ["posixGroup"]
130
+ assert_raises(ArgumentError) do
131
+ group_class.has_many :members, :class_name => "User"
132
+ end
133
+
134
+ mod = Module.new
135
+ assert_nothing_raised do
136
+ group_class.has_many :members, :class => "User", :wrap => "memberUid",
137
+ :extend => mod
138
+ group_class.has_many :primary_members, :class => "User",
139
+ :foreign_key => "gidNumber",
140
+ :primary_key => "gidNumber",
141
+ :extend => mod
142
+ end
143
+ end
144
+
145
+ def test_belongs_to_validation
146
+ user_class = Class.new(ActiveLdap::Base)
147
+ user_class.ldap_mapping :dn_attribute => "uid",
148
+ :prefix => "ou=Users",
149
+ :scope => :sub,
150
+ :classes => ["posixAccount", "person"]
151
+ assert_raises(ArgumentError) do
152
+ user_class.belongs_to :groups, :class_name => "Group"
153
+ end
154
+
155
+ mod = Module.new
156
+ assert_nothing_raised do
157
+ user_class.belongs_to :groups, :class => "Group", :many => "memberUid",
158
+ :extend => mod
159
+ user_class.belongs_to :primary_group, :class => "Group",
160
+ :foreign_key => "gidNumber",
161
+ :primary_key => "gidNumber",
162
+ :extend => mod
163
+ end
164
+ end
165
+
166
+ def test_has_many_assign
167
+ make_temporary_group do |group|
168
+ gid_number1 = group.gid_number.to_i + 1
169
+ gid_number2 = group.gid_number.to_i + 2
170
+ make_temporary_user(:gid_number => gid_number1) do |user1, password1|
171
+ make_temporary_user(:gid_number => gid_number2) do |user2, password2|
172
+ assert_equal(gid_number1, user1.gid_number.to_i)
173
+ group.primary_members = [user1]
174
+ assert_equal([user1.uid].sort,
175
+ group.primary_members.collect {|x| x.uid}.sort)
176
+ assert_equal(group.gid_number, user1.gid_number)
177
+
178
+ assert_equal(gid_number2, user2.gid_number.to_i)
179
+ group.primary_members = [user1, user2]
180
+ assert_equal([user1.uid, user2.uid].sort,
181
+ group.primary_members.collect {|x| x.uid}.sort)
182
+ assert_equal(group.gid_number, user2.gid_number)
183
+
184
+
185
+ assert_raises(ActiveLdap::RequiredAttributeMissed) do
186
+ group.primary_members = []
187
+ end
188
+
189
+ assert_raises(ActiveLdap::RequiredAttributeMissed) do
190
+ group.primary_members = [user1]
191
+ end
192
+
193
+ assert_raises(ActiveLdap::RequiredAttributeMissed) do
194
+ group.primary_members = [user2]
195
+ end
196
+
197
+ assert_nothing_raised do
198
+ group.primary_members = [user1, user2]
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ def test_belongs_to_many
206
+ make_temporary_group do |group1|
207
+ make_temporary_group do |group2|
208
+ make_temporary_user do |user,|
209
+ user.update_attribute(:cn, "new #{user.cn}")
210
+
211
+ assert_equal([], user.groups.to_a)
212
+ assert_equal([], group1.member_uid(true))
213
+ assert_equal([], group2.member_uid(true))
214
+
215
+ user.groups << group1
216
+ assert_equal([group1.id].sort, user.groups.collect {|g| g.id}.sort)
217
+ assert_equal([user.id].sort, group1.member_uid(true))
218
+ assert_equal([].sort, group2.member_uid(true))
219
+
220
+ user.groups << group2
221
+ assert_equal([group1.id, group2.id].sort,
222
+ user.groups.collect {|g| g.id}.sort)
223
+ assert_equal([user.id].sort, group1.member_uid(true))
224
+ assert_equal([user.id].sort, group2.member_uid(true))
225
+ end
226
+ end
227
+ end
228
+ end
229
+
230
+ def test_belongs_to_many_non_exist
231
+ make_temporary_group do |group|
232
+ ensure_delete_user("temp-user1") do |user1,|
233
+ options = {:uid => "temp-user2", :gid_number => group.gid_number.succ}
234
+ make_temporary_user(options) do |user2,|
235
+ ensure_delete_user("temp-user3") do |user3,|
236
+ group.members << user2
237
+ group.member_uid = [user1, group.member_uid, user3]
238
+ assert(group.save)
239
+ group.members.reload
240
+ assert_equal([user1, user2.id, user3],
241
+ group.members.collect {|g| g.id})
242
+ assert_equal([true, false, true],
243
+ group.members.collect {|g| g.new_entry?})
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+
250
+ def test_belongs_to
251
+ make_temporary_group do |group|
252
+ gid_number = group.gid_number.to_i + 1
253
+ make_temporary_user(:gid_number => group.gid_number) do |user_in_group,|
254
+ make_temporary_user(:gid_number => gid_number) do |user_not_in_group,|
255
+ assert(user_in_group.primary_group.reload)
256
+ assert(user_in_group.primary_group.loaded?)
257
+ assert_equal(group.gid_number, user_in_group.gid_number)
258
+ assert_equal(group.gid_number, user_in_group.primary_group.gid_number)
259
+
260
+
261
+ assert(!user_not_in_group.primary_group.loaded?)
262
+
263
+ assert_equal(gid_number, user_not_in_group.gid_number.to_i)
264
+ assert_not_equal(group.gid_number, user_not_in_group.gid_number)
265
+
266
+ user_not_in_group.primary_group = group
267
+ assert(user_not_in_group.primary_group.loaded?)
268
+ assert(user_not_in_group.primary_group.updated?)
269
+ assert_equal(group.gid_number, user_not_in_group.gid_number)
270
+ assert_equal(group.gid_number,
271
+ user_not_in_group.primary_group.gid_number)
272
+ assert_not_equal(gid_number, user_not_in_group.gid_number.to_i)
273
+
274
+ assert_equal(group.gid_number, user_in_group.gid_number)
275
+ assert_equal(group.gid_number, user_in_group.primary_group.gid_number)
276
+ end
277
+ end
278
+ end
279
+ end
280
+
281
+ def test_has_many_wrap
282
+ make_temporary_group do |group|
283
+ gid_number1 = group.gid_number.to_i + 1
284
+ gid_number2 = group.gid_number.to_i + 2
285
+ make_temporary_user(:gid_number => gid_number1) do |user1, password1|
286
+ make_temporary_user(:gid_number => gid_number2) do |user2, password2|
287
+ user1.update_attribute(:cn, "new #{user1.cn}")
288
+ user2.update_attribute(:cn, "new #{user2.cn}")
289
+
290
+ assert_equal([], group.members.to_a)
291
+ assert_equal([], group.member_uid(true))
292
+
293
+ assert_equal(gid_number1, user1.gid_number.to_i)
294
+ group.members << user1
295
+ assert_equal([user1.uid].sort,
296
+ group.members.collect {|x| x.uid}.sort)
297
+ assert_equal([user1.uid].sort, group.member_uid.sort)
298
+ assert_equal(gid_number1, user1.gid_number.to_i)
299
+
300
+ assert_equal(gid_number2, user2.gid_number.to_i)
301
+ group.members << user2
302
+ assert_equal([user1.uid, user2.uid].sort,
303
+ group.members.collect {|x| x.uid}.sort)
304
+ assert_equal([user1.uid, user2.uid].sort, group.member_uid.sort)
305
+ assert_equal(gid_number2, user2.gid_number.to_i)
306
+ end
307
+ end
308
+ end
309
+ end
310
+
311
+ def test_has_many
312
+ make_temporary_group do |group|
313
+ gid_number1 = group.gid_number.to_i + 1
314
+ gid_number2 = group.gid_number.to_i + 2
315
+ make_temporary_user(:gid_number => gid_number1) do |user1, password1|
316
+ make_temporary_user(:gid_number => gid_number2) do |user2, password2|
317
+ assert_equal([], group.primary_members.to_a)
318
+
319
+ assert_equal(gid_number1, user1.gid_number.to_i)
320
+ group.primary_members << user1
321
+ assert_equal([user1.uid].sort,
322
+ group.primary_members.collect {|x| x.uid}.sort)
323
+ assert_equal(group.gid_number, user1.gid_number)
324
+
325
+ assert_equal(gid_number2, user2.gid_number.to_i)
326
+ group.primary_members << user2
327
+ assert_equal([user1.uid, user2.uid].sort,
328
+ group.primary_members.collect {|x| x.uid}.sort)
329
+ assert_equal(group.gid_number, user2.gid_number)
330
+ end
331
+ end
332
+ end
333
+ end
334
+ end
@@ -0,0 +1,71 @@
1
+ require 'al-test-utils'
2
+
3
+ class TestAttributes < Test::Unit::TestCase
4
+ include AlTestUtils
5
+
6
+ priority :must
7
+ def test_protect_object_class_from_mass_assignment
8
+ classes = @user_class.required_classes + ["inetOrgPerson"]
9
+ user = @user_class.new(:uid => "XXX", :object_class => classes)
10
+ assert_equal(["inetOrgPerson"],
11
+ user.classes - @user_class.required_classes)
12
+
13
+ user = @user_class.new(:uid => "XXX", :object_class => ['inetOrgPerson'])
14
+ assert_equal(["inetOrgPerson"],
15
+ user.classes - @user_class.required_classes)
16
+
17
+ user = @user_class.new("XXX")
18
+ assert_equal([], user.classes - @user_class.required_classes)
19
+ user.attributes = {:object_class => classes}
20
+ assert_equal([], user.classes - @user_class.required_classes)
21
+ end
22
+
23
+ priority :normal
24
+ def test_normalize_attribute
25
+ assert_equal(["usercertificate", [{"binary" => []}]],
26
+ ActiveLdap::Base.normalize_attribute("userCertificate", []))
27
+ assert_equal(["usercertificate", [{"binary" => []}]],
28
+ ActiveLdap::Base.normalize_attribute("userCertificate", nil))
29
+ end
30
+
31
+ def test_unnormalize_attribute
32
+ assert_equal({"userCertificate;binary" => []},
33
+ ActiveLdap::Base.unnormalize_attribute("userCertificate",
34
+ [{"binary" => []}]))
35
+ end
36
+
37
+ def test_attr_protected
38
+ user = @user_class.new(:uid => "XXX")
39
+ assert_equal("XXX", user.uid)
40
+ user.attributes = {:uid => "ZZZ"}
41
+ assert_equal("XXX", user.uid)
42
+
43
+ user = @user_class.new(:sn => "ZZZ")
44
+ assert_equal("ZZZ", user.sn)
45
+
46
+ user = @user_class.new(:uid => "XXX", :sn => "ZZZ")
47
+ assert_equal("XXX", user.uid)
48
+ assert_equal("ZZZ", user.sn)
49
+
50
+ @user_class.attr_protected :sn
51
+ user = @user_class.new(:sn => "ZZZ")
52
+ assert_nil(user.sn)
53
+
54
+ sub_user_class = Class.new(@user_class)
55
+ sub_user_class.ldap_mapping :dn_attribute => "uid"
56
+ user = sub_user_class.new(:uid => "XXX", :sn => "ZZZ")
57
+ assert_equal("XXX", user.uid)
58
+ assert_nil(user.sn)
59
+
60
+ sub_user_class.attr_protected :cn
61
+ user = sub_user_class.new(:uid => "XXX", :sn => "ZZZ", :cn => "Common Name")
62
+ assert_equal("XXX", user.uid)
63
+ assert_nil(user.sn)
64
+ assert_nil(user.cn)
65
+
66
+ user = @user_class.new(:uid => "XXX", :sn => "ZZZ", :cn => "Common Name")
67
+ assert_equal("XXX", user.uid)
68
+ assert_nil(user.sn)
69
+ assert_equal("Common Name", user.cn)
70
+ end
71
+ end