|
1 // Copyright (c) 2008-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 the License "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 #define __E32TEST_EXTENSION__ |
|
17 #include <e32test.h> |
|
18 #include <e32def.h> |
|
19 #include <e32def_private.h> |
|
20 #include "t_newldd.h" |
|
21 #include "t_new_classes.h" |
|
22 |
|
23 RTest test(_L("Testing Operator New")); |
|
24 |
|
25 TInt RNewLddTest::DoControl(TInt aFunction) |
|
26 { |
|
27 return RBusLogicalChannel::DoControl(aFunction); |
|
28 } |
|
29 |
|
30 TInt RNewLddTest::Open() |
|
31 { |
|
32 return DoCreate(KLddName,TVersion(0,1,1),KNullUnit,NULL,NULL); |
|
33 } |
|
34 |
|
35 RNewLddTest lddconn; |
|
36 |
|
37 TInt TestNew() |
|
38 { |
|
39 return lddconn.DoControl(RNewLddTest::ENew); |
|
40 } |
|
41 TInt TestPlacementVectorNew() |
|
42 { |
|
43 return lddconn.DoControl(RNewLddTest::EPlacementVectorNew); |
|
44 } |
|
45 TInt TestVectorNew() |
|
46 { |
|
47 return lddconn.DoControl(RNewLddTest::EVectorNew); |
|
48 } |
|
49 TInt TestPlacementNew() |
|
50 { |
|
51 return lddconn.DoControl(RNewLddTest::EPlacementNew); |
|
52 } |
|
53 |
|
54 void UserSideTestNewOOM() |
|
55 { |
|
56 RDebug::Printf("User-Side: operator new OOM"); |
|
57 //OOM tests: should not throw |
|
58 |
|
59 #define TEST_NEW_OOM(CLASS) \ |
|
60 RDebug::Printf("new " #CLASS);\ |
|
61 {\ |
|
62 CLASS* p##CLASS = new CLASS;\ |
|
63 test_Equal(NULL, p##CLASS);\ |
|
64 } |
|
65 |
|
66 TEST_NEW_OOM(XVeryLargeClassCtorAndDtor); |
|
67 TEST_NEW_OOM(XVeryLargeClassCtorOnly); |
|
68 TEST_NEW_OOM(XVeryLargeClassDtorOnly); |
|
69 TEST_NEW_OOM(XVeryLargeClassNoTors); |
|
70 } |
|
71 |
|
72 void UserSideTestNewConstruction() |
|
73 { |
|
74 RDebug::Printf("User-Side: operator new non-OOM"); |
|
75 //Non-OOM: |
|
76 |
|
77 |
|
78 #define TEST_NEW_CONSTRUCTION(CLASS) \ |
|
79 RDebug::Printf("new " #CLASS);\ |
|
80 {\ |
|
81 CLASS* p##CLASS = new CLASS;\ |
|
82 test_NotNull(p##CLASS);\ |
|
83 test_Equal(EConstructed, (p##CLASS)->iState);\ |
|
84 delete p##CLASS;\ |
|
85 } |
|
86 |
|
87 TEST_NEW_CONSTRUCTION(XCtorAndDtor) |
|
88 TEST_NEW_CONSTRUCTION(XCtorOnly) |
|
89 |
|
90 |
|
91 #define TEST_NEW(CLASS) \ |
|
92 RDebug::Printf("new " #CLASS);\ |
|
93 {\ |
|
94 CLASS* p##CLASS = new CLASS;\ |
|
95 test_NotNull(p##CLASS);\ |
|
96 delete p##CLASS;\ |
|
97 } |
|
98 TEST_NEW(XDtorOnly) |
|
99 TEST_NEW(XNoTors) |
|
100 } |
|
101 |
|
102 void UserSideTestNew() |
|
103 { |
|
104 UserSideTestNewOOM(); |
|
105 UserSideTestNewConstruction(); |
|
106 } |
|
107 |
|
108 void TrappedUserSideTestNew() |
|
109 { |
|
110 RDebug::Printf("TRAPPED User-Side: operator new"); |
|
111 //OOM tests: should not throw |
|
112 |
|
113 #define TEST_NEW_ELEAVE_OOM(CLASS) \ |
|
114 RDebug::Printf("new(ELeave) " #CLASS);\ |
|
115 {\ |
|
116 TRAPD(r, new(ELeave) (CLASS));\ |
|
117 test_Equal(KErrNoMemory, r);\ |
|
118 } |
|
119 |
|
120 TEST_NEW_ELEAVE_OOM(XVeryLargeClassCtorAndDtor); |
|
121 TEST_NEW_ELEAVE_OOM(XVeryLargeClassCtorOnly); |
|
122 TEST_NEW_ELEAVE_OOM(XVeryLargeClassDtorOnly); |
|
123 TEST_NEW_ELEAVE_OOM(XVeryLargeClassNoTors); |
|
124 |
|
125 |
|
126 |
|
127 RDebug::Printf("User-Side: operator new non-OOM"); |
|
128 //Non-OOM: |
|
129 |
|
130 #define TEST_NEW_ELEAVE(CLASS, TEST_CTOR ) \ |
|
131 RDebug::Printf("new(ELeave) " #CLASS);\ |
|
132 {\ |
|
133 CLASS* p##CLASS=NULL;\ |
|
134 TRAPD(r, p##CLASS = new(ELeave) (CLASS));\ |
|
135 test_KErrNone(r);\ |
|
136 volatile TBool testCtor=(TEST_CTOR);\ |
|
137 if(testCtor)\ |
|
138 {\ |
|
139 test_Equal(EConstructed, (p##CLASS)->iState);\ |
|
140 }\ |
|
141 delete p##CLASS;\ |
|
142 } |
|
143 |
|
144 TEST_NEW_ELEAVE(XCtorAndDtor, ETrue); |
|
145 TEST_NEW_ELEAVE(XCtorOnly, ETrue); |
|
146 TEST_NEW_ELEAVE(XDtorOnly, EFalse); |
|
147 TEST_NEW_ELEAVE(XNoTors, EFalse); |
|
148 } |
|
149 |
|
150 |
|
151 #define TEST_ARRAY_CONSTRUCTION(ARRAY, LENGTH)\ |
|
152 {\ |
|
153 for(TInt i=0; i<(LENGTH); ++i)\ |
|
154 {\ |
|
155 test_Equal(EConstructed, ARRAY[i].iState);\ |
|
156 }\ |
|
157 } |
|
158 |
|
159 void UserSideTestVectorNew() |
|
160 { |
|
161 RDebug::Printf("User-Side:vector operator new"); |
|
162 RDebug::Printf("OOM tests"); |
|
163 |
|
164 #define TEST_VEC_NEW_OOM(CLASS) \ |
|
165 RDebug::Printf("new " #CLASS "[%d]", KOOMArraySize );\ |
|
166 {\ |
|
167 CLASS* p##CLASS = new CLASS[KOOMArraySize];\ |
|
168 test_Equal(NULL, p##CLASS);\ |
|
169 } |
|
170 |
|
171 TEST_VEC_NEW_OOM(XCtorAndDtor); |
|
172 TEST_VEC_NEW_OOM(XCtorOnly); |
|
173 TEST_VEC_NEW_OOM(XDtorOnly); |
|
174 TEST_VEC_NEW_OOM(XNoTors); |
|
175 |
|
176 RDebug::Printf("non-OOM tests"); |
|
177 |
|
178 #define TEST_VEC_NEW(CLASS, ARRAY_LENGTH, TEST_CTOR) \ |
|
179 RDebug::Printf("new " #CLASS "[%d]", ARRAY_LENGTH);\ |
|
180 {\ |
|
181 CLASS* p##CLASS = new CLASS[(ARRAY_LENGTH)];\ |
|
182 test_NotNull(p##CLASS);\ |
|
183 volatile TBool testCtor=(TEST_CTOR);\ |
|
184 if(testCtor)\ |
|
185 {\ |
|
186 TEST_ARRAY_CONSTRUCTION(p##CLASS, ARRAY_LENGTH);\ |
|
187 }\ |
|
188 delete[] p##CLASS;\ |
|
189 } |
|
190 |
|
191 TEST_VEC_NEW(XCtorAndDtor, KTestArrayLength, ETrue); |
|
192 TEST_VEC_NEW(XCtorOnly, KTestArrayLength, ETrue); |
|
193 TEST_VEC_NEW(XDtorOnly, KTestArrayLength, EFalse); |
|
194 TEST_VEC_NEW(XNoTors, KTestArrayLength, EFalse); |
|
195 } |
|
196 |
|
197 void TrappedUserSideTestVectorNew() |
|
198 { |
|
199 RDebug::Printf("User-Side:vector operator new"); |
|
200 RDebug::Printf("OOM tests"); |
|
201 |
|
202 #define TEST_VEC_NEW_ELEAVE_OOM(CLASS) \ |
|
203 RDebug::Printf("new(ELeave) " #CLASS "[%d]", KOOMArraySize );\ |
|
204 {\ |
|
205 TRAPD(r, new(ELeave) CLASS[KOOMArraySize];)\ |
|
206 test_Equal(KErrNoMemory, r);\ |
|
207 } |
|
208 |
|
209 TEST_VEC_NEW_ELEAVE_OOM(XCtorAndDtor); |
|
210 TEST_VEC_NEW_ELEAVE_OOM(XCtorOnly); |
|
211 TEST_VEC_NEW_ELEAVE_OOM(XDtorOnly); |
|
212 TEST_VEC_NEW_ELEAVE_OOM(XNoTors); |
|
213 |
|
214 |
|
215 |
|
216 RDebug::Printf("non-OOM tests"); |
|
217 #define TEST_VEC_NEW_ELEAVE(CLASS, ARRAY_LENGTH, TEST_CTOR) \ |
|
218 RDebug::Printf("new(ELeave) " #CLASS "[%d]", ARRAY_LENGTH);\ |
|
219 {\ |
|
220 CLASS* p##CLASS = NULL;\ |
|
221 TRAPD(r, p##CLASS = new(ELeave) CLASS[(ARRAY_LENGTH)]);\ |
|
222 test_KErrNone(r);\ |
|
223 TBool testCtor=(TEST_CTOR);\ |
|
224 if(testCtor)\ |
|
225 {\ |
|
226 TEST_ARRAY_CONSTRUCTION(p##CLASS, ARRAY_LENGTH);\ |
|
227 }\ |
|
228 delete[] p##CLASS;\ |
|
229 } |
|
230 |
|
231 TEST_VEC_NEW_ELEAVE(XCtorAndDtor, KTestArrayLength, ETrue); |
|
232 TEST_VEC_NEW_ELEAVE(XCtorOnly, KTestArrayLength, ETrue); |
|
233 TEST_VEC_NEW_ELEAVE(XDtorOnly, KTestArrayLength, EFalse); |
|
234 TEST_VEC_NEW_ELEAVE(XNoTors, KTestArrayLength, EFalse); |
|
235 } |
|
236 |
|
237 void UserSideTestPlacementNew() |
|
238 { |
|
239 RDebug::Printf("::UserSideTestPlacementNew"); |
|
240 |
|
241 #define TEST_PLACMENT_NEW(CLASS, POST_CTOR_STATE, POST_DTOR_STATE)\ |
|
242 {\ |
|
243 void* someram = User::AllocZ(sizeof(CLASS));\ |
|
244 test_NotNull(someram);\ |
|
245 RDebug::Printf("new (someram) " #CLASS);\ |
|
246 CLASS* p##CLASS = new (someram) CLASS;\ |
|
247 test_Equal(someram, p##CLASS);\ |
|
248 test_Equal(POST_CTOR_STATE, p##CLASS->iState);\ |
|
249 p##CLASS->~CLASS();\ |
|
250 test_Equal(POST_DTOR_STATE, p##CLASS->iState);\ |
|
251 User::Free(someram);\ |
|
252 p##CLASS=NULL;\ |
|
253 }\ |
|
254 |
|
255 TEST_PLACMENT_NEW(XCtorAndDtor, EConstructed, EDeconstructed); |
|
256 TEST_PLACMENT_NEW(XCtorOnly, EConstructed, EConstructed); |
|
257 TEST_PLACMENT_NEW(XDtorOnly, ENull, EDeconstructed); |
|
258 TEST_PLACMENT_NEW(XNoTors, ENull, ENull); |
|
259 } |
|
260 |
|
261 |
|
262 void UserSideTestPlacementVectorNew() |
|
263 { |
|
264 __UHEAP_MARK; |
|
265 |
|
266 RDebug::Printf("::UserSideTestPlacementVectorNew"); |
|
267 |
|
268 #define TEST_VEC_PLACEMENT_NEW(CLASS, ARRAY_LENGTH, POST_CTOR_STATE, POST_DTOR_STATE)\ |
|
269 RDebug::Printf("new(someram) " #CLASS "[%d]", ARRAY_LENGTH);\ |
|
270 {\ |
|
271 void* someram = User::AllocZ(sizeof(CLASS) * ARRAY_LENGTH);\ |
|
272 test_NotNull(someram);\ |
|
273 CLASS* p##CLASS = new (someram) CLASS[(ARRAY_LENGTH)];\ |
|
274 for(TInt i=0; i<(ARRAY_LENGTH); ++i)\ |
|
275 {\ |
|
276 test_Equal(POST_CTOR_STATE, p##CLASS[i].iState);\ |
|
277 p##CLASS[i].~CLASS();\ |
|
278 test_Equal(POST_DTOR_STATE, p##CLASS[i].iState);\ |
|
279 }\ |
|
280 User::Free(someram);\ |
|
281 } |
|
282 |
|
283 TEST_VEC_PLACEMENT_NEW(XCtorAndDtor, KTestArrayLength, EConstructed, EDeconstructed); |
|
284 TEST_VEC_PLACEMENT_NEW(XCtorOnly, KTestArrayLength, EConstructed, EConstructed); |
|
285 TEST_VEC_PLACEMENT_NEW(XDtorOnly, KTestArrayLength, ENull, EDeconstructed); |
|
286 TEST_VEC_PLACEMENT_NEW(XNoTors, KTestArrayLength, ENull, ENull); |
|
287 |
|
288 __UHEAP_MARKEND; |
|
289 } |
|
290 |
|
291 |
|
292 TInt E32Main() |
|
293 { |
|
294 __UHEAP_MARK; |
|
295 |
|
296 test.Start(_L("Testing operator new")); |
|
297 |
|
298 test.Next(_L("Installing LDD")); |
|
299 TInt r=User::LoadLogicalDevice(KKInstallLddName); |
|
300 test(r==KErrNone || r==KErrAlreadyExists); |
|
301 |
|
302 __KHEAP_MARK; |
|
303 |
|
304 #define TEST_THIS(X) test.Next(_L(#X)); (X) |
|
305 |
|
306 TEST_THIS(UserSideTestNew()); |
|
307 TEST_THIS(UserSideTestPlacementNew()); |
|
308 |
|
309 // Workaround for bug in MSVC6/CW compilers. The following test case fails on |
|
310 // WINS, WINSCW and X86 targets (not X86GCC), where the placement vector new |
|
311 // operator does not behave as expected, ultimately resulting in heap corruption |
|
312 // when the parameter to placement array new is passed on the stack. |
|
313 #if !(defined(__WINS__) || (defined(__VC32__) && (_MSC_VER < 1300))) |
|
314 TEST_THIS(UserSideTestPlacementVectorNew()); |
|
315 #else |
|
316 test.Next(_L("Emulator and/or VC32 - Skipped: UserSideTestPlacementVectorNew")); |
|
317 #endif |
|
318 |
|
319 TEST_THIS(UserSideTestVectorNew()); |
|
320 TEST_THIS(TrappedUserSideTestNew()); |
|
321 TEST_THIS(TrappedUserSideTestVectorNew()); |
|
322 |
|
323 r=lddconn.Open(); |
|
324 test_KErrNone(r); |
|
325 |
|
326 test.Next(_L("Kernel-side:Normal operator new")); |
|
327 r = TestNew(); |
|
328 test_KErrNone(r); |
|
329 |
|
330 test.Next(_L("Kernel-side:Placement operator new")); |
|
331 r = TestPlacementNew(); |
|
332 test_KErrNone(r); |
|
333 |
|
334 test.Next(_L("Kernel-side:Placement Vector operator new")); |
|
335 r = TestPlacementVectorNew(); |
|
336 test_KErrNone(r); |
|
337 |
|
338 test.Next(_L("Kernel-side:Vector operator new")); |
|
339 r = TestVectorNew(); |
|
340 test_KErrNone(r); |
|
341 |
|
342 r = RTest::CloseHandleAndWaitForDestruction(lddconn); |
|
343 test_KErrNone(r); |
|
344 |
|
345 test.End(); |
|
346 test.Close(); |
|
347 |
|
348 __KHEAP_MARKEND; |
|
349 __UHEAP_MARKEND; |
|
350 return KErrNone; |
|
351 } |
|
352 |