26
26
#include < stdlib.h>
27
27
#include < stdio.h>
28
28
#include < algorithm>
29
- #include " mbed_stats.h"
30
29
31
30
#if !NVSTORE_ENABLED
32
31
#error [NOT_SUPPORTED] NVSTORE needs to be enabled for this test
35
34
using namespace utest ::v1;
36
35
37
36
static const uint16_t max_test_keys = 20 ;
37
+ static const uint16_t max_possible_keys_threshold = 64 ;
38
38
39
39
static const size_t basic_func_max_data_size = 128 ;
40
40
@@ -44,11 +44,9 @@ static const int thr_test_max_data_size = 32;
44
44
static const int thr_test_num_threads = 3 ;
45
45
46
46
#if defined(__CORTEX_M23) || defined(__CORTEX_M33)
47
- static const int thr_test_min_stack_size = 1280 ;
48
- static const int thr_test_max_stack_size = 1280 ;
47
+ static const int thr_test_stack_size = 1280 ;
49
48
#else
50
- static const int thr_test_min_stack_size = 768 ;
51
- static const int thr_test_max_stack_size = 1024 ;
49
+ static const int thr_test_stack_size = 1024 ;
52
50
#endif
53
51
54
52
typedef struct {
@@ -63,8 +61,7 @@ static thread_test_data_t *thr_test_data;
63
61
static const int race_test_num_threads = 4 ;
64
62
static const int race_test_key = 1 ;
65
63
static const int race_test_data_size = 128 ;
66
- static const int race_test_min_stack_size = 768 ;
67
- static const int race_test_max_stack_size = 1024 ;
64
+ static const int race_test_stack_size = 768 ;
68
65
69
66
static bool nvstore_overlaps_code = false ;
70
67
@@ -81,9 +78,7 @@ static void nvstore_basic_functionality_test()
81
78
uint16_t actual_len_bytes = 0 ;
82
79
NVStore &nvstore = NVStore::get_instance ();
83
80
uint16_t key;
84
-
85
- uint8_t *nvstore_testing_buf_set = new uint8_t [basic_func_max_data_size];
86
- uint8_t *nvstore_testing_buf_get = new uint8_t [basic_func_max_data_size];
81
+ uint16_t max_possible_keys;
87
82
88
83
int result;
89
84
@@ -99,11 +94,20 @@ static void nvstore_basic_functionality_test()
99
94
TEST_SKIP_UNLESS_MESSAGE (!nvstore_overlaps_code, " Test skipped. NVStore region overlaps code." );
100
95
}
101
96
97
+ uint8_t *nvstore_testing_buf_set = new (std::nothrow) uint8_t [basic_func_max_data_size];
98
+ uint8_t *nvstore_testing_buf_get = new (std::nothrow) uint8_t [basic_func_max_data_size];
99
+ if (!nvstore_testing_buf_set || !nvstore_testing_buf_get) {
100
+ printf (" Not enough heap space to run test. Test skipped\n " );
101
+ goto clean;
102
+ }
103
+
102
104
gen_random (nvstore_testing_buf_set, basic_func_max_data_size);
103
105
104
- uint16_t max_possible_keys = nvstore.get_max_possible_keys ();
106
+ max_possible_keys = nvstore.get_max_possible_keys ();
105
107
TEST_SKIP_UNLESS_MESSAGE (max_test_keys < max_possible_keys,
106
108
" Not enough possible keys for test. Test skipped." );
109
+ TEST_SKIP_UNLESS_MESSAGE (max_possible_keys >= max_possible_keys_threshold,
110
+ " Max possible keys below threshold. Test skipped." );
107
111
108
112
nvstore.set_max_keys (max_test_keys);
109
113
TEST_ASSERT_EQUAL (max_test_keys, nvstore.get_max_keys ());
@@ -387,46 +391,11 @@ static void nvstore_basic_functionality_test()
387
391
result = nvstore.get (NVSTORE_NUM_PREDEFINED_KEYS + 1 , 64 , nvstore_testing_buf_get, actual_len_bytes);
388
392
TEST_ASSERT_EQUAL (NVSTORE_NOT_FOUND, result);
389
393
394
+ clean:
390
395
delete[] nvstore_testing_buf_set;
391
396
delete[] nvstore_testing_buf_get;
392
397
}
393
398
394
- // This function calculates the stack size that needs to be allocated per thread in
395
- // the multi-thread tests. Given minimal and maximal stack sizes, and based on the heap
396
- // stats (automatically enabled in CI), the function checks whether each thread has at least
397
- // the minimal stack size, otherwise it reduces the number of threads (something that may happen
398
- // on low memory boards).
399
- static void calc_thread_stack_size (int &num_threads, uint32_t min_size, uint32_t max_size,
400
- uint32_t &stack_size)
401
- {
402
- mbed_stats_heap_t heap_stats;
403
- mbed_stats_heap_get (&heap_stats);
404
-
405
- // reserved size (along with all other fields in heap stats) will be zero if
406
- // app is compiled without heap stats (typically local builds)
407
- if (!heap_stats.reserved_size ) {
408
- stack_size = max_size;
409
- printf (" Heap stats disabled in this build, so test may fail due to insufficient heap size\n " );
410
- printf (" If this happens, please build the test with heap stats enabled (-DMBED_HEAP_STATS_ENABLED=1)\n " );
411
- return ;
412
- }
413
-
414
- NVStore &nvstore = NVStore::get_instance ();
415
- int page_size = nvstore.size () / nvstore.get_max_possible_keys ();
416
- // Check if we can allocate enough stack size (per thread) for the current number of threads
417
- while (num_threads) {
418
- stack_size = (heap_stats.reserved_size - heap_stats.current_size ) / num_threads - sizeof (rtos::Thread) - page_size;
419
-
420
- stack_size = std::min (stack_size, max_size);
421
- if (stack_size >= min_size) {
422
- return ;
423
- }
424
-
425
- // Got here - stack not sufficient per thread. Reduce number of threads
426
- num_threads--;
427
- }
428
- }
429
-
430
399
static void thread_test_check_key (uint16_t key)
431
400
{
432
401
uint8_t get_buff[thr_test_max_data_size];
@@ -481,47 +450,66 @@ static void nvstore_multi_thread_test()
481
450
{
482
451
#ifdef MBED_CONF_RTOS_PRESENT
483
452
int i;
484
- int num_threads = thr_test_num_threads;
485
- uint32_t stack_size;
486
453
uint16_t size;
487
454
uint16_t key;
488
455
int ret;
489
-
490
- rtos::Thread **threads = new rtos::Thread*[num_threads] ;
456
+ char *dummy;
457
+ uint16_t max_possible_keys ;
491
458
492
459
NVStore &nvstore = NVStore::get_instance ();
493
460
494
461
TEST_SKIP_UNLESS_MESSAGE (!nvstore_overlaps_code, " Test skipped. NVStore region overlaps code." );
495
462
463
+ thr_test_data = 0 ;
464
+ rtos::Thread **threads = new (std::nothrow) rtos::Thread*[thr_test_num_threads];
465
+ if (!threads) {
466
+ goto mem_fail;
467
+ }
468
+ memset (threads, 0 , thr_test_num_threads * sizeof (rtos::Thread*));
469
+
496
470
ret = nvstore.reset ();
497
471
TEST_ASSERT_EQUAL (NVSTORE_SUCCESS, ret);
498
472
499
- thr_test_data = new thread_test_data_t ;
473
+ thr_test_data = new (std::nothrow) thread_test_data_t ;
474
+ if (!thr_test_data) {
475
+ goto mem_fail;
476
+ }
477
+
478
+ memset (thr_test_data, 0 , sizeof (thread_test_data_t ));
500
479
thr_test_data->max_keys = max_test_keys / 2 ;
501
- uint16_t max_possible_keys = nvstore.get_max_possible_keys ();
480
+ max_possible_keys = nvstore.get_max_possible_keys ();
502
481
TEST_SKIP_UNLESS_MESSAGE (thr_test_data->max_keys < max_possible_keys,
503
482
" Not enough possible keys for test. Test skipped." );
483
+ TEST_SKIP_UNLESS_MESSAGE (max_possible_keys >= max_possible_keys_threshold,
484
+ " Max possible keys below threshold. Test skipped." );
504
485
505
486
thr_test_data->stop_threads = false ;
506
487
for (key = 0 ; key < thr_test_data->max_keys ; key++) {
507
488
for (i = 0 ; i < thr_test_num_buffs; i++) {
508
489
size = 1 + rand () % thr_test_max_data_size;
509
490
thr_test_data->sizes [key][i] = size;
510
- thr_test_data->buffs [key][i] = new uint8_t [size + 1 ];
491
+ thr_test_data->buffs [key][i] = new (std::nothrow) uint8_t [size + 1 ];
492
+ if (!thr_test_data->buffs [key][i]) {
493
+ goto mem_fail;
494
+ }
511
495
gen_random (thr_test_data->buffs [key][i], size);
512
496
}
513
497
ret = nvstore.set (key, thr_test_data->sizes [key][0 ], thr_test_data->buffs [key][0 ]);
514
498
TEST_ASSERT_EQUAL (NVSTORE_SUCCESS, ret);
515
499
}
516
500
517
- calc_thread_stack_size (num_threads, thr_test_min_stack_size, thr_test_max_stack_size, stack_size) ;
518
- if (!num_threads) {
519
- printf ( " Not enough heap space to run test. Test skipped \n " );
520
- goto end ;
501
+ dummy = new (std::nothrow) char [thr_test_num_threads * thr_test_stack_size] ;
502
+ delete[] dummy;
503
+ if (!dummy) {
504
+ goto mem_fail ;
521
505
}
522
506
523
- for (i = 0 ; i < num_threads; i++) {
524
- threads[i] = new rtos::Thread ((osPriority_t)((int )osPriorityBelowNormal - num_threads + i), stack_size);
507
+ for (i = 0 ; i < thr_test_num_threads; i++) {
508
+ threads[i] = new (std::nothrow) rtos::Thread ((osPriority_t)((int )osPriorityBelowNormal - thr_test_num_threads + i),
509
+ thr_test_stack_size);
510
+ if (!threads[i]) {
511
+ goto mem_fail;
512
+ }
525
513
threads[i]->start (callback (thread_test_worker));
526
514
}
527
515
@@ -530,12 +518,6 @@ static void nvstore_multi_thread_test()
530
518
531
519
wait_ms (1000 );
532
520
533
- for (i = 0 ; i < num_threads; i++) {
534
- delete threads[i];
535
- }
536
-
537
- delete[] threads;
538
-
539
521
ret = nvstore.deinit ();
540
522
TEST_ASSERT_EQUAL (NVSTORE_SUCCESS, ret);
541
523
@@ -545,15 +527,32 @@ static void nvstore_multi_thread_test()
545
527
for (key = 0 ; key < thr_test_data->max_keys ; key++) {
546
528
thread_test_check_key (key);
547
529
}
530
+ goto clean;
548
531
549
- end:
550
- for (key = 0 ; key < thr_test_data->max_keys ; key++) {
551
- for (i = 0 ; i < thr_test_num_buffs; i++) {
552
- delete[] thr_test_data->buffs [key][i];
532
+ mem_fail:
533
+ printf (" Not enough heap space to run test. Test skipped\n " );
534
+
535
+ clean:
536
+ if (thr_test_data) {
537
+ thr_test_data->stop_threads = true ;
538
+ wait_ms (1000 );
539
+
540
+ for (key = 0 ; key < thr_test_data->max_keys ; key++) {
541
+ for (i = 0 ; i < thr_test_num_buffs; i++) {
542
+ delete[] thr_test_data->buffs [key][i];
543
+ }
553
544
}
545
+
546
+ delete thr_test_data;
554
547
}
555
548
556
- delete thr_test_data;
549
+ if (threads) {
550
+ for (i = 0 ; i < thr_test_num_threads; i++) {
551
+ delete threads[i];
552
+ }
553
+
554
+ delete[] threads;
555
+ }
557
556
558
557
nvstore.reset ();
559
558
@@ -574,45 +573,68 @@ static void nvstore_race_test()
574
573
{
575
574
#ifdef MBED_CONF_RTOS_PRESENT
576
575
int i;
577
- uint32_t stack_size;
578
576
uint16_t initial_buf_size;
579
577
int ret;
578
+ int num_sets;
580
579
rtos::Thread *threads[race_test_num_threads];
581
- uint8_t *get_buff, *buffs[race_test_num_threads];
582
- int num_threads = race_test_num_threads;
580
+ uint8_t *get_buff = 0 , *buffs[race_test_num_threads];
583
581
uint16_t actual_len_bytes;
582
+ uint16_t max_possible_keys;
583
+ char *dummy;
584
584
585
585
TEST_SKIP_UNLESS_MESSAGE (!nvstore_overlaps_code, " Test skipped. NVStore region overlaps code." );
586
586
587
587
NVStore &nvstore = NVStore::get_instance ();
588
588
589
+ max_possible_keys = nvstore.get_max_possible_keys ();
590
+ TEST_SKIP_UNLESS_MESSAGE (max_possible_keys >= max_possible_keys_threshold,
591
+ " Max possible keys below threshold. Test skipped." );
592
+
589
593
ret = nvstore.reset ();
590
594
TEST_ASSERT_EQUAL (NVSTORE_SUCCESS, ret);
591
595
596
+ memset (buffs, 0 , sizeof (buffs));
597
+ memset (threads, 0 , sizeof (threads));
598
+
592
599
initial_buf_size = std::min ((nvstore.size () - race_test_data_size) / 2 , (size_t ) race_test_data_size);
593
- uint8_t *initial_buf = new uint8_t [initial_buf_size];
594
- int num_sets = (nvstore.size () - race_test_data_size) / initial_buf_size;
600
+ uint8_t *initial_buf = new (std::nothrow) uint8_t [initial_buf_size];
601
+ if (!initial_buf) {
602
+ goto mem_fail;
603
+ }
604
+
605
+ num_sets = (nvstore.size () - race_test_data_size) / initial_buf_size;
595
606
for (i = 0 ; i < num_sets; i++) {
596
607
ret = nvstore.set (0 , initial_buf_size, initial_buf);
597
608
TEST_ASSERT_EQUAL (NVSTORE_SUCCESS, ret);
598
609
}
599
610
delete[] initial_buf;
600
611
601
- get_buff = new uint8_t [race_test_data_size];
602
-
603
- calc_thread_stack_size (num_threads, race_test_min_stack_size, race_test_max_stack_size, stack_size);
604
- if (!num_threads) {
605
- printf (" Not enough heap space to run test. Test skipped\n " );
606
- goto end;
612
+ get_buff = new (std::nothrow) uint8_t [race_test_data_size];
613
+ if (!get_buff) {
614
+ goto mem_fail;
607
615
}
608
616
609
- for (i = 0 ; i < num_threads; i++) {
610
- buffs[i] = new uint8_t [race_test_data_size];
617
+ for (i = 0 ; i < race_test_num_threads; i++) {
618
+ buffs[i] = new (std::nothrow) uint8_t [race_test_data_size];
619
+ if (!buffs[i]) {
620
+ goto mem_fail;
621
+ }
611
622
gen_random (buffs[i], race_test_data_size);
612
623
}
613
624
614
- for (i = 0 ; i < num_threads; i++) {
615
- threads[i] = new rtos::Thread ((osPriority_t)((int )osPriorityBelowNormal - num_threads + i), stack_size);
625
+ for (i = 0 ; i < race_test_num_threads; i++) {
626
+ threads[i] = new (std::nothrow) rtos::Thread ((osPriority_t)((int )osPriorityBelowNormal - race_test_num_threads + i),
627
+ race_test_stack_size);
628
+ if (!threads[i]) {
629
+ goto mem_fail;
630
+ }
631
+
632
+ dummy = new (std::nothrow) char [race_test_stack_size];
633
+ if (!dummy) {
634
+ goto mem_fail;
635
+ }
636
+ delete[] dummy;
637
+
616
638
threads[i]->start (callback (race_test_worker, (void *) buffs[i]));
617
639
threads[i]->join ();
618
640
}
@@ -621,19 +643,23 @@ static void nvstore_race_test()
621
643
TEST_ASSERT_EQUAL (NVSTORE_SUCCESS, ret);
622
644
TEST_ASSERT_EQUAL (race_test_data_size, actual_len_bytes);
623
645
624
- for (i = 0 ; i < num_threads ; i++) {
646
+ for (i = 0 ; i < race_test_num_threads ; i++) {
625
647
if (!memcmp (buffs[i], get_buff, actual_len_bytes)) {
626
648
break ;
627
649
}
628
650
}
629
- TEST_ASSERT_NOT_EQUAL (num_threads , i);
651
+ TEST_ASSERT_NOT_EQUAL (race_test_num_threads , i);
630
652
631
- for (i = 0 ; i < num_threads; i++) {
653
+ goto clean;
654
+
655
+ mem_fail:
656
+ printf (" Not enough heap space to run test. Test skipped\n " );
657
+
658
+ clean:
659
+ for (i = 0 ; i < race_test_num_threads; i++) {
632
660
delete threads[i];
633
661
delete[] buffs[i];
634
662
}
635
-
636
- end:
637
663
delete[] get_buff;
638
664
#endif
639
665
}
0 commit comments