/***************************************************************************
 *   Copyright (C) 2010 by Joris Guisson                                   *
 *   joris.guisson@gmail.com                                               *
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
 ***************************************************************************/

#include <QtTest>
#include <QLocale>
#include <util/log.h>
#include <util/functions.h>
#include <torrent/torrentcontrol.h>
#include <diskio/chunkmanager.h>
#include <diskio/piecedata.h>
#include <testlib/utils.h>
#include <testlib/dummytorrentcreator.h>
#include <util/sha1hashgen.h>
#include <util/signalcatcher.h>
#include <util/fileops.h>


using namespace bt;

const bt::Uint64 TEST_FILE_SIZE = 15*1024*1024;



class ChunkManagerTest : public QObject
{
	Q_OBJECT
	
private Q_SLOTS:
	void initTestCase()
	{
		QLocale::setDefault(QLocale("main"));
		bt::InitLibKTorrent();
		bt::InitLog("chunkmanagertest.log",false,true);
		QMap<QString,bt::Uint64> files;
		
		files["aaa.avi"] = RandomSize(TEST_FILE_SIZE / 2,TEST_FILE_SIZE);
		files["bbb.avi"] = RandomSize(TEST_FILE_SIZE / 2,TEST_FILE_SIZE);
		files["ccc.avi"] = RandomSize(TEST_FILE_SIZE / 2,TEST_FILE_SIZE);
		
		
		QVERIFY(creator.createMultiFileTorrent(files,"movies"));
		
		Out(SYS_GEN|LOG_DEBUG) << "Created " << creator.torrentPath() << endl;
		try
		{
			tor.load(bt::LoadFile(creator.torrentPath()),false);
		}
		catch (bt::Error & err)
		{
			Out(SYS_GEN|LOG_DEBUG) << "Failed to load torrent: " << creator.torrentPath() << endl;
			QFAIL("Torrent load failure");
		}
	}
	
	void cleanupTestCase()
	{
	}
	
	void testPieceDataLoading() 
	{
		ChunkManager cman(tor,creator.tempPath(),creator.dataPath(),true,0);
		Chunk* c = cman.getChunk(0);
		QVERIFY(c);
			
		try
		{
			PieceData::Ptr ptr = c->getPiece(0,MAX_PIECE_LEN,true);
			QVERIFY(ptr && ptr->data() && ptr->inUse());
			
			PieceData::Ptr f = c->getPiece(0,c->getSize(),true);
			QVERIFY(f);
			
			f = PieceData::Ptr();
			QVERIFY(!f);
			
			cman.checkMemoryUsage();
			Uint8 tmp[20];
			QVERIFY(memcpy(tmp,ptr->data(),20));
			
			memset(tmp,0xFF,20);
			QVERIFY(!ptr->writeable());
			ptr->write(tmp,20);
			QFAIL("No exception thrown");
		}
		catch (bt::Error & err)
		{
		}
	}
	
#ifndef Q_CC_MSVC
	void testBusErrorHandling()
	{
		ChunkManager cman(tor,creator.tempPath(),creator.dataPath(),true,0);
		Chunk* c = cman.getChunk(0);
		QVERIFY(c);
		
		PieceData::Ptr f = c->getPiece(0,c->getSize(),false);
		QVERIFY(f);
		QVERIFY(f->writeable());
		
		try
		{
			QString path = creator.dataPath() + tor.getFile(0).getPath();
			bt::TruncateFile(path,0);
			
			Uint8 tmp[20];
			memset(tmp,0xFF,20);
			
			f->write(tmp,20);
			QFAIL("No BusError thrown\n");
		}
		catch (bt::BusError & err)
		{
		}
		catch (bt::Error & err)
		{
			QFAIL("Truncate failed\n");
		}
	}
	
#endif
	
	
private:
	DummyTorrentCreator creator;
	bt::Torrent tor;
};


QTEST_MAIN(ChunkManagerTest)

#include "chunkmanagertest.moc"
