Index: ucs-test-ucsschool/90_ucsschool/215_import-users_username_dry-run =================================================================== --- ucs-test-ucsschool/90_ucsschool/215_import-users_username_dry-run (Revision 80401) +++ ucs-test-ucsschool/90_ucsschool/215_import-users_username_dry-run (Arbeitskopie) @@ -1,12 +1,12 @@ #!/usr/share/ucs-test/runner python ## -*- coding: utf-8 -*- -## desc: remove illegal characters from username (Bug 42313) +## desc: test UsernameHandler with --dry-run (Bug 42465) ## tags: [apptest,ucsschool,skip_in_multiserver,ucsschool_import] ## roles: [domaincontroller_master] ## exposure: dangerous ## packages: ## - ucs-school-import -## bugs: [42313] +## bugs: [42465] import copy import string @@ -18,8 +18,6 @@ from univention.testing.ucs_samba import wait_for_drs_replication from univention.admin.uldap import getAdminConnection from univention.admin.uexceptions import noObject, ldapError -from ucsschool.importer.utils.username_handler import UsernameHandler -from ucsschool.importer.exceptions import FormatError from essential.importusers import Person from essential.importusers_cli_v2 import CLI_Import_v2_Tester @@ -46,7 +44,7 @@ self.log.error("DN %r -> %s", dn, exc) super(Test, self).cleanup() - def test(self): # formally test_create_with_illegal_chars_in_username() + def test(self): """ Bug #42313: remove illegal characters from username * "Username must only contain numbers, letters and dots, and may not be 'admin'!" @@ -62,143 +60,70 @@ name = name.strip(".") return name.translate(None, bad_chars) - for role in ('student', 'teacher', 'teacher_and_staff'): - random_puncts = list(string.punctuation) - random.shuffle(random_puncts) - lastnames = ["{}{}{}".format(uts.random_username(5), x, uts.random_username(5)) for x in random_puncts[:4]] - lastnames.append(".{}".format(uts.random_username())) - lastnames.append(".{}.{}.".format(uts.random_username(4), uts.random_username(4))) - lastnames.append("{}[{}]{}".format(uts.random_username(3), uts.random_username(3), uts.random_username(3))) - lastnames.append(uts.random_username(40)) - self.unique_basenames_to_remove.extend(lastnames) - self.log.info('*** Importing new users with role %r and the following lastnames:\n%r', role, lastnames) + random_puncts = list(string.punctuation) + random.shuffle(random_puncts) + lastname = uts.random_username(20) + self.unique_basenames_to_remove.append(lastname) + self.log.info("Testing with dry_run=False and lastname=%r which will be shortened to %r...", lastname, lastname[:12]) - config = copy.deepcopy(self.default_config) - source_uid = 'sourceUID-%s' % (uts.random_string(),) - config.update_entry('sourceUID', source_uid) - config.update_entry('scheme:recordUID', '') - config.update_entry('user_role', role) - config.update_entry('csv:mapping:recordUID', 'record_uid') - config.update_entry('scheme:username:default', "[ALWAYSCOUNTER]") + role = 'student' + record_uid = uts.random_name() + person = Person(self.ou_A.name, role) + source_uid = 'sourceUID-%s' % (uts.random_string(),) + person.update(record_uid=record_uid, source_uid=source_uid, lastname=lastname) - persons = list() - names = dict() - for lastname in lastnames: - record_uid = uts.random_name() - person = Person(self.ou_A.name, role) - person.update(record_uid=record_uid, source_uid=source_uid, lastname=lastname) - persons.append(person) - names[person] = lastname - fn_csv = self.create_csv_file(person_list=persons, mapping=config['csv']['mapping']) - config.update_entry('input:filename', fn_csv) - fn_config = self.create_config_json(config=config) + config = copy.deepcopy(self.default_config) + config.update_entry('sourceUID', source_uid) + config.update_entry('scheme:recordUID', '') + config.update_entry('user_role', role) + config.update_entry('csv:mapping:recordUID', 'record_uid') + config.update_entry('scheme:username:default', "[ALWAYSCOUNTER]") + fn_csv = self.create_csv_file(person_list=[person], mapping=config['csv']['mapping']) + config.update_entry('input:filename', fn_csv) + fn_config = self.create_config_json(config=config) - # save ldap state for later comparison - self.save_ldap_status() - # start import - self.run_import(['-c', fn_config, '-i', fn_csv]) - utils.wait_for_replication() - # check for new users in LDAP - self.check_new_and_removed_users(len(persons), 0) - # check usernames - for person, lastname in names.items(): - person.update(username=remove_bad_chars("{}1".format(lastname[:12]))) - utils.verify_ldap_object(person.dn, expected_attr={'uid': [person.username]}, strict=False, should_exist=True) - wait_for_drs_replication('cn={}'.format(escape_filter_chars(person.username))) # wait for creation before deletion + self.save_ldap_status() + self.run_import(['-c', fn_config, '-i', fn_csv]) + utils.wait_for_replication() + self.check_new_and_removed_users(1, 0) + person.update(username=remove_bad_chars("{}1".format(lastname[:12]))) + utils.verify_ldap_object(person.dn, expected_attr={'uid': [person.username]}, strict=False, should_exist=True) + wait_for_drs_replication('cn={}'.format(escape_filter_chars(person.username))) # wait for creation before deletion - # delete users - self.log.info('*** Deleting users with role %r and the following lastnames:\n%r', role, lastnames) - fn_csv = self.create_csv_file(person_list=[], mapping=config['csv']['mapping']) - config.update_entry('input:filename', fn_csv) - fn_config = self.create_config_json(config=config) - self.save_ldap_status() - self.run_import(['-c', fn_config, '-i', fn_csv]) - utils.wait_for_replication() + # delete user + self.log.info('*** Deleting user with lastname=%r', lastname) + fn_csv = self.create_csv_file(person_list=[], mapping=config['csv']['mapping']) + config.update_entry('input:filename', fn_csv) + fn_config = self.create_config_json(config=config) + self.save_ldap_status() + self.run_import(['-c', fn_config, '-i', fn_csv]) + utils.wait_for_replication() - # recreate users, but move position of COUNTER variable - self.log.info( - '*** Importing users with role %r and the same lastnames, but move position of COUNTER variable:\n%r', - role, - lastnames) - config.update_entry('scheme:username:default', "[ALWAYSCOUNTER]") - for person in persons: - # Prevent 'The email address is already taken by another user. Please change the email address.' - # because of slow s4 replication. Username is the same, so it doesn't change what's tested. - person.mail = '{}{}'.format(uts.random_username(4), person.mail) - fn_csv = self.create_csv_file(person_list=persons, mapping=config['csv']['mapping']) - config.update_entry('input:filename', fn_csv) - fn_config = self.create_config_json(config=config) - self.save_ldap_status() - self.run_import(['-c', fn_config, '-i', fn_csv]) - utils.wait_for_replication() - for person, lastname in names.items(): - person.update(username=remove_bad_chars("2{}".format(lastname[:12]))) - utils.verify_ldap_object(person.dn, expected_attr={'uid': [person.username]}, strict=False, should_exist=True) + # recreate user with dry_run + self.log.info('*** Importing user with the same lastname with --dry_run') + # Prevent 'The email address is already taken by another user. Please change the email address.' + # because of slow s4 replication. Username is the same, so it doesn't change what's tested. + person.mail = '{}{}'.format(uts.random_username(4), person.mail) + fn_csv = self.create_csv_file(person_list=[person], mapping=config['csv']['mapping']) + config.update_entry('input:filename', fn_csv) + fn_config = self.create_config_json(config=config) + self.save_ldap_status() + self.run_import(['-c', fn_config, '-i', fn_csv, '--dry-run']) + utils.wait_for_replication() + utils.verify_ldap_object(person.dn, should_exist=False) + person.update(username=remove_bad_chars("{}2".format(lastname[:12]))) + utils.verify_ldap_object(person.dn, should_exist=False) - self.log.info('*** Starting unit test for UsernameHandler.format_username() (1/5)') - unh = UsernameHandler(15) # 20 - len("exam-") - name12 = uts.random_username(12) # 15 - 3 - usernames = { - ".abc.def.": "abc.def", - "...abc...def...": "abc...def", - "": None, - "..[ALWAYSCOUNTER]..": None, - "[ALWAYSCOUNTER]": None, - "[FOObar]": "FOObar", - "{}.[COUNTER2]".format(name12): name12, - ".": None, - 'M'*14 + '.' + 'A': 'M' * 14, - } - for input_name, expected in usernames.items(): - try: - out = unh.format_username(input_name) - self.unique_basenames_to_remove.append(expected) - if out != expected: - self.fail("UsernameHandler.format_username(%r) returned %r, expected %r." % (input_name, out, expected)) - except FormatError: - if expected is not None: - self.fail("UsernameHandler.format_username(%r) raise a FormatError, expected it to return %r." % (input_name, expected)) - continue - self.log.info('*** Starting unit test for UsernameHandler.format_username() (2/5)') - for i in range(1000): - name = uts.random_username(15) - self.unique_basenames_to_remove.append(name) - out = unh.format_username(name) - if out != name: - self.fail("UsernameHandler.format_username(%r) returned %r." % (name, out)) - self.log.info('*** Starting unit test for UsernameHandler.format_username() (3/5)') - for i in range(1000): - name = uts.random_name(20) - self.unique_basenames_to_remove.append(name) - out = unh.format_username(name) - if out.startswith(".") or out.endswith(".") or len(out) > 15: - self.fail("UsernameHandler.format_username(%r) returned %r." % (name, out)) - self.log.info('*** Starting unit test for UsernameHandler.format_username() (4/5)') - for i in range(1000): - name = uts.random_name_special_characters(20) - name = name.translate(None, "[]") # those are reserved for counter vars - self.unique_basenames_to_remove.append(name) - out = unh.format_username(name) - if out.startswith(".") or out.endswith(".") or len(out) > 15: - self.fail("UsernameHandler.format_username(%r) returned %r." % (name, out)) - self.log.info('*** Starting unit test for UsernameHandler.format_username() (5/5)') - usernames = [ - ('Max[ALWAYSCOUNTER].Mustermann', 'Max1.Mustermann'), - ('Max[ALWAYSCOUNTER].Mustermann', 'Max2.Mustermann'), - ('Max[ALWAYSCOUNTER].Mustermann', 'Max3.Mustermann'), - ('Max[ALWAYSCOUNTER].Mustermann', 'Max4.Mustermann'), - ('Maria[ALWAYSCOUNTER].Musterfrau', 'Maria1.Musterfrau'), - ('Moritz[COUNTER2]', 'Moritz'), - ('Moritz[COUNTER2]', 'Moritz2') - ] - self.unique_basenames_to_remove.extend(["Max.Mustermann", "Maria.Musterfrau", "Moritz"]) - unh = UsernameHandler(20) - for input_name, expected in usernames: - out = unh.format_username(input_name) - if out != expected: - self.fail("UsernameHandler.format_username(%r) returned %r, expected %r." % (input_name, out, expected)) + lo, po = getAdminConnection() + utils.verify_ldap_object( + "cn={},cn=unique-usernames,cn=ucsschool,cn=univention,{}".format(escape_dn_chars(lastname[:12]), lo.base), + expected_attr={'ucsschoolUsernameNextNumber': ['2']}, + strict=False, + should_exist=True) + self.log.info('*** OK: Import with --dry_run didn\'t raise the counter.') + def main(): tester = Test() try: Index: ucs-test-ucsschool/debian/changelog =================================================================== --- ucs-test-ucsschool/debian/changelog (Revision 80401) +++ ucs-test-ucsschool/debian/changelog (Arbeitskopie) @@ -1,3 +1,9 @@ +ucs-test-ucsschool (3.0.17-63) unstable; urgency=low + + * Bug #42465: add test for dry-run and username counter + + -- Daniel Troeder Thu, 22 Jun 2017 10:42:55 +0200 + ucs-test-ucsschool (3.0.17-62) unstable; urgency=low * Bug #44588: add support for multiple schools to test User