main
cpp 508 lines 17.3 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 #include "precomp.h"
4
5 using namespace System;
6 using namespace Xunit;
7 using namespace WixInternal::TestSupport;
8
9 namespace DutilTests
10 {
11 struct ArrayValue
12 {
13 DWORD dwNum;
14 void *pvNull1;
15 LPWSTR sczString;
16 void *pvNull2;
17 };
18
19 public ref class MemUtil
20 {
21 public:
22 [Fact]
23 void MemUtilAppendTest()
24 {
25 HRESULT hr = S_OK;
26 SIZE_T cbSize = 0;
27 ArrayValue *rgValues = NULL;
28 DWORD cValues = 0;
29
30 DutilInitialize(&DutilTestTraceError);
31
32 try
33 {
34 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
35 NativeAssert::Succeeded(hr, "Failed to grow array size to 1");
36 ++cValues;
37 SetItem(rgValues + 0, 0);
38
39 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
40 NativeAssert::Succeeded(hr, "Failed to grow array size to 2");
41 ++cValues;
42 SetItem(rgValues + 1, 1);
43
44 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
45 NativeAssert::Succeeded(hr, "Failed to grow array size to 3");
46 ++cValues;
47 SetItem(rgValues + 2, 2);
48
49 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
50 NativeAssert::Succeeded(hr, "Failed to grow array size to 4");
51 ++cValues;
52 SetItem(rgValues + 3, 3);
53
54 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
55 NativeAssert::Succeeded(hr, "Failed to grow array size to 5");
56 ++cValues;
57 SetItem(rgValues + 4, 4);
58
59 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
60 NativeAssert::Succeeded(hr, "Failed to grow array size to 6");
61 ++cValues;
62 SetItem(rgValues + 5, 5);
63
64 // OK, we used growth size 5, so let's try ensuring we have space for 6 (5 + first item) items
65 // and make sure it doesn't grow since we already have enough space
66 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues, sizeof(ArrayValue), 5);
67 NativeAssert::Succeeded(hr, "Failed to ensure array size matches what it should already be");
68
69 hr = MemSizeChecked(rgValues, &cbSize);
70 NativeAssert::Succeeded(hr, "Failed to get current array size");
71
72 if (cbSize != 6 * sizeof(ArrayValue))
73 {
74 hr = E_FAIL;
75 ExitOnFailure(hr, "MemEnsureArraySize is growing an array that is already big enough!");
76 }
77
78 for (DWORD i = 0; i < cValues; ++i)
79 {
80 CheckItem(rgValues + i, i);
81 }
82
83 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
84 NativeAssert::Succeeded(hr, "Failed to grow array size to 7");
85 ++cValues;
86 SetItem(rgValues + 6, 6);
87
88 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
89 NativeAssert::Succeeded(hr, "Failed to grow array size to 7");
90 ++cValues;
91 SetItem(rgValues + 7, 7);
92
93 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
94 NativeAssert::Succeeded(hr, "Failed to grow array size to 7");
95 ++cValues;
96 SetItem(rgValues + 8, 8);
97
98 for (DWORD i = 0; i < cValues; ++i)
99 {
100 CheckItem(rgValues + i, i);
101 }
102 }
103 finally
104 {
105 ReleaseMem(rgValues);
106 }
107
108 LExit:
109 DutilUninitialize();
110 }
111
112 [Fact]
113 void MemUtilInsertTest()
114 {
115 HRESULT hr = S_OK;
116 ArrayValue *rgValues = NULL;
117 DWORD cValues = 0;
118
119 DutilInitialize(&DutilTestTraceError);
120
121 try
122 {
123 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 0, 1, cValues + 1, sizeof(ArrayValue), 5);
124 NativeAssert::Succeeded(hr, "Failed to insert into beginning of empty array");
125 ++cValues;
126 CheckNullItem(rgValues + 0);
127 SetItem(rgValues + 0, 5);
128
129 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 1, 1, cValues + 1, sizeof(ArrayValue), 5);
130 NativeAssert::Succeeded(hr, "Failed to insert at end of array");
131 ++cValues;
132 CheckNullItem(rgValues + 1);
133 SetItem(rgValues + 1, 6);
134
135 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 0, 1, cValues + 1, sizeof(ArrayValue), 5);
136 NativeAssert::Succeeded(hr, "Failed to insert into beginning of array");
137 ++cValues;
138 CheckNullItem(rgValues + 0);
139 SetItem(rgValues + 0, 4);
140
141 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 0, 1, cValues + 1, sizeof(ArrayValue), 5);
142 NativeAssert::Succeeded(hr, "Failed to insert into beginning of array");
143 ++cValues;
144 CheckNullItem(rgValues + 0);
145 SetItem(rgValues + 0, 3);
146
147 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 0, 1, cValues + 1, sizeof(ArrayValue), 5);
148 NativeAssert::Succeeded(hr, "Failed to insert into beginning of array");
149 ++cValues;
150 CheckNullItem(rgValues + 0);
151 SetItem(rgValues + 0, 1);
152
153 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 1, 1, cValues + 1, sizeof(ArrayValue), 5);
154 NativeAssert::Succeeded(hr, "Failed to insert into beginning of array");
155 ++cValues;
156 CheckNullItem(rgValues + 1);
157 SetItem(rgValues + 1, 2);
158
159 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 0, 1, cValues + 1, sizeof(ArrayValue), 5);
160 NativeAssert::Succeeded(hr, "Failed to insert into beginning of array");
161 ++cValues;
162 CheckNullItem(rgValues + 0);
163 SetItem(rgValues + 0, 0);
164
165 for (DWORD i = 0; i < cValues; ++i)
166 {
167 CheckItem(rgValues + i, i);
168 }
169
170 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), cValues + 1, sizeof(ArrayValue), 5);
171 NativeAssert::Succeeded(hr, "Failed to grow array size to 7");
172 ++cValues;
173 CheckNullItem(rgValues + 7);
174 SetItem(rgValues + 7, 7);
175
176 hr = MemInsertIntoArray(reinterpret_cast<LPVOID*>(&rgValues), 8, 1, cValues + 1, sizeof(ArrayValue), 5);
177 NativeAssert::Succeeded(hr, "Failed to insert into beginning of array");
178 ++cValues;
179 CheckNullItem(rgValues + 8);
180 SetItem(rgValues + 8, 8);
181
182 for (DWORD i = 0; i < cValues; ++i)
183 {
184 CheckItem(rgValues + i, i);
185 }
186 }
187 finally
188 {
189 ReleaseMem(rgValues);
190 DutilUninitialize();
191 }
192 }
193
194 [Fact]
195 void MemUtilRemovePreserveOrderTest()
196 {
197 HRESULT hr = S_OK;
198 ArrayValue *rgValues = NULL;
199 DWORD cValues = 0;
200
201 DutilInitialize(&DutilTestTraceError);
202
203 try
204 {
205 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), 10, sizeof(ArrayValue), 10);
206 NativeAssert::Succeeded(hr, "Failed to grow array size to 10");
207
208 cValues = 10;
209 for (DWORD i = 0; i < cValues; ++i)
210 {
211 SetItem(rgValues + i, i);
212 }
213
214 // Remove last item
215 MemRemoveFromArray(rgValues, 9, 1, cValues, sizeof(ArrayValue), TRUE);
216 --cValues;
217
218 for (DWORD i = 0; i < cValues; ++i)
219 {
220 CheckItem(rgValues + i, i);
221 }
222
223 // Remove last two items
224 MemRemoveFromArray(rgValues, 7, 2, cValues, sizeof(ArrayValue), TRUE);
225 cValues -= 2;
226
227 for (DWORD i = 0; i < cValues; ++i)
228 {
229 CheckItem(rgValues + i, i);
230 }
231
232 // Remove first item
233 MemRemoveFromArray(rgValues, 0, 1, cValues, sizeof(ArrayValue), TRUE);
234 --cValues;
235
236 for (DWORD i = 0; i < cValues; ++i)
237 {
238 CheckItem(rgValues + i, i + 1);
239 }
240
241
242 // Remove first two items
243 MemRemoveFromArray(rgValues, 0, 2, cValues, sizeof(ArrayValue), TRUE);
244 cValues -= 2;
245
246 for (DWORD i = 0; i < cValues; ++i)
247 {
248 CheckItem(rgValues + i, i + 3);
249 }
250
251 // Remove middle two items
252 MemRemoveFromArray(rgValues, 1, 2, cValues, sizeof(ArrayValue), TRUE);
253 cValues -= 2;
254
255 CheckItem(rgValues, 3);
256 CheckItem(rgValues + 1, 6);
257
258 // Remove last 2 items to ensure we don't crash
259 MemRemoveFromArray(rgValues, 0, 2, cValues, sizeof(ArrayValue), TRUE);
260 cValues -= 2;
261 }
262 finally
263 {
264 ReleaseMem(rgValues);
265 DutilUninitialize();
266 }
267 }
268
269 [Fact]
270 void MemUtilRemoveFastTest()
271 {
272 HRESULT hr = S_OK;
273 ArrayValue *rgValues = NULL;
274 DWORD cValues = 0;
275
276 DutilInitialize(&DutilTestTraceError);
277
278 try
279 {
280 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), 10, sizeof(ArrayValue), 10);
281 NativeAssert::Succeeded(hr, "Failed to grow array size to 10");
282
283 cValues = 10;
284 for (DWORD i = 0; i < cValues; ++i)
285 {
286 SetItem(rgValues + i, i);
287 }
288
289 // Remove last item
290 MemRemoveFromArray(rgValues, 9, 1, cValues, sizeof(ArrayValue), FALSE);
291 --cValues;
292
293 for (DWORD i = 0; i < cValues; ++i)
294 {
295 CheckItem(rgValues + i, i);
296 }
297
298 // Remove last two items
299 MemRemoveFromArray(rgValues, 7, 2, cValues, sizeof(ArrayValue), FALSE);
300 cValues -= 2;
301
302 for (DWORD i = 0; i < cValues; ++i)
303 {
304 CheckItem(rgValues + i, i);
305 }
306
307 // Remove first item
308 MemRemoveFromArray(rgValues, 0, 1, cValues, sizeof(ArrayValue), FALSE);
309 --cValues;
310
311 CheckItem(rgValues, 6);
312 CheckItem(rgValues + 1, 1);
313 CheckItem(rgValues + 2, 2);
314 CheckItem(rgValues + 3, 3);
315 CheckItem(rgValues + 4, 4);
316 CheckItem(rgValues + 5, 5);
317
318 // Remove first two items
319 MemRemoveFromArray(rgValues, 0, 2, cValues, sizeof(ArrayValue), FALSE);
320 cValues -= 2;
321
322 CheckItem(rgValues, 4);
323 CheckItem(rgValues + 1, 5);
324 CheckItem(rgValues + 2, 2);
325 CheckItem(rgValues + 3, 3);
326
327
328 // Remove middle two items
329 MemRemoveFromArray(rgValues, 1, 2, cValues, sizeof(ArrayValue), FALSE);
330 cValues -= 2;
331
332 CheckItem(rgValues, 4);
333 CheckItem(rgValues + 1, 3);
334
335 // Remove last 2 items to ensure we don't crash
336 MemRemoveFromArray(rgValues, 0, 2, cValues, sizeof(ArrayValue), FALSE);
337 cValues -= 2;
338 }
339 finally
340 {
341 ReleaseMem(rgValues);
342 DutilUninitialize();
343 }
344 }
345
346 [Fact]
347 void MemUtilSwapTest()
348 {
349 HRESULT hr = S_OK;
350 ArrayValue *rgValues = NULL;
351 DWORD cValues = 0;
352
353 DutilInitialize(&DutilTestTraceError);
354
355 try
356 {
357 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&rgValues), 10, sizeof(ArrayValue), 10);
358 NativeAssert::Succeeded(hr, "Failed to grow array size to 10");
359
360 cValues = 10;
361 for (DWORD i = 0; i < cValues; ++i)
362 {
363 SetItem(rgValues + i, i);
364 }
365
366 // Swap first two
367 MemArraySwapItems(rgValues, 0, 1, sizeof(ArrayValue));
368 --cValues;
369
370 CheckItem(rgValues, 1);
371 CheckItem(rgValues + 1, 0);
372 for (DWORD i = 2; i < cValues; ++i)
373 {
374 CheckItem(rgValues + i, i);
375 }
376
377 // Swap them back
378 MemArraySwapItems(rgValues, 0, 1, sizeof(ArrayValue));
379 --cValues;
380
381 for (DWORD i = 0; i < cValues; ++i)
382 {
383 CheckItem(rgValues + i, i);
384 }
385
386 // Swap first and last items (index 0 and 9)
387 MemArraySwapItems(rgValues, 0, 9, sizeof(ArrayValue));
388 --cValues;
389
390 CheckItem(rgValues, 9);
391 CheckItem(rgValues + 9, 0);
392 for (DWORD i = 1; i < cValues - 1; ++i)
393 {
394 CheckItem(rgValues + i, i);
395 }
396
397 // Swap index 1 and 8
398 MemArraySwapItems(rgValues, 1, 8, sizeof(ArrayValue));
399 --cValues;
400
401 CheckItem(rgValues, 9);
402 CheckItem(rgValues + 1, 8);
403 CheckItem(rgValues + 8, 1);
404 CheckItem(rgValues + 9, 0);
405 for (DWORD i = 2; i < cValues - 2; ++i)
406 {
407 CheckItem(rgValues + i, i);
408 }
409
410 // Swap index 2 and 7
411 MemArraySwapItems(rgValues, 2, 7, sizeof(ArrayValue));
412 --cValues;
413
414 CheckItem(rgValues, 9);
415 CheckItem(rgValues + 1, 8);
416 CheckItem(rgValues + 2, 7);
417 CheckItem(rgValues + 7, 2);
418 CheckItem(rgValues + 8, 1);
419 CheckItem(rgValues + 9, 0);
420 for (DWORD i = 3; i < cValues - 3; ++i)
421 {
422 CheckItem(rgValues + i, i);
423 }
424
425 // Swap index 0 and 1
426 MemArraySwapItems(rgValues, 0, 1, sizeof(ArrayValue));
427 --cValues;
428
429 CheckItem(rgValues, 8);
430 CheckItem(rgValues + 1, 9);
431 CheckItem(rgValues + 2, 7);
432 CheckItem(rgValues + 7, 2);
433 CheckItem(rgValues + 8, 1);
434 CheckItem(rgValues + 9, 0);
435 for (DWORD i = 3; i < cValues - 3; ++i)
436 {
437 CheckItem(rgValues + i, i);
438 }
439 }
440 finally
441 {
442 ReleaseMem(rgValues);
443 DutilUninitialize();
444 }
445 }
446
447 private:
448 void SetItem(ArrayValue *pValue, DWORD dwValue)
449 {
450 HRESULT hr = S_OK;
451 pValue->dwNum = dwValue;
452
453 hr = StrAllocFormatted(&pValue->sczString, L"%u", dwValue);
454 NativeAssert::Succeeded(hr, "Failed to allocate string");
455 }
456
457 void CheckItem(ArrayValue *pValue, DWORD dwValue)
458 {
459 HRESULT hr = S_OK;
460 LPWSTR sczTemp = NULL;
461
462 try
463 {
464 NativeAssert::Equal(dwValue, pValue->dwNum);
465
466 hr = StrAllocFormatted(&sczTemp, L"%u", dwValue);
467 NativeAssert::Succeeded(hr, "Failed to allocate temp string");
468
469 NativeAssert::StringEqual(sczTemp, pValue->sczString, TRUE);
470
471 if (pValue->pvNull1 || pValue->pvNull2)
472 {
473 hr = E_FAIL;
474 ExitOnFailure(hr, "One of the expected NULL values wasn't NULL!");
475 }
476 }
477 finally
478 {
479 ReleaseStr(sczTemp);
480 }
481
482 LExit:
483 return;
484 }
485
486 void CheckNullItem(ArrayValue *pValue)
487 {
488 HRESULT hr = S_OK;
489
490 NativeAssert::Equal<DWORD>(0, pValue->dwNum);
491
492 if (pValue->sczString)
493 {
494 hr = E_FAIL;
495 ExitOnFailure(hr, "Item found isn't NULL!");
496 }
497
498 if (pValue->pvNull1 || pValue->pvNull2)
499 {
500 hr = E_FAIL;
501 ExitOnFailure(hr, "One of the expected NULL values wasn't NULL!");
502 }
503
504 LExit:
505 return;
506 }
507 };
508 }