WIP: debugging, first tests, basic test case working

This commit is contained in:
Matthias Koefferlein 2024-08-10 23:22:54 +02:00
parent 64b6512bc1
commit f6da5e11c6
5 changed files with 167 additions and 28 deletions

View File

@ -21,10 +21,14 @@
*/
#include "tlProtocolBuffer.h"
#include "tlLog.h"
namespace tl
{
// @@@
// Missing: readers should check for proper wire type (i.e. read(int64)->either VARINT or I64, not I32
// ----------------------------------------------------------------------------------
ProtocolBufferReader::ProtocolBufferReader (tl::InputStream &input)
@ -284,11 +288,17 @@ ProtocolBufferReader::error (const std::string &msg)
// ----------------------------------------------------------------------------------
ProtocolBufferWriter::ProtocolBufferWriter (tl::OutputStream &stream)
: mp_stream (&stream), m_bytes_counted (0)
: mp_stream (&stream), m_bytes_counted (0), m_debug (false), m_debug_pos (0)
{
// .. nothing yet ..
}
void ProtocolBufferWriter::set_debug (bool f)
{
m_debug = f;
m_debug_pos = 0;
}
void ProtocolBufferWriter::write (int tag, float v)
{
write (tag, *reinterpret_cast<uint32_t *> (&v), true);
@ -303,7 +313,7 @@ void ProtocolBufferWriter::write (int tag, uint32_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I32));
write_varint (pb_varint ((tag << 3) + PB_I32), true);
if (is_counting ()) {
@ -311,19 +321,25 @@ void ProtocolBufferWriter::write (int tag, uint32_t v, bool fixed)
} else {
auto vv = v;
char b[sizeof (v)];
for (unsigned int i = 0; i < sizeof (v); ++i) {
b[sizeof (v) - 1 - i] = (char) v;
v >>= 8;
}
if (m_debug) {
dump (b, sizeof (v), "I32", tl::to_string (vv));
}
mp_stream->put (b, sizeof (v));
}
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT));
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v));
}
@ -346,7 +362,7 @@ void ProtocolBufferWriter::write (int tag, uint64_t v, bool fixed)
{
if (fixed) {
write_varint (pb_varint ((tag << 3) + PB_I64));
write_varint (pb_varint ((tag << 3) + PB_I64), true);
if (is_counting ()) {
@ -354,19 +370,25 @@ void ProtocolBufferWriter::write (int tag, uint64_t v, bool fixed)
} else {
auto vv = v;
char b[sizeof (v)];
for (unsigned int i = 0; i < sizeof (v); ++i) {
b[sizeof (v) - 1 - i] = (char) v;
v >>= 8;
}
if (m_debug) {
dump (b, sizeof (v), "I64", tl::to_string (vv));
}
mp_stream->put (b, sizeof (v));
}
} else {
write_varint (pb_varint ((tag << 3) + PB_VARINT));
write_varint (pb_varint ((tag << 3) + PB_VARINT), true);
write_varint (pb_varint (v));
}
@ -392,13 +414,21 @@ void ProtocolBufferWriter::write (int tag, bool b)
void ProtocolBufferWriter::write (int tag, const std::string &s)
{
write_varint (pb_varint ((tag << 3) + PB_LEN));
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
write_varint (s.size ());
if (is_counting ()) {
m_byte_counter_stack.back () += s.size ();
} else {
if (m_debug) {
dump (s.c_str (), s.size (), "(string)", s);
}
mp_stream->put (s.c_str (), s.size ());
}
}
@ -411,16 +441,15 @@ void ProtocolBufferWriter::begin_seq (int tag, bool counting)
{
if (counting) {
// header only
m_byte_counter_stack.push_back (0);
write_varint (pb_varint ((tag << 3) + PB_LEN));
if (is_counting ()) {
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
}
// body only
m_byte_counter_stack.push_back (0);
} else {
write_varint (pb_varint ((tag << 3) + PB_LEN));
write_varint (pb_varint ((tag << 3) + PB_LEN), true);
write_varint (m_bytes_counted);
}
@ -434,17 +463,15 @@ void ProtocolBufferWriter::end_seq ()
m_byte_counter_stack.pop_back ();
// just for adding the required bytes
write_varint (m_bytes_counted);
// now add header bytes
m_bytes_counted += m_byte_counter_stack.back ();
m_byte_counter_stack.pop_back ();
if (is_counting ()) {
write_varint (m_bytes_counted);
}
}
}
void
ProtocolBufferWriter::write_varint (pb_varint v)
ProtocolBufferWriter::write_varint (pb_varint v, bool id)
{
if (is_counting ()) {
@ -461,6 +488,8 @@ ProtocolBufferWriter::write_varint (pb_varint v)
} else {
auto vv = v;
char b[16];
char *cp = b;
while (true) {
@ -473,9 +502,75 @@ ProtocolBufferWriter::write_varint (pb_varint v)
v >>= 7;
}
if (m_debug) {
if (id) {
unsigned int wt = v & 7;
std::string wire_type;
if (wt == PB_EGROUP) {
wire_type = "EGROUP";
} else if (wt == PB_SGROUP) {
wire_type = "SGROUP";
} else if (wt == PB_VARINT) {
wire_type = "VARINT";
} else if (wt == PB_I32) {
wire_type = "I32";
} else if (wt == PB_I64) {
wire_type = "I64";
} else if (wt == PB_LEN) {
wire_type = "LEN";
}
dump (b, cp - b, "(id)", "#" + tl::to_string (vv >> 3) + " " + wire_type);
} else {
dump (b, cp - b, "VARINT", tl::to_string (vv));
}
}
mp_stream->put (b, cp - b);
}
}
void
ProtocolBufferWriter::dump (const char *cp, size_t n, const std::string &type, const std::string &value)
{
bool first = true;
size_t nn = n;
while (n > 0) {
std::string line;
if (first) {
line += tl::sprintf ("%08ld", m_debug_pos);
} else {
line += " ";
}
line += " ";
for (unsigned int i = 0; i < 8; ++i) {
if (n > 0) {
line += tl::sprintf ("%02x", (unsigned int) ((unsigned char) *cp));
++cp;
--n;
} else {
line += " ";
}
line += " ";
}
if (first) {
line += " ";
line += type;
line += " ";
line += value;
}
tl::info << line;
first = false;
}
m_debug_pos += nn;
}
}

