|
7 | 7 | #include <ydb/core/base/statestorage.h>
|
8 | 8 | #include <ydb/core/kafka_proxy/kafka_messages.h>
|
9 | 9 | #include <ydb/core/kafka_proxy/actors/actors.h>
|
10 |
| -#include <ydb/core/kafka_proxy/actors/kafka_metadata_actor.h> |
11 | 10 | #include <ydb/core/kafka_proxy/actors/kafka_describe_configs_actor.h>
|
| 11 | +#include <ydb/core/kafka_proxy/actors/kafka_fetch_actor.h> |
| 12 | +#include <ydb/core/kafka_proxy/actors/kafka_metadata_actor.h> |
12 | 13 | #include <ydb/core/discovery/discovery.h>
|
13 | 14 |
|
14 | 15 |
|
@@ -87,13 +88,24 @@ TMetarequestTestParams SetupServer(const TString shortTopicName, bool serverless
|
87 | 88 | serverSettings.AppConfig->MutableKafkaProxyConfig()->MutableProxy()->SetPort(FAKE_SERVERLESS_KAFKA_PROXY_PORT);
|
88 | 89 | }
|
89 | 90 | NPersQueue::TTestServer server(serverSettings, true, {}, NActors::NLog::PRI_INFO, pm);
|
| 91 | + server.EnableLogs({NKikimrServices::PERSQUEUE, NKikimrServices::PQ_FETCH_REQUEST}); |
90 | 92 |
|
91 | 93 | server.AnnoyingClient->CreateTopic(fullTopicName, 1);
|
92 | 94 | server.WaitInit(shortTopicName);
|
93 | 95 |
|
94 | 96 | return {std::move(server), kafkaPort, serverSettings.AppConfig->GetKafkaProxyConfig(), fullTopicName};
|
95 | 97 | }
|
96 | 98 |
|
| 99 | +namespace NKafka { |
| 100 | + |
| 101 | +struct TestAccessor { |
| 102 | + static std::unordered_map<TActorId, size_t> GetTopicIndexes(TKafkaFetchActor* actor) { |
| 103 | + return actor->TopicIndexes; |
| 104 | + } |
| 105 | +}; |
| 106 | + |
| 107 | +} |
| 108 | + |
97 | 109 | namespace NKafka::NTests {
|
98 | 110 | Y_UNIT_TEST_SUITE(DiscoveryIsNotBroken) {
|
99 | 111 | void CheckEndpointsInDiscovery(bool withSsl, bool expectKafkaEndpoints) {
|
@@ -277,7 +289,6 @@ namespace NKafka::NTests {
|
277 | 289 | CheckKafkaMetaResponse(runtime, kafkaPort);
|
278 | 290 | }
|
279 | 291 |
|
280 |
| - |
281 | 292 | Y_UNIT_TEST(DiscoveryResponsesWithError) {
|
282 | 293 | auto [server, kafkaPort, config, topicName] = SetupServer("topic1");
|
283 | 294 |
|
@@ -467,6 +478,77 @@ namespace NKafka::NTests {
|
467 | 478 | }
|
468 | 479 | }
|
469 | 480 |
|
| 481 | + Y_UNIT_TEST_SUITE(FetchActorTests) { |
| 482 | + std::pair<TActorId, NKafka::TKafkaFetchActor*> CreateFetchActor( |
| 483 | + const TActorId& edge, const TString& topic, auto* runtime, const auto& kafkaConfig |
| 484 | + ) { |
| 485 | + TFetchRequestData::TPtr request = std::make_shared<TFetchRequestData>(); |
| 486 | + request->MaxBytes = 10000; |
| 487 | + request->MaxWaitMs = 1000; |
| 488 | + request->Topics.resize(1); |
| 489 | + request->Topics[0].Topic = topic; |
| 490 | + request->Topics[0].Partitions.resize(1); |
| 491 | + request->Topics[0].Partitions[0].Partition = 0; |
| 492 | + request->Topics[0].Partitions[0].PartitionMaxBytes = 10000; |
| 493 | + |
| 494 | + auto context = std::make_shared<TContext>(kafkaConfig); |
| 495 | + context->ConnectionId = edge; |
| 496 | + context->DatabasePath = "/Root"; |
| 497 | + context->ResourceDatabasePath = "/Root"; |
| 498 | + context->UserToken = new NACLib::TUserToken("root@builtin", {}); |
| 499 | + |
| 500 | + auto* actor = new NKafka::TKafkaFetchActor(context, 1, TMessagePtr<TFetchRequestData>(std::make_shared<TBuffer>(), request)); |
| 501 | + TActorId actorId = runtime->Register(actor); |
| 502 | + runtime->EnableScheduleForActor(actorId); |
| 503 | + return {actorId, actor}; |
| 504 | + } |
| 505 | + |
| 506 | + Y_UNIT_TEST(FetchWithNoneData) { |
| 507 | + auto [server, kafkaPort, config, topicName] = SetupServer("topic1"); |
| 508 | + |
| 509 | + auto* runtime = server.GetRuntime(); |
| 510 | + auto edge = runtime->AllocateEdgeActor(); |
| 511 | + |
| 512 | + CreateFetchActor(edge, {NKikimr::JoinPath({"/Root/PQ/", topicName})}, runtime, config); |
| 513 | + |
| 514 | + TAutoPtr<IEventHandle> handle; |
| 515 | + auto* ev = runtime->GrabEdgeEvent<TEvKafka::TEvResponse>(handle); |
| 516 | + UNIT_ASSERT(ev); |
| 517 | + auto response = dynamic_cast<TFetchResponseData*>(ev->Response.get()); |
| 518 | + |
| 519 | + UNIT_ASSERT_VALUES_EQUAL(response->ErrorCode, static_cast<TKafkaInt16>(EKafkaErrors::NONE_ERROR)); |
| 520 | + UNIT_ASSERT_VALUES_EQUAL(response->Responses.size(), 1); |
| 521 | + UNIT_ASSERT_VALUES_EQUAL(response->Responses[0].Partitions.size(), 1); |
| 522 | + UNIT_ASSERT_VALUES_EQUAL(response->Responses[0].Partitions[0].ErrorCode, static_cast<TKafkaInt16>(EKafkaErrors::NONE_ERROR)); |
| 523 | + } |
| 524 | + |
| 525 | + Y_UNIT_TEST(FetchWithTimeout) { |
| 526 | + auto [server, kafkaPort, config, topicName] = SetupServer("topic1"); |
| 527 | + |
| 528 | + auto* runtime = server.GetRuntime(); |
| 529 | + auto edge = runtime->AllocateEdgeActor(); |
| 530 | + |
| 531 | + auto [actorId, actor] = CreateFetchActor(edge, {NKikimr::JoinPath({"/Root/PQ/", topicName})}, runtime, config); |
| 532 | + Sleep(TDuration::MilliSeconds(100)); // wait actor willbe created |
| 533 | + |
| 534 | + // emulate pipe error |
| 535 | + auto topicIndexes = TestAccessor::GetTopicIndexes(actor); |
| 536 | + UNIT_ASSERT(topicIndexes.size() == 1); |
| 537 | + auto fetchActorId = topicIndexes.begin()->first; |
| 538 | + runtime->Send(fetchActorId, fetchActorId, new TEvents::TEvWakeup(1000)); |
| 539 | + |
| 540 | + TAutoPtr<IEventHandle> handle; |
| 541 | + auto* ev = runtime->GrabEdgeEvent<TEvKafka::TEvResponse>(handle); |
| 542 | + UNIT_ASSERT(ev); |
| 543 | + auto response = dynamic_cast<TFetchResponseData*>(ev->Response.get()); |
| 544 | + |
| 545 | + UNIT_ASSERT_VALUES_EQUAL(response->ErrorCode, static_cast<TKafkaInt16>(EKafkaErrors::NONE_ERROR)); |
| 546 | + UNIT_ASSERT_VALUES_EQUAL(response->Responses.size(), 1); |
| 547 | + UNIT_ASSERT_VALUES_EQUAL(response->Responses[0].Partitions.size(), 1); |
| 548 | + UNIT_ASSERT_VALUES_EQUAL(response->Responses[0].Partitions[0].ErrorCode, static_cast<TKafkaInt16>(EKafkaErrors::NONE_ERROR)); |
| 549 | + } |
| 550 | + } |
| 551 | + |
470 | 552 | Y_UNIT_TEST_SUITE(RequestUtilityActors) {
|
471 | 553 | Y_UNIT_TEST(DescribeConfigs) {
|
472 | 554 | auto [server, kafkaPort, config, topicName] = SetupServer("topic1");
|
|
0 commit comments