Пример #1
0
    def run_testcase(self, testcase):
        env = testcase.get('env', {})
        test_env = {'EDGEDB_HOST': None, 'EDGEDB_PORT': None,
                    'EDGEDB_USER': None, 'EDGEDB_PASSWORD': None,
                    'EDGEDB_DATABASE': None, 'PGSSLMODE': None}
        test_env.update(env)

        dsn = testcase.get('dsn')
        user = testcase.get('user')
        port = testcase.get('port')
        host = testcase.get('host')
        password = testcase.get('password')
        database = testcase.get('database')
        admin = testcase.get('admin')
        timeout = testcase.get('timeout')
        command_timeout = testcase.get('command_timeout')
        server_settings = testcase.get('server_settings')

        expected = testcase.get('result')
        expected_error = testcase.get('error')
        if expected is None and expected_error is None:
            raise RuntimeError(
                'invalid test case: either "result" or "error" key '
                'has to be specified')
        if expected is not None and expected_error is not None:
            raise RuntimeError(
                'invalid test case: either "result" or "error" key '
                'has to be specified, got both')

        result = None
        with contextlib.ExitStack() as es:
            es.enter_context(self.subTest(dsn=dsn, env=env))
            es.enter_context(self.environ(**test_env))

            if expected_error:
                es.enter_context(self.assertRaisesRegex(*expected_error))

            addrs, params, config = con_utils.parse_connect_arguments(
                dsn=dsn, host=host, port=port, user=user, password=password,
                database=database, admin=admin,
                timeout=timeout, command_timeout=command_timeout,
                server_settings=server_settings)

            params = {k: v for k, v in params._asdict().items()
                      if v is not None}
            config = {k: v for k, v in config._asdict().items()
                      if v is not None}

            result = (addrs, params, config)

        if expected is not None:
            for k, v in expected[1].items():
                # If `expected` contains a type, allow that to "match" any
                # instance of that type that `result` may contain.
                if isinstance(v, type) and isinstance(result[1].get(k), v):
                    result[1][k] = v
            self.assertEqual(expected, result, 'Testcase: {}'.format(testcase))
Пример #2
0
    def test_project_config(self):
        with tempfile.TemporaryDirectory() as tmp:
            tmp = os.path.realpath(tmp)
            base = pathlib.Path(tmp)
            home = base / 'home'
            project = base / 'project'
            projects = home / '.edgedb' / 'projects'
            creds = home / '.edgedb' / 'credentials'
            os.makedirs(projects)
            os.makedirs(creds)
            os.makedirs(project)
            with open(project / 'edgedb.toml', 'wt') as f:
                f.write('')  # app don't read toml file
            with open(creds / 'inst1.json', 'wt') as f:
                f.write(json.dumps({
                    "host": "inst1.example.org",
                    "port": 12323,
                    "user": "******",
                    "password": "******",
                    "database": "inst1_db",
                }))

            with mock.patch('edgedb.platform.config_dir',
                            lambda: home / '.edgedb'), \
                    mock.patch('os.getcwd', lambda: str(project)):
                stash_path = con_utils._stash_path(project)
                instance_file = stash_path / 'instance-name'
                os.makedirs(stash_path)
                with open(instance_file, 'wt') as f:
                    f.write('inst1')

                connect_config, client_config = (
                    con_utils.parse_connect_arguments(
                        dsn=None,
                        host=None,
                        port=None,
                        credentials=None,
                        credentials_file=None,
                        user=None,
                        password=None,
                        database=None,
                        tls_ca=None,
                        tls_ca_file=None,
                        tls_security=None,
                        timeout=10,
                        command_timeout=None,
                        server_settings=None,
                        wait_until_available=30,
                    )
                )

        self.assertEqual(connect_config.address, ('inst1.example.org', 12323))
        self.assertEqual(connect_config.user, 'inst1_user')
        self.assertEqual(connect_config.password, 'passw1')
        self.assertEqual(connect_config.database, 'inst1_db')
Пример #3
0
    async def connect(self, single_attempt=False):
        self._params, client_config = con_utils.parse_connect_arguments(
            **self._connect_args,
            command_timeout=None,
            server_settings=None,
        )
        start = time.monotonic()
        if single_attempt:
            max_time = 0
        else:
            max_time = start + client_config.wait_until_available
        iteration = 1

        while True:
            addr = self._params.address
            try:
                await asyncio.wait_for(
                    self.connect_addr(),
                    client_config.connect_timeout,
                )
            except TimeoutError as e:
                if iteration > 1 and time.monotonic() >= max_time:
                    raise errors.ClientConnectionTimeoutError(
                        f"connecting to {addr} failed in"
                        f" {client_config.connect_timeout} sec") from e
            except errors.ClientConnectionError as e:
                if (not e.has_tag(errors.SHOULD_RECONNECT)
                        or (iteration > 1 and time.monotonic() >= max_time)):
                    nice_err = e.__class__(
                        con_utils.render_client_no_connection_error(
                            e,
                            addr,
                            attempts=iteration,
                            duration=time.monotonic() - start,
                        ))
                    raise nice_err from e.__cause__
            else:
                return

            iteration += 1
            await asyncio.sleep(0.01 + random.random() * 0.2)
