summaryrefslogtreecommitdiffstats
path: root/modules/sensors/tests/SensorEventQueue_test.cpp
blob: 3218bb93d3533d90c470ecc01a187c9fea6cd41d (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include <stdio.h>
#include <stdlib.h>
#include <hardware/sensors.h>
#include <pthread.h>
#include <cutils/atomic.h>

#include "SensorEventQueue.cpp"

// Unit tests for the SensorEventQueue.

// Run it like this:
//
// make sensorstests -j32 && \
// out/host/linux-x86/obj/EXECUTABLES/sensorstests_intermediates/sensorstests

bool checkWritableBufferSize(SensorEventQueue* queue, int requested, int expected) {
    sensors_event_t* buffer;
    int actual = queue->getWritableRegion(requested, &buffer);
    if (actual != expected) {
        printf("Expected buffer size was %d; actual was %d\n", expected, actual);
        return false;
    }
    return true;
}

bool checkSize(SensorEventQueue* queue, int expected) {
    int actual = queue->getSize();
    if (actual != expected) {
        printf("Expected queue size was %d; actual was %d\n", expected, actual);
        return false;
    }
    return true;
}

bool checkInt(char* msg, int expected, int actual) {
    if (actual != expected) {
        printf("%s; expected %d; actual was %d\n", msg, expected, actual);
        return false;
    }
    return true;
}

bool testSimpleWriteSizeCounts() {
    printf("testSimpleWriteSizeCounts\n");
    SensorEventQueue* queue = new SensorEventQueue(10);
    if (!checkSize(queue, 0)) return false;
    if (!checkWritableBufferSize(queue, 11, 10)) return false;
    if (!checkWritableBufferSize(queue, 10, 10)) return false;
    if (!checkWritableBufferSize(queue, 9, 9)) return false;

    queue->markAsWritten(7);
    if (!checkSize(queue, 7)) return false;
    if (!checkWritableBufferSize(queue, 4, 3)) return false;
    if (!checkWritableBufferSize(queue, 3, 3)) return false;
    if (!checkWritableBufferSize(queue, 2, 2)) return false;

    queue->markAsWritten(3);
    if (!checkSize(queue, 10)) return false;
    if (!checkWritableBufferSize(queue, 1, 0)) return false;

    printf("passed\n");
    return true;
}

bool testWrappingWriteSizeCounts() {
    printf("testWrappingWriteSizeCounts\n");
    SensorEventQueue* queue = new SensorEventQueue(10);
    queue->markAsWritten(9);
    if (!checkSize(queue, 9)) return false;

    // dequeue from the front
    queue->dequeue();
    queue->dequeue();
    if (!checkSize(queue, 7)) return false;
    if (!checkWritableBufferSize(queue, 100, 1)) return false;

    // Write all the way to the end.
    queue->markAsWritten(1);
    if (!checkSize(queue, 8)) return false;
    // Now the two free spots in the front are available.
    if (!checkWritableBufferSize(queue, 100, 2)) return false;

    // Fill the queue again
    queue->markAsWritten(2);
    if (!checkSize(queue, 10)) return false;

    printf("passed\n");
    return true;
}



struct TaskContext {
  bool success;
  SensorEventQueue* queue;
};

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t dataAvailableCond = PTHREAD_COND_INITIALIZER;

int FULL_QUEUE_CAPACITY = 5;
int FULL_QUEUE_EVENT_COUNT = 31;

void *fullQueueWriterTask(void* ptr) {
    TaskContext* ctx = (TaskContext*)ptr;
    SensorEventQueue* queue = ctx->queue;
    ctx->success = true;
    int totalWaits = 0;
    int totalWrites = 0;
    sensors_event_t* buffer;

    while (totalWrites < FULL_QUEUE_EVENT_COUNT) {
        pthread_mutex_lock(&mutex);
        if (queue->waitForSpace(&mutex)) {
            totalWaits++;
            printf(".");
        }
        int writableSize = queue->getWritableRegion(FULL_QUEUE_CAPACITY, &buffer);
        queue->markAsWritten(writableSize);
        totalWrites += writableSize;
        for (int i = 0; i < writableSize; i++) {
            printf("w");
        }
        pthread_cond_broadcast(&dataAvailableCond);
        pthread_mutex_unlock(&mutex);
    }
    printf("\n");

    ctx->success =
            checkInt("totalWrites", FULL_QUEUE_EVENT_COUNT, totalWrites) &&
            checkInt("totalWaits", FULL_QUEUE_EVENT_COUNT - FULL_QUEUE_CAPACITY, totalWaits);
    return NULL;
}

bool fullQueueReaderShouldRead(int queueSize, int totalReads) {
    if (queueSize == 0) {
        return false;
    }
    int totalWrites = totalReads + queueSize;
    return queueSize == FULL_QUEUE_CAPACITY || totalWrites == FULL_QUEUE_EVENT_COUNT;
}

void* fullQueueReaderTask(void* ptr) {
    TaskContext* ctx = (TaskContext*)ptr;
    SensorEventQueue* queue = ctx->queue;
    int totalReads = 0;
    while (totalReads < FULL_QUEUE_EVENT_COUNT) {
        pthread_mutex_lock(&mutex);
        // Only read if there are events,
        // and either the queue is full, or if we're reading the last few events.
        while (!fullQueueReaderShouldRead(queue->getSize(), totalReads)) {
            pthread_cond_wait(&dataAvailableCond, &mutex);
        }
        queue->dequeue();
        totalReads++;
        printf("r");
        pthread_mutex_unlock(&mutex);
    }
    printf("\n");
    ctx->success = ctx->success && checkInt("totalreads", FULL_QUEUE_EVENT_COUNT, totalReads);
    return NULL;
}

// Test internal queue-full waiting and broadcasting.
bool testFullQueueIo() {
    printf("testFullQueueIo\n");
    SensorEventQueue* queue = new SensorEventQueue(FULL_QUEUE_CAPACITY);

    TaskContext readerCtx;
    readerCtx.success = true;
    readerCtx.queue = queue;

    TaskContext writerCtx;
    writerCtx.success = true;
    writerCtx.queue = queue;

    pthread_t writer, reader;
    pthread_create(&reader, NULL, fullQueueReaderTask, &readerCtx);
    pthread_create(&writer, NULL, fullQueueWriterTask, &writerCtx);

    pthread_join(writer, NULL);
    pthread_join(reader, NULL);

    if (!readerCtx.success || !writerCtx.success) return false;
    printf("passed\n");
    return true;
}


int main(int argc, char **argv) {
    if (testSimpleWriteSizeCounts() &&
            testWrappingWriteSizeCounts() &&
            testFullQueueIo()) {
        printf("ALL PASSED\n");
    } else {
        printf("SOMETHING FAILED\n");
    }
    return EXIT_SUCCESS;
}