sl@0: /* sl@0: * Copyright (c) 1999-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * TPARSE.CPP sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include "T_parse.h" sl@0: #include "T_PARSE_for_TEF.h" sl@0: sl@0: LOCAL_D CTestStep *pTestStep = NULL; sl@0: #define test(cond) \ sl@0: { \ sl@0: TBool __bb = (cond); \ sl@0: pTestStep->TEST(__bb); \ sl@0: if (!__bb) \ sl@0: { \ sl@0: pTestStep->ERR_PRINTF1(_L("ERROR: Test Failed")); \ sl@0: User::Leave(1); \ sl@0: } \ sl@0: } sl@0: #undef INFO_PRINTF1 sl@0: #undef INFO_PRINTF2 sl@0: #undef INFO_PRINTF3 sl@0: // copy from tefexportconst.h sl@0: #define INFO_PRINTF1(p1) pTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1)) sl@0: #define INFO_PRINTF2(p1, p2) pTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2)) sl@0: #define INFO_PRINTF3(p1, p2, p3) pTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2), (p3)) sl@0: sl@0: sl@0: LOCAL_D CTrapCleanup* TrapCleanup; sl@0: LOCAL_D const TInt KTestCleanupStack=0x200; sl@0: sl@0: sl@0: CTestParser* CTestParser::NewL() sl@0: { sl@0: CTestParser* self = new (ELeave) CTestParser; sl@0: CleanupStack::PushL(self); sl@0: self->iDoItText = HBufC::NewL(128); sl@0: *(self->iDoItText) = _L("Or is it just undead?"); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CTestParser::CTestParser() sl@0: { sl@0: } sl@0: sl@0: sl@0: CTestParser::~CTestParser() sl@0: { sl@0: delete iDoItText; sl@0: } sl@0: sl@0: sl@0: TBool CTestParser::ParseThisText(const CRichText& aTextObj, TBool aAllowBack, sl@0: TInt aStartScan, TInt aScanLength, sl@0: TInt& aStartTag, TInt& aTagLength) sl@0: { sl@0: // Very simple - looking for the phrase "the world" sl@0: _LIT(targetText, "TARGET"); sl@0: TInt length = 6; sl@0: // Consider that the start of the scan may be part way through sl@0: // the item that we are looking for, so see if we need to move back sl@0: TInt start = aStartScan; sl@0: if (aAllowBack) sl@0: { sl@0: if (start >= length - 1) sl@0: start -= length - 1; sl@0: else sl@0: start = 0; sl@0: } sl@0: // And it might go beyond the end of the scan sl@0: TInt end = aStartScan + aScanLength; sl@0: if (end + length - 1 <= aTextObj.DocumentLength()) sl@0: end += length - 1; sl@0: else sl@0: end = aTextObj.DocumentLength(); sl@0: while (end - start >= length) sl@0: { sl@0: TPtrC buffer = aTextObj.Read(start, end - start); sl@0: TInt segmentLength= buffer.Length(); sl@0: sl@0: if (segmentLength >= length) // There's enough text to bother searching sl@0: { sl@0: TInt result = buffer.FindF(targetText); sl@0: if (result != KErrNotFound) // We found it sl@0: { sl@0: aStartTag = start + result; sl@0: aTagLength = length; sl@0: return ETrue; sl@0: } sl@0: } sl@0: if (end == start + segmentLength) // There's no more text at all sl@0: break; sl@0: // The buffer is segmented and there's another segment sl@0: sl@0: // It could be over the segment boundary sl@0: TInt start2 = start + segmentLength; sl@0: TInt end2 = start2; sl@0: if (segmentLength >= length - 1) sl@0: start2 -= length - 1; sl@0: else start2 = start; sl@0: if (end >= end2 + length - 1) sl@0: end2 += length -1; sl@0: else sl@0: end2 = end; sl@0: if (end2 - start2 >= length) sl@0: { sl@0: // Create a buffer with the end of one and the start of the other sl@0: TBuf<10> bridgeBuffer; sl@0: aTextObj.Extract(bridgeBuffer, start2, end2 - start2); sl@0: TInt result = bridgeBuffer.FindF(targetText); sl@0: if (result != KErrNotFound) // We found it sl@0: { sl@0: aStartTag = start2 + result; sl@0: aTagLength = length; sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: // Move start up for next segment sl@0: start += segmentLength; sl@0: } sl@0: return EFalse; // Not enough text left in buffer sl@0: } sl@0: sl@0: sl@0: const TDesC& CTestParser::CreateDoItText(const CRichText& /* aTextObj */, sl@0: TInt /* aStartText */, TInt /* aLength */) sl@0: { sl@0: return *iDoItText; sl@0: } sl@0: sl@0: sl@0: void CTestParser::ActivateThisTextL(const CRichText& /* aTextObj */, sl@0: TInt /* aStartText */, TInt /* aLength */) sl@0: { sl@0: // Do something? sl@0: sl@0: } sl@0: sl@0: sl@0: void CTestParser::GetRecogniseFormat(TCharFormat& aFormat) sl@0: { sl@0: aFormat.iFontPresentation.iTextColor = KRgbRed; sl@0: aFormat.iFontPresentation.iUnderline = EUnderlineOn; sl@0: } sl@0: sl@0: sl@0: void CTestParser::GetRolloverFormat(TCharFormat& aFormat) sl@0: { sl@0: aFormat.iFontPresentation.iTextColor = KRgbRed; sl@0: aFormat.iFontPresentation.iUnderline = EUnderlineOn; sl@0: aFormat.iFontPresentation.iHighlightColor = KRgbDarkRed; sl@0: aFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightRounded; sl@0: } sl@0: sl@0: sl@0: void CTestParser::Release() sl@0: { sl@0: delete this; sl@0: } sl@0: sl@0: //-------------------------------------------- sl@0: sl@0: CTestParser2* CTestParser2::NewL() sl@0: { sl@0: CTestParser2* self = new (ELeave) CTestParser2; sl@0: CleanupStack::PushL(self); sl@0: self->iDoItText = HBufC::NewL(128); sl@0: *(self->iDoItText) = _L("Or is it just undead?"); sl@0: CleanupStack::Pop(); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CTestParser2::CTestParser2() sl@0: { sl@0: } sl@0: sl@0: sl@0: CTestParser2::~CTestParser2() sl@0: { sl@0: delete iDoItText; sl@0: } sl@0: sl@0: sl@0: TBool CTestParser2::ParseThisText(const CRichText& aTextObj, TBool aAllowBack, sl@0: TInt aStartScan, TInt aScanLength, sl@0: TInt& aStartTag, TInt& aTagLength) sl@0: { sl@0: // Very simple - looking for the phrase "ARG" sl@0: _LIT(targetText, "ARG"); sl@0: TInt length = 3; sl@0: // Consider that the start of the scan may be part way through sl@0: // the item that we are looking for, so see if we need to move back sl@0: TInt start = aStartScan; sl@0: if (aAllowBack) sl@0: { sl@0: if (start >= length - 1) sl@0: start -= length - 1; sl@0: else sl@0: start = 0; sl@0: } sl@0: // And it might go beyond the end of the scan sl@0: TInt end = aStartScan + aScanLength; sl@0: if (end + length - 1 <= aTextObj.DocumentLength()) sl@0: end += length - 1; sl@0: else sl@0: end = aTextObj.DocumentLength(); sl@0: while (end - start >= length) sl@0: { sl@0: TPtrC buffer = aTextObj.Read(start, end - start); sl@0: TInt segmentLength= buffer.Length(); sl@0: sl@0: if (segmentLength >= length) // There's enough text to bother searching sl@0: { sl@0: TInt result = buffer.FindF(targetText); sl@0: if (result != KErrNotFound) // We found it sl@0: { sl@0: aStartTag = start + result; sl@0: aTagLength = length; sl@0: return ETrue; sl@0: } sl@0: } sl@0: if (end == start + segmentLength) // There's no more text at all sl@0: break; sl@0: // The buffer is segmented and there's another segment sl@0: sl@0: // It could be over the segment boundary sl@0: TInt start2 = start + segmentLength; sl@0: TInt end2 = start2; sl@0: if (segmentLength >= length - 1) sl@0: start2 -= length - 1; sl@0: else start2 = start; sl@0: if (end >= end2 + length - 1) sl@0: end2 += length -1; sl@0: else sl@0: end2 = end; sl@0: if (end2 - start2 >= length) sl@0: { sl@0: // Create a buffer with the end of one and the start of the other sl@0: TBuf<10> bridgeBuffer; sl@0: aTextObj.Extract(bridgeBuffer, start2, end2 - start2); sl@0: TInt result = bridgeBuffer.FindF(targetText); sl@0: if (result != KErrNotFound) // We found it sl@0: { sl@0: aStartTag = start2 + result; sl@0: aTagLength = length; sl@0: return ETrue; sl@0: } sl@0: } sl@0: sl@0: // Move start up for next segment sl@0: start += segmentLength; sl@0: } sl@0: return EFalse; // Not enough text left in buffer sl@0: } sl@0: sl@0: sl@0: const TDesC& CTestParser2::CreateDoItText(const CRichText& /* aTextObj */, sl@0: TInt /* aStartText */, TInt /* aLength */) sl@0: { sl@0: return *iDoItText; sl@0: } sl@0: sl@0: sl@0: void CTestParser2::ActivateThisTextL(const CRichText& /* aTextObj */, sl@0: TInt /* aStartText */, TInt /* aLength */) sl@0: { sl@0: // Do something? sl@0: sl@0: } sl@0: sl@0: sl@0: void CTestParser2::GetRecogniseFormat(TCharFormat& aFormat) sl@0: { sl@0: aFormat.iFontPresentation.iTextColor = KRgbRed; sl@0: aFormat.iFontPresentation.iUnderline = EUnderlineOn; sl@0: } sl@0: sl@0: sl@0: void CTestParser2::GetRolloverFormat(TCharFormat& aFormat) sl@0: { sl@0: aFormat.iFontPresentation.iTextColor = KRgbRed; sl@0: aFormat.iFontPresentation.iUnderline = EUnderlineOn; sl@0: aFormat.iFontPresentation.iHighlightColor = KRgbDarkRed; sl@0: aFormat.iFontPresentation.iHighlightStyle = TFontPresentation::EFontHighlightRounded; sl@0: } sl@0: sl@0: sl@0: void CTestParser2::Release() sl@0: { sl@0: delete this; sl@0: } sl@0: sl@0: sl@0: //-------------------------------------------- sl@0: sl@0: sl@0: CEditObserver::CEditObserver() sl@0: { sl@0: iStart = 0; sl@0: iExtent = 0; sl@0: } sl@0: sl@0: sl@0: CEditObserver::~CEditObserver() sl@0: { sl@0: } sl@0: sl@0: sl@0: void CEditObserver::EditObserver(TInt aStart, TInt aExtent) sl@0: { sl@0: iStart = aStart; sl@0: iExtent = aExtent; sl@0: } sl@0: sl@0: sl@0: void Test1() sl@0: { sl@0: INFO_PRINTF1(_L("Install 5, deinstall in reverse order")); sl@0: CTestParser* parser1 = CTestParser::NewL(); sl@0: CTestParser* parser2 = CTestParser::NewL(); sl@0: CTestParser* parser3 = CTestParser::NewL(); sl@0: CTestParser* parser4 = CTestParser::NewL(); sl@0: CTestParser* parser5 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser1); // List 1 sl@0: CRichText::ActivateParserL(parser2); // List 1, 2 sl@0: CRichText::ActivateParserL(parser3); // List 1, 2, 3 sl@0: CRichText::ActivateParserL(parser4); // List 1, 2, 3, 4 sl@0: CRichText::ActivateParserL(parser5); // List 1, 2, 3, 4, 5 sl@0: CRichText::DeactivateParser(parser5); // List 1, 2, 3, 4 sl@0: CRichText::DeactivateParser(parser4); // List 1, 2, 3 sl@0: CRichText::DeactivateParser(parser3); // List 1, 2 sl@0: CRichText::DeactivateParser(parser2); // List 1 sl@0: CRichText::DeactivateParser(parser1); // List empty sl@0: delete parser5; sl@0: delete parser4; sl@0: delete parser3; sl@0: delete parser2; sl@0: delete parser1; sl@0: CRichText::DeactivateParserDefaults(); sl@0: } sl@0: sl@0: sl@0: void Test2() sl@0: { sl@0: INFO_PRINTF1(_L("Install, deinstall in interleaved order")); sl@0: CTestParser* parser1 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser1); // List 1 sl@0: CTestParser* parser2 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser2); // List 1, 2 sl@0: // Remove first in list sl@0: CRichText::DeactivateParser(parser1); // List 2 sl@0: delete parser1; sl@0: CTestParser* parser3 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser3); // List 2, 3 sl@0: // Remove last in list sl@0: CRichText::DeactivateParser(parser3); // List 2 sl@0: delete parser3; sl@0: CTestParser* parser4 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser4); // List 2, 4 sl@0: CTestParser* parser5 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser5); // List 2, 4, 5 sl@0: // Remove middle in list sl@0: CRichText::DeactivateParser(parser4); // List 2, 5 sl@0: delete parser4; sl@0: // Empty list sl@0: CRichText::DeactivateParser(parser5); // List 2 sl@0: delete parser5; sl@0: CRichText::DeactivateParser(parser2); // List empty sl@0: delete parser2; sl@0: CRichText::DeactivateParserDefaults(); sl@0: } sl@0: sl@0: sl@0: void Test3() sl@0: { sl@0: INFO_PRINTF1(_L("Testing memory with OOM")); sl@0: sl@0: TInt i; sl@0: TInt ret; sl@0: TInt count = 0; sl@0: TInt success = 0; sl@0: sl@0: for (i = 0; i < 20; i++) sl@0: { sl@0: CTestParser* parser1 = NULL; sl@0: CTestParser* parser2 = NULL; sl@0: CTestParser* parser3 = NULL; sl@0: CTestParser* parser4 = NULL; sl@0: CTestParser* parser5 = NULL; sl@0: // Switch on memory problems, varying fail rate from 20 to 1 sl@0: __UHEAP_SETFAIL(RHeap::EDeterministic, 20 - i); sl@0: __UHEAP_MARK; sl@0: count++; sl@0: TRAP(ret, parser1 = CTestParser::NewL()); sl@0: if (ret != KErrNone) sl@0: { sl@0: parser1 = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret, CRichText::ActivateParserL(parser1)); sl@0: if (ret != KErrNone) sl@0: { sl@0: delete parser1; sl@0: parser1 = NULL; sl@0: } sl@0: } sl@0: TRAP(ret, parser2 = CTestParser::NewL()); sl@0: if (ret != KErrNone) sl@0: { sl@0: parser2 = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret, CRichText::ActivateParserL(parser2)); sl@0: if (ret != KErrNone) sl@0: { sl@0: delete parser2; sl@0: parser2 = NULL; sl@0: } sl@0: } sl@0: TRAP(ret, parser3 = CTestParser::NewL()); sl@0: if (ret != KErrNone) sl@0: { sl@0: parser3 = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret, CRichText::ActivateParserL(parser3)); sl@0: if (ret != KErrNone) sl@0: { sl@0: delete parser3; sl@0: parser3 = NULL; sl@0: } sl@0: } sl@0: TRAP(ret, parser4 = CTestParser::NewL()); sl@0: if (ret != KErrNone) sl@0: { sl@0: parser4 = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret, CRichText::ActivateParserL(parser4)); sl@0: if (ret != KErrNone) sl@0: { sl@0: delete parser4; sl@0: parser4 = NULL; sl@0: } sl@0: } sl@0: TRAP(ret, parser5 = CTestParser::NewL()); sl@0: if (ret != KErrNone) sl@0: { sl@0: parser5 = NULL; sl@0: } sl@0: else sl@0: { sl@0: TRAP(ret, CRichText::ActivateParserL(parser5)); sl@0: if (ret != KErrNone) sl@0: { sl@0: delete parser5; sl@0: parser5 = NULL; sl@0: } sl@0: } sl@0: if (parser1) sl@0: { sl@0: success++; sl@0: CRichText::DeactivateParser(parser1); sl@0: delete parser1; sl@0: } sl@0: if (parser2) sl@0: { sl@0: success++; sl@0: CRichText::DeactivateParser(parser2); sl@0: delete parser2; sl@0: } sl@0: if (parser3) sl@0: { sl@0: success++; sl@0: CRichText::DeactivateParser(parser3); sl@0: delete parser3; sl@0: } sl@0: if (parser4) sl@0: { sl@0: success++; sl@0: CRichText::DeactivateParser(parser4); sl@0: delete parser4; sl@0: } sl@0: if (parser5) sl@0: { sl@0: success++; sl@0: CRichText::DeactivateParser(parser5); sl@0: delete parser5; sl@0: } sl@0: CRichText::DeactivateParserDefaults(); sl@0: // Switch off memory problems sl@0: __UHEAP_MARKEND; sl@0: __UHEAP_RESET; sl@0: } sl@0: sl@0: INFO_PRINTF3(_L("%d attempted activations, %d successful\n"), 5 * count, success); sl@0: } sl@0: sl@0: sl@0: void Test4() sl@0: { sl@0: // Create a block of 1000 chars sl@0: // Randomly insert a target string and check: sl@0: // - Can't find target that is not complete sl@0: // - Does find complete target in right place sl@0: // - Once target is removed, can't find it sl@0: // repeat x 100 sl@0: INFO_PRINTF1(_L("Testing EText behaviour with active parsers and single target")); sl@0: // Create and activate a parser sl@0: CTestParser* parser1 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser1); sl@0: // Create a CRichText sl@0: CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL(); sl@0: CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL(); sl@0: CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity); sl@0: richText->SetPictureFactory(NULL, NULL); // forces index generation sl@0: // Switch on parsers for this CRichText sl@0: CEditObserver* editObserver = new (ELeave) CEditObserver; sl@0: richText->SetEditObserver(editObserver); sl@0: sl@0: // Insert 1000 chars (repeated string) sl@0: TInt i; sl@0: for (i = 0; i < 100; i++) sl@0: richText->InsertL(richText->DocumentLength(), _L("abcdefghij")); sl@0: TInt64 seed = 314159; sl@0: TInt startTags; sl@0: TInt lengthTags; sl@0: for (i = 0; i < 100; i++) sl@0: { sl@0: #if 0 sl@0: INFO_PRINTF2(_L("i=%d"), i); sl@0: #endif sl@0: // Get a random in range 0-999 sl@0: TInt random = Math::Rand(seed) % 1000; sl@0: // "Randomly" insert target string that is not complete sl@0: richText->InsertL(random, _L("TARGE")); sl@0: test(!richText->ParseText(startTags, lengthTags, EFalse)); sl@0: test(!richText->ParseText(startTags, lengthTags, ETrue)); sl@0: // Complete target string and check we find single target where we expect sl@0: richText->InsertL(random + 5, 'T'); sl@0: #if 1 sl@0: test(richText->ParseText(startTags, lengthTags, EFalse)); sl@0: #else sl@0: TBool b = richText->ParseText(startTags, lengthTags, EFalse); sl@0: INFO_PRINTF2(_L(" b=%d"), b); sl@0: test(b); sl@0: #endif sl@0: test((startTags == random) && (lengthTags == 6)); sl@0: test(richText->ParseText(startTags, lengthTags, ETrue)); sl@0: test((startTags == random) && (lengthTags == 6)); sl@0: // Completely remove target string sl@0: richText->DeleteL(random, 6); sl@0: test(!richText->ParseText(startTags, lengthTags, EFalse)); sl@0: test(!richText->ParseText(startTags, lengthTags, ETrue)); sl@0: } sl@0: sl@0: // Clean up sl@0: sl@0: delete richText; sl@0: delete GlobalCharFormatLayer; sl@0: delete GlobalParaFormatLayer; sl@0: CRichText::DeactivateParser(parser1); sl@0: delete parser1; sl@0: CRichText::DeactivateParserDefaults(); sl@0: delete editObserver; sl@0: } sl@0: sl@0: sl@0: void Test5() sl@0: { sl@0: // Create a block of 1000 chars sl@0: // Randomly insert two target strings and check: sl@0: // - Can't find targets that are not complete sl@0: // - Does find complete targets with exact range covered sl@0: // - Once targets are removed, can't find it sl@0: // repeat x 100 sl@0: INFO_PRINTF1(_L("Testing EText behaviour with active parsers and double target")); sl@0: // Create and activate a parser sl@0: CTestParser* parser1 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser1); sl@0: // Create a CRichText sl@0: CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL(); sl@0: CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL(); sl@0: CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity); sl@0: richText->SetPictureFactory(NULL, NULL); // forces index generation sl@0: // Switch on parsers for this CRichText sl@0: CEditObserver* editObserver = new (ELeave) CEditObserver; sl@0: richText->SetEditObserver(editObserver); sl@0: sl@0: // Insert 1000 chars (repeated string) sl@0: TInt i; sl@0: for (i = 0; i < 100; i++) sl@0: richText->InsertL(richText->DocumentLength(), _L("abcdefghij")); sl@0: TInt64 seed1 = 314159; sl@0: TInt startTags; sl@0: TInt lengthTags; sl@0: for (i = 0; i < 100; i++) sl@0: { sl@0: #if 0 sl@0: INFO_PRINTF2(_L("i=%d"), i); sl@0: #endif sl@0: // Get a random in range 0-999 sl@0: TInt random1 = Math::Rand(seed1) % 1000; sl@0: TInt random2 = Math::Rand(seed1) % 1000; sl@0: TInt rlow = (random1 < random2) ? random1 : random2; sl@0: TInt rhigh = (random1 > random2) ? random1 : random2; sl@0: if (rlow + 7 > rhigh) sl@0: { // Too close, spread them out sl@0: if (rhigh + 7 <= richText->DocumentLength()) sl@0: rhigh += 7; sl@0: else sl@0: rlow -= 7; sl@0: } sl@0: // "Randomly" insert target strings that are not complete sl@0: richText->InsertL(rlow, _L("TARGE")); sl@0: richText->InsertL(rhigh - 1, _L("TARGE")); sl@0: test(!richText->ParseText(startTags, lengthTags, EFalse)); sl@0: test(!richText->ParseText(startTags, lengthTags, ETrue)); sl@0: // Complete target string and check we find single target where we expect sl@0: richText->InsertL(rlow + 5, 'T'); sl@0: richText->InsertL(rhigh + 5, 'T'); sl@0: #if 1 sl@0: test(richText->ParseText(startTags, lengthTags, EFalse)); sl@0: #else sl@0: TBool bb = richText->ParseText(startTags, lengthTags, EFalse); sl@0: test(bb); sl@0: #endif sl@0: test((startTags == rlow) && (lengthTags == rhigh + 6 - rlow)); sl@0: test(richText->ParseText(startTags, lengthTags, ETrue)); sl@0: test((startTags == rlow) && (lengthTags == rhigh + 6 - rlow)); sl@0: // Completely remove target string sl@0: richText->DeleteL(rhigh, 6); sl@0: richText->DeleteL(rlow, 6); sl@0: test(!richText->ParseText(startTags, lengthTags, EFalse)); sl@0: test(!richText->ParseText(startTags, lengthTags, ETrue)); sl@0: } sl@0: sl@0: // Clean up sl@0: sl@0: delete richText; sl@0: delete GlobalCharFormatLayer; sl@0: delete GlobalParaFormatLayer; sl@0: CRichText::DeactivateParser(parser1); sl@0: delete parser1; sl@0: CRichText::DeactivateParserDefaults(); sl@0: delete editObserver; sl@0: } sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-ETEXT-UT-3405 sl@0: @SYMTestCaseDesc Test for the fix for when CRichText crashes when parsers are active sl@0: @SYMTestPriority Medium sl@0: @SYMTestActions Calls PositionOfNextTag on all available document positions to validate fix. sl@0: @SYMTestExpectedResults Test must be able to call PositionOfNextTag on all document positions sl@0: @SYMDEF PDEF102494 sl@0: */ sl@0: sl@0: void Test6() sl@0: { sl@0: INFO_PRINTF1(_L(" @SYMTestCaseID:SYSLIB-ETEXT-UT-3405 Calling PositionOfNextTag on an empty document ")); sl@0: sl@0: // Create and activate a parser sl@0: CTestParser* parser1 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser1); sl@0: // Create a CRichText sl@0: CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL(); sl@0: CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL(); sl@0: CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity); sl@0: richText->SetPictureFactory(NULL, NULL); // forces index generation sl@0: // Switch on parsers for this CRichText sl@0: CEditObserver* editObserver = new (ELeave) CEditObserver; sl@0: richText->SetEditObserver(editObserver); sl@0: sl@0: //insert and format some text sl@0: richText->InsertL(richText->DocumentLength(), _L("abcdTARGET")); sl@0: sl@0: TCharFormat charFormat; sl@0: TCharFormatMask charFormatMask; sl@0: sl@0: richText->ApplyCharFormatL(charFormat, charFormatMask, 0, richText->DocumentLength()); sl@0: sl@0: TInt startTags; sl@0: TInt lengthTags; sl@0: richText->ParseText(startTags, lengthTags, ETrue); sl@0: sl@0: // Call position of next tag on all document positions sl@0: for (TInt i = 0; i <= richText->DocumentLength(); i++) sl@0: { sl@0: richText->PositionOfNextTag(i, parser1); sl@0: } sl@0: sl@0: // Clean up sl@0: sl@0: delete richText; sl@0: delete GlobalCharFormatLayer; sl@0: delete GlobalParaFormatLayer; sl@0: CRichText::DeactivateParser(parser1); sl@0: delete parser1; sl@0: CRichText::DeactivateParserDefaults(); sl@0: delete editObserver; sl@0: } sl@0: sl@0: /** sl@0: @SYMTestCaseID SYSLIB-ETEXT-UT-3406 sl@0: @SYMTestCaseDesc Test for the fix for when CRichText crashes when parsers are active sl@0: @SYMTestPriority Medium sl@0: @SYMTestActions Initialize two parsers. First parser has a target string of "TARGET", sl@0: and the second parser has a target string of "ARG". By parsing the sl@0: two overlapping (ARG is contained in TARGET) target strings, the changes sl@0: for this defect have full coverage. sl@0: @SYMTestExpectedResults Test must be able to call PositionOfNextTag on the end of document positions sl@0: @SYMDEF PDEF102494 sl@0: */ sl@0: void Test7() sl@0: { sl@0: INFO_PRINTF1(_L(" @SYMTestCaseID:SYSLIB-ETEXT-UT-3406 Testing EText behaviour with active parsers and single target ")); sl@0: sl@0: // Create and activate a parser sl@0: CTestParser* parser1 = CTestParser::NewL(); sl@0: CRichText::ActivateParserL(parser1); sl@0: CTestParser2* parser2 = CTestParser2::NewL(); sl@0: CRichText::ActivateParserL(parser2); sl@0: // Create a CRichText sl@0: CParaFormatLayer* GlobalParaFormatLayer = CParaFormatLayer::NewL(); sl@0: CCharFormatLayer* GlobalCharFormatLayer = CCharFormatLayer::NewL(); sl@0: CRichText* richText = CRichText::NewL(GlobalParaFormatLayer, GlobalCharFormatLayer, CEditableText::ESegmentedStorage, CEditableText::EDefaultTextGranularity); sl@0: richText->SetPictureFactory(NULL, NULL); // forces index generation sl@0: // Switch on parsers for this CRichText sl@0: CEditObserver* editObserver = new (ELeave) CEditObserver; sl@0: richText->SetEditObserver(editObserver); sl@0: sl@0: // Insert 1000 chars (repeated string) sl@0: TInt i; sl@0: for (i = 0; i < 100; i++) sl@0: richText->InsertL(richText->DocumentLength(), _L("abcdefghij")); sl@0: sl@0: TInt startTags; sl@0: TInt lengthTags; sl@0: TInt startPosition = 0; sl@0: sl@0: // Run test twice, once at start of string, once at end. sl@0: for (TInt i=0;i < 2;i++) sl@0: { sl@0: //Insert target string that is not complete (for code coverage purposes). sl@0: richText->InsertL(startPosition, _L("TARGE")); sl@0: // Parse range provided only. Parser two will set it's parser tags on "ARG". sl@0: test(richText->ParseText(startTags, lengthTags, EFalse)); sl@0: // Ensure this call does not fail at end of document (anymore). This gets sl@0: // the position of the next tag at the end of document position. Should sl@0: // be none found at end of document. sl@0: test((richText->PositionOfNextTag(richText->DocumentLength(), parser1)) == -1); sl@0: sl@0: // Parse all text (for coverage purposes). This will first clear all tags, sl@0: // and then re-applies the tags again on "ARG" sl@0: test(richText->ParseText(startTags, lengthTags, ETrue)); sl@0: test((richText->PositionOfNextTag(richText->DocumentLength(), parser1)) == -1); sl@0: sl@0: // Complete target string. The purpose of completing the target string sl@0: // here is for code coverage. The text has changed and the code path in sl@0: // parselst.cpp will change. sl@0: richText->InsertL(startPosition + 5, 'T'); sl@0: sl@0: // Parse range provided only. The tags on "ARG" are considered sl@0: // lower precendence, so this will clear the parser tags on "ARG" and sl@0: // will apply the parser tags on "TARGET". sl@0: test(richText->ParseText(startTags, lengthTags, EFalse)); sl@0: test((richText->PositionOfNextTag(richText->DocumentLength(), parser1)) == -1); sl@0: sl@0: // Completely remove target string sl@0: richText->DeleteL(startPosition, 6); sl@0: test(!richText->ParseText(startTags, lengthTags, EFalse)); sl@0: test(!richText->ParseText(startTags, lengthTags, ETrue)); sl@0: sl@0: startPosition = richText->DocumentLength(); sl@0: } sl@0: sl@0: // Clean up sl@0: sl@0: delete richText; sl@0: delete GlobalCharFormatLayer; sl@0: delete GlobalParaFormatLayer; sl@0: CRichText::DeactivateParser(parser1); sl@0: delete parser1; sl@0: CRichText::DeactivateParser(parser2); sl@0: delete parser2; sl@0: CRichText::DeactivateParserDefaults(); sl@0: delete editObserver; sl@0: } sl@0: sl@0: CT_PARSE::CT_PARSE() sl@0: { sl@0: SetTestStepName(KTestStep_T_PARSE); sl@0: pTestStep = this; sl@0: } sl@0: sl@0: TVerdict CT_PARSE::doTestStepL() sl@0: { sl@0: SetTestStepResult(EFail); sl@0: sl@0: TrapCleanup = CTrapCleanup::New(); sl@0: TRAPD(r,\ sl@0: {\ sl@0: for (TInt i=KTestCleanupStack;i>0;i--)\ sl@0: CleanupStack::PushL((TAny*)1);\ sl@0: test(r==KErrNone);\ sl@0: CleanupStack::Pop(KTestCleanupStack);\ sl@0: }); sl@0: sl@0: INFO_PRINTF1(_L("Testing EText parser system")); sl@0: sl@0: INFO_PRINTF1(_L("Testing memory under normal conditions")); sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret1, Test1()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret2, Test2()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret3, Test3()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret4, Test4()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret5, Test5()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret6, Test6()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: __UHEAP_MARK; sl@0: TRAPD(ret7, Test7()); sl@0: __UHEAP_MARKEND; sl@0: sl@0: delete TrapCleanup; sl@0: sl@0: if (r == KErrNone && ret1 == KErrNone && ret2 == KErrNone && ret3 == KErrNone && ret4 == KErrNone && ret5 == KErrNone && ret6 == KErrNone && ret7 == KErrNone) sl@0: { sl@0: SetTestStepResult(EPass); sl@0: } sl@0: sl@0: return TestStepResult(); sl@0: }