Пример #4
0
    def run_testcase(self, testcase):
        env = testcase.get('env', {})
        test_env = {'EDGEDB_HOST': None, 'EDGEDB_PORT': None,
                    'EDGEDB_USER': None, 'EDGEDB_PASSWORD': None,
                    'EDGEDB_DATABASE': None, 'PGSSLMODE': None,
                    'XDG_CONFIG_HOME': None}
        test_env.update(env)

        fs = testcase.get('fs')

        opts = testcase.get('opts', {})
        dsn = opts.get('dsn')
        credentials = opts.get('credentials')
        credentials_file = opts.get('credentialsFile')
        host = opts.get('host')
        port = opts.get('port')
        database = opts.get('database')
        user = opts.get('user')
        password = opts.get('password')
        tls_ca = opts.get('tlsCA')
        tls_ca_file = opts.get('tlsCAFile')
        tls_security = opts.get('tlsSecurity')
        server_settings = opts.get('serverSettings')

        other_opts = testcase.get('other_opts', {})
        timeout = other_opts.get('timeout')
        command_timeout = other_opts.get('command_timeout')

        expected = (testcase.get('result'), testcase.get('other_results'))
        expected_error = testcase.get('error')
        if expected_error and expected_error.get('type'):
            expected_error = self.error_mapping.get(expected_error.get('type'))
            if not expected_error:
                raise RuntimeError(
                    f"unknown error type: {testcase.get('error').get('type')}")

        if expected[0] is None and expected_error is None:
            raise RuntimeError(
                'invalid test case: either "result" or "error" key '
                'has to be specified')
        if expected[0] is not None and expected_error is not None:
            raise RuntimeError(
                'invalid test case: either "result" or "error" key '
                'has to be specified, got both')

        result = None
        with contextlib.ExitStack() as es:
            es.enter_context(self.subTest(dsn=dsn, env=env, opts=opts))
            es.enter_context(self.environ(**test_env))

            stat_result = os.stat(os.getcwd())
            es.enter_context(
                mock.patch('os.stat', lambda _: stat_result)
            )

            if fs:
                cwd = fs.get('cwd')
                homedir = fs.get('homedir')
                files = fs.get('files')

                if cwd:
                    es.enter_context(mock.patch('os.getcwd', lambda: cwd))
                if homedir:
                    homedir = pathlib.Path(homedir)
                    es.enter_context(
                        mock.patch('pathlib.Path.home', lambda: homedir)
                    )
                if files:
                    for f, v in files.copy().items():
                        if "${HASH}" in f:
                            hash = con_utils._hash_path(v['project-path'])
                            dir = f.replace("${HASH}", hash)
                            files[dir] = ""
                            instance = os.path.join(dir, 'instance-name')
                            files[instance] = v['instance-name']
                            project = os.path.join(dir, 'project-path')
                            files[project] = v['project-path']
                            del files[f]

                    es.enter_context(
                        mock.patch(
                            'os.path.exists',
                            lambda filepath: str(filepath) in files
                        )
                    )
                    es.enter_context(
                        mock.patch(
                            'os.path.isfile',
                            lambda filepath: str(filepath) in files
                        )
                    )

                    es.enter_context(mock.patch(
                        'os.stat',
                        lambda d: mock.Mock(st_dev=0),
                    ))

                    es.enter_context(
                        mock.patch('os.path.realpath', lambda f: f)
                    )

                    def mocked_open(filepath, *args, **kwargs):
                        if str(filepath) in files:
                            return mock.mock_open(
                                read_data=files.get(str(filepath))
                            )()
                        raise FileNotFoundError(
                            f"[Errno 2] No such file or directory: " +
                            f"'{filepath}'"
                        )
                    es.enter_context(mock.patch('builtins.open', mocked_open))

            if expected_error:
                es.enter_context(self.assertRaisesRegex(*expected_error))

            connect_config, client_config = con_utils.parse_connect_arguments(
                dsn=dsn,
                host=host,
                port=port,
                credentials=credentials,
                credentials_file=credentials_file,
                database=database,
                user=user,
                password=password,
                tls_ca=tls_ca,
                tls_ca_file=tls_ca_file,
                tls_security=tls_security,
                timeout=timeout,
                command_timeout=command_timeout,
                server_settings=server_settings,
                wait_until_available=30,
            )

            result = (
                {
                    'address': [
                        connect_config.address[0], connect_config.address[1]
                    ],
                    'database': connect_config.database,
                    'user': connect_config.user,
                    'password': connect_config.password,
                    'tlsCAData': connect_config._tls_ca_data,
                    'tlsSecurity': connect_config.tls_security,
                    'serverSettings': connect_config.server_settings
                }, {
                    k: v for k, v in client_config._asdict().items()
                    if v is not None
                } if testcase.get('other_results') else None
            )

        if expected[0] is not None:
            if (expected[1]):
                for k, v in expected[1].items():
                    # If `expected` contains a type, allow that to "match" any
                    # instance of that type that `result` may contain.
                    if isinstance(v, type) and isinstance(result[1].get(k), v):
                        result[1][k] = v
            self.assertEqual(expected, result)