浏览代码

use unit tests

master
Felix Brendel 5 年前
父节点
当前提交
da6c41bbb0
共有 8 个文件被更改,包括 496 次插入162 次删除
  1. +20
    -2
      arraylist.hpp
  2. +3
    -5
      bucket_allocator.hpp
  3. +11
    -10
      build.bat
  4. +6
    -2
      error.hpp
  5. +452
    -0
      main.cpp
  6. +1
    -2
      print.hpp
  7. +0
    -138
      test.cpp
  8. +3
    -3
      testing.hpp

+ 20
- 2
arraylist.hpp 查看文件

@@ -16,19 +16,26 @@ struct Array_List {
length = initial_capacity;
}

static Array_List<type> create_from(std::initializer_list<type> l) {
Array_List<type> ret;
ret.alloc_from(l);
return ret;
}

void alloc_from(std::initializer_list<type> l) {
length = max(l.size(), 1); // alloc at least one

data = (type*)malloc(length * sizeof(type));
count = 0;
// TODO(Felix): Use memcpy here
for (type t : l) {
data[count++] = t;
}
}


void extend(std::initializer_list<type> l) {
reserve(l.size());
// TODO(Felix): Use memcpy here
for (type e : l) {
append(e);
}
@@ -50,12 +57,23 @@ struct Array_List {
ret.count = count;

ret.data = (type*)malloc(length * sizeof(type));
// TODO(Felix): Maybe use memcpy here
for (u32 i = 0; i < count; ++i) {
ret.data[i] = data[i];
}
return ret;
}

void copy_values_from(Array_List<type> other) {
// clear the array
count = 0;
// make sure we have allocated enough
reserve(other.count);
// copy stuff
count = other.count;
memcpy(data, other.data, sizeof(type) * other.count);
}
type* begin() {
return data;
}
@@ -139,7 +157,7 @@ struct Array_List {
_merge(left, middle, right);
}

u32 sorted_find(type elem, s32 left=-1, s32 right=-1) {
s32 sorted_find(type elem, s32 left=-1, s32 right=-1) {
if (left == -1) {
return sorted_find(elem, 0, count - 1);
} else if (left == right) {


+ 3
- 5
bucket_allocator.hpp 查看文件

@@ -2,7 +2,7 @@
#include "types.hpp"

template <typename type>
class Bucket_Allocator {
struct Bucket_Allocator {
u32 next_index_in_latest_bucket;
u32 next_bucket_index;
u32 bucket_count;
@@ -12,8 +12,6 @@ class Bucket_Allocator {
type** buckets;

void expand() {
// printf("realloc time\n");
// realloc time
buckets = (type**)realloc(buckets, bucket_count * 2 * sizeof(type*));
bucket_count *= 2;
}
@@ -34,8 +32,7 @@ class Bucket_Allocator {
}
}

public:
void alloc(u32 bucket_size = 16, u32 initial_bucket_count = 8) {
void alloc(u32 bucket_size = 16, u32 initial_bucket_count = 8) {
this->free_list.alloc();
this->bucket_size = bucket_size;
next_index_in_latest_bucket = 0;
@@ -76,6 +73,7 @@ public:
template <typename lambda>
void for_each(lambda p) {
free_list.sort();

type* val;
for (u32 i = 0; i < next_bucket_index; ++i) {
for (u32 j = 0; j < bucket_size; ++j) {


+ 11
- 10
build.bat 查看文件

@@ -1,10 +1,11 @@
@echo off

mkdir bin
rmdir bin /s /q 2>NUL
mkdir bin 2>NUL

set EXE_RAW=test
set BINDIR_RAW=bin
set SRC=test.cpp
set SRC=main.cpp

set EXE_WIN=%EXE_RAW%.exe
set EXE_LINUX=%EXE_RAW%
@@ -21,15 +22,15 @@ echo g++:
g++ -std=c++17 %SRC% -o %BINDIR_WIN%\g++_%EXE_WIN%
%BINDIR_WIN%\g++_%EXE_WIN%

REM echo.
REM echo cl:
REM cl %SRC% /std:c++latest /nologo /Zi /Fd: %BINDIR_WIN%\cl_%EXE_WIN%.pdb /Fo: %BINDIR_WIN%\ /Fe: %BINDIR_WIN%\cl_%EXE_WIN% /wd4090
REM %BINDIR_WIN%\cl_%EXE_WIN%
echo.
echo cl:
cl %SRC% /std:c++latest /nologo /Zi /Fd: %BINDIR_WIN%\cl_%EXE_WIN%.pdb /Fo: %BINDIR_WIN%\ /Fe: %BINDIR_WIN%\cl_%EXE_WIN% /wd4090 1>NUL
%BINDIR_WIN%\cl_%EXE_WIN%

REM echo.
REM echo bash_clang:
REM bash -c "clang -std=c++17 %SRC% -o %BINDIR_LINUX%/bash_clang_%EXE_LINUX% && %BINDIR_LINUX%/bash_clang_%EXE_LINUX%"
echo.
echo bash_clang:
bash -c "clang++ --std=c++17 %SRC% -o %BINDIR_LINUX%/bash_clang_%EXE_LINUX% && %BINDIR_LINUX%/bash_clang_%EXE_LINUX%"

echo.
echo bash_g++:
bash -c "g++ -std=c++17 %SRC% -o %BINDIR_LINUX%/bash_g++_%EXE_LINUX% && %BINDIR_LINUX%/bash_g++_%EXE_LINUX%"
bash -c "g++ --std=c++17 %SRC% -o %BINDIR_LINUX%/bash_g++_%EXE_LINUX% && %BINDIR_LINUX%/bash_g++_%EXE_LINUX%"

+ 6
- 2
error.hpp 查看文件

@@ -1,5 +1,6 @@
#pragma once
#include "stdio.h"

#include "math.h"
#include "stdarg.h"
#include "stdlib.h"
@@ -53,11 +54,14 @@ auto create_error(const char* c_func_name, const char* c_file_name,
#define create_generic_error(...) \
__create_error("generic", __VA_ARGS__)

#define assert(condition, ...) \
#ifdef assert
#undef assert
#endif
#define assert(condition, ...) \
do { \
if (!(condition)) { \
char* msg; \
print_to_string(&msg, __VA_ARGS__); \
print_to_string(&msg, __VA_ARGS__); \
create_assertion_error("Assertion-error: %s\n" \
" condition: %s\n" \
" in: %s:%d", \


+ 452
- 0
main.cpp 查看文件

@@ -0,0 +1,452 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include "./types.hpp"

u32 hm_hash(u32 u);
inline bool hm_objects_match(u32 a, u32 b);
struct Key;
u32 hm_hash(Key u);
inline bool hm_objects_match(Key a, Key b);

#define ZoneScoped
#define ZoneScopedN(name)

#include "./print.hpp"
#include "./testing.hpp"
#include "./bucket_allocator.hpp"
#include "./error.hpp"
#include "./hooks.hpp"
#include "./hashmap.hpp"

#include "./error.hpp"


u32 hm_hash(u32 u) {
return ((u64)u * 2654435761) % 4294967296;
}

inline bool hm_objects_match(u32 a, u32 b) {
return a == b;
}

struct Key {
int x;
int y;
int z;
};


u32 hm_hash(Key u) {
return ((u.y ^ (u.x << 1)) >> 1) ^ u.z;
}

inline bool hm_objects_match(Key a, Key b) {
return a.x == b.x
&& a.y == b.y
&& a.z == b.z;
}


auto print_dots(FILE* f) -> u32 {
return print_to_file(f, "...");
}

proc is_sorted = [](Array_List<s32> list) -> bool {
for (u32 i = 0; i < list.count - 1; ++i) {
if (list.data[i] > list.data[i+1])
return false;
}
return true;
};

proc is_sorted_vp = [](Array_List<void*> list) -> bool {
for (u32 i = 0; i < list.count - 1; ++i) {
if (list.data[i] > list.data[i+1])
return false;
}
return true;
};


auto test_printer() -> void {
u32 arr[] = {1,2,3,4,1,1,3};
f32 f_arr[] = {1.1,2.1,3.2};


register_printer("dots", print_dots, Printer_Function_Type::_void);

u32 u1 = -1;
u64 u2 = -1;

char* str;
print_to_string(&str, " - %{dots[5]} %{->} <> %{->,2}\n", &u1, &arr, nullptr);
print("---> %{->char}", str);

print(" - %{dots[3]}\n");
print(" - %{u32} %{u64}\n", u1, u2);
print(" - %{u32} %{u32} %{u32}\n", 2, 5, 7);
print(" - %{f32} %{f32} %{f32}\n", 2.0, 5.0, 7.0);
print(" - %{u32} %{bool} %{->char}\n", 2, true, "hello");
print(" - %{f32[3]}\n", f_arr);
print(" - %{f32,3}\n", 44.9, 55.1, 66.2);
print(" - %{u32[5]}\n", arr);
print(" - %{u32[*]}\n", arr, 4);
print(" - %{u32,5}\n", 1,2,3,4,1,2);
print(" - %{unknown%d}\n", 1);
print(" - %{s32,3}\n", -1,200,-300);
print(" - %{->} <> %{->,2}\n", &u1, &arr, nullptr);

print("%{->char}%{->char}%{->char}",
true ? "general " : "",
false ? "validation " : "",
false ? "performance " : "");

// print("%{->char}%{->char}\n\n", "hallo","");

}

auto test_hm() -> void {
Hash_Map<u32, u32> h1;
h1.alloc();
defer { h1.dealloc(); };

h1.set_object(1, 2);
h1.set_object(2, 4);
h1.set_object(3, 6);
h1.set_object(4, 8);

assert(h1.key_exists(1), "key shoud exist");
assert(h1.key_exists(2), "key shoud exist");
assert(h1.key_exists(3), "key shoud exist");
assert(h1.key_exists(4), "key shoud exist");
assert(!h1.key_exists(5), "key shoud not exist");

assert(h1.get_object(1) == 2, "value should be correct");
assert(h1.get_object(2) == 4, "value should be correct");
assert(h1.get_object(3) == 6, "value should be correct");
assert(h1.get_object(4) == 8, "value should be correct");


Hash_Map<Key, u32> h2;
h2.alloc();
defer { h2.dealloc(); };

h2.set_object({.x = 1, .y = 2, .z = 3}, 1);
h2.set_object({.x = 3, .y = 3, .z = 3}, 3);

assert(h2.key_exists({.x = 1, .y = 2, .z = 3}), "key shoud exist");
assert(h2.key_exists({.x = 3, .y = 3, .z = 3}), "key shoud exist");

assert(h2.get_object({.x = 1, .y = 2, .z = 3}) == 1, "value should be correct");
assert(h2.get_object({.x = 3, .y = 3, .z = 3}) == 3, "value should be correct");

h2.for_each([] (Key k, u32 v, u32 i) {
print("%{s32} %{u32} %{u32}\n", k.x, v, i);
});
}


proc test_array_lists_adding_and_removing() -> testresult {
// test adding and removing
Array_List<s32> list;
list.alloc();

defer {
list.dealloc();
};

list.append(1);
list.append(2);
list.append(3);
list.append(4);

assert_equal_int(list.count, 4);

list.remove_index(0);

assert_equal_int(list.count, 3);
assert_equal_int(list[0], 4);
assert_equal_int(list[1], 2);
assert_equal_int(list[2], 3);

list.remove_index(2);

assert_equal_int(list.count, 2);
assert_equal_int(list[0], 4);
assert_equal_int(list[1], 2);

return pass;
}


proc test_array_lists_sorting() -> testresult {
//
//
// Test simple numbers
//
//
Array_List<s32> list;
list.alloc();
defer {
list.dealloc();
};

list.append(1);
list.append(2);
list.append(3);
list.append(4);

list.sort();
assert_equal_int(is_sorted(list), true);

list.append(4);
list.append(2);
list.append(1);

assert_equal_int(is_sorted(list), false);
list.sort();
assert_equal_int(is_sorted(list), true);

list.clear();
list.extend({
8023, 7529, 2392, 7110,
3259, 2484, 9695, 2199,
6729, 9009, 8429, 7208});
assert_equal_int(is_sorted(list), false);
list.sort();
assert_equal_int(is_sorted(list), true);


//
//
// Test adding and removing
//
//
Array_List<s32> list1;
list1.alloc();
defer {
list1.dealloc();
};

list1.append(1);
list1.append(2);
list1.append(3);
list1.append(4);

list1.sort();

assert_equal_int(list1.count, 4);

assert_equal_int(list1[0], 1);
assert_equal_int(list1[1], 2);
assert_equal_int(list1[2], 3);
assert_equal_int(list1[3], 4);
assert_equal_int(is_sorted(list1), true);

list1.append(0);
list1.append(5);

assert_equal_int(list1.count, 6);

list1.sort();

assert_equal_int(list1[0], 0);
assert_equal_int(list1[1], 1);
assert_equal_int(list1[2], 2);
assert_equal_int(list1[3], 3);
assert_equal_int(list1[4], 4);
assert_equal_int(list1[5], 5);
assert_equal_int(is_sorted(list1), true);

//
//
//
//
// pointer list
Array_List<void*> al;
al.alloc();
defer {
al.dealloc();
};
al.append((void*)0x1703102F100);
al.append((void*)0x1703102F1D8);
al.append((void*)0x1703102F148);
al.append((void*)0x1703102F190);
al.append((void*)0x1703102F190);
al.append((void*)0x1703102F1D8);

assert_equal_int(is_sorted_vp(al), false);
al.sort();
assert_equal_int(is_sorted_vp(al), true);

assert_not_equal_int(al.sorted_find((void*)0x1703102F100), -1);
assert_not_equal_int(al.sorted_find((void*)0x1703102F1D8), -1);
assert_not_equal_int(al.sorted_find((void*)0x1703102F148), -1);
assert_not_equal_int(al.sorted_find((void*)0x1703102F190), -1);
assert_not_equal_int(al.sorted_find((void*)0x1703102F190), -1);
assert_not_equal_int(al.sorted_find((void*)0x1703102F1D8), -1);

return pass;
}

proc test_array_lists_searching() -> testresult {
Array_List<s32> list1;
list1.alloc();
defer {
list1.dealloc();
};

list1.append(1);
list1.append(2);
list1.append(3);
list1.append(4);

s32 index = list1.sorted_find(3);
assert_equal_int(index, 2);

index = list1.sorted_find(1);
assert_equal_int(index, 0);

index = list1.sorted_find(5);
assert_equal_int(index, -1);
return pass;
}

proc test_bucket_allocator() -> testresult {
Bucket_Allocator<s32> ba;
ba.alloc();
defer {
ba.dealloc();
};

s32* s1 = ba.allocate();
s32* s2 = ba.allocate();
s32* s3 = ba.allocate();
s32* s4 = ba.allocate();
s32* s5 = ba.allocate();

*s1 = 1;
*s2 = 2;
*s3 = 3;
*s4 = 4;
*s5 = 5;

s32 wrong_answers = 0;
s32 counter = 1;
ba.for_each([&](s32* s) -> void {
if(counter != *s)
++wrong_answers;
++counter;
});
assert_equal_int(wrong_answers, 0);



Bucket_Allocator<s32> ba2;
ba2.alloc();
defer {
ba2.dealloc();
};

s1 = ba2.allocate();
s2 = ba2.allocate();
s3 = ba2.allocate();


s32* s3_copy = ba2.allocate();
s32* s3_copy2 = ba2.allocate();
s32* s3_copy3 = ba2.allocate();
*s3_copy = 3;
ba2.free_object(s3_copy);


s4 = ba2.allocate();

ba2.free_object(s3_copy2);

s5 = ba2.allocate();

ba2.free_object(s3_copy3);

*s1 = 1;
*s2 = 2;
*s3 = 3;
*s4 = 4;
*s5 = 5;

wrong_answers = 0;
counter = 1;
ba2.for_each([&](s32* s) -> void {
if(counter != *s)
++wrong_answers;
++counter;
});
assert_equal_int(wrong_answers, 0);


return pass;
}

auto test_array_list_sort_many() -> testresult {
Array_List<s32> list;
list.alloc();
defer {
list.dealloc();
};

for (int i = 0; i < 10000; ++i) {
list.append(rand());
}

assert_equal_int(is_sorted(list), false);
list.sort();
assert_equal_int(is_sorted(list), true);

for (int i = 0; i < 10000; ++i) {
assert_not_equal_int(list.sorted_find(list.data[i]), -1);
}

list.clear();
for (int i = 0; i < 1111; ++i) {
list.append(rand());
}

assert_equal_int(is_sorted(list), false);
list.sort();
assert_equal_int(is_sorted(list), true);

for (int i = 0; i < 1111; ++i) {
assert_not_equal_int(list.sorted_find(list.data[i]), -1);
}


list.clear();
for (int i = 0; i < 3331; ++i) {
list.append(rand());
}

assert_equal_int(is_sorted(list), false);
list.sort();
assert_equal_int(is_sorted(list), true);

for (int i = 0; i < 3331; ++i) {
assert_not_equal_int(list.sorted_find(list.data[i]), -1);
}


return pass;
}

s32 main(s32, char**) {
init_printer();
testresult result;

invoke_test(test_array_lists_adding_and_removing);
invoke_test(test_array_lists_sorting);
invoke_test(test_array_lists_searching);
invoke_test(test_array_list_sort_many);
invoke_test(test_bucket_allocator);

return 0;
}

+ 1
- 2
print.hpp 查看文件

@@ -6,11 +6,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "platform.hpp"

#ifdef FTB_WINDOWS
#include <Windows.h>
#endif
#include "platform.hpp"
#include "hashmap.hpp"
#include "hooks.hpp"

@@ -443,7 +443,6 @@ auto print_Str(FILE* f, String* str) -> s32 {

auto print_str_line(FILE* f, char* str) -> s32 {
u32 length = 0;
char* str_cpy = str;
while (str[length] != '\0') {
if (str[length] == '\n')
break;


+ 0
- 138
test.cpp 查看文件

@@ -1,138 +0,0 @@
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include "./types.hpp"

u32 hm_hash(u32 u);
inline bool hm_objects_match(u32 a, u32 b);
struct Key;
u32 hm_hash(Key u);
inline bool hm_objects_match(Key a, Key b);

#define ZoneScoped
#define ZoneScopedN(name)

#include "./error.hpp"
#include "./hooks.hpp"
#include "./hashmap.hpp"

#include "./error.hpp"
#include "./print.hpp"


u32 hm_hash(u32 u) {
return ((u64)u * 2654435761) % 4294967296;
}

inline bool hm_objects_match(u32 a, u32 b) {
return a == b;
}

struct Key {
int x;
int y;
int z;
};


u32 hm_hash(Key u) {
return ((u.y ^ (u.x << 1)) >> 1) ^ u.z;
}

inline bool hm_objects_match(Key a, Key b) {
return a.x == b.x
&& a.y == b.y
&& a.z == b.z;
}


auto print_dots(FILE* f) -> u32 {
return print_to_file(f, "...");
}

auto test_printer() -> void {
u32 arr[] = {1,2,3,4,1,1,3};
f32 f_arr[] = {1.1,2.1,3.2};


register_printer("dots", print_dots, Printer_Function_Type::_void);

u32 u1 = -1;
u64 u2 = -1;

char* str;
print_to_string(&str, " - %{dots[5]} %{->} <> %{->,2}\n", &u1, &arr, nullptr);
print("---> %{->char}", str);

print(" - %{dots[3]}\n");
print(" - %{u32} %{u64}\n", u1, u2);
print(" - %{u32} %{u32} %{u32}\n", 2, 5, 7);
print(" - %{f32} %{f32} %{f32}\n", 2.0, 5.0, 7.0);
print(" - %{u32} %{bool} %{->char}\n", 2, true, "hello");
print(" - %{f32[3]}\n", f_arr);
print(" - %{f32,3}\n", 44.9, 55.1, 66.2);
print(" - %{u32[5]}\n", arr);
print(" - %{u32[*]}\n", arr, 4);
print(" - %{u32,5}\n", 1,2,3,4,1,2);
print(" - %{unknown%d}\n", 1);
print(" - %{s32,3}\n", -1,200,-300);
print(" - %{->} <> %{->,2}\n", &u1, &arr, nullptr);

print("%{->char}%{->char}%{->char}",
true ? "general " : "",
false ? "validation " : "",
false ? "performance " : "");

// print("%{->char}%{->char}\n\n", "hallo","");

}

auto test_hm() -> void {
Hash_Map<u32, u32> h1;
h1.alloc();
defer { h1.dealloc(); };

h1.set_object(1, 2);
h1.set_object(2, 4);
h1.set_object(3, 6);
h1.set_object(4, 8);

assert(h1.key_exists(1), "key shoud exist");
assert(h1.key_exists(2), "key shoud exist");
assert(h1.key_exists(3), "key shoud exist");
assert(h1.key_exists(4), "key shoud exist");
assert(!h1.key_exists(5), "key shoud not exist");

assert(h1.get_object(1) == 2, "value should be correct");
assert(h1.get_object(2) == 4, "value should be correct");
assert(h1.get_object(3) == 6, "value should be correct");
assert(h1.get_object(4) == 8, "value should be correct");


Hash_Map<Key, u32> h2;
h2.alloc();
defer { h2.dealloc(); };

h2.set_object({.x = 1, .y = 2, .z = 3}, 1);
h2.set_object({.x = 3, .y = 3, .z = 3}, 3);

assert(h2.key_exists({.x = 1, .y = 2, .z = 3}), "key shoud exist");
assert(h2.key_exists({.x = 3, .y = 3, .z = 3}), "key shoud exist");

assert(h2.get_object({.x = 1, .y = 2, .z = 3}) == 1, "value should be correct");
assert(h2.get_object({.x = 3, .y = 3, .z = 3}) == 3, "value should be correct");

h2.for_each([] (Key k, u32 v, u32 i) {
print("%{s32} %{u32} %{u32}\n", k.x, v, i);
});
}

s32 main(s32 argc, char* argv[]) {
init_printer();

test_hm();

print("done.");

return 0;
}

+ 3
- 3
testing.hpp 查看文件

@@ -2,7 +2,7 @@

typedef s32 testresult;

#define epsilon 2.2204460492503131E-16
#define float_epsilon 2.2204460492503131E-16
#define pass 1
#define fail 0

@@ -57,13 +57,13 @@ typedef s32 testresult;
} \

#define assert_equal_f64(variable, value) \
if (fabsl((f64)variable - (f64)value) > epsilon) { \
if (fabsl((f64)variable - (f64)value) > float_epsilon) { \
print_assert_equal_fail(variable, value, f64, "%{f64}"); \
return fail; \
}

#define assert_not_equal_f64(variable, value) \
if (fabsl((f64)variable - (f64)value) <= epsilon) { \
if (fabsl((f64)variable - (f64)value) <= float_epsilon) { \
print_assert_not_equal_fail(variable, value, f64, "%{f64}"); \
return fail; \
}


正在加载...
取消
保存