예제 #1
0
    def test_async_arg_lists(self):
        def assert_attrs(mock):
            names = ('call_args_list', 'method_calls', 'mock_calls')
            for name in names:
                attr = getattr(mock, name)
                self.assertIsInstance(attr, _CallList)
                self.assertIsInstance(attr, list)
                self.assertEqual(attr, [])

        assert_attrs(self.mock)
        with assertNeverAwaited(self):
            self.mock()
        with assertNeverAwaited(self):
            self.mock(1, 2)
        with assertNeverAwaited(self):
            self.mock(a=3)

        self.mock.reset_mock()
        assert_attrs(self.mock)

        a_mock = AsyncMock(AsyncClass)
        with assertNeverAwaited(self):
            a_mock.async_method()
        with assertNeverAwaited(self):
            a_mock.async_method(1, a=3)

        a_mock.reset_mock()
        assert_attrs(a_mock)
예제 #2
0
    def test_build_release_image_from_image_stream(
            self, cmd_assert_async: AsyncMock):
        runtime = MagicMock(config={
            "build_config": {
                "ocp_build_data_url": "https://example.com/ocp-build-data.git"
            }
        },
                            working_dir=Path("/path/to/working"),
                            dry_run=False)
        pipeline = PromotePipeline(
            runtime,
            group="openshift-4.10",
            assembly="4.10.99",
            release_offset=None,
            arches=["x86_64", "s390x", "ppc64le", "aarch64"])
        previous_list = ["4.10.98", "4.10.97", "4.9.99"]
        metadata = {
            "description": "whatever",
            "url": "https://access.redhat.com/errata/RHBA-2099:2222"
        }

        # test x86_64
        reference_release = None
        dest_pullspec = "example.com/foo/release:4.10.99-x86_64"
        asyncio.get_event_loop().run_until_complete(
            pipeline.build_release_image("4.10.99", "x86_64", previous_list,
                                         metadata, dest_pullspec,
                                         reference_release))
        expected_cmd = [
            'oc', 'adm', 'release', 'new', '-n', 'ocp', '--name=4.10.99',
            '--to-image=example.com/foo/release:4.10.99-x86_64',
            '--reference-mode=source',
            '--from-image-stream=4.10-art-assembly-4.10.99',
            '--previous=4.10.98,4.10.97,4.9.99', '--metadata',
            '{"description": "whatever", "url": "https://access.redhat.com/errata/RHBA-2099:2222"}'
        ]
        cmd_assert_async.assert_awaited_once_with(expected_cmd,
                                                  env=ANY,
                                                  stdout=ANY)

        # test aarch64
        reference_release = None
        dest_pullspec = "example.com/foo/release:4.10.99-aarch64"
        cmd_assert_async.reset_mock()
        asyncio.get_event_loop().run_until_complete(
            pipeline.build_release_image("4.10.99", "aarch64", previous_list,
                                         metadata, dest_pullspec,
                                         reference_release))
        expected_cmd = [
            'oc', 'adm', 'release', 'new', '-n', 'ocp-arm64', '--name=4.10.99',
            '--to-image=example.com/foo/release:4.10.99-aarch64',
            '--reference-mode=source',
            '--from-image-stream=4.10-art-assembly-4.10.99-arm64',
            '--previous=4.10.98,4.10.97,4.9.99', '--metadata',
            '{"description": "whatever", "url": "https://access.redhat.com/errata/RHBA-2099:2222"}'
        ]
        cmd_assert_async.assert_awaited_once_with(expected_cmd,
                                                  env=ANY,
                                                  stdout=ANY)
