test/test_ldif.rb in activeldap-0.9.0 vs test/test_ldif.rb in activeldap-0.10.0
- old
+ new
@@ -1,35 +1,1849 @@
require 'al-test-utils'
class TestLDIF < Test::Unit::TestCase
- include AlTestUtils
+ include ActiveLdap::GetTextSupport
+ include AlTestUtils::Assertions
+ include AlTestUtils::Config
+ include AlTestUtils::ExampleFile
- def setup
+ priority :must
+
+ priority :normal
+ def test_unknown_change_type
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: XXX
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+changetype: |@|XXX
+EOL
+
+ assert_invalid_ldif(["unknown change type: %s", "XXX"],
+ ldif_source, 3, 13, ldif_source_with_error_mark)
end
- def teardown
+ def test_unknown_modify_type
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: modify
+XXX: postaladdress
+-
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+|@|XXX: postaladdress
+EOL
+
+ assert_invalid_ldif(["unknown modify type: %s", "XXX"],
+ ldif_source, 4, 1, ldif_source_with_error_mark)
end
- priority :must
+ def test_modify_spec_block_separator_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+add: postaladdress
+|@|
+EOL
+
+ assert_invalid_ldif("'-' is missing",
+ ldif_source, 5, 1, ldif_source_with_error_mark)
+ end
+
+ def test_modify_spec_first_line_separator_is_missing
+ ldif_source = <<-EOL.chomp
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+add: postaladdress|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 4, 19, ldif_source_with_error_mark)
+ end
+
+ def test_modify_target_attribute_name_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: modify
+add:
+-
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+add:|@|
+EOL
+
+ assert_invalid_ldif("attribute type is missing",
+ ldif_source, 4, 5, ldif_source_with_error_mark)
+ end
+
+ def test_newsuperior_separator_is_missing
+ ldif_source = <<-EOL.chomp
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+newsuperior: ou=Accounting, dc=airius, dc=com
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+newsuperior: ou=Accounting, dc=airius, dc=com|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 6, 46, ldif_source_with_error_mark)
+ end
+
+ def test_newsuperior_value_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+newsuperior:
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+newsuperior:|@|
+EOL
+
+ assert_invalid_ldif("new superior value is missing",
+ ldif_source, 6, 13, ldif_source_with_error_mark)
+ end
+
+ def test_deleteoldrdn_separator_is_missing
+ ldif_source = <<-EOL.chomp
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+deleteoldrdn: 1|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 5, 16, ldif_source_with_error_mark)
+ end
+
+ def test_invalid_deleteoldrdn_value
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: x
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+deleteoldrdn: |@|x
+EOL
+
+ assert_invalid_ldif("delete old RDN value is missing",
+ ldif_source, 5, 15, ldif_source_with_error_mark)
+ end
+
+ def test_deleteoldrdn_value_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn:
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+deleteoldrdn:|@|
+EOL
+
+ assert_invalid_ldif("delete old RDN value is missing",
+ ldif_source, 5, 14, ldif_source_with_error_mark)
+ end
+
+ def test_deleteoldrdn_mark_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+newrdn: cn=Paula Jensen
+|@|
+EOL
+
+ assert_invalid_ldif("'deleteoldrdn:' is missing",
+ ldif_source, 5, 1, ldif_source_with_error_mark)
+ end
+
+ def test_newrdn_separator_is_missing
+ ldif_source = <<-EOL.chomp
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+newrdn: cn=Paula Jensen|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 4, 24, ldif_source_with_error_mark)
+ end
+
+ def test_newrdn_value_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn:
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+newrdn:|@|
+EOL
+
+ assert_invalid_ldif("new RDN value is missing",
+ ldif_source, 4, 8, ldif_source_with_error_mark)
+ end
+
+ def test_newrdn_mark_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: moddn
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+changetype: moddn
+|@|
+EOL
+
+ assert_invalid_ldif("'newrdn:' is missing",
+ ldif_source, 4, 1, ldif_source_with_error_mark)
+ end
+
+ def test_add_change_type_without_attribute
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: add
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+changetype: add
+|@|
+EOL
+
+ assert_invalid_ldif("attribute spec is missing",
+ ldif_source, 4, 1, ldif_source_with_error_mark)
+ end
+
+ def test_change_type_with_an_extra_space
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: delete
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+changetype: delete|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 3, 19, ldif_source_with_error_mark)
+ end
+
+ def test_change_type_separator_is_missing
+ ldif_source = <<-EOL.chomp
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: delete
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+changetype: delete|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 3, 19, ldif_source_with_error_mark)
+ end
+
+ def test_change_type_value_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype:
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+changetype:|@|
+EOL
+
+ assert_invalid_ldif("change type value is missing",
+ ldif_source, 3, 12, ldif_source_with_error_mark)
+ end
+
+ def test_control_separator_is_missing
+ ldif_source = <<-EOL.chomp
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+control: 1.2.840.113556.1.4.805 true
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+control: 1.2.840.113556.1.4.805 true|@|
+EOL
+
+ assert_invalid_ldif("separator is missing",
+ ldif_source, 3, 37, ldif_source_with_error_mark)
+ end
+
+ def test_criticality_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+control: 1.2.840.113556.1.4.805
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+control: 1.2.840.113556.1.4.805 |@|
+EOL
+
+ assert_invalid_ldif("criticality is missing",
+ ldif_source, 3, 33, ldif_source_with_error_mark)
+ end
+
+ def test_control_type_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+control:
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+control:|@|
+EOL
+
+ assert_invalid_ldif("control type is missing",
+ ldif_source, 3, 9, ldif_source_with_error_mark)
+ end
+
+ def test_change_type_is_missing
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+control: 1.2.840.113556.1.4.805 true
+EOL
+
+ ldif_source_with_error_mark = <<-EOL.chomp
+control: 1.2.840.113556.1.4.805 true
+|@|
+EOL
+
+ assert_invalid_ldif("change type is missing",
+ ldif_source, 4, 1, ldif_source_with_error_mark)
+ end
+
+ def test_invalid_dn
+ ldif_source = <<-EOL
+version: 1
+dn: ou=o=Airius
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+dn: ou=o=Airius|@|
+EOL
+
+ assert_invalid_ldif(["DN is invalid: %s: %s",
+ "ou=o=Airius", "attribute type is missing"],
+ ldif_source, 2, 16, ldif_source_with_error_mark)
+ end
+
+ def test_invalid_dn_value
+ ldif_source = <<-EOL
+version: 1
+# dn:: ou=<JapaneseOU>,o=Airius
+dn: ou=営業部,o=Airius
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+dn: ou=|@|営業部,o=Airius
+EOL
+
+ assert_invalid_ldif(["DN has an invalid character: %s", "営"],
+ ldif_source, 3, 8, ldif_source_with_error_mark)
+ end
+
+ def test_multi_records_without_separator
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development, dc=airius, dc=com
+changetype: delete
+dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+seealso:
+description::
+EOL
+
+ ldif_source_with_error_mark = <<-EOL
+|@|dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+EOL
+
+ assert_invalid_ldif("separator is missing", ldif_source,
+ 4, 1, ldif_source_with_error_mark)
+ end
+
+ def test_to_s_with_blank_value
+ ldif_source = <<-EOL
+version: 1
+dn: ou=Product Development,dc=airius,dc=com
+seealso:
+description::
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: ou=Product Development,dc=airius,dc=com
+description:
+seealso:
+EOL
+ end
+
+ def test_to_s_with_last_space
+ ldif_source = <<-EOL
+version: 1
+# 'ou=Product Development,dc=airius,dc=com '
+dn:: b3U9UHJvZHVjdCBEZXZlbG9wbWVudCwgZGM9YWlyaXVzLCBkYz1jb20g
+# 'ou=Product Development,dc=airius,dc=com '
+description:: b3U9UHJvZHVjdCBEZXZlbG9wbWVudCwgZGM9YWlyaXVzLCBkYz1jb20g
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: ou=Product Development,dc=airius,dc="com "
+description:: b3U9UHJvZHVjdCBEZXZlbG9wbWVudCwgZGM9YWlyaXVzLCBkYz1jb20g
+EOL
+ end
+
+ def test_change_record_with_control
+ ldif_source = <<-EOL
+version: 1
+# Delete an entry. The operation will attach the LDAPv3
+# Tree Delete Control defined in [9]. The criticality
+# field is "true" and the controlValue field is
+# absent, as required by [9].
+dn: ou=Product Development, dc=airius, dc=com
+control: 1.2.840.113556.1.4.805 true
+changetype: delete
+EOL
+
+ change_attributes = {
+ "dn" => "ou=Product Development,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("delete", record.change_type)
+ assert_true(record.delete?)
+ assert_equal([{
+ :type => "1.2.840.113556.1.4.805",
+ :criticality => true,
+ :value => nil
+ }],
+ record.controls.collect {|control| control.to_hash})
+
+ control = record.controls[0]
+ assert_equal("1.2.840.113556.1.4.805", control.type)
+ assert_true(control.criticality?)
+ assert_nil(control.value)
+ end
+
+ def test_change_record_with_control_to_s
+ ldif_source = <<-EOL
+version: 1
+# Delete an entry. The operation will attach the LDAPv3
+# Tree Delete Control defined in [9]. The criticality
+# field is "true" and the controlValue field is
+# absent, as required by [9].
+dn: ou=Product Development, dc=airius, dc=com
+control: 1.2.840.113556.1.4.805 true
+changetype: delete
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: ou=Product Development,dc=airius,dc=com
+control: 1.2.840.113556.1.4.805 true
+changetype: delete
+EOL
+ end
+
+ def test_multi_change_type_records
+ ldif_source = <<-EOL
+version: 1
+# Add a new entry
+dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+changetype: add
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Fiona Jensen
+sn: Jensen
+uid: fiona
+telephonenumber: +1 408 555 1212
+
+# Delete an existing entry
+dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
+changetype: delete
+
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+
+# Modify an entry: add an additional value to the postaladdress
+# attribute, completely delete the description attribute, replace
+# the telephonenumber attribute with two values, and delete a specific
+# value from the facsimiletelephonenumber attribute
+dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+
+# Modify an entry: replace the postaladdress attribute with an empty
+# set of values (which will cause the attribute to be removed), and
+# delete the entire description attribute. Note that the first will
+# always succeed, while the second will only succeed if at least
+# one value for the description attribute is present.
+dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com
+changetype: modify
+replace: postaladdress
+-
+delete: description
+-
+EOL
+
+ change_attributes_add = {
+ "dn" => "cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Fiona Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["fiona"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ }
+
+ change_attributes_delete = {
+ "dn" => "cn=Robert Jensen,ou=Marketing,dc=airius,dc=com",
+ }
+
+ change_attributes_modrdn = {
+ "dn" => "cn=Paul Jensen,ou=Product Development,dc=airius,dc=com",
+ }
+
+ change_attributes_modrdn_with_new_superior = {
+ "dn" => "ou=PD Accountants,ou=Product Development,dc=airius,dc=com",
+ }
+
+ change_attributes_modify = {
+ "dn" => "cn=Paula Jensen,ou=Product Development,dc=airius,dc=com",
+ }
+
+ change_attributes_modify_with_empty_replace = {
+ "dn" => "cn=Ingrid Jensen,ou=Product Support,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1,
+ [change_attributes_add,
+ change_attributes_delete,
+ change_attributes_modrdn,
+ change_attributes_modrdn_with_new_superior,
+ change_attributes_modify,
+ change_attributes_modify_with_empty_replace],
+ ldif_source)
+ record = ldif.records[0]
+ assert_equal("add", record.change_type)
+ assert_true(record.add?)
+
+ record = ldif.records[1]
+ assert_equal("delete", record.change_type)
+ assert_true(record.delete?)
+
+ record = ldif.records[2]
+ assert_equal("modrdn", record.change_type)
+ assert_true(record.modify_rdn?)
+ assert_equal("cn=Paula Jensen", record.new_rdn)
+ assert_true(record.delete_old_rdn?)
+ assert_nil(record.new_superior)
+
+ record = ldif.records[3]
+ assert_equal("modrdn", record.change_type)
+ assert_true(record.modify_rdn?)
+ assert_equal("ou=Product Development Accountants", record.new_rdn)
+ assert_false(record.delete_old_rdn?)
+ assert_equal("ou=Accounting,dc=airius,dc=com", record.new_superior)
+
+ record = ldif.records[4]
+ assert_equal("modify", record.change_type)
+ assert_true(record.modify?)
+ operations = [
+ ["add", "postaladdress",
+ {"postaladdress" =>
+ ["123 Anystreet $ Sunnyvale, CA $ 94086"]}],
+ ["delete", "description", {}],
+ ["replace", "telephonenumber",
+ {"telephonenumber" => [
+ "+1 408 555 1234",
+ "+1 408 555 5678",
+ ]}],
+ ["delete", "facsimiletelephonenumber",
+ {"facsimiletelephonenumber" => ["+1 408 555 9876"]}],
+ ]
+ i = -1
+ actual = record.operations.collect do |operation|
+ i += 1
+ type = operations[i][0]
+ [operation.send("#{type}?"),
+ [operation.type, operation.attribute, operation.attributes]]
+ end
+ assert_equal(operations.collect {|operation| [true, operation]},
+ actual)
+
+ record = ldif.records[5]
+ assert_equal("modify", record.change_type)
+ assert_true(record.modify?)
+ operations = [
+ ["replace", "postaladdress", {}],
+ ["delete", "description", {}],
+ ]
+ i = -1
+ actual = record.operations.collect do |operation|
+ i += 1
+ type = operations[i][0]
+ [operation.send("#{type}?"),
+ [operation.type, operation.attribute, operation.attributes]]
+ end
+ assert_equal(operations.collect {|operation| [true, operation]},
+ actual)
+ end
+
+ def test_multi_change_type_records
+ ldif_source = <<-EOL
+version: 1
+# Add a new entry
+dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+changetype: add
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Fiona Jensen
+sn: Jensen
+uid: fiona
+telephonenumber: +1 408 555 1212
+
+# Delete an existing entry
+dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
+changetype: delete
+
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+
+# Modify an entry: add an additional value to the postaladdress
+# attribute, completely delete the description attribute, replace
+# the telephonenumber attribute with two values, and delete a specific
+# value from the facsimiletelephonenumber attribute
+dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+
+# Modify an entry: replace the postaladdress attribute with an empty
+# set of values (which will cause the attribute to be removed), and
+# delete the entire description attribute. Note that the first will
+# always succeed, while the second will only succeed if at least
+# one value for the description attribute is present.
+dn: cn=Ingrid Jensen, ou=Product Support, dc=airius, dc=com
+changetype: modify
+replace: postaladdress
+-
+delete: description
+-
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com
+changetype: add
+cn: Fiona Jensen
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+uid: fiona
+
+dn: cn=Robert Jensen,ou=Marketing,dc=airius,dc=com
+changetype: delete
+
+dn: cn=Paul Jensen,ou=Product Development,dc=airius,dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+
+dn: ou=PD Accountants,ou=Product Development,dc=airius,dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting,dc=airius,dc=com
+
+dn: cn=Paula Jensen,ou=Product Development,dc=airius,dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+
+dn: cn=Ingrid Jensen,ou=Product Support,dc=airius,dc=com
+changetype: modify
+replace: postaladdress
+-
+delete: description
+-
+EOL
+ end
+
+ def test_modify_record
+ ldif_source = <<-EOL
+version: 1
+# Modify an entry: add an additional value to the postaladdress
+# attribute, completely delete the description attribute, replace
+# the telephonenumber attribute with two values, and delete a specific
+# value from the facsimiletelephonenumber attribute
+dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+EOL
+
+ change_attributes = {
+ "dn" => "cn=Paula Jensen,ou=Product Development,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("modify", record.change_type)
+ assert_true(record.modify?)
+
+ operations = [
+ ["add", "postaladdress",
+ {"postaladdress" =>
+ ["123 Anystreet $ Sunnyvale, CA $ 94086"]}],
+ ["delete", "description", {}],
+ ["replace", "telephonenumber",
+ {"telephonenumber" => [
+ "+1 408 555 1234",
+ "+1 408 555 5678",
+ ]}],
+ ["delete", "facsimiletelephonenumber",
+ {"facsimiletelephonenumber" => ["+1 408 555 9876"]}],
+ ]
+ i = -1
+ actual = record.operations.collect do |operation|
+ i += 1
+ type = operations[i][0]
+ [operation.send("#{type}?"),
+ [operation.type, operation.attribute, operation.attributes]]
+ end
+ assert_equal(operations.collect {|operation| [true, operation]},
+ actual)
+ end
+
+ def test_modify_record_to_s
+ ldif_source = <<-EOL
+version: 1
+# Modify an entry: add an additional value to the postaladdress
+# attribute, completely delete the description attribute, replace
+# the telephonenumber attribute with two values, and delete a specific
+# value from the facsimiletelephonenumber attribute
+dn: cn=Paula Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Paula Jensen,ou=Product Development,dc=airius,dc=com
+changetype: modify
+add: postaladdress
+postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086
+-
+delete: description
+-
+replace: telephonenumber
+telephonenumber: +1 408 555 1234
+telephonenumber: +1 408 555 5678
+-
+delete: facsimiletelephonenumber
+facsimiletelephonenumber: +1 408 555 9876
+-
+EOL
+ end
+
+ def test_modrdn_record_with_newsuperior
+ ldif_source = <<-EOL
+version: 1
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+EOL
+
+ change_attributes = {
+ "dn" => "ou=PD Accountants,ou=Product Development,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("modrdn", record.change_type)
+ assert_true(record.modify_rdn?)
+ assert_equal("ou=Product Development Accountants", record.new_rdn)
+ assert_false(record.delete_old_rdn?)
+ assert_equal("ou=Accounting,dc=airius,dc=com", record.new_superior)
+ end
+
+ def test_modrdn_record_with_newsuperior_to_s
+ ldif_source = <<-EOL
+version: 1
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: ou=PD Accountants,ou=Product Development,dc=airius,dc=com
+changetype: modrdn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting,dc=airius,dc=com
+EOL
+ end
+
+ def test_modrdn_record
+ ldif_source = <<-EOL
+version: 1
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+
+ change_attributes = {
+ "dn" => "cn=Paul Jensen,ou=Product Development,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("modrdn", record.change_type)
+ assert_true(record.modify_rdn?)
+ assert_equal("cn=Paula Jensen", record.new_rdn)
+ assert_true(record.delete_old_rdn?)
+ assert_nil(record.new_superior)
+ end
+
+ def test_modrdn_record_to_s
+ ldif_source = <<-EOL
+version: 1
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Paul Jensen,ou=Product Development,dc=airius,dc=com
+changetype: modrdn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+ end
+
+ def test_moddn_record_with_newsuperior
+ ldif_source = <<-EOL
+version: 1
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+EOL
+
+ change_attributes = {
+ "dn" => "ou=PD Accountants,ou=Product Development,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("moddn", record.change_type)
+ assert_true(record.modify_dn?)
+ assert_equal("ou=Product Development Accountants", record.new_rdn)
+ assert_false(record.delete_old_rdn?)
+ assert_equal("ou=Accounting,dc=airius,dc=com", record.new_superior)
+ end
+
+ def test_moddn_record_with_newsuperior_to_s
+ ldif_source = <<-EOL
+version: 1
+# Rename an entry and move all of its children to a new location in
+# the directory tree (only implemented by LDAPv3 servers).
+dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting, dc=airius, dc=com
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: ou=PD Accountants,ou=Product Development,dc=airius,dc=com
+changetype: moddn
+newrdn: ou=Product Development Accountants
+deleteoldrdn: 0
+newsuperior: ou=Accounting,dc=airius,dc=com
+EOL
+ end
+
+ def test_moddn_record
+ ldif_source = <<-EOL
+version: 1
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+
+ change_attributes = {
+ "dn" => "cn=Paul Jensen,ou=Product Development,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("moddn", record.change_type)
+ assert_true(record.modify_dn?)
+ assert_equal("cn=Paula Jensen", record.new_rdn)
+ assert_true(record.delete_old_rdn?)
+ assert_nil(record.new_superior)
+ end
+
+ def test_moddn_record_to_s
+ ldif_source = <<-EOL
+version: 1
+# Modify an entry's relative distinguished name
+dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Paul Jensen,ou=Product Development,dc=airius,dc=com
+changetype: moddn
+newrdn: cn=Paula Jensen
+deleteoldrdn: 1
+EOL
+ end
+
+ def test_delete_record
+ ldif_source = <<-EOL
+version: 1
+# Delete an existing entry
+dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
+changetype: delete
+EOL
+
+ change_attributes = {
+ "dn" => "cn=Robert Jensen,ou=Marketing,dc=airius,dc=com",
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("delete", record.change_type)
+ assert_true(record.delete?)
+ end
+
+ def test_delete_record_to_s
+ ldif_source = <<-EOL
+version: 1
+# Delete an existing entry
+dn: cn=Robert Jensen, ou=Marketing, dc=airius, dc=com
+changetype: delete
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Robert Jensen,ou=Marketing,dc=airius,dc=com
+changetype: delete
+EOL
+ end
+
+ def test_add_record
+ ldif_source = <<-EOL
+version: 1
+# Add a new entry
+dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+changetype: add
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Fiona Jensen
+sn: Jensen
+uid: fiona
+telephonenumber: +1 408 555 1212
+EOL
+
+ change_attributes = {
+ "dn" => "cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Fiona Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["fiona"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ }
+
+ ldif = assert_ldif(1, [change_attributes], ldif_source)
+ record = ldif.records[0]
+ assert_equal("add", record.change_type)
+ assert_true(record.add?)
+ end
+
+ def test_add_record_to_s
+ ldif_source = <<-EOL
+version: 1
+# Add a new entry
+dn: cn=Fiona Jensen, ou=Marketing, dc=airius, dc=com
+changetype: add
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Fiona Jensen
+sn: Jensen
+uid: fiona
+telephonenumber: +1 408 555 1212
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Fiona Jensen,ou=Marketing,dc=airius,dc=com
+changetype: add
+cn: Fiona Jensen
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+uid: fiona
+EOL
+ end
+
+ def test_records_with_external_file_reference
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Horatio Jensen
+cn: Horatio N Jensen
+sn: Jensen
+uid: hjensen
+telephonenumber: +1 408 555 1212
+jpegphoto:< file://#{jpeg_photo_path}
+EOL
+
+ record = {
+ "dn" => "cn=Horatio Jensen,ou=Product Testing,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Horatio Jensen", "Horatio N Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["hjensen"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ "jpegphoto" => [jpeg_photo],
+ }
+
+ assert_ldif(1, [record], ldif_source)
+ end
+
+ def test_records_with_external_file_reference_to_s
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Horatio Jensen, ou=Product Testing, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Horatio Jensen
+cn: Horatio N Jensen
+sn: Jensen
+uid: hjensen
+telephonenumber: +1 408 555 1212
+jpegphoto:< file://#{jpeg_photo_path}
+EOL
+
+ jpeg_photo_attribute = "jpegphoto:: "
+ value = [jpeg_photo].pack("m").gsub(/\n/, '')
+ first_line_value_size = 75 - jpeg_photo_attribute.size
+ jpeg_photo_attribute << value[0, first_line_value_size] + "\n"
+ value = value[first_line_value_size..-1]
+ value.scan(/.{1,74}/).each do |line|
+ jpeg_photo_attribute << " #{line}\n"
+ end
+ jpeg_photo_attribute = jpeg_photo_attribute.chomp
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Horatio Jensen,ou=Product Testing,dc=airius,dc=com
+cn: Horatio Jensen
+cn: Horatio N Jensen
+#{jpeg_photo_attribute}
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+uid: hjensen
+EOL
+ end
+
+ def test_records_with_option_attributes
+ ldif_source = <<-EOL
+version: 1
+dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
+# dn:: ou=<JapaneseOU>,o=Airius
+objectclass: top
+objectclass: organizationalUnit
+ou:: 5Za25qWt6YOo
+# ou:: <JapaneseOU>
+ou;lang-ja:: 5Za25qWt6YOo
+# ou;lang-ja:: <JapaneseOU>
+ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
+# ou;lang-ja:: <JapaneseOU_in_phonetic_representation>
+ou;lang-en: Sales
+description: Japanese office
+
+dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
+# dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius
+userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: rogasawara
+mail: rogasawara@airius.co.jp
+givenname;lang-ja:: 44Ot44OJ44OL44O8
+# givenname;lang-ja:: <JapaneseGivenname>
+sn;lang-ja:: 5bCP56yg5Y6f
+# sn;lang-ja:: <JapaneseSn>
+cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+# cn;lang-ja:: <JapaneseCn>
+title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
+# title;lang-ja:: <JapaneseTitle>
+preferredlanguage: ja
+givenname:: 44Ot44OJ44OL44O8
+# givenname:: <JapaneseGivenname>
+sn:: 5bCP56yg5Y6f
+# sn:: <JapaneseSn>
+cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+# cn:: <JapaneseCn>
+title:: 5Za25qWt6YOoIOmDqOmVtw==
+# title:: <JapaneseTitle>
+givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
+# givenname;lang-ja;phonetic::
+ <JapaneseGivenname_in_phonetic_representation_kana>
+sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
+# sn;lang-ja;phonetic:: <JapaneseSn_in_phonetic_representation_kana>
+cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
+# cn;lang-ja;phonetic:: <JapaneseCn_in_phonetic_representation_kana>
+title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
+# title;lang-ja;phonetic::
+# <JapaneseTitle_in_phonetic_representation_kana>
+givenname;lang-en: Rodney
+sn;lang-en: Ogasawara
+cn;lang-en: Rodney Ogasawara
+title;lang-en: Sales, Director
+EOL
+
+ record1 = {
+ "dn" => "ou=営業部,o=Airius",
+ "objectclass" => ["top", "organizationalUnit"],
+ "ou" => [
+ "営業部",
+ {"lang-ja" =>
+ [
+ "営業部",
+ {"phonetic" => ["えいぎょうぶ"]},
+ ],
+ },
+ {"lang-en" => ["Sales"]},
+ ],
+ "description" => ["Japanese office"],
+ }
+
+ record2 = {
+ "dn" => "uid=rogasawara,ou=営業部,o=Airius",
+ "userpassword" => ["{SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM="],
+ "objectclass" => ["top", "person",
+ "organizationalPerson", "inetOrgPerson"],
+ "uid" => ["rogasawara"],
+ "mail" => ["rogasawara@airius.co.jp"],
+ "givenname" => [
+ {"lang-ja" =>
+ [
+ "ロドニー",
+ {"phonetic" => ["ろどにー"]},
+ ]
+ },
+ "ロドニー",
+ {"lang-en" => ["Rodney"]},
+ ],
+ "sn" => [
+ {"lang-ja" =>
+ [
+ "小笠原",
+ {"phonetic" => ["おがさわら"]},
+ ]
+ },
+ "小笠原",
+ {"lang-en" => ["Ogasawara"]},
+ ],
+ "cn" => [
+ {"lang-ja" =>
+ [
+ "小笠原 ロドニー",
+ {"phonetic" => ["おがさわら ろどにー"]},
+ ],
+ },
+ "小笠原 ロドニー",
+ {"lang-en" => ["Rodney Ogasawara"]},
+ ],
+ "title" => [
+ {"lang-ja" =>
+ [
+ "営業部 部長",
+ {"phonetic" => ["えいぎょうぶ ぶちょう"]}
+ ]
+ },
+ "営業部 部長",
+ {"lang-en" => ["Sales, Director"]},
+ ],
+ "preferredlanguage" => ["ja"],
+ }
+
+ assert_ldif(1, [record1, record2], ldif_source)
+ end
+
+ def test_records_with_option_attributes_to_s
+ ldif_source = <<-EOL
+version: 1
+dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
+# dn:: ou=<JapaneseOU>,o=Airius
+objectclass: top
+objectclass: organizationalUnit
+ou:: 5Za25qWt6YOo
+# ou:: <JapaneseOU>
+ou;lang-ja:: 5Za25qWt6YOo
+# ou;lang-ja:: <JapaneseOU>
+ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
+# ou;lang-ja:: <JapaneseOU_in_phonetic_representation>
+ou;lang-en: Sales
+description: Japanese office
+
+dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
+# dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius
+userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+objectclass: inetOrgPerson
+uid: rogasawara
+mail: rogasawara@airius.co.jp
+givenname;lang-ja:: 44Ot44OJ44OL44O8
+# givenname;lang-ja:: <JapaneseGivenname>
+sn;lang-ja:: 5bCP56yg5Y6f
+# sn;lang-ja:: <JapaneseSn>
+cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+# cn;lang-ja:: <JapaneseCn>
+title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
+# title;lang-ja:: <JapaneseTitle>
+preferredlanguage: ja
+givenname:: 44Ot44OJ44OL44O8
+# givenname:: <JapaneseGivenname>
+sn:: 5bCP56yg5Y6f
+# sn:: <JapaneseSn>
+cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+# cn:: <JapaneseCn>
+title:: 5Za25qWt6YOoIOmDqOmVtw==
+# title:: <JapaneseTitle>
+givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
+# givenname;lang-ja;phonetic::
+ <JapaneseGivenname_in_phonetic_representation_kana>
+sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
+# sn;lang-ja;phonetic:: <JapaneseSn_in_phonetic_representation_kana>
+cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
+# cn;lang-ja;phonetic:: <JapaneseCn_in_phonetic_representation_kana>
+title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
+# title;lang-ja;phonetic::
+# <JapaneseTitle_in_phonetic_representation_kana>
+givenname;lang-en: Rodney
+sn;lang-en: Ogasawara
+cn;lang-en: Rodney Ogasawara
+title;lang-en: Sales, Director
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn:: b3U95Za25qWt6YOoLG89QWlyaXVz
+description: Japanese office
+objectclass: organizationalUnit
+objectclass: top
+ou:: 5Za25qWt6YOo
+ou;lang-en: Sales
+ou;lang-ja:: 5Za25qWt6YOo
+ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2
+
+dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
+cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+cn;lang-en: Rodney Ogasawara
+cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
+cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
+givenname:: 44Ot44OJ44OL44O8
+givenname;lang-en: Rodney
+givenname;lang-ja:: 44Ot44OJ44OL44O8
+givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
+mail: rogasawara@airius.co.jp
+objectclass: inetOrgPerson
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+preferredlanguage: ja
+sn:: 5bCP56yg5Y6f
+sn;lang-en: Ogasawara
+sn;lang-ja:: 5bCP56yg5Y6f
+sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
+title:: 5Za25qWt6YOoIOmDqOmVtw==
+title;lang-en: Sales, Director
+title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
+title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
+uid: rogasawara
+userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=
+EOL
+ end
+
+ def test_an_record_with_base64_encoded_value
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Gern Jensen
+cn: Gern O Jensen
+sn: Jensen
+uid: gernj
+telephonenumber: +1 408 555 1212
+description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl
+ IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG
+ VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg
+ b3V0IG1vcmUu
+EOL
+
+ record = {
+ "dn" => "cn=Gern Jensen,ou=Product Testing,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Gern Jensen", "Gern O Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["gernj"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ "description" => ["What a careful reader you are! " +
+ "This value is base-64-encoded because it has a " +
+ "control character in it (a CR).\r By the way, " +
+ "you should really get out more."],
+ }
+ assert_ldif(1, [record], ldif_source)
+ end
+
+ def test_an_record_with_base64_encoded_value_to_s
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Gern Jensen, ou=Product Testing, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Gern Jensen
+cn: Gern O Jensen
+sn: Jensen
+uid: gernj
+telephonenumber: +1 408 555 1212
+description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVl
+ IGlzIGJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdG
+ VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQg
+ b3V0IG1vcmUu
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Gern Jensen,ou=Product Testing,dc=airius,dc=com
+cn: Gern Jensen
+cn: Gern O Jensen
+description:: V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUaGlzIHZhbHVlIGlzI
+ GJhc2UtNjQtZW5jb2RlZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRyb2wgY2hhcmFjdGVyIGluIGl
+ 0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIHJlYWxseSBnZXQgb3V0IG1vcmUu
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+uid: gernj
+EOL
+ end
+
+ def test_an_record_with_folded_attribute_value
+ ldif_source = <<-EOL
+version: 1
+dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass:top
+objectclass:person
+objectclass:organizationalPerson
+cn:Barbara Jensen
+cn:Barbara J Jensen
+cn:Babs Jensen
+sn:Jensen
+uid:bjensen
+telephonenumber:+1 408 555 1212
+description:Babs is a big sailing fan, and travels extensively in sea
+ rch of perfect sailing conditions.
+title:Product Manager, Rod and Reel Division
+EOL
+
+ record = {
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Barbara Jensen", "Barbara J Jensen", "Babs Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["bjensen"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ "description" => ["Babs is a big sailing fan, and travels extensively " +
+ "in search of perfect sailing conditions."],
+ "title" => ["Product Manager, Rod and Reel Division"],
+ }
+ assert_ldif(1, [record], ldif_source)
+ end
+
+ def test_an_record_with_folded_attribute_value_to_s
+ ldif_source = <<-EOL
+version: 1
+dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass:top
+objectclass:person
+objectclass:organizationalPerson
+cn:Barbara Jensen
+cn:Barbara J Jensen
+cn:Babs Jensen
+sn:Jensen
+uid:bjensen
+telephonenumber:+1 408 555 1212
+description:Babs is a big sailing fan, and travels extensively in sea
+ rch of perfect sailing conditions.
+title:Product Manager, Rod and Reel Division
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
+cn: Babs Jensen
+cn: Barbara J Jensen
+cn: Barbara Jensen
+description: Babs is a big sailing fan, and travels extensively in search o
+ f perfect sailing conditions.
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+title: Product Manager, Rod and Reel Division
+uid: bjensen
+EOL
+ end
+
+ def test_records
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Barbara Jensen
+cn: Barbara J Jensen
+cn: Babs Jensen
+sn: Jensen
+uid: bjensen
+telephonenumber: +1 408 555 1212
+description: A big sailing fan.
+
+dn: cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Bjorn Jensen
+sn: Jensen
+telephonenumber: +1 408 555 1212
+EOL
+
+ record1 = {
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Barbara Jensen", "Barbara J Jensen", "Babs Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["bjensen"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ "description" => ["A big sailing fan."],
+ }
+ record2 = {
+ "dn" => "cn=Bjorn Jensen,ou=Accounting,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Bjorn Jensen"],
+ "sn" => ["Jensen"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ }
+ assert_ldif(1, [record1, record2], ldif_source)
+ end
+
+ def test_records_to_s
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Barbara Jensen
+cn: Barbara J Jensen
+cn: Babs Jensen
+sn: Jensen
+uid: bjensen
+telephonenumber: +1 408 555 1212
+description: A big sailing fan.
+
+dn: cn=Bjorn Jensen, ou=Accounting, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Bjorn Jensen
+sn: Jensen
+telephonenumber: +1 408 555 1212
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
+cn: Babs Jensen
+cn: Barbara J Jensen
+cn: Barbara Jensen
+description: A big sailing fan.
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+uid: bjensen
+
+dn: cn=Bjorn Jensen,ou=Accounting,dc=airius,dc=com
+cn: Bjorn Jensen
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+EOL
+ end
+
+ def test_an_record
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Barbara Jensen
+cn: Barbara J Jensen
+cn: Babs Jensen
+sn: Jensen
+uid: bjensen
+telephonenumber: +1 408 555 1212
+description: A big sailing fan.
+EOL
+
+ record = {
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
+ "objectclass" => ["top", "person", "organizationalPerson"],
+ "cn" => ["Barbara Jensen", "Barbara J Jensen", "Babs Jensen"],
+ "sn" => ["Jensen"],
+ "uid" => ["bjensen"],
+ "telephonenumber" => ["+1 408 555 1212"],
+ "description" => ["A big sailing fan."],
+ }
+ assert_ldif(1, [record], ldif_source)
+ end
+
+ def test_an_record_to_s
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass: top
+objectclass: person
+objectclass: organizationalPerson
+cn: Barbara Jensen
+cn: Barbara J Jensen
+cn: Babs Jensen
+sn: Jensen
+uid: bjensen
+telephonenumber: +1 408 555 1212
+description: A big sailing fan.
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
+cn: Babs Jensen
+cn: Barbara J Jensen
+cn: Barbara Jensen
+description: A big sailing fan.
+objectclass: organizationalPerson
+objectclass: person
+objectclass: top
+sn: Jensen
+telephonenumber: +1 408 555 1212
+uid: bjensen
+EOL
+ end
+
+ def test_comment
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass: top
+# objectclass: person
+#objectcl
+ ass: organizationalPerson
+EOL
+
+ record = {
+ "dn" => "cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com",
+ "objectclass" => ["top"],
+ }
+ assert_ldif(1, [record], ldif_source)
+ end
+
+ def test_comment_to_s
+ ldif_source = <<-EOL
+version: 1
+dn: cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com
+objectclass: top
+# objectclass: person
+#objectcl
+ ass: organizationalPerson
+EOL
+
+ assert_ldif_to_s(<<-EOL, ldif_source)
+version: 1
+dn: cn=Barbara Jensen,ou=Product Development,dc=airius,dc=com
+objectclass: top
+EOL
+ end
+
+ def test_dn_spec
+ assert_invalid_ldif("'dn:' is missing",
+ "version: 1\n", 2, 1, "version: 1\n|@|")
+ assert_invalid_ldif("DN is missing",
+ "version: 1\ndn:", 2, 4, "dn:|@|")
+ assert_invalid_ldif("DN is missing",
+ "version: 1\ndn::", 2, 5, "dn::|@|")
+ assert_invalid_ldif("DN is missing",
+ "version: 1\ndn:\n", 2, 4, "dn:|@|\n")
+ assert_invalid_ldif("DN is missing",
+ "version: 1\ndn: \n", 2, 5, "dn: |@|\n")
+
+ dn = "cn=Barbara Jensen,ou=Product Development,dc=example,dc=com"
+ cn = "Barbara Jensen"
+ assert_valid_dn(dn, "version: 1\ndn: #{dn}\ncn:#{cn}\n")
+
+ encoded_dn = Base64.encode64(dn).gsub(/\n/, "\n ")
+ encoded_cn = Base64.encode64(cn).gsub(/\n/, "\n ")
+ assert_valid_dn(dn, "version: 1\ndn:: #{encoded_dn}\ncn::#{encoded_cn}\n")
+ end
+
def test_version_number
- assert_invalid_ldif("unsupported version: 0", "version: 0")
- assert_invalid_ldif("unsupported version: 0", "version: 0")
+ assert_valid_version(1, "version: 1\ndn: dc=com\ndc: com")
+ assert_valid_version(1, "version: 1\r\ndn: dc=com\ndc: com\n")
+ assert_valid_version(1, "version: 1\r\n\n\r\n\ndn: dc=com\ndc: com\n")
+
+ assert_invalid_ldif(["unsupported version: %d", 0],
+ "version: 0", 1, 11, "version: 0|@|")
+ assert_invalid_ldif(["unsupported version: %d", 2],
+ "version: 2", 1, 11, "version: 2|@|")
+
+ assert_invalid_ldif("separator is missing",
+ "version: 1", 1, 11, "version: 1|@|")
end
def test_version_spec
- assert_invalid_ldif("version spec is missing", "")
- assert_invalid_ldif("version spec is missing", "version:")
- assert_invalid_ldif("version spec is missing", "version: ")
- assert_invalid_ldif("version spec is missing", "version: XXX")
+ assert_invalid_ldif("version spec is missing",
+ "", 1, 1, "|@|")
+ assert_invalid_ldif("version spec is missing",
+ "VERSION: 1", 1, 1, "|@|VERSION: 1")
+ assert_invalid_ldif("version number is missing",
+ "version:", 1, 9, "version:|@|")
+ assert_invalid_ldif("version number is missing",
+ "version: ", 1, 10, "version: |@|")
+ assert_invalid_ldif("version number is missing",
+ "version: XXX", 1, 10, "version: |@|XXX")
end
- priority :normal
-
private
- def assert_invalid_ldif(reason, ldif)
+ def assert_ldif(version, records, ldif_source)
+ ldif = ActiveLdap::Ldif.parse(ldif_source)
+ assert_equal(version, ldif.version)
+ assert_equal(records,
+ ldif.records.collect {|record| record.to_hash})
+
+ reparsed_ldif = ActiveLdap::Ldif.parse(ldif.to_s)
+ assert_equal(ldif, reparsed_ldif)
+
+ ldif
+ end
+
+ def assert_valid_dn(dn, ldif_source)
+ ldif = ActiveLdap::Ldif.parse(ldif_source)
+ assert_equal([dn], ldif.records.collect {|record| record.dn})
+ end
+
+ def assert_valid_version(version, ldif_source)
+ ldif = ActiveLdap::Ldif.parse(ldif_source)
+ assert_equal(version, ldif.version)
+ end
+
+ def assert_invalid_ldif(reason, ldif, line, column, nearest)
exception = assert_raise(ActiveLdap::LdifInvalid) do
ActiveLdap::Ldif.parse(ldif)
end
- assert_equal(ldif, exception.ldif)
- assert_equal(_(reason), exception.reason)
+ reason, *params = reason
+ params = params.collect {|param| param.is_a?(String) ? _(param) : param}
+ assert_equal([_(reason) % params, line, column, nearest, ldif],
+ [exception.reason, exception.line, exception.column,
+ exception.nearest, exception.ldif])
+ end
+
+ def assert_ldif_to_s(expected_ldif_source, original_ldif_source)
+ ldif = ActiveLdap::Ldif.parse(original_ldif_source)
+ assert_equal(expected_ldif_source, ldif.to_s)
end
end