Skip to content

Commit

Permalink
!WIP serialize testing
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc committed Dec 28, 2023
1 parent 7896f11 commit aa740e3
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 45 deletions.
5 changes: 3 additions & 2 deletions libnixt/include/nixt/SerializeSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ std::size_t write(std::ostream &OS, const T &Data) {
/// while construction.
class StringTable {
public:
friend std::size_t write(std::ostream &OS, StringTable &Self,
std::string Str);
std::size_t write(std::string Str);
std::string_view view() { return OS.view(); }

private:
std::map<std::string, std::size_t> Map;
std::ostringstream OS;

static std::size_t write(std::ostream &OS, const std::string &Data);

Expand Down
8 changes: 4 additions & 4 deletions libnixt/lib/Serialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ class SerializeVisitor : public RecursiveASTVisitor<SerializeVisitor> {
write(OS, Pos.origin.index());
if (std::get_if<nix::SourcePath>(&Pos.origin)) {
std::string Path = std::get<nix::SourcePath>(Pos.origin).to_string();
write(OS, ST, std::move(Path));
write(OS, ST.write(std::move(Path)));
}
return Ret;
}

std::size_t writeSymbol(const nix::Symbol &S) {
return write(OS, ST, STable[S]);
return write(OS, ST.write(STable[S]));
}

std::size_t writeAttrName(const nix::AttrName &AN) {
Expand Down Expand Up @@ -112,14 +112,14 @@ class SerializeVisitor : public RecursiveASTVisitor<SerializeVisitor> {
bool visitExprString(const nix::ExprString *E) {
assert(E);
ExprMap[E] = write(OS, ExprKind::ExprString);
write(OS, ST, E->s);
write(OS, ST.write(E->s));
return true;
}

bool visitExprPath(const nix::ExprPath *E) {
assert(E);
ExprMap[E] = write(OS, ExprKind::ExprPath);
write(OS, ST, E->s);
write(OS, ST.write(E->s));
return true;
}

Expand Down
8 changes: 4 additions & 4 deletions libnixt/lib/SerializeSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ std::size_t StringTable::write(std::ostream &OS,
return write(OS, Data.str());
}

std::size_t write(std::ostream &OS, StringTable &Self, std::string Str) {
if (Self.Map.contains(Str)) {
return Self.Map[std::move(Str)];
std::size_t StringTable::write(std::string Str) {
if (Map.contains(Str)) {
return Map[std::move(Str)];
}
std::size_t Ret = Self.Map[Str] = OS.tellp();
std::size_t Ret = Map[Str] = OS.tellp();
StringTable::write(OS, Str);
return Ret;
}
Expand Down
119 changes: 101 additions & 18 deletions libnixt/test/Serialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
#include <nix/nixexpr.hh>

#include <bit>
#include <string_view>

using namespace nixt::serialize;
using namespace std::literals;

static_assert(std::endian::native == std::endian::little);

Expand All @@ -21,27 +23,59 @@ class SerializeTest : public testing::Test {
nixt::serialize::write(OS, ST, PT, E);
return OS.str();
}
nix::PosIdx somePos() {
nix::Pos::Origin O = nix::Pos::none_tag{};
return PT.add(O, 32, 32);
}
nix::AttrName someAttrName() { return {ST.create("hello")}; }
};

void checkASTHeader(const ASTHeader &H) {
EXPECT_EQ(std::memcmp(H.Magic, "\x7FNixAST\0", 8), 0);
EXPECT_EQ(H.Version, 1);
std::unique_ptr<nix::ExprInt> mkInt() {
return std::make_unique<nix::ExprInt>(0xdeadbeef);
}

void checkASTHeader(const char *Raw) {
std::size_t checkASTHeader(std::string_view Str) {
ASTHeader Header;
std::memcpy(&Header, Raw, sizeof(ASTHeader));
checkASTHeader(Header);
assert(Str.size() >= sizeof(ASTHeader));
std::memcpy(&Header, Str.begin(), sizeof(ASTHeader));
EXPECT_EQ(std::memcmp(Header.Magic, "\x7FNixAST\0", 8), 0);
EXPECT_EQ(Header.Version, 1);
return sizeof(ASTHeader);
}

void check(std::string_view Str, std::string_view Expected) {
checkASTHeader(Str.substr(0, sizeof(ASTHeader)));
EXPECT_EQ(Str.substr(sizeof(ASTHeader)), Expected);
}

std::size_t checkKind(std::string_view Str, ExprKind Expected) {
ExprKind LHS;
assert(Str.size() >= sizeof(ExprKind));
std::memcpy(&LHS, Str.begin(), sizeof(ExprKind));
EXPECT_EQ(LHS, Expected);
return sizeof(ExprKind);
}

std::size_t checkSomeInt(std::string_view Str) {
std::string_view Expected = "\x6\0\0\0\xEF\xBE\xAD\xDE\0\0\0\0"sv;
assert(Str.size() >= Expected.size());
EXPECT_EQ(Str.substr(0, Expected.size()), Expected);
return Expected.size();
}

std::size_t checkSomePos(std::string_view Str) {
std::string_view Expected = "\x20\0\0\0" // E->pos, column
"\x20\0\0\0" // E->pos, column
"\0\0\0\0\0\0\0\0"sv; // origin.index() == 0
assert(Str.size() >= Expected.size());
EXPECT_EQ(Str.substr(0, Expected.size()), Expected);
return Expected.size();
}

TEST_F(SerializeTest, ExprInt) {
nix::ExprInt E(0x2adeadbeef);
std::string Result = write(&E);
const char Expected[] = "\x6\0\0\0\xEF\xBE\xAD\xDE\x2A\0\0";
checkASTHeader(Result.c_str());
auto Content = std::string_view(Result).substr(sizeof(ASTHeader));
EXPECT_TRUE(std::memcmp(Expected, Content.begin(), sizeof(Expected)) == 0);
EXPECT_EQ(Content.size(), sizeof(Expected));
std::string_view Expected = "\x6\0\0\0\xEF\xBE\xAD\xDE\x2A\0\0\0"sv;
check(write(&E), Expected);
}

TEST_F(SerializeTest, ExprFloat) {
Expand All @@ -52,12 +86,61 @@ TEST_F(SerializeTest, ExprFloat) {
Data.U = 0x2adeadbeef;

nix::ExprFloat E(Data.D);
std::string Result = write(&E);
const char Expected[] = "\x4\0\0\0\xEF\xBE\xAD\xDE\x2A\0\0";
checkASTHeader(Result.c_str());
auto Content = std::string_view(Result).substr(sizeof(ASTHeader));
EXPECT_TRUE(std::memcmp(Expected, Content.begin(), sizeof(Expected)) == 0);
EXPECT_EQ(Content.size(), sizeof(Expected));
std::string_view Expected = "\x4\0\0\0\xEF\xBE\xAD\xDE\x2A\0\0\0"sv;
check(write(&E), Expected);
}

TEST_F(SerializeTest, ExprString) {
nix::ExprString E("Hello World");
std::string_view Expected = "\x16\0\0\0"
"\0\0\0\0\0\0\0\0"sv;
check(write(&E), Expected);
}

TEST_F(SerializeTest, ExprPath) {
nix::ExprPath E("Hello World");
std::string_view Expected = "\x13\0\0\0"
"\0\0\0\0\0\0\0\0"sv;
check(write(&E), Expected);
}

TEST_F(SerializeTest, ExprVar) {
nix::Symbol S = ST.create("hello");
nix::ExprVar E(somePos(), S);
E.fromWith = true;
E.level = 0xdeadbeef;
E.displ = 0xbeef5a5a;
std::string_view Expected =
"\x17\0\0\0" // kind
"\x20\0\0\0" // E->pos, column
"\x20\0\0\0" // E->pos, column
"\0\0\0\0\0\0\0\0" // origin.index() == 0
"\0\0\0\0\0\0\0\0" // E->symbol, 5, length of "hello"
"\x01" // E->fromWidth
"\xEF\xBE\xAD\xDE" // E->level
"\x5A\x5A\xEF\xBE"sv; // E->displ
check(write(&E), Expected);
}

TEST_F(SerializeTest, ExprSelect) {
auto SubE = mkInt();
auto SubDef = mkInt();
nix::AttrPath Path{someAttrName()};
nix::ExprSelect E(somePos(), SubE.get(), std::move(Path), SubDef.get());
std::string Data = write(&E);
std::string_view View = Data;
std::size_t Base = 0;

Base += checkASTHeader(View);
Base += checkSomeInt(View.substr(Base));
Base += checkSomeInt(View.substr(Base));
Base += checkKind(View.substr(Base), ExprKind::ExprSelect);
Base += checkSomePos(View.substr(Base));

std::string_view Expected = "\x0c\0\0\0\0\0\0\0"
"\x18\0\0\0\0\0\0\0"sv;

EXPECT_EQ(View.substr(Base), Expected);
}

} // namespace
37 changes: 20 additions & 17 deletions libnixt/test/SerializeSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,26 @@

#include <bit>

#include <string_view>

using namespace std::literals;

namespace nixt::serialize {

/// These asserts are generated on little-endian machine.

TEST(SerializeSupport, StringTable) {
StringTable ST;
std::ostringstream OS;
static_assert(std::endian::native == std::endian::little);
EXPECT_EQ(write(OS, ST, "Hello"), 0);
EXPECT_EQ(write(OS, ST, "World"), 13);
EXPECT_EQ(write(OS, ST, "Hello"), 0);
EXPECT_EQ(write(OS, ST, "World"), 13);
const char Expected[] = "\x5\0\0\0\0\0\0\0"
"Hello"
"\x5\0\0\0\0\0\0\0"
"World";
EXPECT_TRUE(std::memcmp(Expected, OS.str().c_str(), sizeof(Expected)) == 0);
EXPECT_EQ(ST.write("Hello"), 0);
EXPECT_EQ(ST.write("World"), 13);
EXPECT_EQ(ST.write("Hello"), 0);
EXPECT_EQ(ST.write("World"), 13);
std::string_view Expected = "\x5\0\0\0\0\0\0\0"
"Hello"
"\x5\0\0\0\0\0\0\0"
"World"sv;
EXPECT_EQ(Expected, ST.view());
}

TEST(SerializeSupport, writeMisc) {
Expand All @@ -33,13 +36,13 @@ TEST(SerializeSupport, writeMisc) {
EXPECT_EQ(write(OS, 6.5), 24);

static_assert(std::endian::native == std::endian::little);
const char Expected[] = "\x1\0\0\0"
"\x2\0\0\0"
"\x3\0\0\0"
"\x4\0\0\0"
"\0\0\0\0\0\0\x16\x40"
"\0\0\0\0\0\0\x1A\x40";
EXPECT_TRUE(std::memcmp(Expected, OS.str().c_str(), sizeof(Expected)) == 0);
std::string_view Expected = "\x1\0\0\0"
"\x2\0\0\0"
"\x3\0\0\0"
"\x4\0\0\0"
"\0\0\0\0\0\0\x16\x40"
"\0\0\0\0\0\0\x1A\x40"sv;
EXPECT_EQ(Expected, OS.view());
}

} // namespace nixt::serialize

0 comments on commit aa740e3

Please sign in to comment.