예제 #3
0
    def test_build_release_image_from_reference_release(
            self, cmd_assert_async: AsyncMock):
        runtime = MagicMock(config={
            "build_config": {
                "ocp_build_data_url": "https://example.com/ocp-build-data.git"
            }
        },
                            working_dir=Path("/path/to/working"),
                            dry_run=False)
        pipeline = PromotePipeline(
            runtime,
            group="openshift-4.10",
            assembly="4.10.99",
            release_offset=None,
            arches=["x86_64", "s390x", "ppc64le", "aarch64"])
        previous_list = ["4.10.98", "4.10.97", "4.9.99"]
        metadata = {
            "description": "whatever",
            "url": "https://access.redhat.com/errata/RHBA-2099:2222"
        }

        # test x86_64
        reference_release = "whatever-x86_64"
        dest_pullspec = "example.com/foo/release:4.10.99-x86_64"
        asyncio.get_event_loop().run_until_complete(
            pipeline.build_release_image("4.10.99", "x86_64", previous_list,
                                         metadata, dest_pullspec,
                                         reference_release))
        expected_cmd = [
            "oc", "adm", "release", "new", "-n", "ocp", "--name=4.10.99",
            "--to-image=example.com/foo/release:4.10.99-x86_64",
            "--from-release=registry.ci.openshift.org/ocp/release:whatever-x86_64",
            "--previous=4.10.98,4.10.97,4.9.99", "--metadata",
            "{\"description\": \"whatever\", \"url\": \"https://access.redhat.com/errata/RHBA-2099:2222\"}"
        ]
        cmd_assert_async.assert_awaited_once_with(expected_cmd,
                                                  env=ANY,
                                                  stdout=ANY)

        # test aarch64
        reference_release = "whatever-aarch64"
        dest_pullspec = "example.com/foo/release:4.10.99-aarch64"
        cmd_assert_async.reset_mock()
        asyncio.get_event_loop().run_until_complete(
            pipeline.build_release_image("4.10.99", "aarch64", previous_list,
                                         metadata, dest_pullspec,
                                         reference_release))
        expected_cmd = [
            "oc", "adm", "release", "new", "-n", "ocp-arm64", "--name=4.10.99",
            "--to-image=example.com/foo/release:4.10.99-aarch64",
            "--from-release=registry.ci.openshift.org/ocp-arm64/release-arm64:whatever-aarch64",
            "--previous=4.10.98,4.10.97,4.9.99", "--metadata",
            "{\"description\": \"whatever\", \"url\": \"https://access.redhat.com/errata/RHBA-2099:2222\"}"
        ]
        cmd_assert_async.assert_awaited_once_with(expected_cmd,
                                                  env=ANY,
                                                  stdout=ANY)
