"use strict";
/**
 * Discover and run Nexus test files (*_test.nex and tests/*.nex).
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.runTests = runTests;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const engine_1 = require("./compiler/engine");
const modules_1 = require("./runtime/modules");
const values_1 = require("./language/values");
function discover(root, paths) {
    const files = [];
    const seen = new Set();
    const add = (p) => {
        const cleaned = path.normalize(p);
        if (seen.has(cleaned)) {
            return;
        }
        seen.add(cleaned);
        files.push(cleaned);
    };
    const searchRoots = paths.length > 0 ? paths : [path.join(root, "tests"), root];
    for (let p of searchRoots) {
        if (!path.isAbsolute(p)) {
            p = path.join(root, p);
        }
        let st;
        try {
            st = fs.statSync(p);
        }
        catch {
            continue;
        }
        if (!st.isDirectory()) {
            if (p.endsWith(".nex")) {
                add(p);
            }
            continue;
        }
        walk(p, root, add);
    }
    return files;
}
function walk(dir, root, add) {
    for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
        const full = path.join(dir, entry.name);
        if (entry.isDirectory()) {
            if (entry.name === "node_modules" ||
                entry.name === ".git" ||
                entry.name === "out" ||
                entry.name === "bin") {
                continue;
            }
            walk(full, root, add);
            continue;
        }
        const rel = path.relative(root, full).replace(/\\/g, "/");
        const inTests = rel.startsWith("tests/");
        if (entry.name.endsWith("_test.nex") ||
            (inTests && entry.name.endsWith(".nex"))) {
            add(full);
        }
    }
}
async function runTests(opts) {
    const log = opts.out ?? ((line) => {
        // eslint-disable-next-line no-console
        console.log(line);
    });
    const files = discover(opts.rootDir, opts.paths ?? []);
    if (files.length === 0) {
        throw new Error("no test files found (looked for *_test.nex and tests/**/*.nex)");
    }
    const stdlibDir = opts.stdlibDir !== undefined
        ? opts.stdlibDir
        : (0, modules_1.findStdlibDir)(opts.rootDir);
    const summary = { results: [], passed: 0, failed: 0 };
    for (const file of files) {
        const start = Date.now();
        const source = fs.readFileSync(file, "utf8");
        const result = await (0, engine_1.evaluate)(source, {
            tier: "eval",
            rootDir: opts.rootDir,
            modulesDir: path.join(opts.rootDir, modules_1.MODULES_DIRNAME),
            stdlibDir,
            filePath: file,
            checkOwnership: false,
            enableEffects: false,
        });
        const durationMs = Date.now() - start;
        const rel = path.relative(opts.rootDir, file) || file;
        const failed = (0, values_1.isError)(result.value);
        const tr = {
            file,
            passed: !failed,
            durationMs,
            error: failed ? result.value.inspect() : undefined,
            output: result.output,
        };
        summary.results.push(tr);
        if (tr.passed) {
            summary.passed++;
            log(`ok   ${rel} (${durationMs}ms)`);
        }
        else {
            summary.failed++;
            log(`FAIL ${rel} (${durationMs}ms)`);
            log(`  ${tr.error}`);
        }
    }
    log("");
    log(`${summary.passed} passed, ${summary.failed} failed`);
    return summary;
}
//# sourceMappingURL=nextest.js.map