|
1 /** |
|
2 * Copyright (c) 2003-2009 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 /** |
|
21 @file |
|
22 */ |
|
23 |
|
24 #ifndef __CMTF_TEST_CASE_H__ |
|
25 #define __CMTF_TEST_CASE_H__ |
|
26 |
|
27 #include <test/testexecutestepbase.h> |
|
28 #include "TMtfTestParameterType.h" |
|
29 #include "CMtfTestParameter.h" |
|
30 #include "CMtfTestParameterStore.h" |
|
31 #include "CMtfConfigurationType.h" |
|
32 #include "CMtfEnumeratorConverter.h" |
|
33 #include "CMtfTestAction.h" |
|
34 |
|
35 class CMtfTestServer; |
|
36 class CMtfTestAction; |
|
37 |
|
38 _LIT(KMtfDontCare,"_"); |
|
39 _LIT(_,"_"); // Short form for nonscripted test scripts |
|
40 |
|
41 |
|
42 /** Base class from which all test cases are derived. To create a new test case class the functions |
|
43 SetupTestCaseL(), ExecuteTestCaseL() and CheckPostConditionsL() must be overridden. */ |
|
44 class CMtfTestCase: public CTestStep |
|
45 { |
|
46 public: |
|
47 |
|
48 // These panics signify that the test case script is invalid in case of a scripted |
|
49 // test case. In case of a non-scripted test case, the overridden sections of the test |
|
50 // case are invalid. The test actions are not used correctly. |
|
51 // |
|
52 enum TMtfTestCasePanic |
|
53 { |
|
54 EMtfGeneralTypeMismatch, // mismatch of general parameter types |
|
55 EMtfSpecificTypeMismatch, // mismatch of specific parameter types |
|
56 EMtfMissingParameters, // a test action was used without providing all |
|
57 // required parameters |
|
58 EMtfUnexpectedQueuedAction, // the test case expected iQueuedActions to be empty |
|
59 EMtfInvalidParameter, // invalid parameter |
|
60 EMtfInternalError |
|
61 }; |
|
62 |
|
63 static void Panic(TMtfTestCasePanic aPanic); |
|
64 virtual ~CMtfTestCase(); |
|
65 |
|
66 /** Required by TestExecute */ |
|
67 virtual TVerdict doTestStepPreambleL(); |
|
68 |
|
69 /** Required by TestExecute */ |
|
70 virtual TVerdict doTestStepL(); |
|
71 |
|
72 /** Required by TestExecute */ |
|
73 virtual TVerdict doTestStepPostambleL(); |
|
74 |
|
75 /** Notifies the test case that an action has been completed. Used by test actions. */ |
|
76 void ActionCompletedL(CMtfTestAction& aTestAction); |
|
77 |
|
78 /** Notifies the test case that a section has been completed. Used by the framework. */ |
|
79 void SectionCompletedL(); |
|
80 |
|
81 /** Queues an action for execution. Takes ownership */ |
|
82 void QueueTestActionL(CMtfTestAction* aTestAction); |
|
83 |
|
84 TBool ScriptedTestCase() const; |
|
85 |
|
86 /** Sets the test case to wait for the specified action to complete before executing |
|
87 any other actions. */ |
|
88 void WaitForActionL(const TDesC& aActionId); |
|
89 |
|
90 /** Sets the test case to wait for the completion of all currently executing actions |
|
91 before starting the execution of any other actions. */ |
|
92 void WaitForAllActionsL(); |
|
93 |
|
94 TBool IsSynchronous(); |
|
95 |
|
96 void DeleteParameterL(const TDesC& aName); |
|
97 |
|
98 /** Obtains the configuration file corresponding to the required type. Configuration file returned was either set |
|
99 from the main script, set as the test case default, or a global default one is used.*/ |
|
100 const TDesC& GetConfigurationFileL(const CMtfConfigurationType::TMtfConfigurationType& aType, TInt aIndex) const; |
|
101 const TDesC& GetConfigurationFileL(const CMtfConfigurationType::TMtfConfigurationType& aType) const; |
|
102 |
|
103 /** Sets the default configuration for this test case only.*/ |
|
104 void SetTestCaseDefaultConfigurationTypeL(CMtfConfigurationType* aConfiguration); |
|
105 |
|
106 TInt ConvertEnumeratorL(const TDesC& aParameter) const; |
|
107 |
|
108 const CMtfTestParameterStore& ParameterStore() const; |
|
109 void StoreParameterL(CMtfTestParameter* aParameter); |
|
110 const CMtfTestParameter& ObtainParameterL(const TDesC& aName) const; |
|
111 |
|
112 enum TMtfTestCaseState |
|
113 { |
|
114 EMtfTestCaseInitialState, |
|
115 EMtfTestCaseExecutingSetup, |
|
116 EMtfTestCaseExecutingTest, |
|
117 EMtfTestCaseCheckingPostconditions, |
|
118 EMtfTestCaseTestCompleted |
|
119 }; |
|
120 |
|
121 const CMtfTestServer& Server() { return iTestServer; } |
|
122 |
|
123 protected: |
|
124 CMtfTestCase(const CMtfTestServer& aTestServer, const TBool& aScripted, const TBool& aSynchronous); |
|
125 void ConstructL(); |
|
126 |
|
127 private: |
|
128 |
|
129 virtual void SetupTestCaseL()=0; |
|
130 virtual void ExecuteTestCaseL()=0; |
|
131 virtual void CheckPostConditionsL()=0; |
|
132 |
|
133 /** Can be overridden if this section is not synchronous. By default returns true. */ |
|
134 virtual TBool SetupTestCaseIsSynchronous() const; |
|
135 |
|
136 /** Can be overridden if this section is not synchronous. By default returns true. */ |
|
137 virtual TBool ExecuteTestCaseIsSynchronous() const; |
|
138 |
|
139 /** Can be overridden if this section is not synchronous. By default returns true. */ |
|
140 virtual TBool CheckPostconditionsIsSynchronous() const; |
|
141 |
|
142 void ExecuteActionsL(); |
|
143 void ChangeState(); |
|
144 |
|
145 private: |
|
146 RPointerArray<CMtfTestAction> iQueuedActions; |
|
147 RPointerArray<CMtfTestAction> iCurrentActions; |
|
148 RPointerArray<CMtfTestAction> iCompletedActions; |
|
149 TInt iWaitListCount; |
|
150 CMtfTestParameterStore* iParameterStore; |
|
151 TMtfTestCaseState iCurrentState; |
|
152 TBool iScriptedTestCase; |
|
153 TBool iActiveSchedulerRunning; |
|
154 TBool iSynchronous; // used if scripted |
|
155 CActiveScheduler* iScheduler; |
|
156 RPointerArray<CMtfConfigurationType> iTestCaseDefaultConfigurations; |
|
157 const CMtfTestServer& iTestServer; |
|
158 }; |
|
159 |
|
160 |
|
161 /** Used for optional parameters. This function requires a default value for the optional parameter to be |
|
162 provided. This function should be a member function of CMtfTestCase but unfortunately member template functions |
|
163 are not supported by all three compilers. */ |
|
164 template<class T> |
|
165 T* ObtainParameterReferenceL(CMtfTestCase& aTestCase, const TDesC& aParameterName,T* aDefault) |
|
166 { |
|
167 // if parameter is not provided use default |
|
168 if (aParameterName == KMtfDontCare) |
|
169 { |
|
170 return aDefault; |
|
171 } |
|
172 |
|
173 return ObtainParameterReferenceL<T>(aTestCase,aParameterName); |
|
174 } |
|
175 |
|
176 /** Used to obtain non-optional reference parameters. This function should be a member function of CMtfTestCase |
|
177 but unfortunately member template functions are not supported by all three compilers. Type T and the type of the |
|
178 requested parameter must match exactly, otherwise the function leaves. T must be either a CBase derived class or HBufC. */ |
|
179 template<class T> |
|
180 T* ObtainParameterReferenceL(CMtfTestCase& aTestCase, const TDesC& aParameterName) |
|
181 { |
|
182 // if optional leave |
|
183 if (aParameterName == KMtfDontCare) |
|
184 { |
|
185 User::Leave(KErrNotFound); |
|
186 } |
|
187 |
|
188 // obtain type information for T |
|
189 TMtfTestParameterType<T> parameterType; |
|
190 TMtfTestParameterGeneralType generalTypeId = parameterType.GeneralTypeId(); |
|
191 TMtfTestParameterSpecificType specificTypeId = parameterType.SpecificTypeId(); |
|
192 |
|
193 // This function must only be called with T being either a CBase derived class |
|
194 // or HBufC, otherwise it is a programming error. |
|
195 // can also be called with an RArray type ptr |
|
196 |
|
197 __ASSERT_ALWAYS( (generalTypeId == EMtfCBaseType) || (generalTypeId == EMtfHBufCType) || (generalTypeId == EMtfValueType) , |
|
198 CMtfTestAction::Panic(CMtfTestAction::EMtfNonReferenceParameter)); |
|
199 |
|
200 T* returnPtr = NULL; |
|
201 |
|
202 if (generalTypeId == EMtfHBufCType) |
|
203 { |
|
204 // if hbufc check if it is a constant descriptor |
|
205 if (aParameterName[0] == '\"') |
|
206 { |
|
207 if (aParameterName[aParameterName.Length()-1] == '\"') |
|
208 { |
|
209 // find parameter in const store first |
|
210 |
|
211 if (specificTypeId == EMtfHBufC) |
|
212 { |
|
213 // add the constant to parameter store |
|
214 |
|
215 HBufC* buf = HBufC::NewLC(aParameterName.Length()-2); |
|
216 |
|
217 for(TInt c=0; c<aParameterName.Length()-2; c++) |
|
218 buf->Des().Append(aParameterName[c+1]); |
|
219 |
|
220 // parameter store takes ownership |
|
221 |
|
222 CMtfTestParameter* newParameter = CMtfTestParameter::NewL(aParameterName,generalTypeId,specificTypeId,reinterpret_cast<TAny*>(buf)); |
|
223 CleanupStack::PushL(newParameter); |
|
224 aTestCase.StoreParameterL(newParameter); |
|
225 CleanupStack::Pop(2,buf); |
|
226 returnPtr = reinterpret_cast<T*>(buf); |
|
227 } |
|
228 else if (specificTypeId == EMtfHBufC8) |
|
229 { |
|
230 HBufC8* buf = HBufC8::NewLC(aParameterName.Length()-2); |
|
231 |
|
232 for(TInt c=0; c<aParameterName.Length()-2; c++) |
|
233 buf->Des().Append(aParameterName[c+1]); |
|
234 |
|
235 CMtfTestParameter* newParameter = CMtfTestParameter::NewL(aParameterName,generalTypeId,specificTypeId,reinterpret_cast<TAny*>(buf)); |
|
236 CleanupStack::PushL(newParameter); |
|
237 aTestCase.StoreParameterL(newParameter); |
|
238 CleanupStack::Pop(2,buf); |
|
239 returnPtr = reinterpret_cast<T*>(buf); |
|
240 } |
|
241 else |
|
242 User::Panic(KMtfTypeMismatch,0); |
|
243 } |
|
244 } |
|
245 } |
|
246 |
|
247 if(returnPtr == NULL) // not a constant descriptor |
|
248 { |
|
249 const CMtfTestParameter& parameter = aTestCase.ObtainParameterL(aParameterName); |
|
250 |
|
251 __ASSERT_ALWAYS(generalTypeId == parameter.GeneralTypeId(), User::Panic(KMtfTypeMismatch,0)); |
|
252 __ASSERT_ALWAYS(specificTypeId == parameter.SpecificTypeId(), User::Panic(KMtfTypeMismatch,0)); |
|
253 |
|
254 returnPtr = reinterpret_cast<T*>(parameter.Parameter()); |
|
255 } |
|
256 return returnPtr; |
|
257 } |
|
258 |
|
259 |
|
260 /** Used for value and reference parameters. */ |
|
261 template<class T> |
|
262 void StoreParameterL(CMtfTestCase& aTestCase,T& aPtr, const TDesC& aName) |
|
263 { |
|
264 // if the parameter is "don't care" then don't store the parameter |
|
265 if (aName == KMtfDontCare) |
|
266 { |
|
267 return; |
|
268 } |
|
269 |
|
270 // obtain type information for T |
|
271 TMtfTestParameterType<T> parameterType; |
|
272 TMtfTestParameterGeneralType generalTypeId = parameterType.GeneralTypeId(); |
|
273 TMtfTestParameterSpecificType specificTypeId = parameterType.SpecificTypeId(); |
|
274 |
|
275 CMtfTestParameter* newParameter=NULL; |
|
276 // TPckgC<T> pack(aPtr); |
|
277 // HBufC8 *valueStorage; |
|
278 |
|
279 switch(generalTypeId) |
|
280 { |
|
281 case EMtfCBaseType: |
|
282 case EMtfHBufCType: |
|
283 { |
|
284 newParameter = CMtfTestParameter::NewL( |
|
285 aName,generalTypeId,specificTypeId,reinterpret_cast<TAny*>(&aPtr)); |
|
286 CleanupStack::PushL(newParameter); |
|
287 aTestCase.StoreParameterL(newParameter); |
|
288 CleanupStack::Pop(newParameter); |
|
289 return; |
|
290 } |
|
291 case EMtfValueType: |
|
292 if(specificTypeId == EMtfTTime) |
|
293 { |
|
294 newParameter = CMtfTestParameter::NewL( |
|
295 aName,generalTypeId,specificTypeId,reinterpret_cast<TAny*>(&aPtr)); |
|
296 CleanupStack::PushL(newParameter); |
|
297 aTestCase.StoreParameterL(newParameter); |
|
298 CleanupStack::Pop(newParameter); |
|
299 return; |
|
300 } |
|
301 else |
|
302 { |
|
303 TPckgC<T> pack(aPtr); |
|
304 HBufC8 *valueStorage = pack.AllocLC(); |
|
305 newParameter = CMtfTestParameter::NewL( |
|
306 aName,generalTypeId,specificTypeId,reinterpret_cast<TAny*>(valueStorage)); |
|
307 CleanupStack::PushL(newParameter); |
|
308 aTestCase.StoreParameterL(newParameter); |
|
309 CleanupStack::Pop(2,valueStorage); |
|
310 return; |
|
311 } |
|
312 case EMtfEnumeratorType: |
|
313 { |
|
314 TPckgC<T> pack(aPtr); |
|
315 HBufC8 *valueStorage = pack.AllocLC(); |
|
316 newParameter = CMtfTestParameter::NewL( |
|
317 aName,generalTypeId,specificTypeId,reinterpret_cast<TAny*>(valueStorage)); |
|
318 CleanupStack::PushL(newParameter); |
|
319 aTestCase.StoreParameterL(newParameter); |
|
320 CleanupStack::Pop(2,valueStorage); |
|
321 return; |
|
322 } |
|
323 default: |
|
324 User::Panic(KMtfTypeMismatch,0); |
|
325 } |
|
326 } |
|
327 |
|
328 /** Usef for optional value parameters. A default value must be provided. */ |
|
329 template<class T> |
|
330 T ObtainValueParameterL(CMtfTestCase& aTestCase, const TDesC& aParameterName,T aDefault) |
|
331 { |
|
332 if (aParameterName == KMtfDontCare) |
|
333 { |
|
334 return aDefault; |
|
335 } |
|
336 |
|
337 return ObtainValueParameterL<T>(aTestCase,aParameterName); |
|
338 } |
|
339 |
|
340 /** Used for non-optional value parameters. TInt parameters and enumerator parameters may be constant values. */ |
|
341 template<class T> |
|
342 T ObtainValueParameterL(CMtfTestCase& aTestCase, const TDesC& aParameterName) |
|
343 { |
|
344 // if optional leave |
|
345 if (aParameterName == KMtfDontCare) |
|
346 { |
|
347 User::Leave(KErrNotFound); |
|
348 } |
|
349 |
|
350 T result; |
|
351 T* resultPtr = NULL; |
|
352 |
|
353 TMtfTestParameterType<T> parameterType; |
|
354 TMtfTestParameterGeneralType generalTypeId = parameterType.GeneralTypeId(); |
|
355 TMtfTestParameterSpecificType specificTypeId = parameterType.SpecificTypeId(); |
|
356 |
|
357 // check that id is value |
|
358 __ASSERT_ALWAYS(((generalTypeId == EMtfValueType) || (generalTypeId == EMtfEnumeratorType)),User::Panic(KMtfTypeMismatch,0)); |
|
359 |
|
360 if (generalTypeId == EMtfEnumeratorType) |
|
361 { |
|
362 // check if it is a constant enumerator |
|
363 if (CMtfEnumeratorConverter::IsConstantEnumerator(aParameterName)) |
|
364 { |
|
365 *reinterpret_cast<TInt*>(&result) = aTestCase.ConvertEnumeratorL(aParameterName); |
|
366 resultPtr = &result; |
|
367 } |
|
368 } |
|
369 else if (specificTypeId == EMtfTInt) |
|
370 { |
|
371 // if TInt then check if it is a constant parameter |
|
372 TLex converter(aParameterName); |
|
373 |
|
374 if (converter.Val(*(reinterpret_cast<TInt*>(&result))) == KErrNone) |
|
375 { |
|
376 // const parameter |
|
377 resultPtr = &result; |
|
378 } |
|
379 } |
|
380 |
|
381 if(resultPtr == NULL) |
|
382 { |
|
383 const CMtfTestParameter& parameter=aTestCase.ObtainParameterL(aParameterName); |
|
384 |
|
385 __ASSERT_ALWAYS(generalTypeId == parameter.GeneralTypeId(), User::Panic(KMtfTypeMismatch,0)); |
|
386 __ASSERT_ALWAYS(specificTypeId == parameter.SpecificTypeId(), User::Panic(KMtfTypeMismatch,0)); |
|
387 |
|
388 HBufC8* buf=reinterpret_cast<HBufC8*>(parameter.Parameter()); |
|
389 T value; |
|
390 TPckgC<T> unpack(value); |
|
391 unpack.Set(*buf); |
|
392 result = unpack(); |
|
393 resultPtr = &result; |
|
394 } |
|
395 |
|
396 return *resultPtr; |
|
397 } |
|
398 |
|
399 /** Deletes the named parameter. */ |
|
400 template<class T> |
|
401 #if defined (__WINS__) |
|
402 T* // vc6bug - doesn't expand to correct type if T is not employed as param or return |
|
403 #else |
|
404 void // normal case |
|
405 #endif |
|
406 DeleteParameterL(CMtfTestCase& aTestCase, const TDesC& aParameterName) |
|
407 { |
|
408 TMtfTestParameterType<T> parameterType; |
|
409 TMtfTestParameterGeneralType generalTypeId = parameterType.GeneralTypeId(); |
|
410 TMtfTestParameterSpecificType specificTypeId = parameterType.SpecificTypeId(); |
|
411 |
|
412 const CMtfTestParameter& parameter = aTestCase.ObtainParameterL(aParameterName); |
|
413 |
|
414 __ASSERT_ALWAYS(generalTypeId == parameter.GeneralTypeId(), User::Panic(KMtfTypeMismatch,0)); |
|
415 __ASSERT_ALWAYS(specificTypeId == parameter.SpecificTypeId(), User::Panic(KMtfTypeMismatch,0)); |
|
416 |
|
417 aTestCase.DeleteParameterL(aParameterName); |
|
418 #if defined (__WINS__) |
|
419 return (reinterpret_cast<T*>(0)); // vc6bug |
|
420 #endif |
|
421 } |
|
422 |
|
423 |
|
424 #endif |