|
25 | 25 | #include <future>
|
26 | 26 | #include <sstream>
|
27 | 27 |
|
| 28 | +#include "MockClientImpl.h" |
28 | 29 | #include "PulsarAdminHelper.h"
|
29 | 30 | #include "PulsarFriend.h"
|
30 | 31 | #include "WaitUtils.h"
|
|
36 | 37 | DECLARE_LOG_OBJECT()
|
37 | 38 |
|
38 | 39 | using namespace pulsar;
|
| 40 | +using testing::AtLeast; |
39 | 41 |
|
40 | 42 | static std::string lookupUrl = "pulsar://localhost:6650";
|
41 | 43 | static std::string adminUrl = "http://localhost:8080/";
|
@@ -434,3 +436,68 @@ TEST(ClientTest, testConnectionClose) {
|
434 | 436 | client.close();
|
435 | 437 | }
|
436 | 438 | }
|
| 439 | + |
| 440 | +TEST(ClientTest, testRetryUntilSucceed) { |
| 441 | + auto clientImpl = std::make_shared<MockClientImpl>(lookupUrl); |
| 442 | + constexpr int kFailCount = 3; |
| 443 | + EXPECT_CALL(*clientImpl, getConnection).Times((kFailCount + 1) * 2); |
| 444 | + std::atomic_int count{0}; |
| 445 | + ON_CALL(*clientImpl, getConnection) |
| 446 | + .WillByDefault([&clientImpl, &count](const std::string &topic, size_t index) { |
| 447 | + if (count++ < kFailCount) { |
| 448 | + return GetConnectionFuture::failed(ResultRetryable); |
| 449 | + } |
| 450 | + return clientImpl->getConnectionReal(topic, index); |
| 451 | + }); |
| 452 | + |
| 453 | + auto topic = "client-test-retry-until-succeed"; |
| 454 | + ASSERT_EQ(ResultOk, clientImpl->createProducer(topic).result); |
| 455 | + count = 0; |
| 456 | + ASSERT_EQ(ResultOk, clientImpl->subscribe(topic).result); |
| 457 | + ASSERT_EQ(ResultOk, clientImpl->close()); |
| 458 | +} |
| 459 | + |
| 460 | +TEST(ClientTest, testRetryTimeout) { |
| 461 | + auto clientImpl = |
| 462 | + std::make_shared<MockClientImpl>(lookupUrl, ClientConfiguration().setOperationTimeoutSeconds(2)); |
| 463 | + EXPECT_CALL(*clientImpl, getConnection).Times(AtLeast(2 * 2)); |
| 464 | + ON_CALL(*clientImpl, getConnection).WillByDefault([](const std::string &topic, size_t index) { |
| 465 | + return GetConnectionFuture::failed(ResultRetryable); |
| 466 | + }); |
| 467 | + |
| 468 | + auto topic = "client-test-retry-timeout"; |
| 469 | + { |
| 470 | + MockClientImpl::SyncOpResult result = clientImpl->createProducer(topic); |
| 471 | + ASSERT_EQ(ResultTimeout, result.result); |
| 472 | + ASSERT_TRUE(result.timeMs >= 2000 && result.timeMs < 2100) << "producer: " << result.timeMs << " ms"; |
| 473 | + } |
| 474 | + { |
| 475 | + MockClientImpl::SyncOpResult result = clientImpl->subscribe(topic); |
| 476 | + ASSERT_EQ(ResultTimeout, result.result); |
| 477 | + ASSERT_TRUE(result.timeMs >= 2000 && result.timeMs < 2100) << "consumer: " << result.timeMs << " ms"; |
| 478 | + } |
| 479 | + |
| 480 | + ASSERT_EQ(ResultOk, clientImpl->close()); |
| 481 | +} |
| 482 | + |
| 483 | +TEST(ClientTest, testNoRetry) { |
| 484 | + auto clientImpl = |
| 485 | + std::make_shared<MockClientImpl>(lookupUrl, ClientConfiguration().setOperationTimeoutSeconds(100)); |
| 486 | + EXPECT_CALL(*clientImpl, getConnection).Times(2); |
| 487 | + ON_CALL(*clientImpl, getConnection).WillByDefault([](const std::string &, size_t) { |
| 488 | + return GetConnectionFuture::failed(ResultAuthenticationError); |
| 489 | + }); |
| 490 | + |
| 491 | + auto topic = "client-test-no-retry"; |
| 492 | + { |
| 493 | + MockClientImpl::SyncOpResult result = clientImpl->createProducer(topic); |
| 494 | + ASSERT_EQ(ResultAuthenticationError, result.result); |
| 495 | + ASSERT_TRUE(result.timeMs < 1000) << "producer: " << result.timeMs << " ms"; |
| 496 | + } |
| 497 | + { |
| 498 | + MockClientImpl::SyncOpResult result = clientImpl->subscribe(topic); |
| 499 | + LOG_INFO("It takes " << result.timeMs << " ms to subscribe"); |
| 500 | + ASSERT_EQ(ResultAuthenticationError, result.result); |
| 501 | + ASSERT_TRUE(result.timeMs < 1000) << "consumer: " << result.timeMs << " ms"; |
| 502 | + } |
| 503 | +} |
0 commit comments