@@ -95,11 +95,18 @@ namespace
95
95
auto operator <=>(const ValueType&) const noexcept = default ;
96
96
};
97
97
98
+ // NOTE: We do not use TEMPLATE_TEST_CASE or TEMPLATE_LIST_TEST_CASE here because code coverage
99
+ // tools (such as gcov/lcov) do not properly attribute coverage to tests instantiated via
100
+ // template test cases. Instead, we use individual TEST_CASEs for each mutex type, and factorize
101
+ // the test logic into function templates to avoid code duplication. This ensures accurate code
102
+ // coverage reporting.
103
+
98
104
using supported_mutex_types = std::tuple<std::mutex, std::shared_mutex, std::recursive_mutex>;
99
105
100
- TEMPLATE_LIST_TEST_CASE (" synchronized_value basics" , " [template][thread-safe]" , supported_mutex_types)
106
+ template <mamba::util::Mutex MutexType>
107
+ void test_synchronized_value_basics ()
101
108
{
102
- using synchronized_value = mamba::util::synchronized_value<ValueType, TestType >;
109
+ using synchronized_value = mamba::util::synchronized_value<ValueType, MutexType >;
103
110
104
111
SECTION (" default constructible" )
105
112
{
@@ -208,23 +215,36 @@ namespace
208
215
}
209
216
}
210
217
211
- TEMPLATE_LIST_TEST_CASE (
212
- " synchronized_value initializer-list" ,
213
- " [template][thread-safe]" ,
214
- supported_mutex_types
215
- )
218
+ TEST_CASE (" synchronized_value basics with std::mutex" , " [thread-safe]" )
216
219
{
217
- using synchronized_value = mamba::util::synchronized_value<std::vector<int >, TestType>;
218
- synchronized_value values{ 1 , 2 , 3 , 4 };
220
+ test_synchronized_value_basics<std::mutex>();
221
+ }
222
+
223
+ TEST_CASE (" synchronized_value basics with std::shared_mutex" , " [thread-safe]" )
224
+ {
225
+ test_synchronized_value_basics<std::shared_mutex>();
226
+ }
227
+
228
+ TEST_CASE (" synchronized_value basics with std::recursive_mutex" , " [thread-safe]" )
229
+ {
230
+ test_synchronized_value_basics<std::recursive_mutex>();
219
231
}
220
232
221
- TEMPLATE_LIST_TEST_CASE (" synchronized_value apply example" , " [template][thread-safe]" , supported_mutex_types)
233
+ // Factorized initializer-list test
234
+ template <mamba::util::Mutex MutexType>
235
+ void test_synchronized_value_initializer_list ()
222
236
{
223
- using synchronized_value = mamba::util::synchronized_value<std::vector<int >, TestType>;
237
+ using synchronized_value = mamba::util::synchronized_value<std::vector<int >, MutexType>;
238
+ synchronized_value values{ 1 , 2 , 3 , 4 };
239
+ }
224
240
241
+ // Factorized apply example test
242
+ template <mamba::util::Mutex MutexType>
243
+ void test_synchronized_value_apply_example ()
244
+ {
245
+ using synchronized_value = mamba::util::synchronized_value<std::vector<int >, MutexType>;
225
246
const std::vector initial_values{ 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 };
226
247
const std::vector sorted_values{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
227
-
228
248
synchronized_value values{ initial_values };
229
249
values.apply (std::ranges::sort);
230
250
REQUIRE (values == sorted_values);
@@ -288,7 +308,6 @@ namespace
288
308
}
289
309
}
290
310
291
-
292
311
run_tasks = true ; // green light, tasks will run probably concurrently, worse case in
293
312
// unpredictable order
294
313
for (auto & task : tasks)
@@ -299,24 +318,20 @@ namespace
299
318
REQUIRE (current_value->x == expected_result);
300
319
}
301
320
302
- TEMPLATE_LIST_TEST_CASE (
303
- " synchronized_value thread-safe direct_access" ,
304
- " [template][thread-safe]" ,
305
- supported_mutex_types
306
- )
321
+ // Factorized thread-safe direct_access test
322
+ template <mamba::util::Mutex MutexType>
323
+ void test_synchronized_value_threadsafe_direct_access ()
307
324
{
308
- using synchronized_value = mamba::util::synchronized_value<ValueType, TestType >;
309
- test_concurrent_increment<TestType >([](synchronized_value& sv) { sv->x += 1 ; });
325
+ using synchronized_value = mamba::util::synchronized_value<ValueType, MutexType >;
326
+ test_concurrent_increment<MutexType >([](synchronized_value& sv) { sv->x += 1 ; });
310
327
}
311
328
312
- TEMPLATE_LIST_TEST_CASE (
313
- " synchronized_value thread-safe synchronize" ,
314
- " [template][thread-safe]" ,
315
- supported_mutex_types
316
- )
329
+ // Factorized thread-safe synchronize test
330
+ template <mamba::util::Mutex MutexType>
331
+ void test_synchronized_value_threadsafe_synchronize ()
317
332
{
318
- using synchronized_value = mamba::util::synchronized_value<ValueType, TestType >;
319
- test_concurrent_increment<TestType >(
333
+ using synchronized_value = mamba::util::synchronized_value<ValueType, MutexType >;
334
+ test_concurrent_increment<MutexType >(
320
335
[](synchronized_value& sv)
321
336
{
322
337
auto synched_sv = sv.synchronize ();
@@ -325,26 +340,22 @@ namespace
325
340
);
326
341
}
327
342
328
- TEMPLATE_LIST_TEST_CASE (
329
- " synchronized_value thread-safe apply" ,
330
- " [template][thread-safe]" ,
331
- supported_mutex_types
332
- )
343
+ // Factorized thread-safe apply test
344
+ template <mamba::util::Mutex MutexType>
345
+ void test_synchronized_value_threadsafe_apply ()
333
346
{
334
- using synchronized_value = mamba::util::synchronized_value<ValueType, TestType >;
335
- test_concurrent_increment<TestType >([](synchronized_value& sv)
336
- { sv.apply ([](ValueType& value) { value.x += 1 ; }); });
347
+ using synchronized_value = mamba::util::synchronized_value<ValueType, MutexType >;
348
+ test_concurrent_increment<MutexType >([](synchronized_value& sv)
349
+ { sv.apply ([](ValueType& value) { value.x += 1 ; }); });
337
350
}
338
351
339
- TEMPLATE_LIST_TEST_CASE (
340
- " synchronized_value thread-safe multiple synchronize" ,
341
- " [template][thread-safe]" ,
342
- supported_mutex_types
343
- )
352
+ // Factorized thread-safe multiple synchronize test
353
+ template <mamba::util::Mutex MutexType>
354
+ void test_synchronized_value_threadsafe_multiple_synchronize ()
344
355
{
345
- using synchronized_value = mamba::util::synchronized_value<ValueType, TestType >;
356
+ using synchronized_value = mamba::util::synchronized_value<ValueType, MutexType >;
346
357
const mamba::util::synchronized_value<std::vector<int >, std::shared_mutex> extra_values{ 1 };
347
- test_concurrent_increment<TestType >(
358
+ test_concurrent_increment<MutexType >(
348
359
[&](synchronized_value& sv)
349
360
{
350
361
auto [ssv, sev] = synchronize (sv, extra_values);
@@ -353,6 +364,97 @@ namespace
353
364
);
354
365
}
355
366
367
+ // Individual test cases for each mutex type
368
+ TEST_CASE (" synchronized_value initializer-list with std::mutex" , " [thread-safe]" )
369
+ {
370
+ test_synchronized_value_initializer_list<std::mutex>();
371
+ }
372
+
373
+ TEST_CASE (" synchronized_value initializer-list with std::shared_mutex" , " [thread-safe]" )
374
+ {
375
+ test_synchronized_value_initializer_list<std::shared_mutex>();
376
+ }
377
+
378
+ TEST_CASE (" synchronized_value initializer-list with std::recursive_mutex" , " [thread-safe]" )
379
+ {
380
+ test_synchronized_value_initializer_list<std::recursive_mutex>();
381
+ }
382
+
383
+ TEST_CASE (" synchronized_value apply example with std::mutex" , " [thread-safe]" )
384
+ {
385
+ test_synchronized_value_apply_example<std::mutex>();
386
+ }
387
+
388
+ TEST_CASE (" synchronized_value apply example with std::shared_mutex" , " [thread-safe]" )
389
+ {
390
+ test_synchronized_value_apply_example<std::shared_mutex>();
391
+ }
392
+
393
+ TEST_CASE (" synchronized_value apply example with std::recursive_mutex" , " [thread-safe]" )
394
+ {
395
+ test_synchronized_value_apply_example<std::recursive_mutex>();
396
+ }
397
+
398
+ TEST_CASE (" synchronized_value thread-safe direct_access with std::mutex" , " [thread-safe]" )
399
+ {
400
+ test_synchronized_value_threadsafe_direct_access<std::mutex>();
401
+ }
402
+
403
+ TEST_CASE (" synchronized_value thread-safe direct_access with std::shared_mutex" , " [thread-safe]" )
404
+ {
405
+ test_synchronized_value_threadsafe_direct_access<std::shared_mutex>();
406
+ }
407
+
408
+ TEST_CASE (" synchronized_value thread-safe direct_access with std::recursive_mutex" , " [thread-safe]" )
409
+ {
410
+ test_synchronized_value_threadsafe_direct_access<std::recursive_mutex>();
411
+ }
412
+
413
+ TEST_CASE (" synchronized_value thread-safe synchronize with std::mutex" , " [thread-safe]" )
414
+ {
415
+ test_synchronized_value_threadsafe_synchronize<std::mutex>();
416
+ }
417
+
418
+ TEST_CASE (" synchronized_value thread-safe synchronize with std::shared_mutex" , " [thread-safe]" )
419
+ {
420
+ test_synchronized_value_threadsafe_synchronize<std::shared_mutex>();
421
+ }
422
+
423
+ TEST_CASE (" synchronized_value thread-safe synchronize with std::recursive_mutex" , " [thread-safe]" )
424
+ {
425
+ test_synchronized_value_threadsafe_synchronize<std::recursive_mutex>();
426
+ }
427
+
428
+ TEST_CASE (" synchronized_value thread-safe apply with std::mutex" , " [thread-safe]" )
429
+ {
430
+ test_synchronized_value_threadsafe_apply<std::mutex>();
431
+ }
432
+
433
+ TEST_CASE (" synchronized_value thread-safe apply with std::shared_mutex" , " [thread-safe]" )
434
+ {
435
+ test_synchronized_value_threadsafe_apply<std::shared_mutex>();
436
+ }
437
+
438
+ TEST_CASE (" synchronized_value thread-safe apply with std::recursive_mutex" , " [thread-safe]" )
439
+ {
440
+ test_synchronized_value_threadsafe_apply<std::recursive_mutex>();
441
+ }
442
+
443
+ TEST_CASE (" synchronized_value thread-safe multiple synchronize with std::mutex" , " [thread-safe]" )
444
+ {
445
+ test_synchronized_value_threadsafe_multiple_synchronize<std::mutex>();
446
+ }
447
+
448
+ TEST_CASE (" synchronized_value thread-safe multiple synchronize with std::shared_mutex" , " [thread-safe]" )
449
+ {
450
+ test_synchronized_value_threadsafe_multiple_synchronize<std::shared_mutex>();
451
+ }
452
+
453
+ TEST_CASE (" synchronized_value thread-safe multiple synchronize with std::recursive_mutex" , " [thread-safe]" )
454
+ {
455
+ test_synchronized_value_threadsafe_multiple_synchronize<std::recursive_mutex>();
456
+ }
457
+
356
458
TEST_CASE (" synchronized_value basics multiple synchronize" )
357
459
{
358
460
using namespace mamba ::util;
0 commit comments