/* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
/*======================================================================
Copyright (C) 2004,2005,2009 Walter Doekes <walter+tthsum@wjd.nu>
This file is part of tthsum.

tthsum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

tthsum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with tthsum.  If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "thex.h"

#include "base32.h"
#include "test.h"
#include <string.h>


static int thex_cmp(struct rofile* stream, const char* base32) {
    /* Don't forget to zero out cmpres/tstres */
    uint64_t cmpres[3] = {_ULL(0), _ULL(0), _ULL(0)};
    uint64_t tstres[3] = {_ULL(0), _ULL(0), _ULL(0)};
    char tstbase32[40];
    if (base32touint64(&cmpres[0], base32, 3) == -1)
	FAIL1("base32touint64 returned -1 on %s", base32);
    if (thex_tiger_root(stream, &tstres[0], NULL) == -1)
	FAIL1("thex_tiger_root returned -1 on %s", base32);
    if (uint64tobase32(tstbase32, tstres, 3) == -1)
	FAIL1("uint64tobase32 returned -1 on %s", base32);
    if (memcmp(&cmpres[0], &tstres[0], 3 * sizeof(uint64_t)) != 0) {
	unsigned i;
	char hexbuf[49];
	memset(hexbuf, '.', 48);
	hexbuf[48] = '\0';
	for (i = 0; i < 3 * sizeof(uint64_t); ++i) {
	    char cmphigh = (char)(*(((uint8_t*)&cmpres[0]) + i) >> 4);
	    char cmplow = (char)(*(((uint8_t*)&cmpres[0]) + i) & 0xf);
	    char tsthigh = (char)(*(((uint8_t*)&tstres[0]) + i) >> 4);
	    char tstlow = (char)(*(((uint8_t*)&tstres[0]) + i) & 0xf);
	    if (cmphigh != tsthigh)
		hexbuf[2*i] = tsthigh >= 10 ? 'a' + tsthigh : '0' + tsthigh;
	    if (cmplow != tstlow)
		hexbuf[2*i+1] = tstlow >= 10 ? 'a' + tstlow : '0' + tstlow;
	}
	FAIL3("memcmp: mismatch on %s != %s: %s", base32, tstbase32, hexbuf);
    }
    return 0;
}

static int thex_memcmp(const char* data, unsigned length, const char* base32) {
    int ret;
    struct rofile* stream;
    stream = rofopen_mem(data, length);
    if (stream == NULL)
	FAIL1("rofopen_mem failed on %s", base32);
    ret = thex_cmp(stream, base32);
    rofclose(stream);
    return ret;
}

static int thex_strcmp(const char* str, const char* base32) {
    return thex_memcmp(str, strlen(str), base32);
}

static int test_standard_hashes() {
    char buf[1026];
    int i;
    for (i = 0; i < 1025; ++i)
	buf[i] = 'A';
    buf[1025] = '\0';

    return thex_strcmp("", "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ")
	 + thex_memcmp("\0", 1, "VK54ZIEEVTWNAUI5D5RDFIL37LX2IQNSTAXFKSA")
	 + thex_memcmp(buf, 1024, "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA")
	 + thex_memcmp(buf, 1025, "PZMRYHGY6LTBEH63ZWAHDORHSYTLO4LEFUIKHWY");
}


TESTS(thex_test)
    TEST(test_standard_hashes);
ENDTESTS
