Added tests for postgres

This commit is contained in:
Dr. Patrick Urbanke
2025-05-15 16:56:07 +02:00
parent ce12604870
commit 1d11e1cb14
20 changed files with 562 additions and 147 deletions
+2
View File
@@ -8,6 +8,8 @@ option(SQLGEN_SQLITE3 "Enable SQLite3 support" ON) # enabled by default
option(SQLGEN_BUILD_TESTS "Build tests" OFF)
option(SQLGEN_BUILD_DRY_TESTS_ONLY "Build 'dry' tests only (those that do not require a database connection)" OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
+1 -1
View File
@@ -225,7 +225,7 @@ std::string insert_to_sql(const dynamic::Insert& _stmt) noexcept {
", ",
internal::collect::vector(_stmt.columns | transform(wrap_in_quotes)));
return "COPY " + schema + "." + table + "(" + colnames +
") FROM STDIN WITH DELIMITER '\t' NULL '\e' QUOTE '\a';";
") FROM STDIN WITH DELIMITER '\t' NULL '\e' CSV QUOTE '\a';";
}
std::string select_from_to_sql(const dynamic::SelectFrom& _stmt) noexcept {
+3 -18
View File
@@ -1,27 +1,12 @@
project(sqlgen-tests)
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "*.cpp")
add_executable(
sqlgen-tests
${SOURCES}
)
target_precompile_headers(sqlgen-tests PRIVATE [["sqlgen.hpp"]] <iostream> <string> <functional> <gtest/gtest.h>)
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std:c++20")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -Wall -Werror -ggdb -fconcepts-diagnostics-depth=5")
endif()
target_link_libraries(
sqlgen-tests
PRIVATE
"${SQLGEN_GTEST_LIB}"
)
find_package(GTest)
gtest_discover_tests(sqlgen-tests)
if (SQLGEN_BUILD_DRY_TESTS_ONLY)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSQLGEN_BUILD_DRY_TESTS_ONLY")
endif()
if(SQLGEN_POSTGRES)
add_subdirectory(postgres)
+59
View File
@@ -0,0 +1,59 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_delete_from {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_delete_from) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0},
Person{
.id = 4, .first_name = "Hugo", .last_name = "Simpson", .age = 10}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
sqlgen::write(conn, people1).value();
const auto delete_hugo =
delete_from<Person> | where("first_name"_c == "Hugo");
const auto people2 =
conn.and_then(delete_hugo)
.and_then(sqlgen::read<std::vector<Person>> | order_by("id"_c))
.value();
const std::string expected =
R"([{"id":0,"first_name":"Homer","last_name":"Simpson","age":45},{"id":1,"first_name":"Bart","last_name":"Simpson","age":10},{"id":2,"first_name":"Lisa","last_name":"Simpson","age":8},{"id":3,"first_name":"Maggie","last_name":"Simpson","age":0}])";
EXPECT_EQ(rfl::json::write(people2), expected);
}
} // namespace test_delete_from
#endif
+1 -1
View File
@@ -17,7 +17,7 @@ TEST(postgres, test_insert_dry) {
const auto expected =
"COPY \"public\".\"TestTable\"(\"field1\", \"field2\", \"id\", "
"\"nullable\") FROM STDIN WITH DELIMITER '\t' NULL '\e' QUOTE '\a';";
"\"nullable\") FROM STDIN WITH DELIMITER '\t' NULL '\e' CSV QUOTE '\a';";
EXPECT_EQ(sqlgen::postgres::to_sql(query), expected);
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_limit {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_limit) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0},
Person{
.id = 4, .first_name = "Hugo", .last_name = "Simpson", .age = 10}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
sqlgen::write(conn, people1).value();
const auto query =
sqlgen::read<std::vector<Person>> | order_by("age"_c) | limit(2);
const auto people2 = query(conn).value();
const std::string expected =
R"([{"id":3,"first_name":"Maggie","last_name":"Simpson","age":0},{"id":2,"first_name":"Lisa","last_name":"Simpson","age":8}])";
EXPECT_EQ(rfl::json::write(people2), expected);
}
} // namespace test_limit
#endif
+63
View File
@@ -0,0 +1,63 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <ranges>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_range {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_range) {
static_assert(std::ranges::input_range<sqlgen::Range<Person>>,
"Must be an input range.");
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
const auto people2 =
sqlgen::write(conn, people1)
.and_then(sqlgen::read<sqlgen::Range<Person>> | order_by("id"_c))
.value();
using namespace std::ranges::views;
const auto first_names =
internal::collect::vector(people2 | transform([](const auto& _r) {
return _r.value().first_name;
}));
EXPECT_EQ(first_names.at(0), "Homer");
EXPECT_EQ(first_names.at(1), "Bart");
EXPECT_EQ(first_names.at(2), "Lisa");
EXPECT_EQ(first_names.at(3), "Maggie");
}
} // namespace test_range
#endif
+47
View File
@@ -0,0 +1,47 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
namespace test_timestamp {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
sqlgen::Timestamp<"%Y-%m-%d %H:%M:%S"> ts;
};
TEST(postgres, test_timestamp) {
const auto people1 =
std::vector<Person>({Person{.id = 0,
.first_name = "Homer",
.last_name = "Simpson",
.ts = "2000-01-01 01:00:00"}});
using namespace sqlgen;
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
const auto people2 = sqlgen::write(conn, people1)
.and_then(sqlgen::read<std::vector<Person>>)
.value();
const auto json1 = rfl::json::write(people1);
const auto json2 = rfl::json::write(people2);
EXPECT_EQ(json1, json2);
}
} // namespace test_timestamp
#endif
+47
View File
@@ -0,0 +1,47 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
namespace test_timestamp_with_tz {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
sqlgen::Timestamp<"%Y-%m-%d %H:%M:%S%z"> ts;
};
TEST(postgres, test_timestamp_with_tz) {
const auto people1 =
std::vector<Person>({Person{.id = 0,
.first_name = "Homer",
.last_name = "Simpson",
.ts = "2000-01-01 01:00:00+0100"}});
using namespace sqlgen;
const auto credentials = postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
const auto conn =
postgres::connect(credentials).and_then(drop<Person> | if_exists);
const auto people2 = sqlgen::write(conn, people1)
.and_then(sqlgen::read<std::vector<Person>>)
.value();
const auto json1 = rfl::json::write(people1);
const auto json2 = rfl::json::write(people2);
EXPECT_EQ(json1, json2);
}
} // namespace test_timestamp_with_tz
#endif
+62
View File
@@ -0,0 +1,62 @@
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_update {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_transaction) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0},
Person{
.id = 4, .first_name = "Hugo", .last_name = "Simpson", .age = 10}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
postgres::connect(credentials).and_then(drop<Person> | if_exists);
sqlgen::write(conn, people1).value();
const auto delete_hugo =
delete_from<Person> | where("first_name"_c == "Hugo");
const auto update_homers_age =
update<Person>("age"_c.set(46)) | where("first_name"_c == "Homer");
const auto get_data = sqlgen::read<std::vector<Person>> | order_by("id"_c);
const auto people2 = begin_transaction(conn)
.and_then(delete_hugo)
.and_then(update_homers_age)
.and_then(commit)
.and_then(get_data)
.value();
const std::string expected =
R"([{"id":0,"first_name":"Homer","last_name":"Simpson","age":46},{"id":1,"first_name":"Bart","last_name":"Simpson","age":10},{"id":2,"first_name":"Lisa","last_name":"Simpson","age":8},{"id":3,"first_name":"Maggie","last_name":"Simpson","age":0}])";
EXPECT_EQ(rfl::json::write(people2), expected);
}
} // namespace test_update
+60
View File
@@ -0,0 +1,60 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_update {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_update) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0},
Person{
.id = 4, .first_name = "Hugo", .last_name = "Simpson", .age = 10}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
sqlgen::write(conn, people1).value();
const auto update_hugos_age =
update<Person>("first_name"_c.set("last_name"_c), "age"_c.set(100)) |
where("first_name"_c == "Hugo");
const auto people2 =
conn.and_then(update_hugos_age)
.and_then(sqlgen::read<std::vector<Person>> | order_by("id"_c))
.value();
const std::string expected =
R"([{"id":0,"first_name":"Homer","last_name":"Simpson","age":45},{"id":1,"first_name":"Bart","last_name":"Simpson","age":10},{"id":2,"first_name":"Lisa","last_name":"Simpson","age":8},{"id":3,"first_name":"Maggie","last_name":"Simpson","age":0},{"id":4,"first_name":"Simpson","last_name":"Simpson","age":100}])";
EXPECT_EQ(rfl::json::write(people2), expected);
}
} // namespace test_update
#endif
+52
View File
@@ -0,0 +1,52 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_varchar {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
sqlgen::Varchar<6> first_name;
sqlgen::Varchar<7> last_name;
int age;
};
TEST(postgres, test_varchar) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
sqlgen::write(conn, people1).value();
const auto people2 = sqlgen::read<std::vector<Person>>(conn).value();
const auto json1 = rfl::json::write(people1);
const auto json2 = rfl::json::write(people2);
EXPECT_EQ(json1, json2);
}
} // namespace test_varchar
#endif
+57
View File
@@ -0,0 +1,57 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_where {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_where) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0},
Person{
.id = 4, .first_name = "Hugo", .last_name = "Simpson", .age = 10}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
sqlgen::postgres::connect(credentials).and_then(drop<Person> | if_exists);
sqlgen::write(conn, people1).value();
const auto query = sqlgen::read<std::vector<Person>> |
where("age"_c < 18 and "first_name"_c != "Hugo") |
order_by("age"_c);
const auto people2 = query(conn).value();
const std::string expected =
R"([{"id":3,"first_name":"Maggie","last_name":"Simpson","age":0},{"id":2,"first_name":"Lisa","last_name":"Simpson","age":8},{"id":1,"first_name":"Bart","last_name":"Simpson","age":10}])";
EXPECT_EQ(rfl::json::write(people2), expected);
}
} // namespace test_where
#endif
+51
View File
@@ -0,0 +1,51 @@
#ifndef SQLGEN_BUILD_DRY_TESTS_ONLY
#include <gtest/gtest.h>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/postgres.hpp>
#include <vector>
namespace test_write_and_read {
struct Person {
sqlgen::PrimaryKey<uint32_t> id;
std::string first_name;
std::string last_name;
int age;
};
TEST(postgres, test_write_and_read) {
const auto people1 = std::vector<Person>(
{Person{
.id = 0, .first_name = "Homer", .last_name = "Simpson", .age = 45},
Person{.id = 1, .first_name = "Bart", .last_name = "Simpson", .age = 10},
Person{.id = 2, .first_name = "Lisa", .last_name = "Simpson", .age = 8},
Person{
.id = 3, .first_name = "Maggie", .last_name = "Simpson", .age = 0}});
const auto credentials = sqlgen::postgres::Credentials{.user = "postgres",
.password = "password",
.host = "localhost",
.dbname = "postgres"};
using namespace sqlgen;
const auto conn =
postgres::connect(credentials).and_then(drop<Person> | if_exists);
const auto people2 = sqlgen::write(conn, people1)
.and_then(sqlgen::read<std::vector<Person>>)
.value();
const auto json1 = rfl::json::write(people1);
const auto json2 = rfl::json::write(people2);
EXPECT_EQ(json1, json2);
}
} // namespace test_write_and_read
#endif
+1 -1
View File
@@ -15,7 +15,7 @@ struct Person {
sqlgen::Timestamp<"%Y-%m-%d %H:%M:%S"> birthdate;
};
TEST(sqlite, test_birthdate) {
TEST(sqlite, test_timestamp) {
const auto people1 =
std::vector<Person>({Person{.id = 0,
.first_name = "Homer",
-23
View File
@@ -1,23 +0,0 @@
#include <gtest/gtest.h>
#include <sqlgen.hpp>
#include <sqlgen/transpilation/to_create_table.hpp>
namespace test_schema {
struct TestTable {
static constexpr const char* schema = "test";
std::string field1;
int32_t field2;
sqlgen::PrimaryKey<uint32_t> id;
std::optional<std::string> nullable;
};
TEST(general, test_schema) {
const auto create_table_stmt =
sqlgen::transpilation::to_create_table<TestTable>();
EXPECT_EQ(create_table_stmt.table.schema, "test");
}
} // namespace test_schema
-23
View File
@@ -1,23 +0,0 @@
#include <gtest/gtest.h>
#include <sqlgen.hpp>
#include <sqlgen/transpilation/to_create_table.hpp>
namespace test_tablename {
struct TestTable {
static constexpr const char* tablename = "TEST_TABLE";
std::string field1;
int32_t field2;
sqlgen::PrimaryKey<uint32_t> id;
std::optional<std::string> nullable;
};
TEST(general, test_tablename) {
const auto create_table_stmt =
sqlgen::transpilation::to_create_table<TestTable>();
EXPECT_EQ(create_table_stmt.table.name, "TEST_TABLE");
}
} // namespace test_tablename
-27
View File
@@ -1,27 +0,0 @@
#include <gtest/gtest.h>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/transpilation/to_create_table.hpp>
namespace test_to_create_table {
struct TestTable {
std::string field1;
int32_t field2;
sqlgen::PrimaryKey<uint32_t> id;
std::optional<std::string> nullable;
};
TEST(general, test_to_create_table) {
const auto create_table_stmt =
sqlgen::transpilation::to_create_table<TestTable>();
const std::string expected =
R"({"table":{"name":"TestTable"},"columns":[{"name":"field1","type":{"type":"Text","properties":{"primary":false,"nullable":false}}},{"name":"field2","type":{"type":"Int32","properties":{"primary":false,"nullable":false}}},{"name":"id","type":{"type":"UInt32","properties":{"primary":true,"nullable":false}}},{"name":"nullable","type":{"type":"Text","properties":{"primary":false,"nullable":true}}}],"if_not_exists":true})";
const auto json_str = rfl::json::write(create_table_stmt);
EXPECT_EQ(json_str, expected);
}
} // namespace test_to_create_table
-26
View File
@@ -1,26 +0,0 @@
#include <gtest/gtest.h>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/transpilation/to_insert.hpp>
namespace test_to_insert {
struct TestTable {
std::string field1;
int32_t field2;
sqlgen::PrimaryKey<uint32_t> id;
std::optional<std::string> nullable;
};
TEST(general, test_to_insert) {
const auto insert_stmt = sqlgen::transpilation::to_insert<TestTable>();
const std::string expected =
R"({"table":{"name":"TestTable"},"columns":["field1","field2","id","nullable"]})";
const auto json_str = rfl::json::write(insert_stmt);
EXPECT_EQ(json_str, expected);
}
} // namespace test_to_insert
-27
View File
@@ -1,27 +0,0 @@
#include <gtest/gtest.h>
#include <rfl/json.hpp>
#include <sqlgen.hpp>
#include <sqlgen/transpilation/to_select_from.hpp>
namespace test_to_select_from {
struct TestTable {
std::string field1;
int32_t field2;
sqlgen::PrimaryKey<uint32_t> id;
std::optional<std::string> nullable;
};
TEST(general, test_to_select_from) {
const auto select_from_stmt =
sqlgen::transpilation::to_select_from<TestTable>();
const std::string expected =
R"({"table":{"name":"TestTable"},"columns":[{"name":"field1","type":{"type":"Text","properties":{"primary":false,"nullable":false}}},{"name":"field2","type":{"type":"Int32","properties":{"primary":false,"nullable":false}}},{"name":"id","type":{"type":"UInt32","properties":{"primary":true,"nullable":false}}},{"name":"nullable","type":{"type":"Text","properties":{"primary":false,"nullable":true}}}]})";
const auto json_str = rfl::json::write(select_from_stmt);
EXPECT_EQ(json_str, expected);
}
} // namespace test_to_select_from