bluetooth/btsdp/test/tsdpdb.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btsdp/test/tsdpdb.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,2006 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// SDP Database library test code
+// 
+//
+
+
+#include <e32test.h>
+#include <f32file.h>
+#include <e32math.h>
+#include <btsdp.h>
+#include <e32def.h>
+#include <e32const.h>
+#include <e32std.h>
+#include "listener.h"
+#include "reqhandler.h"
+#include "SDPDatabase.h"
+#include "protocolmanl.h"
+#include "MAttributeVisitor.h"
+#include "ServiceSearchVisitor.h"
+#include "DataEncoder.h"
+#include "ExtractorVisitor.h"
+#include "EncoderVisitor.h"
+#include "responsesizevisitor.h"
+#include "debug.h"
+//#ifdef __EPOC32__
+#include <c32comm.h>
+//#endif
+
+GLDEF_D RTest test(_L("SDP database DLL tests"));
+
+#if defined (__WINS__)
+#define PDD_NAME _L("ECDRV")
+#define LDD_NAME _L("ECOMM")
+#else  // __GCC32__
+#define PDD_NAME _L("EUART1")
+#define LDD_NAME _L("ECOMM")
+// #define ETNA_PDD_NAME _L("EUART2") // for debugging over com2
+#endif
+
+CSdpDatabase *BuildDbL();
+CSdpDatabase *BuildUpf4DbL();
+CSdpDatabase* BuildContinuationDbL();
+CSdpDatabase* BuildNestedListDbL();
+CSdpDatabase* BuildPrequalDbL();
+// in Builddb.cpp
+
+void LoadLDD_PDD()
+	{
+	TInt r;
+//#ifdef __EPOC32__
+	r=StartC32();
+	if (r!=KErrNone && r!=KErrAlreadyExists)
+		{
+		test.Printf(_L("Failed %d!\n\r"),r);
+		test(r==KErrNone);
+		}
+	else
+		test.Printf(_L("Started C32\n"));
+//#endif
+	test.Printf(_L("Loading PDD\n"));
+	r=User::LoadPhysicalDevice(PDD_NAME);
+	if (r!=KErrNone && r!=KErrAlreadyExists)
+		{
+		test.Printf(_L("Failed %d!\n\r"),r);
+		test(r==KErrNone);
+		}
+	else 
+		test.Printf(_L("Loaded PDD\n"));
+	test.Printf(_L("Loading LDD\n"));
+	r=User::LoadLogicalDevice(LDD_NAME);
+	if (r!=KErrNone && r!=KErrAlreadyExists)
+		{
+		test.Printf(_L("Failed %d!\n\r"),r);
+		test(r==KErrNone);
+		}
+	else
+		test.Printf(_L("Loaded LDD\n"));
+	}
+
+// plagiarised from tsdp.cpp
+// actually Mel can't cast from Shortest form (TPtrC8) to a TDesC8 without this call
+void HexDes(const TDesC8& aDes)
+	{
+	for (TInt i = 0; i < aDes.Length(); ++i)
+		test.Printf(_L("%02x"), aDes[i]);
+	}
+
+class CAttrPrintVisitor : public CBase, public MAttributeVisitor
+	{
+public:
+	CAttrPrintVisitor(CConsoleBase& aConsole) : iConsole(aConsole) {iIndent=0;}
+	~CAttrPrintVisitor() {/*iConsole.Getch();*/}
+    void VisitAttributeL(CSdpAttr &aAttribute)
+		{
+		Indent();
+		test.Printf(_L("\nID:0x%x:"), aAttribute.AttributeID());
+		}
+	void VisitAttributeValueL(CSdpAttrValue & aValue, TSdpElementType aType)
+		{
+// FIXME need a new object like the match list that will just store the object in
+// FIXME an array, or perhaps just print it ? Is it a visitor ?
+//		CSdpSearchPattern* encAttrList = new (ELeave) CSdpSearchPattern;
+//		CleanupStack::PushL(encAttrList);
+
+//		CElementParser* parser = CElementParser::NewL(encAttrList);
+//		CleanupStack::PushL(parser);
+
+//		TInt rem;
+
+		TBuf16<64> iString;
+//		TInt iFound;
+		switch (aType)
+			{
+			case ETypeString:
+				iString.Copy(aValue.Des());
+				test.Printf(_L("\"%S\""),&iString);
+				break;
+			case ETypeDES:
+				test.Printf(_L(" DES"));
+				break;
+			case ETypeUint:
+				test.Printf(_L(" UInt:0x%x"), aValue.Uint());
+				break;
+			case ETypeUUID:
+				test.Printf(_L(" UUID:0x"));
+				HexDes(aValue.UUID().ShortestForm());
+				break;
+			case ETypeEncoded:
+				HexDes(aValue.Des());  // simplest
+//parse out the elements in this encoded attribute
+//				rem = parser->ParseElementsL(aValue.Des());
+//				CleanupStack::PopAndDestroy(/*parser*/);
+//				for (iFound=0 ; iFound++ ; (iFound < (encAttrList->Length())))
+//				{
+//					VisitAttributeValueL(encAttrList->At(iFound).Value, encAttrList->At(iFound).Type);
+//				}
+//				CleanupStack::PopAndDestroy(/*encAttrList*/);
+				break;
+			default:
+				test.Printf(_L("type %d\n"), aType);
+			}
+		}
+	void StartListL(CSdpAttrValueList &/*aList*/)
+		{
+		++iIndent;
+		test.Printf(_L("{"));
+		}
+    void EndListL()
+		{
+		if(iIndent<=0)
+			{
+			test.Printf(_L("\nERROR! Unmatched EndList!\n"));
+			__DEBUGGER();
+			}
+		test.Printf(_L("}"));
+		--iIndent;
+		}
+private:
+	void Indent() {/*test.SetPos(iIndent)*/;}
+	CConsoleBase &iConsole;
+	TInt iIndent;
+	};
+
+void PrintDb(CSdpDatabase& aDb, CConsoleBase& aConsole)
+	{
+	aConsole.Printf(_L("Printing Database...\n"));
+
+	for(TServRecordIter recIter(aDb.RecordIter()); recIter; recIter++)
+		{// Iterate thru records in Db
+		aConsole.Printf(_L("\n...Printing Record 0x%x\n"), (*recIter).Handle());
+		for(TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++)
+			{// Iterate thru attributes in record
+			CAttrPrintVisitor* theVisitor = new CAttrPrintVisitor(aConsole);
+			(*attrIter).AcceptVisitorL(*theVisitor);
+			delete theVisitor;
+			}
+		}
+	}
+
+class CAttrFlogVisitor : public CBase, public MAttributeVisitor
+	{
+public:
+	CAttrFlogVisitor(){}
+    void VisitAttributeL(CSdpAttr &aAttribute)
+		{
+		Indent();
+
+		//3 lines for one here, but prevents warning.
+		TUint id;
+		id= aAttribute.AttributeID(); 
+		FTRACE(FPrint(_L("Attribute ID: 0x%x\n"), id));
+
+		(void)(id != 0); // keep compiler happy by referencing id as an r-value in urel
+		}
+	void VisitAttributeValueL(CSdpAttrValue & aValue, TSdpElementType aType)
+		{
+		TBuf16<64> iString;
+		switch (aType)
+			{
+			case ETypeString:
+				iString.Copy(aValue.Des());
+				FTRACE(FPrint(_L("\"%S\""),&iString));
+				break;
+			case ETypeDES:
+				FTRACE(FPrint(_L(" DES")));
+				break;
+			case ETypeUint:
+				FTRACE(FPrint(_L(" UInt:0x%x"), aValue.Uint()));
+				break;
+			case ETypeUUID:
+				FTRACE(FPrint(_L(" UUID:0x")));
+				HexDes(aValue.UUID().ShortestForm());
+				break;
+			case ETypeEncoded:
+				HexDes(aValue.Des());  // simplest
+				break;
+			default:
+				FTRACE(FPrint(_L("type %d\n"), aType));
+			}
+		}
+    //void VisitAttributeValueL(CSdpAttrValue &aValue, TSdpElementType aType)
+	//	{
+	//	Indent();
+	//	FTRACE(FPrint(_L("(Val: type %d)\n"), aType));
+	//	if(aType==ETypeUUID)
+	//		{
+	//		TUUID u = aValue.UUID();
+	//		FTRACE(FPrint(_L("(Val: uuid 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x)\n"), 
+	//					  u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]));
+	//		}
+	//
+	//		}
+    void StartListL(CSdpAttrValueList &/*aList*/)
+		{
+		++iIndent;
+		Indent();
+		FTRACE(FPrint(_L("{\n")));
+		}
+    void EndListL()
+		{
+		if(iIndent<=0)
+			{
+			FTRACE(FPrint(_L("\nERROR! Unmatched EndList!\n")));
+			__DEBUGGER();
+			}
+		Indent();
+		FTRACE(FPrint(_L("}\n")));
+		--iIndent;
+		}
+private:
+	void HexDes(const TDesC8& aDes)
+		{
+		for (TInt i = 0; i < aDes.Length(); ++i)
+			{
+			FTRACE(FPrint(_L("%02x"), aDes[i]));
+			}
+		}
+
+	void Indent() 
+		{
+		for(TInt i=0; i<iIndent;++i)
+			{
+			FTRACE(FPrint(_L("  ")));
+			}
+			
+		}
+	TInt iIndent;
+	};
+
+
+void FlogDb(CSdpDatabase& aDb)
+	{
+	FTRACE(FPrint(_L("\n\nPrinting Database...\n\n")));
+
+	for(TServRecordIter recIter(aDb.RecordIter()); recIter; recIter++)
+		{// Iterate thru records in Db
+		FTRACE(FPrint(_L("\n...Printing Record 0x%x\n"), (*recIter).Handle()));
+		for(TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++)
+			{// Iterate thru attributes in record
+			CAttrFlogVisitor* theVisitor = new CAttrFlogVisitor();
+			(*attrIter).AcceptVisitorL(*theVisitor);
+			delete theVisitor;
+			}
+		}
+	FTRACE(FPrint(_L("\n\nEnd Printing Database...\n\n\n\n")));
+	}
+
+
+
+class CSearchObserver : public CBase, public MServiceSearchHandler
+	{
+public:
+	void RecordFoundL(CSdpServRecord& aMatchingRec)
+		{
+		++iMatchesFound;
+		test.Printf(_L("Match %d found in record 0x%x\n"), iMatchesFound, aMatchingRec.Handle());
+		};
+	TInt iMatchesFound;
+	};
+
+void SearchDbL(CSdpDatabase &aDb, const CSdpSearchPattern &aPattern, TInt aExpectedMatches)
+   	{
+	CSearchObserver *ob = new(ELeave) CSearchObserver;
+	CleanupStack::PushL(ob);
+	CServiceSearchVisitor::SearchDbL(aDb, aPattern, *ob);
+	test(aExpectedMatches==ob->iMatchesFound);
+	CleanupStack::PopAndDestroy();
+	}
+
+void RegisterDatabaseInServerL (RSdpDatabase& aDb, CSdpDatabase& aDbStruct)
+	{
+	for(TServRecordIter recIter(aDbStruct.RecordIter()); recIter; recIter++)
+		{// Iterate thru records in Db
+		TServAttrIter attrIter((*recIter).AttributeIter());
+		if(!attrIter) 
+			continue;
+		if((*attrIter).AttributeID() == 0)
+			attrIter++;	//Skip rec handle
+		if(!attrIter) 
+			continue;
+		if((*attrIter).AttributeID() != 1 || (*attrIter).Value().Type() != ETypeDES)
+			continue;
+		// Get service class list
+		TSdpServRecordHandle handle;
+		aDb.CreateServiceRecordL((CSdpAttrValueDES&)(*attrIter).Value(), handle);
+		attrIter++;
+		for(; attrIter; attrIter++)
+			{// Iterate thru attributes in record
+			aDb.UpdateAttributeL(handle, (*attrIter).AttributeID(), (*attrIter).Value());
+			}
+		}
+	}
+ 
+TSdpServRecordHandle BuildPagonisL(RSdpDatabase& aDb, TUUID aUUID, TUint8 aCN)
+/**
+ Record Pagonis should be used when building a record with a protocol ID
+ list consisting of L2CAP and RFCOMM. This record is for a service of class
+ "serial port" - UUID16 0x1101
+ note that attributes 2, 5 and 0x201 should be updated.
+ also note only English, pas de Francais, keine Deutsch, non Espanol
+**/
+	{
+	TBuf8<4> value1;
+	TBuf8<4> value2;
+	TSdpServRecordHandle recHandle;
+	CSdpAttrValue* attrVal = 0;
+	CSdpAttrValueDES* attrValDES = 0;
+
+
+	value1.FillZ(4);
+	value2.FillZ(4);
+
+	// Set Attr 1 (service class list) to list with UUID = 0x1101 (serial port)
+	//													 or 0x1102 (LANP)
+	aDb.CreateServiceRecordL(aUUID, recHandle);
+	test.Printf(_L("Service Record Created - Handle: 0x%x!\n\n"), recHandle);
+
+	// Set Attr 2 (service record state) to 0
+	value1.FillZ(4);
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x02, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set attr 4 (protocol list) to L2CAP, and RFCOMM
+	value1.FillZ(4);
+	value1[3] = 3;
+	value2.FillZ(4);
+	value2[3] = aCN;
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildDESL()
+			->StartListL()
+				->BuildUUIDL(TUUID(TUint16(0x0100))) // L2CAP
+				->BuildUintL(value1)
+			->EndListL()
+			->BuildDESL()
+			->StartListL()
+				->BuildUUIDL(TUUID(TUint16(0x0003))) // RFCOMM
+				->BuildUintL(value2)
+			->EndListL()
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x04, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+	// Set Attr 5 (browse group list) to list with one UUID
+	// 0x1101 (serial port class)
+	// this should be updated with other service classes when other services are added.
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildUUIDL(TUUID(TUint32(0x1002)))
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x05, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+
+	// Set Attr 0x006 (language base)
+	value1.FillZ(4);
+	value1[2] = 0x65;
+	value1[3] = 0x6e;
+	TBuf8<4> val2;
+	TBuf8<4> val3;
+	val2.FillZ(4);
+	val3.FillZ(4);
+	val2[3] = 0x6a;
+	val3[2] = 0x01;
+
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildUintL(value1) // english
+			->BuildUintL(val2) // UTF-8
+			->BuildUintL(val3) // language base
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x06, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+	// Set Attr 0x007 (time to live) to 1200 (0x4B0) seconds (20 minutes)
+	value1.FillZ(4);
+	value1[2]=4;
+	value1[3]=0xb0;
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x07, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x008 (availability) to 0xff - fully available - not in use
+	value1.FillZ(4);
+	value1[3]=0xff;
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x08, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+
+	// Set Attr 0x100 (default Name) to string
+	attrVal = CSdpAttrValueString::NewStringL(_L8("Pagonis Service"));
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0100, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x101 (def. description) to string
+	attrVal = CSdpAttrValueString::NewStringL(_L8("It's all Greek to me!"));
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0101, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x102 (def. provider) to Symbian
+	attrVal = CSdpAttrValueString::NewStringL(_L8("Symbian Ltd."));
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0102, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x201 (service database state) to 0
+	value1.FillZ(4);
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0201, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	return recHandle;
+}
+
+
+TSdpServRecordHandle BuildWAPL(RSdpDatabase& aDb, TUint8 aCN)
+/**
+ Record Wap should be used when building a record with a protocol ID
+ list consisting of L2CAP and RFCOMM, similar to Pagonis but containing
+ a profile descriptor list with LAN access using PPP.
+ This record is for a service of class "WAP bearer" - UUID16 0x1113
+**/
+	{
+	TBuf8<4> value1;
+	TBuf8<4> value2;
+	TSdpServRecordHandle recHandle;
+	CSdpAttrValue* attrVal = 0;
+	CSdpAttrValueDES* attrValDES = 0;
+
+
+	value1.FillZ(4);
+	value2.FillZ(4);
+
+	// Set Attr 1 (service class list) to list with UUID = 0x1113 (WAP access device)
+	aDb.CreateServiceRecordL(TUUID(TUint16(0x1113)), recHandle);
+	test.Printf(_L("WAP Service Record Created - Handle: 0x%x!\n\n"), recHandle);
+
+	// Set Attr 2 (service record state) to 0
+	value1.FillZ(4);
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x02, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set attr 4 (protocol list) to L2CAP, and RFCOMM
+	value1.FillZ(4);
+	value1[3] = 3;
+	value2.FillZ(4);
+	value2[3] = aCN;
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildDESL()
+			->StartListL()
+				->BuildUUIDL(TUUID(TUint16(0x0100))) // L2CAP
+				->BuildUintL(value1)
+			->EndListL()
+			->BuildDESL()
+			->StartListL()
+				->BuildUUIDL(TUUID(TUint16(0x0003))) // RFCOMM
+				->BuildUintL(value2)
+			->EndListL()
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x04, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+	// Set Attr 5 (browse group list) to list with one UUID
+	// 0x1101 (serial port class)
+	// this should be updated with other service classes when other services are added.
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildUUIDL(TUUID(TUint32(0x1002)))
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x05, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+
+	// Set Attr 0x006 (language base)
+	value1.FillZ(4);
+	value1[2] = 0x65;
+	value1[3] = 0x6e;
+	TBuf8<4> val2;
+	TBuf8<4> val3;
+	val2.FillZ(4);
+	val3.FillZ(4);
+	val2[3] = 0x6a;
+	val3[2] = 0x01;
+
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildUintL(value1) // english
+			->BuildUintL(val2) // UTF-8
+			->BuildUintL(val3) // language base
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x06, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+	// Set Attr 0x007 (time to live) to 1200 (0x4B0) seconds (20 minutes)
+	value1.FillZ(4);
+	value1[2]=4;
+	value1[3]=0xb0;
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x07, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x008 (availability) to 0xff - fully available - not in use
+	value1.FillZ(4);
+	value1[3]=0xff;
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x08, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x009 (profile descriptor) to confuse the BTCOMM client when looking for LANP
+	value1.FillZ(4);
+	value1[3] = 1;
+	attrValDES = CSdpAttrValueDES::NewDESL(0);
+	CleanupStack::PushL(attrValDES);
+	attrValDES
+		->StartListL()
+			->BuildDESL()
+			->StartListL()
+				->BuildUUIDL(TUUID(TUint16(0x1102))) // LAN access using PPP
+				->BuildUintL(value1)
+			->EndListL()
+		->EndListL();
+	aDb.UpdateAttributeL(recHandle, 0x09, *attrValDES);
+	CleanupStack::PopAndDestroy();
+	attrValDES = 0;
+
+
+	// Set Attr 0x100 (default Name) to string
+	attrVal = CSdpAttrValueString::NewStringL(_L8("Pagonis Service"));
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0100, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x101 (def. description) to string
+	attrVal = CSdpAttrValueString::NewStringL(_L8("It's all Greek to me!"));
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0101, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x102 (def. provider) to Symbian
+	attrVal = CSdpAttrValueString::NewStringL(_L8("Symbian Ltd."));
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0102, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	// Set Attr 0x201 (service database state) to 0
+	value1.FillZ(4);
+	attrVal = CSdpAttrValueUint::NewUintL(value1);
+	CleanupStack::PushL(attrVal);
+	aDb.UpdateAttributeL(recHandle, 0x0201, *attrVal);
+	CleanupStack::PopAndDestroy();
+	attrVal = 0;
+
+	return recHandle;
+}
+
+
+
+void Test0()
+/**
+	Client/server test.
+**/
+	{
+	FLOG(_L("Running test 0"));
+	//FIXME: TRAPD? 
+	test.Start(_L("Test 0 -- Client/Server"));
+	TInt ret;
+	LoadLDD_PDD();
+
+	RSdp sdp;
+	ret = sdp.Connect();
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+	RSdpDatabase db;
+	ret = db.Open(sdp);
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+	TSdpServRecordHandle recHandle = 0;
+	TUUID uuid = TUUID(0x20000); //prevents warning
+	db.CreateServiceRecordL(uuid, recHandle);
+	test.Printf(_L("Service Record Created - Handle: 0x%x!\n\n"), recHandle);
+		CSdpAttrValueDES* list = CSdpAttrValueDES::NewDESL(NULL);
+		MSdpElementBuilder* bldr= list;
+		CleanupStack::PushL(list);
+
+		bldr
+			->StartListL()
+				->BuildUUIDL(TUUID(TUint32(0x20002000)))
+				->BuildUUIDL(TUUID(TUint32(0x11112222), TUint32(0x33334444), 
+									  TUint32(0x55556666), TUint32(0x77778888)))
+				->BuildUUIDL(TUUID(TUint32(0x40000)))
+			->EndListL();
+		//db.CreateServiceRecordL(*list, recHandle);
+		CleanupStack::PopAndDestroy(); //list
+		//test.Printf(_L("Service Record Created - Handle: 0x%x!\n\n"), recHandle);
+	//User::WaitForRequest(status);
+	//if(status==KErrNone)
+	//	test.Printf(_L("Service Record Created - Handle: 0x%x!\n\n"), recHandlePckgBuf());
+	//else
+	//	test.Printf(_L("Service Record Creation ERROR %d!\n\n"), status.Int());
+
+	TBuf8<8> buf8(_L8("Mel!"));
+	buf8[1] = 'E';
+	buf8[2] = 'L';
+	TDesC16 buf16(_L("Nicky!"));
+	db.UpdateAttributeL(recHandle, 0x3454, buf8);
+	db.UpdateAttributeL(recHandle, 0x3455, _L("Nicky!"));
+	db.UpdateAttributeL(recHandle, 0x3455, _L("Micky!"));
+	db.UpdateAttributeL(recHandle, 0x3456, 0x9999);
+	db.DeleteAttributeL(recHandle, 0x3456);
+	db.UpdateAttributeL(recHandle, 0x3456, 0x7777);
+	db.DeleteAttributeL(recHandle, 0x5555); //does not exist!
+	//db.DeleteRecordL(recHandleSpecial);
+	db.Close();
+	sdp.Close();
+	test.End();
+	}
+
+
+void Test1()
+/**
+	Client/server test for use with John Pagonis.
+	Suitable database built on client side, and placed in server.
+	Server left alive till user chooses to kill it.
+**/
+	{
+	FLOG(_L("Running test 1"));
+	//FIXME: TRAPD? 
+	test.Start(_L("Test 1 -- Client/Server for BTCOMM testing...\n"));
+	test.Printf(_L("This builds a database with three service records\n"));
+	test.Printf(_L("The First one (UUID 1101) containing protocol attribute value: L2CAP, 3; RFCOMM, 1\n"));
+	test.Printf(_L("the second (UUID 1102 LANP) containing protocol attribute value: L2CAP, 3; RFCOMM, 2.\n"));
+	test.Printf(_L("the third (UUID 1103) containing protocol attribute value: L2CAP, 3; RFCOMM, 3.\n"));
+	test.Printf(_L("the third is a WAP server record and should never be selected\n"));
+	test.Printf(_L("The server then remains in listening mode\n"));
+	test.Printf(_L("until the user of Test 1 types 'x'.\n\n\n\n"));
+	
+	TChar c;
+	RSdp sdp;
+	RSdpDatabase db;
+//	User::After(5000000);
+	TInt ret;
+	LoadLDD_PDD();
+
+	ret = sdp.Connect();
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+	ret = db.Open(sdp);
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+
+	TSdpServRecordHandle recHandle1;
+	TSdpServRecordHandle recHandle2;
+	TSdpServRecordHandle recHandle3;
+
+	test.Printf(_L("SDP server with record 0, type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle1 = BuildPagonisL(db,TUUID(TUint32(0x1101)), 1);
+	test.Printf(_L("Pagonis record (0x1101), type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+
+	recHandle2 = BuildPagonisL(db,TUUID(TUint32(0x1102)), 2);
+	test.Printf(_L("Pagonis record (0x1102), type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle3 = BuildWAPL(db, 3);
+	test.Printf(_L("one WAP record, type 'x' to continue.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	test.Printf(_L("The database is now ready to test, type 'x' to exit.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+/**/
+	db.DeleteRecordL(recHandle2);
+
+	test.Printf(_L("The database has now had the second Pagonis record removed.\
+					\nWhen you have finished using this database please type 'x'.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+	db.UpdateAttributeL(recHandle1, 0x3455, _L("Nicky!"));
+	test.Printf(_L("\nTo check on updating record STATE attribute we have now\
+		            \nupdated one random attribute in the first Pagonis record.\
+					\nPlease type 'x' AGAIN.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+	db.UpdateAttributeL(recHandle1, 0x3455, _L("Nicky!"));
+	test.Printf(_L("\nTo check on updating record STATE attribute we have now\
+		            \nupdated ONCE AGAIN a random attribute in the first Pagonis\
+					\nrecord.\
+					\nPlease type 'x' ONCE AGAIN.\n\n"));
+	c = test.Getch();
+	db.DeleteAttributeL(recHandle1, 0x3455);
+	while (c!='x' && c!='X')
+		c = test.Getch();
+	test.Printf(_L("\nTo check on updating record STATE attribute we have now\
+		            \ndeleted an attribute in the first Pagonis\
+					\nrecord.\
+					\nPlease type 'x' YET AGAIN - THIS TIME TO KILL THE DATABASE.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+	db.DeleteAttributeL(recHandle1, 0x3455);
+/**/
+	db.DeleteRecordL(recHandle3);
+	// Record with recHandle2 has already been deleted
+	db.DeleteRecordL(recHandle1);
+	db.Close();
+	sdp.Close();
+
+  
+	test.End();
+	}
+
+
+
+
+void TestD()
+/**
+	Client/server test for use with John Pagonis.
+	Suitable database built on client side, and placed in server.
+	Server left alive till user chooses to kill it.
+**/
+	{
+	FLOG(_L("Running test D"));
+	//FIXME: TRAPD? 
+	test.Start(_L("Test D -- Client/Server for BTCOMM testing...\n"));
+	test.Printf(_L("This builds a database with four service records\n"));
+	test.Printf(_L("The first one (UUID 1103 WAP) containing protocol attribute value: L2CAP, 3; RFCOMM, 3\n"));
+	test.Printf(_L("the second (UUID 1101) containing protocol attribute value: L2CAP, 3; RFCOMM, 1.\n"));
+	test.Printf(_L("the third (UUID 1103 WAP) containing protocol attribute value: L2CAP, 3; RFCOMM, 4.\n"));
+	test.Printf(_L("the forth (UUID 1102 LANP) containing protocol attribute value: L2CAP, 3; RFCOMM, 2.\n"));
+	test.Printf(_L("The server then remains in listening mode\n"));
+	test.Printf(_L("until the user of Test D types 'x'.\n\n\n\n"));
+	
+	TChar c;
+	RSdp sdp;
+	RSdpDatabase db;
+//	User::After(5000000);
+	TInt ret;
+	LoadLDD_PDD();
+
+	ret = sdp.Connect();
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+	ret = db.Open(sdp);
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+
+	TSdpServRecordHandle recHandle1;
+	TSdpServRecordHandle recHandle2;
+	TSdpServRecordHandle recHandle3;
+	TSdpServRecordHandle recHandle4;
+
+	test.Printf(_L("SDP server with record 0, type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle3 = BuildWAPL(db, 3);
+	test.Printf(_L("one WAP record, type 'x' to continue.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle1 = BuildPagonisL(db,TUUID(TUint32(0x1101)), 1);
+	test.Printf(_L("Pagonis record (0x1101), type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle4 = BuildWAPL(db, 4);
+	test.Printf(_L("one WAP record, type 'x' to continue.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle2 = BuildPagonisL(db,TUUID(TUint32(0x1102)), 2);
+	test.Printf(_L("Pagonis record (0x1102), type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+
+	test.Printf(_L("The database is now ready to test, type 'x' to exit.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+	db.DeleteRecordL(recHandle4);
+	db.DeleteRecordL(recHandle3);
+	db.DeleteRecordL(recHandle2);
+	db.DeleteRecordL(recHandle1);
+	db.Close();
+	sdp.Close();
+
+  
+	test.End();
+	}
+
+
+void TestE()
+/**
+	Client/server test for use with John Pagonis.
+	Suitable database built on client side, and placed in server.
+	Server left alive till user chooses to kill it.
+**/
+	{
+	FLOG(_L("Running test D"));
+	//FIXME: TRAPD? 
+	test.Start(_L("Test E -- Client/Server for BTCOMM testing...\n"));
+	test.Printf(_L("This builds a database with four service records\n"));
+	test.Printf(_L("The first one (UUID 1103 WAP) containing protocol attribute value: L2CAP, 3; RFCOMM, 3\n"));
+	test.Printf(_L("the second (UUID 1101) containing protocol attribute value: L2CAP, 3; RFCOMM, 1.\n"));
+	test.Printf(_L("the third (UUID 1102 LANP) containing protocol attribute value: L2CAP, 3; RFCOMM, 2.\n"));
+	test.Printf(_L("the forth (UUID 1103 WAP) containing protocol attribute value: L2CAP, 3; RFCOMM, 4.\n"));
+	test.Printf(_L("The server then remains in listening mode\n"));
+	test.Printf(_L("until the user of Test E types 'x'.\n\n\n\n"));
+	
+	TChar c;
+	RSdp sdp;
+	RSdpDatabase db;
+//	User::After(5000000);
+	TInt ret;
+	LoadLDD_PDD();
+
+	ret = sdp.Connect();
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+	ret = db.Open(sdp);
+	if(ret!=KErrNone)
+		{
+		test.End();
+		return;
+		}
+
+	TSdpServRecordHandle recHandle1;
+	TSdpServRecordHandle recHandle2;
+	TSdpServRecordHandle recHandle3;
+	TSdpServRecordHandle recHandle4;
+
+	test.Printf(_L("SDP server with record 0, type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle3 = BuildWAPL(db, 3);
+	test.Printf(_L("one WAP record, type 'x' to continue.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle1 = BuildPagonisL(db,TUUID(TUint32(0x1101)), 1);
+	test.Printf(_L("Pagonis record (0x1101), type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle2 = BuildPagonisL(db,TUUID(TUint32(0x1102)), 2);
+	test.Printf(_L("Pagonis record (0x1102), type 'x' to continue.\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+	recHandle4 = BuildWAPL(db, 4);
+	test.Printf(_L("one WAP record, type 'x' to continue.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+
+
+	test.Printf(_L("The database is now ready to test, type 'x' to exit.\n\n"));
+	c = test.Getch();
+	while (c!='x' && c!='X')
+		c = test.Getch();
+	db.DeleteRecordL(recHandle4);
+	db.DeleteRecordL(recHandle3);
+	db.DeleteRecordL(recHandle2);
+	db.DeleteRecordL(recHandle1);
+	db.Close();
+	sdp.Close();
+
+  
+	test.End();
+	}
+
+void WhichTest()
+	{
+	TChar c;
+	test.Printf(_L("\nwhich test? "));
+	test.Printf(_L("\npress 0 for UUID 1101, 1102, 1103 "));
+	test.Printf(_L("\npress 1 for UUID 1103, 1101, 1103, 1102 "));
+	test.Printf(_L("\npress 2 for UUID 1103, 1101, 1102, 1103 "));
+	c = test.Getch(); 
+	switch (c) 
+		{
+	case '0':
+		Test1();
+		break;
+	case '1':
+		TestD();
+		break;
+	case '2':
+		TestE();
+		break;
+	default:
+		break;
+		}
+	}
+
+
+
+
+
+
+void Test2()
+/**
+	Builds up a static DB, and prints it,
+	using the record and attribute iteraotrs, and a
+	simple console-printing attribute value visitor.
+**/
+	{
+	//FIXME: TRAPD?
+	test.Start(_L("Test 2 -- Build and print Db"));
+//	CSdpDatabase *theDb = BuildDbL();
+	CSdpDatabase *theDb = BuildUpf4DbL();
+	test(theDb!=NULL);
+	PrintDb(*theDb, *test.Console());
+	delete theDb;
+
+	test.End();
+	}
+
+void Test3()
+/**
+	Builds up a static DB, and copies it into the RSdpDatabase
+**/
+	{
+	//FIXME: TRAPD?
+	test.Start(_L("Test 3 -- Build and print Db"));
+//	CSdpDatabase *theDb = BuildDbL();
+	CSdpDatabase *theDb = BuildUpf4DbL();
+	test(theDb!=NULL);
+	CleanupStack::PushL(theDb);
+
+	RSdp sdp;
+	RSdpDatabase db;
+	TInt ret;
+	LoadLDD_PDD();
+
+	test.Next(_L("Opening SDP Database"));
+	ret = sdp.Connect();
+	test(ret==KErrNone);
+	CleanupClosePushL(sdp);
+	ret = db.Open(sdp);
+	test(ret==KErrNone);
+	CleanupClosePushL(db);
+
+	test.Next(_L("Storing database"));
+	RegisterDatabaseInServerL(db, *theDb);
+
+	test.Next(_L("Database stored. Now run your tests! Press any key to close SDDB"));
+	test.Getch();
+
+	CleanupStack::PopAndDestroy(3); // db, sdp, theDb
+
+	test.End();
+	}
+
+
+void Test4()
+/**
+	Builds a static DB and searches it for a 
+	UUID search pattern (as per SDP service search
+	requests)
+**/
+	{
+	test.Start(_L("Test 2 -- Service search over Db"));
+	CSdpDatabase *theDb = BuildDbL();
+
+	CSdpSearchPattern* thePattern = CSdpSearchPattern::NewL();
+	//Service pattern with one UUID in it...
+	test.Next(_L("Doing un-encoded tests"));
+	test.Next(_L("Searching for SDP server service UUID (0x1000)"));
+	thePattern->AddL(TUUID(TUint16(0x1000)));
+	SearchDbL(*theDb, *thePattern, 2); // Expect 2 matches
+
+	test.Next(_L("Searching for SDP server service and bogoid UUID"));
+	thePattern->AddL(TUUID(TUint32(0x55667788)));	
+	SearchDbL(*theDb, *thePattern, 1); // Expect 1 matches
+
+	test.Next(_L("Searching for SDP server service and two bogoid UUID"));
+	thePattern->AddL(TUUID(TUint32(0x11112222)));	
+	SearchDbL(*theDb, *thePattern, 0); // Expect 0 matches
+
+	test.Next(_L("Searching for RFCOMM uuid"));
+	thePattern->Reset();
+	thePattern->AddL(TUUID(TUint16(0x0003)));	
+	SearchDbL(*theDb, *thePattern, 1); // Expect 1 matches
+
+
+	thePattern->Reset();
+
+	theDb->EncodeDbL();
+
+	test.Next(_L("Doing encoded tests"));
+	test.Next(_L("Searching for SDP server service UUID (0x1000)"));
+	thePattern->AddL(TUUID(TUint16(0x1000)));
+	SearchDbL(*theDb, *thePattern, 2); // Expect 2 matches
+
+	test.Next(_L("Searching for SDP server service and bogoid UUID"));
+	thePattern->AddL(TUUID(TUint32(0x55667788)));	
+	SearchDbL(*theDb, *thePattern, 1); // Expect 1 matches
+
+	test.Next(_L("Searching for SDP server service and two bogoid UUID"));
+	thePattern->AddL(TUUID(TUint32(0x11112222)));	
+	SearchDbL(*theDb, *thePattern, 0); // Expect 0 matches
+
+	test.Next(_L("Searching for RFCOMM uuid"));
+	thePattern->Reset();
+	thePattern->AddL(TUUID(TUint16(0x0003)));	
+	SearchDbL(*theDb, *thePattern, 1); // Expect 1 matches
+
+
+
+	delete thePattern;
+	delete theDb;
+	test.End();
+	}
+
+void TestEncoder(TInt aType, CSdpDatabase *aDb)
+	{
+	TInt64 seed = aType * 49;
+
+	test.Start(_L("Test 3 -- Encoder & Parser"));
+	CSdpDatabase *builtDb = CSdpDatabase::NewL();
+
+	HBufC8* outbuf = HBufC8::New(1024);
+	TPtr8 writePtr (outbuf->Des());
+	TElementEncoder theEncoder(writePtr);
+	CElementParser* theParser = CElementParser::NewL(0);
+	CSdpAttrIdMatchList *theAttrList = CSdpAttrIdMatchList::NewL();
+
+	theAttrList->AddL(KAttrRangeAll);
+
+	test.Next(_L("Encode and parse ref DB"));
+		{
+		for(TServRecordIter recIter(aDb->RecordIter()); recIter; recIter++)
+			{// Iterate thru records in Db
+			TInt startPos = writePtr.Length();
+			CAttrExtractVisitor::EncodeAttributesL(theEncoder, *recIter, *theAttrList);
+			// grows writePtr
+
+			CSdpServRecord* builtRec = CSdpServRecord::NewL();
+			theParser->Reset(builtRec);
+			TInt incr = 1;
+			TBool moreExpected = ETrue;
+			for (TInt i = startPos; i < writePtr.Length(); i += incr)
+				{// parse it back, in inreasing chunks
+				switch(aType)
+					{
+				case 0:
+					incr += 1;
+					break;
+				case 1:
+					incr <<= 1;
+					break;
+				case 2:
+				default:
+					incr = Math::Rand(seed) % (i+2);
+					}
+				incr=Min(incr, writePtr.Length() - i);
+				moreExpected = theParser->BufferedParseL(writePtr.Mid(i, incr));
+				}
+			test(!moreExpected);
+			builtDb->AddRecord(builtRec);
+			}
+		}
+
+	HBufC8* outbuf2 = HBufC8::New(outbuf->Size());
+	writePtr.Set (outbuf2->Des());
+
+	test.Next(_L("Re-Encode the DB built from parser"));
+		{
+		for(TServRecordIter recIter(builtDb->RecordIter()); recIter; recIter++)
+			{// Iterate thru records in Db
+			CAttrExtractVisitor::EncodeAttributesL(theEncoder, *recIter, *theAttrList);
+			}
+		}
+
+//	test(*outbuf == *outbuf2);
+
+	// The bit below is equivalent to the above line, only easier to debug
+	test(outbuf->Length() == outbuf2->Length());
+	for (TInt i = 0; i < outbuf->Length(); ++i)
+		{
+		test((*outbuf)[i] == (*outbuf2)[i]);
+		}
+
+	delete outbuf;
+	delete outbuf2;
+	delete theParser;
+	delete theAttrList;
+	delete builtDb;
+	test.End();
+	}
+
+
+void Test5()
+	{
+	for (TInt i = 0; i < 8; ++i)
+		{
+		test.Next(_L("Doing tests with ref Db"));
+		CSdpDatabase *theDb = BuildDbL();
+		TestEncoder(i, theDb);
+		delete theDb;
+
+		test.Next(_L("Doing tests with UPF4 Db"));
+		theDb = BuildUpf4DbL();
+		TestEncoder(i, theDb);
+		delete theDb;
+		}
+	}
+
+void Test6()
+	{
+	test.Start(_L("Test 6 -- Database size and encoding stuff"));
+	CSdpDatabase *theDb = BuildDbL();
+
+	const TUint KExpectedSizes[] = 
+		{
+		5,  5,  12, 28,
+		14, 5,  5,  22,
+		23, 35, 5,  10,
+		3,  15, 19,
+		};
+	test.Next(_L("Testing the size functions"));
+	TInt ind = 0;
+	for(TServRecordIter recIter(theDb->RecordIter()); recIter; recIter++)
+		{// Iterate thru records in Db
+		for(TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++)
+			{// Iterate thru attributes in record
+			TUint size = TElementEncoder::EncodedSize((*attrIter).Value().Type(), (*attrIter).Value().DataSize());
+			test.Printf(_L("Attribute value Encoded size is %d\n"), size);
+			test(size == KExpectedSizes[ind]);
+			++ind;
+			}
+		}
+
+	delete theDb;
+
+	test.Next(_L("Testing attribute match list stuff"));
+	CSdpAttrIdMatchList *theAttrList = CSdpAttrIdMatchList::NewL();
+
+	theAttrList->AddL(TAttrRange(10, 15));	// insert at beginning ->	10-15
+	theAttrList->AddL(TAttrRange(30, 40));	// insert at end	->	10-15,30-40
+	theAttrList->AddL(TAttrRange(18, 19));	// insert between 2	->	10-15, 18-19, 30-40
+	theAttrList->AddL(TAttrRange(27, 29));	// append to start of another range	->	10-15, 18-19, 27-40
+	theAttrList->AddL(TAttrRange(41, 45));	// append to end of another range	->	10-15, 18-19, 27-45
+	theAttrList->AddL(TAttrRange(16, 17));	// join 2 ranges together	->	10-19,  27-45
+	theAttrList->AddL(TAttrRange(21, 24));	// insert between 2	->	10-19, 21-24, 27-45
+	test(theAttrList->Count() == 3);
+		
+	TInt posn;
+	test(theAttrList->InMatchListRange(10, posn));
+	test(theAttrList->InMatchListRange(11, posn));
+	test(theAttrList->InMatchListRange(15, posn));
+	
+	test(theAttrList->InMatchListRange(21, posn));
+	test(theAttrList->InMatchListRange(22, posn));
+	test(theAttrList->InMatchListRange(23, posn));	
+	test(theAttrList->InMatchListRange(24, posn));	
+	
+	test(theAttrList->InMatchListRange(45, posn));	
+	
+	theAttrList->RemoveL(TAttrRange(12, 14));	// mid-range ->	10-11, 15-19, 21-24, 27-45
+	test(theAttrList->Count() == 4);
+
+	theAttrList->RemoveL(TAttrRange(12, 14));	// 	no change ->	10-11, 15-19, 21-24, 27-45
+	theAttrList->RemoveL(TAttrRange(14, 16));	// overlap start	->	10-11, 17-19, 21-24, 27-45
+	test(theAttrList->Count() == 4);	
+	theAttrList->RemoveL(TAttrRange(17, 20));	// remove one item	->	10-11, 21-24, 27-45
+	theAttrList->RemoveL(TAttrRange(40, 45));	// end of range 	->	10-11, 21-24, 27-39
+	theAttrList->RemoveL(TAttrRange(28, 28));	// range of one 	->	10-11, 21-24, 27, 29-39
+	test(theAttrList->Count() == 4);	
+	test(theAttrList->InMatchList(27));	
+	theAttrList->RemoveL(TAttrRange(26, 28));	// remove range of one 	->	10-11, 21-24, 29-39
+	test(theAttrList->Count() == 3);
+			
+	theAttrList->AddL(TAttrRange(15, 15));	// insert between 2	->	10-11, 15, 21-24, 29-39
+	theAttrList->AddL(TAttrRange(17, 18));	// insert between 2	->	10-11, 15, 17-18, 21-24, 29-39
+	test(theAttrList->Count() == 5);
+	theAttrList->AddL(TAttrRange(13, 26));	// obliterate 3 with one big insertion ->	10-11, 13-26, 29-39
+	test(theAttrList->Count() == 3);			
+	theAttrList->RemoveL(TAttrRange(15, 17));	//->	10-11, 13-14, 18-26, 29-39		
+	theAttrList->RemoveL(TAttrRange(19, 21));	//->	10-11, 13-14, 18, 22-26, 29-39
+	theAttrList->RemoveL(TAttrRange(23, 24));	//->	10-11, 13-14, 18, 22, 25-26, 29-39	
+	test(theAttrList->Count() == 6);	
+	theAttrList->AddL(TAttrRange(16, 28));	// obliterate 3 with one big deletion ->	10-11, 13-14, 29-39
+	test(theAttrList->Count() == 3);	
+
+	theAttrList->RemoveL(TAttrRange(31, 31));	//->		10-11, 13-14, 29-30 32-39
+	test(theAttrList->Count() == 4);	
+	theAttrList->AddL(TAttrRange(28, 31));	// new range contiguous with 2 current ranges ->	10-11, 13-14, 28-39	
+	test(theAttrList->Count() == 3);				
+				
+	theAttrList->RemoveL(TAttrRange(0, 45)); // remove all entries
+					
+	theAttrList->AddL(TAttrRange(50, 300));	// 50-300
+		
+	test(theAttrList->InMatchList(50));
+	test(theAttrList->InMatchList(256));	
+	test(theAttrList->InMatchList(300));
+
+	test(theAttrList->InMatchList(301) == EFalse);
+	test(theAttrList->InMatchList(49) == EFalse);
+
+	theAttrList->AddL(TAttrRange(302, 304));	// 50-300, 302-304
+	test(theAttrList->Count() == 2);
+
+	theAttrList->AddL(TAttrRange(50, 50));
+	test(theAttrList->Count() == 2);
+
+	theAttrList->AddL(TAttrRange(45, 310));		// 45-310
+	test(theAttrList->Count() == 1);
+	test(theAttrList->InMatchList(45));
+	test(theAttrList->InMatchList(310));
+	test(theAttrList->InMatchList(311) == EFalse);
+	test(theAttrList->InMatchList(44) == EFalse);
+
+	theAttrList->AddL(TAttrRange(45, 200));		// 45-310
+	test(theAttrList->Count() == 1);
+
+	theAttrList->RemoveL(TAttrRange(50, 60));		// 45-49 61-310
+	test(theAttrList->Count() == 2);
+	test(theAttrList->InMatchList(49));
+	test(theAttrList->InMatchList(50) == EFalse);
+	test(theAttrList->InMatchList(60) == EFalse);
+	test(theAttrList->InMatchList(61));
+	test(theAttrList->InMatchList(45));
+	test(theAttrList->InMatchList(310));
+	test(theAttrList->InMatchList(311) == EFalse);
+
+	theAttrList->RemoveL(TAttrRange(55, 65));		// 45-49 66-310
+	test(theAttrList->Count() == 2);
+	test(theAttrList->InMatchList(66));
+	test(theAttrList->InMatchList(65) == EFalse);
+
+	theAttrList->RemoveL(TAttrRange(55, 55));
+	test(theAttrList->Count() == 2);
+	theAttrList->RemoveL(TAttrRange(1, 2));
+	theAttrList->RemoveL(TAttrRange(400, 500));
+	test(theAttrList->Count() == 2);
+
+	theAttrList->RemoveL(TAttrRange(40, 70));		// 71-310
+	test(theAttrList->Count() == 1);
+
+	theAttrList->AddL(TAttrRange(5, 39));			// 5-39, 71-310
+	test(theAttrList->Count() == 2);
+
+	theAttrList->RemoveL(TAttrRange(38, 38));		// 5-37, 39, 71-310
+	test(theAttrList->Count() == 3);
+	theAttrList->RemoveL(TAttrRange(36, 36));		// 5-35, 37, 39, 71-310
+	test(theAttrList->Count() == 4);
+
+	theAttrList->RemoveL(TAttrRange(30, 70));		// 5-29, 71-310
+	test(theAttrList->Count() == 2);
+
+	theAttrList->RemoveL(TAttrRange(1, 309));		// 310
+	test(theAttrList->Count() == 1);
+	test(theAttrList->InMatchList(310));
+	test(theAttrList->InMatchList(309) == EFalse);
+	test(theAttrList->InMatchList(311) == EFalse);
+
+	theAttrList->RemoveL(TAttrRange(1, 310));		// none
+	test(theAttrList->Count() == 0);
+
+
+	theAttrList->AddL(TAttrRange(45, 310));			// 45-310
+	test(theAttrList->Count() == 1);
+
+	theAttrList->AddL(TAttrRange(2000));			// 45-310, 2000
+	test(theAttrList->Count() == 2);
+	test(theAttrList->InMatchList(2000));
+	test(theAttrList->InMatchList(2001) == EFalse);
+
+	theAttrList->AddL(TAttrRange(2002));			// 45-310, 2000, 2002
+	test(theAttrList->Count() == 3);
+
+	theAttrList->AddL(TAttrRange(2004));			// 45-310, 2000, 2002, 2004
+	test(theAttrList->Count() == 4);
+	test(theAttrList->InMatchList(2004));
+	test(theAttrList->InMatchList(2003) == EFalse);
+
+	theAttrList->AddL(TAttrRange(2003));			// 45-310, 2000, 2002-2004
+	test(theAttrList->Count() == 3);
+
+	theAttrList->AddL(TAttrRange(301, 2001));		// 45-2004
+	test(theAttrList->Count() == 1);
+	test(theAttrList->InMatchList(45));
+	test(theAttrList->InMatchList(2004));
+	test(theAttrList->InMatchList(0) == EFalse);
+	test(theAttrList->InMatchList(2010) == EFalse);
+
+	TInt count = theAttrList->Count();
+	for (TUint16 i = 3000; i < 4000; i += 2)
+		{
+		theAttrList->AddL(TAttrRange(i, i));
+		++count;
+		test(theAttrList->Count() == count);
+		test(theAttrList->InMatchList(i));
+		test(theAttrList->InMatchList(TUint16(i-1)) == EFalse);
+		test(theAttrList->InMatchList(TUint16(i+1)) == EFalse);
+		}
+
+	for (TUint16 j = 3001; j < 3501; j += 2)
+		{
+		theAttrList->AddL(TAttrRange(j, j));
+		--count;
+		test(theAttrList->Count() == count);
+		test(theAttrList->InMatchList(j));
+		test(theAttrList->InMatchList(TUint16(j-1)));
+		test(theAttrList->InMatchList(TUint16(j+1)));
+		}
+
+	for (TUint16 k = 3001; k < 3400; k += 2)
+		{
+		theAttrList->RemoveL(TAttrRange(k, k));
+		++count;
+		test(theAttrList->Count() == count);
+		test(theAttrList->InMatchList(k) == EFalse);
+		test(theAttrList->InMatchList(TUint16(k-1)));
+		test(theAttrList->InMatchList(TUint16(k+1)));
+		}
+
+	theAttrList->AddL(TAttrRange(0, 5000));
+	test(theAttrList->Count() == 1);
+	test(theAttrList->InMatchList(0));
+	test(theAttrList->InMatchList(5000));
+	test(theAttrList->InMatchList(5001) == EFalse);
+	test(theAttrList->InMatchList(KMaxTUint16) == EFalse);
+
+	theAttrList->RemoveL(TAttrRange(0, 5000));
+	test(theAttrList->Count() == 0);
+
+	delete theAttrList;
+
+	test.End();
+
+	}
+
+/* moved out to the database dll as a utility method
+CSdpDatabase * EncodeDb(CSdpDatabase * nonEncodedDb)
+{
+	CSdpDatabase *encDb = CSdpDatabase::NewL();
+
+	TUint8 outbuf[72];
+	TPtr8 writePtr (outbuf, 0, 72);
+	CSdpServRecord *theRec = CSdpServRecord::NewL();
+	TElementEncoder theEncoder(writePtr);
+
+	test.Next(_L("Test attribute encoder"));
+	for(TServRecordIter recIter(nonEncodedDb->RecordIter()); recIter; recIter++)
+		{// Iterate through records in Db
+
+		for (TServAttrIter attrIter((*recIter).AttributeIter()); attrIter; attrIter++)
+			{// iterate through attributes in record
+			writePtr.Set(outbuf, 0, 72);  // bug, just declaring this (see above) didn't reset the pointer on each loop
+
+			CAttrEncoderVisitor::EncodeAttributeL(theEncoder, (*attrIter).Value());
+			TBuf8<sizeof(TUint)> val(2);
+			TElementEncoder::PutUint(&val[0], (*attrIter).AttributeID(), 2);
+			test.Printf(_L("AttrID:0x%02x%02x, <"), val[0], val[1]);
+			HexDes(writePtr);
+			test.Printf(_L(">\n"));
+			theRec->BuildUintL(val)->BuildEncodedL(writePtr);
+			}
+		encDb->AddRecord(theRec);
+		theRec = CSdpServRecord::NewL(); // need a new one
+		}
+	delete theRec;
+	return encDb;
+}
+*/
+
+// build an encoded version of the database then print it.
+void Test7()
+	{
+	test.Start(_L("Test 7 -- Encoded database"));
+	CSdpDatabase *theDb = BuildUpf4DbL();
+	theDb->EncodeDbL();
+
+	test.Next(_L("Print encoded attributes"));
+	PrintDb(*theDb, *test.Console());
+
+	delete theDb;
+	test.End();
+	}
+
+// test the access routines.
+void ShowCollected(	CSizeAccumulator* aCollector)
+{
+	__UHEAP_MARK;
+	CAttrPrintVisitor* theVisitor = new CAttrPrintVisitor(*test.Console());
+	TInt indRec, indAtt;
+	TUint leftOver;
+	TInt startSize = 0;
+	TInt nextLeft;
+	TInt nextSize;
+	TBool succ = EFalse;
+	TInt orig = aCollector->SizeLeft();
+	TInt hcount = aCollector->HandleCount();
+	test.Printf(_L("Size:%d, handles %d\n"), orig, hcount);
+	for (TInt i = 0; i<hcount; i++)
+	{
+		TSdpServRecordHandle hhand = aCollector->HandleAt(i);
+		TInt atcount = aCollector->AttrCount(i);
+		test.Printf(_L("HandleID:%x, attrib count:%d\n"), hhand, atcount);
+		for (TInt j = 0; j<atcount; j++)
+		{
+			CAttrSizeItem* atpointer = aCollector->AttributeOf(i, j);
+			test.Printf(_L("Attribute Pointer:%x\n"), atpointer);
+			test.Printf(_L("Attr:"));
+//			HexDes(atpointer->Attr()->Value().Des());
+// just in case we get a non-encoded attribute
+			theVisitor->VisitAttributeL(*atpointer->Attr());
+			theVisitor->VisitAttributeValueL(atpointer->Attr()->Value(), atpointer->Attr()->Value().Type());
+			test.Printf(_L("\n"));
+			nextSize = atpointer->Size();
+			startSize += nextSize;
+			startSize += 3;			// the header size...
+			indRec = 0;
+			indAtt = 0;
+			leftOver = 0;
+			succ = aCollector->StartAt(startSize, leftOver, indRec, indAtt);
+			if (succ)
+			{
+				nextLeft = aCollector->SizeLeft();
+				test.Printf(_L("updated start point by (%d+3) from %d to %d\n"), nextSize, orig, nextLeft);
+				test.Printf(_L("indices are L:%d, R:%d, A:%d\n"),leftOver, indRec, indAtt);
+				orig = nextLeft;
+			}
+			else
+				test.Printf(_L("failed to update start point by %d from %d\n"), nextSize, orig);
+
+
+		}
+	}
+	delete theVisitor;
+	__UHEAP_MARKEND;
+	test.Getch();
+}
+
+void Test8()
+	{
+	__UHEAP_MARK;
+	test.Start(_L("Test 8 -- Size visitor"));
+	CSdpDatabase *theDb = BuildUpf4DbL();
+	theDb->EncodeDbL();
+
+//	test.Next(_L("Testing sizes of records"));
+	CSdpAttrIdMatchList *theAttrList = CSdpAttrIdMatchList::NewL();
+
+	theAttrList->AddL(TAttrRange(4)); // protocol descriptor list
+
+	theAttrList->AddL(TAttrRange(50, 300)); // mostly text based stuff
+
+	CSdpSearchPattern* thePattern = CSdpSearchPattern::NewL();
+//Service pattern with one UUID in it...
+	thePattern->AddL(TUUID(TUint16(0x1103)));
+	CSizeAccumulator* collector = CSizeAccumulator::NewL();
+	test.Next(_L("Testing for UUID 1103\n"));
+	CResponseSizeVisitor::SizeRespSSL(*theDb, *thePattern, *collector);
+	ShowCollected(collector);
+// Iterate thru records in Db for SizeRespARL
+	test.Next(_L("Testing for attr 4, 50-300\n"));
+	for(TServRecordIter recIter(theDb->RecordIter()); recIter; recIter++)
+		{
+		test.Printf(_L("\n...Sizing Record 0x%x\n"), (*recIter).Handle());
+		delete collector;
+		collector = CSizeAccumulator::NewL();
+		CResponseSizeVisitor::SizeRespARL((*recIter), *theAttrList, *collector); // what does it do if the collectors been used ?
+		ShowCollected(collector);
+		}
+//
+	test.Next(_L("Testing for attr 100\n"));
+	delete theAttrList;
+	theAttrList = CSdpAttrIdMatchList::NewL();
+	theAttrList->AddL(TAttrRange(0x0100)); // names
+	delete thePattern;
+	thePattern = CSdpSearchPattern::NewL();
+//Service pattern with one UUID in it...
+	thePattern->AddL(TUUID(TUint16(0x1002)));
+	delete collector;
+	collector = CSizeAccumulator::NewL();
+	CResponseSizeVisitor::SizeRespSAL(*theDb, *thePattern, *theAttrList, *collector);
+	ShowCollected(collector);
+	delete collector;
+	delete theAttrList;
+	delete thePattern;
+	delete theDb;
+	__UHEAP_MARKEND;
+	test.End();
+	}
+
+
+void Test9(TInt flag)
+	{
+	CSdpDatabase *theDb;
+	__UHEAP_MARK;
+	TChar c = 'c';
+	if(!flag)
+		{
+		c = test.Getch();
+		switch (c)
+			{
+		case 'A': case 'a':
+			test.Start(_L("Test 9 -- \"Rhubarb\" Continuation"));
+			//FIXME: TRAPD?
+			theDb = BuildContinuationDbL();
+			break;
+		case 'B': case 'b':
+			test.Start(_L("Test 9 -- Continuation with Nested Lists"));
+			//FIXME: TRAPD?
+			theDb = BuildNestedListDbL();
+			break;
+		default:
+		return;
+			}
+		}
+	else
+		{
+		test.Start(_L("Test 9 -- Prequal Database"));
+		//FIXME: TRAPD?
+		theDb = BuildPrequalDbL();
+		}
+
+	test(theDb!=NULL);
+	CleanupStack::PushL(theDb);
+	TServRecordIter recIter(theDb->RecordIter());
+	TServAttrIter attrIter((*recIter).AttributeIter());
+	TServAttrIter attrIter2((*recIter).AttributeIter());
+	for(; recIter; recIter++)
+		{// Iterate thru records in Db
+		attrIter = (*recIter).AttributeIter();
+		for(; attrIter; attrIter++)
+			{// Iterate thru attributes in record
+			if((*attrIter).Value().Type()==ETypeString)
+				{
+				TPtrC8 ptr((*attrIter).Value().Des());
+				if(ptr.Length()<0x100)
+					{
+					attrIter2 = attrIter;
+					}
+				}
+			}
+		}
+	if((*attrIter2).Value().Type()==ETypeString)
+		{
+		TPtrC8 ptr1((*attrIter2).Value().Des());
+		TBuf16<0x100> ptr(0);
+		for(TInt i = 0;i<ptr1.Length()&&i<(ptr.MaxLength()-3);++i)
+			ptr.Append(ptr1[i]);
+		if(c=='a'||c=='A')
+			{
+			test.Printf(_L("Id: %d\n"),(*attrIter2).AttributeID());
+			test.Printf(_L("String length: %d\n"),ptr.Length());
+			if(ptr.Length()<0x100)
+				test.Printf(_L("%s\n"),&ptr[0]);
+			}
+		}
+
+	RSdp sdp;
+	RSdpDatabase db;
+	TInt ret;
+	LoadLDD_PDD();
+
+	test.Next(_L("Opening SDP Database"));
+	ret = sdp.Connect();
+	if(ret!=KErrNone)
+		{
+		if(ret==KErrNotFound)
+			test.Printf(_L("Cannot start sdp server, could not find bluetooth.\n"));
+		else
+			test.Printf(_L("Cannot start sdp server.\n"));
+		test.Next(_L("PRESS ANY KEY.\n"));
+		test.Getch();
+
+		CleanupStack::PopAndDestroy(); // theDb
+		goto end;
+		}
+	test(ret==KErrNone);
+	CleanupClosePushL(sdp);
+	ret = db.Open(sdp);
+	test(ret==KErrNone);
+	CleanupClosePushL(db);
+
+	test.Next(_L("Storing database"));
+	RegisterDatabaseInServerL(db, *theDb);
+
+	test.Next(_L("Database stored. Now run your tests!"));
+	test.Next(_L("Press any key to close SDDB"));
+	test.Getch();
+
+	CleanupStack::PopAndDestroy(3); // db, sdp, theDb
+end:
+	__UHEAP_MARKEND;
+	test.End();
+	}
+
+void Test10()
+{
+	__UHEAP_MARK;
+//TUint32
+	TInt64 putVal32 = static_cast<TInt64>(0xBA1EFACE);
+	TPckgBuf<TUint32> value32Packaged;	
+	SdpUtil::PutUint(&value32Packaged[0], putVal32, 4);
+	
+	TUint32 getVal32= SdpUtil::GetUint(value32Packaged);
+	test.Printf(_L("SdpUtil: TPckgBuf<TUint32> created with 0x%08lx would return 0x%x\n"), putVal32, getVal32);
+
+
+	TBuf8<32/8> testValue32Packaged;
+	testValue32Packaged.SetLength(4);
+	testValue32Packaged = value32Packaged;
+	
+	CSdpAttrValue* attrVal = 0;	
+	attrVal = CSdpAttrValueUint::NewUintL(testValue32Packaged);
+	TUint getter = attrVal->Uint();
+	delete attrVal;
+	
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%08lx returns 0x%x\n"), putVal32, getter);
+	
+	
+// Now we have confirmed that exercising SdpUtil this way is equivalent to using CSdpAttrValueUint's methods.
+// The CSdpAttrValueUint::Uint64 and CSdpAttrValueUint::Uint128 methods are now exported so we can test them, 
+// but they use SdpUtil too, so..
+	
+//TUint64
+//	TPckgBuf<TUint64> putVal64Packaged =0x1234FACE5678ABCD;   // Use this to test the full functionality
+	TPckgBuf<TUint64> putVal64Packaged =0x1234FACE;  	// This number is acceptable to the gcc_xml compiler
+
+	TUint64 putVal64 = putVal64Packaged();
+	
+	TPckgBuf<TUint64> val64Packaged;
+	SdpUtil::PutUint64(&val64Packaged[0], putVal64);
+	
+	TUint64 getVal64;
+	SdpUtil::GetUint64(val64Packaged, getVal64);
+	
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx would return 0x%lx\n"), putVal64, getVal64);
+
+	TBuf8<64/8> testValue64Packaged;
+	testValue64Packaged.SetLength(8);
+	testValue64Packaged = val64Packaged;
+
+	CSdpAttrValue* attrVal64 = 0;	
+	attrVal64 = CSdpAttrValueUint::NewUintL(testValue64Packaged);
+	TUint size64 = attrVal64->DataSize();
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx would be %d bytes long\n"), putVal64, size64);
+
+	CSdpAttrValueUint& attrValueUint64 = static_cast<CSdpAttrValueUint&>(*attrVal64);
+	attrValueUint64.Uint64(getVal64);
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx would return 0x%lx\n"), putVal64, getVal64);
+
+	delete attrVal64;
+	
+
+//two TUint64s	
+//	TUint64 putLoVal = 0x1234FACE5678ABCD;  // Use these to test the full functionality
+//	TUint64 putHiVal = 0x3456789BA1EFACED; 
+
+	TUint64 putLoVal = 0x1234FACE; 	// These numbers are acceptable to the gcc_xml compiler
+	TUint64 putHiVal = 0xBA1EACED; 
+
+	TBuf8<128/8> putValue128Packaged;
+	putValue128Packaged.SetLength(16);
+
+	SdpUtil::PutUint128(&putValue128Packaged[0], putLoVal, putHiVal);
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx,0x%lx would be %d bytes long\n"), putHiVal, putLoVal, 16);
+
+	TUint64 getLoVal128;
+	TUint64 getHiVal128;
+	SdpUtil::GetUint128(putValue128Packaged, getLoVal128, getHiVal128);
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx,0x%lx would return 0x%lx,0x%lx\n"), putHiVal, putLoVal, getHiVal128, getLoVal128);
+
+	TBuf8<128/8> testValue128Packaged;
+	testValue128Packaged.SetLength(16);
+	testValue128Packaged = putValue128Packaged;
+
+	CSdpAttrValue* attrVal128 = 0;	
+	attrVal128 = CSdpAttrValueUint::NewUintL(testValue128Packaged);
+	TUint size128 = attrVal128->DataSize();
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx,0x%lx would be %d bytes long\n"), putHiVal, putLoVal, size128);
+
+	CSdpAttrValueUint& attrValueUint128 = static_cast<CSdpAttrValueUint&>(*attrVal128);
+	attrValueUint128.Uint128(getLoVal128, getHiVal128);
+	test.Printf(_L("SdpUtil: CSdpAttrValueUint created with 0x%lx,0x%lx would return 0x%lx,0x%lx\n"), putHiVal, putLoVal, getHiVal128, getLoVal128);
+
+	delete attrVal128;
+
+	__UHEAP_MARKEND;
+	
+}
+
+void IntConversionTest()
+/**
+	Checks compiler has done uint-int cast correctly
+	in CSdpAttrValueInt::Int().
+**/
+	{
+	TBuf8<4> tstr;
+	tstr.FillZ(4);
+	tstr[0] = 0xff;
+	tstr[1] = 0xff;
+	tstr[2] = 0xff;
+	tstr[3] = 0xff;
+	TInt ret = 0;
+	CSdpAttrValueInt* avi = 0;
+	avi = CSdpAttrValueInt::NewIntL(tstr);
+	ret = avi->Int();
+	delete avi;
+	avi = 0;
+	__ASSERT_DEBUG(ret==-1, User::Panic(_L("Bad4ByteIntConversion"), KErrGeneral));
+	tstr.SetLength(2);
+	avi = CSdpAttrValueInt::NewIntL(tstr);
+	ret = avi->Int();
+	delete avi;
+	avi = 0;
+	__ASSERT_DEBUG(ret==-1, User::Panic(_L("Bad2ByteIntConversion"), KErrGeneral));
+	//tstr[0] = 0x0e;
+	tstr.SetLength(1);
+	avi = CSdpAttrValueInt::NewIntL(tstr);
+	ret = avi->Int();
+	delete avi;
+	avi = 0;
+	__ASSERT_DEBUG(ret==-1, User::Panic(_L("BadByteIntConversion"), KErrGeneral));
+
+	(void)(ret != 0); // keep compiler happy by referencing ret as an r-value in urel
+
+	return;
+	}
+
+void RunAppL()
+	{
+//	TInt ret;
+	test.Title();
+	test.Start(_L("Running SDP server tests"));
+// For some reason, you have to do the following to
+// ensure that the file server behaves properly.
+	RFs fs;
+	(void)fs.Connect();
+	fs.Close();
+// Run through tests
+	IntConversionTest();
+	FOREVER
+		{
+		test.Printf(_L("Choose the test to run...\n"));
+		test.Printf(_L("************************\n"));
+		test.Printf(_L("0. Run client/server\n"));
+		test.Printf(_L("1. Run client/server building the John Pagonis database\n"));
+		test.Printf(_L("2. Build static DB & print\n"));
+		test.Printf(_L("3. Build static DB & copy it over into the SDP database server\n"));
+		test.Printf(_L("4. Service Search (no continuation)\n"));
+		test.Printf(_L("5. Attribute Request (no continuation)\n"));
+		test.Printf(_L("6. Sizing and encoding stuff\n"));
+		test.Printf(_L("7. encoded database\n"));
+		test.Printf(_L("8. size visitor\n"));
+		test.Printf(_L("9a.(Press keys SLOWLY) Build \"Rhubarb\" continuation database\n"));
+		test.Printf(_L("9b.(Press keys SLOWLY) Build nested lists continuation database\n"));
+		test.Printf(_L("B. Run UPF back to back tests\n"));
+		test.Printf(_L("C. Continuation stress tests\n"));
+//		test.Printf(_L("U. Unplugfest tests\n"));
+		test.Printf(_L("P. Prequal tests database\n"));
+		test.Printf(_L("Q. SdpUtil tests\n"));
+		test.Printf(_L("\n"));
+		test.Printf(_L("A. Run All tests\n"));
+		test.Printf(_L("************************\n"));
+		test.Printf(_L("press Escape to quit\n\n"));
+
+		__UHEAP_MARK;
+		TChar c = test.Getch();
+		switch (c)
+			{
+		case 'A': case 'a':
+			Test1();
+			__UHEAP_CHECK(0);
+			Test2();
+			__UHEAP_CHECK(0);
+			Test3();
+			__UHEAP_CHECK(0);
+			Test4();
+			__UHEAP_CHECK(0);
+			Test5();
+			__UHEAP_CHECK(0);
+			Test6();
+			__UHEAP_CHECK(0);
+			break;
+		case '0':
+			Test0();
+			break;
+		case '1':
+			WhichTest();
+			break;
+		case '2':
+			Test2();
+			break;
+		case '3':
+			Test3();
+			break;
+		case '4':
+			Test4();
+			break;
+		case '5':
+			Test5();
+			break;
+		case '6':
+			Test6();
+			break;
+		case '7':
+			Test7();
+			break;
+		case '8':
+			Test8();
+			break;
+		case '9':
+			Test9(0);
+			break;
+		case 'B': case 'b':
+			TestBL(test);
+			break;
+		case 'C': case 'c':
+			__UHEAP_MARK;
+			TestCL(test, BuildContinuationDbL());
+			__UHEAP_MARKEND;
+			break;
+		case 'D': case 'd':
+			TestD();
+			break;
+		case 'E': case 'e':
+			TestE();
+			break;
+		case 'P': case 'p':
+			Test9(1);
+			break;
+		case 'Q': case 'q':
+			Test10();
+			break;
+
+		case EKeyEscape:
+			goto done;
+		default:
+			test.Printf(_L("Unknown command\n"));
+			};
+		__UHEAP_MARKEND;
+		}
+
+done:
+
+	test.Printf(_L("Finished! Press any key...\r\n"));
+	test.Getch();
+	test.End();
+	}
+
+
+TInt E32Main()
+	{
+
+	test.SetLogged(ETrue);
+	test.Title();
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	TRAPD(error,RunAppL()); // Run the App
+	__ASSERT_ALWAYS(error==KErrNone,User::Panic(_L("EPOC32EX"),error));
+	delete cleanup;
+	__UHEAP_MARKEND;
+	test.Close();
+	return KErrNone;
+	}