phonebookengines/VirtualPhonebook/tsrc/MT_VPbkEng_StrCntAnalyzer/src/MT_VPbkEng_StrCntAnalyzer.cpp
changeset 0 e686773b3f54
child 9 0d28c1c5b6dd
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2002 - 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  MT_VPbkEng_StrCntAnalyzer class member functions
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // [INCLUDE FILES] - do not remove
       
    21 #include <Stiftestinterface.h>
       
    22 #include "MT_VPbkEng_StrCntAnalyzer.h"
       
    23 #include <SettingServerClient.h>
       
    24 
       
    25 // Logging path
       
    26 _LIT( KMT_VPbkEng_StrCntAnalyzerLogPath, "\\logs\\testframework\\MT_VPbkEng_StrCntAnalyzer\\" ); 
       
    27 // Log file
       
    28 _LIT( KMT_VPbkEng_StrCntAnalyzerLogFile, "MT_VPbkEng_StrCntAnalyzer.txt" ); 
       
    29 _LIT( KMT_VPbkEng_StrCntAnalyzerLogFileWithTitle, "MT_VPbkEng_StrCntAnalyzer_[%S].txt" );
       
    30 
       
    31 #define GETPTR &
       
    32 #define ENTRY(str1,str2,func1,func2,func3) {(const TText*)(L##str1 L" [" L##str2 L"]"),GETPTR func1,GETPTR func2, GETPTR func3, 0,0,0}
       
    33 #define OOM_ENTRY(str1,str2,func1,func2,func3,a,b,c) {(const TText*)(L##str1 L" [" L##str2 L"]"), GETPTR func1,GETPTR func2, GETPTR func3,a,b,c}
       
    34 
       
    35 typedef void (CMT_VPbkEng_StrCntAnalyzer::* TestFunction)();
       
    36 
       
    37 class TCaseInfoInternal
       
    38     {
       
    39     public:
       
    40         const TText*    iCaseName;
       
    41         TestFunction    iSetup;
       
    42         TestFunction    iMethod;
       
    43         TestFunction    iTeardown;
       
    44         TBool           iIsOOMTest;
       
    45         TInt            iFirstMemoryAllocation;
       
    46         TInt            iLastMemoryAllocation;
       
    47         TPtrC CaseName() const {return TPtrC(iCaseName);};        
       
    48     };
       
    49 
       
    50 // ============================= LOCAL FUNCTIONS ===============================
       
    51 // ============================ MEMBER FUNCTIONS ===============================
       
    52 
       
    53 // -----------------------------------------------------------------------------
       
    54 // CMT_VPbkEng_StrCntAnalyzer::CMT_VPbkEng_StrCntAnalyzer
       
    55 // C++ default constructor can NOT contain any code, that
       
    56 // might leave.
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 CMT_VPbkEng_StrCntAnalyzer::CMT_VPbkEng_StrCntAnalyzer()
       
    60     {
       
    61 
       
    62     }
       
    63 
       
    64 // -----------------------------------------------------------------------------
       
    65 // CMT_VPbkEng_StrCntAnalyzer::ConstructL
       
    66 // Symbian 2nd phase constructor can leave.
       
    67 //
       
    68 // Note: If OOM test case uses STIF Logger, then STIF Logger must be created
       
    69 // with static buffer size parameter (aStaticBufferSize). Otherwise Logger 
       
    70 // allocates memory from heap and therefore causes error situations with OOM 
       
    71 // testing. For more information about STIF Logger construction, see STIF Users 
       
    72 // Guide.
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 void CMT_VPbkEng_StrCntAnalyzer::ConstructL()
       
    76     {
       
    77     //Read logger settings to check whether test case name is to be
       
    78     //appended to log file name.
       
    79     RSettingServer settingServer;
       
    80     TInt ret = settingServer.Connect();
       
    81     if(ret != KErrNone)
       
    82         {
       
    83         User::Leave(ret);
       
    84         }
       
    85     // Struct to StifLogger settigs.
       
    86     TLoggerSettings loggerSettings; 
       
    87     // Parse StifLogger defaults from STIF initialization file.
       
    88     ret = settingServer.GetLoggerSettings(loggerSettings);
       
    89     if(ret != KErrNone)
       
    90         {
       
    91         User::Leave(ret);
       
    92         } 
       
    93     // Close Setting server session
       
    94     settingServer.Close();
       
    95     iAddTestCaseTitleToLogName = loggerSettings.iAddTestCaseTitle;
       
    96 
       
    97     iStdLog = CStifLogger::NewL( KMT_VPbkEng_StrCntAnalyzerLogPath, 
       
    98                           KMT_VPbkEng_StrCntAnalyzerLogFile);
       
    99     iLog = iStdLog;
       
   100 
       
   101     // Sample how to use logging
       
   102     _LIT( KLogStart, "MT_VPbkEng_StrCntAnalyzer logging starts!" );
       
   103     iLog->Log( KLogStart );
       
   104 
       
   105     iVersionLogged = EFalse;
       
   106     }
       
   107 
       
   108 // -----------------------------------------------------------------------------
       
   109 // CMT_VPbkEng_StrCntAnalyzer::NewL
       
   110 // Two-phased constructor.
       
   111 // -----------------------------------------------------------------------------
       
   112 //
       
   113 CMT_VPbkEng_StrCntAnalyzer* CMT_VPbkEng_StrCntAnalyzer::NewL()
       
   114     {
       
   115     CMT_VPbkEng_StrCntAnalyzer* self = new (ELeave) CMT_VPbkEng_StrCntAnalyzer;
       
   116 
       
   117     CleanupStack::PushL( self );
       
   118     self->ConstructL();
       
   119     CleanupStack::Pop();
       
   120 
       
   121     return self;
       
   122 
       
   123     }
       
   124 
       
   125 // Destructor
       
   126 CMT_VPbkEng_StrCntAnalyzer::~CMT_VPbkEng_StrCntAnalyzer()
       
   127     {
       
   128     iLog = NULL;
       
   129     delete iStdLog;
       
   130     iStdLog = NULL;
       
   131     delete iTCLog;
       
   132     iTCLog = NULL;
       
   133     }
       
   134 
       
   135 // -----------------------------------------------------------------------------
       
   136 // CMT_VPbkEng_StrCntAnalyzer::InitL
       
   137 // InitL is used to initialize the Test Module.
       
   138 // -----------------------------------------------------------------------------
       
   139 //
       
   140 TInt CMT_VPbkEng_StrCntAnalyzer::InitL( 
       
   141     TFileName& /*aIniFile*/, 
       
   142     TBool /*aFirstTime*/ )
       
   143     {
       
   144     return KErrNone;
       
   145 
       
   146     }
       
   147 
       
   148 // -----------------------------------------------------------------------------
       
   149 // CMT_VPbkEng_StrCntAnalyzer::GetTestCasesL
       
   150 // GetTestCases is used to inquire test cases from the Test Module. Test
       
   151 // cases are stored to array of test cases. The Test Framework will be 
       
   152 // the owner of the data in the RPointerArray after GetTestCases return
       
   153 // and it does the memory deallocation. 
       
   154 // -----------------------------------------------------------------------------
       
   155 //
       
   156 TInt CMT_VPbkEng_StrCntAnalyzer::GetTestCasesL( 
       
   157     const TFileName& /*aConfig*/, 
       
   158     RPointerArray<TTestCaseInfo>& aTestCases )
       
   159     {
       
   160 
       
   161     // Loop through all test cases and create new
       
   162     // TTestCaseInfo items and append items to aTestCase array    
       
   163     for( TInt i = 0; Case(i).iMethod != NULL; i++ )
       
   164         {
       
   165 
       
   166         // Allocate new TTestCaseInfo from heap for a testcase definition.
       
   167         TTestCaseInfo* newCase = new( ELeave ) TTestCaseInfo();
       
   168 
       
   169         // PushL TTestCaseInfo to CleanupStack.    
       
   170         CleanupStack::PushL( newCase );
       
   171 
       
   172         // Set number for the testcase.
       
   173         // When the testcase is run, this comes as a parameter to RunTestCaseL.
       
   174         newCase->iCaseNumber = i;
       
   175 
       
   176         // Set title for the test case. This is shown in UI to user.
       
   177         newCase->iTitle.Copy( Case(i).CaseName() );
       
   178 
       
   179         // Append TTestCaseInfo to the testcase array. After appended 
       
   180         // successfully the TTestCaseInfo object is owned (and freed) 
       
   181         // by the TestServer. 
       
   182         User::LeaveIfError(aTestCases.Append ( newCase ) );
       
   183 
       
   184         // Pop TTestCaseInfo from the CleanupStack.
       
   185         CleanupStack::Pop( newCase );
       
   186 
       
   187         }
       
   188 
       
   189     return KErrNone;
       
   190 
       
   191     }
       
   192 
       
   193 // -----------------------------------------------------------------------------
       
   194 // CMT_VPbkEng_StrCntAnalyzer::RunTestCaseL
       
   195 // RunTestCaseL is used to run an individual test case specified 
       
   196 // by aTestCase. Test cases that can be run may be requested from 
       
   197 // Test Module by GetTestCases method before calling RunTestCase.
       
   198 // -----------------------------------------------------------------------------
       
   199 //
       
   200 TInt CMT_VPbkEng_StrCntAnalyzer::RunTestCaseL( 
       
   201     const TInt aCaseNumber,   
       
   202     const TFileName& /*aConfig*/,
       
   203     TTestResult& aResult )
       
   204     {
       
   205     iResult = &aResult;
       
   206     if(!iVersionLogged)
       
   207     	{
       
   208     	SendTestModuleVersion();
       
   209     	iVersionLogged = ETrue;
       
   210     	}
       
   211     
       
   212     // Return value
       
   213     TInt execStatus = KErrNone;
       
   214 
       
   215     // Get the pointer to test case function
       
   216     const TCaseInfoInternal& tmp = Case ( aCaseNumber );
       
   217 
       
   218     _LIT( KLogStartTC, "Starting testcase [%S]" );
       
   219     TPtrC caseName = tmp.CaseName();
       
   220     iLog->Log( KLogStartTC, &caseName);
       
   221 
       
   222     // Check that case number was valid
       
   223     if ( tmp.iMethod != NULL )
       
   224         {
       
   225         //Open new log file with test case title in file name
       
   226         if(iAddTestCaseTitleToLogName)
       
   227             {
       
   228             //Delete test case logger if exists
       
   229             if(iTCLog)
       
   230                 {
       
   231                 delete iTCLog;
       
   232                 iTCLog = NULL;
       
   233                 }
       
   234 
       
   235             TFileName logFileName;
       
   236             TName title;
       
   237             TestModuleIf().GetTestCaseTitleL(title);
       
   238         
       
   239             logFileName.Format(KMT_VPbkEng_StrCntAnalyzerLogFileWithTitle, &title);
       
   240 
       
   241             iTCLog = CStifLogger::NewL(KMT_VPbkEng_StrCntAnalyzerLogPath, 
       
   242                                        logFileName);
       
   243             iLog = iTCLog;                                       
       
   244             }
       
   245 
       
   246 
       
   247         TInt err = KErrNone;
       
   248         TRAP(err, ( this->*(tmp.iSetup) )());
       
   249         if(err!=KErrNone)
       
   250         	{
       
   251         	_LIT( KDescription, "Setup failed" );
       
   252         	aResult.SetResult( err, KDescription );
       
   253         	execStatus = KErrNone;
       
   254         	}
       
   255         else
       
   256         	{
       
   257 	        aResult.iResult = KErrNone;
       
   258 	        TRAP(err, ( this->*(tmp.iMethod) )());
       
   259 	        if(err==KErrNone)
       
   260 	        	{
       
   261 	        	_LIT( KDescription, "Test passed" );
       
   262 	        	aResult.SetResult( err, KDescription );
       
   263 	        	}
       
   264 	        else if ( aResult.iResult == KErrNone )
       
   265 	            {
       
   266 	        	_LIT( KDescription, "Test failed" );
       
   267 	        	aResult.SetResult( err, KDescription );
       
   268 	            }
       
   269 	        TRAP(err, ( this->*(tmp.iTeardown) )());
       
   270 	        if(err!=KErrNone)
       
   271 	        	{
       
   272 	        	_LIT( KDescription, "Teardown failed" );
       
   273 	        	aResult.SetResult( err, KDescription );
       
   274 	        	execStatus = KErrNone;
       
   275 	        	}
       
   276         	}
       
   277         }
       
   278     else
       
   279         {
       
   280         // Valid case was not found, return error.
       
   281         execStatus = KErrNotFound;
       
   282         }
       
   283 
       
   284     // Return case execution status (not the result of the case execution)
       
   285     return execStatus;
       
   286 
       
   287     }
       
   288 
       
   289 // -----------------------------------------------------------------------------
       
   290 // CMT_VPbkEng_StrCntAnalyzer::OOMTestQueryL
       
   291 // Used to check if a particular test case should be run in OOM conditions and 
       
   292 // which memory allocations should fail.    
       
   293 // -----------------------------------------------------------------------------
       
   294 //
       
   295 TBool CMT_VPbkEng_StrCntAnalyzer::OOMTestQueryL( 
       
   296                                 const TFileName& /* aTestCaseFile */, 
       
   297                                 const TInt aCaseNumber, 
       
   298                                 TOOMFailureType& /* aFailureType */, 
       
   299                                 TInt& aFirstMemFailure, 
       
   300                                 TInt& aLastMemFailure ) 
       
   301     {
       
   302     _LIT( KLogOOMTestQueryL, "CMT_VPbkEng_StrCntAnalyzer::OOMTestQueryL" );
       
   303     iLog->Log( KLogOOMTestQueryL );     
       
   304 
       
   305     aFirstMemFailure = Case( aCaseNumber ).iFirstMemoryAllocation;
       
   306     aLastMemFailure = Case( aCaseNumber ).iLastMemoryAllocation;
       
   307 
       
   308     return Case( aCaseNumber ).iIsOOMTest;
       
   309 
       
   310     }
       
   311 
       
   312 // -----------------------------------------------------------------------------
       
   313 // CMT_VPbkEng_StrCntAnalyzer::OOMTestInitializeL
       
   314 // Used to perform the test environment setup for a particular OOM test case. 
       
   315 // Test Modules may use the initialization file to read parameters for Test 
       
   316 // Module initialization but they can also have their own configure file or 
       
   317 // some other routine to initialize themselves.  
       
   318 //
       
   319 // NOTE: User may add implementation for OOM test environment initialization.
       
   320 // Usually no implementation is required.
       
   321 // -----------------------------------------------------------------------------
       
   322 //
       
   323 void CMT_VPbkEng_StrCntAnalyzer::OOMTestInitializeL( 
       
   324                                 const TFileName& /* aTestCaseFile */, 
       
   325                                 const TInt /* aCaseNumber */ )
       
   326     {
       
   327     }
       
   328 
       
   329 // -----------------------------------------------------------------------------
       
   330 // CMT_VPbkEng_StrCntAnalyzer::OOMHandleWarningL
       
   331 // In some cases the heap memory allocation should be skipped, either due to
       
   332 // problems in the OS code or components used by the code being tested, or even 
       
   333 // inside the tested components which are implemented this way on purpose (by 
       
   334 // design), so it is important to give the tester a way to bypass allocation 
       
   335 // failures.
       
   336 //
       
   337 // NOTE: User may add implementation for OOM test warning handling. Usually no
       
   338 // implementation is required.
       
   339 // -----------------------------------------------------------------------------
       
   340 //
       
   341 void CMT_VPbkEng_StrCntAnalyzer::OOMHandleWarningL( 
       
   342                                 const TFileName& /* aTestCaseFile */,
       
   343                                 const TInt /* aCaseNumber */, 
       
   344                                 TInt& /* aFailNextValue */ )
       
   345     {
       
   346     }
       
   347 
       
   348 // -----------------------------------------------------------------------------
       
   349 // CMT_VPbkEng_StrCntAnalyzer::OOMTestFinalizeL
       
   350 // Used to perform the test environment cleanup for a particular OOM test case.
       
   351 //
       
   352 // NOTE: User may add implementation for OOM test environment finalization.
       
   353 // Usually no implementation is required.
       
   354 // -----------------------------------------------------------------------------
       
   355 //
       
   356 void CMT_VPbkEng_StrCntAnalyzer::OOMTestFinalizeL( 
       
   357                                 const TFileName& /* aTestCaseFile */, 
       
   358                                 const TInt /* aCaseNumber */ )
       
   359     {
       
   360     }
       
   361 
       
   362 //-----------------------------------------------------------------------------
       
   363 // CMT_VPbkEng_StrCntAnalyzer::SendTestModuleVersion
       
   364 // Method used to send version of test module
       
   365 //-----------------------------------------------------------------------------
       
   366 //
       
   367 void CMT_VPbkEng_StrCntAnalyzer::SendTestModuleVersion()
       
   368 	{
       
   369 	TVersion moduleVersion;
       
   370 	moduleVersion.iMajor = TEST_MODULE_VERSION_MAJOR;
       
   371 	moduleVersion.iMinor = TEST_MODULE_VERSION_MINOR;
       
   372 	moduleVersion.iBuild = TEST_MODULE_VERSION_BUILD;
       
   373 	
       
   374 	TFileName moduleName;
       
   375 	moduleName = _L("MT_VPbkEng_StrCntAnalyzer.dll");
       
   376 
       
   377 	TestModuleIf().SendTestModuleVersion(moduleVersion, moduleName);
       
   378 	}
       
   379 
       
   380 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
   381 
       
   382 // -----------------------------------------------------------------------------
       
   383 // LibEntryL is a polymorphic Dll entry point
       
   384 // Returns: CTestModuleBase*: Pointer to Test Module object
       
   385 // -----------------------------------------------------------------------------
       
   386 //
       
   387 EXPORT_C CTestModuleBase* LibEntryL()
       
   388     {
       
   389     return CMT_VPbkEng_StrCntAnalyzer::NewL();
       
   390 
       
   391     }
       
   392 
       
   393 // -----------------------------------------------------------------------------
       
   394 // SetRequirements handles test module parameters(implements evolution
       
   395 // version 1 for test module's heap and stack sizes configuring).
       
   396 // Returns: TInt: Symbian error code.
       
   397 // -----------------------------------------------------------------------------
       
   398 //
       
   399 EXPORT_C TInt SetRequirements( CTestModuleParam*& /*aTestModuleParam*/, 
       
   400                                 TUint32& /*aParameterValid*/ )
       
   401     {
       
   402 
       
   403     /* --------------------------------- NOTE ---------------------------------
       
   404     USER PANICS occurs in test thread creation when:
       
   405     1) "The panic occurs when the value of the stack size is negative."
       
   406     2) "The panic occurs if the minimum heap size specified is less
       
   407        than KMinHeapSize".
       
   408        KMinHeapSize: "Functions that require a new heap to be allocated will
       
   409        either panic, or will reset the required heap size to this value if
       
   410        a smaller heap size is specified".
       
   411     3) "The panic occurs if the minimum heap size specified is greater than
       
   412        the maximum size to which the heap can grow".
       
   413     Other:
       
   414     1) Make sure that your hardware or Symbian OS is supporting given sizes.
       
   415        e.g. Hardware might support only sizes that are divisible by four.
       
   416     ------------------------------- NOTE end ------------------------------- */
       
   417 
       
   418     // Normally STIF uses default heap and stack sizes for test thread, see:
       
   419     // KTestThreadMinHeap, KTestThreadMinHeap and KStackSize.
       
   420     // If needed heap and stack sizes can be configured here by user. Remove
       
   421     // comments and define sizes.
       
   422 
       
   423 /*
       
   424     aParameterValid = KStifTestModuleParameterChanged;
       
   425 
       
   426     CTestModuleParamVer01* param = CTestModuleParamVer01::NewL();
       
   427     // Stack size
       
   428     param->iTestThreadStackSize= 16384; // 16K stack
       
   429     // Heap sizes
       
   430     param->iTestThreadMinHeap = 4096;   // 4K heap min
       
   431     param->iTestThreadMaxHeap = 1048576;// 1M heap max
       
   432 
       
   433     aTestModuleParam = param;
       
   434 */
       
   435     return KErrNone;
       
   436 
       
   437     }
       
   438 
       
   439 // -----------------------------------------------------------------------------
       
   440 // CMT_VPbkEng_StrCntAnalyzer::Case
       
   441 // Returns a test case by number.
       
   442 //
       
   443 // This function contains an array of all available test cases 
       
   444 // i.e pair of case name and test function. If case specified by parameter
       
   445 // aCaseNumber is found from array, then that item is returned.
       
   446 // 
       
   447 // The reason for this rather complicated function is to specify all the
       
   448 // test cases only in one place. It is not necessary to understand how
       
   449 // function pointers to class member functions works when adding new test
       
   450 // cases. See function body for instructions how to add new test case.
       
   451 // -----------------------------------------------------------------------------
       
   452 //
       
   453 const TCaseInfoInternal& CMT_VPbkEng_StrCntAnalyzer::Case ( 
       
   454     const TInt aCaseNumber ) const 
       
   455      {
       
   456 
       
   457     /**
       
   458     * To add new test cases, implement new test case function and add new 
       
   459     * line to KCases array specify the name of the case and the function 
       
   460     * doing the test case
       
   461     * In practice, do following
       
   462     * 1) Make copy of existing test case function and change its name
       
   463     *    and functionality. Note that the function must be added to 
       
   464     *    MT_VPbkEng_StrCntAnalyzer.cpp file and to MT_VPbkEng_StrCntAnalyzer.h 
       
   465     *    header file.
       
   466     *
       
   467     * 2) Add entry to following KCases array either by using:
       
   468     *
       
   469     * 2.1: FUNCENTRY or ENTRY macro
       
   470     * ENTRY macro takes two parameters: test case name and test case 
       
   471     * function name.
       
   472     *
       
   473     * FUNCENTRY macro takes only test case function name as a parameter and
       
   474     * uses that as a test case name and test case function name.
       
   475     *
       
   476     * Or
       
   477     *
       
   478     * 2.2: OOM_FUNCENTRY or OOM_ENTRY macro. Note that these macros are used
       
   479     * only with OOM (Out-Of-Memory) testing!
       
   480     *
       
   481     * OOM_ENTRY macro takes five parameters: test case name, test case 
       
   482     * function name, TBool which specifies is method supposed to be run using
       
   483     * OOM conditions, TInt value for first heap memory allocation failure and 
       
   484     * TInt value for last heap memory allocation failure.
       
   485     * 
       
   486     * OOM_FUNCENTRY macro takes test case function name as a parameter and uses
       
   487     * that as a test case name, TBool which specifies is method supposed to be
       
   488     * run using OOM conditions, TInt value for first heap memory allocation 
       
   489     * failure and TInt value for last heap memory allocation failure. 
       
   490     */ 
       
   491 
       
   492     static TCaseInfoInternal const KCases[] =
       
   493         {
       
   494         // [test cases entries] - do not remove
       
   495         
       
   496         // NOTE: When compiled to GCCE, there must be Classname::
       
   497         // declaration in front of the method name, e.g. 
       
   498         // CMT_VPbkEng_StrCntAnalyzer::PrintTest. Otherwise the compiler
       
   499         // gives errors.
       
   500 #include "MT_VPbkEng_StrCntAnalyzertesttable.cpp"                                
       
   501         // Example how to use OOM functionality
       
   502         //OOM_ENTRY( "Loop test with OOM", CMT_VPbkEng_StrCntAnalyzer::LoopTest, ETrue, 2, 3),
       
   503         //OOM_FUNCENTRY( CMT_VPbkEng_StrCntAnalyzer::PrintTest, ETrue, 1, 3 ),
       
   504         };
       
   505 
       
   506     // Verify that case number is valid
       
   507     if( (TUint) aCaseNumber >= sizeof( KCases ) / 
       
   508                                sizeof( TCaseInfoInternal ) )
       
   509         {
       
   510         // Invalid case, construct empty object
       
   511         static const TCaseInfoInternal nullCase = {NULL, NULL, NULL,NULL,EFalse,0,0};
       
   512         return nullCase;
       
   513         } 
       
   514 
       
   515     return KCases[ aCaseNumber ];
       
   516     }
       
   517 
       
   518 //  End of File