/*
* Copyright (c) 1997-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:
*
*/
#include <e32test.h>
#include "TESTFAC.H"
#include <fldset.h>
#include <flddef.h>
#define UNUSED_VAR(a) a = a
const TInt KTestCleanupStack=0x40;
LOCAL_D RTest test(_L("Testing Fields"));
LOCAL_D CTrapCleanup* TheTrapCleanup;
LOCAL_D CTextFieldSet* TheFieldSet;
LOCAL_D TTestFieldFactory* TheFactory;
LOCAL_C TBool UpdateField(TInt aPos)
{
// find out which field aPos is in
TFindFieldInfo info;
TBool inField=TheFieldSet->FindFields(info,aPos);
test(inField);
// get the new value
HBufC* buf = HBufC::NewLC(5);
TInt ret=TheFieldSet->NewFieldValueL(buf,aPos);
CleanupStack::Pop();
CleanupStack::PushL(buf);
test(ret==KErrNone);
// Notify FieldSet of update
TheFieldSet->NotifyFieldUpdate(aPos,buf->Length());
// tidy up
CleanupStack::PopAndDestroy();
return ret;
}
LOCAL_C void test1()
// Tests that all CTextFieldSet methods exist as specced
//
{
test.Next(_L("- Testing that all CTextFieldSet methods exist"));
// inform TheFieldSet about an imaginary insertion, then an imaginary deletion
TheFieldSet->NotifyInsertion(0,10); // pos=0, len=10
TheFieldSet->NotifyDeletion(2,5); // pos=2, len=5
// insert a field & get its initial value
CTextField* field = TheFieldSet->NewFieldL(KDummyFieldUid);
TInt ret = TheFieldSet->InsertFieldL(1,field,KDummyFieldUid); // pos=1
test(ret==KErrNone);
HBufC* buf = HBufC::NewLC(20); // max length 20
TheFieldSet->NewFieldValueL(buf,1); // pos=1
CleanupStack::Pop();
CleanupStack::PushL(buf);
TheFieldSet->NotifyFieldUpdate(1,buf->Length());
CleanupStack::PopAndDestroy(); // buf
// count number of fields & characters
TheFieldSet->FieldCount();
TheFieldSet->CharCount();
// find the inserted field
TheFieldSet->FindFields(0); // pos=0
TFindFieldInfo info;
TheFieldSet->FindFields(info,0,3); // pos=0, range=3
// remove the field
TheFieldSet->RemoveField(2);
// reset the field array
TheFieldSet->Reset();
}
LOCAL_C void test2()
// Tests inserting, updating and removing a field
//
{
test.Next(_L("- Testing field insertion, update and removal"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// insert a field
CTextField* field = TheFieldSet->NewFieldL(KDummyFieldUid);
TInt ret=TheFieldSet->InsertFieldL(0,field,KDummyFieldUid); // pos=0
test(ret==KErrNone);
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==1);
// get its initial value
ret=UpdateField(0);
test(ret==KErrNone);
test(TheFieldSet->CharCount()==3);
test(TheFieldSet->FieldCount()==1);
// get its value in a buffer of insufficient size
HBufC* miniBuf = HBufC::NewLC(0);
ret=TheFieldSet->NewFieldValueL(miniBuf,0); // pos=0
CleanupStack::Pop();
CleanupStack::PushL(miniBuf);
test(ret==KErrNone);
// delete part of the field & update
TheFieldSet->NotifyDeletion(1,1); // pos=1, len=1
test(TheFieldSet->CharCount()==2);
test(TheFieldSet->FieldCount()==1);
ret=UpdateField(0);
test(TheFieldSet->CharCount()==3);
test(TheFieldSet->FieldCount()==1);
// delete over a zero length
TheFieldSet->NotifyDeletion(1,0); // pos=1, len=0
test(TheFieldSet->CharCount()==3);
test(TheFieldSet->FieldCount()==1);
TFindFieldInfo info;
TBool inField=TheFieldSet->FindFields(info,0);
test(inField);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==0);
// delete all the contents of the field & update
TheFieldSet->NotifyDeletion(0,3); // pos=0, len=3
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
/* ret=UpdateField(0);
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
ret=TheFieldSet->RemoveField(0); // pos=0
test(ret);
test(TheFieldSet->CharCount()==3);
test(TheFieldSet->FieldCount()==0);
*/ // reset the field array
TheFieldSet->Reset();
CleanupStack::PopAndDestroy(); // miniBuf
}
LOCAL_C void test3()
// Tests InField() in "all" the oddball situations
//
{
TFindFieldInfo info;
test.Next(_L("- Testing InField() calls"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// Zero length doc
TBool inField=TheFieldSet->FindFields(info,0);
test(!inField);
test(info.iFieldCountInRange==0);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==0);
// Insert field (zero length) & test before
CTextField* field = TheFieldSet->NewFieldL(KDummyFieldUid);
TInt ret=TheFieldSet->InsertFieldL(0,field,KDummyFieldUid); // pos=0
test(ret==KErrNone);
inField=TheFieldSet->FindFields(info,0);
test(inField);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==0);
// Insert another field (zero length) & test before
CTextField* field2 = TheFieldSet->NewFieldL(KDummyFieldUid);
ret=TheFieldSet->InsertFieldL(0,field2,KDummyFieldUid); // pos=0
test(ret==KErrNone);
inField=TheFieldSet->FindFields(info,0);
test(inField);
test(info.iFieldCountInRange==2);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==0);
// Get the value of the first field, test before & test between them
ret=UpdateField(0);
test(ret==KErrNone);
inField=TheFieldSet->FindFields(info,0);
test(inField);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==0);
inField=TheFieldSet->FindFields(info,3);
test(inField);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==3);
// Get the value of the second field, test between them
ret=UpdateField(3);
test(ret==KErrNone);
inField=TheFieldSet->FindFields(info,3);
test(inField);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==3);
// end of doc - after field
inField=TheFieldSet->FindFields(info,6);
test(!inField);
test(info.iFieldCountInRange==0);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==0);
// In field
inField=TheFieldSet->FindFields(info,2);
test(inField);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==0);
// Other method at same pos
inField=TheFieldSet->FindFields(2);
test(inField);
// Pretend to insert some text between the fields
TheFieldSet->NotifyInsertion(3,5); // pos=3, len=5
test(TheFieldSet->CharCount()==11);
test(TheFieldSet->FieldCount()==2);
// Test in text
inField=TheFieldSet->FindFields(info,6);
test(info.iFieldCountInRange==0);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==0);
// Test from field to field over the intervening text
inField=TheFieldSet->FindFields(info,1,9);
test(info.iFieldCountInRange==2);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==0);
// Test from field 1 up to field 2
inField=TheFieldSet->FindFields(info,0,8);
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==0);
TheFieldSet->Reset();
}
LOCAL_C void test4()
// Tests Insertion and deletion of text around and into fields
//
{
TFindFieldInfo info;
test.Next(_L("- Testing insertion and deletion of text around and into fields"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// Insert some text
TheFieldSet->NotifyInsertion(0,4); // pos=0, len=4
test(TheFieldSet->CharCount()==4);
test(TheFieldSet->FieldCount()==0);
// Insert some text into the text
TheFieldSet->NotifyInsertion(2,6); // pos=2, len=6
test(TheFieldSet->CharCount()==10);
test(TheFieldSet->FieldCount()==0);
// Insert a field into the text
CTextField* field = TheFieldSet->NewFieldL(KDummyFieldUid);
TInt ret=TheFieldSet->InsertFieldL(4,field,KDummyFieldUid); // pos=4
if(ret != KErrNone && field !=NULL)
{
delete field;
field = NULL;
}
test(ret==KErrNone);
ret=UpdateField(4);
test(ret==KErrNone);
test(TheFieldSet->CharCount()==13);
test(TheFieldSet->FieldCount()==1);
// Insert some text directly before the field (check it hasn't inserted into the field)
TheFieldSet->NotifyInsertion(4,2); // pos=4, len=2
test(TheFieldSet->CharCount()==15);
test(TheFieldSet->FieldCount()==1);
TBool inField=TheFieldSet->FindFields(info,7); // pos=7
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==6);
// Insert some text directly after the field
TheFieldSet->NotifyInsertion(9,1); // pos=9, len=1
test(TheFieldSet->CharCount()==16);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,7); // pos=7
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==6);
// Insert some text into the field
TheFieldSet->NotifyInsertion(7,4); // pos=9, len=4
test(TheFieldSet->CharCount()==20);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,7); // pos=7
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==7);
test(info.iFirstFieldPos==6);
// Delete some text directly after the field
TheFieldSet->NotifyDeletion(13,1); // pos=13, len=1
test(TheFieldSet->CharCount()==19);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,9); // pos=9
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==7);
test(info.iFirstFieldPos==6);
// Delete some text before the field
TheFieldSet->NotifyDeletion(4,2); // pos=4, len=2
test(TheFieldSet->CharCount()==17);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,7); // pos=7
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==7);
test(info.iFirstFieldPos==4);
// Delete some text overlapping into the field
TheFieldSet->NotifyDeletion(1,5); // pos=1, len=5
test(TheFieldSet->CharCount()==12);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,3); // pos=3
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==5);
test(info.iFirstFieldPos==1);
// Delete some text overlapping out of the field
TheFieldSet->NotifyDeletion(3,4); // pos=3, len=4
test(TheFieldSet->CharCount()==8);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,2); // pos=2
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==2);
test(info.iFirstFieldPos==1);
// Delete all text, inc field
TheFieldSet->NotifyDeletion(0,8); // pos=0, len=8
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
//Adding some character & field at the end & then deleting all
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// Insert some text
TheFieldSet->NotifyInsertion(0,4); // pos=0, len=4
test(TheFieldSet->CharCount()==4);
test(TheFieldSet->FieldCount()==0);
// Insert some text into the text
TheFieldSet->NotifyInsertion(2,7); // pos=2, len=7
test(TheFieldSet->CharCount()==11);
test(TheFieldSet->FieldCount()==0);
//Insert field at the last position
CTextField* field1 = TheFieldSet->NewFieldL(KDummyFieldUid);
ret=TheFieldSet->InsertFieldL(5,field1,KDummyFieldUid); // pos=5
if(ret != KErrNone && field1 !=NULL)
{
delete field1;
field1 = NULL;
}
test(ret==KErrNone);
ret=UpdateField(5);
//Delete last character
TheFieldSet->NotifyDeletion(10,1); // pos=10, len=1
test(TheFieldSet->CharCount()==13);
test(TheFieldSet->FieldCount()==1);
//Insert characters at the field position so field moves to 8th pos
TheFieldSet->NotifyInsertion(5,3); // pos=5, len=3
test(TheFieldSet->CharCount()==16);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,8); // pos=8
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==3);
test(info.iFirstFieldPos==8);
//Delete last character
TheFieldSet->NotifyDeletion(15,1); // pos=15, len=1
test(TheFieldSet->CharCount()==15);
test(TheFieldSet->FieldCount()==1);
//Delete out of range character that doesnt exist..
TheFieldSet->NotifyDeletion(15,1); // pos=15, len=1
test(TheFieldSet->CharCount()==15);
test(TheFieldSet->FieldCount()==1);
//Delete all the characters after the field
TheFieldSet->NotifyDeletion(11, 4); // pos=11, len=4
test(TheFieldSet->CharCount()==11);
test(TheFieldSet->FieldCount()==1);
//Shorten the field by deleting the last character of the field
TheFieldSet->NotifyDeletion(10, 1); // pos=10, len=1
test(TheFieldSet->CharCount()==10);
test(TheFieldSet->FieldCount()==1);
inField=TheFieldSet->FindFields(info,8); // pos=0
test(info.iFieldCountInRange==1);
test(info.iFirstFieldLen==2);
test(info.iFirstFieldPos==8);
//length to be removed is one more than the existing data..DEF095911
TheFieldSet->NotifyDeletion(0,11); // pos=0, len=11
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
inField=TheFieldSet->FindFields(info,0); // pos=0
test(info.iFieldCountInRange==0);
test(info.iFirstFieldLen==0);
test(info.iFirstFieldPos==0);
// Finish up
TheFieldSet->Reset();
}
LOCAL_C void test5()
// Tests inserting, updating and removing a CDateTimeField
//
{
test.Next(_L("- Testing CDateTimeField"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// insert a field with default format
CTextField* field = TheFieldSet->NewFieldL(KDateTimeFieldUid);
TInt ret=TheFieldSet->InsertFieldL(0,field,KDateTimeFieldUid); // pos=0
test(ret==KErrNone);
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==1);
// get its initial value
ret=UpdateField(0);
test(ret==KErrNone);
test(TheFieldSet->FieldCount()==1);
// get its value and display it
HBufC* miniBuf = HBufC::NewLC(5);
ret=TheFieldSet->NewFieldValueL(miniBuf,0); // pos=0
CleanupStack::Pop();
CleanupStack::PushL(miniBuf);
test(ret==KErrNone);
TPtr buf = miniBuf->Des();
test.Printf(_L(" The field value is: "));
test.Printf(buf);
test.Printf(_L("\n"));
// reset the field array
TheFieldSet->Reset();
CleanupStack::PopAndDestroy(); // miniBuf
}
LOCAL_C void test6()
// Tests CDateTimeFields with non-default formatting
//
{
test.Next(_L("- Testing CDateTimeField with non-default formatting"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// create a field and set format
CTextField* field = TheFieldSet->NewFieldL(KDateTimeFieldUid);
((CDateTimeField*)field)->SetFormat(_L("%-A%*I%:1%T%+A")); //
// insert field
TInt ret=TheFieldSet->InsertFieldL(0,field,KDateTimeFieldUid); // pos=0
test(ret==KErrNone);
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==1);
// get its initial value
ret=UpdateField(0);
test(ret==KErrNone);
// test(TheFieldSet->CharCount()==5);
test(TheFieldSet->FieldCount()==1);
// get its value and display it
HBufC* miniBuf = HBufC::NewLC(5);
ret=TheFieldSet->NewFieldValueL(miniBuf,0); // pos=0
CleanupStack::Pop();
CleanupStack::PushL(miniBuf);
test(ret==KErrNone);
TPtr buf = miniBuf->Des();
test.Printf(_L(" The field value is: "));
test.Printf(buf);
test.Printf(_L("\n"));
// reset the field array
TheFieldSet->Reset();
CleanupStack::PopAndDestroy(); // miniBuf
}
LOCAL_C void test7()
// Tests inserting, updating and removing a CPageNumberField
//
{
test.Next(_L("- Testing CPageNumberField"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// insert a field with default format
CTextField* field = TheFieldSet->NewFieldL(KPageNumberFieldUid);
TInt ret=TheFieldSet->InsertFieldL(0,field,KPageNumberFieldUid); // pos=0
test(ret==KErrNone);
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==1);
// get its initial value
ret=UpdateField(0);
test(ret==KErrNone);
test(TheFieldSet->FieldCount()==1);
// get its value and display it
HBufC* miniBuf = HBufC::NewLC(5);
ret=TheFieldSet->NewFieldValueL(miniBuf,0); // pos=0
CleanupStack::Pop();
CleanupStack::PushL(miniBuf);
test(ret==KErrNone);
TPtr buf = miniBuf->Des();
test.Printf(_L(" The field value is: "));
test.Printf(buf);
test.Printf(_L("\n"));
// reset the field array
TheFieldSet->Reset();
CleanupStack::PopAndDestroy(); // miniBuf
}
LOCAL_C void test8()
// Tests inserting, updating and removing a CPageNumberField
//
{
test.Next(_L("- Testing CFileNameField"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
// insert a field with default format
CTextField* field = TheFieldSet->NewFieldL(KFileNameFieldUid);
TInt ret=TheFieldSet->InsertFieldL(0,field,KFileNameFieldUid); // pos=0
test(ret==KErrNone);
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==1);
// get its initial value
ret=UpdateField(0);
test(ret==KErrNone);
test(TheFieldSet->FieldCount()==1);
// get its value and display it
HBufC* miniBuf = HBufC::NewLC(5);
ret=TheFieldSet->NewFieldValueL(miniBuf,0); // pos=0
CleanupStack::Pop();
CleanupStack::PushL(miniBuf);
test(ret==KErrNone);
TPtr buf = miniBuf->Des();
test.Printf(_L(" The field value is: "));
test.Printf(buf);
test.Printf(_L("\n"));
// reset the field array
TheFieldSet->Reset();
CleanupStack::PopAndDestroy(); // miniBuf
}
/*
Added to test the fix to 'EDNHARN-4NVDHC: Text fields are not removed correctly in edwin'. Deletion
of two fields failed to delete the second one.
*/
static void test_multiple_fields()
{
test.Next(_L(" - testing multiple fields"));
test(TheFieldSet->CharCount()==0);
test(TheFieldSet->FieldCount()==0);
/*
Insert two dummy fields and some imaginary text. Dummy fields have the value 'XXX'.
If the text is represented by 'x's the text will be: "xxXXXxXXXxxxx".
*/
CTextField* field1 = TheFieldSet->NewFieldL(KDummyFieldUid);
TInt ret = TheFieldSet->InsertFieldL(0,field1,KDummyFieldUid);
test(ret == KErrNone);
test(TheFieldSet->FieldCount() == 1);
ret = UpdateField(0);
test(ret == KErrNone);
CTextField* field2 = TheFieldSet->NewFieldL(KDummyFieldUid);
ret = TheFieldSet->InsertFieldL(3,field2,KDummyFieldUid);
test(ret == KErrNone);
test(TheFieldSet->FieldCount() == 2);
ret = UpdateField(3);
test(ret == KErrNone);
TheFieldSet->NotifyInsertion(0,2);
TheFieldSet->NotifyInsertion(5,1);
TheFieldSet->NotifyInsertion(9,4);
test(TheFieldSet->CharCount() == 13);
// Delete the two fields and the character between them.
TheFieldSet->NotifyDeletion(2,7);
test(TheFieldSet->FieldCount() == 0);
test(TheFieldSet->CharCount() == 6);
TheFieldSet->Reset();
}
LOCAL_C void testFields()
// Test the fields dll.
//
{
test.Start(_L("Testing Fields"));
// instantiate the FieldSet and use the default factory
TheFactory = new(ELeave) TTestFieldFactory();
TheFieldSet = CTextFieldSet::NewL();
TheFieldSet->SetFieldFactory(TheFactory);
// the first test just checks that all methods exist (a la Duncan)
test1();
// Tests inserting, updating and removing a field
test2();
// Tests FindFields() & InField() in "all" the oddball situations
test3();
// Tests Insertion and deletion of text around and into fields
test4();
// Tests the CDateTimeField class
test5();
// Tests the CDateTimeField class with non-default formatting
test6();
// Test CPageNumberField
test7();
// Test CFileNameField
test8();
// Test multiple field insertion and deletion.
test_multiple_fields();
// clean up
delete TheFieldSet;
delete TheFactory;
//CleanupStack::PopAndDestroy();
}
LOCAL_C void setupCleanup()
//
// Initialise the cleanup stack.
//
{
TheTrapCleanup=CTrapCleanup::New();
TRAPD(r,\
{\
for (TInt i=KTestCleanupStack;i>0;i--)\
CleanupStack::PushL((TAny*)1);\
test(r==KErrNone);\
CleanupStack::Pop(KTestCleanupStack);\
});
}
GLDEF_C TInt E32Main()
//
// Test the streaming framework.
//
{
test.Title();
__UHEAP_MARK;
setupCleanup();
TRAPD(r,testFields());
UNUSED_VAR(r);
test(r == KErrNone);
delete TheTrapCleanup;
__UHEAP_MARKEND;
test.End();
test.Close();
return 0;
}