mirror of
https://github.com/boostorg/mysql.git
synced 2026-02-14 12:52:17 +00:00
Converted resultset tests into network tests
This commit is contained in:
@@ -73,6 +73,31 @@ public:
|
||||
return stmt.execute(values, err, info);
|
||||
});
|
||||
}
|
||||
network_result<const mysql::row*> fetch_one(
|
||||
tcp_resultset& r
|
||||
) override
|
||||
{
|
||||
return impl([&](error_code& errc, error_info& info) {
|
||||
return r.fetch_one(errc, info);
|
||||
});
|
||||
}
|
||||
network_result<std::vector<mysql::owning_row>> fetch_many(
|
||||
tcp_resultset& r,
|
||||
std::size_t count
|
||||
) override
|
||||
{
|
||||
return impl([&](error_code& errc, error_info& info) {
|
||||
return r.fetch_many(count, errc, info);
|
||||
});
|
||||
}
|
||||
network_result<std::vector<mysql::owning_row>> fetch_all(
|
||||
tcp_resultset& r
|
||||
) override
|
||||
{
|
||||
return impl([&](error_code& errc, error_info& info) {
|
||||
return r.fetch_all(errc, info);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class sync_exc : public network_functions
|
||||
@@ -141,6 +166,31 @@ public:
|
||||
return stmt.execute(values);
|
||||
});
|
||||
}
|
||||
network_result<const mysql::row*> fetch_one(
|
||||
tcp_resultset& r
|
||||
) override
|
||||
{
|
||||
return impl([&] {
|
||||
return r.fetch_one();
|
||||
});
|
||||
}
|
||||
network_result<std::vector<mysql::owning_row>> fetch_many(
|
||||
tcp_resultset& r,
|
||||
std::size_t count
|
||||
) override
|
||||
{
|
||||
return impl([&] {
|
||||
return r.fetch_many(count);
|
||||
});
|
||||
}
|
||||
network_result<std::vector<mysql::owning_row>> fetch_all(
|
||||
tcp_resultset& r
|
||||
) override
|
||||
{
|
||||
return impl([&] {
|
||||
return r.fetch_all();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
class async : public network_functions
|
||||
@@ -210,6 +260,31 @@ public:
|
||||
return stmt.async_execute(values, std::forward<decltype(token)>(token));
|
||||
});
|
||||
}
|
||||
network_result<const mysql::row*> fetch_one(
|
||||
tcp_resultset& r
|
||||
) override
|
||||
{
|
||||
return impl<const mysql::row*>([&](auto&& token) {
|
||||
return r.async_fetch_one(std::forward<decltype(token)>(token));
|
||||
});
|
||||
}
|
||||
network_result<std::vector<mysql::owning_row>> fetch_many(
|
||||
tcp_resultset& r,
|
||||
std::size_t count
|
||||
) override
|
||||
{
|
||||
return impl<std::vector<mysql::owning_row>>([&](auto&& token) {
|
||||
return r.async_fetch_many(count, std::forward<decltype(token)>(token));
|
||||
});
|
||||
}
|
||||
network_result<std::vector<mysql::owning_row>> fetch_all(
|
||||
tcp_resultset& r
|
||||
) override
|
||||
{
|
||||
return impl<std::vector<mysql::owning_row>>([&](auto&& token) {
|
||||
return r.async_fetch_all(std::forward<decltype(token)>(token));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Global objects to be exposed
|
||||
|
||||
@@ -59,6 +59,9 @@ public:
|
||||
tcp_prepared_statement&, value_list_it params_first, value_list_it params_last) = 0;
|
||||
virtual network_result<tcp_resultset> execute_statement(
|
||||
tcp_prepared_statement&, const std::vector<value>&) = 0;
|
||||
virtual network_result<const row*> fetch_one(tcp_resultset&) = 0;
|
||||
virtual network_result<std::vector<owning_row>> fetch_many(tcp_resultset&, std::size_t count) = 0;
|
||||
virtual network_result<std::vector<owning_row>> fetch_all(tcp_resultset&) = 0;
|
||||
};
|
||||
|
||||
extern network_functions* sync_errc_network_functions;
|
||||
|
||||
@@ -16,477 +16,280 @@ using mysql::field_metadata;
|
||||
using mysql::field_type;
|
||||
using mysql::error_code;
|
||||
using mysql::error_info;
|
||||
using mysql::tcp_resultset;
|
||||
namespace net = boost::asio;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class resultset_generator
|
||||
{
|
||||
public:
|
||||
virtual ~resultset_generator() {}
|
||||
virtual const char* name() const = 0;
|
||||
virtual mysql::tcp_resultset generate(mysql::tcp_connection&, std::string_view) = 0;
|
||||
};
|
||||
|
||||
struct ResultsetTestParam : named_param
|
||||
{
|
||||
std::string name;
|
||||
std::function<mysql::tcp_resultset(mysql::tcp_connection&, std::string_view)> generate_resultset;
|
||||
resultset_generator* gen;
|
||||
network_functions* net;
|
||||
|
||||
template <typename Callable>
|
||||
ResultsetTestParam(std::string name, Callable&& cb):
|
||||
name(std::move(name)), generate_resultset(std::forward<Callable>(cb)) {}
|
||||
ResultsetTestParam(resultset_generator* gen, network_functions* net):
|
||||
gen(gen), net(net) {}
|
||||
};
|
||||
|
||||
struct ResultsetTest : public IntegTestAfterHandshake, public testing::WithParamInterface<ResultsetTestParam>
|
||||
std::ostream& operator<<(std::ostream& os, const ResultsetTestParam& v)
|
||||
{
|
||||
return os << v.gen->name() << '.' << v.net->name();
|
||||
}
|
||||
|
||||
struct ResultsetTest : public IntegTestAfterHandshake,
|
||||
public testing::WithParamInterface<ResultsetTestParam>
|
||||
{
|
||||
auto do_generate(std::string_view query) { return GetParam().gen->generate(conn, query); }
|
||||
auto do_fetch_one(tcp_resultset& r) { return GetParam().net->fetch_one(r); }
|
||||
auto do_fetch_many(tcp_resultset& r, std::size_t count) { return GetParam().net->fetch_many(r, count); }
|
||||
auto do_fetch_all(tcp_resultset& r) { return GetParam().net->fetch_all(r); }
|
||||
};
|
||||
|
||||
// FetchOne, sync errc
|
||||
TEST_P(ResultsetTest, FetchOneSyncErrc_NoResults)
|
||||
// FetchOne
|
||||
TEST_P(ResultsetTest, FetchOne_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM empty_table");
|
||||
auto result = do_generate("SELECT * FROM empty_table");
|
||||
EXPECT_TRUE(result.valid());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(result.fields().size(), 2);
|
||||
|
||||
// Already in the end of the resultset, we receive the EOF
|
||||
const mysql::row* row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_EQ(row, nullptr);
|
||||
auto row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
EXPECT_EQ(row_result.value, nullptr);
|
||||
validate_eof(result);
|
||||
|
||||
// Fetching again just returns null
|
||||
reset_errors();
|
||||
row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_EQ(row, nullptr);
|
||||
row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
EXPECT_EQ(row_result.value, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchOneSyncErrc_OneRow)
|
||||
TEST_P(ResultsetTest, FetchOne_OneRow)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM one_row_table");
|
||||
auto result = do_generate("SELECT * FROM one_row_table");
|
||||
EXPECT_TRUE(result.valid());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(result.fields().size(), 2);
|
||||
|
||||
// Fetch only row
|
||||
const mysql::row* row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
ASSERT_NE(row, nullptr);
|
||||
auto row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
ASSERT_NE(row_result.value, nullptr);
|
||||
validate_2fields_meta(result, "one_row_table");
|
||||
EXPECT_EQ(row->values(), makevalues(1, "f0"));
|
||||
EXPECT_EQ(row_result.value->values(), makevalues(1, "f0"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next: end of resultset
|
||||
reset_errors();
|
||||
row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
ASSERT_EQ(row, nullptr);
|
||||
row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
ASSERT_EQ(row_result.value, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchOneSyncErrc_TwoRows)
|
||||
TEST_P(ResultsetTest, FetchOne_TwoRows)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
auto result = do_generate("SELECT * FROM two_rows_table");
|
||||
EXPECT_TRUE(result.valid());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(result.fields().size(), 2);
|
||||
|
||||
// Fetch first row
|
||||
const mysql::row* row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
ASSERT_NE(row, nullptr);
|
||||
auto row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
ASSERT_NE(row_result.value, nullptr);
|
||||
validate_2fields_meta(result, "two_rows_table");
|
||||
EXPECT_EQ(row->values(), makevalues(1, "f0"));
|
||||
EXPECT_EQ(row_result.value->values(), makevalues(1, "f0"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next row
|
||||
reset_errors();
|
||||
row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
ASSERT_NE(row, nullptr);
|
||||
row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
ASSERT_NE(row_result.value, nullptr);
|
||||
validate_2fields_meta(result, "two_rows_table");
|
||||
EXPECT_EQ(row->values(), makevalues(2, "f1"));
|
||||
EXPECT_EQ(row_result.value->values(), makevalues(2, "f1"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next: end of resultset
|
||||
reset_errors();
|
||||
row = result.fetch_one(errc, info);
|
||||
validate_no_error();
|
||||
ASSERT_EQ(row, nullptr);
|
||||
row_result = do_fetch_one(result);
|
||||
row_result.validate_no_error();
|
||||
ASSERT_EQ(row_result.value, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
// There seems to be no real case where fetch can fail (other than net fails)
|
||||
|
||||
// FetchOne, sync exc
|
||||
TEST_P(ResultsetTest, FetchOneSyncExc_TwoRows)
|
||||
// FetchMany
|
||||
TEST_P(ResultsetTest, FetchMany_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
EXPECT_TRUE(result.valid());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(result.fields().size(), 2);
|
||||
|
||||
// Fetch first row
|
||||
const mysql::row* row = result.fetch_one();
|
||||
ASSERT_NE(row, nullptr);
|
||||
validate_2fields_meta(result, "two_rows_table");
|
||||
EXPECT_EQ(row->values(), makevalues(1, "f0"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next row
|
||||
row = result.fetch_one();
|
||||
ASSERT_NE(row, nullptr);
|
||||
validate_2fields_meta(result, "two_rows_table");
|
||||
EXPECT_EQ(row->values(), makevalues(2, "f1"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next: end of resultset
|
||||
row = result.fetch_one();
|
||||
ASSERT_EQ(row, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
// FetchOne, async
|
||||
TEST_P(ResultsetTest, FetchOneAsync_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM empty_table");
|
||||
|
||||
// Already in the end of the resultset, we receive the EOF
|
||||
auto [info, row] = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_EQ(row, nullptr);
|
||||
validate_eof(result);
|
||||
|
||||
// Fetching again just returns null
|
||||
std::tie(info, row) = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_EQ(row, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchOneAsync_OneRow)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM one_row_table");
|
||||
|
||||
// Fetch only row
|
||||
auto [info, row] = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
ASSERT_NE(row, nullptr);
|
||||
EXPECT_EQ(row->values(), makevalues(1, "f0"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next: end of resultset
|
||||
reset_errors();
|
||||
std::tie(info, row) = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
ASSERT_EQ(row, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchOneAsync_TwoRows)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
|
||||
// Fetch first row
|
||||
auto [info, row] = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
ASSERT_NE(row, nullptr);
|
||||
EXPECT_EQ(row->values(), makevalues(1, "f0"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next row
|
||||
reset_errors();
|
||||
std::tie(info, row) = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
ASSERT_NE(row, nullptr);
|
||||
EXPECT_EQ(row->values(), makevalues(2, "f1"));
|
||||
EXPECT_FALSE(result.complete());
|
||||
|
||||
// Fetch next: end of resultset
|
||||
reset_errors();
|
||||
std::tie(info, row) = result.async_fetch_one(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
ASSERT_EQ(row, nullptr);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
// FetchMany, sync errc
|
||||
TEST_P(ResultsetTest, FetchManySyncErrc_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM empty_table");
|
||||
auto result = do_generate("SELECT * FROM empty_table");
|
||||
|
||||
// Fetch many, but there are no results
|
||||
auto rows = result.fetch_many(10, errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_TRUE(rows.empty());
|
||||
auto rows_result = do_fetch_many(result, 10);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_TRUE(rows_result.value.empty());
|
||||
EXPECT_TRUE(result.complete());
|
||||
validate_eof(result);
|
||||
|
||||
// Fetch again, should return OK and empty
|
||||
reset_errors();
|
||||
rows = result.fetch_many(10, errc, info);
|
||||
ASSERT_EQ(errc, error_code());
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(rows.empty());
|
||||
rows_result = do_fetch_many(result, 10);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_TRUE(rows_result.value.empty());
|
||||
EXPECT_TRUE(result.complete());
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManySyncErrc_MoreRowsThanCount)
|
||||
TEST_P(ResultsetTest, FetchMany_MoreRowsThanCount)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM three_rows_table");
|
||||
auto result = do_generate("SELECT * FROM three_rows_table");
|
||||
|
||||
// Fetch 2, one remaining
|
||||
auto rows = result.fetch_many(2, errc, info);
|
||||
validate_no_error();
|
||||
auto rows_result = do_fetch_many(result, 2);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 1, "f0", 2, "f1")));
|
||||
|
||||
// Fetch another two (completes the resultset)
|
||||
reset_errors();
|
||||
rows = result.fetch_many(2, errc, info);
|
||||
validate_no_error();
|
||||
rows_result = do_fetch_many(result, 2);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_TRUE(result.complete());
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows, (makerows(2, 3, "f2")));
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 3, "f2")));
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManySyncErrc_LessRowsThanCount)
|
||||
TEST_P(ResultsetTest, FetchMany_LessRowsThanCount)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
auto result = do_generate("SELECT * FROM two_rows_table");
|
||||
|
||||
// Fetch 3, resultset exhausted
|
||||
auto rows = result.fetch_many(3, errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
auto rows_result = do_fetch_many(result, 3);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 1, "f0", 2, "f1")));
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManySyncErrc_SameRowsAsCount)
|
||||
TEST_P(ResultsetTest, FetchMany_SameRowsAsCount)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
auto result = do_generate("SELECT * FROM two_rows_table");
|
||||
|
||||
// Fetch 2, 0 remaining but resultset not exhausted
|
||||
auto rows = result.fetch_many(2, errc, info);
|
||||
validate_no_error();
|
||||
auto rows_result = do_fetch_many(result, 2);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 1, "f0", 2, "f1")));
|
||||
|
||||
// Fetch again, exhausts the resultset
|
||||
reset_errors();
|
||||
rows = result.fetch_many(2, errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_EQ(rows.size(), 0);
|
||||
rows_result = do_fetch_many(result, 2);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_EQ(rows_result.value.size(), 0);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManySyncErrc_CountEqualsOne)
|
||||
TEST_P(ResultsetTest, FetchMany_CountEqualsOne)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM one_row_table");
|
||||
auto result = do_generate("SELECT * FROM one_row_table");
|
||||
|
||||
// Fetch 1, 1 remaining
|
||||
auto rows = result.fetch_many(1, errc, info);
|
||||
validate_no_error();
|
||||
auto rows_result = do_fetch_many(result, 1);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0")));
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 1, "f0")));
|
||||
}
|
||||
|
||||
// FetchMany, sync exc
|
||||
TEST_P(ResultsetTest, FetchManySyncExc_MoreRowsThanCount)
|
||||
// FetchAll
|
||||
TEST_P(ResultsetTest, FetchAll_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM three_rows_table");
|
||||
|
||||
// Fetch 2, one remaining
|
||||
auto rows = result.fetch_many(2);
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
|
||||
// Fetch another two (completes the resultset)
|
||||
rows = result.fetch_many(2);
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows, (makerows(2, 3, "f2")));
|
||||
|
||||
// Fetching another time returns empty
|
||||
rows = result.fetch_many(2);
|
||||
EXPECT_EQ(rows.size(), 0);
|
||||
}
|
||||
|
||||
// FetchMany, async
|
||||
TEST_P(ResultsetTest, FetchManyAsync_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM empty_table");
|
||||
auto result = do_generate("SELECT * FROM empty_table");
|
||||
|
||||
// Fetch many, but there are no results
|
||||
auto [info, rows] = result.async_fetch_many(10, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(rows.empty());
|
||||
EXPECT_TRUE(result.complete());
|
||||
validate_eof(result);
|
||||
|
||||
// Fetch again, should return OK and empty
|
||||
reset_errors();
|
||||
std::tie(info, rows) = result.async_fetch_many(10, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(rows.empty());
|
||||
EXPECT_TRUE(result.complete());
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManyAsync_MoreRowsThanCount)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM three_rows_table");
|
||||
|
||||
// Fetch 2, one remaining
|
||||
auto [info, rows] = result.async_fetch_many(2, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
|
||||
// Fetch another two (completes the resultset)
|
||||
std::tie(info, rows) = result.async_fetch_many(2, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(result.complete());
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows, (makerows(2, 3, "f2")));
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManyAsync_LessRowsThanCount)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
|
||||
// Fetch 3, resultset exhausted
|
||||
auto [info, rows] = result.async_fetch_many(3, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManyAsync_SameRowsAsCount)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
|
||||
// Fetch 2, 0 remaining but resultset not exhausted
|
||||
auto [info, rows] = result.async_fetch_many(2, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
|
||||
// Fetch again, exhausts the resultset
|
||||
reset_errors();
|
||||
std::tie(info, rows) = result.async_fetch_many(2, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_EQ(rows.size(), 0);
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchManyAsync_CountEqualsOne)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM one_row_table");
|
||||
|
||||
// Fetch 1, 1 remaining
|
||||
auto [info, rows] = result.async_fetch_many(1, net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_FALSE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0")));
|
||||
}
|
||||
|
||||
// FetchAll, sync errc
|
||||
TEST_P(ResultsetTest, FetchAllSyncErrc_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM empty_table");
|
||||
|
||||
// Fetch many, but there are no results
|
||||
auto rows = result.fetch_all(errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_TRUE(rows.empty());
|
||||
auto rows_result = do_fetch_all(result);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_TRUE(rows_result.value.empty());
|
||||
EXPECT_TRUE(result.complete());
|
||||
|
||||
// Fetch again, should return OK and empty
|
||||
reset_errors();
|
||||
rows = result.fetch_all(errc, info);
|
||||
validate_no_error();
|
||||
EXPECT_TRUE(rows.empty());
|
||||
rows_result = do_fetch_all(result);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_TRUE(rows_result.value.empty());
|
||||
validate_eof(result);
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchAllSyncErrc_OneRow)
|
||||
TEST_P(ResultsetTest, FetchAll_OneRow)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM one_row_table");
|
||||
auto result = do_generate("SELECT * FROM one_row_table");
|
||||
|
||||
auto rows = result.fetch_all(errc, info);
|
||||
validate_no_error();
|
||||
auto rows_result = do_fetch_all(result);
|
||||
rows_result.validate_no_error();
|
||||
EXPECT_TRUE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0")));
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 1, "f0")));
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchAllSyncErrc_SeveralRows)
|
||||
TEST_P(ResultsetTest, FetchAll_SeveralRows)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
auto result = do_generate("SELECT * FROM two_rows_table");
|
||||
|
||||
auto rows = result.fetch_all(errc, info);
|
||||
validate_no_error();
|
||||
auto rows_result = do_fetch_all(result);
|
||||
rows_result.validate_no_error();
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
}
|
||||
|
||||
// FetchAll, sync exc
|
||||
TEST_P(ResultsetTest, FetchAllSyncExc_SeveralRows)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
auto rows = result.fetch_all();
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
}
|
||||
|
||||
// FetchAll, async
|
||||
TEST_P(ResultsetTest, FetchAllAsync_NoResults)
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM empty_table");
|
||||
|
||||
// Fetch many, but there are no results
|
||||
auto [info, rows] = result.async_fetch_all(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(rows.empty());
|
||||
EXPECT_TRUE(result.complete());
|
||||
|
||||
// Fetch again, should return OK and empty
|
||||
reset_errors();
|
||||
std::tie(info, rows) = result.async_fetch_all(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(rows.empty());
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows_result.value, (makerows(2, 1, "f0", 2, "f1")));
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchAllAsync_OneRow)
|
||||
|
||||
// Instantiate the test suites
|
||||
class text_resultset_generator : public resultset_generator
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM one_row_table");
|
||||
public:
|
||||
const char* name() const override { return "text"; }
|
||||
mysql::tcp_resultset generate(mysql::tcp_connection& conn, std::string_view query) override
|
||||
{
|
||||
return conn.query(query);
|
||||
}
|
||||
};
|
||||
|
||||
auto [info, rows] = result.async_fetch_all(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
EXPECT_TRUE(result.complete());
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0")));
|
||||
}
|
||||
|
||||
TEST_P(ResultsetTest, FetchAllAsync_SeveralRows)
|
||||
class binary_resultset_generator : public resultset_generator
|
||||
{
|
||||
auto result = GetParam().generate_resultset(conn, "SELECT * FROM two_rows_table");
|
||||
public:
|
||||
const char* name() const override { return "binary"; }
|
||||
mysql::tcp_resultset generate(mysql::tcp_connection& conn, std::string_view query) override
|
||||
{
|
||||
return conn.prepare_statement(query).execute(mysql::no_statement_params);
|
||||
}
|
||||
};
|
||||
|
||||
auto [info, rows] = result.async_fetch_all(net::use_future).get();
|
||||
EXPECT_EQ(info, error_info());
|
||||
validate_eof(result);
|
||||
EXPECT_EQ(rows, (makerows(2, 1, "f0", 2, "f1")));
|
||||
}
|
||||
text_resultset_generator text_obj;
|
||||
binary_resultset_generator binary_obj;
|
||||
|
||||
mysql::tcp_resultset make_text_resultset(mysql::tcp_connection& conn, std::string_view query)
|
||||
resultset_generator* all_resultset_generators [] = {
|
||||
&text_obj,
|
||||
&binary_obj
|
||||
};
|
||||
|
||||
std::vector<ResultsetTestParam> make_resultset_test_params()
|
||||
{
|
||||
return conn.query(query);
|
||||
}
|
||||
|
||||
mysql::tcp_resultset make_binary_resultset(mysql::tcp_connection& conn, std::string_view query)
|
||||
{
|
||||
return conn.prepare_statement(query).execute(mysql::no_statement_params);
|
||||
std::vector<ResultsetTestParam> res;
|
||||
for (auto* gen: all_resultset_generators)
|
||||
{
|
||||
for (auto* net: all_network_functions)
|
||||
{
|
||||
res.push_back(ResultsetTestParam{gen, net});
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(Default, ResultsetTest, testing::Values(
|
||||
ResultsetTestParam("text", &make_text_resultset),
|
||||
ResultsetTestParam("binary", &make_binary_resultset)
|
||||
INSTANTIATE_TEST_SUITE_P(Default, ResultsetTest, testing::ValuesIn(
|
||||
make_resultset_test_params()
|
||||
), test_name_generator);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user