mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2026-01-08 12:00:16 -06:00
Specifically:
* Extend tables so that they won't wrap around wrongly for big sizes
(we would never hit this since our blocks are at most a few MBs
big).
* Use CRC instructions to compute remainders.
109 lines
3.2 KiB
C++
109 lines
3.2 KiB
C++
// Copyright 2025 XTX Markets Technologies Limited
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <vector>
|
|
#include <immintrin.h>
|
|
|
|
#include "crc32c.h"
|
|
#include "Random.hpp"
|
|
|
|
#define ASSERT(expr) do { \
|
|
if (!(expr)) { \
|
|
fprintf(stderr, "Assertion failed: " #expr "\n"); \
|
|
exit(1); \
|
|
} \
|
|
} while (false)
|
|
|
|
#define BOTH(f, ...) ({ \
|
|
auto x1 = f(__VA_ARGS__); \
|
|
auto x2 = f##_pclmul(__VA_ARGS__); \
|
|
ASSERT(x1 == x2); \
|
|
x1; \
|
|
})
|
|
|
|
int main() {
|
|
uint32_t expectedCrc = 0x6c0ec068u;
|
|
const char* str = "bazzer\n";
|
|
ASSERT(expectedCrc == BOTH(crc32c, 0, str, strlen(str)));
|
|
|
|
RandomGenerator rand(0);
|
|
|
|
const auto randString = [&rand](size_t l) -> std::vector<char> {
|
|
std::vector<char> s(l, 0);
|
|
rand.generateBytes(s.data(), s.size());
|
|
return s;
|
|
};
|
|
|
|
// Test append
|
|
for (int i = 0; i < 1000; i++) {
|
|
auto s1 = randString(1 + rand.generate64()%100);
|
|
uint32_t crc1 = BOTH(crc32c, 0, s1.data(), s1.size());
|
|
ASSERT(crc1 == BOTH(crc32c_append, 0, crc1, s1.size()));
|
|
auto s2 = randString(1 + rand.generate64()%100);
|
|
uint32_t crc2 = BOTH(crc32c, 0, s2.data(), s2.size());
|
|
std::vector<char> s = s1;
|
|
s.insert(s.end(), s2.begin(), s2.end());
|
|
uint32_t crc = BOTH(crc32c, 0, s.data(), s.size());
|
|
ASSERT(crc == BOTH(crc32c_append, crc1, crc2, s2.size()));
|
|
}
|
|
|
|
// Test XOR
|
|
for (int i = 0; i < 1000; i++) {
|
|
size_t l = 1 + rand.generate64()%100;
|
|
auto s1 = randString(l);
|
|
uint32_t crc1 = BOTH(crc32c, 0, s1.data(), s1.size());
|
|
auto s2 = randString(l);
|
|
uint32_t crc2 = BOTH(crc32c, 0, s2.data(), s2.size());
|
|
std::vector<char> s = s1;
|
|
for (int i = 0; i < l; i++) {
|
|
s[i] ^= s2[i];
|
|
}
|
|
uint32_t crc = BOTH(crc32c, 0, s.data(), s.size());
|
|
ASSERT(crc == BOTH(crc32c_xor, crc1, crc2, l));
|
|
}
|
|
|
|
// Test zero extend
|
|
for (int i = 0; i < 100; i++) {
|
|
size_t l = 1 + rand.generate64()%100;
|
|
size_t lzeros = rand.generate64()%100;
|
|
auto s = randString(l);
|
|
std::vector<char> szeros(l + lzeros, 0);
|
|
memcpy(&szeros[0], s.data(), l);
|
|
uint32_t crc = BOTH(crc32c, 0, s.data(), l);
|
|
ASSERT(
|
|
BOTH(crc32c_zero_extend, crc, lzeros) ==
|
|
BOTH(crc32c, 0, szeros.data(), szeros.size())
|
|
);
|
|
}
|
|
|
|
// Test zero contract
|
|
for (int i = 0; i < 100; i++) {
|
|
size_t l = 1 + rand.generate64()%100;
|
|
ssize_t lzeros = rand.generate64()%100;
|
|
auto s = randString(l);
|
|
std::vector<char> szeros(l + lzeros, 0);
|
|
memcpy(&szeros[0], s.data(), l);
|
|
uint32_t crc = BOTH(crc32c, 0, szeros.data(), szeros.size());
|
|
ASSERT(
|
|
BOTH(crc32c_zero_extend, crc, -lzeros) ==
|
|
BOTH(crc32c, 0, s.data(), s.size())
|
|
);
|
|
}
|
|
|
|
for (int i = 0; i < 100; i++) {
|
|
size_t l = 1 + rand.generate64()%100;
|
|
auto s = randString(l);
|
|
ASSERT(
|
|
BOTH(crc32c, 0, s.data(), s.size()) ==
|
|
BOTH(crc32c, crc32c(0, s.data(), s.size()), "", 0)
|
|
);
|
|
}
|
|
|
|
printf("All tests pass.\n");
|
|
|
|
return 0;
|
|
}
|