Skip to content

Commit 5660181

Browse files
authored
test(spanner): speed up test with emulator (#8072)
The `rpc_failure_threshold_integration_test` was running very slowly against the emulator. The test is not that useful against the emulator, but we do not want it to rot. I changed the test to detect that it is running against the emulator, and then simply reduce the running time, and ignore the statistical results as they become unreliable.
1 parent 08b74fd commit 5660181

File tree

1 file changed

+27
-16
lines changed

1 file changed

+27
-16
lines changed

google/cloud/spanner/integration_tests/rpc_failure_threshold_integration_test.cc

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class RpcFailureThresholdTest
4141
google::cloud::internal::GetEnv("GOOGLE_CLOUD_PROJECT").value_or("");
4242
ASSERT_FALSE(project_id.empty());
4343

44-
generator_ = google::cloud::internal::MakeDefaultPRNG();
44+
generator_ = google::cloud::internal::DefaultPRNG(std::random_device{}());
4545
auto instance_id =
4646
spanner_testing::PickRandomInstance(generator_, project_id);
4747
ASSERT_STATUS_OK(instance_id);
@@ -81,9 +81,8 @@ class RpcFailureThresholdTest
8181
}
8282

8383
void TearDown() override {
84-
if (!db_) {
85-
return;
86-
}
84+
if (!db_) return;
85+
8786
std::cout << "Dropping database " << db_->database_id() << std::flush;
8887
spanner_admin::DatabaseAdminClient admin_client(
8988
spanner_admin::MakeDatabaseAdminConnection());
@@ -102,6 +101,8 @@ struct Result {
102101
int number_of_failures;
103102
};
104103

104+
auto constexpr kReportCount = 5;
105+
105106
/// Run a single copy of the experiment
106107
Result RunExperiment(Database const& db, int iterations) {
107108
// Use a different client on each thread because we do not want to share
@@ -129,7 +130,7 @@ Result RunExperiment(Database const& db, int iterations) {
129130
}
130131
};
131132

132-
int const report = iterations / 5;
133+
int const report = iterations / kReportCount;
133134
for (int i = 0; i != iterations; ++i) {
134135
if (i % report == 0) std::cout << '.' << std::flush;
135136
auto delete_status =
@@ -163,7 +164,7 @@ Result RunExperiment(Database const& db, int iterations) {
163164
* If the confidence interval includes a critical threshold (0.999) then the
164165
* program fails, claiming that the underlying error rate may be too high.
165166
*
166-
* The number of iteration in the program was chosen to the statistical test
167+
* The number of iteration in the program was chosen so the statistical test
167168
* would have 0.99 power. That is, the test would miss an actual change from
168169
* 0.001 to 0.002 only 1% of the time.
169170
*
@@ -173,6 +174,10 @@ Result RunExperiment(Database const& db, int iterations) {
173174
*/
174175
TEST_F(RpcFailureThresholdTest, ExecuteDmlDeleteErrors) {
175176
ASSERT_TRUE(db_);
177+
// When using the emulator there is not much value in this test, we still run
178+
// it just to get the code coverage.
179+
auto const emulator =
180+
google::cloud::internal::GetEnv("SPANNER_EMULATOR_HOST").has_value();
176181

177182
// We are using the approximation via a normal distribution from here:
178183
// https://en.wikipedia.org/wiki/Binomial_proportion_confidence_interval
@@ -193,8 +198,8 @@ TEST_F(RpcFailureThresholdTest, ExecuteDmlDeleteErrors) {
193198
// ```R
194199
// require(pwr)
195200
// pwr.p.test(
196-
// h=ES.h(p1=0.002, p2=0.001),
197-
// power=0.99, sig.level=0.01, alternative="greater")
201+
// h=ES.h(p1=0.001, p2=0.0001),
202+
// power=0.95, sig.level=0.01, alternative="greater")
198203
// proportion power calculation for binomial distribution
199204
// (arcsine transformation)
200205
//
@@ -214,15 +219,20 @@ TEST_F(RpcFailureThresholdTest, ExecuteDmlDeleteErrors) {
214219

215220
int const desired_samples = 32000; // slightly higher sample rate.
216221

217-
auto const threads_per_core = 8;
218-
// GCC and Clang default capture constants, but MSVC does not, so pass the
219-
// constant as an argument.
220-
auto const number_of_threads = [](int tpc) -> unsigned {
222+
auto constexpr kMinThreads = 8;
223+
auto const number_of_threads = [&] {
221224
auto number_of_cores = std::thread::hardware_concurrency();
222-
return number_of_cores == 0 ? tpc : number_of_cores * tpc;
223-
}(threads_per_core);
225+
return number_of_cores == 0 ? kMinThreads : number_of_cores;
226+
}();
224227

225-
auto const iterations = static_cast<int>(desired_samples / number_of_threads);
228+
// When using the emulator we run the minimal number of iterations needed to
229+
// ensure the code does not rot. Otherwise, we run the same number of
230+
// iterations in each thread, such that the total number of "samples" matches
231+
// the `desired_samples. We are a bit sloppy and add 1 to account for
232+
// truncation, running an extra iteration won't hurt.
233+
auto const iterations = std::max(
234+
kReportCount, // minimum value that does not crash
235+
emulator ? 1 : static_cast<int>(desired_samples / number_of_threads) + 1);
226236

227237
int number_of_successes = 0;
228238
int number_of_failures = 0;
@@ -250,12 +260,13 @@ TEST_F(RpcFailureThresholdTest, ExecuteDmlDeleteErrors) {
250260
<< "\nEstimated 99% confidence interval for success rate is ["
251261
<< (mid - r) << "," << (mid + r) << "]\n";
252262

263+
if (emulator) return;
253264
EXPECT_GT(mid - r, 1.0 - threshold)
254265
<< " number_of_failures=" << number_of_failures
255266
<< ", number_of_successes=" << number_of_successes
256267
<< ", number_of_trials=" << number_of_trials << ", mid=" << mid
257268
<< ", r=" << r << ", range=[ " << (mid - r) << " , " << (mid + r) << "]"
258-
<< ", kTheshold=" << threshold;
269+
<< ", kThreshold=" << threshold;
259270
}
260271

261272
} // namespace

0 commit comments

Comments
 (0)