def make_idockerclient_tests(fixture):
    """
    Create a TestCase for IDockerClient.

    :param fixture: A fixture that returns a :class:`IDockerClient`
        provider.
    """
    class IDockerClientTests(AsyncTestCase):
        """
        Tests for :class:`IDockerClientTests`.

        These are functional tests if run against a real Docker daemon.
        """
        def test_interface(self):
            """The tested object provides :class:`IDockerClient`."""
            client = fixture(self)
            self.assertTrue(verifyObject(IDockerClient, client))

        def test_add_and_remove(self):
            """
            An added container can be removed without an error.
            """
            client = fixture(self)
            name = random_name(self)
            d = client.add(name, u"busybox")
            d.addCallback(lambda _: client.remove(name))
            return d

        def test_no_double_add(self):
            """
            Adding a container with name that already exists results in error.
            """
            client = fixture(self)
            name = random_name(self)
            self.addCleanup(client.remove, name)
            d = client.add(name, u"busybox")

            def added(_):
                return client.add(name, u"busybox")
            d.addCallback(added)
            d = self.assertFailure(d, AlreadyExists)
            d.addCallback(lambda exc: self.assertEqual(exc.args[0], name))
            return d

        def test_remove_nonexistent_is_ok(self):
            """
            Removing a non-existent container does not result in a error.
            """
            client = fixture(self)
            name = random_name(self)
            return client.remove(name)

        def test_double_remove_is_ok(self):
            """
            Removing a container twice in a row does not result in error.
            """
            client = fixture(self)
            name = random_name(self)
            d = client.add(name, u"busybox")
            d.addCallback(lambda _: client.remove(name))
            d.addCallback(lambda _: client.remove(name))
            return d

        def test_unknown_does_not_exist(self):
            """
            A container that was never added does not exist.
            """
            client = fixture(self)
            name = random_name(self)
            d = client.exists(name)
            d.addCallback(self.assertFalse)
            return d

        def test_added_exists(self):
            """
            An added container exists.
            """
            client = fixture(self)
            name = random_name(self)
            self.addCleanup(client.remove, name)
            d = client.add(name, u"busybox")

            def added(_):
                return client.exists(name)
            d.addCallback(added)
            d.addCallback(self.assertTrue)
            return d

        def test_removed_does_not_exist(self):
            """
            A removed container does not exist.
            """
            client = fixture(self)
            name = random_name(self)
            d = client.add(name, ANY_IMAGE)
            d.addCallback(lambda _: client.remove(name))
            d.addCallback(lambda _: client.exists(name))
            d.addCallback(self.assertFalse)
            return d

        def test_zero_port_randomly_assigned(self):
            """
            If an external port number is given as 0, a random available port
            number is used.
            """
            client = fixture(self)
            name = random_name(self)
            portmap = PortMap(
                internal_port=1234, external_port=0,
            )
            self.addCleanup(client.remove, name)
            d = client.add(name, ANY_IMAGE, ports=(portmap,))
            d.addCallback(lambda ignored: client.list())

            def check_port(units):
                portmap = list(list(units)[0].ports)[0]
                self.assertTrue(
                    0 < portmap.external_port < 2 ** 16,
                    "Unexpected automatic port assignment: {}".format(
                        portmap.external_port
                    ),
                )
            d.addCallback(check_port)
            return d

        def test_port_collision_raises_addressinuse(self):
            """
            If the container is configured with an external port number which
            is already in use, ``AddressInUse`` is raised.
            """
            client = fixture(self)
            name = random_name(self)
            portmap = PortMap(
                internal_port=12345, external_port=0,
            )
            self.addCleanup(client.remove, name)
            d = client.add(name, ANY_IMAGE, ports=(portmap,))
            d.addCallback(lambda ignored: client.list())

            def extract_port(units):
                return list(list(units)[0].ports)[0].external_port
            d.addCallback(extract_port)

            def collide(external_port):
                self.external_port = external_port
                portmap = PortMap(
                    internal_port=54321, external_port=external_port,
                )
                name = random_name(self)
                self.addCleanup(client.remove, name)
                return client.add(name, ANY_IMAGE, ports=(portmap,))
            d.addCallback(collide)
            d = self.assertFailure(d, AddressInUse)

            def failed(exception):
                self.assertEqual(
                    exception.address, (b"0.0.0.0", self.external_port)
                )
                self.assertIsInstance(exception.apierror, APIError)
            d.addCallback(failed)
            return d

        def test_added_is_listed(self):
            """
            An added container is included in the output of ``list()``.
            """
            client = fixture(self)
            name = random_name(self)
            image = ANY_IMAGE

            portmaps = [
                PortMap(internal_port=80, external_port=0),
                PortMap(internal_port=5432, external_port=0),
            ]
            volumes = (
                Volume(node_path=FilePath(self.mktemp()),
                       container_path=FilePath(b'/var/lib/data')),
            )
            environment = (
                (u'CUSTOM_ENV_A', u'a value'),
                (u'CUSTOM_ENV_B', u'another value'),
            )
            environment = Environment(variables=frozenset(environment))
            self.addCleanup(client.remove, name)

            d = add_with_port_collision_retry(
                client,
                name,
                image_name=image,
                ports=portmaps,
                volumes=volumes,
                environment=environment,
                mem_limit=100000000,
                cpu_shares=512,
                restart_policy=RestartAlways(),
            )

            def added((app, portmaps)):
                d = client.list()
                d.addCallback(lambda units: (units, portmaps))
                return d
            d.addCallback(added)

            def got_list((units, portmaps)):
                result = units.pop()

                expected = Unit(
                    name=name, container_name=name, activation_state=u"active",
                    container_image=image, ports=frozenset(portmaps),
                    environment=environment, volumes=frozenset(volumes),
                    mem_limit=100000000, cpu_shares=512,
                    restart_policy=RestartAlways(),
                )

                # This test is not concerned with a returned ``Unit``'s
                # ``container_name`` and unlike other properties of the
                # result, does not expect ``container_name`` to be any
                # particular value. Manually setting it below to a fixed
                # known value simply allows us to compare an entire Unit
                # object instead of individual properties and is therefore
                # a convenience measure.
                result = result.set("container_name", name)
                self.assertEqual(result, expected)
            d.addCallback(got_list)
            return d

        def test_removed_is_not_listed(self):
            """
            A removed container is not included in the output of ``list()``.
            """
            client = fixture(self)
            name = random_name(self)

            d = client.add(name, ANY_IMAGE)
            d.addCallback(lambda _: client.remove(name))
            d.addCallback(lambda _: client.list())

            def got_list(units):
                self.assertNotIn(name, [unit.name for unit in units])
            d.addCallback(got_list)
            return d

        def test_container_name(self):
            """
            Each container also records the container name twice.
            """
            # This is silly behavior.  Get rid of it when fixing
            # <https://clusterhq.atlassian.net/browse/FLOC-819>.
            client = fixture(self)
            name = random_name(self)
            self.addCleanup(client.remove, name)
            d = client.add(name, u"busybox")
            d.addCallback(lambda _: client.list())

            def got_list(units):
                unit = [unit for unit in units if unit.name == name][0]
                self.assertIsInstance(unit.container_name, unicode)
            d.addCallback(got_list)
            return d

        def test_command_line(self):
            """
            Containers created with a command-line have a command-line included
            when listed.
            """
            client = fixture(self)
            name = random_name(self)
            self.addCleanup(client.remove, name)
            command_line = [u"nc", u"-l", u"-p", u"1234"]
            d = client.add(name, u"busybox", command_line=command_line)
            d.addCallback(lambda _: client.list())

            def got_list(units):
                unit = [unit for unit in units if unit.name == name][0]
                self.assertEqual(unit.command_line, pvector(command_line))
            d.addCallback(got_list)
            return d

        def assert_restart_policy_round_trips(self, restart_policy):
            """
            Creating a container with the given restart policy creates a
            container that reports that same policy.

            :param IRestartPolicy restart_policy: The restart policy to test.
            """
            client = fixture(self)
            name = random_name(self)
            self.addCleanup(client.remove, name)
            d = client.add(name, u"busybox", restart_policy=restart_policy)
            d.addCallback(lambda _: client.list())

            def got_list(units):
                unit = [unit for unit in units if unit.name == name][0]
                self.assertEqual(unit.restart_policy, restart_policy)
            d.addCallback(got_list)
            return d

        def test_add_with_restart_never(self):
            """
            ``DockerClient.add`` when creating a container with a restart
            policy, of never will create a container with this policy.
            """
            return self.assert_restart_policy_round_trips(RestartNever())

        def test_add_with_restart_always(self):
            """
            ``DockerClient.add`` when creating a container with a restart
            policy, of always will create a container with this policy.
            """
            return self.assert_restart_policy_round_trips(RestartAlways())

        def test_add_with_restart_on_failure(self):
            """
            ``DockerClient.add`` when creating a container with a restart
            policy, of on failure will create a container with this policy.
            """
            return self.assert_restart_policy_round_trips(RestartOnFailure())

        def test_add_with_restart_on_failure_with_maximum_retry(self):
            """
            ``DockerClient.add`` when creating a container with a restart
            policy, of on failure with a retry count will create a container
            with this policy.
            """
            return self.assert_restart_policy_round_trips(
                RestartOnFailure(maximum_retry_count=5))

    return IDockerClientTests
dataset/ETHPy150Open ClusterHQ/flocker/flocker/node/test/test_docker.py/make_idockerclient_tests/original