|
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // This contains CTestCase which is the base class for all the TestCase DLLs |
|
15 //just to test p4 |
|
16 |
|
17 // EPOC includes |
|
18 #include <e32base.h> |
|
19 #include <commdb.h> |
|
20 #include <f32file.h> |
|
21 // Test system includes |
|
22 #include "teststepcomsdbg.h" |
|
23 #include <comms-infras/commsdebugutility.h> |
|
24 #include "TestMessage.h" |
|
25 |
|
26 |
|
27 // constructor |
|
28 CTestStepFlogger::CTestStepFlogger() |
|
29 { |
|
30 } |
|
31 |
|
32 // destructor |
|
33 CTestStepFlogger::~CTestStepFlogger() |
|
34 { |
|
35 } |
|
36 |
|
37 |
|
38 TVerdict CTestStepFlogger::doTestStepPostambleL() |
|
39 { |
|
40 SetTestStepResult(EPass); return TestStepResult(); |
|
41 } |
|
42 |
|
43 |
|
44 TInt CTestStepFlogger::executeStepL() |
|
45 { |
|
46 return KErrGeneral; |
|
47 } |
|
48 |
|
49 TInt CTestStepFlogger::executeStepL( /*aLogger*/ TBool /*aStatus*/) |
|
50 { |
|
51 return KErrGeneral; |
|
52 } |
|
53 |
|
54 |
|
55 TInt CTestStepFlogger::executeStep(CTestStepFlogger& aTestStep) |
|
56 { |
|
57 TInt r = 0; |
|
58 TInt ret= 0; |
|
59 |
|
60 TRAP( r, ret = aTestStep.executeStepL() ); |
|
61 |
|
62 if ( r != KErrNone ) |
|
63 ret = r; |
|
64 |
|
65 return ret; |
|
66 } |
|
67 |
|
68 TInt CTestStepFlogger::executeStep( TBool bypassChecks ) |
|
69 { |
|
70 TInt ret=0; |
|
71 TInt r; |
|
72 |
|
73 // bypassChecks is optional, so many clients don't know to supply it |
|
74 if (bypassChecks) |
|
75 { |
|
76 TRAP( r, ret = executeStepL(bypassChecks) ); |
|
77 } |
|
78 else |
|
79 { |
|
80 TRAP( r, ret = executeStepL() ); |
|
81 } |
|
82 |
|
83 if ( r != KErrNone ) |
|
84 ret = r; |
|
85 |
|
86 return ret; |
|
87 } |
|
88 |
|
89 TInt CTestStepFlogger::executeStep(CTestStepFlogger& aTestStep, TBool aStatus) |
|
90 { |
|
91 TInt result=KErrNone; |
|
92 TRAPD(err,result=aTestStep.executeStepL(aStatus)); |
|
93 return (KErrNone!=err)?err:result; |
|
94 } |
|
95 |
|
96 // |
|
97 //This heap failure member function is used to ensure correct operation in low-memory |
|
98 // situations. It requires the flogger server to be started in order to inform the server |
|
99 // on each loop iteration as to the new memory requirement. Thus, this harness is no |
|
100 // good for cases where the flogger server must be shut down and restarted or |
|
101 // when server is not meant to be running before the test case commences. |
|
102 // |
|
103 TInt CTestStepFlogger::doTestStepWithHeapFailureL( CTestStepFlogger& aTestStep, TInt lowMemory, TInt highMemory, TInt aReturnValue, TBool bypassChecks) |
|
104 /** |
|
105 @param bypassChecks allows a parameter to be passed to the executeStep to let it know that the |
|
106 case is being used for heap checking. This is needed because most flogger methods do |
|
107 not return an error code when they fail to write due to no memory. Thus, when running |
|
108 the heap test the part of the test case which ensures the data was written to disk |
|
109 may fail to find the data, and thus we need to bypass these checks. |
|
110 @param aReturnValue - expected return value if everything works |
|
111 @param lowMemory - amount of memory to start testing at - must be at least 10 lower than highMemory and test must fail due to low memory at this level |
|
112 @param highMemory - amount of memory to stop testing at - if we reach this, test has failed. |
|
113 */ |
|
114 { |
|
115 TInt ret=0; |
|
116 TInt loop; |
|
117 TPtrC8 ptrSubSystemTmp; |
|
118 TPtrC8 ptrComponentTmp; |
|
119 ptrSubSystemTmp.Set(_L8("SubSystem")); |
|
120 ptrComponentTmp.Set(_L8("Component")); |
|
121 |
|
122 RFileLogger logger; |
|
123 User::LeaveIfError(logger.Connect()); |
|
124 CleanupClosePushL(logger); |
|
125 logger.SetLogTags(KStdSubsysTag8, KStdCompTag8); |
|
126 // clear the log so that any previous test data is gone and not detected |
|
127 logger.ClearLog(); |
|
128 User::After(KTimeToLog); |
|
129 |
|
130 for (loop = lowMemory; loop < highMemory ; loop++) |
|
131 { |
|
132 INFO_PRINTF2(_L("%d"),loop); |
|
133 logger.__DbgSetHeapFailure(loop); |
|
134 |
|
135 ret = aTestStep.executeStep(bypassChecks); |
|
136 |
|
137 if ( ret == KErrNoMemory) |
|
138 { |
|
139 //The heap failure has been trapped correctly |
|
140 continue; |
|
141 } |
|
142 else if (( ret == aReturnValue ) && (loop != lowMemory)) |
|
143 { |
|
144 //Test step normal behaviour |
|
145 INFO_PRINTF4(_L("%S PASSED heap failure test, loop = %d return code==%d"), |
|
146 &aTestStep.TestStepName(), loop, ret ); |
|
147 SetTestStepResult(EPass); break; |
|
148 } |
|
149 else |
|
150 { |
|
151 // test step has not returned the exepected error value ( which was either KErrNoMemory or aReturnValue ) |
|
152 INFO_PRINTF5(_L("%S *FAILED* heap failure test, loop=%d return code:%d expected:%d"), |
|
153 &aTestStep.TestStepName(), loop, ret, aReturnValue ); |
|
154 SetTestStepResult(EFail); break; |
|
155 } |
|
156 |
|
157 } |
|
158 // shutdown flogger server so we can see if any memory leaks - flogger svr will panic if there are |
|
159 // This also means the next test does not get any residuals in the log buffers. |
|
160 logger.ClearLog(); |
|
161 logger.__DbgShutDownServer(); |
|
162 CleanupStack::PopAndDestroy(); //logger |
|
163 if (loop == highMemory) |
|
164 { |
|
165 // often the return code isn't checked, so make sure the test harness sees that it failed. |
|
166 SetTestStepResult(EFail); return KErrGeneral; |
|
167 } |
|
168 if ( ret != aReturnValue ) |
|
169 { |
|
170 // often the return code isn't checked, so make sure the test harness sees that it failed. |
|
171 SetTestStepResult(EFail); return KErrGeneral; |
|
172 } |
|
173 return KErrNone; |
|
174 } |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 TInt CTestStepFlogger::DoTestConnect(RFileLogger& aLogger) |
|
181 { |
|
182 TInt ret = KErrNone; |
|
183 TPtrC8 ptrSubSystem; |
|
184 TPtrC8 ptrComponent; |
|
185 ptrSubSystem.Set(_L8("SubSystem")); |
|
186 ptrComponent.Set(_L8("Component")); |
|
187 |
|
188 ret = aLogger.Connect(); |
|
189 if (ret == KErrNone) |
|
190 ret = aLogger.SetLogTags(ptrSubSystem, ptrComponent); //SetLogTags() of Flogger called |
|
191 |
|
192 if (ret == KErrNone) |
|
193 ret = aLogger.ClearLog(); //clear the contents from the log |
|
194 |
|
195 return ret; |
|
196 } |
|
197 |
|
198 |
|
199 TInt CTestStepFlogger::constructFloggerIniL( const TDesC8& additionalConfig ) |
|
200 /** |
|
201 Replace the flogger.ini with a new one made up of the contents of ts_flogger.ini and additionalConfig. |
|
202 @param additionalConfig string with the extra config items to be set in flogger.ini |
|
203 @return KErrNone if no probs, otherwise an error code. |
|
204 @note This function deletes then recreates the flogger.ini file, so during the short time between |
|
205 the delete and the recreate, if flogger server is running, it will report that there were errors in the ini file (because |
|
206 the ini file is not there). |
|
207 */ |
|
208 { |
|
209 RFile theFile; |
|
210 RFile outFile; |
|
211 RFs fileServer; |
|
212 User::LeaveIfError(fileServer.Connect()); |
|
213 HBufC8 * fileContentsHeap; |
|
214 TInt fileSize; |
|
215 TInt returnCode; |
|
216 |
|
217 returnCode = theFile.Open(fileServer,KFloggerTestIniMediaSourceFile,EFileRead); |
|
218 |
|
219 if (returnCode == KErrNone) |
|
220 { |
|
221 theFile.Size(fileSize); |
|
222 |
|
223 // allocate the heap space for the string given size of ts_flogger and |
|
224 // the length of the additional items string. |
|
225 TInt newFileSize = fileSize + additionalConfig.Length(); //just so we can see this during debugging |
|
226 |
|
227 fileContentsHeap = HBufC8::NewLC(newFileSize); |
|
228 |
|
229 TPtr8 fileContentsAppend(fileContentsHeap->Des()); |
|
230 |
|
231 // read into the buffer the contents of ts_flogger.ini |
|
232 User::LeaveIfError(returnCode = theFile.Read(fileContentsAppend)); |
|
233 |
|
234 // append addition items |
|
235 fileContentsAppend.Append(additionalConfig); |
|
236 |
|
237 // We must assume the flogger.ini is either there or not there, |
|
238 // If the flogger.ini is already there, and the flogger server is already running |
|
239 // and watching this file, we cannot do any of the following: |
|
240 //* Open and overwrite - if we overwrite a large file with a smaller one, it fails to overwrite the whole file |
|
241 //* Delete and create - after the delete but before the create flogger server will attempt to access |
|
242 //* use RFile::Replace - between the replace and the write flogger server will attempt access |
|
243 |
|
244 // so we must create a temporary file and then use the file system to overwrite the |
|
245 // current with our temp using "replace" which is an atomic operation as far as flogger server is concerned |
|
246 |
|
247 returnCode = outFile.Create(fileServer,KTempDuringCreationFloggerIniFile,EFileWrite); |
|
248 if (returnCode == KErrNone) |
|
249 { |
|
250 TInt pos = 0; |
|
251 outFile.Seek(ESeekStart,pos); |
|
252 outFile.Write(fileContentsAppend); |
|
253 |
|
254 outFile.Close(); |
|
255 |
|
256 fileServer.Replace(KTempDuringCreationFloggerIniFile,KFloggerIniFile); |
|
257 } |
|
258 CleanupStack::PopAndDestroy(fileContentsHeap); |
|
259 theFile.Close(); |
|
260 } |
|
261 |
|
262 fileServer.Close(); |
|
263 |
|
264 if (returnCode != KErrNone) |
|
265 { |
|
266 return returnCode; |
|
267 } |
|
268 else |
|
269 { |
|
270 return KErrNone; |
|
271 } |
|
272 |
|
273 } |
|
274 |
|
275 TInt CTestStepFlogger::replaceFloggerIniL( const TDesC8& newConfig ) |
|
276 /** |
|
277 Replace the flogger.ini with a new one made up of the contents of newConfig |
|
278 @param newConfig string with all the config items to be set in flogger.ini |
|
279 @return KErrNone if no probs, otherwise an error code. |
|
280 */ |
|
281 { |
|
282 RFile outFile; |
|
283 RFs fileServer; |
|
284 User::LeaveIfError(fileServer.Connect()); |
|
285 HBufC8 * fileContentsHeap; |
|
286 TInt returnCode; |
|
287 |
|
288 // allocate the heap space for the string given size of |
|
289 // the items string. |
|
290 TInt newFileSize = newConfig.Length(); //just so we can see this during debugging |
|
291 |
|
292 fileContentsHeap = HBufC8::NewLC(newFileSize); |
|
293 |
|
294 TPtr8 newFileContents(fileContentsHeap->Des()); |
|
295 |
|
296 // add the config items |
|
297 newFileContents.Append(newConfig); |
|
298 |
|
299 // We must assume the flogger.ini is either there or not there, |
|
300 // If the flogger.ini is already there, and the flogger server is already running |
|
301 // and watching this file, we cannot do any of the following: |
|
302 //* Open and overwrite - if we overwrite a large file with a smaller one, it fails to overwrite the whole file |
|
303 //* Delete and create - after the delete but before the create flogger server will attempt to access |
|
304 //* use RFile::Replace - between the replace and the write flogger server will attempt access |
|
305 |
|
306 // so we must create a temporary file and then use the file system to overwrite the |
|
307 // current with our temp using "replace" which is an atomic operation as far as flogger server is concerned |
|
308 |
|
309 returnCode = outFile.Create(fileServer,KTempDuringCreationFloggerIniFile,EFileWrite); |
|
310 if (returnCode == KErrNone) |
|
311 { |
|
312 TInt pos = 0; |
|
313 outFile.Seek(ESeekStart,pos); |
|
314 outFile.Write(newFileContents); |
|
315 |
|
316 outFile.Close(); |
|
317 |
|
318 fileServer.Replace(KTempDuringCreationFloggerIniFile,KFloggerIniFile); |
|
319 } |
|
320 CleanupStack::PopAndDestroy(fileContentsHeap); |
|
321 |
|
322 fileServer.Close(); |
|
323 |
|
324 if (returnCode != KErrNone) |
|
325 { |
|
326 return returnCode; |
|
327 } |
|
328 else |
|
329 { |
|
330 return KErrNone; |
|
331 } |
|
332 |
|
333 } |
|
334 |
|
335 |
|
336 /** |
|
337 * Function Name : ForceLogFlush |
|
338 * Input parameters : None |
|
339 * Output parameters : RFileLogger |
|
340 * Description : This function writes enough data to flogger to force it to flush its |
|
341 file buffer. We need to do this for heap tests since the timer is disabled during heap tests. |
|
342 Normally, the timer would ensure the buffer is flushed each second. |
|
343 We must write enough data to match the KHeapBufSize (50K) constant in flogger. |
|
344 However, it is usually necessary to wait one second after writing this data to ensure flogger |
|
345 gets a chance to move the data from its queue to the buffer. |
|
346 When determining how much to write, we take into account that flogger will have added the |
|
347 component, subsystem and a few other characters to each line. |
|
348 |
|
349 * |
|
350 */ |
|
351 |
|
352 |
|
353 void CTestStepFlogger::ForceLogFlush(RFileLogger& aLogger) |
|
354 { |
|
355 const TInt KLineLen = KLogBufferSize - KMarginTemplateSize; |
|
356 TBuf8<KLineLen> buf; |
|
357 buf.SetLength(KLineLen); |
|
358 |
|
359 for(TUint8 i = 0; i < KLineLen; i++) |
|
360 { |
|
361 buf[i] = i; |
|
362 } |
|
363 for(TInt j = 0; j < KHeapBufFillIterations; j++) |
|
364 { |
|
365 aLogger.Write(buf); |
|
366 } |
|
367 } |