예제 #4
0
class AsyncMockAssert(unittest.TestCase):
    def setUp(self):
        self.mock = AsyncMock()

    async def _runnable_test(self, *args, **kwargs):
        await self.mock(*args, **kwargs)

    async def _await_coroutine(self, coroutine):
        return await coroutine

    def test_assert_called_but_not_awaited(self):
        mock = AsyncMock(AsyncClass)
        with assertNeverAwaited(self):
            mock.async_method()
        self.assertTrue(iscoroutinefunction(mock.async_method))
        mock.async_method.assert_called()
        mock.async_method.assert_called_once()
        mock.async_method.assert_called_once_with()
        with self.assertRaises(AssertionError):
            mock.assert_awaited()
        with self.assertRaises(AssertionError):
            mock.async_method.assert_awaited()

    def test_assert_called_then_awaited(self):
        mock = AsyncMock(AsyncClass)
        mock_coroutine = mock.async_method()
        mock.async_method.assert_called()
        mock.async_method.assert_called_once()
        mock.async_method.assert_called_once_with()
        with self.assertRaises(AssertionError):
            mock.async_method.assert_awaited()

        run(self._await_coroutine(mock_coroutine))
        # Assert we haven't re-called the function
        mock.async_method.assert_called_once()
        mock.async_method.assert_awaited()
        mock.async_method.assert_awaited_once()
        mock.async_method.assert_awaited_once_with()

    def test_assert_called_and_awaited_at_same_time(self):
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited()

        with self.assertRaises(AssertionError):
            self.mock.assert_called()

        run(self._runnable_test())
        self.mock.assert_called_once()
        self.mock.assert_awaited_once()

    def test_assert_called_twice_and_awaited_once(self):
        mock = AsyncMock(AsyncClass)
        coroutine = mock.async_method()
        # The first call will be awaited so no warning there
        # But this call will never get awaited, so it will warn here
        with assertNeverAwaited(self):
            mock.async_method()
        with self.assertRaises(AssertionError):
            mock.async_method.assert_awaited()
        mock.async_method.assert_called()
        run(self._await_coroutine(coroutine))
        mock.async_method.assert_awaited()
        mock.async_method.assert_awaited_once()

    def test_assert_called_once_and_awaited_twice(self):
        mock = AsyncMock(AsyncClass)
        coroutine = mock.async_method()
        mock.async_method.assert_called_once()
        run(self._await_coroutine(coroutine))
        with self.assertRaises(RuntimeError):
            # Cannot reuse already awaited coroutine
            run(self._await_coroutine(coroutine))
        mock.async_method.assert_awaited()

    def test_assert_awaited_but_not_called(self):
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited()
        with self.assertRaises(AssertionError):
            self.mock.assert_called()
        with self.assertRaises(TypeError):
            # You cannot await an AsyncMock, it must be a coroutine
            run(self._await_coroutine(self.mock))

        with self.assertRaises(AssertionError):
            self.mock.assert_awaited()
        with self.assertRaises(AssertionError):
            self.mock.assert_called()

    def test_assert_has_calls_not_awaits(self):
        kalls = [call('foo')]
        with assertNeverAwaited(self):
            self.mock('foo')
        self.mock.assert_has_calls(kalls)
        with self.assertRaises(AssertionError):
            self.mock.assert_has_awaits(kalls)

    def test_assert_has_mock_calls_on_async_mock_no_spec(self):
        with assertNeverAwaited(self):
            self.mock()
        kalls_empty = [('', (), {})]
        self.assertEqual(self.mock.mock_calls, kalls_empty)

        with assertNeverAwaited(self):
            self.mock('foo')
        with assertNeverAwaited(self):
            self.mock('baz')
        mock_kalls = ([call(), call('foo'), call('baz')])
        self.assertEqual(self.mock.mock_calls, mock_kalls)

    def test_assert_has_mock_calls_on_async_mock_with_spec(self):
        a_class_mock = AsyncMock(AsyncClass)
        with assertNeverAwaited(self):
            a_class_mock.async_method()
        kalls_empty = [('', (), {})]
        self.assertEqual(a_class_mock.async_method.mock_calls, kalls_empty)
        self.assertEqual(a_class_mock.mock_calls, [call.async_method()])

        with assertNeverAwaited(self):
            a_class_mock.async_method(1, 2, 3, a=4, b=5)
        method_kalls = [call(), call(1, 2, 3, a=4, b=5)]
        mock_kalls = [
            call.async_method(),
            call.async_method(1, 2, 3, a=4, b=5)
        ]
        self.assertEqual(a_class_mock.async_method.mock_calls, method_kalls)
        self.assertEqual(a_class_mock.mock_calls, mock_kalls)

    def test_async_method_calls_recorded(self):
        with assertNeverAwaited(self):
            self.mock.something(3, fish=None)
        with assertNeverAwaited(self):
            self.mock.something_else.something(6, cake=sentinel.Cake)

        self.assertEqual(self.mock.method_calls, [("something", (3, ), {
            'fish': None
        }), ("something_else.something", (6, ), {
            'cake': sentinel.Cake
        })], "method calls not recorded correctly")
        self.assertEqual(self.mock.something_else.method_calls,
                         [("something", (6, ), {
                             'cake': sentinel.Cake
                         })], "method calls not recorded correctly")

    def test_async_arg_lists(self):
        def assert_attrs(mock):
            names = ('call_args_list', 'method_calls', 'mock_calls')
            for name in names:
                attr = getattr(mock, name)
                self.assertIsInstance(attr, _CallList)
                self.assertIsInstance(attr, list)
                self.assertEqual(attr, [])

        assert_attrs(self.mock)
        with assertNeverAwaited(self):
            self.mock()
        with assertNeverAwaited(self):
            self.mock(1, 2)
        with assertNeverAwaited(self):
            self.mock(a=3)

        self.mock.reset_mock()
        assert_attrs(self.mock)

        a_mock = AsyncMock(AsyncClass)
        with assertNeverAwaited(self):
            a_mock.async_method()
        with assertNeverAwaited(self):
            a_mock.async_method(1, a=3)

        a_mock.reset_mock()
        assert_attrs(a_mock)

    def test_assert_awaited(self):
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited()

        run(self._runnable_test())
        self.mock.assert_awaited()

    def test_assert_awaited_once(self):
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited_once()

        run(self._runnable_test())
        self.mock.assert_awaited_once()

        run(self._runnable_test())
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited_once()

    def test_assert_awaited_with(self):
        msg = 'Not awaited'
        with self.assertRaisesRegex(AssertionError, msg):
            self.mock.assert_awaited_with('foo')

        run(self._runnable_test())
        msg = 'expected await not found'
        with self.assertRaisesRegex(AssertionError, msg):
            self.mock.assert_awaited_with('foo')

        run(self._runnable_test('foo'))
        self.mock.assert_awaited_with('foo')

        run(self._runnable_test('SomethingElse'))
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited_with('foo')

    def test_assert_awaited_once_with(self):
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited_once_with('foo')

        run(self._runnable_test('foo'))
        self.mock.assert_awaited_once_with('foo')

        run(self._runnable_test('foo'))
        with self.assertRaises(AssertionError):
            self.mock.assert_awaited_once_with('foo')

    def test_assert_any_wait(self):
        with self.assertRaises(AssertionError):
            self.mock.assert_any_await('foo')

        run(self._runnable_test('baz'))
        with self.assertRaises(AssertionError):
            self.mock.assert_any_await('foo')

        run(self._runnable_test('foo'))
        self.mock.assert_any_await('foo')

        run(self._runnable_test('SomethingElse'))
        self.mock.assert_any_await('foo')

    def test_assert_has_awaits_no_order(self):
        calls = [call('foo'), call('baz')]

        with self.assertRaises(AssertionError) as cm:
            self.mock.assert_has_awaits(calls)
        self.assertEqual(len(cm.exception.args), 1)

        run(self._runnable_test('foo'))
        with self.assertRaises(AssertionError):
            self.mock.assert_has_awaits(calls)

        run(self._runnable_test('foo'))
        with self.assertRaises(AssertionError):
            self.mock.assert_has_awaits(calls)

        run(self._runnable_test('baz'))
        self.mock.assert_has_awaits(calls)

        run(self._runnable_test('SomethingElse'))
        self.mock.assert_has_awaits(calls)

    def test_awaits_asserts_with_any(self):
        class Foo:
            def __eq__(self, other):
                pass

        run(self._runnable_test(Foo(), 1))

        self.mock.assert_has_awaits([call(ANY, 1)])
        self.mock.assert_awaited_with(ANY, 1)
        self.mock.assert_any_await(ANY, 1)

    def test_awaits_asserts_with_spec_and_any(self):
        class Foo:
            def __eq__(self, other):
                pass

        mock_with_spec = AsyncMock(spec=Foo)

        async def _custom_mock_runnable_test(*args):
            await mock_with_spec(*args)

        run(_custom_mock_runnable_test(Foo(), 1))
        mock_with_spec.assert_has_awaits([call(ANY, 1)])
        mock_with_spec.assert_awaited_with(ANY, 1)
        mock_with_spec.assert_any_await(ANY, 1)

    def test_assert_has_awaits_ordered(self):
        calls = [call('foo'), call('baz')]
        with self.assertRaises(AssertionError):
            self.mock.assert_has_awaits(calls, any_order=True)

        run(self._runnable_test('baz'))
        with self.assertRaises(AssertionError):
            self.mock.assert_has_awaits(calls, any_order=True)

        run(self._runnable_test('bamf'))
        with self.assertRaises(AssertionError):
            self.mock.assert_has_awaits(calls, any_order=True)

        run(self._runnable_test('foo'))
        self.mock.assert_has_awaits(calls, any_order=True)

        run(self._runnable_test('qux'))
        self.mock.assert_has_awaits(calls, any_order=True)

    def test_assert_not_awaited(self):
        self.mock.assert_not_awaited()

        run(self._runnable_test())
        with self.assertRaises(AssertionError):
            self.mock.assert_not_awaited()

    def test_assert_has_awaits_not_matching_spec_error(self):
        async def f(x=None):
            pass

        self.mock = AsyncMock(spec=f)
        run(self._runnable_test(1))

        with self.assertRaisesRegex(
                AssertionError, '^{}$'.format(
                    re.escape('Awaits not found.\n'
                              'Expected: [call()]\n'
                              'Actual: [call(1)]'))) as cm:
            self.mock.assert_has_awaits([call()])
        self.assertIsNone(cm.exception.__cause__)

        with self.assertRaisesRegex(
                AssertionError, '^{}$'.format(
                    re.escape('Error processing expected awaits.\n'
                              "Errors: [None, TypeError('too many positional "
                              "arguments')]\n"
                              'Expected: [call(), call(1, 2)]\n'
                              'Actual: [call(1)]').replace(
                                  "arguments\\'", "arguments\\',?"))) as cm:
            self.mock.assert_has_awaits([call(), call(1, 2)])
        self.assertIsInstance(cm.exception.__cause__, TypeError)
