<commit_before>import * as BluebirdPromise from "bluebird";
import { ChildProcess, spawn } from "child_process";
import * as os from "os";
import { MultiError } from "verror";

import { CONSTANTS } from "../Constants";
import { DocumentStore } from "../Documents/DocumentStore";
import { IDocumentStore } from "../Documents/IDocumentStore";
import { DatabaseStatistics } from "../Documents/Operations/DatabaseStatistics";
import { GetStatisticsOperation } from "../Documents/Operations/GetStatisticsOperation";
import { throwError, getError } from "../Exceptions";
import { DatabaseRecord } from "../ServerWide";
import { CreateDatabaseOperation } from "../ServerWide/Operations/CreateDatabaseOperation";
import { DeleteDatabasesOperation } from "../ServerWide/Operations/DeleteDatabasesOperation";
import { Todo } from "../Types";
import { IDisposable } from "../Types/Contracts";
import { getLogger } from "../Utility/LogUtil";
import { RavenServerLocator } from "./RavenServerLocator";
import { RavenServerRunner } from "./RavenServerRunner";
import { TypeUtil } from "../Utility/TypeUtil";

const log = getLogger({ module: "TestDriver" });

export abstract class RavenTestDriver implements IDisposable {

    private _locator: RavenServerLocator;
    private _securedLocator: RavenServerLocator;

    private static _globalServer: DocumentStore;
    private static _globalServerProcess: ChildProcess;

    private static _globalSecuredServer: DocumentStore;
    private static _globalSecuredServerProcess: ChildProcess;

    private _documentStores: Set<IDocumentStore> = new Set();

    private static _index: number = 0;

    protected _disposed: boolean = false;

    public constructor(locator: RavenServerLocator, securedLocator: RavenServerLocator) {
        this._locator = locator;
        this._securedLocator = securedLocator;
    }

    public isDisposed(): boolean {
        return this._disposed;
    }

    public static debug: boolean;

    public getSecuredDocumentStore(): Promise<DocumentStore>; 
    public getSecuredDocumentStore(database?): Promise<DocumentStore> { 
        return this.getDocumentStore(database, true, null);
    }

    private _customizeDbRecord: (dbRecord: DatabaseRecord) => void = TypeUtil.NOOP;

    public set customizeDbRecord(customizeDbRecord: (dbRecord: DatabaseRecord) => void) {
        this._customizeDbRecord = customizeDbRecord;
    }

    public get customizeDbRecord() {
        return this._customizeDbRecord;
    }

    public getDocumentStore(): Promise<DocumentStore>;
    public getDocumentStore(database: string): Promise<DocumentStore>;
    public getDocumentStore(database: string, secured: boolean): Promise<DocumentStore>;
    public getDocumentStore(
        database: string, secured: boolean, waitForIndexingTimeoutInMs?: number): Promise<DocumentStore>; 
    public getDocumentStore(
        database = "test_db", secured = false, waitForIndexingTimeoutInMs: number = null): Promise<DocumentStore> {

        const databaseName = database + "_" + (++RavenTestDriver._index);
        log.info(`getDocumentStore for db ${ database }.`);

        let documentStore: IDocumentStore;
        return Promise.resolve()
        .then(() => {
            if (!this._getGlobalServer(secured)) {
                return this._runServer(secured);
            }
        })
        .then(() => {
            documentStore = this._getGlobalServer(secured);
            const databaseRecord: DatabaseRecord = { databaseName };

            if (this._customizeDbRecord) {
                this._customizeDbRecord(databaseRecord);
            }

            const createDatabaseOperation = new CreateDatabaseOperation(databaseRecord);
            return documentStore.maintenance.server.send(createDatabaseOperation);
        })
        .then(createDatabaseResult => {
            const store = new DocumentStore(documentStore.urls, databaseName);
            if (secured) {
                store.authOptions = this._securedLocator.getClientAuthOptions();
            }

            store.initialize();

            (store as IDocumentStore).once("afterDispose", (callback) => {
                if (!this._documentStores.has(store)) {
                    callback();
                    return; 
                }

                return BluebirdPromise.resolve()
                    .then(() => {
                        return store.maintenance.server.send(new DeleteDatabasesOperation({
                            databaseNames: [ store.database ],
                            hardDelete: true
                        }));
                    })
                    .tap((deleteResult) => {
                        log.info(`Database ${store.database} deleted.`);
                    })
                    .catch(err => {
                        if (err.name === "DatabaseDoesNotExistException"
                        || err.name === "NoLeaderException") {
                            return;
                        }
                        
                        throwError("TestDriverTearDownError", `Error deleting database ${ store.database }.`, err);
                    })
                    .finally(() => callback());
            });

            return Promise.resolve()
                .then(() => this._setupDatabase(store))
                .then(() => {
                    if (!TypeUtil.isNullOrUndefined(waitForIndexingTimeoutInMs)) {
                        return this.waitForIndexing(store);
                    }
                })
                .then(() => this._documentStores.add(store))
                .then(() => store);

        });
    }

