view tests/run.d @ 208:41ccd50e7cbc

Added missing tests
author Anders Johnsen <skabet@gmail.com>
date Tue, 12 Aug 2008 18:21:06 +0200
parents d3c148ca429b
children
line wrap: on
line source

// skip
module run.d;

import tango.core.Array,
       tango.io.FileConduit,
       tango.io.FileScan,
       tango.io.Stdout,
       tango.sys.Process,
       tango.text.Ascii,
       tango.text.Regex,
       tango.text.Util;

// -- Settings --
char[] compiler = "./Dang";
char[] test_folder = "tests";
char[] valid_filenames = r"^[^.].*";
bool print_expected = false;
char[][] options;
// the tests can be sorted by one of the following functions
bool nameSort    (FilePath a, FilePath b) { return a.name     < b.name;     }
bool pathSort    (FilePath a, FilePath b) { return a.toString < b.toString; }
bool modifiedSort(FilePath a, FilePath b) { return a.modified < b.modified; }
bool createdSort (FilePath a, FilePath b) { return a.created  < b.created;  }
const sortBy = &pathSort;

// -- end of settings

enum TestResult
{
    Skipped,
    Expected,
    Unexpected
}

void main(char[][] args)
{
    foreach (arg ; args[1..$])
        options ~= arg;

    scope scan = new FileScan;
//    scope regex = new Regex(valid_filenames); // DMD FAILS!! ?? 
    // Return true for files/folders to include
    bool filter(FilePath p, bool isDir)
    {
        if (isDir)
            return p.name[0] != '.';
        else
            return p.ext == "d" ; //&& regex.test(p.name);
    }
    scan.sweep(test_folder, &filter, true);
    FilePath[] files = scan.files;
    int total_tests = files.length;

    // Sort the result by the chosen function - default is the full path
    sort(files, sortBy);

    int[TestResult.max + 1] results = 0;
    foreach (i, ref test; files)
    {
        begin_test(i + 1, total_tests, test.name);
        TestResult res = run_test(test);
        results[res] += 1;
        end_test();
    }
    Stdout.format("\r{,80}\r", " ");
    Stdout.newline;
    int good = TestResult.Expected;
    int bad = TestResult.Unexpected;
    int tests_run = results[good] + results[bad];
    Stdout.formatln("{}/{} tests failed", results[bad], tests_run);
}

void begin_test(int number, int total_tests, char[] name)
{
    char[60] progressbar = ' ';
    int progress = number*progressbar.length/total_tests;
    progressbar[0 .. progress] = '=';
    if(progress)
        progressbar[progress-1] = '>';
    Stdout.format("\r{}% - [{}]", 1e2 * number / total_tests, progressbar);
    Stdout.flush();
    //Thread.sleep(0.05);
}

void end_test() { }

enum {
    NoFail,
    CompiletimeFail,
    RuntimeFail
}

private int min(int a, int b) { return a < b? a : b; }
TestResult run_test(ref FilePath p)
{
    auto file = new FileConduit(p.toString(), FileConduit.ReadExisting);
    char[256] content;
    int len = file.read(content);
    file.close();
    char[] line = content[0 .. min(len, content.find('\n'))];

    bool compile = true;
    int fail = NoFail;
    if (line.length >= 2 && line[0 .. 2] == "//")
    {
        foreach (command; line[2 .. $].delimiters(",;"))
        {
            switch (toLower(substitute(command, " ", "")))
            {
                case "skip", "dontcompile":
                    compile = false;
                    break;
                case "fail", "compilefail",
                     "compiletimefail", "failatcompiletime":
                    fail = CompiletimeFail;
                    break;
                case "runtime", "runtimefail", "failatruntime":
                    fail = RuntimeFail;
                    Stderr("== Compiled tests will not be run! ==").newline;
                    return TestResult.Skipped;
                default:
                    break;
            }
            break;
        }
    }

    if (compile)
    {
        auto o = compiler ~ options ~ p.toString;
        auto process = new Process(o);
        process.execute();
        auto result = process.wait();
        return resultOf(p, result.status, fail); 
    }

    return TestResult.Skipped;
}

private TestResult resultOf(FilePath p, int result, int expected)
{
    char[] good(char[] s)
    {
        version (Posix)
            return "\033[1;32m" ~ s ~ "\033[m";
        else
            return s;
    }

    char[] bad(char[] s)
    {
        s = s ~ " - Unexpected";
        version (Posix)
            return "\033[1;31m" ~ s ~ "\033[m";
        else
            return s;
    }

    bool unexpected = expected == 0 ? result != 0 : result == 0;
    auto f = unexpected? &bad : &good;
    char[] s = (result == 0)? "SUCCESS" : "FAILURE";
    // always print if unexpeted, otherwise check the settings
    if (unexpected || print_expected)
    {
        Stdout.format("\r{,80}\r", " ");
        Stdout.format("  {,-45}", p);
        Stdout(f(s)).newline;
    }
    return unexpected? TestResult.Unexpected : TestResult.Expected;
}