Exemple #1
0
    def test_class(self):
        # Setup
        master_key = MasterKey()
        settings = Settings()
        contact_list = ContactList(master_key, settings)
        group_list = GroupList(master_key, settings, contact_list)
        members = [
            create_contact(n) for n in [
                'Alice', 'Bob', 'Charlie', 'David', 'Eric', 'Fido', 'Gunter',
                'Heidi', 'Ivan', 'Joana', 'Karol'
            ]
        ]
        contact_list.contacts = members
        groups = [
            Group(n, False, False, members, settings,
                  group_list.store_groups())
            for n in [
                'testgroup_1', 'testgroup_2', 'testgroup3', 'testgroup_4',
                'testgroup_5', 'testgroup_6', 'testgroup_7', 'testgroup8',
                'testgroup_9', 'testgroup_10', 'testgroup_11'
            ]
        ]
        group_list.groups = groups
        group_list.store_groups()

        # Test
        for g in group_list:
            self.assertIsInstance(g, Group)
        self.assertEqual(len(group_list), 11)

        self.assertTrue(os.path.isfile(f'{DIR_USER_DATA}/ut_groups'))
        self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}/ut_groups'),
                         24 + 32 + 20 * (1024 + 2 + (20 * 1024)) + 16)

        settings.m_number_of_groups = 10
        settings.m_members_in_group = 10

        group_list2 = GroupList(master_key, settings, contact_list)

        self.assertEqual(len(group_list2), 11)

        self.assertEqual(settings.m_number_of_groups, 20)
        self.assertEqual(settings.m_members_in_group, 20)

        bytestring = group_list2.generate_header()
        self.assertEqual(len(bytestring), 32)
        self.assertIsInstance(bytestring, bytes)

        dg_bytestring = group_list2.generate_dummy_group()
        self.assertEqual(len(dg_bytestring), (1024 + 2 + (20 * 1024)))
        self.assertIsInstance(dg_bytestring, bytes)

        members.append(create_contact('Laura'))
        group_list2.add_group('testgroup_12', False, False, members)
        group_list2.add_group('testgroup_12', False, True, members)
        self.assertTrue(group_list2.get_group('testgroup_12').notifications)
        self.assertEqual(len(group_list2), 12)
        self.assertEqual(group_list2.largest_group(), 12)

        g_names = [
            'testgroup_1', 'testgroup_2', 'testgroup3', 'testgroup_4',
            'testgroup_5', 'testgroup_6', 'testgroup_7', 'testgroup8',
            'testgroup_9', 'testgroup_10', 'testgroup_11', 'testgroup_12'
        ]
        self.assertEqual(group_list2.get_list_of_group_names(), g_names)

        g_o = group_list2.get_group('testgroup_1')
        self.assertIsInstance(g_o, Group)
        self.assertEqual(g_o.name, 'testgroup_1')
        self.assertTrue(group_list2.has_group('testgroup_12'))
        self.assertFalse(group_list2.has_group('testgroup_13'))
        self.assertTrue(group_list2.has_groups(), True)

        members = group_list2.get_group_members('testgroup_1')
        for c in members:
            self.assertIsInstance(c, Contact)

        self.assertEqual(len(group_list2), 12)
        group_list2.remove_group('testgroup_13')
        self.assertEqual(len(group_list2), 12)
        group_list2.remove_group('testgroup_12')
        self.assertEqual(len(group_list2), 11)
        self.assertIsNone(group_list2.print_groups())

        # Teardown
        cleanup()