    protected _setupDatabase(documentStore: IDocumentStore): Promise<void> {
        return Promise.resolve();
    }
<commit_msg>discard connection errors when server is killed already<commit_after>import * as BluebirdPromise from "bluebird";
import { ChildProcess, spawn } from "child_process";
import * as os from "os";
import { MultiError } from "verror";

import { CONSTANTS } from "../Constants";
import { DocumentStore } from "../Documents/DocumentStore";
import { IDocumentStore } from "../Documents/IDocumentStore";
import { DatabaseStatistics } from "../Documents/Operations/DatabaseStatistics";
import { GetStatisticsOperation } from "../Documents/Operations/GetStatisticsOperation";
import { throwError, getError } from "../Exceptions";
import { DatabaseRecord } from "../ServerWide";
import { CreateDatabaseOperation } from "../ServerWide/Operations/CreateDatabaseOperation";
import { DeleteDatabasesOperation } from "../ServerWide/Operations/DeleteDatabasesOperation";
import { Todo } from "../Types";
import { IDisposable } from "../Types/Contracts";
import { getLogger } from "../Utility/LogUtil";
import { RavenServerLocator } from "./RavenServerLocator";
import { RavenServerRunner } from "./RavenServerRunner";
import { TypeUtil } from "../Utility/TypeUtil";

const log = getLogger({ module: "TestDriver" });

export abstract class RavenTestDriver implements IDisposable {

    private _locator: RavenServerLocator;
    private _securedLocator: RavenServerLocator;

    private static _globalServer: DocumentStore;
    private static _globalServerProcess: ChildProcess;

    private static _globalSecuredServer: DocumentStore;
    private static _globalSecuredServerProcess: ChildProcess;

    private _documentStores: Set<IDocumentStore> = new Set();

    private static _index: number = 0;

    protected _disposed: boolean = false;

    public constructor(locator: RavenServerLocator, securedLocator: RavenServerLocator) {
        this._locator = locator;
        this._securedLocator = securedLocator;
    }

    public isDisposed(): boolean {
        return this._disposed;
    }

    public static debug: boolean;

    public getSecuredDocumentStore(): Promise<DocumentStore>; 
    public getSecuredDocumentStore(database?): Promise<DocumentStore> { 
        return this.getDocumentStore(database, true, null);
    }

    private _customizeDbRecord: (dbRecord: DatabaseRecord) => void = TypeUtil.NOOP;

    public set customizeDbRecord(customizeDbRecord: (dbRecord: DatabaseRecord) => void) {
        this._customizeDbRecord = customizeDbRecord;
    }

    public get customizeDbRecord() {
        return this._customizeDbRecord;
    }

    public getDocumentStore(): Promise<DocumentStore>;
    public getDocumentStore(database: string): Promise<DocumentStore>;
    public getDocumentStore(database: string, secured: boolean): Promise<DocumentStore>;
    public getDocumentStore(
        database: string, secured: boolean, waitForIndexingTimeoutInMs?: number): Promise<DocumentStore>; 
    public getDocumentStore(
        database = "test_db", secured = false, waitForIndexingTimeoutInMs: number = null): Promise<DocumentStore> {

        const databaseName = database + "_" + (++RavenTestDriver._index);
        log.info(`getDocumentStore for db ${ database }.`);

        let documentStore: IDocumentStore;
        return Promise.resolve()
        .then(() => {
            if (!this._getGlobalServer(secured)) {
                return this._runServer(secured);
            }
        })
        .then(() => {
            documentStore = this._getGlobalServer(secured);
            const databaseRecord: DatabaseRecord = { databaseName };

            if (this._customizeDbRecord) {
                this._customizeDbRecord(databaseRecord);
            }

            const createDatabaseOperation = new CreateDatabaseOperation(databaseRecord);
            return documentStore.maintenance.server.send(createDatabaseOperation);
        })
        .then(createDatabaseResult => {
            const store = new DocumentStore(documentStore.urls, databaseName);
            if (secured) {
                store.authOptions = this._securedLocator.getClientAuthOptions();
            }

            store.initialize();

            (store as IDocumentStore).once("afterDispose", (callback) => {
                if (!this._documentStores.has(store)) {
                    callback();
                    return; 
                }

                return BluebirdPromise.resolve()
                    .then(() => {
                        return store.maintenance.server.send(new DeleteDatabasesOperation({
                            databaseNames: [ store.database ],
                            hardDelete: true
                        }));
                    })
                    .tap((deleteResult) => {
                        log.info(`Database ${store.database} deleted.`);
                    })
                    .catch(err => {
                        if (err.name === "DatabaseDoesNotExistException"
                        || err.name === "NoLeaderException") {
                            return;
                        }

                        const p1 = this._getGlobalProcess(true);
                        const p2 = this._getGlobalProcess(false);
                        if (!p1 && !p2) {
                            return;
                        }
                        
                        throwError("TestDriverTearDownError", `Error deleting database ${ store.database }.`, err);
                    })
                    .finally(() => callback());
            });

            return Promise.resolve()
                .then(() => this._setupDatabase(store))
                .then(() => {
                    if (!TypeUtil.isNullOrUndefined(waitForIndexingTimeoutInMs)) {
                        return this.waitForIndexing(store);
                    }
                })
                .then(() => this._documentStores.add(store))
                .then(() => store);

        });
    }

    protected _setupDatabase(documentStore: IDocumentStore): Promise<void> {
        return Promise.resolve();
    }

{'fraction_non_alphanumeric': 0.10550847457627119, 'fraction_numerical': 0.0005084745762711864, 'mean_word_length': 2.27623542476402, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1323924', 'n_tokens_mistral': 2914, 'n_tokens_neox': 2752, 'n_words': 631}