#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%require-types
%enable-all-warnings
%new-style
%strict-args
%allow-injection

%requires ../../../../qlib/Util.qm
%requires ../../../../qlib/QUnit.qm
%requires ../../../../qlib/Logger.qm
%requires ../../../../qlib/DataProvider
%requires ../../../../qlib/FsUtil.qm
%requires ../../../../qlib/FileDataProvider

%exec-class FileDataProviderTest

public class FileDataProviderTest inherits QUnit::Test {
    constructor() : Test("FileDataProvider Test", "1.0") {
        addTestCase("test", \fileDataProviderTest());

        # Return for compatibility with test harness that checks return value.
        set_return_value(main());
    }

    fileDataProviderTest() {
        # create test file
        TmpDir tmpdir("FileDataProviderTest-");
        TmpFile tmp("FileDataProviderTest-", NOTHING, tmpdir.path);
        string str = get_random_string();
        tmp.file.write(str);

        FileDataProvider fdp();

        AbstractDataProvider prov = fdp.getChildProviderEx("stat");
        hash<DataProviderSummaryInfo> sinfo = prov.getSummaryInfo();
        assertEq("stat", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        hash<auto> h = prov.doRequest({
            "path": tmp.path,
        });
        assertEq(tmp.path, h.filepath);
        assertEq("REGULAR", h.type);

        prov = fdp.getChildProviderEx("copy");
        sinfo = prov.getSummaryInfo();
        assertEq("copy", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        string targ = join_paths(tmpdir.path, get_random_string());
        h = prov.doRequest({
            "source": tmp.path,
            "target": targ,
        });
        assertEq(targ, h.target);
        assertTrue(is_file(tmp.path));
        assertTrue(is_file(targ));

        prov = fdp.getChildProviderEx("move");
        sinfo = prov.getSummaryInfo();
        assertEq("move", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        string new_targ = join_paths(tmpdir.path, get_random_string());
        assertNeq(new_targ, targ);
        h = prov.doRequest({
            "source": targ,
            "target": new_targ,
        });
        assertEq(new_targ, h.target);
        assertFalse(is_file(targ));
        assertTrue(is_file(new_targ));

        prov = fdp.getChildProviderEx("delete");
        sinfo = prov.getSummaryInfo();
        assertEq("delete", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        h = prov.doRequest({
            "path": new_targ,
        });
        assertEq(new_targ, h.path);
        assertFalse(is_file(new_targ));

        # delete original file
        delete tmp;

        prov = fdp.getChildProviderEx("create");
        sinfo = prov.getSummaryInfo();
        assertEq("create", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        h = prov.doRequest({
            "path": new_targ,
            "data": str,
        });
        assertEq(new_targ, h.path);
        assertTrue(is_file(new_targ));

        prov = fdp.getChildProviderEx("get");
        sinfo = prov.getSummaryInfo();
        assertEq("get", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        h = prov.doRequest({
            "path": new_targ,
            "text": True,
        });
        assertEq(new_targ, h.path);
        assertEq(str, h."data");

        prov = fdp.getChildProviderEx("list");
        sinfo = prov.getSummaryInfo();
        assertEq("list", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        h = prov.doRequest({
            "path": tmpdir.path,
        })[0];
        assertEq(basename(new_targ), h.name);

        string dir = join_paths(tmpdir.path, get_random_string());
        prov = fdp.getChildProviderEx("mkdir");
        sinfo = prov.getSummaryInfo();
        assertEq("mkdir", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        h = prov.doRequest({
            "path": dir,
        });
        assertEq(dir, h.path);

        prov = fdp.getChildProviderEx("stat");
        sinfo = prov.getSummaryInfo();
        assertEq("stat", sinfo.name);
        assertEq(Type::String, sinfo.desc.type());
        h = prov.doRequest({
            "path": dir,
        });
        assertEq(basename(dir), h.name);
        assertEq("DIRECTORY", h.type);
    }
}
