Skip to content

Commit

Permalink
Set simple test for avro
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzicheng1987 committed Nov 24, 2024
1 parent 5ae9984 commit 65b9032
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 65 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ if (REFLECTCPP_AVRO)
list(APPEND REFLECT_CPP_SOURCES
src/reflectcpp_avro.cpp
)
find_package(jansson CONFIG REQUIRED)
if(REFLECTCPP_USE_VCPKG)
target_include_directories(reflectcpp SYSTEM PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include")
if (MSVC)
Expand All @@ -111,6 +112,7 @@ if (REFLECTCPP_AVRO)
target_link_libraries(reflectcpp PRIVATE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib/libavro${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif ()
endif()
target_link_libraries(reflectcpp PRIVATE jansson::jansson)
endif ()

if (REFLECTCPP_BSON)
Expand Down
18 changes: 15 additions & 3 deletions include/rfl/avro/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,30 @@ struct Reader {
if (type == AVRO_DOUBLE) {
double result = 0.0;
const auto err = avro_value_get_double(_var.val_, &result);
if (err) {
return Error("Could not cast to double.");
}
return static_cast<T>(result);
} else if (type == AVRO_INT32) {
int32_t result = 0;
avro_value_get_int(_var.val_, &result);
const auto err = avro_value_get_int(_var.val_, &result);
if (err) {
return Error("Could not cast to int32.");
}
return static_cast<T>(result);
} else if (type == AVRO_INT64) {
int64_t result = 0;
avro_value_get_long(_var.val_, &result);
const auto err = avro_value_get_long(_var.val_, &result);
if (err) {
return Error("Could not cast to int64.");
}
return static_cast<T>(result);
} else if (type == AVRO_FLOAT) {
double result = 0.0;
float result = 0.0;
const auto err = avro_value_get_float(_var.val_, &result);
if (err) {
return Error("Could not cast to float.");
}
return static_cast<T>(result);
}
return rfl::Error(
Expand Down
2 changes: 1 addition & 1 deletion include/rfl/avro/SchemaImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SchemaImpl {
const std::string& json_str() const { return json_str_; }

/// The interface used to create new values.
const avro_value_iface_t* iface() const { return iface_; };
avro_value_iface_t* iface() const { return iface_; };

private:
/// The JSON string used to create the schema.
Expand Down
19 changes: 10 additions & 9 deletions include/rfl/avro/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../internal/wrap_in_rfl_array_t.hpp"
#include "Parser.hpp"
#include "Reader.hpp"
#include "Schema.hpp"

namespace rfl::avro {

Expand All @@ -26,20 +27,20 @@ auto read(const InputVarType& _obj) {

/// Parses an object from AVRO using reflection.
template <class T, class... Ps>
Result<internal::wrap_in_rfl_array_t<T>> read(const char* _bytes,
const size_t _size) {
AvroParser parser;
InputVarType doc;
avro_parser_init(std::bit_cast<const uint8_t*>(_bytes), _size, 0, &parser,
&doc.val_);
auto result = read<T, Ps...>(doc);
Result<internal::wrap_in_rfl_array_t<T>> read(
const char* _bytes, const size_t _size, const Schema<T>& _schema) noexcept {
avro_reader_t avro_reader = avro_reader_memory(_bytes, _size);
avro_value_t root;
avro_generic_value_new(_schema.iface(), &root);
auto result = read<T, Ps...>(InputVarType{&root});
avro_reader_free(avro_reader);
return result;
}

/// Parses an object from AVRO using reflection.
template <class T, class... Ps>
auto read(const std::vector<char>& _bytes, const auto& _schema) {
return read<T, Ps...>(_bytes.data(), _bytes.size());
auto read(const std::vector<char>& _bytes, const Schema<T>& _schema) {
return read<T, Ps...>(_bytes.data(), _bytes.size(), _schema);
}

/// Parses an object from a stream.
Expand Down
13 changes: 8 additions & 5 deletions include/rfl/avro/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,30 @@
#include "../parsing/Parent.hpp"
#include "Parser.hpp"
#include "Schema.hpp"
#include "Writer.hpp"

namespace rfl::avro {

/// Returns AVRO bytes.
template <class... Ps>
std::vector<char> write(const auto& _obj, const auto& _schema) noexcept {
static_assert(std::is_same<std::remove_cvref_t<decltype(_obj)>,
typename decltype(_schema)::Type>(),
using T = std::remove_cvref_t<decltype(_obj)>;
using U = typename std::remove_cvref_t<decltype(_schema)>::Type;
using ParentType = parsing::Parent<Writer>;
static_assert(std::is_same<T, U>(),
"The schema must be compatible with the type to write.");
std::vector<char> buffer(4096);
avro_value_t root;
avro_generic_value_new(_schema.iface(), &root);
const auto writer = Writer(&root);
Parser<T, Processors<Ps...>>::write(writer, _obj,
typename ParentType::Root{});
avro_writer_t avro_writer;
avro_writer_memory(buffer.data(), buffer.size());
avro_writer_t avro_writer = avro_writer_memory(buffer.data(), buffer.size());
// TODO: Handle cases in which the buffer isn't large enough.
avro_value_write(avro_writer, &root);
const auto len = avro_writer_tell(writer);
const auto len = avro_writer_tell(avro_writer);
avro_value_decref(&root);
avro_writer_free(avro_writer);
buffer.resize(len);
return buffer;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O2")
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std:c++20")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -ggdb -ftemplate-backtrace-limit=0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -ggdb -ftemplate-backtrace-limit=0")
endif()

if (REFLECTCPP_JSON)
Expand Down
46 changes: 0 additions & 46 deletions tests/avro/test_readme_example.cpp

This file was deleted.

46 changes: 46 additions & 0 deletions tests/avro/test_tutorial_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <gtest/gtest.h>

#include <iostream>
#include <rfl.hpp>
#include <rfl/avro.hpp>
#include <string>
#include <vector>

#include "write_and_read.hpp"

/// The basic example from the Avro C tutorial.
namespace test_tutorial_example {

const char PERSON_SCHEMA[] =
"{\"type\":\"record\",\
\"name\":\"Person\",\
\"fields\":[\
{\"name\": \"ID\", \"type\": \"long\"},\
{\"name\": \"First\", \"type\": \"string\"},\
{\"name\": \"Last\", \"type\": \"string\"},\
{\"name\": \"Phone\", \"type\": \"string\"},\
{\"name\": \"Age\", \"type\": \"int\"}]}";

struct Person {
size_t ID;
std::string First;
std::string Last;
std::string Phone;
int Age;
};

TEST(avro, test_tutorial_example) {
const auto person = Person{.ID = 1,
.First = "Randal",
.Last = "Graves",
.Phone = "(555) 123-5678",
.Age = 30};
const auto schema = rfl::avro::Schema<Person>::from_json(PERSON_SCHEMA);
const auto serialized1 = rfl::avro::write(person, schema.value());
const auto res = rfl::avro::read<Person>(serialized1, schema.value());
EXPECT_TRUE(res && true) << "Test failed on read. Error: "
<< res.error().value().what();
const auto serialized2 = rfl::avro::write(res.value(), schema.value());
EXPECT_EQ(serialized1, serialized2);
}
} // namespace test_tutorial_example

0 comments on commit 65b9032

Please sign in to comment.