diff --git a/bigtable/client/testing/inprocess_admin_client.h b/bigtable/client/testing/inprocess_admin_client.h index e8ccf450128f8..6a75c595a0bd9 100644 --- a/bigtable/client/testing/inprocess_admin_client.h +++ b/bigtable/client/testing/inprocess_admin_client.h @@ -52,7 +52,7 @@ class InProcessAdminClient : public bigtable::AdminClient { std::shared_ptr channel_; }; -} // namespace BIGTABLE_CLIENT_NS +} // namespace testing } // namespace bigtable #endif // GOOGLE_CLOUD_CPP_BIGTABLE_CLIENT_TESTING_INPROCESS_ADMIN_CLIENT_H_ diff --git a/bigtable/client/testing/inprocess_data_client.h b/bigtable/client/testing/inprocess_data_client.h index 3e73cede7c905..26cf4aaf1a52f 100644 --- a/bigtable/client/testing/inprocess_data_client.h +++ b/bigtable/client/testing/inprocess_data_client.h @@ -57,7 +57,7 @@ class InProcessDataClient : public bigtable::DataClient { std::shared_ptr channel_; }; -} // namespace BIGTABLE_CLIENT_NS +} // namespace testing } // namespace bigtable #endif // GOOGLE_CLOUD_CPP_BIGTABLE_CLIENT_TESTING_INPROCESS_DATA_CLIENT_H_ diff --git a/bigtable/client/testing/table_integration_test.cc b/bigtable/client/testing/table_integration_test.cc index 590755428290f..3eb7ade888b38 100644 --- a/bigtable/client/testing/table_integration_test.cc +++ b/bigtable/client/testing/table_integration_test.cc @@ -15,6 +15,7 @@ #include "bigtable/client/testing/table_integration_test.h" #include "bigtable/client/internal/make_unique.h" #include +#include #include namespace bigtable { @@ -71,6 +72,16 @@ std::vector TableIntegrationTest::ReadRows( return result; } +std::vector TableIntegrationTest::MoveCellsFromReader( + bigtable::RowReader& reader) { + std::vector result; + for (auto const& row : reader) { + std::move(row.cells().begin(), row.cells().end(), + std::back_inserter(result)); + } + return result; +} + /// A helper function to create a list of cells. void TableIntegrationTest::CreateCells( bigtable::Table& table, std::vector const& cells) { diff --git a/bigtable/client/testing/table_integration_test.h b/bigtable/client/testing/table_integration_test.h index f0fb3b33cf976..8961a76ed519c 100644 --- a/bigtable/client/testing/table_integration_test.h +++ b/bigtable/client/testing/table_integration_test.h @@ -64,6 +64,8 @@ class TableIntegrationTest : public ::testing::Test { std::int64_t rows_limit, bigtable::Filter filter); + std::vector MoveCellsFromReader(bigtable::RowReader& reader); + /// Return all the cells in @p table that pass @p filter. void CreateCells(bigtable::Table& table, std::vector const& cells); diff --git a/bigtable/tests/data_integration_test.cc b/bigtable/tests/data_integration_test.cc index f454d939ecbdd..a8431404c2816 100644 --- a/bigtable/tests/data_integration_test.cc +++ b/bigtable/tests/data_integration_test.cc @@ -41,6 +41,10 @@ class DataIntegrationTest : public bigtable::testing::TableIntegrationTest { {}); }; +bool UsingCloudBigtableEmulator() { + return std::getenv("BIGTABLE_EMULATOR_HOST") != nullptr; +} + } // anonymous namespace int main(int argc, char* argv[]) { @@ -212,6 +216,142 @@ TEST_F(DataIntegrationTest, TableReadRowNotExistTest) { EXPECT_FALSE(row_cell.first); } +TEST_F(DataIntegrationTest, TableReadRowsAllRows) { + std::string const table_name = "table-read-rows-all-rows"; + auto table = CreateTable(table_name, table_config); + std::string const row_key1 = "row-key-1"; + std::string const row_key2 = "row-key-2"; + std::string const row_key3(1024, '3'); // a long key + std::string const long_value(1024, 'v'); // a long value + + std::vector created{ + {row_key1, family, "c1", 1000, "data1", {}}, + {row_key1, family, "c2", 1000, "data2", {}}, + {row_key2, family, "c1", 1000, "", {}}, + {row_key3, family, "c1", 1000, long_value, {}}}; + + CreateCells(*table, created); + + // Some equivalent ways to read the three rows + auto read1 = + table->ReadRows(bigtable::RowSet(bigtable::RowRange::InfiniteRange()), + bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(created, MoveCellsFromReader(read1)); + + auto read2 = + table->ReadRows(bigtable::RowSet(bigtable::RowRange::InfiniteRange()), 3, + bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(created, MoveCellsFromReader(read2)); + + auto read3 = table->ReadRows( + bigtable::RowSet(bigtable::RowRange::InfiniteRange()), + bigtable::RowReader::NO_ROWS_LIMIT, bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(created, MoveCellsFromReader(read3)); + + if (!UsingCloudBigtableEmulator()) { + // TODO(#151) - remove workarounds for emulator bug(s). + auto read4 = + table->ReadRows(bigtable::RowSet(), bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(created, MoveCellsFromReader(read4)); + } + DeleteTable(table_name); +} + +TEST_F(DataIntegrationTest, TableReadRowsPartialRows) { + std::string const table_name = "table-read-rows-partial-rows"; + auto table = CreateTable(table_name, table_config); + std::string const row_key1 = "row-key-1"; + std::string const row_key2 = "row-key-2"; + std::string const row_key3 = "row-key-3"; + + std::vector created{ + {row_key1, family, "c1", 1000, "data1", {}}, + {row_key1, family, "c2", 1000, "data2", {}}, + {row_key2, family, "c1", 1000, "data3", {}}, + {row_key3, family, "c1", 1000, "data4", {}}}; + + CreateCells(*table, created); + + std::vector expected{ + {row_key1, family, "c1", 1000, "data1", {}}, + {row_key1, family, "c2", 1000, "data2", {}}, + {row_key2, family, "c1", 1000, "data3", {}}}; + + // Some equivalent ways of reading just the first two rows + auto read1 = + table->ReadRows(bigtable::RowSet(bigtable::RowRange::InfiniteRange()), 2, + bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(expected, MoveCellsFromReader(read1)); + + bigtable::RowSet rs2; + rs2.Append(row_key1); + rs2.Append(row_key2); + auto read2 = + table->ReadRows(std::move(rs2), bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(expected, MoveCellsFromReader(read2)); + + bigtable::RowSet rs3(bigtable::RowRange::Closed(row_key1, row_key2)); + auto read3 = + table->ReadRows(std::move(rs3), bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(expected, MoveCellsFromReader(read3)); + + DeleteTable(table_name); +} + +TEST_F(DataIntegrationTest, TableReadRowsNoRows) { + std::string const table_name = "table-read-rows-no-rows"; + auto table = CreateTable(table_name, table_config); + std::string const row_key1 = "row-key-1"; + std::string const row_key2 = "row-key-2"; + std::string const row_key3 = "row-key-3"; + + std::vector created{ + {row_key1, family, "c1", 1000, "data1", {}}, + {row_key3, family, "c1", 1000, "data2", {}}}; + + CreateCells(*table, created); + + std::vector expected; // empty + + // read nonexistent rows + auto read1 = table->ReadRows(bigtable::RowSet(row_key2), + bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(expected, MoveCellsFromReader(read1)); + + auto read2 = + table->ReadRows(bigtable::RowSet(bigtable::RowRange::Prefix(row_key2)), + bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(expected, MoveCellsFromReader(read2)); + + auto read3 = table->ReadRows(bigtable::RowSet(bigtable::RowRange::Empty()), + bigtable::Filter::PassAllFilter()); + CheckEqualUnordered(expected, MoveCellsFromReader(read3)); + + DeleteTable(table_name); +} + +TEST_F(DataIntegrationTest, TableReadRowsWrongTable) { + std::string const table_name = "table-read-rows-wrong-table"; + +#if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS + bigtable::Table table(data_client_, table_name); +#else + bigtable::noex::Table table(data_client_, table_name); +#endif + + auto read1 = + table.ReadRows(bigtable::RowSet(bigtable::RowRange::InfiniteRange()), + bigtable::Filter::PassAllFilter()); + +#if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS + EXPECT_THROW(read1.begin(), std::runtime_error); +#else + EXPECT_EQ(read1.begin(), read1.end()); + grpc::Status status1 = read1.Finish(); + EXPECT_FALSE(status1.ok()); +#endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS +} + TEST_F(DataIntegrationTest, TableCheckAndMutateRowPass) { std::string const table_name = "table-check-and-mutate-row-pass"; auto table = CreateTable(table_name, table_config);