View File

@ -259,12 +259,21 @@ public:
*/
void end_seq ();
/**
* @brief Enables or disables debug mode
* In debug mode, the stream will be dumped in a human readable form
*/
void set_debug (bool f);
private:
void write_varint (pb_varint v);
void write_varint (pb_varint v, bool id = false);
void dump (const char *cp, size_t n, const std::string &type, const std::string &value);
tl::OutputStream *mp_stream;
size_t m_bytes_counted;
std::vector<size_t> m_byte_counter_stack;
bool m_debug;
size_t m_debug_pos;
};
}

View File

@ -68,6 +68,7 @@ PBParser::parse_element (const PBElementBase *parent, tl::ProtocolBufferReader &
} else {
new_element->create (parent, *mp_state);
new_element->parse (this, reader);
new_element->finish (parent, *mp_state);
}
}

View File

@ -604,7 +604,9 @@ public:
virtual void parse (PBParser *parser, tl::ProtocolBufferReader &reader) const
{
reader.open ();
parser->parse_element (this, reader);
reader.close ();
}
virtual void write (const PBElementBase * /*parent*/, tl::ProtocolBufferWriter &writer, PBWriterState &objs) const
@ -660,7 +662,7 @@ private:
}
objs.pop (self_tag);
writer.end_seq ();
if (! writer.is_counting ()) {
if (writer.is_counting ()) {
break;
}
}

View File

