def test_build_hosts_file(self):
        expected = [
            '10.2.1.1\tmd md0 mongod0 mongod0.dsitest.dev',
            '10.2.1.2\tmd1 mongod1 mongod1.dsitest.dev',
            '10.2.1.3\tmd2 mongod2 mongod2.dsitest.dev',
            '10.2.1.4\tmd3 mongod3 mongod3.dsitest.dev',
            '10.2.1.5\tmd4 mongod4 mongod4.dsitest.dev',
            '10.2.1.6\tmd5 mongod5 mongod5.dsitest.dev',
            '10.2.1.7\tmd6 mongod6 mongod6.dsitest.dev',
            '10.2.1.8\tmd7 mongod7 mongod7.dsitest.dev',
            '10.2.1.9\tmd8 mongod8 mongod8.dsitest.dev',
            '10.2.1.100\tms ms0 mongos0 mongos0.dsitest.dev',
            '10.2.1.101\tms1 mongos1 mongos1.dsitest.dev',
            '10.2.1.102\tms2 mongos2 mongos2.dsitest.dev',
            '10.2.1.51\tcs cs0 configsvr0 configsvr0.dsitest.dev',
            '10.2.1.52\tcs1 configsvr1 configsvr1.dsitest.dev',
            '10.2.1.53\tcs2 configsvr2 configsvr2.dsitest.dev',
            '10.2.1.10\twc wc0 workload_client0 workload_client0.dsitest.dev'
        ]

        config_files = os.path.dirname(os.path.abspath(__file__)) + '/../../docs/config-specs/'
        with test_config.in_dir(config_files):
            real_config_dict = ConfigDict('infrastructure_provisioning')
            real_config_dict.load()
            real_config_dict.save = MagicMock(name='save')

            provisioner = ip.Provisioner(real_config_dict,
                                         provisioning_file=self.provision_log_path)
            hosts_contents = provisioner._build_hosts_file()
            self.assertEqual(expected, hosts_contents)
    def test_setup_hostnames(self, mock_exec_command, mock_create_file, mock_ssh):
        _ = mock_ssh
        config_files = os.path.dirname(os.path.abspath(__file__)) + '/../../docs/config-specs/'
        with test_config.in_dir(config_files):
            real_config_dict = ConfigDict('infrastructure_provisioning')
            real_config_dict.load()
            real_config_dict.save = MagicMock(name='save')

            provisioner = ip.Provisioner(real_config_dict,
                                         provisioning_file=self.provision_log_path)
            provisioner.setup_hostnames()
            out = provisioner.config['infrastructure_provisioning']['out']
            self.assertEqual(out['mongod'][0]['private_hostname'], 'mongod0.dsitest.dev')
            self.assertEqual(out['configsvr'][2]['private_hostname'], 'configsvr2.dsitest.dev')
            self.assertEqual(mock_create_file.call_count, 16)
            self.assertEqual(mock_exec_command.call_count, 16)
