Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#define game // include this symbol if platform_conio.h is available
- #include <stdio.h>
- #include <string.h>
- #include "clist.h"
- #define SUCCESS 0
- #define FAIL 1
- typedef struct {
- const char* file;
- int line;
- char message[240];
- } TestErrorResult;
- typedef TestErrorResult* (*TestFunction)();
- typedef struct {
- const char * name;
- TestFunction func;
- } TestFunctionEntry;
- #ifdef game
- #include "platform_conio.h"
- int WaitJustOneMomentTillKeyPress(int milliseconds) {
- int soon = platform_upTimeMS() + milliseconds;
- while(platform_upTimeMS() < soon && !platform_kbhit()) {
- platform_sleep(1);
- }
- if (platform_kbhit()) {
- platform_getchar();
- return 1;
- }
- return 0;
- }
- void Success(const char* message, int pause, int flashes) {
- int delay = pause / (flashes * 2);
- for(int i = 0; i < flashes; ++i) {
- platform_setColor(PLATFORM_COLOR_GREEN|PLATFORM_COLOR_INTENSITY, -1);
- printf("\r%s",message);
- if(WaitJustOneMomentTillKeyPress(delay)) break;
- platform_setColor(PLATFORM_COLOR_GREEN, -1);
- printf("\r%s",message);
- if(WaitJustOneMomentTillKeyPress(delay)) break;
- }
- platform_setColor(PLATFORM_COLOR_INTENSITY, -1);
- printf("\r%s",message);
- platform_setColor(-1, -1);
- }
- #else
- void Success(const char* message, int pause, int flashes) {}
- #endif
- static TestErrorResult _err;
- #define ERR(format, ...) (\
- _err.file = __FILE__,\
- _err.line = __LINE__ ,\
- sprintf(_err.message, format, ##__VA_ARGS__),\
- &_err\
- )
- #define IMPLEMENT_CHECK(result) if (result == Listfloat_NotImplemented) return ERR("function not implemented!");
- int AppendArrayToCharBuffer(char* buffer, int bufferSize, float* list, int listCount, int maxDigits) {
- if (list == NULL || listCount == 0) { return SUCCESS; }
- char smallBuffer[16];
- int index = 0;
- for(int i = 0; i < bufferSize; ++i) {
- if (buffer[i] == '\0') {
- index = i;
- break;
- }
- }
- for(int i = 0; i < listCount; ++i) {
- sprintf(smallBuffer, "%f", list[i]);
- int len = strlen(smallBuffer);
- if (len > maxDigits) {
- len = maxDigits;
- }
- if (index+len >= bufferSize) { break; }
- for (int j = 0; j < len; ++j) {
- buffer[index+j] = smallBuffer[j];
- }
- index += len;
- if (index+1 >= bufferSize) { break; }
- buffer[index++] = ' ';
- if (index+1 >= bufferSize) { break; }
- }
- buffer[index] = '\0';
- return SUCCESS;
- }
- #define LISTERR(list,format, ...) (_err.file = __FILE__, _err.line = __LINE__ , sprintf(_err.message, format, ##__VA_ARGS__),\
- AppendArrayToCharBuffer(_err.message, sizeof(_err.message), (list)->get, (list)->count, 5), &_err)
- TestErrorResult* test_Listfloat_Init() {
- Listfloat list;
- int result = Listfloat_Init(&list);
- IMPLEMENT_CHECK(result)
- if (result == FAIL) {
- return ERR("Listfloat_Init failed. it should not fail");
- }
- if (list.get != NULL || list.capacity != 0 || list.count != 0) {
- return ERR("Listfloat_Init should set all values to zero. list: 0x%zx, capacity:%d, count:%d",
- list.get, list.capacity, list.count);
- }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_SetCapacity(){
- Listfloat list;
- Listfloat_Init(&list);
- int expectedSize = 10;
- int result = Listfloat_SetCapacity(&list, expectedSize);
- IMPLEMENT_CHECK(result)
- if (result != Listfloat_Success) { return ERR("SetCapacity failed (%d)", result); }
- if (list.get == NULL) { return ERR("SetCapacity clearly did not allocate memory", result); }
- if (list.capacity != expectedSize)
- return ERR("capacity did not grow as expected. expected %d, value is %d",
- expectedSize, list.capacity);
- if (list.count != 0) {
- return ERR("count changed, unexpectedly: %d", list.count);
- }
- if (list.get == 0) {
- return ERR("data is still null", 0);
- }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_Release() {
- Listfloat list;
- Listfloat_Init(&list);
- int result = Listfloat_SetCapacity(&list, 2);
- result = Listfloat_Release(&list);
- IMPLEMENT_CHECK(result)
- if (list.capacity != 0) {
- return ERR("capacity isn't zero, it's %d!", list.capacity);
- }
- if (list.count != 0) {
- return ERR("count isn't zero, it's %d!", list.count);
- }
- if (list.get != NULL) {
- return ERR("data isn't null, it's 0x%x!", list.get);
- }
- return NULL;
- }
- TestErrorResult* test_Listfloat_Add() {
- Listfloat list;
- Listfloat_Init(&list);
- int result = Listfloat_Add(&list, 1);
- IMPLEMENT_CHECK(result)
- if (result != 0) {
- return ERR("Add failed (%d)", result);
- }
- if (list.capacity == 0) {
- return ERR("capacity did not grow", 0);
- }
- if (list.count != 1) {
- return ERR("count is not 1, as expected: %d", list.count);
- }
- if (list.get == 0) {
- return ERR("data is still null", 0);
- }
- Listfloat_Release(&list);
- return NULL;
- }
- float RandomFloat() { return (rand() & 0xffff) / (float)(0x10000); }
- TestErrorResult* AddRandomFloats(Listfloat * self, int count) {
- int initialCount = self->count;
- float * randomNums = malloc(sizeof(float)*count);
- for(int i = 0; i < count; ++i){
- randomNums[i] = RandomFloat();
- int result = Listfloat_Add(self, randomNums[i]);
- if (result != 0) {
- return LISTERR(self,"Add failed: %d\n", result);
- }
- if (self->count != initialCount+i+1) {
- return LISTERR(self,"count unexpected value: %d\n", self->count);
- }
- for(int j = 0; j < i; ++j) {
- if (self->get[initialCount+j] != randomNums[j]) {
- return LISTERR(self,"unexpected value at index %d: %f, instead of %f\n",
- j, self->get[initialCount+j], randomNums[i]);
- }
- }
- }
- free(randomNums);
- return NULL;
- }
- #define GIVEN_A_RANDOM_LIST(listname, size) \
- Listfloat listname; \
- Listfloat_Init(&listname); \
- { TestErrorResult* err = AddRandomFloats(&listname, size); \
- if (err != NULL) { \
- return err; \
- } }
- TestErrorResult* test_Listfloat_Adds() {
- GIVEN_A_RANDOM_LIST(list,10)
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_Remove() {
- GIVEN_A_RANDOM_LIST(list,10)
- int result = Listfloat_Remove(&list, -1);
- IMPLEMENT_CHECK(result)
- if (result == 0) {
- return LISTERR(&list,"Remove returned no error code with negative index\n", 0);
- }
- result = Listfloat_Remove(&list, list.capacity);
- if (result == 0) {
- return LISTERR(&list,"Remove returned no error code with OOB index\n", 0);
- }
- int initialCapacity = list.capacity;
- int originalCount = list.count;
- for(int i = 0; i < originalCount; ++i) {
- int indexToRemove = rand() % list.count;
- float valueToRemove = list.get[indexToRemove];
- float nextValue = 0;
- if (indexToRemove < list.count-1) {
- nextValue = list.get[indexToRemove+1];
- }
- result = Listfloat_Remove(&list, indexToRemove);
- if (result != 0) {
- return LISTERR(&list,"Remove returned an error code %d when none was expected\n", result);
- }
- if (list.count != originalCount-(1+i)) {
- return LISTERR(&list,"Remove didn't reduce the count as expected. got %d instead of %d\n",
- list.count, originalCount-(1+i));
- }
- if (list.capacity != initialCapacity) {
- return LISTERR(&list,"Remove changed the capacity? expected capacity to stay %d, it changed to %d\n",
- initialCapacity, list.capacity);
- }
- if (list.get[indexToRemove] == valueToRemove) {
- return LISTERR(&list,"Remove(%d) didn't remove.\n", indexToRemove);
- }
- }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_RemoveRange() {
- GIVEN_A_RANDOM_LIST(list,20)
- int initialSize = list.count;
- int start = 1 + rand() % (initialSize-3), length = 2;
- int result = Listfloat_RemoveRange(&list, -1, 2);
- IMPLEMENT_CHECK(result)
- if (result == 0) {
- return ERR("RemoveRange returned no error code with negative index");
- }
- result = Listfloat_RemoveRange(&list, list.capacity, 1);
- if (result == 0) {
- return ERR("RemoveRange returned no error code with OOB index");
- }
- result = Listfloat_RemoveRange(&list, 1, -1);
- if (result == 0) {
- return ERR("RemoveRange returned no error code with negative count");
- }
- result = Listfloat_RemoveRange(&list, start, length);
- if (result != 0) {
- return ERR("RemoveRange returned error (%d) for values %d, %d (should be valid for size %d)",
- result, start, length, initialSize);
- }
- if (list.count != initialSize-length) {
- return ERR("count did not reduce as expected. expected %d, instead of %d",
- (initialSize-length), list.count);
- }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_Insert() {
- Listfloat list;
- Listfloat_Init(&list);
- int index = 0;
- float value = RandomFloat();
- // insert index 0 from empty list
- int result = Listfloat_Insert(&list, index, value);
- IMPLEMENT_CHECK(result)
- if (result != 0) { return ERR("insert should return 0 if successful"); }
- result = Listfloat_Insert(&list, -1, value);
- if (result == 0) { return ERR("insert should return error code for invalid indexes"); }
- result = Listfloat_Insert(&list, list.capacity+1, value);
- if (result == 0) { return ERR("insert should return error code for invalid indexes"); }
- if (list.count != 1) {
- return ERR("inserting %f into empty list should add", value);
- }
- if (list.count != 1 || list.get[index] != value) {
- return LISTERR(&list,"inserting %f into empty list should add\n", value);
- }
- int expectedCount = list.count;
- for(index = 0; index < 3; ++index) {
- value = RandomFloat();
- result = Listfloat_Insert(&list, index, value);
- expectedCount++;
- if (list.count != expectedCount || list.get[index] != value) {
- return LISTERR(&list,"inserting %f into %d didn't work\n", value, index);
- }
- }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_Clear() {
- GIVEN_A_RANDOM_LIST(list,10)
- if(list.count == 0) { return ERR("list started empty. that shouldn't happen."); }
- int result = Listfloat_Clear(&list);
- IMPLEMENT_CHECK(result)
- if(list.count != 0) { return LISTERR(&list,"clear does not set count to zero!\n"); }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_IndexOf() {
- GIVEN_A_RANDOM_LIST(list,20)
- int found = Listfloat_IndexOf(&list, 2);
- IMPLEMENT_CHECK(found)
- if (found >= 0) { return LISTERR(&list,"found element 2, which should be impossible\n"); }
- for(int i = 0; i < 10; i++) {
- int index = rand() % (list.count-2);
- list.get[index] = 2;
- list.get[index+2] = 2;
- found = Listfloat_IndexOf(&list, 2);
- if (found != index) {
- return LISTERR(&list,"didn't find element 2 (at %d), IndexOf found it at %d\n", index, found);
- }
- found = Listfloat_IndexOfStartingAt(&list, 2, index+1, list.count);
- if (found != index+2) {
- return LISTERR(&list,"didn't find element 2 after %d (at %d), IndexOf found it at %d\n",
- index+1, index+2, found);
- }
- list.get[index] = 0;
- list.get[index+2] = 0;
- }
- found = Listfloat_IndexOf(&list, 2);
- if (found >= 0) { return LISTERR(&list,"found element 2 again, which should be impossible\n"); }
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_IndexOfLast() {
- GIVEN_A_RANDOM_LIST(list,20)
- int found = Listfloat_IndexOfLast(&list, 2);
- IMPLEMENT_CHECK(found)
- if (found >= 0) { return LISTERR(&list,"found element 2, which should be impossible\n"); }
- for(int i = 0; i < 10; i++) {
- int index = (rand() % (list.count-2)) + 2;
- list.get[index] = 2;
- list.get[index-2] = 2;
- found = Listfloat_IndexOfLast(&list, 2);
- if (found != index) {
- return LISTERR(&list,"didn't find element 2 (at %d), IndexOf found it at %d\n", index, found);
- }
- found = Listfloat_IndexOfLastEndingAt(&list, 2, index-1, 0);
- if (found != index-2) {
- return LISTERR(&list,"didn't find element 2 after %d (at %d), IndexOf found it at %d\n",
- index+1, index-2, found);
- }
- list.get[index] = 0;
- list.get[index-2] = 0;
- }
- found = Listfloat_IndexOf(&list, 2);
- if (found >= 0) {
- return LISTERR(&list,"found element 2 again, which should be impossible\n");
- }
- Listfloat_Release(&list);
- return NULL;
- }
- void Swap(float* a, float* b) {
- float temp = *a;
- *a = *b;
- *b = temp;
- }
- int IsListInOrder(Listfloat* list, SortPredicate sortPredicate) {
- for(int i = 1; i < list->count; ++i)
- if (sortPredicate(&(list->get[i]), &(list->get[i-1])))
- return FAIL;
- return SUCCESS;
- }
- int SortPredicateLittleEndian(void* a, void* b) {
- float fa = *((float*)a);
- float fb = *((float*)b);
- return fa < fb;
- }
- void MakeSureListIsOutOfOrder (Listfloat* list) {
- if (IsListInOrder(list, SortPredicateLittleEndian) == FAIL) {
- return;
- }
- if (list->get[0] != list->get[1]) {
- Swap(&list->get[0], &list->get[1]);
- return;
- }
- list->get[0] = list->get[1] + 1;
- }
- TestErrorResult* test_Listfloat_Sort() {
- GIVEN_A_RANDOM_LIST(list,20)
- MakeSureListIsOutOfOrder(&list);
- int result = Listfloat_Sort(&list);
- IMPLEMENT_CHECK(result)
- if (IsListInOrder(&list, SortPredicateLittleEndian) == FAIL) {
- return LISTERR(&list, "sort did not sort a random list\n");
- }
- Listfloat_Release(&list);
- return NULL;
- }
- int SortPredicateBigEndian(void* a, void* b) {
- float fa = *((float*)a);
- float fb = *((float*)b);
- return fb < fa;
- }
- TestErrorResult* test_Listfloat_SortPredicate() {
- GIVEN_A_RANDOM_LIST(list,20)
- MakeSureListIsOutOfOrder(&list);
- int result = Listfloat_SortPredicate(&list, SortPredicateLittleEndian);
- IMPLEMENT_CHECK(result)
- if (IsListInOrder(&list, SortPredicateLittleEndian) == FAIL) {
- return LISTERR(&list, "sort predicate did not sort a random list in order\n");
- }
- Listfloat_Clear(&list);
- AddRandomFloats(&list, 30);
- Listfloat_SortPredicate(&list, SortPredicateBigEndian);
- if (IsListInOrder(&list, SortPredicateBigEndian) == FAIL) {
- return LISTERR(&list, "sort predicate did not sort a random list in reverse order\n");
- }
- Listfloat_Release(&list);
- return NULL;
- }
- int __SortPredicateLittleEndianCounted_count;
- int SortPredicateLittleEndianCounted(void* X, void* Y) {
- ++__SortPredicateLittleEndianCounted_count;
- float r = *((float*)X) - *((float*)Y);
- return r < 0 ? -1 : r > 0 ? 1 : 0;
- }
- int GetLog2(int value) {
- int count = 0;
- while(value > 0) {
- value >>= 1;
- ++count;
- }
- return count;
- }
- TestErrorResult* test_Listfloat_BinarySearchComparer() {
- GIVEN_A_RANDOM_LIST(list,40)
- Listfloat_SortPredicate(&list, SortPredicateLittleEndian);
- int maxSearches = GetLog2(list.count);
- int indexToSearch = 0;//(list.count-1) /2 /2;
- float lookingFor = list.get[indexToSearch];
- __SortPredicateLittleEndianCounted_count = 0;
- int found = Listfloat_BinarySearchComparer(&list, lookingFor, SortPredicateLittleEndianCounted);
- IMPLEMENT_CHECK(found)
- if (found < 0 || list.get[found] != lookingFor) {
- return LISTERR(&list, "binarysearch looked for %f (at index %d), and %d was returned after %d searches\n",
- lookingFor, indexToSearch, found, __SortPredicateLittleEndianCounted_count);
- }
- if (__SortPredicateLittleEndianCounted_count > maxSearches) {
- return LISTERR(&list, "binarysearch found %f at %d, after %d searches (too many searches)\n",
- lookingFor, indexToSearch, __SortPredicateLittleEndianCounted_count);
- }
- indexToSearch = list.count-1-indexToSearch;
- lookingFor = list.get[indexToSearch];
- __SortPredicateLittleEndianCounted_count = 0;
- found = Listfloat_BinarySearchComparer(&list, lookingFor, SortPredicateLittleEndianCounted);
- if (found < 0 || list.get[found] != lookingFor) {
- return LISTERR(&list, "binarysearch looked for %f (at index %d), and %d was returned after %d searches\n",
- lookingFor, indexToSearch, found, __SortPredicateLittleEndianCounted_count);
- }
- if (__SortPredicateLittleEndianCounted_count > maxSearches) {
- return LISTERR(&list, "binarysearch found %f at %d, after %d searches (too many searches)\n",
- lookingFor, indexToSearch, __SortPredicateLittleEndianCounted_count);
- }
- Listfloat_Release(&list);
- return NULL;
- }
- void AddTwoListsToErrorMessage(TestErrorResult* e, float* list1, int list1count, float* list2, int list2count, int digits) {
- AppendArrayToCharBuffer(e->message, sizeof(e->message), list1, list1count, digits);
- int len = strlen(e->message);
- if(len+2 < sizeof(e->message)) {
- e->message[len] = '\n';
- e->message[len+1] = '\0';
- AppendArrayToCharBuffer(e->message, sizeof(e->message), list2, list2count, digits);
- }
- }
- TestErrorResult* test_Listfloat_Reverse() {
- GIVEN_A_RANDOM_LIST(list,10)
- float* copy = malloc(sizeof(float)*list.count);
- for(int i = 0; i < 10; ++i)
- list.get[i] = i;
- Listfloat_Copy(copy, list.get, list.count);
- int result = Listfloat_Reverse(&list);
- IMPLEMENT_CHECK(result)
- for(int i = 0; i < list.count; ++i) {
- if (list.get[i] != copy[list.count-1-i]) {
- TestErrorResult* e = ERR("reverse doesn't work.\n");
- AddTwoListsToErrorMessage(e, copy, list.count, list.get, list.count, 4);
- return e;
- }
- }
- free(copy);
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_GetSublist() {
- GIVEN_A_RANDOM_LIST(list,10)
- int count = (rand() % 5) + 3;
- int start = rand() % 3;
- float* destination = malloc(sizeof(float)*count);
- int result = Listfloat_GetSublist(&list, start, count, destination);
- IMPLEMENT_CHECK(result)
- for(int i = 0; i < count; ++i) {
- if (destination[i] != list.get[start+i]) {
- TestErrorResult* e = ERR("failed to get complete sublist index:%d count:%d.\n", start, count);
- AddTwoListsToErrorMessage(e, destination, count, list.get, list.count, 4);
- return e;
- }
- }
- free(destination);
- Listfloat_Release(&list);
- return NULL;
- }
- TestErrorResult* test_Listfloat_InsertRange() {
- int originalListSize = (rand() % 5) + 5;
- int count = (rand() % 5) + 3;
- int start = rand() % 3;
- GIVEN_A_RANDOM_LIST(list,originalListSize)
- GIVEN_A_RANDOM_LIST(sublist,count)
- int result = Listfloat_InsertRange(&list, start, sublist.get, sublist.count);
- IMPLEMENT_CHECK(result)
- if (list.count != originalListSize + sublist.count) {
- TestErrorResult* e = ERR("InsertRange(%d, %d) didn't increase size correctly.\n", start, count);
- AddTwoListsToErrorMessage(e, list.get, list.count, sublist.get, sublist.count, 4);
- return e;
- }
- for(int i = 0; i < sublist.count; ++i) {
- if (list.get[start+i] != sublist.get[i]) {
- TestErrorResult* e = ERR("InsertRange(%d, %d) didn't copy data correctly.\n", start, count);
- AddTwoListsToErrorMessage(e, list.get, list.count, sublist.get, sublist.count, 4);
- return e;
- }
- }
- Listfloat_Release(&sublist);
- Listfloat_Release(&list);
- return NULL;
- }
- // TODO make test cases for
- // for each
- // find index (predicate)
- // find last (predicate)
- // find all (predicate)
- #define TEST(a) {#a, a}
- TestFunctionEntry testFunctionEntries[] = {
- TEST(test_Listfloat_Init),
- TEST(test_Listfloat_SetCapacity),
- TEST(test_Listfloat_Release),
- TEST(test_Listfloat_Add),
- TEST(test_Listfloat_Adds),
- TEST(test_Listfloat_Remove),
- TEST(test_Listfloat_RemoveRange),
- TEST(test_Listfloat_Clear),
- TEST(test_Listfloat_Insert),
- TEST(test_Listfloat_IndexOf),
- TEST(test_Listfloat_IndexOfLast),
- TEST(test_Listfloat_Sort),
- TEST(test_Listfloat_SortPredicate),
- TEST(test_Listfloat_BinarySearchComparer),
- TEST(test_Listfloat_Reverse),
- TEST(test_Listfloat_GetSublist),
- TEST(test_Listfloat_InsertRange),
- TEST(NULL),
- };
- #include <time.h>
- int RunTest(TestFunctionEntry* test) {
- TestErrorResult* error = test->func();
- if (error != NULL) {
- printf("%s failed @ %s:%d\n%s\n", test->name, error->file, error->line, error->message);
- return FAIL;
- }
- return SUCCESS;
- }
- void RunTests() {
- srand(time(0));
- int t = 0;
- while(testFunctionEntries[t].func) {
- printf("%s\r", testFunctionEntries[t].name);
- if(RunTest(&testFunctionEntries[t]) == FAIL)
- return;
- Success(testFunctionEntries[t].name, 500, 2);
- printf("\n");
- ++t;
- }
- Success("ALL TESTS PASSED!", 500*10, 2*10);
- }
- int main(int argc, char** argv) {
- RunTests();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement