def test_composes_bootloader_section_v4(self): ip = factory.make_ipv4_address() output = config.compose_conditional_bootloader(False, ip) for name, method in BootMethodRegistry: if name == "pxe": self.assertThat(output, Contains("else")) self.assertThat(output, Contains(method.bootloader_path)) elif method.arch_octet is not None: if isinstance(method.arch_octet, list): self.assertThat(output, ContainsAll(method.arch_octet)) else: self.assertThat(output, Contains(method.arch_octet)) self.assertThat(output, Contains(method.bootloader_path)) else: # No DHCP configuration is rendered for boot methods that have # no `arch_octet`, with the solitary exception of PXE. pass if method.path_prefix_http or method.http_url: self.assertThat(output, Contains("http://%s:5248/" % ip)) if method.path_prefix_force: self.assertThat( output, Contains("option dhcp-parameter-request-list = concat("), ) self.assertThat( output, Contains("option dhcp-parameter-request-list,d2);")) if method.http_url: self.assertThat( output, Contains('option vendor-class-identifier "HTTPClient";'), )
def test__loads_yaml_embedded_attributes(self): embedded_yaml = { 'name': factory.make_name('name'), 'title': factory.make_name('title'), 'description': factory.make_name('description'), 'tags': [factory.make_name('tag') for _ in range(3)], 'script_type': factory.pick_choice(SCRIPT_TYPE_CHOICES), 'hardware_type': factory.pick_choice(HARDWARE_TYPE_CHOICES), 'parallel': factory.pick_choice(SCRIPT_PARALLEL_CHOICES), 'results': ['write_speed'], 'parameters': [{'type': 'storage'}, {'type': 'runtime'}], 'packages': {'apt': [factory.make_name('package')]}, 'timeout': random.randint(0, 1000), 'destructive': factory.pick_bool(), } script_content = factory.make_script_content(embedded_yaml) form = ScriptForm(data={'script': script_content}) self.assertTrue(form.is_valid(), form.errors) script = form.save() self.assertEquals(embedded_yaml['name'], script.name) self.assertEquals(embedded_yaml['title'], script.title) self.assertEquals(embedded_yaml['description'], script.description) self.assertThat(script.tags, ContainsAll(embedded_yaml['tags'])) self.assertEquals(embedded_yaml['script_type'], script.script_type) self.assertEquals(embedded_yaml['hardware_type'], script.hardware_type) self.assertEquals(embedded_yaml['parallel'], script.parallel) self.assertItemsEqual(embedded_yaml['results'], script.results) self.assertItemsEqual(embedded_yaml['parameters'], script.parameters) self.assertDictEqual(embedded_yaml['packages'], script.packages) self.assertEquals( timedelta(0, embedded_yaml['timeout']), script.timeout) self.assertEquals(embedded_yaml['destructive'], script.destructive) self.assertFalse(script.default) self.assertEquals(script_content, script.script.data)
def test_zone_list_displays_zone_details(self): # Zone listing displays the zone name and the zone description. self.client_log_in() [factory.make_Zone() for _ in range(3)] zones = Zone.objects.all() response = self.client.get(reverse('zone-list')) zone_names = [ zone.name.encode(settings.DEFAULT_CHARSET) for zone in zones ] truncated_zone_descriptions = [ zone.description[:20].encode(settings.DEFAULT_CHARSET) for zone in zones ] self.assertThat(response.content, ContainsAll(zone_names)) self.assertThat(response.content, ContainsAll(truncated_zone_descriptions))
def test_settings_contains_names_and_content_of_scripts(self): self.client.login(user=factory.make_admin()) scripts = { factory.make_Script(script_type=SCRIPT_TYPE.COMMISSIONING), factory.make_Script(script_type=SCRIPT_TYPE.COMMISSIONING), } response = self.client.get(reverse('settings_scripts')) names = [script.name for script in scripts] contents = [script.script.data for script in scripts] self.assertThat( response.content, ContainsAll( [name.encode(settings.DEFAULT_CHARSET) for name in names])) self.assertThat( response.content, ContainsAll([content.encode() for content in contents]))
def test_serialization_roundtrip(self, obj): """ An ``IObject`` provider can be round-trip through JSON using ``iobject_to_raw`` and ``iobject_from_raw``. """ model = v1_5_model marshalled = model.iobject_to_raw(obj) # Every IObject has these marshalled fields - and when looking at the # marshalled form, they're necessary to figure out the # schema/definition for the data. We can't say anything in general # about the *values* (because of things like "extensions/v1beta1") but # we can at least assert the keys are present. self.expectThat(marshalled, ContainsAll([u"kind", u"apiVersion"])) # We should be able to unmarshal the data back to the same model # object as we started with. reloaded = model.iobject_from_raw(marshalled) self.expectThat(obj, PClassEquals(reloaded)) # And, to be extra sure (ruling out any weird Python object # semantic hijinx), that that reconstituted object should marshal # back to exactly the same simplified object graph. remarshalled = model.iobject_to_raw(reloaded) self.expectThat(marshalled, MappingEquals(remarshalled)) # Also, the marshalled form must be JSON compatible. serialized = dumps(marshalled) deserialized = loads(serialized) self.expectThat(marshalled, MappingEquals(deserialized))
def test_writes_reverse_dns_zone_config_for_small_network(self): target_dir = patch_dns_config_path(self) domain = factory.make_string() ns_host_name = factory.make_name("ns") network = IPNetwork("192.168.0.1/26") dynamic_network = IPNetwork("192.168.0.1/28") dns_zone_config = DNSReverseZoneConfig( domain, serial=random.randint(1, 100), network=network, ns_host_name=ns_host_name, dynamic_ranges=[ IPRange(dynamic_network.first, dynamic_network.last) ], ) dns_zone_config.write_config() reverse_zone_name = "0-26.0.168.192.in-addr.arpa" reverse_file_name = "zone.0-26.0.168.192.in-addr.arpa" expected_GEN_direct = dns_zone_config.get_GENERATE_directives( dynamic_network, domain, DomainInfo(network, reverse_zone_name) ) expected = ContainsAll( ["30 IN NS %s." % ns_host_name] + [ "$GENERATE %s %s IN PTR %s" % (iterator_values, reverse_dns, hostname) for iterator_values, reverse_dns, hostname in expected_GEN_direct ] ) self.assertThat( os.path.join(target_dir, reverse_file_name), FileContains(matcher=expected), )
def test_log_err_is_error(self): # An error logged during the test run is recorded as an error in the # tests. class LogAnError(TestCase): def test_something(self): try: 1 / 0 except ZeroDivisionError: f = failure.Failure() log.err(f) test = LogAnError('test_something') runner = self.make_runner(test, store_twisted_logs=False) result = self.make_result() runner.run(result) self.assertThat( result._events, MatchesEvents(('startTest', test), ('addError', test, { 'logged-error': AsText( ContainsAll([ 'Traceback (most recent call last):', 'ZeroDivisionError', ])), }), ('stopTest', test)))
def _list_by_param_value_and_assert(self, params, expected_list=None, with_detail=False): """ Perform list or list_details action with given params and validates result. """ if with_detail: resp, fetched_vol_list = \ self.client.list_volumes_with_detail(params=params) else: resp, fetched_vol_list = self.client.list_volumes(params=params) self.assertEqual(200, resp.status) if expected_list is None: expected_list = self.volume_list self.assertVolumesIn(fetched_vol_list, expected_list, fields=VOLUME_FIELDS) # Validating params of fetched volumes if with_detail: for volume in fetched_vol_list: for key in params: msg = "Failed to list volumes %s by %s" % \ ('details' if with_detail else '', key) if key == 'metadata': self.assertThat(volume[key].items(), ContainsAll(params[key].items()), msg) else: self.assertEqual(params[key], volume[key], msg)
def test_composes_bootloader_section_v6(self): ip = factory.make_ipv6_address() output = config.compose_conditional_bootloader(True, ip) for name, method in BootMethodRegistry: if name == "uefi": self.assertThat(output, Contains("else")) self.assertThat(output, Contains(method.bootloader_path)) elif method.arch_octet is not None: if isinstance(method.arch_octet, list): self.assertThat(output, ContainsAll(method.arch_octet)) else: self.assertThat(output, Contains(method.arch_octet)) self.assertThat(output, Contains(method.bootloader_path)) else: # No DHCP configuration is rendered for boot methods that have # no `arch_octet`, with the solitary exception of PXE. pass if method.path_prefix_http or method.http_url: self.assertThat(output, Contains("http://[%s]:5248/" % ip)) if method.path_prefix_force: self.assertThat( output, Contains( "option dhcp6.oro = concat(option dhcp6.oro,00d2);"), ) if method.http_url: self.assertThat( output, Contains('option dhcp6.vendor-class 0 10 "HTTPClient";'), )
def test_generate_user_data_produces_commissioning_script(self): # generate_user_data produces a commissioning script which contains # both definitions and use of various commands in python. node = factory.make_Node() user_data = generate_user_data_for_status( node, status=NODE_STATUS.COMMISSIONING) parsed_data = email.message_from_string(user_data.decode("utf-8")) self.assertTrue(parsed_data.is_multipart()) user_data_script = parsed_data.get_payload()[0] self.assertEquals( 'text/x-shellscript; charset="utf-8"', user_data_script["Content-Type"], ) self.assertEquals("base64", user_data_script["Content-Transfer-Encoding"]) self.assertEquals( 'attachment; filename="user_data.sh"', user_data_script["Content-Disposition"], ) self.assertThat( base64.b64decode(user_data_script.get_payload()), ContainsAll({ b"find_creds_cfg()", b"main()", b"# maas-run-remote-scripts -", }), )
def test_generate_user_data_produces_testing_script(self): node = factory.make_Node() user_data = generate_user_data_for_status(node, status=NODE_STATUS.TESTING) parsed_data = email.message_from_string(user_data.decode("utf-8")) self.assertTrue(parsed_data.is_multipart()) user_data_script = parsed_data.get_payload()[0] self.assertEquals( 'text/x-shellscript; charset="utf-8"', user_data_script["Content-Type"], ) self.assertEquals("base64", user_data_script["Content-Transfer-Encoding"]) self.assertEquals( 'attachment; filename="user_data.sh"', user_data_script["Content-Disposition"], ) self.assertThat( base64.b64decode(user_data_script.get_payload()), ContainsAll({ b"export DEBIAN_FRONTEND=noninteractive", b"maas-run-remote-scripts", b"def signal", b"def download_and_extract_tar", }), )
def test_generate_user_data_produces_commissioning_script(self): # generate_user_data produces a commissioning script which contains # both definitions and use of various commands in python. node = factory.make_Node() user_data = generate_user_data_for_status( node, status=NODE_STATUS.COMMISSIONING) parsed_data = email.message_from_string(user_data.decode("utf-8")) self.assertTrue(parsed_data.is_multipart()) user_data_script = parsed_data.get_payload()[0] self.assertEquals('text/x-shellscript; charset="utf-8"', user_data_script['Content-Type']) self.assertEquals('base64', user_data_script['Content-Transfer-Encoding']) self.assertEquals('attachment; filename="user_data.sh"', user_data_script['Content-Disposition']) self.assertThat( base64.b64decode(user_data_script.get_payload()), ContainsAll({ b'export DEBIAN_FRONTEND=noninteractive', b'maas-run-remote-scripts', b'def detect_ipmi', b'class IPMIError', b'def signal', b'VALID_STATUS =', b'def download_and_extract_tar', }))
def test_generate_user_data_produces_disk_erase_script(self): node = factory.make_Node() user_data = generate_user_data_for_status( node, status=NODE_STATUS.DISK_ERASING, extra_content=self.extra_content) parsed_data = email.message_from_string(user_data.decode("utf-8")) self.assertTrue(parsed_data.is_multipart()) user_data_script = parsed_data.get_payload()[0] self.assertEquals( 'text/x-shellscript; charset="utf-8"', user_data_script['Content-Type']) self.assertEquals( 'base64', user_data_script['Content-Transfer-Encoding']) self.assertEquals( 'attachment; filename="user_data.sh"', user_data_script['Content-Disposition']) payload = base64.b64decode(user_data_script.get_payload()) self.assertThat( payload, ContainsAll({ b'export DEBIAN_FRONTEND=noninteractive', b'maas-wipe', b'def signal', b'VALID_STATUS =', b'class WipeError' })) self.assertIsNotNone( re.search(self.maas_wipe, payload, re.MULTILINE | re.DOTALL))
def test_get_boot_config_returns_expected_result(self): rack_controller = yield deferToDatabase( transactional(factory.make_RackController)) yield deferToDatabase(make_usable_architecture, self) local_ip = factory.make_ip_address() remote_ip = factory.make_ip_address() response = yield call_responder( Region(), GetBootConfig, { "system_id": rack_controller.system_id, "local_ip": local_ip, "remote_ip": remote_ip, }) self.assertThat( response, ContainsAll([ "arch", "subarch", "osystem", "release", "kernel", "initrd", "boot_dtb", "purpose", "hostname", "domain", "preseed_url", "fs_host", "log_host", "extra_opts", ]))
def test_commissioning_compose_kernel_command_line_apparmor_disabled(self): # The result of compose_kernel_command_line includes the # options for apparmor. See LP: #1677336 and LP: #1408106 params = self.make_kernel_parameters( purpose="commissioning", fs_host=factory.make_ipv4_address()) cmdline = compose_kernel_command_line(params) self.assertThat(cmdline, ContainsAll(["apparmor=0"]))
def test_prefers_closest_addresses(self): subnet4 = factory.make_Subnet(version=4) subnet6 = factory.make_Subnet(version=6) # Separate subnets but sharing the VLAN, hence routable. subnet4v1 = factory.make_Subnet(version=4, vlan=subnet4.vlan) subnet6v1 = factory.make_Subnet(version=6, vlan=subnet6.vlan) subnet4v2 = factory.make_Subnet(version=4, vlan=subnet4.vlan) subnet6v2 = factory.make_Subnet(version=6, vlan=subnet6.vlan) # Create a node with an address in the first two subnets and the first # two same-VLAN subnets. node1 = self.make_node() populate_node_with_addresses(node1, {subnet4, subnet6, subnet4v1, subnet6v1}) # Create a node with an address in the first two subnets and the # second two same-VLAN subnets. node2 = self.make_node() populate_node_with_addresses(node2, {subnet4, subnet6, subnet4v2, subnet6v2}) # The NTP server addresses chosen will be those that are "closest" to # the node, and same-subnet wins in this over same-VLAN. No additional # preference is made between IPv4 or IPv6, hence we allow for either. preferred_subnets = subnet4, subnet6 preferred_networks = IPSet(subnet.get_ipnetwork() for subnet in preferred_subnets) for node in (node1, node2): peers = get_peers_for(node) self.assertThat(peers, Not(HasLength(0))) self.assertThat(preferred_networks, ContainsAll(peers))
def test_prefers_closest_addresses(self): subnet4 = factory.make_Subnet(version=4) subnet6 = factory.make_Subnet(version=6) # Separate subnets but sharing the VLAN, hence routable. subnet4v = factory.make_Subnet(version=4, vlan=subnet4.vlan) subnet6v = factory.make_Subnet(version=6, vlan=subnet6.vlan) # Create a node with an address in the first two subnets... node = self.make_node() populate_node_with_addresses(node, {subnet4, subnet6}) # ... and a server with an address in every subnet. server = self.make_server() populate_node_with_addresses(server, {subnet4, subnet6, subnet4v, subnet6v}) # The NTP server addresses chosen will be those that are "closest" to # the node, and same-subnet wins in this over same-VLAN. No additional # preference is made between IPv4 or IPv6, hence we allow for either. preferred_subnets = subnet4, subnet6 preferred_networks = IPSet(subnet.get_ipnetwork() for subnet in preferred_subnets) servers = get_servers_for(node) self.assertThat(servers, Not(HasLength(0))) self.assertThat(preferred_networks, ContainsAll(servers))
def test_writes_reverse_dns_zone_config(self): target_dir = patch_dns_config_path(self) domain = factory.make_string() ns_host_name = factory.make_name("ns") network = IPNetwork('192.168.0.1/22') dynamic_network = IPNetwork('192.168.0.1/28') dns_zone_config = DNSReverseZoneConfig(domain, serial=random.randint(1, 100), network=network, ns_host_name=ns_host_name, dynamic_ranges=[ IPRange( dynamic_network.first, dynamic_network.last) ]) dns_zone_config.write_config() for sub in range(4): reverse_file_name = 'zone.%d.168.192.in-addr.arpa' % sub expected_GEN_direct = dns_zone_config.get_GENERATE_directives( dynamic_network, domain, DomainInfo(IPNetwork('192.168.%d.0/24' % sub), "%d.168.192.in-addr.arpa" % sub)) expected = ContainsAll(['30 IN NS %s.' % ns_host_name] + [ '$GENERATE %s %s IN PTR %s' % (iterator_values, reverse_dns, hostname) for iterator_values, reverse_dns, hostname in expected_GEN_direct ]) self.assertThat(os.path.join(target_dir, reverse_file_name), FileContains(matcher=expected))
def test_tryUpdate_updates_syslog_server(self): service = syslog.RegionSyslogService(reactor) port, peers = yield deferToDatabase(self.make_example_configuration) write_config = self.patch_autospec(syslog, "write_config") restartService = self.patch_autospec(service_monitor, "restartService") yield service._tryUpdate() self.assertThat( write_config, MockCalledOnceWith( True, Matches( ContainsAll( [ { "ip": service._formatIP(ip), "name": node.hostname, } for node, ip in peers ] ) ), port=port, ), ) self.assertThat(restartService, MockCalledOnceWith("syslog_region")) # If the configuration has not changed then a second call to # `_tryUpdate` does not result in another call to `write_config`. yield service._tryUpdate() self.assertThat(write_config, MockCalledOnce()) self.assertThat(restartService, MockCalledOnceWith("syslog_region"))
def test_opencv(self): if (os.environ.get('ADT_TEST') and snapcraft.ProjectOptions().deb_arch == 'armhf'): self.skipTest("The autopkgtest armhf runners can't install snaps") snap_path = self.build_snap(self.snap_content_dir) bin_path = os.path.join(os.path.dirname(snap_path), 'prime', 'bin', 'example') self.assertThat(bin_path, FileExists()) interpreter = subprocess.check_output( [self.patchelf_command, '--print-interpreter', bin_path]).decode() expected_interpreter = r'^/snap/core/current/.*' self.assertThat(interpreter, MatchesRegex(expected_interpreter)) arch_triplet = snapcraft.ProjectOptions().arch_triplet # test $ORIGIN in action rpath = subprocess.check_output( [self.patchelf_command, '--print-rpath', bin_path]).decode() expected_rpath = '$ORIGIN/../usr/lib/{}:'.format(arch_triplet) self.assertThat(rpath, Contains(expected_rpath)) # test $ORIGIN applied ldd = subprocess.check_output(['ldd', bin_path]).decode() expected_opencv_path = ( '/prime/bin/../usr/lib/{}/libopencv_core'.format(arch_triplet)) self.assertThat(ldd, Contains(expected_opencv_path)) self.install_snap(snap_path, 'opencv-example', '1.0', classic=True) if not snaps_tests.config.get('skip-install', False): output = self.run_command_in_snappy_testbed( '/snap/bin/opencv-example.example').splitlines() # Depending on opencv the result is now displayed differently # so let's do a lazy match. # On artful you see: # [ 1, 3; # 2, 4] # And on others: # [1, 3; # 2, 4] expected_in_first_line = ['[', '1', ',', '3', ';'] self.assertThat(output[0], ContainsAll(expected_in_first_line)) expected_in_second_line = ['2', ',', '4', ']'] self.assertThat(output[1], ContainsAll(expected_in_second_line))
def test_get_reader_scenarios(self): # The commissioning config uses an extra PXELINUX module to auto # select between i386 and amd64. method = PXEBootMethod() get_ephemeral_name = self.patch(kernel_opts, "get_ephemeral_name") get_ephemeral_name.return_value = factory.make_name("ephemeral") osystem = factory.make_name("osystem") options = { "backend": None, "kernel_params": make_kernel_parameters( testcase=self, osystem=osystem, subarch="generic", purpose="enlist", ), } fs_host = "http://%s:5248/images" % ( convert_host_to_uri_str(options["kernel_params"].fs_host) ) output = method.get_reader(**options).read(10000).decode("utf-8") config = parse_pxe_config(output) # The default section is defined. default_section_label = config.header["DEFAULT"] self.assertThat(config, Contains(default_section_label)) default_section = config[default_section_label] # The default section uses the ifcpu64 module, branching to the "i386" # or "amd64" labels accordingly. self.assertEqual("ifcpu64.c32", default_section["KERNEL"]) self.assertEqual( ["amd64", "--", "i386"], default_section["APPEND"].split() ) # Both "i386" and "amd64" sections exist. self.assertThat(config, ContainsAll(("i386", "amd64"))) # Each section defines KERNEL, INITRD, and APPEND settings. The # KERNEL and INITRD ones contain paths referring to their # architectures. for section_label in ("i386", "amd64"): section = config[section_label] self.assertThat( section, ContainsAll(("KERNEL", "INITRD", "APPEND")) ) contains_arch_path = StartsWith( "%s/%s/%s/" % (fs_host, osystem, section_label) ) self.assertThat(section["KERNEL"], contains_arch_path) self.assertThat(section["INITRD"], contains_arch_path) self.assertIn("APPEND", section)
def test_settings_contains_names_and_content_of_scripts(self): self.client_log_in(as_admin=True) scripts = [ factory.make_Script(script_type=SCRIPT_TYPE.TESTING), factory.make_Script(script_type=SCRIPT_TYPE.TESTING), factory.make_Script(script_type=SCRIPT_TYPE.TESTING, default=True) ] response = self.client.get(reverse('settings')) names = [script.name for script in scripts[:-1]] contents = [script.script.data for script in scripts[:-1]] self.assertThat( response.content, ContainsAll( [name.encode(settings.DEFAULT_CHARSET) for name in names])) self.assertThat( response.content, ContainsAll([content.encode() for content in contents]))
def test_returns_dict_with_required_fields(self): setting = make_setting_field( factory.make_name('name'), factory.make_name('label')) self.assertThat( setting, ContainsAll([ 'name', 'label', 'required', 'field_type', 'choices', 'default', 'scope']))
def test_compose_kernel_command_line_inc_common_opts(self): # Test that some kernel arguments appear on commissioning, install # and xinstall command lines. expected = ["nomodeset"] params = self.make_kernel_parameters(purpose="commissioning", arch="i386") cmdline = compose_kernel_command_line(params) self.assertThat(cmdline, ContainsAll(expected)) params = self.make_kernel_parameters(purpose="xinstall", arch="i386") cmdline = compose_kernel_command_line(params) self.assertThat(cmdline, ContainsAll(expected)) params = self.make_kernel_parameters(purpose="install", arch="i386") cmdline = compose_kernel_command_line(params) self.assertThat(cmdline, ContainsAll(expected))
def test_compose_kernel_command_line_inc_purpose_opts_comm_node(self): # The result of compose_kernel_command_line includes the purpose # options for a "commissioning" node. params = self.make_kernel_parameters(purpose="commissioning") self.assertThat( compose_kernel_command_line(params), ContainsAll(["root=squash:http://"]), )
def test_settings_contains_osystem_and_distro_series(self): self.client.login(user=factory.make_admin()) keys, _ = self.make_license_keys(3) response = self.client.get(reverse('settings_license_keys')) os_titles = [key.osystem for key in keys] series_titles = [key.distro_series for key in keys] self.assertThat( response.content.decode(settings.DEFAULT_CHARSET), ContainsAll([title for title in os_titles + series_titles]))
def tests_yaml_tags_can_be_list_of_strings(self): tags = [factory.make_name('tag') for _ in range(3)] form = ScriptForm(data={'script': factory.make_script_content({ 'name': factory.make_name('name'), 'tags': tags, })}) self.assertTrue(form.is_valid(), form.errors) script = form.save() self.assertThat(script.tags, ContainsAll(tags))
def test_update_volume_metadata_item(self): # Update metadata item for the volume metadata = {"key1": "value1", "key2": "value2", "key3": "value3"} update_item = {"key3": "value3_update"} expect = {"key1": "value1", "key2": "value2", "key3": "value3_update"} # Create metadata for the volume resp, body = self.volumes_client.create_volume_metadata( self.volume_id, metadata) self.assertEqual(200, resp.status) self.assertThat(body.items(), ContainsAll(metadata.items())) # Update metadata item resp, body = self.volumes_client.update_volume_metadata_item( self.volume_id, "key3", update_item) self.assertEqual(200, resp.status) # Get the metadata of the volume resp, body = self.volumes_client.get_volume_metadata(self.volume_id) self.assertEqual(200, resp.status) self.assertThat(body.items(), ContainsAll(expect.items()))
def test_renders_with_hosts(self): params = make_sample_params(self, ipv6=self.ipv6) self.assertThat(params["hosts"], AfterPreprocessing(len, GreaterThanOrEqual(1))) config_output = config.get_config(self.template, **params) validate_dhcpd_configuration(self, config_output, self.ipv6) self.assertThat( config_output, ContainsAll([host["host"] for host in params["hosts"]]), ) self.assertThat( config_output, ContainsAll([host["mac"] for host in params["hosts"]]), ) self.assertThat( config_output, ContainsAll([host["ip"] for host in params["hosts"]]), )
def test_settings_contains_links_to_edit(self): self.client.login(user=factory.make_admin()) keys, _ = self.make_license_keys(3) links = get_content_links( self.client.get(reverse('settings_license_keys'))) license_key_delete_links = [ reverse('license-key-edit', args=[key.osystem, key.distro_series]) for key in keys ] self.assertThat(links, ContainsAll(license_key_delete_links))