1ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte#include <stdio.h>
2ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte#include <stdlib.h>
3ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte#include <hardware/sensors.h>
4ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte#include <pthread.h>
592863c14b7d36f74ec715b45ca6adc8bf95dc87cAaron Whyte#include <cutils/atomic.h>
692863c14b7d36f74ec715b45ca6adc8bf95dc87cAaron Whyte
7ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte#include "SensorEventQueue.cpp"
8ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
9ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte// Unit tests for the SensorEventQueue.
10ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
11ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte// Run it like this:
12ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte//
13ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte// make sensorstests -j32 && \
14ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte// out/host/linux-x86/obj/EXECUTABLES/sensorstests_intermediates/sensorstests
15ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
16ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whytebool checkWritableBufferSize(SensorEventQueue* queue, int requested, int expected) {
17ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    sensors_event_t* buffer;
18ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    int actual = queue->getWritableRegion(requested, &buffer);
19ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (actual != expected) {
20ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte        printf("Expected buffer size was %d; actual was %d\n", expected, actual);
21ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte        return false;
22ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    }
23ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    return true;
24ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte}
25ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
26ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whytebool checkSize(SensorEventQueue* queue, int expected) {
27ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    int actual = queue->getSize();
28ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (actual != expected) {
29c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        printf("Expected queue size was %d; actual was %d\n", expected, actual);
30c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        return false;
31c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    }
32c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    return true;
33c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte}
34c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
35c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytebool checkInt(char* msg, int expected, int actual) {
36c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    if (actual != expected) {
37c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        printf("%s; expected %d; actual was %d\n", msg, expected, actual);
38ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte        return false;
39ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    }
40ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    return true;
41ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte}
42ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
43ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whytebool testSimpleWriteSizeCounts() {
44c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    printf("testSimpleWriteSizeCounts\n");
45ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    SensorEventQueue* queue = new SensorEventQueue(10);
46ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 0)) return false;
47ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 11, 10)) return false;
48ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 10, 10)) return false;
49ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 9, 9)) return false;
50ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
51ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->markAsWritten(7);
52ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 7)) return false;
53ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 4, 3)) return false;
54ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 3, 3)) return false;
55ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 2, 2)) return false;
56ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
57ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->markAsWritten(3);
58ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 10)) return false;
59ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 1, 0)) return false;
60ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
61ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    printf("passed\n");
62ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    return true;
63ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte}
64ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
65ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whytebool testWrappingWriteSizeCounts() {
66c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    printf("testWrappingWriteSizeCounts\n");
67ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    SensorEventQueue* queue = new SensorEventQueue(10);
68ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->markAsWritten(9);
69ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 9)) return false;
70ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
71ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    // dequeue from the front
72ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->dequeue();
73ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->dequeue();
74ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 7)) return false;
75ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 100, 1)) return false;
76ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
77ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    // Write all the way to the end.
78ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->markAsWritten(1);
79ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 8)) return false;
80ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    // Now the two free spots in the front are available.
81ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkWritableBufferSize(queue, 100, 2)) return false;
82ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
83ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    // Fill the queue again
84ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    queue->markAsWritten(2);
85ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (!checkSize(queue, 10)) return false;
86ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
87ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    printf("passed\n");
88ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    return true;
89ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte}
90ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte
91c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
92c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
93c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytestruct TaskContext {
94c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte  bool success;
95c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte  SensorEventQueue* queue;
96c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte};
97c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
98c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytestatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
99c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytestatic pthread_cond_t dataAvailableCond = PTHREAD_COND_INITIALIZER;
100c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
101c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyteint FULL_QUEUE_CAPACITY = 5;
102c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyteint FULL_QUEUE_EVENT_COUNT = 31;
103c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
104c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytevoid *fullQueueWriterTask(void* ptr) {
105c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    TaskContext* ctx = (TaskContext*)ptr;
106c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    SensorEventQueue* queue = ctx->queue;
107c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    ctx->success = true;
108c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    int totalWaits = 0;
109c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    int totalWrites = 0;
110c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    sensors_event_t* buffer;
111c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
112c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    while (totalWrites < FULL_QUEUE_EVENT_COUNT) {
113c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        pthread_mutex_lock(&mutex);
114c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        if (queue->waitForSpace(&mutex)) {
115c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            totalWaits++;
116c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            printf(".");
117c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        }
118c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        int writableSize = queue->getWritableRegion(FULL_QUEUE_CAPACITY, &buffer);
119c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        queue->markAsWritten(writableSize);
120c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        totalWrites += writableSize;
121c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        for (int i = 0; i < writableSize; i++) {
122c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            printf("w");
123c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        }
124c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        pthread_cond_broadcast(&dataAvailableCond);
125c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        pthread_mutex_unlock(&mutex);
126c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    }
127c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    printf("\n");
128c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
129c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    ctx->success =
130c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            checkInt("totalWrites", FULL_QUEUE_EVENT_COUNT, totalWrites) &&
131c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            checkInt("totalWaits", FULL_QUEUE_EVENT_COUNT - FULL_QUEUE_CAPACITY, totalWaits);
132c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    return NULL;
133c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte}
134c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
135c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytebool fullQueueReaderShouldRead(int queueSize, int totalReads) {
136c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    if (queueSize == 0) {
137c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        return false;
138c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    }
139c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    int totalWrites = totalReads + queueSize;
140c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    return queueSize == FULL_QUEUE_CAPACITY || totalWrites == FULL_QUEUE_EVENT_COUNT;
141c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte}
142c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
143c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytevoid* fullQueueReaderTask(void* ptr) {
144c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    TaskContext* ctx = (TaskContext*)ptr;
145c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    SensorEventQueue* queue = ctx->queue;
146c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    int totalReads = 0;
147c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    while (totalReads < FULL_QUEUE_EVENT_COUNT) {
148c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        pthread_mutex_lock(&mutex);
149c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        // Only read if there are events,
150c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        // and either the queue is full, or if we're reading the last few events.
151c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        while (!fullQueueReaderShouldRead(queue->getSize(), totalReads)) {
152c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            pthread_cond_wait(&dataAvailableCond, &mutex);
153c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        }
154c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        queue->dequeue();
155c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        totalReads++;
156c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        printf("r");
157c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte        pthread_mutex_unlock(&mutex);
158c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    }
159c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    printf("\n");
160c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    ctx->success = ctx->success && checkInt("totalreads", FULL_QUEUE_EVENT_COUNT, totalReads);
161c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    return NULL;
162c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte}
163c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
164c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte// Test internal queue-full waiting and broadcasting.
165c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whytebool testFullQueueIo() {
166c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    printf("testFullQueueIo\n");
167c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    SensorEventQueue* queue = new SensorEventQueue(FULL_QUEUE_CAPACITY);
168c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
169c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    TaskContext readerCtx;
170c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    readerCtx.success = true;
171c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    readerCtx.queue = queue;
172c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
173c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    TaskContext writerCtx;
174c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    writerCtx.success = true;
175c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    writerCtx.queue = queue;
176c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
177c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    pthread_t writer, reader;
178c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    pthread_create(&reader, NULL, fullQueueReaderTask, &readerCtx);
179c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    pthread_create(&writer, NULL, fullQueueWriterTask, &writerCtx);
180c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
181c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    pthread_join(writer, NULL);
182c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    pthread_join(reader, NULL);
183c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
184c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    if (!readerCtx.success || !writerCtx.success) return false;
185c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    printf("passed\n");
186c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte    return true;
187c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte}
188c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
189c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte
190ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyteint main(int argc, char **argv) {
191ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    if (testSimpleWriteSizeCounts() &&
192c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            testWrappingWriteSizeCounts() &&
193c69f3a70ecbc4303cdfdea961f7a2a4a8f58fa05Aaron Whyte            testFullQueueIo()) {
194ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte        printf("ALL PASSED\n");
195ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    } else {
196ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte        printf("SOMETHING FAILED\n");
197ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    }
198ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte    return EXIT_SUCCESS;
199ab6ec384c456022f37a9c6183d3afbcefcb436a9Aaron Whyte}
200