#!/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

%exec-class ConnectionProviderModuleTest

public class ConnectionProviderModuleTest inherits QUnit::Test {
    constructor() : Test("ConnectionProvider Test", "1.0") {
        addTestCase("urlp test", \urlProviderTest());
        addTestCase("urlp neg test", \urlProviderNegativeTest());
        addTestCase("filesystem", \filesystemConnectionTest());

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

    urlProviderTest() {
        Program mp(PO_NO_CHILD_PO_RESTRICTIONS|PO_NEW_STYLE);
        mp.setGlobalVarValue("ENV", ENV + {"QORE_CONNECTION_PROVIDERS": get_script_dir() + "./TestConnectionProvider.qm"});
        mp.loadApplyToUserModule(get_script_dir() + "../../../../qlib/ConnectionProvider", True);

        {
            Program p();
            p.loadModule("ConnectionProvider");
            p.parse("string sub test(string str) { return get_connection_url(str); }", "");
            assertEq("test://user:pass@x", p.callFunction("test", "X"));
            assertThrows("CONNECTION-ERROR", \p.callFunction(), ("test", "Y"));
        }

        {
            Program p();
            p.loadModule("ConnectionProvider");
            p.parsePending("AbstractConnection sub get_obj(string str) { return get_connection(str); }", "");
            p.parsePending("hash sub get_conn() { return get_connections(); }", "");
            p.parse("hash sub get_hash() { return get_connection_hash(); }", "");
            any obj = p.callFunction("get_obj", "X");
            assertEq(Type::Object, obj.type());
            assertEq("test://user:<masked>@x", obj.getInfo().url);
            assertEq(NOTHING, obj.getInfo().url_hash.password);
            assertEq("test://user:pass@x", obj.getInfo(True).url);
            assertEq("pass", obj.getInfo(True).url_hash.password);
            assertEq(Type::Hash, p.callFunction("get_conn").type());
            assertEq(Type::Hash, p.callFunction("get_hash").type());
        }
    }

    urlProviderNegativeTest() {
        Program mp(PO_NO_CHILD_PO_RESTRICTIONS|PO_NEW_STYLE);
        mp.loadApplyToUserModule(get_script_dir() + "../../../../qlib/ConnectionProvider", True);

        Program p();
        p.loadModule("ConnectionProvider");
        p.parse("string sub test(string str) { return get_connection_url(str); }", "");
        assertThrows("CONNECTION-ERROR", \p.callFunction(), ("test", "X"));
        assertEq("X://x", p.callFunction("test", "X://x"));
    }

    filesystemConnectionTest() {
        Program p();
        p.loadModule("ConnectionProvider");
        p.loadModule("Util");

        p.parse("FilesystemConnection sub get_conn() {
    string dir = tmp_location() + '/' + get_random_string() + '/' + get_random_string();
    string url = 'file://' + dir;
    return new FilesystemConnection('test', 'desc', url);
}", "");

        object o = p.callFunction("get_conn");
        hash h = o.ping();
        assertEq("test", h.name);
        assertEq("desc", h.desc);
        assertEq(False, h.ok);

        o.opts.readonly = True;
        h = o.ping();
        assertEq("test", h.name);
        assertEq("desc", h.desc);
        assertEq(True, h.ok);
    }
}
