login

local ffi = require "ffi"

ffi.cdef[[
typedef unsigned long ino_t;
typedef unsigned long off_t;
struct dirent {
    ino_t          d_ino;       /* Inode number */
    off_t          d_off;       /* Not an offset; see below */
    unsigned short d_reclen;    /* Length of this record */
    unsigned char  d_type;      /* Type of file; not supported
                                  by all filesystem types */
    char           d_name[256]; /* Null-terminated filename */
};
int scandir(const char *restrict dirp,
    struct dirent ***restrict namelist,
    int (*filter)(const struct dirent *),
    int (*compar)(const struct dirent **,
        const struct dirent **));
int alphasort(const struct dirent **a, const struct dirent **b);
]]
local C = ffi.C

local function listdir(path, filter)
    local c_filter = filter and function (entry)
        return filter(ffi.string(entry.d_name))
    end
    local pentries = ffi.new("struct dirent **[1]")
    local n = C.scandir(path, pentries, c_filter, C.alphasort)
    local entries = pentries[0]
    local list = {}
    for i = 1, n do
        table.insert(list, ffi.string(entries[i-1].d_name))
    end
    return list
end

local function run_pattern(pattern)
    local function filter(name)
        return name:match(pattern) ~= nil
    end
    local list = listdir(".", filter)
    local total_test_count = 0
    local mod_count = 0
    for _, name in ipairs(list) do
        local modname = name:match(pattern)
        print(modname)
        local Suite = require(modname)
        local test_count = 0
        for funcname in pairs(Suite) do
            print("  "..funcname)
            Suite[funcname]()
            test_count = test_count + 1
        end
        print("  "..test_count.." test(s) OK")
        total_test_count = total_test_count + test_count
        mod_count = mod_count + 1
    end
    print(total_test_count.." test(s) in "..mod_count.." suite(s) OK")
end

run_pattern("^(test_.*)%.lua")