diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btsdp/test/tsdpdb.cpp --- /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 +#include +#include +#include +#include +#include +#include +#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 +//#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; iiMatchesFound); + 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 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; iHandleAt(i); + TInt atcount = aCollector->AttrCount(i); + test.Printf(_L("HandleID:%x, attrib count:%d\n"), hhand, atcount); + for (TInt j = 0; jAttributeOf(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(0xBA1EFACE); + TPckgBuf value32Packaged; + SdpUtil::PutUint(&value32Packaged[0], putVal32, 4); + + TUint32 getVal32= SdpUtil::GetUint(value32Packaged); + test.Printf(_L("SdpUtil: TPckgBuf 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 putVal64Packaged =0x1234FACE5678ABCD; // Use this to test the full functionality + TPckgBuf putVal64Packaged =0x1234FACE; // This number is acceptable to the gcc_xml compiler + + TUint64 putVal64 = putVal64Packaged(); + + TPckgBuf 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(*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(*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; + }