1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "google/cloud/internal/future_impl.h"
16 #include "google/cloud/testing_util/chrono_literals.h"
17 #include "google/cloud/testing_util/expect_future_error.h"
18 #include "google/cloud/testing_util/testing_types.h"
19 #include "absl/memory/memory.h"
20 #include <gmock/gmock.h>
21
22 namespace google {
23 namespace cloud {
24 inline namespace GOOGLE_CLOUD_CPP_NS {
25 namespace internal {
26 namespace {
27
28 using ::testing::HasSubstr;
29 using testing_util::chrono_literals::operator"" _us;
30 using testing_util::ExpectFutureError;
31 using testing_util::NoDefaultConstructor;
32 using testing_util::Observable;
33
TEST(FutureImplBaseTest,Basic)34 TEST(FutureImplBaseTest, Basic) {
35 future_shared_state_base shared_state;
36 EXPECT_FALSE(shared_state.is_ready());
37 }
38
TEST(FutureImplBaseTest,WaitFor)39 TEST(FutureImplBaseTest, WaitFor) {
40 future_shared_state_base shared_state;
41 auto start = std::chrono::steady_clock::now();
42 auto s = shared_state.wait_for(100_us);
43 auto elapsed = std::chrono::steady_clock::now() - start;
44 EXPECT_EQ(static_cast<int>(s), static_cast<int>(std::future_status::timeout));
45 EXPECT_LE(100_us, elapsed);
46 EXPECT_FALSE(shared_state.is_ready());
47 }
48
TEST(FutureImplBaseTest,WaitForReady)49 TEST(FutureImplBaseTest, WaitForReady) {
50 future_shared_state_base shared_state;
51 shared_state.set_exception(
52 std::make_exception_ptr(std::runtime_error("test_message")));
53 auto s = shared_state.wait_for(100_us);
54 EXPECT_EQ(std::future_status::ready, s);
55 EXPECT_TRUE(shared_state.is_ready());
56 }
57
TEST(FutureImplBaseTest,WaitUntil)58 TEST(FutureImplBaseTest, WaitUntil) {
59 future_shared_state_base shared_state;
60 EXPECT_FALSE(shared_state.is_ready());
61 auto start = std::chrono::steady_clock::now();
62 auto s = shared_state.wait_until(std::chrono::system_clock::now() + 100_us);
63 auto elapsed = std::chrono::steady_clock::now() - start;
64 EXPECT_EQ(static_cast<int>(s), static_cast<int>(std::future_status::timeout));
65 EXPECT_LE(100_us, elapsed);
66 EXPECT_FALSE(shared_state.is_ready());
67 }
68
TEST(FutureImplBaseTest,WaitUntilReady)69 TEST(FutureImplBaseTest, WaitUntilReady) {
70 future_shared_state_base shared_state;
71 shared_state.set_exception(
72 std::make_exception_ptr(std::runtime_error("test message")));
73 auto s = shared_state.wait_until(std::chrono::system_clock::now() + 100_us);
74 EXPECT_EQ(static_cast<int>(s), static_cast<int>(std::future_status::ready));
75 EXPECT_TRUE(shared_state.is_ready());
76 }
77
TEST(FutureImplBaseTest,SetExceptionCanBeCalledOnlyOnce)78 TEST(FutureImplBaseTest, SetExceptionCanBeCalledOnlyOnce) {
79 future_shared_state_base shared_state;
80 EXPECT_FALSE(shared_state.is_ready());
81
82 shared_state.set_exception(
83 std::make_exception_ptr(std::runtime_error("test message")));
84 EXPECT_TRUE(shared_state.is_ready());
85 ExpectFutureError(
86 [&] {
87 shared_state.set_exception(
88 std::make_exception_ptr(std::runtime_error("blah")));
89 },
90 std::future_errc::promise_already_satisfied);
91
92 EXPECT_TRUE(shared_state.is_ready());
93 }
94
TEST(FutureImplBaseTest,Abandon)95 TEST(FutureImplBaseTest, Abandon) {
96 future_shared_state_base shared_state;
97 shared_state.abandon();
98 EXPECT_TRUE(shared_state.is_ready());
99 }
100
TEST(FutureImplBaseTest,AbandonReady)101 TEST(FutureImplBaseTest, AbandonReady) {
102 future_shared_state_base shared_state;
103 shared_state.set_exception(
104 std::make_exception_ptr(std::runtime_error("test message")));
105 shared_state.abandon();
106 SUCCEED();
107 EXPECT_TRUE(shared_state.is_ready());
108 }
109
110 // @test Verify that we can create continuations.
TEST(ContinuationVoidTest,Constructor)111 TEST(ContinuationVoidTest, Constructor) {
112 auto functor = [](std::shared_ptr<future_shared_state<void>> const&) {};
113
114 using tested_type = continuation<decltype(functor), void>;
115
116 auto input = std::make_shared<future_shared_state<void>>();
117 auto cont = std::make_shared<tested_type>(std::move(functor), input);
118
119 auto current = cont->input.lock();
120 EXPECT_EQ(input.get(), current.get());
121 }
122
123 /// @test Verify that satisfying the shared state with an exception calls the
124 /// continuation.
TEST(ContinuationVoidTest,SetExceptionCallsContinuation)125 TEST(ContinuationVoidTest, SetExceptionCallsContinuation) {
126 bool called = false;
127 auto functor =
128 [&called](std::shared_ptr<future_shared_state<void>> const& state) {
129 called = true;
130 state->get();
131 };
132
133 auto input = std::make_shared<future_shared_state<void>>();
134 std::shared_ptr<future_shared_state<void>> output =
135 input->make_continuation(input, std::move(functor));
136
137 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
138 input->set_exception(
139 std::make_exception_ptr(std::runtime_error("test message")));
140 EXPECT_TRUE(called);
141 EXPECT_TRUE(output->is_ready());
142 EXPECT_THROW(
143 try { output->get(); } catch (std::runtime_error const& ex) {
144 EXPECT_THAT(ex.what(), HasSubstr("test message"));
145 throw;
146 },
147 std::runtime_error);
148 #else
149 EXPECT_DEATH_IF_SUPPORTED(
150 input->set_exception(
151 std::make_exception_ptr(std::runtime_error("test message"))),
152 "future<void>::get\\(\\) had an exception but exceptions are disabled");
153 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
154 }
155
156 /// @test Verify that satisfying the shared state with a value calls the
157 /// continuation.
TEST(ContinuationVoidTest,SetValueCallsContinuation)158 TEST(ContinuationVoidTest, SetValueCallsContinuation) {
159 bool called = false;
160 auto functor =
161 [&called](std::shared_ptr<future_shared_state<void>> const& state) {
162 called = true;
163 state->get();
164 };
165
166 auto input = std::make_shared<future_shared_state<void>>();
167 std::shared_ptr<future_shared_state<void>> output =
168 input->make_continuation(input, std::move(functor));
169
170 input->set_value();
171 EXPECT_TRUE(called);
172 EXPECT_TRUE(output->is_ready());
173 output->get();
174 SUCCEED();
175 }
176
177 class TestContinuation : public continuation_base {
178 public:
TestContinuation(int * r)179 explicit TestContinuation(int* r) : execute_counter(r) {}
execute()180 void execute() override { (*execute_counter)++; }
181
182 int* execute_counter;
183 };
184
TEST(FutureImplVoid,SetValue)185 TEST(FutureImplVoid, SetValue) {
186 future_shared_state<void> shared_state;
187 EXPECT_FALSE(shared_state.is_ready());
188 shared_state.set_value();
189 EXPECT_TRUE(shared_state.is_ready());
190 shared_state.get();
191 SUCCEED();
192 }
193
TEST(FutureImplVoid,SetValueCanBeCalledOnlyOnce)194 TEST(FutureImplVoid, SetValueCanBeCalledOnlyOnce) {
195 future_shared_state<void> shared_state;
196 EXPECT_FALSE(shared_state.is_ready());
197
198 shared_state.set_value();
199 ExpectFutureError([&] { shared_state.set_value(); },
200 std::future_errc::promise_already_satisfied);
201
202 shared_state.get();
203 SUCCEED();
204 }
205
TEST(FutureImplVoid,GetException)206 TEST(FutureImplVoid, GetException) {
207 future_shared_state<void> shared_state;
208 EXPECT_FALSE(shared_state.is_ready());
209 shared_state.set_exception(
210 std::make_exception_ptr(std::runtime_error("test message")));
211 EXPECT_TRUE(shared_state.is_ready());
212 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
213 EXPECT_THROW(
214 try { shared_state.get(); } catch (std::runtime_error const& ex) {
215 EXPECT_THAT(ex.what(), HasSubstr("test message"));
216 throw;
217 },
218 std::runtime_error);
219 #else
220 EXPECT_DEATH_IF_SUPPORTED(
221 shared_state.get(),
222 "future<void>::get\\(\\) had an exception but exceptions are disabled");
223 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
224 }
225
TEST(FutureImplVoid,Abandon)226 TEST(FutureImplVoid, Abandon) {
227 future_shared_state<void> shared_state;
228 shared_state.abandon();
229 EXPECT_TRUE(shared_state.is_ready());
230 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
231 EXPECT_THROW(
232 try { shared_state.get(); } catch (std::future_error const& ex) {
233 EXPECT_EQ(std::future_errc::broken_promise, ex.code());
234 throw;
235 },
236 std::future_error);
237 #else
238 EXPECT_DEATH_IF_SUPPORTED(
239 shared_state.get(),
240 "future<void>::get\\(\\) had an exception but exceptions are disabled");
241 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
242 }
243
TEST(FutureImplVoid,SetContinuation)244 TEST(FutureImplVoid, SetContinuation) {
245 future_shared_state<void> shared_state;
246 EXPECT_FALSE(shared_state.is_ready());
247
248 int execute_counter = 0;
249 shared_state.set_continuation(
250 absl::make_unique<TestContinuation>(&execute_counter));
251 EXPECT_EQ(0, execute_counter);
252 EXPECT_FALSE(shared_state.is_ready());
253 shared_state.set_value();
254 EXPECT_EQ(1, execute_counter);
255
256 shared_state.get();
257 SUCCEED();
258 }
259
TEST(FutureImplVoid,SetContinuationAlreadySet)260 TEST(FutureImplVoid, SetContinuationAlreadySet) {
261 future_shared_state<void> shared_state;
262 EXPECT_FALSE(shared_state.is_ready());
263
264 int execute_counter = 0;
265 shared_state.set_continuation(
266 absl::make_unique<TestContinuation>(&execute_counter));
267
268 ExpectFutureError(
269 [&] {
270 shared_state.set_continuation(
271 absl::make_unique<TestContinuation>(&execute_counter));
272 },
273 std::future_errc::future_already_retrieved);
274 }
275
TEST(FutureImplVoid,SetContinuationAlreadySatisfied)276 TEST(FutureImplVoid, SetContinuationAlreadySatisfied) {
277 future_shared_state<void> shared_state;
278 EXPECT_FALSE(shared_state.is_ready());
279
280 int execute_counter = 0;
281 shared_state.set_value();
282 EXPECT_EQ(0, execute_counter);
283 shared_state.set_continuation(
284 absl::make_unique<TestContinuation>(&execute_counter));
285 EXPECT_EQ(1, execute_counter);
286
287 shared_state.get();
288 SUCCEED();
289 }
290
TEST(FutureImplVoid,MarkRetrieved)291 TEST(FutureImplVoid, MarkRetrieved) {
292 auto sh = std::make_shared<future_shared_state<void>>();
293 future_shared_state<void>::mark_retrieved(sh);
294 SUCCEED();
295 }
296
TEST(FutureImplVoid,MarkRetrievedCanBeCalledOnlyOnce)297 TEST(FutureImplVoid, MarkRetrievedCanBeCalledOnlyOnce) {
298 auto sh = std::make_shared<future_shared_state<void>>();
299 future_shared_state<void>::mark_retrieved(sh);
300 ExpectFutureError([&] { future_shared_state<void>::mark_retrieved(sh); },
301 std::future_errc::future_already_retrieved);
302 }
303
TEST(FutureImplVoid,MarkRetrievedFailure)304 TEST(FutureImplVoid, MarkRetrievedFailure) {
305 std::shared_ptr<future_shared_state<void>> sh;
306 ExpectFutureError([&] { future_shared_state<void>::mark_retrieved(sh); },
307 std::future_errc::no_state);
308 }
309
TEST(FutureImplInt,SetException)310 TEST(FutureImplInt, SetException) {
311 future_shared_state<int> shared_state;
312 EXPECT_FALSE(shared_state.is_ready());
313
314 shared_state.set_exception(
315 std::make_exception_ptr(std::runtime_error("test message")));
316 EXPECT_TRUE(shared_state.is_ready());
317 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
318 EXPECT_THROW(
319 try { shared_state.get(); } catch (std::runtime_error const& ex) {
320 EXPECT_THAT(ex.what(), HasSubstr("test message"));
321 throw;
322 },
323 std::runtime_error);
324 #else
325 std::cerr << "About to die\n";
326 EXPECT_DEATH_IF_SUPPORTED(
327 shared_state.get(),
328 "future<T>::get\\(\\) had an exception but exceptions are disabled");
329 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
330 }
331
TEST(FutureImplInt,SetValue)332 TEST(FutureImplInt, SetValue) {
333 future_shared_state<int> shared_state;
334 EXPECT_FALSE(shared_state.is_ready());
335 shared_state.set_value(42);
336 EXPECT_TRUE(shared_state.is_ready());
337 EXPECT_EQ(42, shared_state.get());
338 }
339
TEST(FutureImplInt,SetValueCanBeCalledOnlyOnce)340 TEST(FutureImplInt, SetValueCanBeCalledOnlyOnce) {
341 future_shared_state<int> shared_state;
342 EXPECT_FALSE(shared_state.is_ready());
343
344 shared_state.set_value(42);
345 ExpectFutureError([&] { shared_state.set_value(42); },
346 std::future_errc::promise_already_satisfied);
347
348 EXPECT_EQ(42, shared_state.get());
349 }
350
TEST(FutureImplInt,GetException)351 TEST(FutureImplInt, GetException) {
352 future_shared_state<int> shared_state;
353 EXPECT_FALSE(shared_state.is_ready());
354 shared_state.set_exception(
355 std::make_exception_ptr(std::runtime_error("test message")));
356 EXPECT_TRUE(shared_state.is_ready());
357 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
358 EXPECT_THROW(
359 try { shared_state.get(); } catch (std::runtime_error const& ex) {
360 EXPECT_THAT(ex.what(), HasSubstr("test message"));
361 throw;
362 },
363 std::runtime_error);
364 #else
365 EXPECT_DEATH_IF_SUPPORTED(
366 shared_state.get(),
367 "future<T>::get\\(\\) had an exception but exceptions are disabled");
368 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
369 }
370
TEST(FutureImplInt,Abandon)371 TEST(FutureImplInt, Abandon) {
372 future_shared_state<int> shared_state;
373 shared_state.abandon();
374 EXPECT_TRUE(shared_state.is_ready());
375 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
376 EXPECT_THROW(
377 try { shared_state.get(); } catch (std::future_error const& ex) {
378 EXPECT_EQ(std::future_errc::broken_promise, ex.code());
379 throw;
380 },
381 std::future_error);
382 #else
383 EXPECT_DEATH_IF_SUPPORTED(
384 shared_state.get(),
385 "future<T>::get\\(\\) had an exception but exceptions are disabled");
386 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
387 }
388
TEST(FutureImplInt,MarkRetrieved)389 TEST(FutureImplInt, MarkRetrieved) {
390 auto sh = std::make_shared<future_shared_state<int>>();
391 future_shared_state<int>::mark_retrieved(sh);
392 SUCCEED();
393 }
394
TEST(FutureImplInt,MarkRetrievedCanBeCalledOnlyOnce)395 TEST(FutureImplInt, MarkRetrievedCanBeCalledOnlyOnce) {
396 auto sh = std::make_shared<future_shared_state<int>>();
397 future_shared_state<int>::mark_retrieved(sh);
398 ExpectFutureError([&] { future_shared_state<int>::mark_retrieved(sh); },
399 std::future_errc::future_already_retrieved);
400 }
401
TEST(FutureImplInt,MarkRetrievedFailure)402 TEST(FutureImplInt, MarkRetrievedFailure) {
403 std::shared_ptr<future_shared_state<int>> sh;
404 ExpectFutureError([&] { future_shared_state<int>::mark_retrieved(sh); },
405 std::future_errc::no_state);
406 }
407
TEST(FutureImplInt,SetContinuation)408 TEST(FutureImplInt, SetContinuation) {
409 future_shared_state<int> shared_state;
410 EXPECT_FALSE(shared_state.is_ready());
411
412 int execute_counter = 0;
413 shared_state.set_continuation(
414 absl::make_unique<TestContinuation>(&execute_counter));
415 EXPECT_EQ(0, execute_counter);
416 EXPECT_FALSE(shared_state.is_ready());
417 shared_state.set_value(42);
418 EXPECT_EQ(1, execute_counter);
419
420 shared_state.get();
421 SUCCEED();
422 }
423
TEST(FutureImplInt,SetContinuationAlreadySet)424 TEST(FutureImplInt, SetContinuationAlreadySet) {
425 future_shared_state<int> shared_state;
426 EXPECT_FALSE(shared_state.is_ready());
427
428 int execute_counter = 0;
429 shared_state.set_continuation(
430 absl::make_unique<TestContinuation>(&execute_counter));
431 ExpectFutureError(
432 [&] {
433 shared_state.set_continuation(
434 absl::make_unique<TestContinuation>(&execute_counter));
435 },
436 std::future_errc::future_already_retrieved);
437 }
438
TEST(FutureImplInt,SetContinuationAlreadySatisfied)439 TEST(FutureImplInt, SetContinuationAlreadySatisfied) {
440 future_shared_state<int> shared_state;
441 EXPECT_FALSE(shared_state.is_ready());
442
443 int execute_counter = 0;
444 shared_state.set_value(42);
445 EXPECT_EQ(0, execute_counter);
446 shared_state.set_continuation(
447 absl::make_unique<TestContinuation>(&execute_counter));
448 EXPECT_EQ(1, execute_counter);
449
450 EXPECT_EQ(42, shared_state.get());
451 }
452
453 // @test Verify that we can create continuations.
TEST(ContinuationIntTest,Constructor)454 TEST(ContinuationIntTest, Constructor) {
455 auto functor = [](std::shared_ptr<future_shared_state<int>> const&) {};
456
457 using tested_type = continuation<decltype(functor), int>;
458
459 auto input = std::make_shared<future_shared_state<int>>();
460 auto cont = std::make_shared<tested_type>(std::move(functor), input);
461
462 auto current = cont->input.lock();
463 EXPECT_EQ(input.get(), current.get());
464 }
465
466 /// @test Verify that satisfying the shared state with an exception calls the
467 /// continuation.
TEST(ContinuationIntTest,SetExceptionCallsContinuation)468 TEST(ContinuationIntTest, SetExceptionCallsContinuation) {
469 bool called = false;
470 auto functor =
471 [&called](std::shared_ptr<future_shared_state<int>> const& state) {
472 called = true;
473 return 2 * state->get();
474 };
475
476 auto input = std::make_shared<future_shared_state<int>>();
477 std::shared_ptr<future_shared_state<int>> output =
478 input->make_continuation(input, std::move(functor));
479
480 #if GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
481 input->set_exception(
482 std::make_exception_ptr(std::runtime_error("test message")));
483 EXPECT_TRUE(called);
484 EXPECT_TRUE(output->is_ready());
485 EXPECT_THROW(
486 try { output->get(); } catch (std::runtime_error const& ex) {
487 EXPECT_THAT(ex.what(), HasSubstr("test message"));
488 throw;
489 },
490 std::runtime_error);
491 #else
492 EXPECT_DEATH_IF_SUPPORTED(
493 input->set_exception(
494 std::make_exception_ptr(std::runtime_error("test message"))),
495 "future<T>::get\\(\\) had an exception but exceptions are disabled");
496 #endif // GOOGLE_CLOUD_CPP_HAVE_EXCEPTIONS
497 }
498
499 /// @test Verify that satisfying the shared state with a value calls the
500 /// continuation.
TEST(ContinuationIntTest,SetValueCallsContinuation)501 TEST(ContinuationIntTest, SetValueCallsContinuation) {
502 bool called = false;
503 auto functor =
504 [&called](std::shared_ptr<future_shared_state<int>> const& state) {
505 called = true;
506 return 2 * state->get();
507 };
508
509 auto input = std::make_shared<future_shared_state<int>>();
510 std::shared_ptr<future_shared_state<int>> output =
511 input->make_continuation(input, std::move(functor));
512
513 input->set_value(42);
514 EXPECT_TRUE(called);
515 EXPECT_TRUE(output->is_ready());
516 EXPECT_EQ(84, output->get());
517 }
518
TEST(FutureImplNoDefaultConstructor,SetValue)519 TEST(FutureImplNoDefaultConstructor, SetValue) {
520 future_shared_state<NoDefaultConstructor> shared_state;
521 EXPECT_FALSE(shared_state.is_ready());
522
523 shared_state.set_value(NoDefaultConstructor("42"));
524 EXPECT_TRUE(shared_state.is_ready());
525
526 NoDefaultConstructor result = shared_state.get();
527 EXPECT_EQ("42", result.str());
528 }
529
TEST(FutureImplObservable,NeverSet)530 TEST(FutureImplObservable, NeverSet) {
531 Observable::reset_counters();
532 {
533 future_shared_state<Observable> shared_state;
534 EXPECT_FALSE(shared_state.is_ready());
535 EXPECT_EQ(0, Observable::default_constructor());
536 EXPECT_EQ(0, Observable::destructor());
537 }
538 EXPECT_EQ(0, Observable::default_constructor());
539 EXPECT_EQ(0, Observable::destructor());
540 }
541
TEST(FutureImplObservable,SetValue)542 TEST(FutureImplObservable, SetValue) {
543 Observable::reset_counters();
544 {
545 future_shared_state<Observable> shared_state;
546 EXPECT_FALSE(shared_state.is_ready());
547
548 shared_state.set_value(Observable("set value"));
549 EXPECT_EQ(0, Observable::default_constructor());
550 EXPECT_EQ(1, Observable::value_constructor());
551 EXPECT_EQ(0, Observable::copy_constructor());
552 EXPECT_EQ(1, Observable::move_constructor());
553 EXPECT_EQ(0, Observable::copy_assignment());
554 EXPECT_EQ(0, Observable::move_assignment());
555 EXPECT_EQ(1, Observable::destructor());
556 {
557 Observable value = shared_state.get();
558 EXPECT_EQ(0, Observable::default_constructor());
559 EXPECT_EQ(1, Observable::value_constructor());
560 EXPECT_EQ(0, Observable::copy_constructor());
561 EXPECT_EQ(2, Observable::move_constructor());
562 EXPECT_EQ(0, Observable::copy_assignment());
563 EXPECT_EQ(0, Observable::move_assignment());
564 EXPECT_EQ(1, Observable::destructor());
565 }
566 EXPECT_EQ(0, Observable::default_constructor());
567 EXPECT_EQ(1, Observable::value_constructor());
568 EXPECT_EQ(0, Observable::copy_constructor());
569 EXPECT_EQ(2, Observable::move_constructor());
570 EXPECT_EQ(0, Observable::copy_assignment());
571 EXPECT_EQ(0, Observable::move_assignment());
572 EXPECT_EQ(2, Observable::destructor());
573 }
574 EXPECT_EQ(0, Observable::default_constructor());
575 EXPECT_EQ(1, Observable::value_constructor());
576 EXPECT_EQ(0, Observable::copy_constructor());
577 EXPECT_EQ(2, Observable::move_constructor());
578 EXPECT_EQ(0, Observable::copy_assignment());
579 EXPECT_EQ(0, Observable::move_assignment());
580 EXPECT_EQ(3, Observable::destructor());
581 }
582
583 } // namespace
584 } // namespace internal
585 } // namespace GOOGLE_CLOUD_CPP_NS
586 } // namespace cloud
587 } // namespace google
588