diff --git a/.gitignore b/.gitignore index 9b68984..0e500f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ tests.out -*.out.* \ No newline at end of file +*.out.* +.vscode \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 60f240a..c0a25ca 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,17 +1,37 @@ { - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format "version": "2.0.0", "tasks": [ { "type": "shell", "label": "build with make", "command": "make", - "problemMatcher": [ "$gcc" ], "group": "build" + }, + { + "type": "cppbuild", + "label": "C/C++: gcc Aktive Datei kompilieren", + "command": "/usr/bin/gcc", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Vom Debugger generierte Aufgabe." } ] } \ No newline at end of file diff --git a/src/ringbuffer.c b/src/ringbuffer.c index e197857..7ec8454 100644 --- a/src/ringbuffer.c +++ b/src/ringbuffer.c @@ -2,14 +2,68 @@ #include #include -RingBuffer *ring_create(int maxSize) { +//#define DEBUG_MESSAGES_ON +#ifdef DEBUG_MESSAGES_ON +#include +#endif + + +RingBuffer* ring_create(int maxSize) { + //The two nullpointer return checks do not come from TDD. No idea how to force an exception in malloc. RingBuffer *buffer = (RingBuffer *)malloc(sizeof(RingBuffer)); - buffer->nbOfElements = -1; + if(!buffer) + return (RingBuffer*) NULL; + + int *buffer_data = (int *)malloc(sizeof(int) * maxSize); + if(!buffer_data) + { + free(buffer); + return (RingBuffer*) NULL; + } + buffer->data = buffer_data; + buffer->nbOfElements = buffer->offRead = buffer->offWrite = 0; + buffer->maxNbOfElements = maxSize; return buffer; } -void ring_delete(RingBuffer *buffer) {} +void ring_delete(RingBuffer *buffer) { + if(buffer->data) + { + free(buffer->data); + buffer->data = NULL; + } + + if(buffer) + { + free(buffer); + buffer = NULL; + } +} + +void ring_add(RingBuffer *buffer, int element) { + buffer->nbOfElements += 1; + if(buffer->nbOfElements > buffer->maxNbOfElements){ //overwrite last element + buffer->nbOfElements -= 1; + buffer->offRead = (buffer->offRead + 1) % buffer->maxNbOfElements; + } + #ifdef DEBUG_MESSAGES_ON + printf("Added element %d, Value %d\n", element, buffer->nbOfElements); + #endif + buffer->data[buffer->offWrite] = element; + buffer->offWrite = (buffer->offWrite + 1) % buffer->maxNbOfElements; +} + +bool ring_remove(RingBuffer *buffer, int *result) { + if(0 == buffer->nbOfElements){ + return false; + } -void ring_add(RingBuffer *buffer, int element) {} + buffer->nbOfElements -= 1; + *result = buffer->data[buffer->offRead]; + buffer->offRead = (buffer->offRead + 1) % buffer->maxNbOfElements; -bool ring_remove(RingBuffer *buffer, int *result) { return false; } + #ifdef DEBUG_MESSAGES_ON + printf("Popped element %d, Value %d\n", *result, buffer->nbOfElements); + #endif + return true; +} diff --git a/src/ringbuffer.h b/src/ringbuffer.h index b0822dc..91af2f3 100644 --- a/src/ringbuffer.h +++ b/src/ringbuffer.h @@ -4,8 +4,11 @@ #include typedef struct { - int nbOfElements; // the number of elements currently stored in the ring - int *data; // the actual ring buffer data + int nbOfElements; // the number of elements currently stored in the ring + int maxNbOfElements; //max Number of elements in the buffer + int *data; // the actual ring buffer data, always is at the starting location + int offRead; // offset for read pointer + int offWrite; // offset for write pointer } RingBuffer; /* diff --git a/test/ringbuffer.test.c b/test/ringbuffer.test.c index 6012331..b68a230 100644 --- a/test/ringbuffer.test.c +++ b/test/ringbuffer.test.c @@ -12,10 +12,11 @@ void tearDown(void) { ring_delete(buffer); } void test_ring_create(void) { TEST_ASSERT_NOT_NULL(buffer); - /*TEST_ASSERT_NOT_NULL_MESSAGE(buffer->data, "buffer->data is null"); + TEST_MESSAGE("The next test does never fail when in debug mode."); + TEST_ASSERT_NOT_NULL_MESSAGE(buffer->data, "buffer->data is null"); for (int i = 0; i < MAX_nbOfElements; i++) { TEST_ASSERT_EQUAL_INT_MESSAGE(0, buffer->data[i], "data should be 0"); - }*/ + } } void an_empty_ring_should_have_nbOfElements_0(void) { @@ -28,11 +29,103 @@ void it_should_report_the_correct_number_of_elements(void) { ring_add(buffer, 2); ring_add(buffer, 3); TEST_ASSERT_EQUAL_INT(3, buffer->nbOfElements); + + int retVal = 0; + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(2, buffer->nbOfElements); } void it_should_not_exceed_its_maximum_nbOfElements(void) { - //... - TEST_ASSERT_FALSE(true); + ring_add(buffer, 1); + ring_add(buffer, 2); + ring_add(buffer, 3); + ring_add(buffer, 4); //last element + TEST_ASSERT_EQUAL_INT(4, buffer->nbOfElements); + ring_add(buffer, 5); //exceeding element + TEST_ASSERT_EQUAL_INT(4, buffer->nbOfElements); +} + +void it_should_return_the_before_pushed_values(void) { + ring_add(buffer, 1); + ring_add(buffer, 2); + ring_add(buffer, 3); + int retVal = 0; + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(1, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(2, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(3, retVal); +} + +void it_should_return_the_before_pushed_values_full_test(void) { + ring_add(buffer, 1); + ring_add(buffer, 2); + ring_add(buffer, 3); + ring_add(buffer, 4); + int retVal = 0; + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(1, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(2, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(3, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(4, retVal); +} + +void it_should_return_false_when_empty(void) { + int retVal = 0; + TEST_ASSERT_FALSE(ring_remove(buffer, &retVal)); +} + +void it_should_return_true_when_element_was_successfully_returned(void) { + int retVal = 0; + ring_add(buffer, 1); + TEST_ASSERT_TRUE(ring_remove(buffer, &retVal)); +} + +void it_should_write_in_a_circle_when_old_values_are_read(void) { + ring_add(buffer, 1); + ring_add(buffer, 2); + ring_add(buffer, 3); + ring_add(buffer, 4); + int retVal = 0; + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(1, retVal); + ring_add(buffer, 5); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(2, retVal); + ring_add(buffer, 6); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(3, retVal); + ring_add(buffer, 7); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(4, retVal); + ring_add(buffer, 8); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(5, retVal); + ring_add(buffer, 9); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(6, retVal); +} + +void it_should_overwrite_the_last_element_when_buffer_is_full(void){ + ring_add(buffer, 1); + ring_add(buffer, 2); + ring_add(buffer, 3); + ring_add(buffer, 4); + ring_add(buffer, 5); + + int retVal = 0; + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(2, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(3, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(4, retVal); + ring_remove(buffer, &retVal); + TEST_ASSERT_EQUAL_INT(5, retVal); } int main(void) { @@ -42,6 +135,12 @@ int main(void) { RUN_TEST(an_empty_ring_should_have_nbOfElements_0); RUN_TEST(it_should_report_the_correct_number_of_elements); RUN_TEST(it_should_not_exceed_its_maximum_nbOfElements); + RUN_TEST(it_should_return_the_before_pushed_values); + RUN_TEST(it_should_return_false_when_empty); + RUN_TEST(it_should_return_true_when_element_was_successfully_returned); + RUN_TEST(it_should_return_the_before_pushed_values_full_test); + RUN_TEST(it_should_write_in_a_circle_when_old_values_are_read); + RUN_TEST(it_should_overwrite_the_last_element_when_buffer_is_full); UnityEnd(); return 0;