Welcome to mirror list, hosted at ThFree Co, Russian Federation.

furi_valuemutex_test.c « tests « applications - github.com/ClusterM/flipperzero-firmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 43383f94cd87b2a5ebeeadc12edc21cb24716b9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <string.h>
#include <furi.h>
#include "furi-hal-delay.h"

#include "minunit.h"

void test_furi_valuemutex() {
    const int init_value = 0xdeadbeef;
    const int changed_value = 0x12345678;

    int value = init_value;
    bool result;
    ValueMutex valuemutex;

    // init mutex case
    result = init_mutex(&valuemutex, &value, sizeof(value));
    mu_assert(result, "init mutex failed");

    // acquire mutex case
    int* value_pointer = acquire_mutex(&valuemutex, 100);
    mu_assert_pointers_eq(value_pointer, &value);

    // second acquire mutex case
    int* value_pointer_second = acquire_mutex(&valuemutex, 100);
    mu_assert_pointers_eq(value_pointer_second, NULL);

    // change value case
    *value_pointer = changed_value;
    mu_assert_int_eq(value, changed_value);

    // release mutex case
    result = release_mutex(&valuemutex, &value);
    mu_assert(result, "release mutex failed");

    // TODO
    //acquire mutex blocking case
    //write mutex blocking case
    //read mutex blocking case

    mu_check(delete_mutex(&valuemutex));
}

/*
TEST: concurrent access

1. Create holding record
2. Open it twice
3. Change value simultaneously in two app and check integrity
*/

// TODO this test broke because mutex in furi is not implemented

typedef struct {
    // a and b must be equal
    uint8_t a;
    uint8_t b;
} ConcurrentValue;

void furi_concurent_app(void* p) {
    ValueMutex* mutex = (ValueMutex*)p;
    if(mutex == NULL) {
        printf("cannot open mutex\r\n");
        osThreadExit();
    }

    for(size_t i = 0; i < 10; i++) {
        ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(mutex);

        if(value == NULL) {
            printf("cannot take record\r\n");
            release_mutex(mutex, value);
            osThreadExit();
        }

        // emulate read-modify-write broken by context switching
        uint8_t a = value->a;
        uint8_t b = value->b;
        a++;
        b++;
        delay(2);
        value->a = a;
        value->b = b;
        release_mutex(mutex, value);
    }

    osThreadExit();
}

void test_furi_concurrent_access() {
    // TODO: reimplement or delete test
    return;
    /*
    // 1. Create holding record
    ConcurrentValue value = {.a = 0, .b = 0};
    ValueMutex mutex;
    mu_check(init_mutex(&mutex, &value, sizeof(value)));

    // 3. Create second app for interact with it
    FuriApp* second_app = furiac_start(furi_concurent_app, "furi concurent app", (void*)&mutex);

    // 4. multiply ConcurrentValue::a
    for(size_t i = 0; i < 4; i++) {
        ConcurrentValue* value = (ConcurrentValue*)acquire_mutex_block(&mutex);

        if(value == NULL) {
            release_mutex(&mutex, value);
            mu_fail("cannot take record\r\n");
        }

        // emulate read-modify-write broken by context switching
        uint8_t a = value->a;
        uint8_t b = value->b;
        a++;
        b++;
        value->a = a;
        delay(10); // this is only for test, do not add delay between take/give in prod!
        value->b = b;
        release_mutex(&mutex, value);
    }

    delay(50);

    mu_assert_pointers_eq(second_app->handler, NULL);

    mu_assert_int_eq(value.a, value.b);

    mu_check(delete_mutex(&mutex));
    */
}