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/" ;
@@ -248,7 +250,7 @@ TEST(ClientTest, testWrongListener) {
248
250
249
251
Client client (lookupUrl, ClientConfiguration ().setListenerName (" test" ));
250
252
Producer producer;
251
- ASSERT_EQ (ResultServiceUnitNotReady , client.createProducer (topic, producer));
253
+ ASSERT_EQ (ResultConnectError , client.createProducer (topic, producer));
252
254
ASSERT_EQ (ResultProducerNotInitialized, producer.close ());
253
255
ASSERT_EQ (PulsarFriend::getProducers (client).size (), 0 );
254
256
ASSERT_EQ (ResultOk, client.close ());
@@ -257,7 +259,7 @@ TEST(ClientTest, testWrongListener) {
257
259
// creation of Consumer or Reader could fail with ResultConnectError.
258
260
client = Client (lookupUrl, ClientConfiguration ().setListenerName (" test" ));
259
261
Consumer consumer;
260
- ASSERT_EQ (ResultServiceUnitNotReady , client.subscribe (topic, " sub" , consumer));
262
+ ASSERT_EQ (ResultConnectError , client.subscribe (topic, " sub" , consumer));
261
263
ASSERT_EQ (ResultConsumerNotInitialized, consumer.close ());
262
264
263
265
ASSERT_EQ (PulsarFriend::getConsumers (client).size (), 0 );
@@ -266,7 +268,7 @@ TEST(ClientTest, testWrongListener) {
266
268
client = Client (lookupUrl, ClientConfiguration ().setListenerName (" test" ));
267
269
268
270
Consumer multiTopicsConsumer;
269
- ASSERT_EQ (ResultServiceUnitNotReady ,
271
+ ASSERT_EQ (ResultConnectError ,
270
272
client.subscribe ({topic + " -partition-0" , topic + " -partition-1" , topic + " -partition-2" },
271
273
" sub" , multiTopicsConsumer));
272
274
@@ -278,7 +280,7 @@ TEST(ClientTest, testWrongListener) {
278
280
279
281
// Currently Reader can only read a non-partitioned topic in C++ client
280
282
Reader reader;
281
- ASSERT_EQ (ResultServiceUnitNotReady ,
283
+ ASSERT_EQ (ResultConnectError ,
282
284
client.createReader (topic + " -partition-0" , MessageId::earliest (), {}, reader));
283
285
ASSERT_EQ (ResultConsumerNotInitialized, reader.close ());
284
286
ASSERT_EQ (PulsarFriend::getConsumers (client).size (), 0 );
@@ -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