Merge branch 'main' into heightmaps
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "coders/byte_utils.hpp"
|
||||
|
||||
TEST(byte_utils, BytesBuildAndRead) {
|
||||
ByteBuilder builder;
|
||||
builder.putCStr("MAGIC.#");
|
||||
builder.put(50);
|
||||
builder.putInt16(1980);
|
||||
builder.putInt32(123456789);
|
||||
builder.putInt64(98765432123456789LL);
|
||||
auto data = builder.build();
|
||||
|
||||
ByteReader reader(data.data(), data.size());
|
||||
reader.checkMagic("MAGIC.#", 8);
|
||||
EXPECT_EQ(reader.get(), 50);
|
||||
EXPECT_EQ(reader.getInt16(), 1980);
|
||||
EXPECT_EQ(reader.getInt32(), 123456789);
|
||||
EXPECT_EQ(reader.getInt64(), 98765432123456789LL);
|
||||
}
|
||||
+27
-25
@@ -3,46 +3,48 @@
|
||||
#include "typedefs.hpp"
|
||||
#include "coders/rle.hpp"
|
||||
|
||||
TEST(RLE, EncodeDecode) {
|
||||
const int initial_size = 50'000;
|
||||
static void test_encode_decode(
|
||||
size_t(*encodefunc)(const ubyte*, size_t, ubyte*),
|
||||
size_t(*decodefunc)(const ubyte*, size_t, ubyte*),
|
||||
int dencity
|
||||
) {
|
||||
const size_t initial_size = 50'000;
|
||||
uint8_t initial[initial_size];
|
||||
uint8_t next = rand();
|
||||
for (int i = 0; i < initial_size; i++) {
|
||||
for (size_t i = 0; i < initial_size; i++) {
|
||||
initial[i] = next;
|
||||
if (rand() % 13 == 0) {
|
||||
if (rand() % dencity == 0) {
|
||||
next = rand();
|
||||
}
|
||||
}
|
||||
uint8_t encoded[initial_size * 2];
|
||||
auto encoded_size = rle::encode(initial, initial_size, encoded);
|
||||
size_t encoded_size = encodefunc(initial, initial_size, encoded);
|
||||
uint8_t decoded[initial_size * 2];
|
||||
auto decoded_size = rle::decode(encoded, encoded_size, decoded);
|
||||
size_t decoded_size = decodefunc(encoded, encoded_size, decoded);
|
||||
|
||||
EXPECT_EQ(decoded_size, initial_size);
|
||||
|
||||
for (int i = 0; i < decoded_size; i++) {
|
||||
for (size_t i = 0; i < decoded_size; i++) {
|
||||
EXPECT_EQ(decoded[i], initial[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RLE, EncodeDecode) {
|
||||
test_encode_decode(rle::encode, rle::decode, 13);
|
||||
test_encode_decode(rle::encode, rle::decode, 90123);
|
||||
}
|
||||
|
||||
TEST(RLE16, EncodeDecode) {
|
||||
test_encode_decode(rle::encode16, rle::decode16, 13);
|
||||
test_encode_decode(rle::encode16, rle::decode16, 90123);
|
||||
}
|
||||
|
||||
TEST(ExtRLE, EncodeDecode) {
|
||||
const int initial_size = 50'000;
|
||||
uint8_t initial[initial_size];
|
||||
uint8_t next = rand();
|
||||
for (int i = 0; i < initial_size; i++) {
|
||||
initial[i] = next;
|
||||
if (rand() % 13 == 0) {
|
||||
next = rand();
|
||||
}
|
||||
}
|
||||
uint8_t encoded[initial_size * 2];
|
||||
auto encoded_size = extrle::encode(initial, initial_size, encoded);
|
||||
uint8_t decoded[initial_size * 2];
|
||||
auto decoded_size = extrle::decode(encoded, encoded_size, decoded);
|
||||
|
||||
EXPECT_EQ(decoded_size, initial_size);
|
||||
test_encode_decode(extrle::encode, extrle::decode, 13);
|
||||
test_encode_decode(extrle::encode, extrle::decode, 90123);
|
||||
}
|
||||
|
||||
for (int i = 0; i < decoded_size; i++) {
|
||||
EXPECT_EQ(decoded[i], initial[i]);
|
||||
}
|
||||
TEST(ExtRLE16, EncodeDecode) {
|
||||
test_encode_decode(extrle::encode16, extrle::decode16, 13);
|
||||
test_encode_decode(extrle::encode16, extrle::decode16, 90123);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#include "data/StructLayout.hpp"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
|
||||
using namespace data;
|
||||
|
||||
TEST(StructLayout, ReadWrite) {
|
||||
ubyte buffer[16] {};
|
||||
|
||||
std::vector<Field> fields {
|
||||
Field {FieldType::I8, "a", 1},
|
||||
Field {FieldType::CHAR, "s", 4},
|
||||
Field {FieldType::F32, "f", 1},
|
||||
};
|
||||
auto layout = StructLayout::create(fields);
|
||||
EXPECT_EQ(layout.size(), 9);
|
||||
|
||||
layout.setInteger(buffer, 42, "a");
|
||||
EXPECT_EQ(layout.getInteger(buffer, "a"), 42);
|
||||
|
||||
layout.setNumber(buffer, 3.141592f, "f");
|
||||
EXPECT_FLOAT_EQ(layout.getNumber(buffer, "f"), 3.141592f);
|
||||
|
||||
layout.setAscii(buffer, "hello", "s");
|
||||
EXPECT_EQ(layout.getChars(buffer, "s"), "hell");
|
||||
}
|
||||
|
||||
TEST(StructLayout, Unicode) {
|
||||
ubyte buffer[8] {};
|
||||
std::vector<Field> fields {
|
||||
Field {FieldType::CHAR, "text", 5},
|
||||
};
|
||||
auto layout = StructLayout::create(fields);
|
||||
EXPECT_EQ(layout.size(), 5);
|
||||
|
||||
layout.setUnicode(buffer, u8"テキストデモ", "text");
|
||||
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"テ"));
|
||||
|
||||
layout.setUnicode(buffer, u8"пример", "text");
|
||||
EXPECT_EQ(layout.getChars(buffer, "text"), std::string(u8"пр"));
|
||||
}
|
||||
|
||||
TEST(StructLayout, ConvertReorder) {
|
||||
ubyte src[16] {};
|
||||
std::vector<Field> srcFields {
|
||||
Field {FieldType::CHAR, "text", 5},
|
||||
Field {FieldType::F64, "pi", 1},
|
||||
};
|
||||
auto srcLayout = StructLayout::create(srcFields);
|
||||
srcLayout.setAscii(src, "truth", "text");
|
||||
srcLayout.setNumber(src, 3.141592, "pi");
|
||||
|
||||
EXPECT_EQ(srcLayout.getChars(src, "text"), "truth");
|
||||
EXPECT_DOUBLE_EQ(srcLayout.getNumber(src, "pi"), 3.141592);
|
||||
|
||||
ubyte dst[32] {};
|
||||
std::vector<Field> dstFields {
|
||||
Field {FieldType::I64, "arr", 2}, // an array of 2 i64
|
||||
Field {FieldType::CHAR, "text", 5},
|
||||
Field {FieldType::F64, "pi", 1},
|
||||
};
|
||||
auto dstLayout = StructLayout::create(dstFields);
|
||||
EXPECT_EQ(srcLayout.checkCompatibility(dstLayout).size(), 0);
|
||||
dstLayout.convert(srcLayout, src, dst, false);
|
||||
|
||||
EXPECT_EQ(dstLayout.getChars(dst, "text"), "truth");
|
||||
EXPECT_DOUBLE_EQ(dstLayout.getNumber(dst, "pi"), 3.141592);
|
||||
}
|
||||
|
||||
TEST(StructLayout, ConvertWithLoss) {
|
||||
ubyte src[32] {};
|
||||
std::vector<Field> srcFields {
|
||||
Field {FieldType::CHAR, "text", 5},
|
||||
Field {FieldType::I16, "someint", 1},
|
||||
Field {FieldType::F64, "pi", 1},
|
||||
};
|
||||
auto srcLayout = StructLayout::create(srcFields);
|
||||
srcLayout.setAscii(src, "truth", "text");
|
||||
srcLayout.setInteger(src, 150, "someint");
|
||||
srcLayout.setNumber(src, 3.141592, "pi");
|
||||
|
||||
EXPECT_EQ(srcLayout.getChars(src, "text"), "truth");
|
||||
EXPECT_EQ(srcLayout.getInteger(src, "someint"), 150);
|
||||
EXPECT_DOUBLE_EQ(srcLayout.getNumber(src, "pi"), 3.141592);
|
||||
|
||||
ubyte dst[8] {};
|
||||
std::vector<Field> dstFields {
|
||||
Field {FieldType::CHAR, "text", 3},
|
||||
Field {FieldType::I8, "someint", 1, FieldConvertStrategy::CLAMP},
|
||||
};
|
||||
auto dstLayout = StructLayout::create(dstFields);
|
||||
auto report = srcLayout.checkCompatibility(dstLayout);
|
||||
|
||||
// check report
|
||||
std::sort(report.begin(), report.end(), [](const auto& a, const auto& b) {
|
||||
return a.name < b.name;
|
||||
});
|
||||
EXPECT_EQ(report.size(), 3);
|
||||
|
||||
EXPECT_EQ(report[0].name, "pi");
|
||||
EXPECT_EQ(report[0].type, FieldIncapatibilityType::MISSING);
|
||||
|
||||
EXPECT_EQ(report[1].name, "someint");
|
||||
EXPECT_EQ(report[1].type, FieldIncapatibilityType::DATA_LOSS);
|
||||
|
||||
EXPECT_EQ(report[2].name, "text");
|
||||
EXPECT_EQ(report[2].type, FieldIncapatibilityType::DATA_LOSS);
|
||||
|
||||
// convert with losses
|
||||
dstLayout.convert(srcLayout, src, dst, true);
|
||||
|
||||
EXPECT_EQ(dstLayout.getChars(dst, "text"), "tru");
|
||||
EXPECT_EQ(dstLayout.getInteger(dst, "someint"), INT8_MAX);
|
||||
}
|
||||
|
||||
TEST(StructLayout, Serialization) {
|
||||
std::vector<Field> fields {
|
||||
Field (FieldType::CHAR, "text", 5),
|
||||
Field (FieldType::I16, "someint", 1),
|
||||
Field (FieldType::F64, "pi", 1),
|
||||
};
|
||||
auto layout1 = StructLayout::create(fields);
|
||||
auto serialized = layout1.serialize();
|
||||
|
||||
std::cout << serialized << std::endl;
|
||||
|
||||
StructLayout layout2;
|
||||
layout2.deserialize(serialized);
|
||||
|
||||
EXPECT_EQ(layout1, layout2);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "util/SmallHeap.hpp"
|
||||
|
||||
using namespace util;
|
||||
|
||||
TEST(SmallHeap, Allocation) {
|
||||
auto index = 0;
|
||||
auto size = 4;
|
||||
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
auto ptr = map.allocate(index, size);
|
||||
EXPECT_EQ(map.sizeOf(ptr), size);
|
||||
EXPECT_EQ(ptr, map.find(index));
|
||||
}
|
||||
|
||||
TEST(SmallHeap, MultipleAllocation) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
map.allocate(32, 4);
|
||||
map.allocate(1, 5);
|
||||
EXPECT_EQ(map.sizeOf(map.find(32)), 4);
|
||||
EXPECT_EQ(map.sizeOf(map.find(1)), 5);
|
||||
}
|
||||
|
||||
TEST(SmallHeap, Free) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
map.free(map.allocate(5, 4));
|
||||
EXPECT_EQ(map.find(5), nullptr);
|
||||
}
|
||||
|
||||
TEST(SmallHeap, ReAllocationSame) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
auto ptr1 = map.allocate(1, 2);
|
||||
auto ptr2 = map.allocate(1, 2);
|
||||
EXPECT_EQ(ptr1, ptr2);
|
||||
}
|
||||
|
||||
TEST(SmallHeap, ReAllocationDifferent) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
map.allocate(1, 34);
|
||||
map.allocate(1, 2);
|
||||
EXPECT_EQ(map.sizeOf(map.find(1)), 2);
|
||||
}
|
||||
|
||||
TEST(SmallHeap, RandomFill) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
int n = 3'000;
|
||||
map.allocate(n, 123);
|
||||
for (int i = 0; i < n; i++) {
|
||||
int index = rand() % n;
|
||||
int size = rand() % 254 + 1;
|
||||
map.allocate(index, size);
|
||||
}
|
||||
EXPECT_EQ(map.sizeOf(map.find(n)), 123);
|
||||
}
|
||||
|
||||
TEST(SmallHeap, EncodeDecode) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
int n = 3'000;
|
||||
map.allocate(n, 123);
|
||||
for (int i = 0; i < n; i++) {
|
||||
int index = rand() % n;
|
||||
int size = rand() % 254 + 1;
|
||||
map.allocate(index, size);
|
||||
}
|
||||
auto bytes = map.serialize();
|
||||
|
||||
SmallHeap<uint16_t, uint8_t> out;
|
||||
out.deserialize(bytes.data(), bytes.size());
|
||||
EXPECT_EQ(map, out);
|
||||
}
|
||||
|
||||
TEST(SmallHeap, Iterator) {
|
||||
SmallHeap<uint16_t, uint8_t> map;
|
||||
map.allocate(1, 10);
|
||||
map.allocate(2, 20);
|
||||
map.allocate(4, 14);
|
||||
|
||||
int sum = 0;
|
||||
for (const auto& it : map) {
|
||||
sum += it.size();
|
||||
}
|
||||
EXPECT_EQ(sum, 44);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "voxels/Chunk.hpp"
|
||||
|
||||
TEST(Chunk, EncodeDecode) {
|
||||
Chunk chunk1(0, 0);
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
chunk1.voxels[i].id = rand();
|
||||
chunk1.voxels[i].state.rotation = rand();
|
||||
chunk1.voxels[i].state.segment = rand();
|
||||
chunk1.voxels[i].state.userbits = rand();
|
||||
}
|
||||
auto bytes = chunk1.encode();
|
||||
|
||||
Chunk chunk2(0, 0);
|
||||
chunk2.decode(bytes.get());
|
||||
|
||||
for (uint i = 0; i < CHUNK_VOL; i++) {
|
||||
EXPECT_EQ(chunk1.voxels[i].id, chunk2.voxels[i].id);
|
||||
EXPECT_EQ(
|
||||
blockstate2int(chunk1.voxels[i].state),
|
||||
blockstate2int(chunk2.voxels[i].state)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user