@ -155,17 +155,18 @@ struct Child {
struct Root {
long m;
unsigned int mi;
bool b;
std::vector<double> m_subs;
std::vector<int> m_isubs;
std::vector<Child> m_children;
Child m_child;
Root () : m(0), mi(0) { }
Root () : m(0), mi(0), b(false) { }
bool operator== (const Root &x) const { return m == x.m &&
mi == x.mi && m_subs == x.m_subs &&
m_isubs == x.m_isubs && m_children == x.m_children
&& m_child == x.m_child; }
&& m_child == x.m_child && b == x.b; }
int get_mi () const { return mi; }
void set_mi (int i) { mi = i; }
@ -204,23 +205,26 @@ struct Root {
const Child &get_child () const { return m_child; }
};
TEST (100)
TEST (100_BasicStruct)
{
Root root;
tl::PBElementList child_struct =
tl::pb_make_member (&Child::txt, 1) +
tl::pb_make_member (&Child::d, 2) +
tl::pb_make_element (&Child::begin_children, &Child::end_children, &Child::add_child, 3, &child_struct);
tl::PBStruct<Root> structure (
tl::pb_make_member (&Root::begin_subs, &Root::end_subs, &Root::add_sub, 1) +
tl::pb_make_member (&Root::begin_isubs, &Root::end_isubs, &Root::add_isub, 2) +
tl::pb_make_element (&Root::begin_children, &Root::end_children, &Root::add_child, 3,
tl::pb_make_member (&Child::txt, 1) +
tl::pb_make_member (&Child::d, 2)
) +
tl::pb_make_element (&Root::begin_children, &Root::end_children, &Root::add_child, 3, &child_struct) +
tl::pb_make_element (&Root::get_child, &Root::set_child, 4,
tl::pb_make_member (&Child::txt, 1) +
tl::pb_make_member (&Child::d, 2)
) +
tl::pb_make_member (&Root::m, 5) +
tl::pb_make_member (&Root::get_mi, &Root::set_mi, 6)
tl::pb_make_member (&Root::get_mi, &Root::set_mi, 6) +
tl::pb_make_member (&Root::b, 7)
);
root.add_sub (0.5);
@ -228,6 +232,7 @@ TEST (100)
root.add_isub (420000000);
root.m = -1700000;
root.set_mi (21);
root.b = true;
Child c1;
c1.txt = "c1";
@ -265,6 +270,7 @@ TEST (100)
{
tl::OutputStream os (fn);
tl::ProtocolBufferWriter writer (os);
// For development: writer.set_debug (true);
structure.write (writer, root);
}
@ -287,10 +293,11 @@ TEST (100)
EXPECT_EQ (root.m_isubs.size (), size_t (1));
EXPECT_EQ (root.m_isubs [0], 420000000);
EXPECT_EQ (root.m, -1700000);
EXPECT_EQ (root.b, true);
EXPECT_EQ (root.mi, (unsigned int) 21);
EXPECT_EQ (root.m_children.size (), size_t (2));
EXPECT_EQ (root.m_children [0].txt, "c1");
EXPECT_EQ (root.m_children [1].d, 1.0);
EXPECT_EQ (root.m_children [0].d, 1.0);
EXPECT_EQ (root.m_children [1].txt, "c2");
EXPECT_EQ (root.m_children [1].d, 2.0);
EXPECT_EQ (root.m_children [1].end_children () - root.m_children [1].begin_children (), 3);
@ -322,4 +329,29 @@ TEST (100)
EXPECT_EQ (error, "");
EXPECT_EQ (root == rsave, true);
// write empty object
out.clear ();
root = Root ();
{
tl::OutputStream os (out);
tl::ProtocolBufferWriter writer (os);
structure.write (writer, root);
}
// and read again.
try {
error.clear ();
tl::InputMemoryStream s2 (out.data (), out.size ());
tl::InputStream is (s2);
root = Root ();
tl::ProtocolBufferReader reader (is);
structure.parse (reader, root);
} catch (tl::Exception &ex) {
error = ex.msg ();
}
EXPECT_EQ (error, "");
EXPECT_EQ (root == Root (), true);
}