Example #1
0
File: initdb.py Project: zhill/quay
def setup_database_for_testing(testcase,
                               with_storage=False,
                               force_rebuild=False):
    """ Called when a testcase has started using the database, indicating that
      the database should be setup (if not already) and a savepoint created.
  """

    # Sanity check to make sure we're not killing our prod db
    if not IS_TESTING_REAL_DATABASE and not isinstance(db.obj, SqliteDatabase):
        raise RuntimeError("Attempted to wipe production database!")

    if not db_initialized_for_testing.is_set() or force_rebuild:
        logger.debug("Setting up DB for testing.")

        # Setup the database.
        if os.environ.get("SKIP_DB_SCHEMA", "") != "true":
            wipe_database()
            initialize_database()

        populate_database(with_storage=with_storage)

        models_missing_data = find_models_missing_data()
        if models_missing_data:
            raise RuntimeError("%s models are missing data: %s",
                               len(models_missing_data), models_missing_data)

        # Enable foreign key constraints.
        if not IS_TESTING_REAL_DATABASE:
            db.obj.execute_sql("PRAGMA foreign_keys = ON;")

        db_initialized_for_testing.set()

    # Initialize caches.
    Repository.kind.get_id("image")

    # Create a savepoint for the testcase.
    testcases[testcase] = {}
    testcases[testcase]["transaction"] = db.transaction()
    testcases[testcase]["transaction"].__enter__()

    testcases[testcase]["savepoint"] = db.savepoint()
    testcases[testcase]["savepoint"].__enter__()
Example #2
0
def initialized_db(appconfig):
    """
    Configures the database for the database found in the appconfig.
    """
    under_test_real_database = bool(os.environ.get("TEST_DATABASE_URI"))

    # Configure the database.
    configure(appconfig)

    # Initialize caches.
    model._basequery._lookup_team_roles()
    model._basequery.get_public_repo_visibility()
    model.log.get_log_entry_kinds()

    if not under_test_real_database:
        # Make absolutely sure foreign key constraints are on.
        db.obj.execute_sql("PRAGMA foreign_keys = ON;")
        db.obj.execute_sql('PRAGMA encoding="UTF-8";')
        assert db.obj.execute_sql("PRAGMA foreign_keys;").fetchone()[0] == 1
        assert db.obj.execute_sql("PRAGMA encoding;").fetchone()[0] == "UTF-8"

    # If under a test *real* database, setup a savepoint.
    if under_test_real_database:
        with db.transaction():
            test_savepoint = db.savepoint()
            test_savepoint.__enter__()

            yield  # Run the test.

            try:
                test_savepoint.rollback()
                test_savepoint.__exit__(None, None, None)
            except InternalError:
                # If postgres fails with an exception (like IntegrityError) mid-transaction, it terminates
                # it immediately, so when we go to remove the savepoint, it complains. We can safely ignore
                # this case.
                pass
    else:
        if os.environ.get("DISALLOW_AUTO_JOINS", "false").lower() == "true":
            # Patch get_rel_instance to fail if we try to load any non-joined foreign key. This will allow
            # us to catch missing joins when running tests.
            def get_rel_instance(self, instance):
                value = instance.__data__.get(self.name)
                if value is not None or self.name in instance.__rel__:
                    if self.name not in instance.__rel__:
                        # NOTE: We only raise an exception if this auto-lookup occurs from non-testing code.
                        # Testing code can be a bit inefficient.
                        lookup_allowed = False

                        try:
                            outerframes = inspect.getouterframes(
                                inspect.currentframe())
                        except IndexError:
                            # Happens due to a bug in Jinja.
                            outerframes = []

                        for allowed_auto_join in ALLOWED_AUTO_JOINS:
                            if lookup_allowed:
                                break

                            if (len(outerframes) >=
                                    allowed_auto_join.frame_start_index +
                                    CALLER_FRAMES_OFFSET):
                                found_match = True
                                for index, pattern_prefix in enumerate(
                                        allowed_auto_join.pattern_prefixes):
                                    frame_info = outerframes[
                                        index + CALLER_FRAMES_OFFSET]
                                    if not frame_info[
                                            FRAME_NAME_INDEX].startswith(
                                                pattern_prefix):
                                        found_match = False
                                        break

                                if found_match:
                                    lookup_allowed = True
                                    break

                        if not lookup_allowed:
                            raise Exception(
                                "Missing join on instance `%s` for field `%s`",
                                instance, self.name)

                        obj = self.rel_model.get(self.field.rel_field == value)
                        instance.__rel__[self.name] = obj
                    return instance.__rel__[self.name]
                elif not self.field.null:
                    raise self.rel_model.DoesNotExist

                return value

            with patch("peewee.ForeignKeyAccessor.get_rel_instance",
                       get_rel_instance):
                yield
        else:
            yield