예제 #5
0
    def test_promote_arch(self, get_release_image_info: AsyncMock,
                          build_release_image: AsyncMock,
                          get_image_stream_tag: AsyncMock,
                          tag_release: AsyncMock):
        runtime = MagicMock(config={
            "build_config": {
                "ocp_build_data_url": "https://example.com/ocp-build-data.git"
            }
        },
                            working_dir=Path("/path/to/working"),
                            dry_run=False)
        pipeline = PromotePipeline(
            runtime,
            group="openshift-4.10",
            assembly="4.10.99",
            release_offset=None,
            arches=["x86_64", "s390x", "ppc64le", "aarch64"])
        previous_list = ["4.10.98", "4.10.97", "4.9.99"]
        metadata = {
            "description": "whatever",
            "url": "https://access.redhat.com/errata/RHBA-2099:2222"
        }

        # test x86_64
        reference_release = "whatever-x86_64"
        actual = asyncio.get_event_loop().run_until_complete(
            pipeline.promote_arch(release_name="4.10.99",
                                  arch="x86_64",
                                  previous_list=previous_list,
                                  metadata=metadata,
                                  reference_release=reference_release,
                                  tag_stable=True))
        get_release_image_info.assert_any_await(
            "quay.io/openshift-release-dev/ocp-release:4.10.99-x86_64")
        build_release_image.assert_awaited_once_with(
            "4.10.99", "x86_64", previous_list, metadata,
            "quay.io/openshift-release-dev/ocp-release:4.10.99-x86_64",
            reference_release)
        get_image_stream_tag.assert_awaited_once_with("ocp", "release:4.10.99")
        tag_release.assert_awaited_once_with(
            "quay.io/openshift-release-dev/ocp-release:4.10.99-x86_64",
            "ocp/release:4.10.99")
        self.assertEqual(
            actual["image"],
            "quay.io/openshift-release-dev/ocp-release:4.10.99-x86_64")

        # test aarch64
        reference_release = "whatever-aarch64"
        get_release_image_info.reset_mock()
        build_release_image.reset_mock()
        get_image_stream_tag.reset_mock()
        tag_release.reset_mock()
        actual = asyncio.get_event_loop().run_until_complete(
            pipeline.promote_arch(release_name="4.10.99",
                                  arch="aarch64",
                                  previous_list=previous_list,
                                  metadata=metadata,
                                  reference_release=reference_release,
                                  tag_stable=True))
        get_release_image_info.assert_any_await(
            "quay.io/openshift-release-dev/ocp-release:4.10.99-aarch64")
        build_release_image.assert_awaited_once_with(
            "4.10.99", "aarch64", previous_list, metadata,
            "quay.io/openshift-release-dev/ocp-release:4.10.99-aarch64",
            reference_release)
        get_image_stream_tag.assert_awaited_once_with("ocp-arm64",
                                                      "release-arm64:4.10.99")
        tag_release.assert_awaited_once_with(
            "quay.io/openshift-release-dev/ocp-release:4.10.99-aarch64",
            "ocp-arm64/release-arm64:4.10.99")
        self.assertEqual(
            actual["image"],
            "quay.io/openshift-release-dev/ocp-release:4.10.99-aarch64")

        # test release tag already exists but doesn't match the to-be-promoted release image
        get_image_stream_tag.return_value = {
            "image": {
                "dockerImageReference":
                "quay.io/openshift-release-dev/ocp-release@fake:foobar",
            }
        }
        reference_release = "whatever-aarch64"
        get_release_image_info.reset_mock()
        build_release_image.reset_mock()
        get_image_stream_tag.reset_mock()
        tag_release.reset_mock()
        with self.assertRaisesRegex(
                ValueError, "already exists, but it has a different digest"):
            asyncio.get_event_loop().run_until_complete(
                pipeline.promote_arch(release_name="4.10.99",
                                      arch="aarch64",
                                      previous_list=previous_list,
                                      metadata=metadata,
                                      reference_release=reference_release,
                                      tag_stable=True))
        get_release_image_info.assert_any_await(
            "quay.io/openshift-release-dev/ocp-release:4.10.99-aarch64")
        build_release_image.assert_awaited_once_with(
            "4.10.99", "aarch64", previous_list, metadata,
            "quay.io/openshift-release-dev/ocp-release:4.10.99-aarch64",
            reference_release)
        get_image_stream_tag.assert_awaited_once_with("ocp-arm64",
                                                      "release-arm64:4.10.99")
        tag_release.assert_not_awaited()