ClickHouse/src/Common/tests/compact_array.cpp
2020-04-03 18:14:31 +03:00

268 lines
8.3 KiB
C++

/// Bug in GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
#if !__clang__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
#include <Common/CompactArray.h>
#include <IO/WriteBufferFromFile.h>
#include <IO/ReadBufferFromFile.h>
#include <filesystem>
#include <string>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <cstdlib>
#include <unistd.h>
namespace fs = std::filesystem;
static std::string createTmpPath(const std::string & filename)
{
char pattern[] = "/tmp/fileXXXXXX";
char * dir = mkdtemp(pattern);
if (dir == nullptr)
throw std::runtime_error("Could not create directory");
return std::string(dir) + "/" + filename;
}
template <size_t width, size_t bucket_count, typename Generator>
struct Test
{
static void perform()
{
bool ok = true;
std::string filename;
try
{
using Store = DB::CompactArray<UInt64, width, bucket_count>;
Store store;
for (size_t i = 0; i < bucket_count; ++i)
store[i] = Generator::execute(i, width);
filename = createTmpPath("compact_array.bin");
{
DB::WriteBufferFromFile wb(filename);
wb.write(reinterpret_cast<const char *>(&store), sizeof(store));
}
{
DB::ReadBufferFromFile rb(filename);
typename Store::Reader reader(rb);
while (reader.next())
{
const auto & data = reader.get();
if (data.second != store[data.first])
throw std::runtime_error("Found discrepancy");
}
}
}
catch (const Poco::Exception & ex)
{
std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " failed "
<< "(Error: " << ex.what() << ": " << ex.displayText() << ")\n";
ok = false;
}
catch (const std::runtime_error & ex)
{
std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " failed "
<< "(Error: " << ex.what() << ")\n";
ok = false;
}
catch (...)
{
std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " failed\n";
ok = false;
}
fs::remove_all(fs::path(filename).parent_path().string());
if (ok)
std::cout << "Test width=" << width << " bucket_count=" << bucket_count << " passed\n";
}
};
template <typename Generator>
struct TestSet
{
static void execute()
{
Test<1, 1, Generator>::perform();
Test<1, 2, Generator>::perform();
Test<1, 3, Generator>::perform();
Test<1, 4, Generator>::perform();
Test<1, 5, Generator>::perform();
Test<1, 6, Generator>::perform();
Test<1, 7, Generator>::perform();
Test<1, 8, Generator>::perform();
Test<1, 9, Generator>::perform();
Test<1, 10, Generator>::perform();
Test<1, 16, Generator>::perform();
Test<1, 32, Generator>::perform();
Test<1, 64, Generator>::perform();
Test<1, 128, Generator>::perform();
Test<1, 256, Generator>::perform();
Test<1, 512, Generator>::perform();
Test<1, 1024, Generator>::perform();
Test<2, 1, Generator>::perform();
Test<2, 2, Generator>::perform();
Test<2, 3, Generator>::perform();
Test<2, 4, Generator>::perform();
Test<2, 5, Generator>::perform();
Test<2, 6, Generator>::perform();
Test<2, 7, Generator>::perform();
Test<2, 8, Generator>::perform();
Test<2, 9, Generator>::perform();
Test<2, 10, Generator>::perform();
Test<2, 16, Generator>::perform();
Test<2, 32, Generator>::perform();
Test<2, 64, Generator>::perform();
Test<2, 128, Generator>::perform();
Test<2, 256, Generator>::perform();
Test<2, 512, Generator>::perform();
Test<2, 1024, Generator>::perform();
Test<3, 1, Generator>::perform();
Test<3, 2, Generator>::perform();
Test<3, 3, Generator>::perform();
Test<3, 4, Generator>::perform();
Test<3, 5, Generator>::perform();
Test<3, 6, Generator>::perform();
Test<3, 7, Generator>::perform();
Test<3, 8, Generator>::perform();
Test<3, 9, Generator>::perform();
Test<3, 10, Generator>::perform();
Test<3, 16, Generator>::perform();
Test<3, 32, Generator>::perform();
Test<3, 64, Generator>::perform();
Test<3, 128, Generator>::perform();
Test<3, 256, Generator>::perform();
Test<3, 512, Generator>::perform();
Test<3, 1024, Generator>::perform();
Test<4, 1, Generator>::perform();
Test<4, 2, Generator>::perform();
Test<4, 3, Generator>::perform();
Test<4, 4, Generator>::perform();
Test<4, 5, Generator>::perform();
Test<4, 6, Generator>::perform();
Test<4, 7, Generator>::perform();
Test<4, 8, Generator>::perform();
Test<4, 9, Generator>::perform();
Test<4, 10, Generator>::perform();
Test<4, 16, Generator>::perform();
Test<4, 32, Generator>::perform();
Test<4, 64, Generator>::perform();
Test<4, 128, Generator>::perform();
Test<4, 256, Generator>::perform();
Test<4, 512, Generator>::perform();
Test<4, 1024, Generator>::perform();
Test<5, 1, Generator>::perform();
Test<5, 2, Generator>::perform();
Test<5, 3, Generator>::perform();
Test<5, 4, Generator>::perform();
Test<5, 5, Generator>::perform();
Test<5, 6, Generator>::perform();
Test<5, 7, Generator>::perform();
Test<5, 8, Generator>::perform();
Test<5, 9, Generator>::perform();
Test<5, 10, Generator>::perform();
Test<5, 16, Generator>::perform();
Test<5, 32, Generator>::perform();
Test<5, 64, Generator>::perform();
Test<5, 128, Generator>::perform();
Test<5, 256, Generator>::perform();
Test<5, 512, Generator>::perform();
Test<5, 1024, Generator>::perform();
Test<6, 1, Generator>::perform();
Test<6, 2, Generator>::perform();
Test<6, 3, Generator>::perform();
Test<6, 4, Generator>::perform();
Test<6, 5, Generator>::perform();
Test<6, 6, Generator>::perform();
Test<6, 7, Generator>::perform();
Test<6, 8, Generator>::perform();
Test<6, 9, Generator>::perform();
Test<6, 10, Generator>::perform();
Test<6, 16, Generator>::perform();
Test<6, 32, Generator>::perform();
Test<6, 64, Generator>::perform();
Test<6, 128, Generator>::perform();
Test<6, 256, Generator>::perform();
Test<6, 512, Generator>::perform();
Test<6, 1024, Generator>::perform();
Test<7, 1, Generator>::perform();
Test<7, 2, Generator>::perform();
Test<7, 3, Generator>::perform();
Test<7, 4, Generator>::perform();
Test<7, 5, Generator>::perform();
Test<7, 6, Generator>::perform();
Test<7, 7, Generator>::perform();
Test<7, 8, Generator>::perform();
Test<7, 9, Generator>::perform();
Test<7, 10, Generator>::perform();
Test<7, 16, Generator>::perform();
Test<7, 32, Generator>::perform();
Test<7, 64, Generator>::perform();
Test<7, 128, Generator>::perform();
Test<7, 256, Generator>::perform();
Test<7, 512, Generator>::perform();
Test<7, 1024, Generator>::perform();
}
};
struct Generator1
{
static UInt8 execute(size_t, size_t width)
{
return (1 << width) - 1;
}
};
struct Generator2
{
static UInt8 execute(size_t i, size_t width)
{
return (i >> 1) & ((1 << width) - 1);
}
};
struct Generator3
{
static UInt8 execute(size_t i, size_t width)
{
return (i * 17 + 31) % (1ULL << width);
}
};
static void runTests()
{
std::cout << "Test set 1\n";
TestSet<Generator1>::execute();
std::cout << "Test set 2\n";
TestSet<Generator2>::execute();
std::cout << "Test set 3\n";
TestSet<Generator3>::execute();
}
int main()
{
runTests();
return 0;
}
#if !__clang__
#pragma GCC diagnostic pop
#endif