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

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

%requires ../../../../qlib/QUnit.qm

%exec-class SprintfTest

public class A {
}

public class SprintfTest inherits QUnit::Test {
    constructor() : Test("Sprintf test", "1.0") {
        addTestCase("separators", \separators());
        addTestCase("broken sprintf test", \brokenSprintf());
        addTestCase("Test 1", \test(), NOTHING);

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

    separators() {
        string str = sprintf("%y", (1, 2.0));
        assertEq("[1, 2.0]", str);
        assertEq("-2e-34", sprintf("%g", -2e-34));
    }

    brokenSprintf() {
        Program p(PO_NEW_STYLE | PO_BROKEN_SPRINTF);
        p.parse("
auto sub test0() { return call_function_args('vsprintf', argv); }
auto sub test1(string fmt) { softlist<auto> args = fmt; if (argv) args += argv; return call_function_args('sprintf', args); }
", "");
        assertEq("% d", p.callFunction("test0", "% d"));
        assertEq("% d", p.callFunction("test0", "% d", NOTHING));
        # corner cases verified with the old implementation
        assertEq("0", p.callFunction("test0", "% d", ()));
        assertEq("% d", p.callFunction("test0", "% d", NOTHING));
        assertEq("% d", p.callFunction("test0", "% d"));
        assertEq("0", p.callFunction("test1", "%d", NOTHING));
        assertEq("%d", p.callFunction("test1", "%d"));
        assertEq("0 %d", p.callFunction("test1", "%d %d", NOTHING));
        assertEq("%d %d", p.callFunction("test1", "%d %d"));
    }

    test() {
        assertEq("0025-101.24", sprintf("%04d-%.2f", 25, 101.239));
        assertEq("0025-101.24", vsprintf("%04d-%.2f", (25, 101.239)));
        assertEq("   +101.24", sprintf("%+10.2f", 101.239));
        assertEq("+101.24   ", sprintf("%-+10.2f", 101.239));
        assertEq("+000101.24", sprintf("%+010.2f", 101.239));
        assertEq("%%%%", sprintf("%%%%%%%%"));
        assertEq("99", sprintf("%N%n", 9, 9));
        assertEq("7f 1C FFFF", sprintf("%x %X %X", 127, 28, 65535));
        assertEq("class A: <NO MEMBERS>", sprintf("%n", new A()));
        assertEq("niñ", f_sprintf("%3s", "niña"), "UTF-8 f_sprintf()");
        assertEq("0", sprintf("% d", NOTHING));
        assertEq("0", sprintf("% d"));
        assertEq("0", vsprintf("% d", (NOTHING,)));
        assertEq("0", vsprintf("% d", ()));
        assertEq("% 0", sprintf("%% % d", NOTHING));
        assertEq("% 0", sprintf("%% % d"));
        assertEq("% 0", vsprintf("%% % d", (NOTHING,)));
        assertEq("% 0", vsprintf("%% % d", ()));
        assertEq("0.000000", sprintf("% f", NOTHING));
        assertEq("0.000000", sprintf("% f"));
        assertEq("0.000000", vsprintf("% f", (NOTHING,)));
        assertEq("0.000000", vsprintf("% f", ()));
        assertEq("% 0.000000", sprintf("%% % f", NOTHING));
        assertEq("% 0.000000", sprintf("%% % f"));
        assertEq("% 0.000000", vsprintf("%% % f", (NOTHING,)));
        assertEq("% 0.000000", vsprintf("%% % f", ()));
        assertEq("", sprintf("% s", NOTHING));
        assertEq("", sprintf("% s"));
        assertEq("", vsprintf("% s", (NOTHING,)));
        assertEq("", vsprintf("% s", ()));
        assertEq("%", sprintf("%%% s", NOTHING));
        assertEq("%", sprintf("%%% s"));
        assertEq("%", vsprintf("%%% s", (NOTHING,)));
        assertEq("%", vsprintf("%%% s", ()));
        assertEq("arg", vsprintf("%s", "arg"));
        assertEq("arg", vsprintf("%s", ("arg",)));
    }
}
