/*
**  OSSP tai - Time Handling
**  Copyright (c) 2002-2003 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2002-2003 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2002-2003 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
**  This file is part of OSSP tai, a time handling library
**  which can be found at http://www.ossp.org/pkg/lib/tai/.
**
**  Permission to use, copy, modify, and distribute this software for
**  any purpose with or without fee is hereby granted, provided that
**  the above copyright notice and this permission notice appear in all
**  copies.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
**  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
**  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
**  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
**  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
**  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
**  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
**  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
**  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
**  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
**  SUCH DAMAGE.
**
**  tai_test.c: test suite
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "ts.h"
#include "tai.h"

TS_TEST(test_calendar)
{
    tai_t *tai;
    char out[1024];

    ts_test_check(TS_CTX, "calendar calculations");
    tai_create(&tai);
    tai_import(tai, TAI_TYPE_UNIX);
    tai_format(tai, out, sizeof(out), "%a %Y-%m-%d %H:%M:%S %z");
    tai_destroy(tai);
}
TS_TEST(test_object)
{
    tai_t *tm;
    tai_rc_t rv;

    ts_test_check(TS_CTX, "object creation");
    if ((rv = tai_create(&tm)) != TAI_OK) {
        ts_test_fail(TS_CTX, "tai_create: rv=%d", rv);
        return;
    }

    ts_test_check(TS_CTX, "object destruction");
    if ((rv = tai_destroy(tm)) != TAI_OK)
        ts_test_fail(TS_CTX, "tai_destroy: rv=%d", rv);
}

TS_TEST(test_importexport)
{
    tai_t *tm;
    tai_rc_t rv;
    time_t t;
    time_t t2;

    ts_test_check(TS_CTX, "time import");
    tai_create(&tm);
    if ((rv = tai_import(tm, TAI_TYPE_TIMET, 0)) != TAI_OK)
        ts_test_fail(TS_CTX, "tai_import: rv=%d", rv);
    if ((rv = tai_export(tm, TAI_TYPE_TIMET, &t)) != TAI_OK)
        ts_test_fail(TS_CTX, "tai_export: rv=%d", rv);
    if (t != 0)
        ts_test_fail(TS_CTX, "unexpected time %d (!= 0)", t);
    t = time(NULL);
    if ((rv = tai_import(tm, TAI_TYPE_TIMET, t)) != TAI_OK)
        ts_test_fail(TS_CTX, "tai_import: rv=%d", rv);
    if ((rv = tai_export(tm, TAI_TYPE_TIMET, &t2)) != TAI_OK)
        ts_test_fail(TS_CTX, "tai_export: rv=%d", rv);
    if (t != t2)
        ts_test_fail(TS_CTX, "unexpected time %d (!= %d)", t2, t);
    tai_destroy(tm);
}

TS_TEST(test_parsing)
{
    tai_t *tm;
    tai_rc_t rv;
    char out[32];
    int i;
    struct {
        char *date;
        char *fmt;
    } table[] = {
        { "2000-02-22", "%Y-%m-%d" },
        { "22-02-2000", "%d-%m-%Y" },
        { "22-Feb-2000", "%d-%b-%Y" },
        { "29-Feb-2000", "%d-%b-%Y" },
        { "31-Feb-2000", "%d-%b-%Y" },
        { NULL, NULL }
    };

    ts_test_check(TS_CTX, "time parsing");
    tai_create(&tm);
    for (i = 0; table[i].date != NULL; i++) {
        ts_test_log(TS_CTX, "date=%s, fmt=%s", table[i].date, table[i].fmt);
        if ((rv = tai_parse(tm, table[i].date, strlen(table[i].date), table[i].fmt)) != TAI_OK) 
            ts_test_fail(TS_CTX, "#%d: tai_parse(\"%s\"): rv=%d", i, table[i].date, rv);
        else {
            if ((rv = tai_format(tm, out, sizeof(out), table[i].fmt)) != TAI_OK) 
                ts_test_fail(TS_CTX, "#%d: tai_format(\"%s\"): rv=%d", i, table[i].date, rv);
            if (strcmp(table[i].date, out) != 0)
                ts_test_fail(TS_CTX, "#%d: output \"%s\", expected \"%s\" (input)", i, out, table[i].date);
        }
    }
    tai_destroy(tm);
}

TS_TEST(test_comparing)
{
    tai_rc_t rv;
    tai_t *tm1, *tm2;
    int i;
    struct {
        char *date1;
        char *date2;
        int   op;
        int   exp;
    } table[] = {
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:31 +0200", TAI_OP_NE, TAI_OK    }, /* 00 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:30 +0200", TAI_OP_NE, TAI_FALSE }, /* 01 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:30 +0200", TAI_OP_EQ, TAI_OK    }, /* 02 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:31 +0200", TAI_OP_EQ, TAI_FALSE }, /* 03 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:20 +0200", TAI_OP_LT, TAI_OK    }, /* 04 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:30 +0200", TAI_OP_LT, TAI_FALSE }, /* 05 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:20 +0200", TAI_OP_LE, TAI_OK    }, /* 06 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:30 +0200", TAI_OP_LE, TAI_OK    }, /* 07 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:31 +0200", TAI_OP_LE, TAI_FALSE }, /* 08 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:31 +0200", TAI_OP_GT, TAI_OK    }, /* 09 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:30 +0200", TAI_OP_GT, TAI_FALSE }, /* 10 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:31 +0200", TAI_OP_GE, TAI_OK    }, /* 11 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:30 +0200", TAI_OP_GE, TAI_OK    }, /* 12 */
        { "2000-02-22 10:20:30 +0200", "2000-02-22 10:20:20 +0200", TAI_OP_GE, TAI_FALSE }, /* 13 */
        { NULL, NULL, 0, 0 }
    };

    tai_create(&tm1);
    tai_create(&tm2);
    ts_test_check(TS_CTX, "time comparing");
    for (i = 0; table[i].date1 != NULL; i++) {
        ts_test_log(TS_CTX, "date1=%s, date2=%s, op=%d", table[i].date1, table[i].date2, table[i].op);
        tai_parse(tm1, table[i].date1, strlen(table[i].date1), "%Y-%m-%d %H:%M:%S %z");
        tai_parse(tm2, table[i].date2, strlen(table[i].date2), "%Y-%m-%d %H:%M:%S %z");
        if ((rv = tai_op(tm1, table[i].op, tm2)) != table[i].exp)
            ts_test_fail(TS_CTX, "#%d: output \"%d\", expected \"%d\"", i, rv, table[i].exp);
    }
    tai_destroy(tm2);
    tai_destroy(tm1);
}

int main(int argc, char *argv[])
{
    ts_suite_t *ts;
    int n;

    ts = ts_suite_new("OSSP tai (Time Handling)");
    ts_suite_test(ts, test_calendar,     "calendar calculations");
    ts_suite_test(ts, test_object,       "object handling");
    ts_suite_test(ts, test_importexport, "time import/export");
    ts_suite_test(ts, test_parsing,      "time parsing");
    ts_suite_test(ts, test_comparing,    "time comparing");
    n = ts_suite_run(ts);
    ts_suite_free(ts);
    return n;
}

