
#include <iwear/hash.h>
#include <iwear/utility.h>
#include <iostream>

using namespace std;
using namespace iwear;

#define P_SIZEOF(x) cout << ANSI_BROWN << "sizeof" << ANSI_NORMAL << "(" << ANSI_GREEN << ""#x << ANSI_NORMAL << ") = " << ANSI_BLUE << sizeof(x) << ANSI_NORMAL << endl;

template<class H, class HC> 
void test_hash( H& h, HC& hc, const string& s )
{
    cout << "Testing " << typenameof(h) << endl;
    P_SIZEOF(hc);
    h.From(s);
    hc = h.getHashcode();
}

template<class HC>
void test_result( HC& hc1, HC& hc2 )
{
    cout << "HC1 = " << hc1.asHex() << endl;
    cout << "HC2 = " << hc2.asHex() << endl;

    if ( hc1 != hc2 )
    {
	cout << "Don't mach" << endl;
    }
    if ( hc1 != hc1 )
    {
	cout << "Same dont mach" << endl;
    }
    if ( hc1 == hc1 )
    {
	cout << "Same match" << endl;
    }
}

void do_test( )
{
    string test1("Hello World");
    string test2("Hello World\n");

    MD5Hash md5;
    MD5HashCode HC51;
    MD5HashCode HC52;
    test_hash(md5,HC51,test1);
    test_hash(md5,HC52,test2);
    test_result(HC51,HC52);

    MD2Hash md2;
    MD2HashCode HC21;
    MD2HashCode HC22;
    test_hash(md2,HC21,test1);
    test_hash(md2,HC22,test2);
    test_result(HC21,HC22);

    MD4Hash md4;
    MD4HashCode HC41;
    MD4HashCode HC42;
    test_hash(md4,HC41,test1);
    test_hash(md4,HC42,test2);
    test_result(HC41,HC42);

    SHAHash sha;
    SHAHashCode SHA1;
    SHAHashCode SHA2;
    test_hash(sha,SHA1,test1);
    test_hash(sha,SHA2,test2);
    test_result(SHA1,SHA2);

    SHA1Hash sha1;
    SHA1HashCode SHA11;
    SHA1HashCode SHA12;
    test_hash(sha1,SHA11,test1);
    test_hash(sha1,SHA12,test2);
    test_result(SHA11,SHA12);

    RipeMD160Hash ripe;
    RipeMD160HashCode RIPE1;
    RipeMD160HashCode RIPE2;
    test_hash(ripe,RIPE1,test1);
    test_hash(ripe,RIPE2,test2);
    test_result(RIPE1,RIPE2);

#ifndef OPENSSL_NO_MDC2
    MDC2Hash mdc;
    MDC2HashCode MDC1;
    MDC2HashCode MDC2;
    test_hash(mdc,MDC1,test1);
    test_hash(mdc,MDC2,test2);
    test_result(MDC1,MDC2);
#endif
}

int main ( void )
{
    std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
    enable_verbose_crash();

    try {
    do_test();
    }
    catch( const exception& e )
    {
	cout <<e << endl;
    }

    return 0;
}
