sl@0: // Copyright (c) 2006-2009 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: // These macros and templates extend the tef testsuite support. sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @test sl@0: @internalComponent - Internal Symbian test code sl@0: */ sl@0: sl@0: #ifndef __EXTENDTEF_H__ sl@0: #define __EXTENDTEF_H__ sl@0: sl@0: #include sl@0: sl@0: // Adds a test suite that is not called CreateSuiteL so that one class can describe multiple subsets of tests. sl@0: #define ADD_TEST_SUITE_SUB(subname) \ sl@0: _LIT( KTest ## subname, #subname); \ sl@0: lTestSuite->AddL( CreateSuiteSub##subname##L( KTest##subname)); sl@0: sl@0: // Calls a subfunction to add more members to the current test suite at the current level. Can be the same function as used to create nested tests. sl@0: #define ADD_TEST_SUITE_SUB_FLAT(subname) \ sl@0: _LIT( KTest ## subname, #subname); \ sl@0: CreateSuiteSub##subname##L( KTest##subname,lTestSuite); sl@0: sl@0: // Allows the class suite to be added with a name different to the class name, so class names can be computational sl@0: #define ADD_TEST_SUITE_MODULE_SUB_AS(module,subname,as) \ sl@0: _LIT( KTest ## as, #as); \ sl@0: lTestSuite->AddL( module::CreateSuiteSub##subname##L( KTest##as)); sl@0: sl@0: /** Use in a subsuite to distinguish between ADD_TEST_SUITE_SUB and ADD_TEST_SUITE_SUB_FLAT caller sl@0: * ClassName is required - it defines the name of the class containing the referenced methods. sl@0: * aTestSuite is optional - it should be the function parameter aTestSuite or the keyword NULL sl@0: **/ sl@0: #define SUB_SUITE_OPT(ClassName,aTestSuite) \ sl@0: CTestSuite* lTestSuite = aTestSuite? (CTestSuite*)aTestSuite: CTestSuite::NewL(aName); \ sl@0: typedef ClassName ThisThis; sl@0: sl@0: // Create a dotted name subtest in the script that represents a parameter to the named test sl@0: // This should be called from a ADD_TEST_SUITE_SUB with the same name as the test method, sl@0: // so that entries can be inserted of the form CMyTestClass.MyTest.EColor256 sl@0: #define ADD_TEST_STEP_PARAM_1(method,param) \ sl@0: _LIT( KTest ## method ## param, #param); \ sl@0: AddTestCaseParam(lTestSuite, KTest ## method ## param, method, param); sl@0: sl@0: // Insert a test that takes a parameter and a range of dotted subtests that set that parameter sl@0: // This allows tests of the form CMyTestClass.MyLoopTest.8 sl@0: #define ADD_TEST_STEP_PARAM_RANGE(method,minparam,maxparam) \ sl@0: _LIT(KTest ## method,#method); \ sl@0: AddTestCaseParamRangeL(lTestSuite,KTest ## method,&ThisThis::method,minparam,maxparam); sl@0: sl@0: // Insert a test that takes a parameter and a range of dotted subtests that set that parameter sl@0: // This allows tests of the form CMyTestClass.MyLoopTest.8 sl@0: #define ADD_TEST_STEP_PARAM_RANGE_STEP(method,minparam,maxparam,step) \ sl@0: _LIT( KTest ## method , #method); \ sl@0: AddTestCaseParamRangeL(lTestSuite, KTest ## method, &ThisThis::method, minparam,maxparam,step); sl@0: sl@0: // Insert a test that takes a boolean parameter and a range of dotted subtests that set that parameter sl@0: // Names for dotted tests include "true", "yes", "on", "1" sl@0: // This allows tests of the form CMyTestClass.EnableFeature.on sl@0: #define ADD_TEST_STEP_PARAM_BOOL(method) \ sl@0: _LIT(KTest ## method,#method); \ sl@0: AddTestCaseParamBoolL(lTestSuite,KTest ## method,&ThisThis::method); sl@0: sl@0: // Insert a test that that just requires calling a function sl@0: #define ADD_WSGCE_TEST_STEP(classname,method) \ sl@0: _LIT(KTest ## method,#method); \ sl@0: AddTestCase(lTestSuite,KTest ## method,&classname::method); sl@0: sl@0: // Insert an asyncronus test that that just requires calling a function sl@0: #define ADD_WSGCE_ASYNC_TEST_STEP(classname,method) \ sl@0: _LIT(KTest ## method,#method); \ sl@0: AddAsyncTestCase(lTestSuite,KTest ## method,&classname::method); sl@0: sl@0: // Insert a test that that just requires calling a function sl@0: #define ADD_THIS_TEST_STEP(method) \ sl@0: _LIT(KTest ## method,#method); \ sl@0: AddTestCase(lTestSuite,KTest ## method,&ThisThis::method); sl@0: sl@0: // Insert an asyncronus test that that just requires calling a function sl@0: #define ADD_THIS_ASYNC_TEST_STEP(method) \ sl@0: _LIT(KTest ## method,#method); \ sl@0: AddAsyncTestCase(lTestSuite,KTest ## method,&ThisThis::method); sl@0: sl@0: /********************************************************************************* sl@0: * Base class for derived doers that use the Setup/Shutdown sl@0: *********************************************************************************/ sl@0: template sl@0: class CTestCaseDoTemplate : public CTestCase sl@0: { sl@0: private: sl@0: sl@0: public: sl@0: CTestCaseDoTemplate(const TDesC &aName); sl@0: virtual ~CTestCaseDoTemplate(); sl@0: sl@0: virtual void RunL(CTestConfig& aConfig, CTestExecuteLogger& aLogger); sl@0: virtual void DoRunL(Fixture*aFixture)=0; sl@0: sl@0: protected: sl@0: }; sl@0: sl@0: /********************************************************************************* sl@0: * Derived dorun to run a test with a parameter sl@0: *********************************************************************************/ sl@0: template sl@0: class CTestCaseParamTemplate : public CTestCaseDoTemplate sl@0: { sl@0: private: sl@0: typedef void (Fixture::*TestMethod)(Param aParam); sl@0: sl@0: public: sl@0: CTestCaseParamTemplate(const TDesC &aName, TestMethod aTestMethod, Param aParam) sl@0: : CTestCaseDoTemplate(aName), sl@0: iTest(aTestMethod),iParam(aParam) sl@0: {} sl@0: virtual void DoRunL(Fixture*aFixture) sl@0: { sl@0: (aFixture->*iTest)(iParam); sl@0: } sl@0: sl@0: protected: sl@0: TestMethod iTest; sl@0: Param iParam; sl@0: }; sl@0: sl@0: /*************************************** sl@0: * sl@0: * Implementation of template class CTestCaseTemplate sl@0: * sl@0: ***************************************/ sl@0: template sl@0: CTestCaseDoTemplate::CTestCaseDoTemplate(const TDesC &aName) sl@0: : CTestCase(aName) sl@0: { sl@0: } sl@0: template sl@0: CTestCaseDoTemplate::~CTestCaseDoTemplate() sl@0: { sl@0: } sl@0: template sl@0: void CTestCaseDoTemplate::RunL(CTestConfig& aConfig, CTestExecuteLogger& aLogger) sl@0: /** sl@0: * Creates and destroys the test fixture, but runs the DoRunL in the derived class, which in turn runs the test. sl@0: * sl@0: * @param aConfig - Test configuration sl@0: * @param aLogger - Test logger sl@0: */ sl@0: { sl@0: Fixture* iFixture = new (ELeave) Fixture(); sl@0: CleanupStack::PushL(iFixture); sl@0: sl@0: // Must set the Logger and Config now sl@0: iFixture->SetLoggerL( aLogger ); sl@0: iFixture->SetConfigL( aConfig ); sl@0: sl@0: // Setup code sl@0: iFixture->SetupL(); sl@0: sl@0: // Run the test sl@0: TRAPD( err, DoRunL(iFixture) ); sl@0: sl@0: // Log the result sl@0: CTEFLogger::LogResult( iName, err, aLogger ); sl@0: sl@0: // Now the test case has been logged we need to leave sl@0: // again if that is what the test did sl@0: if( err != KErrTEFUnitPass ) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: sl@0: // Teardown code sl@0: iFixture->TearDownL(); sl@0: sl@0: CleanupStack::PopAndDestroy(); sl@0: } sl@0: /** sl@0: * Support method to add a test that takes a specific value as its parameter. sl@0: * Can be used from ADD_TEST_STEP_PARAM_1, or from the methods below sl@0: **/ sl@0: template sl@0: inline void AddTestCaseParam(CTestSuite* aTestSuite, const TDesC& aName, void (Fixture::*aTestMethod)(Param aParam),Param aParam) sl@0: { sl@0: CTestCaseParamTemplate *testCaseTemplate = new (ELeave) CTestCaseParamTemplate(aName, aTestMethod,aParam); sl@0: CleanupStack::PushL(testCaseTemplate); sl@0: aTestSuite->AddL( testCaseTemplate ); sl@0: CleanupStack::Pop(testCaseTemplate); sl@0: } sl@0: /** sl@0: * Adds a test with a range of parameter values. Usually launched from ADD_TEST_STEP_PARAM_RANGE sl@0: * sl@0: **/ sl@0: template sl@0: inline void AddTestCaseParamRangeL(CTestSuite* aTestSuite, const TDesC& aName, void (Fixture::*aTestMethod)(Param aParam),TInt aParamMin,TInt aParamMax,TInt aDelta=1) sl@0: { sl@0: CTestSuite* lTestSuite = CTestSuite::NewL(aName); sl@0: CleanupStack::PushL(lTestSuite); sl@0: __ASSERT_ALWAYS(aDelta!=0 && aParamMin!=aParamMax,User::Invariant()); sl@0: __ASSERT_ALWAYS((aDelta>0) == (aParamMax>aParamMin),User::Invariant()); sl@0: for (TInt count=aParamMin;count!=aParamMax;count+=aDelta) sl@0: { sl@0: TBuf<10> name2; sl@0: name2.AppendNum(count); sl@0: CTestCaseParamTemplate *testCaseTemplate = new (ELeave) CTestCaseParamTemplate(name2, aTestMethod,Param(count)); sl@0: CleanupStack::PushL(testCaseTemplate); sl@0: lTestSuite->AddL( testCaseTemplate ); sl@0: CleanupStack::Pop(testCaseTemplate); sl@0: } sl@0: aTestSuite->AddL(lTestSuite); sl@0: CleanupStack::Pop(lTestSuite); sl@0: } sl@0: sl@0: /** sl@0: * Adds a test with a range of parameter values. Usually launched from ADD_TEST_STEP_PARAM_BOOL sl@0: * sl@0: **/ sl@0: template sl@0: inline void AddTestCaseParamBoolL(CTestSuite* aTestSuite, const TDesC& aName, void (Fixture::*aTestMethod)(Param aParam)) sl@0: { sl@0: class CTestSuiteBool: public CTestSuite sl@0: { sl@0: public: sl@0: static CTestSuite* NewL(const TTestName& aName) sl@0: { sl@0: CTestSuite* lTestSuite = new (ELeave) CTestSuiteBool(aName); sl@0: CleanupStack::PushL(lTestSuite); sl@0: lTestSuite->ConstructL(); sl@0: CleanupStack::Pop(); sl@0: return lTestSuite; sl@0: } sl@0: protected: sl@0: CTestSuiteBool(const TTestName& aName): CTestSuite(aName) sl@0: { } sl@0: virtual void RunL(CTestConfig& aConfig, CTestExecuteLogger& aLogger) sl@0: { //run "all the tests" sl@0: // Log that the runner is currently in this suite sl@0: CTEFLogger::LogTraverse( iName, aLogger ); sl@0: TInt lError=KErrNone; sl@0: for(TInt lIndex = 0; lIndex < Count() && lIndex<2; lIndex++) sl@0: { sl@0: TRAPD(err,TestL(lIndex)->RunL(aConfig, aLogger)); sl@0: if(err != KErrTEFUnitPass) sl@0: { sl@0: lError=err; sl@0: } sl@0: } sl@0: if(lError != KErrTEFUnitPass) sl@0: { sl@0: User::Leave(lError); sl@0: } sl@0: } sl@0: sl@0: }; sl@0: typedef Fixture ThisThis; sl@0: CTestSuite* lTestSuite = CTestSuiteBool::NewL(aName); sl@0: CleanupStack::PushL(lTestSuite); sl@0: #define yes 1 sl@0: #define true 1 sl@0: #define on 1 sl@0: #define off 0 sl@0: #define no 0 sl@0: #define false 0 sl@0: sl@0: #define Yes 1 sl@0: #define True 1 sl@0: #define On 1 sl@0: #define Off 0 sl@0: #define No 0 sl@0: #define False 0 sl@0: sl@0: #define YES 1 sl@0: #define ON 1 sl@0: #define OFF 0 sl@0: #define NO 0 sl@0: sl@0: sl@0: #define ETrue 1 sl@0: #define EFalse 0 sl@0: //The first two MUST be a true and a false so running "all" will run them both sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,ETrue); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,EFalse); sl@0: sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,1); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,0); sl@0: sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,yes); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,true); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,on); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,no); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,false); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,off); sl@0: sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,Yes); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,True); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,On); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,No); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,False); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,Off); sl@0: sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,YES); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,TRUE); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,ON); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,NO); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,FALSE); sl@0: ADD_TEST_STEP_PARAM_1(aTestMethod,OFF); sl@0: sl@0: #undef yes sl@0: #undef true sl@0: #undef on sl@0: #undef off sl@0: #undef no sl@0: #undef false sl@0: sl@0: #undef Yes sl@0: #undef True sl@0: #undef On sl@0: #undef Off sl@0: #undef No sl@0: #undef False sl@0: sl@0: #undef YES sl@0: #undef ON sl@0: #undef OFF sl@0: #undef NO sl@0: sl@0: sl@0: #undef ETrue sl@0: #undef EFalse sl@0: sl@0: aTestSuite->AddL(lTestSuite); sl@0: CleanupStack::Pop(lTestSuite); sl@0: } sl@0: sl@0: void TefUnitFailLeaveL(); sl@0: sl@0: #undef __ASSERT_SHARED sl@0: #define __MAKE_L_STRING(S) L##S sl@0: /** sl@0: * Redefining this macro allows the condition text of the assert to be logged when the fail is reported as well as the file and line number sl@0: * This allows simple issues to be diagnosed without resorting to the source. sl@0: **/ sl@0: #define __ASSERT_SHARED(aFunction, aMessage) \ sl@0: if(!aFunction) \ sl@0: { \ sl@0: struct Log \ sl@0: { /*This wrapper is provided purely to hide the temp string from the debugger.*/ \ sl@0: static const TLitC& Str()\ sl@0: {\ sl@0: _LIT(aMessage, "ASSERT FAILED: " __MAKE_L_STRING(#aFunction) ); \ sl@0: return aMessage;\ sl@0: }\ sl@0: };\ sl@0: Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrAll, Log::Str() );\ sl@0: TefUnitFailLeaveL();\ sl@0: } sl@0: #define ASSERT_NOT_EQUALS(aExpected, aActual) \ sl@0: __ASSERT_SHARED(!AssertEquals(aExpected, aActual) , KAssertFailedEquals); sl@0: sl@0: template sl@0: inline TBool AssertTrue(Pointer* aCondition) sl@0: { sl@0: return AssertTrue((TBool)aCondition); sl@0: } sl@0: sl@0: sl@0: #define LOG_AND_RETURN_IF_GOT_GCE \ sl@0: { \ sl@0: if (GCEIsSupported()) \ sl@0: { \ sl@0: INFO_PRINTF1(_L("Test skipped: GCE support is loaded")); \ sl@0: User::Panic(_L("GCE.Wrong.Mode"),1); \ sl@0: return; \ sl@0: } \ sl@0: } sl@0: sl@0: #define LOG_AND_PANIC_IF_NOT_GCE \ sl@0: { \ sl@0: if (!GCEIsSupported()) \ sl@0: { \ sl@0: INFO_PRINTF1(_L("Test skipped: GCE support is not loaded")); \ sl@0: User::Panic(_L("GCE.Wrong.Mode"),1); \ sl@0: return; \ sl@0: } \ sl@0: } sl@0: sl@0: sl@0: #define _LIT2(NAME,STRING) \ sl@0: class NAME \ sl@0: { \ sl@0: public: \ sl@0: static const TLitC& S() \ sl@0: { \ sl@0: _LIT(singleton,STRING); \ sl@0: return singleton; \ sl@0: } \ sl@0: } ; sl@0: sl@0: sl@0: #endif //__EXTENDTEF_H__