Esempio n. 3
0
class ConfigDictTestCase(unittest.TestCase):
    """Unit tests for ConfigDict library."""
    def setUp(self):
        """Init a ConfigDict object and load the configuration files from docs/config-specs/"""
        self.restore = dirmarker(
            './../../docs/config-specs/')  # Save the old path to restore Note
        # that this chdir only works without breaking relative imports
        # because it's at the same directory depth
        self.conf = ConfigDict('mongodb_setup')
        self.conf.load()
        self.assertEqual(self.conf.module, 'mongodb_setup')

    def tearDown(self):
        self.restore()

    @patch('os.path.join')
    def test_load_new(self, mock_path_join):
        """Test loading ConfigDict with old naming convention .yml files"""
        os.chdir(
            os.path.dirname(os.path.abspath(__file__)) +
            '/../tests/test_config_files/new_format')
        mock_path_join.return_value = './configurations/defaults.yml'
        test_conf = ConfigDict('bootstrap')
        test_conf.load()
        self.assertFalse('cluster_type' in test_conf.raw['bootstrap'])
        self.assertTrue(
            'infrastructure_provisioning' in test_conf.raw['bootstrap'])
        self.assertFalse('cluster_type' in test_conf.defaults['bootstrap'])
        self.assertTrue(
            'infrastructure_provisioning' in test_conf.defaults['bootstrap'])
        os.chdir(
            os.path.dirname(os.path.abspath(__file__)) +
            '/../../docs/config-specs/')

    def test_none_valued_keys(self):
        config_dict = ConfigDict('test_control')
        config_dict.load()
        self.assertEqual(config_dict['runtime']['overridden_none'],
                         'hey there')
        self.assertEqual(config_dict['runtime']['override_with_none'], None)
        self.assertEqual(config_dict['runtime']['overridden_dict'], None)
        self.assertEqual(config_dict['runtime']['overridden_list'], None)
        with self.assertRaises(KeyError):
            config_dict['runtime']['nonexistant']  # pylint: disable=pointless-statement

    def test_traverse_entire_dict(self):
        """Traverse entire dict (also tests that the structure of docs/config-specs/ files are ok)"""
        # We actually could compare the result to a constant megadict here, but maintaining that
        # would quickly become tedious. In practice, there's huge value just knowing we can traverse
        # the entire structure without errors.
        str(self.conf)

    @unittest.skip("dict(instance_of_ConfigDict) does not work")
    def test_cast_as_dict(self):
        """It is possible to cast a ConfigDict to a dict"""
        # TODO: this doesn't actually work. Seems like a limitation of python when sub-classing
        # native type like dict: http://stackoverflow.com/questions/18317905/overloaded-iter-is-bypassed-when-deriving-from-dict
        complete_dict = dict(self.conf)
        sub_dict = dict(
            self.conf['workload_setup']['tasks'][0]['on_workload_client'])
        self.assertEqual(
            complete_dict['workload_setup']['tasks'][0]['on_workload_client']
            ['retrieve_files'][0], {
                'source': 'http://url1',
                'target': 'file'
            })
        self.assertEqual(sub_dict['retrieve_files'][0], {
            'source': 'remote_file_path',
            'target': 'local_file_path'
        })

    def test_convert_to_dict(self):
        """It is possible to convert a ConfigDict to a dict with self.as_dict()"""
        complete_dict = self.conf.as_dict()
        sub_dict = self.conf['workload_setup']['ycsb'][0][
            'on_workload_client'].as_dict()
        self.assertEqual(
            complete_dict['workload_setup']['ycsb'][0]['on_workload_client']
            ['retrieve_files'][0], {
                'source': 'remote_file_path',
                'target': 'local_file_path'
            })
        self.assertEqual(sub_dict['retrieve_files'][0], {
            'source': 'remote_file_path',
            'target': 'local_file_path'
        })

    def test_basic_checks(self):
        """Basic checks"""
        self.assert_equal_dicts(
            self.conf['workload_setup']['ycsb'][0]['on_workload_client']
            ['retrieve_files'][0], {
                'source': 'remote_file_path',
                'target': 'local_file_path'
            })
        expected_result = [{
            'source': 'remote_file_path',
            'target': 'local_file_path'
        }]
        actual_result = self.conf['workload_setup']['ycsb'][0][
            'on_workload_client']['retrieve_files']
        self.assertEqual(len(actual_result), len(expected_result))
        for actual, expected in zip(actual_result, expected_result):
            self.assert_equal_dicts(actual, expected)
        self.assert_equal_dicts(
            self.conf['infrastructure_provisioning']['out']['mongos'][2], {
                'public_ip': '53.1.1.102',
                'private_ip': '10.2.1.102'
            })
        self.assertEqual(
            self.conf['infrastructure_provisioning']['out']['workload_client']
            [0]['public_ip'], "53.1.1.101")

    def test_overrides(self):
        """Test value from overrides.yml"""
        self.assertEqual(
            self.conf['infrastructure_provisioning']['tfvars']
            ['configsvr_instance_type'], "t1.micro")
        self.assertEqual(
            self.conf['infrastructure_provisioning']['tfvars'].as_dict(), {
                'cluster_name': 'shard',
                'mongos_instance_type': 'c3.8xlarge',
                'availability_zone': 'us-west-2a',
                'workload_instance_count': 1,
                'region': 'us-west-2',
                'image': 'amazon2',
                'mongod_instance_count': 9,
                'configsvr_instance_count': 3,
                'mongos_instance_count': 3,
                'ssh_key_file': '~/.ssh/linustorvalds.pem',
                'ssh_user': '******',
                'mongod_instance_type': 'c3.8xlarge',
                'ssh_key_name': 'linus.torvalds',
                'workload_instance_type': 'c3.8xlarge',
                'tags': {
                    'Project': 'sys-perf',
                    'owner': '*****@*****.**',
                    'Variant': 'Linux 3-shard cluster',
                    'expire-on-delta': 2
                },
                'configsvr_instance_type': 't1.micro',
                'expire-on-delta': 24
            })

    def test_defaults(self):
        """Test value from defaults.yml"""
        self.assertEqual(
            self.conf['mongodb_setup']['mongod_config_file']['net']['port'],
            27017)
        self.assertEqual(
            self.conf['mongodb_setup']['mongod_config_file']
            ['processManagement']['fork'], True)

    def test_copy(self):
        """Copy value into new python variable"""
        out = self.conf['infrastructure_provisioning']['out']
        self.conf.raw['infrastructure_provisioning']['out']['workload_client'][
            0]['private_ip'] = "foo"
        out.raw['workload_client'][0]['public_ip'] = "bar"
        self.assertTrue(isinstance(out, ConfigDict))
        self.assert_equal_lists(
            self.conf.raw['infrastructure_provisioning']['out']
            ['workload_client'], [{
                'public_ip': 'bar',
                'private_ip': 'foo'
            }])
        self.assert_equal_lists(
            self.conf.root['infrastructure_provisioning']['out']
            ['workload_client'], [{
                'public_ip': 'bar',
                'private_ip': 'foo'
            }])
        self.assert_equal_lists(out.raw['workload_client'],
                                [{
                                    'public_ip': 'bar',
                                    'private_ip': 'foo'
                                }])
        self.assert_equal_lists(
            out.root['infrastructure_provisioning']['out']['workload_client'],
            [{
                'public_ip': 'bar',
                'private_ip': 'foo'
            }])
        self.assert_equal_dicts(out.overrides, {})
        self.assertEqual(out['workload_client'][0]['public_ip'], 'bar')

    def test_variable_references(self):
        """Test ${variable.references}"""
        self.assertEqual(
            self.conf['mongodb_setup']['topology'][0]['mongos'][0]
            ['private_ip'], "10.2.1.100")
        self.assertEqual(self.conf['mongodb_setup']['meta']['hosts'],
                         "10.2.1.100:27017,10.2.1.101:27017,10.2.1.102:27017")

        # reference to reference
        self.assertEqual(self.conf['mongodb_setup']['meta']['hostname'],
                         '10.2.1.100')

        # recursive reference ${a.${foo}.c} where "foo: b"
        value = self.conf['test_control']['run'][0]['workload_config'][
            'tests']['default'][2]['insert_vector']['thread_levels']
        expected = [1, 8, 16]
        self.assertEqual(value, expected)

    def test_variable_reference_in_list(self):
        """Test ${variable.references} in a list"""
        self.assertEqual(
            self.conf['mongodb_setup']['validate']['primaries'][0],
            "10.2.1.1:27017")

    def test_variable_reference_value_error(self):
        """Test ${variable.references} that point to nonexisting value PERF-1705"""
        # PERF-1705 happened when infrastructure_provisioning.out doesn't exist and variable
        # references point to it.
        del self.conf.raw['infrastructure_provisioning']['out']

        # ConfigDict is late binding
        # assert_valid_ids() (used in load()) should not raise for such variable references.
        self.conf.assert_valid_ids()

        # Otoh actively accessing a field with such a variable reference must raise
        with self.assertRaises(ValueError):
            _ = self.conf['mongodb_setup']['meta']['mongodb_url']

        # As must other methods where user causes entire ConfigDict to be traversed
        with self.assertRaises(ValueError):
            _ = self.conf.as_dict()
        with self.assertRaises(ValueError):
            _ = str(self.conf)

    def test_per_node_mongod_config(self):
        """Test magic per_node_mongod_config() (merging the common mongod_config_file with per node config_file)"""
        mycluster = self.conf['mongodb_setup']['topology'][0]
        mongod = mycluster['shard'][2]['mongod'][0]
        self.assert_equal_dicts(
            mycluster['shard'][0]['mongod'][0]['config_file'], {
                'replication': {
                    'replSetName': 'override-rs'
                },
                'systemLog': {
                    'path': 'data/logs/mongod.log',
                    'destination': 'file'
                },
                'setParameter': {
                    'enableTestCommands': True,
                    'foo': True
                },
                'net': {
                    'port': 27017,
                    'bindIp': '0.0.0.0',
                },
                'processManagement': {
                    'fork': True
                },
                'storage': {
                    'engine': 'wiredTiger',
                    'dbPath': 'data/dbs'
                }
            })
        self.assert_equal_dicts(
            mycluster['shard'][2]['mongod'][0]['config_file'], {
                'replication': {
                    'replSetName': 'override-rs'
                },
                'systemLog': {
                    'path': 'data/logs/mongod.log',
                    'destination': 'file'
                },
                'setParameter': {
                    'enableTestCommands': True,
                    'foo': True
                },
                'net': {
                    'port': 27017,
                    'bindIp': '0.0.0.0',
                },
                'processManagement': {
                    'fork': True
                },
                'storage': {
                    'engine': 'inMemory',
                    'dbPath': 'data/dbs'
                }
            })
        self.assert_equal_dicts(
            mycluster['shard'][2]['mongod'][0]['config_file'].overrides,
            {'storage': {
                'engine': 'inMemory'
            }})
        self.assertEqual(
            mycluster['shard'][2]['mongod'][0]['config_file']['storage']
            ['engine'], "inMemory")
        self.assertEqual(
            mycluster['shard'][2]['mongod'][0]['config_file']['net']['port'],
            27017)
        self.assertEqual(
            mycluster['shard'][2]['mongod'][0]['config_file']['net']['bindIp'],
            "0.0.0.0")
        self.assertEqual(
            mycluster['shard'][2]['mongod'][0]['config_file']
            ['processManagement']['fork'], True)
        self.assertEqual(
            mongod.raw, {
                'public_ip':
                '${infrastructure_provisioning.out.mongod.6.public_ip}',
                'mongodb_binary_archive':
                '${mongodb_setup.mongodb_binary_archive}',
                'config_file': {
                    'storage': {
                        'engine': 'inMemory'
                    }
                },
                'private_ip':
                '${infrastructure_provisioning.out.mongod.6.private_ip}'
            })
        # Standalone node
        self.assert_equal_dicts(
            self.conf['mongodb_setup']['topology'][2]['config_file'], {
                'replication': {
                    'replSetName': 'override-rs'
                },
                'systemLog': {
                    'path': 'data/logs/mongod.log',
                    'destination': 'file'
                },
                'setParameter': {
                    'enableTestCommands': True,
                    'foo': True
                },
                'net': {
                    'port': 27017,
                    'bindIp': '0.0.0.0',
                },
                'processManagement': {
                    'fork': True
                },
                'storage': {
                    'engine': 'wiredTiger',
                    'dbPath': 'data/dbs'
                }
            })
        # self.keys() should return a 'config_file' key
        self.assertTrue(
            'config_file' in mycluster['shard'][0]['mongod'][0].keys())
        self.assertTrue(
            'config_file' in mycluster['shard'][2]['mongod'][0].keys())
        self.assertTrue(
            'config_file' in self.conf['mongodb_setup']['topology'][2].keys())
        self.assertFalse(
            'config_file' in self.conf['mongodb_setup']['topology'][0].keys())

    def test_replset_rs_conf(self):
        """Test magic rs_conf for a replset"""
        mycluster = self.conf['mongodb_setup']['topology'][0]
        rs_conf = mycluster['shard'][2]['rs_conf']
        self.assertEqual(rs_conf['protocolVersion'], 1)
        myreplset = self.conf['mongodb_setup']['topology'][1]
        rs_conf = myreplset['rs_conf']
        self.assertEqual(rs_conf['settings']['chainingAllowed'], False)
        self.assertEqual(rs_conf['protocolVersion'], 1)

        # conf.keys() should return a 'config_file' key for replsets, not otherwise
        self.assertTrue('rs_conf' in mycluster['shard'][0].keys())
        self.assertTrue('rs_conf' in mycluster['shard'][2].keys())
        self.assertTrue('rs_conf' in myreplset.keys())
        self.assertFalse('rs_conf' in mycluster.keys())
        self.assertFalse(
            'rs_conf' in self.conf['mongodb_setup']['topology'][2].keys())
        self.assertFalse(
            'rs_conf' in self.conf['infrastructure_provisioning'].keys())

    def test_set_some_values(self):
        """Set some values and write out file"""
        self.conf['mongodb_setup']['out'] = {'foo': 'bar'}
        # Read the value multiple times, because once upon a time that didn't work (believe it or not)
        self.assert_equal_dicts(self.conf['mongodb_setup']['out'],
                                {'foo': 'bar'})
        self.assert_equal_dicts(self.conf['mongodb_setup']['out'],
                                {'foo': 'bar'})
        self.assert_equal_dicts(self.conf['mongodb_setup']['out'],
                                {'foo': 'bar'})
        self.conf['mongodb_setup']['out']['zoo'] = 'zar'
        self.assert_equal_dicts(self.conf['mongodb_setup']['out'], {
            'foo': 'bar',
            'zoo': 'zar'
        })
        with self.assertRaises(KeyError):
            self.conf['foo'] = 'bar'
        # Write the out file only if it doesn't already exist, and delete it when done
        file_name = '../../docs/config-specs/mongodb_setup.out.yml'
        if os.path.exists(file_name):
            self.fail(
                "Cannot test writing docs/config-specs/mongodb_setup.out.yml file, file already exists."
            )
        else:
            self.conf.save()
            file_handle = open(file_name)
            saved_out_file = yaml.safe_load(file_handle)
            file_handle.close()
            self.assert_equal_dicts({'out': self.conf['mongodb_setup']['out']},
                                    saved_out_file)
            os.remove(file_name)

    def test_iterators(self):
        """Test that iterators .keys() and .values() work"""
        mycluster = self.conf['mongodb_setup']['topology'][0]
        actual_keys = self.conf.keys()
        actual_keys.sort()
        expected_keys = [
            'analysis', 'bootstrap', 'infrastructure_provisioning',
            'mongodb_setup', 'runtime', 'runtime_secret', 'system_setup',
            'test_control', 'workload_setup'
        ]

        self.assertEqual(expected_keys, actual_keys)

        tfvars_dict = dict(
            zip(self.conf['infrastructure_provisioning']['tfvars'].keys(),
                self.conf['infrastructure_provisioning']['tfvars'].values()))

        self.assert_equal_dicts(
            tfvars_dict, {
                'cluster_name': 'shard',
                'mongos_instance_type': 'c3.8xlarge',
                'availability_zone': 'us-west-2a',
                'workload_instance_count': 1,
                'image': 'amazon2',
                'region': 'us-west-2',
                'mongod_instance_count': 9,
                'configsvr_instance_count': 3,
                'mongos_instance_count': 3,
                'ssh_key_file': '~/.ssh/linustorvalds.pem',
                'ssh_user': '******',
                'mongod_instance_type': 'c3.8xlarge',
                'ssh_key_name': 'linus.torvalds',
                'workload_instance_type': 'c3.8xlarge',
                'tags': {
                    'Project': 'sys-perf',
                    'owner': '*****@*****.**',
                    'Variant': 'Linux 3-shard cluster',
                    'expire-on-delta': 2
                },
                'configsvr_instance_type': 't1.micro',
                'expire-on-delta': 24
            })

        actual_values = mycluster['shard'][2]['mongod'][0].values()
        print(actual_values)
        expected_values = [
            'https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.4.6.tgz',
            '53.1.1.7', '10.2.1.7'
        ]
        expected_dict = {
            'setParameter': {
                'foo': True,
                'enableTestCommands': 1
            },
            'storage': {
                'engine': 'inMemory',
                'dbPath': 'data/dbs'
            },
            'net': {
                'bindIp': '0.0.0.0',
                'port': 27017
            },
            'systemLog': {
                'path': 'data/logs/mongod.log',
                'destination': 'file'
            },
            'replication': {
                'replSetName': 'override-rs'
            },
            'processManagement': {
                'fork': True
            }
        }
        for item in actual_values:
            if isinstance(item, str):
                assert item in expected_values
            else:
                self.assert_equal_dicts(expected_dict, item)

    def test_lookup_path(self):
        """check that the lookup_path works as expected."""

        conf = self.conf['infrastructure_provisioning']['out']

        self.assertIsInstance(conf.lookup_path('mongod'), list)
        self.assertIsInstance(conf.lookup_path('mongod.0'), ConfigDict)
        self.assertIsInstance(conf.lookup_path('mongod.0.public_ip'), str)

        # hard coded but quick and easy
        mongod = ['53.1.1.{}'.format(i) for i in range(1, 10)]
        mongos = ['53.1.1.{}'.format(i) for i in range(100, 102)]
        configsvr = ['53.1.1.{}'.format(i) for i in range(51, 54)]
        workload_client = ['53.1.1.101']

        self.assertEqual(conf.lookup_path('mongod.0.public_ip'), mongod[0])

        self.assertEqual(conf.lookup_path('mongod.1.public_ip'), mongod[1])
        self.assertEqual(conf.lookup_path('mongod.4.public_ip'), mongod[4])

        self.assertEqual(conf.lookup_path('mongos.0.public_ip'), mongos[0])
        self.assertEqual(conf.lookup_path('configsvr.0.public_ip'),
                         configsvr[0])
        self.assertEqual(conf.lookup_path('workload_client.0.public_ip'),
                         workload_client[0])

        # document that this is the current behavior
        self.assertEqual(conf.lookup_path('mongod.-1.public_ip'), mongod[-1])

    def test_lookup_path_ex(self):
        """check that lookup_path throws exceptions for the correct portion of the pathspec."""

        conf = self.conf['infrastructure_provisioning']['out']
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: Key not found: MONGOD in path \\['MONGOD'\\]",
            conf.lookup_path, 'MONGOD')
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: Key not found: MONGOD in path \\['MONGOD', 50\\]",
            conf.lookup_path, 'MONGOD.50')
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: list index out of range: mongod.50 in path \\['mongod', 50\\]",
            conf.lookup_path, 'mongod.50')
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: Key not found: mongod.50e-1 in path \\['mongod', '50e-1'\\]",
            conf.lookup_path, 'mongod.50e-1')
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: list index out of range: mongod.50 in path \\['mongod', 50, 'public_ip'\\]",
            conf.lookup_path, 'mongod.50.public_ip')
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: Key not found: mongod.0.0 in path \\['mongod', 0, 0\\]",
            conf.lookup_path, 'mongod.0.0')
        self.assertRaisesRegex(
            KeyError,
            "ConfigDict: list index out of range: mongod.50 in path \\['mongod', 50, 'public_ip', 0\\]",
            conf.lookup_path, 'mongod.50.public_ip.0')

    # Helpers
    def assert_equal_dicts(self, dict1, dict2):
        """Compare 2 dicts element by element for equal values."""
        dict1keys = list(dict1.keys())
        dict2keys = list(dict2.keys())
        self.assertEqual(len(dict1keys), len(dict2keys))
        self.assertEqual(set(dict1keys), set(dict2keys))
        for dict1key in dict1keys:
            # Pop the corresponding key from dict2, note that they won't be in the same order.
            dict2key = dict2keys.pop(dict2keys.index(dict1key))
            self.assertEqual(
                dict1key, dict2key,
                'assert_equal_dicts failed: mismatch in keys: ' +
                str(dict1key) + '!=' + str(dict2key))
            if isinstance(dict1[dict1key], dict):
                self.assert_equal_dicts(dict1[dict1key], dict2[dict2key])
            elif isinstance(dict1[dict1key], list):
                self.assert_equal_lists(dict1[dict1key], dict2[dict2key])
            else:
                self.assertEqual(
                    dict1[dict1key], dict2[dict2key],
                    'assert_equal_dicts failed: mismatch in values.')
        self.assertEqual(len(dict2keys), 0)

    def assert_equal_lists(self, list1, list2):
        """Compare 2 lists element by element for equal values."""
        self.assertEqual(len(list1), len(list2))
        for list1value in list1:
            list2value = list2.pop(0)
            if isinstance(list1value, dict):
                self.assert_equal_dicts(list1value, list2value)
            elif isinstance(list1value, list):
                self.assert_equal_lists(list1value, list2value)
            else:
                self.assertEqual(list1value, list2value,
                                 '{} != {}'.format(list1, list2))
        self.assertEqual(len(list2), 0)