/***************************************************************************
              tth-test.cpp  -  Test a TTH calculated is correct
                             -------------------
    begin                : Thu Sep 11 2008
    copyright            : (C) 2008 by Edward Sheldrake
    email                : ejs1920@yahoo.co.uk
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <dclib/core/cstring.h>
#include <dclib/core/cbytearray.h>
#include <dclib/core/cfile.h>
#include <dclib/cfilehasher.h>
#include <dclib/core/cbase32.h>

#include <stdio.h>

int main( int /* argc */, char* [] /* argv */ )
{
	/* create test data */
	
	/* 2 of the published test vectors */
	CByteArray tv1(1024);
	for ( unsigned long i = 0; i < tv1.Size(); ++i )
	{
		tv1.Data()[i] = 'A';
	}
	
	CByteArray tv2(1025);
	for ( unsigned long i = 0; i < tv2.Size(); ++i )
	{
		tv2.Data()[i] = 'A';
	}
	
	CByteArray * res = CFileHasher::HashByteArray( &tv1, tv1.Size() );
	CString v;
	CBase32::Encode( &v, res );
	delete res;
	if ( v != "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA" )
	{
		printf("tth-test: wrong tth %s calculated for test vector 1\n",v.Data());
		return 10;
	}
	
	res = CFileHasher::HashByteArray( &tv2, tv2.Size() );
	CBase32::Encode( &v, res );
	delete res;
	if ( v != "PZMRYHGY6LTBEH63ZWAHDORHSYTLO4LEFUIKHWY" )
	{
		printf("tth-test: wrong tth %s calculated for test vector 2\n",v.Data());
		return 20;
	}
	
	CByteArray buffer(50*1024*1024);
	
	unsigned char c = 'a';
	for ( unsigned long i = 0; i < buffer.Size(); ++i )
	{
		if ( i%26 == 0 )
		{
			c = 'a';
		}
		buffer.Data()[i] = c;
		++c;
	}
	
	res = CFileHasher::HashByteArray( &buffer, buffer.Size() );
	CBase32::Encode( &v, res );
	delete res;
	res = 0;
	if ( v != "B4OKDH3FH3JZJJBNN4OLNTCHW7TK7G2O6IG2JHQ" )
	{
		printf("tth-test: wrong tth %s calculated for test file data\n",v.Data());
		return 30;
	}
	
	if ( buffer.SaveToFile("testdata.bin") == false )
	{
		printf("tth-test: cannot create testdata.bin file\n");
		return 1;
	}
	
	CFileHasher hasher("testdata.bin");
	hasher.ComputeHash();
	int ret = 100;
	if ( hasher.GetStatus() != efhsFinished )
	{
		printf("tth-test: error during hashing\n");
		ret = 2;
	}
	
	if ( hasher.GetHashRoot() == "B4OKDH3FH3JZJJBNN4OLNTCHW7TK7G2O6IG2JHQ" )
	{
		CByteArray * leaves = hasher.GetLeafData();
		if ( leaves && leaves->Size() > 0 )
		{
			if ( CFileHasher::ValidateHashLeaves( hasher.GetHashRoot(), leaves, buffer.Size() ) )
			{
				/* change leaf data */
				unsigned char c = leaves->Data()[0];
				if ( c == 0 )
				{
					c = 1;
				}
				else
				{
					c--;
				}
				
				leaves->Data()[0] = c;
				
				if ( CFileHasher::ValidateHashLeaves( hasher.GetHashRoot(), leaves, buffer.Size() ) == false )
				{
					ret = 0;
				}
				else
				{
					printf("tth-test: modified leaves passed validation!\n");
					ret = 6;
				}
			}
			else
			{
				printf("tth-test: leaves failed validation!\n");
				ret = 5;
			}
		}
		else
		{
			printf("tth-test: no leaves generated!\n");
			ret = 4;
		}
		
		if ( leaves )
		{
			delete leaves;
			leaves = 0;
		}
	}
	else
	{
		printf("tth-test: incorrect tth %s calculated!\n",hasher.GetHashRoot().Data());
		ret = 3;
	}
	
	CFile::UnLink("testdata.bin");
	
	return ret;
}
