/* * Copyright (c) 2001 by Cliff Green. All rights reserved. Individual files * may be covered by other copyrights (as noted in the file itself). * * Redistribution and use in source and binary forms are permitted * provided that this entire copyright notice is duplicated in all such * copies. * * This software is provided "as is" and without any expressed or implied * warranties, including, without limitation, the implied warranties of * merchantibility and fitness for any particular purpose. */ /* * A portion of this code (testing generic abstract factory template) is * from Jim Hyslop: * Copyright 2001, Jim Hyslop */ //---------------------------------------------------------------------- // Source file: utiltest.cpp // Written by: Cliff Green, 2001 // Compiler: Metrowerks CodeWarrior Pro 6 // History: // Modified: 8/28/2001 // By: Cliff Green // Comments: Significant enhancements to BinaryBuf, BitBuffer, and // GenericFactory. //---------------------------------------------------------------------- // This commentheader supports documentation tools such as Doc++ and // Doxygen: http://www.doxygen.org/ //---------------------------------------------------------------------- /// Unit test harness for utility classes and functions. /** * This file provides a main function to exercise and test various * utility functions and classes. It is meant to be a fairly comprehensive * and exhaustive test, but the current version still needs significantly * more testing code. The current state of this test code is at least a * good start, and can be used as a base to add even more comprehensive * tests. * * Any changes to utility code should use this as a first step regression test. */ #ifdef _MSC_VER #pragma warning(disable:4786) #endif #include "align.h" #include "binarybuf.h" #include "bitbuffer.h" #include "nil.h" #include "strutils.h" #include "factory.h" #include #include #include #include // Classes and functions for testing generic abstract factory code // The class to be stored in the factory template. class Vehicle { public: Vehicle () { std::cout << "In Vehicle ctor" << std::endl; } // A virtual function to illustrate how well this system works. virtual void doSomething() { std::cout << "Hi, I'm a Vehicle method." << std::endl; } virtual ~Vehicle() { } }; class SportsCar : public Vehicle { public: SportsCar() : Vehicle() { std::cout << "In SportsCar ctor" << std::endl; } SportsCar(const std::string& s, unsigned short x) : Vehicle() { std::cout << "In SportsCar ctor with string s: " << s << ", ushort x: " << x << std::endl; } // A virtual function to illustrate how well this system works. virtual void doSomething() { std::cout << "Hi, I'm a SportsCar method\n\tMy parent says: "; Vehicle::doSomething(); } }; class Truck : public Vehicle { public: Truck (const std::string& s) : Vehicle() { std::cout << "In Truck ctor with string s: " << s << std::endl; } // A virtual function to illustrate how well this system works. virtual void doSomething() { std::cout << "Hi, I'm a Truck method\n\tMy parent says: "; Vehicle::doSomething(); } }; typedef Util::GenericFactory VehFactNoParm; typedef Util::GenericFactory VehFactOneParm; typedef Util::GenericFactory VehFactTwoParms; typedef Loki::SingletonHolder VehFactNoParmSing; typedef Loki::SingletonHolder VehFactOneParmSing; typedef Loki::SingletonHolder VehFactTwoParmsSing; namespace { // Note that this highlights one of the dangers of this technique. We have // no control over the order in which various modules will call regCreateFn, // so this technique cannot be safely used if the factory is required // to instantiate an object before main() executes. Util::RegisterInFactory regVeh("Vehicle"); Util::RegisterInFactory regSpCar1("SportsCar"); Util::RegisterInFactory regSpCar2("SportsCar"); Util::RegisterInFactory regTruck(150); } void callVirtFunc(Vehicle& ); void callVirtFunc(Vehicle& v) { v.doSomething(); } template void testBinBuf (Util::BinaryBuf); // note pass by value, for copy ctor testing template void testBinBuf (Util::BinaryBuf a) { typedef typename T::value_type Char; typedef Util::BinaryBuf BinBuf; std::cout << "Max size of a: " << a.max_size() << std::endl; std::cout << "Testing character appending to a." << std::endl; std::cout << "Len of a: "; for (unsigned char i (0); i < 255; ++i) { // careful - "< 256" is a bug for unsigned char a += static_cast(i); std::cout << a.length() << ' '; } std::cout << std::endl; std::cout << "a should have bytes with binary vals from 00 to FE:" << std::endl << a << std::endl; std::cout << "toHex value from a should be same as above:" << std::endl << Util::toHex(a) << std::endl; std::cout << "From hex val:" << std::endl << Util::fromHex(Util::toHex(a)) << std::endl; std::cout << "To and from hex are: " << (Util::fromHex(Util::toHex(a)) == a ? "Equal. " : "Not equal!!") << std::endl; BinBuf tb1, tb2; for (Char i(0); i < 10; ++i) { tb1 += i; tb2 += i; } std::cout << "tb1, tb2: " << tb1 << " " << tb2 << std::endl; BinBuf tb3(tb1 + tb2); std::cout << "Result of buf appends: " << tb3 << std::endl; std::cout << "Result of comparing tb1 and tb2: " << (tb1 == tb2 ? "Equal" : "Not equal!!") << std::endl; Char b [20] = { 10, 11, 12, 13, 14, 15, 16 }; a.assign(b, 7); std::cout << "a after assign is: " << a << std::endl; std::string aaa(Util::toHex(a)); std::cout << "to hex: " << aaa << std::endl; std::cout << "from hex: " << Util::fromHex(aaa) << std::endl; BinBuf xyz(b, 7); BinBuf c(a); std::cout << "c after copy construction from a: " << c << std::endl; std::string testStr("AAAA3"); std::cout << "Testing hex conversion and odd num nibbles, testStr: " << testStr << " After fromHex: " << Util::fromHex(testStr) << std::endl; } template void testBitBuffer (Util::BitBuffer); // note pass by value, for copy ctor testing template void testBitBuffer (Util::BitBuffer a) { a.appendBit (true); a.appendBit(false); a.appendBit(true); unsigned int zz (13572468); a.appendVal(zz, 32); unsigned short tt (7); a.appendVal(tt, 3); std::cout << "Bit buf: " << a.getBinaryBuf() << " num bits: " << a.size() << std::endl; unsigned char first3 (a.template getVal(0, 3)); unsigned int next32 (a.template getVal(3, 32)); unsigned short next3 (a.template getVal(35, 3)); std::cout << "Extracting vals, first 3: " << static_cast(first3) << (first3 == 5 ? " Worked" : " Failed!") << " next 32: " << next32 << (next32 == 13572468 ? " Worked" : " Failed!") << " next 3: " << next3 << (next3 == 7 ? " Worked" : " Failed!") << std::endl; std::cout << "Testing exception handling in BitBuffer code" << std::endl; std::cout << "Trying to extract short val off end - should throw" << std::endl; try { unsigned short st (a.template getVal(34, 5)); } catch (const std::exception& err) { std::cout << "Caught Util err: " << err.what() << std::endl; } std::cout << "Trying to extract buf past end - should throw" << std::endl; try { U tt(a.getBinaryBuf(1, 38)); } catch (const std::exception& err) { std::cout << "Caught Util err: " << err.what() << std::endl; } typedef typename U::value_type CharType; U bb; bb += CharType(10); bb += CharType(11); bb += CharType(12); Util::BitBuffer a2(bb, 24); std::cout << "Bit buf: " << a2.getBinaryBuf() << " should be equal to: " << bb << (bb == a2.getBinaryBuf() ? " true" : " false!") << std::endl; std::cout << "Extracting one byte at a time: " << a2.getBinaryBuf(0,8) << ' ' << a2.getBinaryBuf(8,8) << ' ' << a2.getBinaryBuf(16,8) << std::endl; a2.appendBinaryBuf(bb, 8); std::cout << "Appending first byte: " << a2.getBinaryBuf() << std::endl; a2.setBit(true, 0); a2.setBit(true, 1); std::cout << "Setting first and second bit on: " << a2.getBinaryBuf() << "\n\n" << std::endl; } int main() { try { std::cout << "\n---Testing nil function" << std::endl; { int a; int* t (Util::nil(a)); std::cout << "Value returned from nil fct: " << t << std::endl; } std::cout << "\n---Testing binary buf class / utilities" << std::endl; { // Util::BinaryBuf > tt2; // test with non-default wide char types Util::BinaryBuf<> t1; testBinBuf(t1); Util::BinaryBuf t2; testBinBuf(t2); } std::cout << "\n---Testing alignment templates" << std::endl; { unsigned int aa (0xaabbccdd); // assume 4 byte ints unsigned int bb (0xddccbbaa); std::cout << "4 byte swap: " << (Util::swap4bytes(aa) == bb ? "Worked. " : "Failed!!") << std::endl; } { unsigned short aa (0xefab); // assume 2 byte shorts unsigned short bb (0xabef); std::cout << "2 byte swap: " << (Util::swap2bytes(aa) == bb ? "Worked. " : "Failed!!") << std::endl; } { unsigned char b[5] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; unsigned int t = Util::align4bytes (b + 1); // the following logic is different depending on the endian ordering of the processor std::cout << "4 byte align, offset 1: " << (t == 0xeeddccbb ? "Worked. " : "Failed!!") << std::endl; unsigned short u = Util::align2bytes (b + 2); std::cout << "2 byte align, offset 2: " << (u == 0xddcc ? "Worked. " : "Failed!!") << std::endl; } std::cout << "\n---Testing bit buffer class / utilities" << std::endl; { Util::BitBuffer<> t1; testBitBuffer(t1); Util::BitBuffer, Util::BinaryBuf<> > t2; testBitBuffer(t2); Util::BitBuffer, Util::BinBufUnChar> t3; testBitBuffer(t3); // Util::BitBuffer, std::string> t4; // works same, doesn't display as well // testBitBuffer(t4); } std::cout << "\n--- Testing string conversion template" << std::endl; { int a (53); std::cout << "a as str: " << Util::toStr(a) << std::endl; short b (5001); std::cout << "b as str: " << Util::toStr(b) << std::endl; std::cout << "a and b concatenated: " << (Util::toStr(a) + Util::toStr(b)) << std::endl; } std::cout << "\n--- Testing generic (templatized) abstract factory" << std::endl; { std::auto_ptr newVeh = VehFactNoParmSing::Instance().create("Vehicle"); std::auto_ptr newSpCar1 = VehFactNoParmSing::Instance().create("SportsCar"); std::auto_ptr newSpCar2 = VehFactTwoParmsSing::Instance().create("SportsCar", "Red", 220); std::auto_ptr newTruck = VehFactOneParmSing::Instance().create(150, "Big Lights"); callVirtFunc(*newVeh); callVirtFunc(*newSpCar1); callVirtFunc(*newSpCar2); callVirtFunc(*newTruck); } } catch (const std::exception& err) { std::cout << "Std exception caught: " << err.what() << std::endl; } return 0; }