Exemple #2
0
class TestGroupList(TFCTestCase):
    def setUp(self):
        self.unittest_dir = cd_unittest()
        self.master_key = MasterKey()
        self.settings = Settings()
        self.file_name = f'{DIR_USER_DATA}{self.settings.software_operation}_groups'
        self.contact_list = ContactList(self.master_key, self.settings)
        self.group_list = GroupList(self.master_key, self.settings,
                                    self.contact_list)
        self.nicks = [
            'Alice', 'Bob', 'Charlie', 'David', 'Eric', 'Fido', 'Guido',
            'Heidi', 'Ivan', 'Joana', 'Karol'
        ]
        self.group_names = [
            'test_group_1', 'test_group_2', 'test_group_3', 'test_group_4',
            'test_group_5', 'test_group_6', 'test_group_7', 'test_group_8',
            'test_group_9', 'test_group_10', 'test_group_11'
        ]
        members = list(map(create_contact, self.nicks))

        self.contact_list.contacts = members

        self.group_list.groups = \
            [Group(name         =name,
                   group_id     =group_name_to_group_id(name),
                   log_messages =False,
                   notifications=False,
                   members      =members,
                   settings     =self.settings,
                   store_groups =self.group_list.store_groups)
             for name in self.group_names]

        self.single_member_data_len = (
            GROUP_STATIC_LENGTH + self.settings.max_number_of_group_members *
            ONION_SERVICE_PUBLIC_KEY_LENGTH)

    def tearDown(self):
        cleanup(self.unittest_dir)

    def test_group_list_iterates_over_group_objects(self):
        for g in self.group_list:
            self.assertIsInstance(g, Group)

    def test_len_returns_the_number_of_groups(self):
        self.assertEqual(len(self.group_list), len(self.group_names))

    def test_storing_and_loading_of_groups(self):
        self.group_list.store_groups()

        self.assertTrue(os.path.isfile(self.file_name))
        self.assertEqual(
            os.path.getsize(self.file_name),
            XCHACHA20_NONCE_LENGTH + GROUP_DB_HEADER_LENGTH +
            self.settings.max_number_of_groups * self.single_member_data_len +
            POLY1305_TAG_LENGTH)

        # Reduce setting values from 20 to 10
        self.settings.max_number_of_groups = 10
        self.settings.max_number_of_group_members = 10

        group_list2 = GroupList(self.master_key, self.settings,
                                self.contact_list)
        self.assertEqual(len(group_list2), 11)

        # Check that `_load_groups()` increased setting values back to 20 so it fits the 11 groups
        self.assertEqual(self.settings.max_number_of_groups, 20)
        self.assertEqual(self.settings.max_number_of_group_members, 20)

        # Check that removed contact from contact list updates group
        self.contact_list.remove_contact_by_address_or_nick('Alice')
        group_list3 = GroupList(self.master_key, self.settings,
                                self.contact_list)
        self.assertEqual(len(group_list3.get_group('test_group_1').members),
                         10)

    def test_invalid_content_raises_critical_error(self):
        # Setup
        invalid_data = b'a'
        pt_bytes = self.group_list._generate_group_db_header()
        pt_bytes += b''.join([
            g.serialize_g()
            for g in (self.group_list.groups + self.group_list._dummy_groups())
        ])
        ct_bytes = encrypt_and_sign(pt_bytes + invalid_data,
                                    self.master_key.master_key)

        ensure_dir(DIR_USER_DATA)
        with open(self.file_name, 'wb+') as f:
            f.write(ct_bytes)

        # Test
        with self.assertRaises(SystemExit):
            GroupList(self.master_key, self.settings, self.contact_list)

    def test_load_of_modified_database_raises_critical_error(self):
        self.group_list.store_groups()

        # Test reading works normally
        self.assertIsInstance(
            GroupList(self.master_key, self.settings, self.contact_list),
            GroupList)

        # Test loading of the tampered database raises CriticalError
        tamper_file(self.file_name, tamper_size=1)
        with self.assertRaises(SystemExit):
            GroupList(self.master_key, self.settings, self.contact_list)

    def test_check_db_settings(self):
        self.assertFalse(
            self.group_list._check_db_settings(
                number_of_actual_groups=self.settings.max_number_of_groups,
                members_in_largest_group=self.settings.
                max_number_of_group_members))

        self.assertTrue(
            self.group_list._check_db_settings(
                number_of_actual_groups=self.settings.max_number_of_groups + 1,
                members_in_largest_group=self.settings.
                max_number_of_group_members))

        self.assertTrue(
            self.group_list._check_db_settings(
                number_of_actual_groups=self.settings.max_number_of_groups,
                members_in_largest_group=self.settings.
                max_number_of_group_members + 1))

    def test_generate_group_db_header(self):
        header = self.group_list._generate_group_db_header()
        self.assertEqual(len(header), GROUP_DB_HEADER_LENGTH)
        self.assertIsInstance(header, bytes)

    def test_generate_dummy_group(self):
        dummy_group = self.group_list._generate_dummy_group()
        self.assertIsInstance(dummy_group, Group)
        self.assertEqual(len(dummy_group.serialize_g()),
                         self.single_member_data_len)

    def test_dummy_groups(self):
        dummies = self.group_list._dummy_groups()
        self.assertEqual(
            len(dummies),
            self.settings.max_number_of_contacts - len(self.nicks))
        for g in dummies:
            self.assertIsInstance(g, Group)

    def test_add_group(self):
        members = [create_contact('Laura')]
        self.group_list.add_group('test_group_12', bytes(GROUP_ID_LENGTH),
                                  False, False, members)
        self.group_list.add_group('test_group_12', bytes(GROUP_ID_LENGTH),
                                  False, True, members)
        self.assertTrue(
            self.group_list.get_group('test_group_12').notifications)
        self.assertEqual(len(self.group_list), len(self.group_names) + 1)

    def test_remove_group_by_name(self):
        self.assertEqual(len(self.group_list), len(self.group_names))

        # Remove non-existing group
        self.assertIsNone(
            self.group_list.remove_group_by_name('test_group_12'))
        self.assertEqual(len(self.group_list), len(self.group_names))

        # Remove existing group
        self.assertIsNone(
            self.group_list.remove_group_by_name('test_group_11'))
        self.assertEqual(len(self.group_list), len(self.group_names) - 1)

    def test_remove_group_by_id(self):
        self.assertEqual(len(self.group_list), len(self.group_names))

        # Remove non-existing group
        self.assertIsNone(
            self.group_list.remove_group_by_id(
                group_name_to_group_id('test_group_12')))
        self.assertEqual(len(self.group_list), len(self.group_names))

        # Remove existing group
        self.assertIsNone(
            self.group_list.remove_group_by_id(
                group_name_to_group_id('test_group_11')))
        self.assertEqual(len(self.group_list), len(self.group_names) - 1)

    def test_get_group(self):
        self.assertEqual(
            self.group_list.get_group('test_group_3').name, 'test_group_3')

    def test_get_group_by_id(self):
        members = [create_contact('Laura')]
        group_id = os.urandom(GROUP_ID_LENGTH)
        self.group_list.add_group('test_group_12', group_id, False, False,
                                  members)
        self.assertEqual(
            self.group_list.get_group_by_id(group_id).name, 'test_group_12')

    def test_get_list_of_group_names(self):
        self.assertEqual(self.group_list.get_list_of_group_names(),
                         self.group_names)

    def test_get_list_of_group_ids(self):
        self.assertEqual(self.group_list.get_list_of_group_ids(),
                         list(map(group_name_to_group_id, self.group_names)))

    def test_get_list_of_hr_group_ids(self):
        self.assertEqual(self.group_list.get_list_of_hr_group_ids(), [
            b58encode(gid)
            for gid in list(map(group_name_to_group_id, self.group_names))
        ])

    def test_get_group_members(self):
        members = self.group_list.get_group_members(
            group_name_to_group_id('test_group_1'))
        for c in members:
            self.assertIsInstance(c, Contact)

    def test_has_group(self):
        self.assertTrue(self.group_list.has_group('test_group_11'))
        self.assertFalse(self.group_list.has_group('test_group_12'))

    def test_has_group_id(self):
        members = [create_contact('Laura')]
        group_id = os.urandom(GROUP_ID_LENGTH)
        self.assertFalse(self.group_list.has_group_id(group_id))
        self.group_list.add_group('test_group_12', group_id, False, False,
                                  members)
        self.assertTrue(self.group_list.has_group_id(group_id))

    def test_largest_group(self):
        self.assertEqual(self.group_list.largest_group(), len(self.nicks))

    def test_print_group(self):
        self.group_list.get_group("test_group_1").name = "group"
        self.group_list.get_group("test_group_2").log_messages = True
        self.group_list.get_group("test_group_3").notifications = True
        self.group_list.get_group("test_group_4").log_messages = True
        self.group_list.get_group("test_group_4").notifications = True
        self.group_list.get_group("test_group_5").members = []
        self.group_list.get_group("test_group_6").members = list(
            map(create_contact,
                ['Alice', 'Bob', 'Charlie', 'David', 'Eric', 'Fido']))
        self.assert_prints(
            """\
Group            Group ID         Logging     Notify    Members
────────────────────────────────────────────────────────────────────────────────
group            2drs4c4VcDdrP    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_2     2dnGTyhkThmPi    Yes         No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_3     2df7s3LZhwLDw    No          Yes       Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_4     2djy3XwUQVR8q    Yes         Yes       Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_5     2dvbcgnjiLLMo    No          No        <Empty group>

test_group_6     2dwBRWAqWKHWv    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido

test_group_7     2eDPg5BAM6qF4    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_8     2dqdayy5TJKcf    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_9     2e45bLYvSX3C8    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_10    2dgkncX9xRibh    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol

test_group_11    2e6vAGmHmSEEJ    No          No        Alice, Bob, Charlie,
                                                        David, Eric, Fido,
                                                        Guido, Heidi, Ivan,
                                                        Joana, Karol


""", self.group_list.print_groups)
Exemple #3
0
class TestGroupList(TFCTestCase):

    def setUp(self):
        self.master_key   = MasterKey()
        self.settings     = Settings()
        self.contact_list = ContactList(self.master_key, self.settings)
        self.group_list   = GroupList(self.master_key, self.settings, self.contact_list)
        members           = [create_contact(n) for n in ['Alice', 'Bob', 'Charlie', 'David', 'Eric',
                                                         'Fido', 'Guido', 'Heidi', 'Ivan', 'Joana', 'Karol']]
        self.contact_list.contacts = members

        groups = [Group(n, False, False, members, self.settings, self.group_list.store_groups)
                  for n in ['testgroup_1', 'testgroup_2', 'testgroup_3', 'testgroup_4', 'testgroup_5',
                            'testgroup_6', 'testgroup_7', 'testgroup_8', 'testgroup_9', 'testgroup_10',
                            'testgroup_11']]

        self.group_list.groups = groups
        self.group_list.store_groups()

        self.single_member_data = (PADDED_UTF32_STR_LEN
                                   + (2 * BOOLEAN_SETTING_LEN)
                                   + (self.settings.max_number_of_group_members * PADDED_UTF32_STR_LEN))

    def tearDown(self):
        cleanup()

    def test_group_list_iterates_over_group_objects(self):
        for g in self.group_list:
            self.assertIsInstance(g, Group)

    def test_len_returns_number_of_groups(self):
        self.assertEqual(len(self.group_list), 11)

    def test_database_size(self):
        self.assertTrue(os.path.isfile(f'{DIR_USER_DATA}ut_groups'))
        self.assertEqual(os.path.getsize(f'{DIR_USER_DATA}ut_groups'),
                         XSALSA20_NONCE_LEN
                         + GROUP_DB_HEADER_LEN
                         + self.settings.max_number_of_groups * self.single_member_data
                         + POLY1305_TAG_LEN)

        self.settings.max_number_of_groups        = 10
        self.settings.max_number_of_group_members = 10

        group_list2 = GroupList(self.master_key, self.settings, self.contact_list)
        self.assertEqual(len(group_list2), 11)

        # Check that load_groups() function increases setting values with larger db
        self.assertEqual(self.settings.max_number_of_groups, 20)
        self.assertEqual(self.settings.max_number_of_group_members, 20)

        # Check that removed contact from contact list updates group
        self.contact_list.remove_contact('Alice')
        group_list3 = GroupList(self.master_key, self.settings, self.contact_list)
        self.assertEqual(len(group_list3.get_group('testgroup_1').members), 10)

        group_list4 = GroupList(self.master_key, self.settings, self.contact_list)
        self.assertEqual(len(group_list4.get_group('testgroup_2').members), 10)

    def test_generate_group_db_header(self):
        header = self.group_list.generate_group_db_header()
        self.assertEqual(len(header), GROUP_DB_HEADER_LEN)
        self.assertIsInstance(header, bytes)

    def test_generate_dummy_group(self):
        dummy_group = self.group_list.generate_dummy_group()
        self.assertEqual(len(dummy_group.serialize_g()), self.single_member_data)
        self.assertIsInstance(dummy_group, Group)

    def test_add_group(self):
        members = [create_contact('Laura')]
        self.group_list.add_group('testgroup_12', False, False, members)
        self.group_list.add_group('testgroup_12', False, True, members)
        self.assertTrue(self.group_list.get_group('testgroup_12').notifications)
        self.assertEqual(len(self.group_list), 12)

    def test_remove_group(self):
        self.assertEqual(len(self.group_list), 11)

        self.assertIsNone(self.group_list.remove_group('testgroup_12'))
        self.assertEqual(len(self.group_list), 11)

        self.assertIsNone(self.group_list.remove_group('testgroup_11'))
        self.assertEqual(len(self.group_list), 10)

    def test_get_list_of_group_names(self):
        g_names = ['testgroup_1', 'testgroup_2', 'testgroup_3', 'testgroup_4', 'testgroup_5', 'testgroup_6',
                   'testgroup_7', 'testgroup_8', 'testgroup_9', 'testgroup_10', 'testgroup_11']
        self.assertEqual(self.group_list.get_list_of_group_names(), g_names)

    def test_get_group(self):
        self.assertEqual(self.group_list.get_group('testgroup_3').name, 'testgroup_3')

    def test_get_group_members(self):
        members = self.group_list.get_group_members('testgroup_1')
        for c in members:
            self.assertIsInstance(c, Contact)

    def test_has_group(self):
        self.assertTrue(self.group_list.has_group('testgroup_11'))
        self.assertFalse(self.group_list.has_group('testgroup_12'))

    def test_has_groups(self):
        self.assertTrue(self.group_list.has_groups())
        self.group_list.groups = []
        self.assertFalse(self.group_list.has_groups())

    def test_largest_group(self):
        self.assertEqual(self.group_list.largest_group(), 11)

    def test_print_group(self):
        self.group_list.get_group("testgroup_1").log_messages  = True
        self.group_list.get_group("testgroup_2").notifications = True
        self.group_list.get_group("testgroup_3").members       = []
        self.assertPrints("""\
Group            Logging     Notify     Members
────────────────────────────────────────────────────────────────────────────────
testgroup_1      Yes         No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_2      No          Yes        Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_3      No          No         <Empty group>

testgroup_4      No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_5      No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_6      No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_7      No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_8      No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_9      No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_10     No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol

testgroup_11     No          No         Alice, Bob, Charlie, David, Eric, Fido,
                                        Guido, Heidi, Ivan, Joana, Karol


""", self.group_list.print_groups)