2 * Unit test suite for vcomp110
4 * Copyright 2021 Paul Gofman for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
24 static HMODULE vcomp_handle
;
26 static void (WINAPIV
*pC2VectParallel
)(int start
, int end
, int step
, BOOL end_included
, int thread_count
,
27 BOOL dynamic_distribution
, void *function
, int nargs
, ...);
28 static int (CDECL
*p_vcomp_get_thread_num
)(void);
29 static int (CDECL
*pomp_get_num_threads
)(void);
30 static void (CDECL
*pomp_set_num_threads
)(int num_threads
);
31 static void (CDECL
*p_vcomp_set_num_threads
)(int num_threads
);
33 #define VCOMP_GET_PROC(func) \
36 p ## func = (void *)GetProcAddress(vcomp_handle, #func); \
37 if (!p ## func) trace("Failed to get address for %s\n", #func); \
41 static BOOL
init_vcomp(void)
43 vcomp_handle
= LoadLibraryA("vcomp110.dll");
46 win_skip("vcomp110.dll is not installed.\n");
50 VCOMP_GET_PROC(C2VectParallel
);
51 VCOMP_GET_PROC(_vcomp_get_thread_num
);
52 VCOMP_GET_PROC(omp_get_num_threads
);
53 VCOMP_GET_PROC(omp_set_num_threads
);
54 VCOMP_GET_PROC(_vcomp_set_num_threads
);
59 #define TEST_C2VECTPARALLEL_MAX_THREADS 256
60 #define TEST_C2VECTPARALLEL_MAX_VALUES 256
61 #define TEST_C2VECTPARALLEL_MAX_CALLS 256
63 struct C2VectParallel_test_data
70 unsigned int expected_call_count
;
71 unsigned int expected_dynamic_call_count
;
74 static volatile LONG test_C2VectParallel_call_count
;
76 static void CDECL
test_C2VectParallel_payload(int start
, int end
, void *test_parameter
,
77 const struct C2VectParallel_test_data
*test
, unsigned int test_index
, BOOL dynamic_distribution
)
79 int thread_count
= test
->thread_count
? test
->thread_count
: 5;
80 int thread
= p_vcomp_get_thread_num();
81 int expected_start
, expected_end
;
85 step_sign
= test
->step
> 0 ? 1 : -1;
87 omp_num_threads
= pomp_get_num_threads();
89 InterlockedIncrement(&test_C2VectParallel_call_count
);
91 if ((step_sign
> 0 && test
->end
< test
->start
) || (step_sign
< 0 && test
->end
> test
->start
)
92 || (test
->end
- test
->start
) / test
->step
< 2)
94 ok(omp_num_threads
== 1, "Got unexpected omp_num_threads %u, thread_count %u, test %u.\n",
95 omp_num_threads
, thread_count
, test_index
);
96 ok(!thread
, "Got unexpected thread %d, test %u.\n", thread
, test_index
);
97 ok(start
== test
->start
, "Got unexpected start %d, expected %d, thread %d, test %u.\n",
98 start
, test
->start
, thread
, test_index
);
99 ok(end
== test
->end
, "Got unexpected end %d, expected %d, thread %d, test %u.\n",
100 end
, test
->end
, thread
, test_index
);
104 ok(thread_count
== omp_num_threads
, "Got unexpected omp_num_threads %u, thread_count %u, test %u.\n",
105 omp_num_threads
, thread_count
, test_index
);
107 ok(test_parameter
== (void *)0xdeadbeef, "Got unexpected test_parameter %p.\n", test_parameter
);
109 if (dynamic_distribution
)
111 unsigned int remaining_count
;
112 unsigned int loop_count
= 0;
114 expected_start
= test
->start
;
118 remaining_count
= test
->end
- expected_start
+ test
->step
- step_sign
* !test
->end_included
;
120 remaining_count
= (unsigned int)-remaining_count
/ -test
->step
;
122 remaining_count
/= test
->step
;
124 expected_end
= expected_start
+ (remaining_count
+ thread_count
- 1) / thread_count
* test
->step
125 + step_sign
* !test
->end_included
;
127 if ((expected_end
- test
->end
) * step_sign
> 0)
128 expected_end
= test
->end
;
130 expected_end
-= test
->step
;
132 if (expected_start
== start
)
135 expected_start
= expected_end
- step_sign
* !test
->end_included
+ test
->step
;
137 while (loop_count
< 100);
138 ok(loop_count
< 100, "Could not match start %d after %u iterations, test %u.\n",
139 start
, loop_count
, test_index
);
143 unsigned int step_count
, steps_per_call
, remainder
;
145 step_count
= test
->end
- test
->start
+ test
->step
- step_sign
* !test
->end_included
;
147 step_count
= (unsigned int)-step_count
/ -test
->step
;
149 step_count
/= test
->step
;
151 steps_per_call
= step_count
/ thread_count
;
152 remainder
= step_count
% thread_count
;
154 if (thread
< remainder
)
156 expected_start
= thread
* (steps_per_call
+ 1);
157 expected_end
= expected_start
+ steps_per_call
+ 1;
159 else if (thread
< step_count
)
161 expected_start
= remainder
+ steps_per_call
* thread
;
162 expected_end
= expected_start
+ steps_per_call
;
166 expected_start
= expected_end
= 0;
169 expected_start
= test
->start
+ expected_start
* test
->step
;
170 expected_end
= test
->start
+ expected_end
* test
->step
;
172 expected_end
-= test
->step
;
173 if (!test
->end_included
)
174 expected_end
+= step_sign
;
177 ok(start
== expected_start
, "Got unexpected start %d, expected %d, thread %d, test %u.\n",
178 start
, expected_start
, thread
, test_index
);
179 ok(end
== expected_end
, "Got unexpected end %d, expected %d, start %d, thread %d, dynamic %#x, test %u.\n",
180 end
, expected_end
, start
, thread
, dynamic_distribution
, test_index
);
184 static void CDECL
test_C2VectParallel_single_argument(int start
)
186 ok(0, "Should not get here.\n");
190 static void test_C2VectParallel(void)
192 static const struct C2VectParallel_test_data tests
[] =
194 {28, 28, 1, 0, 6, 1, 1},
195 {28, 28, 1, 1, 6, 1, 1},
196 {28, 29, 1, 0, 6, 1, 1},
197 {28, 29, 1, 1, 6, 1, 1},
199 /* Native generates calls from excessive threads with empty range here. */
200 {28, 30, 1, 0, 6, 6, 2},
201 {28, 31, 1, 0, 6, 6, 3},
202 {28, 33, 1, 0, 6, 6, 5},
203 {0, -2, -1, 0, 3, 3, 2},
205 /* But not in such cases. */
206 {28, 30, 1, 1, 6, 3, 3},
207 {28, 31, 2, 0, 6, 1, 1},
208 {28, 32, 2, 0, 6, 2, 2},
210 {28, 57, 1, 0, 6, 6, 13},
211 {28, 57, 1, 1, 6, 6, 13},
212 {28, 57, 4, 1, 6, 6, 7},
213 {28, 36, 4, 0, 6, 2, 2},
214 {28, 36, 4, 1, 6, 3, 3},
215 {36, 28, 4, 0, 6, 1, 1},
216 {36, 28, 4, 1, 6, 1, 1},
217 {57, 28, -1, 0, 6, 6, 13},
218 {57, 28, -1, 1, 6, 6, 13},
219 {36, 28, -4, 0, 6, 2, 2},
220 {36, 28, -4, 1, 6, 3, 3},
221 {28, 57, 1, 0, 0, 5, 11},
222 {-10, -2, 2, 1, 2, 2, 3},
223 {0x7ffffffd, 0x7fffffff, 1, 1, 2, 2, 2},
224 {-1, 0x7fffffff, 0x10000000, 1, 2, 1, 1},
225 {0, 0x7fffffff, 1, 0, 2, 2, 31},
226 {0, 0x7fffffff, 1, 1, 2, 2, 32},
227 {-10000, 0x7fffffff, 1, 1, 2, 1, 1},
228 {-10000, 0x7fffffff, -1, 1, 2, 1, 1},
229 {-10000, 0x7fffffff, 2, 1, 2, 1, 1},
230 {-10000, 0x7ffffff0, 2, 1, 2, 1, 1},
231 {-10000, 0x7fffffff - 10000, 1, 0, 1, 1, 1},
232 {-10000, 0x7fffffff - 10000, 1, 1, 1, 1, 1},
233 {-10000, 0x7fffffff - 10000, 1, 0, 2, 2, 31},
234 {-10000, 0x7fffffff - 10000, 1, 1, 2, 2, 32},
235 {-10000, 0x7fffffff - 10000, 2, 0, 2, 2, 31},
236 {-10000, 0x7fffffff - 10000, 2, 1, 2, 2, 31},
237 {0x80000001, 0, 2, 0, 3, 3, 51},
238 {0x80000001, 0, 2, 1, 3, 3, 51},
239 {0x80000000, 0x7fffffff, 1, 0, 3, 1, 1},
240 {0x80000000, 0x7fffffff, 1, 1, 3, 1, 1},
241 {0x80000000, 0x7fffffff, 2, 0, 3, 1, 1},
242 {0x80000000, 0x7fffffff, 2, 1, 3, 1, 1},
243 {0x80000001, 1, 1, 0, 3, 1, 1},
244 {0x80000001, 1, 1, 1, 3, 1, 1},
245 {0x80000001, 0, 1, 0, 3, 3, 52},
246 {0x80000001, 0, 1, 1, 3, 3, 52},
247 {28, 28, 1, 0, -1, 1, 1},
249 /* Results in division by zero on Windows. */
250 {28, 57, 0, 0, 6, 6},
256 pomp_set_num_threads(5);
257 p_vcomp_set_num_threads(3);
258 num_threads
= pomp_get_num_threads();
259 ok(num_threads
== 1, "Got unexpected num_threads %u.\n", num_threads
);
262 /* Results in stack overflow on Windows. */
263 pC2VectParallel(28, 57, 1, 0, 2, FALSE
, test_C2VectParallel_single_argument
, 1);
266 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
268 const struct C2VectParallel_test_data
*test
= &tests
[i
];
270 test_C2VectParallel_call_count
= 0;
271 pC2VectParallel(test
->start
, test
->end
, test
->step
, test
->end_included
, test
->thread_count
,
272 FALSE
, test_C2VectParallel_payload
, 6, (void *)0xdeadbeef, test
, i
, FALSE
);
273 ok(test_C2VectParallel_call_count
== test
->expected_call_count
,
274 "Got unexpected call count %u, expected %u, test %u.\n",
275 test_C2VectParallel_call_count
, test
->expected_call_count
, i
);
277 test_C2VectParallel_call_count
= 0;
278 pC2VectParallel(test
->start
, test
->end
, test
->step
, test
->end_included
, test
->thread_count
,
279 ~0u, test_C2VectParallel_payload
, 6, (void *)0xdeadbeef, test
, i
, TRUE
);
280 ok(test_C2VectParallel_call_count
== test
->expected_dynamic_call_count
,
281 "Got unexpected call count %u, expected %u, test %u.\n",
282 test_C2VectParallel_call_count
, test
->expected_dynamic_call_count
, i
);
291 test_C2VectParallel();