Skip to content

Commit c26e18b

Browse files
committed
chore: add latest version of tests
1 parent 8440c5d commit c26e18b

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

google/cloud/bigtable/tests/data_integration_test.cc

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ TEST_P(DataIntegrationTest, ClientQueryColumnFamily) {
648648
Project project(project_id());
649649
InstanceResource instance_resource(project, instance_id());
650650

651+
651652
auto prepared_query = client.PrepareQuery(
652653
instance_resource,
653654
SqlStatement("SELECT family4 AS c0 FROM " + quoted_table_name +
@@ -672,6 +673,138 @@ TEST_P(DataIntegrationTest, ClientQueryColumnFamily) {
672673
ASSERT_EQ(row1.values().at(1), Value(value2));
673674
}
674675

676+
TEST_P(DataIntegrationTest, ClientQueryColumnFamilyWithHistory) {
677+
if (UsingCloudBigtableEmulator()) GTEST_SKIP();
678+
auto const table_id = testing::TableTestEnvironment::table_id();
679+
auto retry_policy_option = DataLimitedErrorCountRetryPolicy(0).clone();
680+
auto backoff_policy_option =
681+
google::cloud::internal::ExponentialBackoffPolicy(ms(0), ms(0), 2.0)
682+
.clone();
683+
auto query_refresh_option =
684+
bigtable::experimental::QueryPlanRefreshLimitedErrorCountRetryPolicy(0)
685+
.clone();
686+
auto opts =
687+
Options{}
688+
.set<DataRetryPolicyOption>(std::move(retry_policy_option))
689+
.set<DataBackoffPolicyOption>(std::move(backoff_policy_option))
690+
.set<bigtable::experimental::QueryPlanRefreshRetryPolicyOption>(
691+
std::move(query_refresh_option));
692+
auto connection = google::cloud::bigtable::MakeDataConnection(opts);
693+
auto table =
694+
Table(connection, TableResource(project_id(), instance_id(), table_id));
695+
std::string const row_key = "row-key-for-history-test";
696+
std::string const family = kFamily4;
697+
std::string const column1 = "c1";
698+
std::string const column2 = "c2";
699+
std::string const column_1_value_old = "c1_v1_old";
700+
std::string const column_1_value_new = "c1_v2_new";
701+
std::string const column_2_value_old = "c2_v1_old";
702+
std::string const column_2_value_new = "c2_v2_new";
703+
704+
// Get times in microseconds
705+
auto now_sys = std::chrono::system_clock::now();
706+
auto current_time = std::chrono::duration_cast<std::chrono::microseconds>(
707+
now_sys.time_since_epoch())
708+
.count();
709+
auto old_time = current_time - 5000000; // 5 seconds older
710+
711+
// Apply mutations with specific timestamps
712+
SingleRowMutation mutation(row_key);
713+
mutation.emplace_back(
714+
SetCell(family, column1,
715+
duration_cast<milliseconds>(std::chrono::microseconds(old_time)),
716+
column_1_value_old));
717+
mutation.emplace_back(SetCell(
718+
family, column1,
719+
duration_cast<milliseconds>(std::chrono::microseconds(current_time)),
720+
column_1_value_new));
721+
mutation.emplace_back(
722+
SetCell(family, column2,
723+
duration_cast<milliseconds>(std::chrono::microseconds(old_time)),
724+
column_2_value_old));
725+
mutation.emplace_back(SetCell(
726+
family, column2,
727+
duration_cast<milliseconds>(std::chrono::microseconds(current_time)),
728+
column_2_value_new));
729+
auto apply_status = table.Apply(std::move(mutation));
730+
ASSERT_TRUE(apply_status.ok()) << apply_status.message();
731+
732+
// Execute query using WITH_HISTORY
733+
auto client = Client(connection, opts);
734+
std::vector<std::string> full_table_path =
735+
absl::StrSplit(table.table_name(), '/');
736+
auto table_name = full_table_path.back();
737+
std::string quoted_table_name = "`" + table_name + "`";
738+
Project project(project_id());
739+
InstanceResource instance_resource(project, instance_id());
740+
std::string query_string = absl::StrFormat(
741+
R"sql(SELECT family4 AS family4_history
742+
FROM %s(WITH_HISTORY => TRUE)
743+
WHERE _key = '%s')sql",
744+
quoted_table_name, row_key);
745+
auto prepared_query =
746+
client.PrepareQuery(instance_resource, SqlStatement(query_string));
747+
ASSERT_TRUE(prepared_query.ok()) << prepared_query.status().message();
748+
749+
auto bound_query = (*prepared_query).BindParameters({});
750+
auto row_stream = client.ExecuteQuery(std::move(bound_query));
751+
std::vector<StatusOr<QueryRow>> rows;
752+
for (auto const& row : std::move(row_stream)) {
753+
rows.push_back(row);
754+
}
755+
ASSERT_EQ(rows.size(), 1);
756+
ASSERT_TRUE(rows[0].ok()) << rows[0].status().message();
757+
auto const& row = *rows[0];
758+
ASSERT_EQ(row.columns().size(), 2);
759+
EXPECT_EQ(row.columns().at(0), "family4_history");
760+
761+
auto value_hist = row.get("family4_history");
762+
ASSERT_TRUE(value_hist.ok()) << value_hist.status().message();
763+
Value const& bigtable_val = *value_hist;
764+
using HistoryEntry = std::tuple<Timestamp, std::string>;
765+
auto history_map = bigtable_val.get<std::map<std::string, std::vector<HistoryEntry>>>();
766+
ASSERT_TRUE(history_map.ok()) << history_array.status().message();
767+
ASSERT_EQ(history_map->size(), 2);
768+
769+
// Verify cells returned ordered from newest to oldest.
770+
auto const& c1_entry0 = (*history_map)["c1"][0];
771+
auto ts_new = std::get<0>(c1_entry0).get<sys_time<std::chrono::microseconds>>();
772+
ASSERT_STATUS_OK(ts_new);
773+
auto expected_current_time_ms =
774+
duration_cast<milliseconds>(std::chrono::microseconds(current_time));
775+
EXPECT_EQ(duration_cast<milliseconds>(ts_new->time_since_epoch()),
776+
expected_current_time_ms);
777+
EXPECT_EQ(std::get<1>(c1_entry0), column_1_value_new);
778+
779+
auto const& c1_entry1 = (*history_map)["c1"][1];
780+
auto ts_old = std::get<0>(c1_entry1).get<sys_time<std::chrono::microseconds>>();
781+
ASSERT_STATUS_OK(ts_old);
782+
auto expected_old_time_ms =
783+
duration_cast<milliseconds>(std::chrono::microseconds(old_time));
784+
EXPECT_EQ(duration_cast<milliseconds>(ts_old->time_since_epoch()),
785+
expected_old_time_ms);
786+
EXPECT_EQ(std::get<1>(c1_entry1), column_1_value_old);
787+
788+
// Verify cells returned ordered from newest to oldest.
789+
auto const& c2_entry0 = (*history_map)["c2"][0];
790+
auto ts_new = std::get<0>(c2_entry0).get<sys_time<std::chrono::microseconds>>();
791+
ASSERT_STATUS_OK(ts_new);
792+
auto expected_current_time_ms =
793+
duration_cast<milliseconds>(std::chrono::microseconds(current_time));
794+
EXPECT_EQ(duration_cast<milliseconds>(ts_new->time_since_epoch()),
795+
expected_current_time_ms);
796+
EXPECT_EQ(std::get<1>(c2_entry0), column_2_value_new);
797+
798+
auto const& c2_entry1 = (*history_map)["c2"][1];
799+
auto ts_old = std::get<0>(c2_entry1).get<sys_time<std::chrono::microseconds>>();
800+
ASSERT_STATUS_OK(ts_old);
801+
auto expected_old_time_ms =
802+
duration_cast<milliseconds>(std::chrono::microseconds(old_time));
803+
EXPECT_EQ(duration_cast<milliseconds>(ts_old->time_since_epoch()),
804+
expected_old_time_ms);
805+
EXPECT_EQ(std::get<1>(c2_entry1), column_2_value_old);
806+
}
807+
675808
// TODO(#8800) - remove after deprecation is complete
676809
#include "google/cloud/internal/disable_deprecation_warnings.inc"
677810

0 commit comments

Comments
 (0)