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 + }