|
1 // Copyright (c) 1997-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 // |
|
15 |
|
16 #include "ASTstAlarmTest.h" |
|
17 |
|
18 // Globals |
|
19 static TRequestStatus TheStatus; |
|
20 |
|
21 TAlarmId addAlarm(const TTime& aTime) |
|
22 { |
|
23 TheAlarmTest.Test().Printf(_L("Adding alarm\n")); |
|
24 // |
|
25 TASShdAlarm alarm; |
|
26 alarm.Category() = KASCliCategoryClock; |
|
27 alarm.RepeatDefinition() = EAlarmRepeatDefintionRepeatOnce; |
|
28 alarm.NextDueTime()=aTime; |
|
29 // |
|
30 TheAlarmTest(TheAlarmTest.Session().AlarmAdd(alarm) == KErrNone, __LINE__); |
|
31 const TAlarmId id = alarm.Id(); |
|
32 TheAlarmTest(id != KNullAlarmId, __LINE__); |
|
33 |
|
34 return id; |
|
35 } |
|
36 |
|
37 TAlarmId addUtcAlarm(const TTime& aTime) |
|
38 { |
|
39 TheAlarmTest.Test().Printf(_L("Adding UTC alarm\n")); |
|
40 // |
|
41 TASShdAlarm alarm; |
|
42 alarm.Category()=KASCliCategoryClock; |
|
43 alarm.RepeatDefinition()=EAlarmRepeatDefintionRepeatOnce; |
|
44 alarm.SetUtcNextDueTime(aTime); |
|
45 // |
|
46 TheAlarmTest(TheAlarmTest.Session().AlarmAdd(alarm) == KErrNone, __LINE__); |
|
47 const TAlarmId id = alarm.Id(); |
|
48 TheAlarmTest(id != KNullAlarmId, __LINE__); |
|
49 |
|
50 return id; |
|
51 } |
|
52 |
|
53 |
|
54 void waitForAlarmToExpire() |
|
55 { |
|
56 TheAlarmTest.Test().Printf(_L("Waiting for alarm to expire...\n")); |
|
57 |
|
58 TAlarmId alarmId; |
|
59 TRequestStatus status; |
|
60 FOREVER |
|
61 { |
|
62 TheAlarmTest.Session().NotifyChange(status, alarmId); |
|
63 User::WaitForRequest(status); |
|
64 if (status.Int() == EAlarmChangeEventTimerExpired) |
|
65 break; |
|
66 } |
|
67 } |
|
68 |
|
69 void verifyStates(TInt aQueued, TInt aNotifying=0, TInt aWaitingToNotify=0, TInt aNotified=0, TInt aSnoozed=0) |
|
70 { |
|
71 TInt queued = TheAlarmTest.Session().AlarmCountByState(EAlarmStateQueued); |
|
72 TInt notifying = TheAlarmTest.Session().AlarmCountByState(EAlarmStateNotifying); |
|
73 TInt waitingToNotify = TheAlarmTest.Session().AlarmCountByState(EAlarmStateWaitingToNotify); |
|
74 TInt notified = TheAlarmTest.Session().AlarmCountByState(EAlarmStateNotified); |
|
75 TInt snoozed = TheAlarmTest.Session().AlarmCountByState(EAlarmStateSnoozed); |
|
76 // |
|
77 TheAlarmTest(queued == aQueued, __LINE__); |
|
78 TheAlarmTest(notifying == aNotifying, __LINE__); |
|
79 TheAlarmTest(waitingToNotify == aWaitingToNotify, __LINE__); |
|
80 TheAlarmTest(notified == aNotified, __LINE__); |
|
81 TheAlarmTest(snoozed == aSnoozed, __LINE__); |
|
82 } |
|
83 |
|
84 void checkGlobalSoundState(TAlarmGlobalSoundState aGlobalSoundState) |
|
85 { |
|
86 TAlarmGlobalSoundState soundState; |
|
87 TInt r = TheAlarmTest.Session().GetAlarmSoundState(soundState); |
|
88 TheAlarmTest(r == KErrNone, __LINE__); |
|
89 TheAlarmTest(soundState == aGlobalSoundState, __LINE__); |
|
90 } |
|
91 |
|
92 // |
|
93 // |
|
94 // |
|
95 // |
|
96 // |
|
97 |
|
98 void simpleTestOfGlobalSoundState() |
|
99 { |
|
100 TheAlarmTest.Test().Next(_L("test global sound state")); |
|
101 |
|
102 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
103 TheAlarmTest.Session().SetAlarmSoundState(EAlarmGlobalSoundStateOff); |
|
104 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
105 TheAlarmTest.Session().SetAlarmSoundState(EAlarmGlobalSoundStateOn); |
|
106 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
107 |
|
108 TheAlarmTest.Test().Printf(_L("- test silent period\n")); |
|
109 TheAlarmTest.Session().SetAlarmSoundsSilentFor(TTimeIntervalMinutes(1)); |
|
110 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
111 //wait for the silent period to expire |
|
112 User::After(1000000 * 61); |
|
113 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
114 } |
|
115 |
|
116 void testSoundsSilentUntilL() |
|
117 { |
|
118 TheAlarmTest.Test().Next(_L("test sounds silent until")); |
|
119 |
|
120 TheAlarmTest.TestClearStoreL(); |
|
121 |
|
122 // Add an alarm |
|
123 TTime time; |
|
124 time.HomeTime(); |
|
125 time += TTimeIntervalSeconds(10); |
|
126 TInt alarmId = addAlarm(time); |
|
127 |
|
128 // Silence alarms until 1 minute after this alarm expires - this gets rounded |
|
129 // down to the nearest minute - do here so we have the actual time silenced until |
|
130 time += TTimeIntervalMinutes(1); |
|
131 TDateTime temp(time.DateTime()); |
|
132 temp.SetSecond(0); |
|
133 temp.SetMicroSecond(0); |
|
134 time = temp; |
|
135 |
|
136 TInt r = TheAlarmTest.Session().SetAlarmSoundsSilentUntil(time); |
|
137 TheAlarmTest(r == KErrNone, __LINE__); |
|
138 |
|
139 // Check silent until time |
|
140 TTime checkTime; |
|
141 r = TheAlarmTest.Session().GetAlarmSoundsSilentUntil(checkTime); |
|
142 TheAlarmTest(r == KErrNone, __LINE__); |
|
143 TheAlarmTest(time == checkTime, __LINE__); |
|
144 |
|
145 // Wait for the alarm to expire |
|
146 waitForAlarmToExpire(); |
|
147 |
|
148 // Test sound state is correct |
|
149 TheAlarmTest.Test().Printf(_L("- alarm expired, check silent\r\n")); |
|
150 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
151 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
152 |
|
153 // Wait until sounds are allowed again |
|
154 User::At(time); |
|
155 |
|
156 TheAlarmTest.Test().Printf(_L("- silence expired, check sounding\r\n")); |
|
157 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
158 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
159 |
|
160 // delete this alarm |
|
161 r = TheAlarmTest.Session().AlarmDelete(alarmId); |
|
162 TheAlarmTest(r == KErrNone, __LINE__); |
|
163 } |
|
164 |
|
165 void simpleTestOfSoundsSilentForL() |
|
166 { |
|
167 TheAlarmTest.Test().Next(_L("test sounds silent for - 1")); |
|
168 |
|
169 TheAlarmTest.TestClearStoreL(); |
|
170 |
|
171 // Add 3 alarms, due in 1, 2 and 4 minutes |
|
172 TTime time; |
|
173 time.HomeTime(); |
|
174 time += TTimeIntervalMinutes(1); |
|
175 addAlarm(time); |
|
176 time += TTimeIntervalMinutes(1); |
|
177 addAlarm(time); |
|
178 time += TTimeIntervalMinutes(2); |
|
179 addAlarm(time); |
|
180 |
|
181 // Silence alarms for 3 minutes |
|
182 TInt r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(3); |
|
183 TheAlarmTest(r == KErrNone, __LINE__); |
|
184 |
|
185 //wait for first alarm to expire - should be silent |
|
186 waitForAlarmToExpire(); |
|
187 TheAlarmTest.Test().Printf(_L("- alarm 1 expired, check silent\r\n")); |
|
188 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
189 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
190 |
|
191 //wait for the next alarm to expire - should still be silent |
|
192 waitForAlarmToExpire(); |
|
193 TheAlarmTest.Test().Printf(_L("- alarm 2 expired, check silent\r\n")); |
|
194 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
195 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
196 |
|
197 //wait 1 minute for the silent period to expire |
|
198 User::After(1000000 * 61); |
|
199 TheAlarmTest.Test().Printf(_L("- silence expired, check sound state\r\n")); |
|
200 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
201 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
202 |
|
203 //wait for the next alarm to expire - sounds should be back on |
|
204 waitForAlarmToExpire(); |
|
205 TheAlarmTest.Test().Printf(_L("- alarm 3 expired, check sound state\r\n")); |
|
206 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
207 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
208 } |
|
209 |
|
210 void testSoundsSilentFor() |
|
211 { |
|
212 TheAlarmTest.Test().Next(_L("test sounds silent for - 2")); |
|
213 |
|
214 // add 2 alarms to expire immediately |
|
215 TTime time; |
|
216 time.HomeTime(); |
|
217 addAlarm(time); |
|
218 addAlarm(time); |
|
219 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
220 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
221 |
|
222 // Silence alarms for 1 minute, wait 10 seconds, then silence again for 1 minute |
|
223 TInt r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(1); |
|
224 TheAlarmTest(r == KErrNone, __LINE__); |
|
225 User::After(1000000 * 10); |
|
226 r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(1); |
|
227 TheAlarmTest(r == KErrNone, __LINE__); |
|
228 // expect to be silent for 70 seconds (from alarm time) |
|
229 time += TTimeIntervalSeconds(65); |
|
230 User::At(time); |
|
231 // approx 5 seconds before silence ends - check still silent |
|
232 TheAlarmTest.Test().Printf(_L("- check sound state is still silent\r\n")); |
|
233 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
234 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
235 |
|
236 time += TTimeIntervalSeconds(7); |
|
237 User::At(time); |
|
238 // 2 seconds after silence should end - check state |
|
239 TheAlarmTest.Test().Printf(_L("- check sound state is now sounding\r\n")); |
|
240 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
241 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
242 |
|
243 // test cancel alarm silence |
|
244 TheAlarmTest.Test().Printf(_L("- check sound state is silent\r\n")); |
|
245 r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(10); |
|
246 TheAlarmTest(r == KErrNone, __LINE__); |
|
247 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
248 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
249 |
|
250 TheAlarmTest.Test().Printf(_L("- check silence is canceled\r\n")); |
|
251 r = TheAlarmTest.Session().CancelAlarmSilence(); |
|
252 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
253 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
254 } |
|
255 |
|
256 |
|
257 void testSoundsSilentUntilUtcL() |
|
258 { |
|
259 TheAlarmTest.Test().Next(_L("test sounds silent until")); |
|
260 |
|
261 TheAlarmTest.TestClearStoreL(); |
|
262 |
|
263 // Add an alarm |
|
264 TTime time; |
|
265 time.UniversalTime(); |
|
266 time += TTimeIntervalSeconds(10); |
|
267 TInt alarmId = addUtcAlarm(time); |
|
268 |
|
269 // Silence alarms until 1 minute after this alarm expires - this gets rounded |
|
270 // down to the nearest minute - do here so we have the actual time silenced until |
|
271 TTimeIntervalSeconds offset = User::UTCOffset(); |
|
272 time += TTimeIntervalMinutes(1); |
|
273 time += offset; |
|
274 TDateTime temp(time.DateTime()); |
|
275 temp.SetSecond(0); |
|
276 temp.SetMicroSecond(0); |
|
277 time = temp; |
|
278 |
|
279 TInt r = TheAlarmTest.Session().SetAlarmSoundsSilentUntil(time); |
|
280 TheAlarmTest(r == KErrNone, __LINE__); |
|
281 |
|
282 // Check silent until time |
|
283 TTime checkTime; |
|
284 r = TheAlarmTest.Session().GetAlarmSoundsSilentUntil(checkTime); |
|
285 TheAlarmTest(r == KErrNone, __LINE__); |
|
286 TheAlarmTest(time == checkTime, __LINE__); |
|
287 |
|
288 // Wait for the alarm to expire |
|
289 waitForAlarmToExpire(); |
|
290 |
|
291 // Test sound state is correct |
|
292 TheAlarmTest.Test().Printf(_L("- alarm expired, check silent\r\n")); |
|
293 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
294 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
295 |
|
296 // Wait until sounds are allowed again |
|
297 User::At(time); |
|
298 |
|
299 TheAlarmTest.Test().Printf(_L("- silence expired, check sounding\r\n")); |
|
300 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
301 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
302 |
|
303 // delete this alarm |
|
304 r = TheAlarmTest.Session().AlarmDelete(alarmId); |
|
305 TheAlarmTest(r == KErrNone, __LINE__); |
|
306 } |
|
307 |
|
308 |
|
309 void simpleTestOfSoundsSilentForUtcL() |
|
310 { |
|
311 TheAlarmTest.Test().Next(_L("test sounds silent for - 1")); |
|
312 |
|
313 TheAlarmTest.TestClearStoreL(); |
|
314 |
|
315 // Add 3 alarms, due in 1, 2 and 4 minutes |
|
316 TTime time; |
|
317 time.UniversalTime(); |
|
318 time += TTimeIntervalMinutes(1); |
|
319 addUtcAlarm(time); |
|
320 time += TTimeIntervalMinutes(1); |
|
321 addUtcAlarm(time); |
|
322 time += TTimeIntervalMinutes(2); |
|
323 addUtcAlarm(time); |
|
324 |
|
325 // Silence alarms for 3 minutes |
|
326 TInt r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(3); |
|
327 TheAlarmTest(r == KErrNone, __LINE__); |
|
328 |
|
329 //wait for first alarm to expire - should be silent |
|
330 waitForAlarmToExpire(); |
|
331 TheAlarmTest.Test().Printf(_L("- alarm 1 expired, check silent\r\n")); |
|
332 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
333 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
334 |
|
335 //wait for the next alarm to expire - should still be silent |
|
336 waitForAlarmToExpire(); |
|
337 TheAlarmTest.Test().Printf(_L("- alarm 2 expired, check silent\r\n")); |
|
338 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
339 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
340 |
|
341 //wait 1 minute for the silent period to expire |
|
342 User::After(1000000 * 61); |
|
343 TheAlarmTest.Test().Printf(_L("- silence expired, check sound state\r\n")); |
|
344 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
345 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
346 |
|
347 //wait for the next alarm to expire - sounds should be back on |
|
348 waitForAlarmToExpire(); |
|
349 TheAlarmTest.Test().Printf(_L("- alarm 3 expired, check sound state\r\n")); |
|
350 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
351 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
352 } |
|
353 |
|
354 void testSoundsSilentForUtc() |
|
355 { |
|
356 TheAlarmTest.Test().Next(_L("test sounds silent for - 2")); |
|
357 |
|
358 // add 2 alarms to expire immediately |
|
359 TTimeIntervalSeconds offset = User::UTCOffset(); |
|
360 |
|
361 TTime time; |
|
362 time.UniversalTime(); |
|
363 addUtcAlarm(time); |
|
364 addUtcAlarm(time); |
|
365 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
366 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
367 |
|
368 // Silence alarms for 1 minute, wait 10 seconds, then silence again for 1 minute |
|
369 TInt r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(1); |
|
370 TheAlarmTest(r == KErrNone, __LINE__); |
|
371 User::After(1000000 * 10); |
|
372 r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(1); |
|
373 TheAlarmTest(r == KErrNone, __LINE__); |
|
374 // expect to be silent for 70 seconds (from alarm time) |
|
375 time += TTimeIntervalSeconds(65); |
|
376 User::At(time + offset); |
|
377 // approx 5 seconds before silence ends - check still silent |
|
378 TheAlarmTest.Test().Printf(_L("- check sound state is still silent\r\n")); |
|
379 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
380 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
381 |
|
382 time += TTimeIntervalSeconds(7); |
|
383 User::At(time + offset); |
|
384 // 2 seconds after silence should end - check state |
|
385 TheAlarmTest.Test().Printf(_L("- check sound state is now sounding\r\n")); |
|
386 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
387 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
388 |
|
389 // test cancel alarm silence |
|
390 TheAlarmTest.Test().Printf(_L("- check sound state is silent\r\n")); |
|
391 r = TheAlarmTest.Session().SetAlarmSoundsSilentFor(10); |
|
392 TheAlarmTest(r == KErrNone, __LINE__); |
|
393 checkGlobalSoundState(EAlarmGlobalSoundStateOff); |
|
394 TheAlarmTest(TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
395 |
|
396 TheAlarmTest.Test().Printf(_L("- check silence is canceled\r\n")); |
|
397 r = TheAlarmTest.Session().CancelAlarmSilence(); |
|
398 checkGlobalSoundState(EAlarmGlobalSoundStateOn); |
|
399 TheAlarmTest(!TheAlarmTest.Session().AlarmSoundsTemporarilySilenced(), __LINE__); |
|
400 } |
|
401 |
|
402 /** |
|
403 @SYMTestCaseID PIM-TSOUNDCONTROL-0001 |
|
404 */ |
|
405 static void doTestsL() |
|
406 { |
|
407 TheAlarmTest.Start(_L("@SYMTestCaseID PIM-TSOUNDCONTROL-0001 Connecting to server")); |
|
408 |
|
409 const TInt KGmtOffset = 3600; |
|
410 _LIT(KTime, "20040730:050000.000000"); //In summer time |
|
411 TInt err = User::SetUTCTimeAndOffset(TTime(KTime), KGmtOffset); |
|
412 TheAlarmTest(err == KErrNone, __LINE__); |
|
413 |
|
414 |
|
415 TInt r = TheAlarmTest.Session().Connect(); |
|
416 TheAlarmTest(r == KErrNone, __LINE__); |
|
417 |
|
418 TheAlarmTest.TestClearStoreL(); |
|
419 |
|
420 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler; |
|
421 CleanupStack::PushL(scheduler); |
|
422 CActiveScheduler::Install(scheduler); |
|
423 |
|
424 simpleTestOfGlobalSoundState(); |
|
425 |
|
426 testSoundsSilentUntilL(); |
|
427 simpleTestOfSoundsSilentForL(); |
|
428 testSoundsSilentFor(); |
|
429 |
|
430 testSoundsSilentUntilUtcL(); |
|
431 simpleTestOfSoundsSilentForUtcL(); |
|
432 testSoundsSilentForUtc(); |
|
433 |
|
434 TheAlarmTest.TestClearStoreL(); |
|
435 |
|
436 TheAlarmTest.Session().Close(); |
|
437 |
|
438 CleanupStack::PopAndDestroy(scheduler); |
|
439 } |
|
440 |
|
441 GLDEF_C TInt E32Main() |
|
442 // |
|
443 // Test the alarm server. |
|
444 // |
|
445 { |
|
446 TInt ret = KErrNone; |
|
447 __UHEAP_MARK; |
|
448 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
449 if (!cleanup) |
|
450 return KErrNoMemory; |
|
451 |
|
452 TheAlarmTest.Title(); |
|
453 TheAlarmTest.TestStartServers(); |
|
454 // |
|
455 TRAPD(error, doTestsL()); |
|
456 TheAlarmTest(error == KErrNone, __LINE__); |
|
457 // |
|
458 TRAP(ret,TheAlarmTest.EndL()); |
|
459 TheAlarmTest.Test().Close(); |
|
460 ASTstAlarmTest::Close(); |
|
461 |
|
462 delete cleanup; |
|
463 __UHEAP_MARKEND; |
|
464 return ret; |
|
465 } |