os/kernelhwsrv/kerneltest/e32test/misc/t_bytepair.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/misc/t_bytepair.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,289 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32test\misc\t_bytepair.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#define __E32TEST_EXTENSION__
    1.22 +#include <e32test.h>
    1.23 +#include <e32math.h>
    1.24 +#include <e32rom.h>
    1.25 +#include <e32svr.h>
    1.26 +#include "decompress.h"
    1.27 +
    1.28 +#define BYTE_PAIR_COMPRESS_INCLUDE_IMPLEMENTATION
    1.29 +#include <byte_pair_compress.h>
    1.30 +
    1.31 +const TInt KMaxSize = 0x1000;
    1.32 +const TInt KPageSize = 0x1000;
    1.33 +
    1.34 +RTest test(_L("T_BYTEPAIR"));
    1.35 +TUint8 InputBuffer[KMaxSize];
    1.36 +TUint8 CompressedBuffer[4*KMaxSize];
    1.37 +TUint8 OutputBuffer[KMaxSize+1];
    1.38 +TRomHeader* RomHeader = NULL;
    1.39 +TInt RomOffset = 0;
    1.40 +TInt FailCount = 0;
    1.41 +TUint32 RandomState;
    1.42 +
    1.43 +void PrintHex(TUint8* aBuffer, TInt aSize)
    1.44 +	{
    1.45 +	const TInt KBytesPerLine = 38;
    1.46 +	TBuf<KBytesPerLine * 2 + 3> buf;
    1.47 +	for (TInt i = 0 ; i < aSize ; )
    1.48 +		{
    1.49 +		buf.Zero();
    1.50 +		buf.Append(_L("  "));
    1.51 +		TInt nextChunk = Min(aSize - i, KBytesPerLine);
    1.52 +		for (TInt j = 0 ; j < nextChunk ; ++j, ++i)
    1.53 +			buf.AppendFormat(_L("%02x"), aBuffer[i]);
    1.54 +		buf.Append(_L("\n"));
    1.55 +		RDebug::RawPrint(buf);
    1.56 +		}
    1.57 +	}
    1.58 +
    1.59 +TUint32 Random()
    1.60 +	{
    1.61 +	RandomState = RandomState * 69069 + 1;
    1.62 +	return RandomState;
    1.63 +	}
    1.64 +
    1.65 +typedef void (*TGenerator)(TUint8* aDest, TInt aSize);
    1.66 +
    1.67 +void GenerateUniform(TUint8* aDest, TInt aSize)
    1.68 +	{
    1.69 +	TInt value = aSize & 255;
    1.70 +	Mem::Fill(aDest, aSize, value);
    1.71 +	}
    1.72 +
    1.73 +void GenerateUniformRandom(TUint8* aDest, TInt aSize)
    1.74 +	{
    1.75 +	for (TInt i = 0 ; i < aSize ; ++i)
    1.76 +		aDest[i] = TUint8(Random());
    1.77 +	}
    1.78 +
    1.79 +void GenerateZipfRandom(TUint8* aDest, TInt aSize)
    1.80 +	{
    1.81 +	// Some details from http://www.cs.hut.fi/Opinnot/T-106.4000/K2007/Ohjeet/Zipf.html
    1.82 +	const TInt max = 255;
    1.83 +	TReal c;
    1.84 +	test_KErrNone(Math::Log(c, max + 1.0));
    1.85 +	for (TInt i = 0 ; i < aSize ; ++i)
    1.86 +		{
    1.87 +		int r;
    1.88 +		do
    1.89 +			{
    1.90 +			TReal x = Random() / TReal(KMaxTUint32);
    1.91 +			test_KErrNone(Math::Exp(x, x * c));
    1.92 +			r = (int)x - 1;
    1.93 +			}
    1.94 +		while (r > max);
    1.95 +		aDest[i] = TUint8(r);
    1.96 +		}
    1.97 +	}
    1.98 +
    1.99 +void GenerateRomPage(TUint8* aDest, TInt aSize)
   1.100 +	{
   1.101 +	if (TUint(RomOffset + aSize) > RomHeader->iUncompressedSize)
   1.102 +		RomOffset = 0;
   1.103 +	Mem::Copy(aDest, ((TUint8*)RomHeader) + RomOffset, aSize);
   1.104 +	RomOffset += KPageSize;
   1.105 +	}
   1.106 +
   1.107 +enum TTestMode
   1.108 +	{
   1.109 +	ENormal,
   1.110 +	EOutputBufferTooLong,
   1.111 +	EOutputBufferTooShort,
   1.112 +	ETruncatedCompressedData,
   1.113 +	ECorruptCompressedData,
   1.114 +	ERandomCompressedData
   1.115 +	};
   1.116 +
   1.117 +void TestCompressDecompress(TGenerator aGenFunc, TInt aSize, TTestMode aMode = ENormal)
   1.118 +	{
   1.119 +	ASSERT(aSize <= KMaxSize);
   1.120 +	
   1.121 +	TInt compressedSize;
   1.122 +	if (aMode != ERandomCompressedData)
   1.123 +		{
   1.124 +		// Prepare intput data
   1.125 +		aGenFunc(InputBuffer, aSize);
   1.126 +	
   1.127 +		// Compress input data
   1.128 +		compressedSize = BytePairCompress(CompressedBuffer, InputBuffer, aSize);
   1.129 +		ASSERT(compressedSize <= KMaxSize+1);
   1.130 +		}
   1.131 +	else
   1.132 +		{
   1.133 +		// Generate random compressed data
   1.134 +		compressedSize = aSize;
   1.135 +		GenerateUniformRandom(CompressedBuffer, compressedSize);
   1.136 +		}
   1.137 +
   1.138 +	if (aMode == ETruncatedCompressedData)
   1.139 +		{
   1.140 +		// Truncate compressed data by up to half its length
   1.141 +		compressedSize -= Math::Random() % (compressedSize / 2);
   1.142 +		}
   1.143 +	else if (aMode == ECorruptCompressedData)
   1.144 +		{
   1.145 +		// Corrupt a random byte of the compressed data
   1.146 +		TInt pos = Random() % compressedSize;
   1.147 +		CompressedBuffer[pos] = TUint8(Random());
   1.148 +		}
   1.149 +	
   1.150 +	// Decomress compressed data
   1.151 +	Mem::Fill(OutputBuffer, KMaxSize+1, 0);
   1.152 +	TUint8* srcNext = NULL;
   1.153 +	TInt outputBufferSize = aSize;
   1.154 +	if (aMode == EOutputBufferTooLong || aMode == ERandomCompressedData)
   1.155 +		outputBufferSize = KMaxSize+1;
   1.156 +	else if (aMode == EOutputBufferTooShort)
   1.157 +		outputBufferSize = aSize / 2 + 1;
   1.158 +	TInt decompressedSize = BytePairDecompress(OutputBuffer, outputBufferSize, CompressedBuffer, compressedSize, srcNext);
   1.159 +	TInt srcUsed = srcNext ? srcNext - CompressedBuffer : 0;
   1.160 +
   1.161 +	// Print stats
   1.162 +	RDebug::Printf("%d -> %d -> %d, %d, %d", aSize, compressedSize, outputBufferSize, srcUsed, decompressedSize);
   1.163 +	
   1.164 +	TBool ok = ETrue;
   1.165 +
   1.166 +	// Check decompressed data not larger than output buffer
   1.167 +	if (decompressedSize > outputBufferSize)
   1.168 +		ok = EFalse;
   1.169 +	
   1.170 +	// Check output buffer not written beyond what was reported
   1.171 +	if (decompressedSize >= 0 && OutputBuffer[decompressedSize] != 0)
   1.172 +		ok = EFalse;
   1.173 +
   1.174 +	if (aMode == ETruncatedCompressedData || aMode == ECorruptCompressedData || aMode == ERandomCompressedData)
   1.175 +		{
   1.176 +		// Input corrupt, expect error or partial sucess
   1.177 +		
   1.178 +		// If there was an error, check it was KErrCorrupt and srcNext was set to NULL
   1.179 +		if (decompressedSize < 0 && (decompressedSize != KErrCorrupt || srcNext != NULL))
   1.180 +			ok = EFalse;	
   1.181 +		}
   1.182 +	else if (aMode == EOutputBufferTooShort)
   1.183 +		{
   1.184 +		// Input consistent, output buffer too short
   1.185 +
   1.186 +		// Expect error, or initial part correctly decompressed
   1.187 +		if (decompressedSize < 0)
   1.188 +			{
   1.189 +			if (decompressedSize != KErrCorrupt || srcNext != NULL)
   1.190 +				ok = EFalse;
   1.191 +			}
   1.192 +		else
   1.193 +			{
   1.194 +			if (decompressedSize > aSize  ||
   1.195 +				srcUsed > compressedSize ||
   1.196 +				Mem::Compare(InputBuffer, decompressedSize, OutputBuffer, decompressedSize) != 0)
   1.197 +				ok = EFalse;
   1.198 +			}
   1.199 +		}
   1.200 +	else
   1.201 +		{
   1.202 +		// Input consistent, expect success
   1.203 +
   1.204 +		// Check no error, correct size, all compressed input used, and output same as orignal data
   1.205 +		if (decompressedSize < 0 ||
   1.206 +			aSize != decompressedSize ||
   1.207 +			srcUsed != compressedSize ||
   1.208 +			Mem::Compare(InputBuffer, decompressedSize, OutputBuffer, decompressedSize) != 0)
   1.209 +			ok = EFalse;		
   1.210 +		}
   1.211 +
   1.212 +	if (!ok)
   1.213 +		{
   1.214 +		RDebug::Printf("Failure:");
   1.215 +		RDebug::Printf("Input");
   1.216 +		PrintHex(InputBuffer, aSize);
   1.217 +		RDebug::Printf("Compressed");
   1.218 +		PrintHex(CompressedBuffer, compressedSize);
   1.219 +		RDebug::Printf("Output");
   1.220 +		PrintHex(OutputBuffer, decompressedSize);
   1.221 +		++FailCount;
   1.222 +		}
   1.223 +	}
   1.224 +
   1.225 +TInt E32Main()
   1.226 +//
   1.227 +// Benchmark for Mem functions
   1.228 +//
   1.229 +    {
   1.230 +	TInt i;
   1.231 +    test.Title();
   1.232 +    test.Start(_L("T_BYTEPAIR"));
   1.233 +
   1.234 +	RandomState = User::FastCounter();
   1.235 +	RDebug::Printf("RandomState == %08x", RandomState);
   1.236 +	
   1.237 +	test_Equal(0, FailCount);
   1.238 +
   1.239 +	const TInt KStartSize = KMaxSize / 2;
   1.240 +
   1.241 +	// Test correct operation
   1.242 +
   1.243 +	test.Next(_L("Test compressing uniform data"));	
   1.244 +	for (i = KStartSize ; i < KMaxSize ; i += 19)
   1.245 +		TestCompressDecompress(GenerateUniform, i);
   1.246 +
   1.247 +	test.Next(_L("Test compressing uniformly distributed random data"));				
   1.248 +	for (i = KStartSize + 2 ; i < KMaxSize ; i += 19)
   1.249 +		TestCompressDecompress(GenerateUniformRandom, i);
   1.250 +	
   1.251 +	test.Next(_L("Test compressing zipf-distributed random data"));				
   1.252 +	for (i = KStartSize + 3 ; i < KMaxSize ; i += 19)
   1.253 +		TestCompressDecompress(GenerateZipfRandom, i);
   1.254 +	
   1.255 +#ifdef __EPOC32__
   1.256 +	RomHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
   1.257 +	TGenerator pageGen = GenerateRomPage;
   1.258 +#else
   1.259 +	TGenerator pageGen = GenerateZipfRandom;
   1.260 +#endif
   1.261 +	
   1.262 +	test.Next(_L("Test compressing pages"));				
   1.263 +	for (i = 0 ; i < 100 ; ++i)
   1.264 +		TestCompressDecompress(pageGen, KPageSize);
   1.265 +
   1.266 +	// Test failure modes
   1.267 +
   1.268 +	test.Next(_L("Test output buffer too short"));				
   1.269 +	for (i = KStartSize ; i < KMaxSize ; i += 19)
   1.270 +		TestCompressDecompress(pageGen, i, EOutputBufferTooShort);
   1.271 +
   1.272 +	test.Next(_L("Test output buffer too long"));				
   1.273 +	for (i = KStartSize + 1 ; i < KMaxSize ; i += 19)
   1.274 +		TestCompressDecompress(pageGen, i, EOutputBufferTooLong);
   1.275 +	
   1.276 +	test.Next(_L("Test truncated compressed data"));				
   1.277 +	for (i = KStartSize + 2 ; i < KMaxSize ; i += 19)
   1.278 +		TestCompressDecompress(pageGen, i, ETruncatedCompressedData);
   1.279 +	
   1.280 +	test.Next(_L("Test corrupt compressed data "));				
   1.281 +	for (i = KStartSize + 3 ; i < KMaxSize ; i += 19)
   1.282 +		TestCompressDecompress(pageGen, i, ECorruptCompressedData);
   1.283 +	
   1.284 +	test.Next(_L("Test random compressed data"));				
   1.285 +	for (i = KStartSize + 4 ; i < KMaxSize ; i += 19)
   1.286 +		TestCompressDecompress(GenerateUniformRandom, i, ERandomCompressedData);
   1.287 +
   1.288 +	test_Equal(0, FailCount);
   1.289 +	
   1.290 +    test.End();
   1.291 +	return(KErrNone);
   1.292 +    }