123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #include <library/cpp/testing/unittest/registar.h>
- #include "client.h"
- #include "http_code_extractor.h"
- #include <library/cpp/messagebus/rain_check/test/ut/test.h>
- #include <library/cpp/messagebus/test/helper/fixed_port.h>
- #include <library/cpp/http/io/stream.h>
- #include <library/cpp/neh/rpc.h>
- #include <util/generic/cast.h>
- #include <util/generic/ptr.h>
- #include <util/generic/strbuf.h>
- #include <util/generic/string.h>
- #include <util/generic/vector.h>
- #include <util/network/ip.h>
- #include <util/stream/str.h>
- #include <util/string/printf.h>
- #include <util/system/defaults.h>
- #include <util/system/yassert.h>
- #include <cstdlib>
- #include <utility>
- using namespace NRainCheck;
- using namespace NBus::NTest;
- namespace {
- class THttpClientEnv: public TTestEnvTemplate<THttpClientEnv> {
- public:
- THttpClientService HttpClientService;
- };
- const TString TEST_SERVICE = "test-service";
- const TString TEST_GET_PARAMS = "p=GET";
- const TString TEST_POST_PARAMS = "p=POST";
- const TString TEST_POST_HEADERS = "Content-Type: application/json\r\n";
- const TString TEST_GET_RECV = "GET was ok.";
- const TString TEST_POST_RECV = "POST was ok.";
- TString BuildServiceLocation(ui32 port) {
- return Sprintf("http://*:%" PRIu32 "/%s", port, TEST_SERVICE.data());
- }
- TString BuildPostServiceLocation(ui32 port) {
- return Sprintf("post://*:%" PRIu32 "/%s", port + 1, TEST_SERVICE.data());
- }
- TString BuildGetTestRequest(ui32 port) {
- return BuildServiceLocation(port) + "?" + TEST_GET_PARAMS;
- }
- class TSimpleServer {
- public:
- inline void ServeRequest(const NNeh::IRequestRef& req) {
- NNeh::TData response;
- if (req->Data() == TEST_GET_PARAMS) {
- response.assign(TEST_GET_RECV.begin(), TEST_GET_RECV.end());
- } else {
- response.assign(TEST_POST_RECV.begin(), TEST_POST_RECV.end());
- }
- req->SendReply(response);
- }
- };
- NNeh::IServicesRef RunServer(ui32 port, TSimpleServer& server) {
- NNeh::IServicesRef runner = NNeh::CreateLoop();
- runner->Add(BuildServiceLocation(port), server);
- runner->Add(BuildPostServiceLocation(port), server);
- try {
- const int THR_POOL_SIZE = 2;
- runner->ForkLoop(THR_POOL_SIZE);
- } catch (...) {
- Y_ABORT("Can't run server: %s", CurrentExceptionMessage().data());
- }
- return runner;
- }
- enum ERequestType {
- RT_HTTP_GET = 0,
- RT_HTTP_POST = 1
- };
- using TTaskParam = std::pair<TIpPort, ERequestType>;
- class THttpClientTask: public ISimpleTask {
- public:
- THttpClientTask(THttpClientEnv* env, TTaskParam param)
- : Env(env)
- , ServerPort(param.first)
- , ReqType(param.second)
- {
- }
- TContinueFunc Start() override {
- switch (ReqType) {
- case RT_HTTP_GET: {
- TString getRequest = BuildGetTestRequest(ServerPort);
- for (size_t i = 0; i < 3; ++i) {
- Requests.push_back(new THttpFuture());
- Env->HttpClientService.Send(getRequest, Requests[i].Get());
- }
- break;
- }
- case RT_HTTP_POST: {
- TString servicePath = BuildPostServiceLocation(ServerPort);
- TStringInput headersText(TEST_POST_HEADERS);
- THttpHeaders headers(&headersText);
- for (size_t i = 0; i < 3; ++i) {
- Requests.push_back(new THttpFuture());
- Env->HttpClientService.SendPost(servicePath, TEST_POST_PARAMS, headers, Requests[i].Get());
- }
- break;
- }
- }
- return &THttpClientTask::GotReplies;
- }
- TContinueFunc GotReplies() {
- const TString& TEST_OK_RECV = (ReqType == RT_HTTP_GET) ? TEST_GET_RECV : TEST_POST_RECV;
- for (size_t i = 0; i < Requests.size(); ++i) {
- UNIT_ASSERT_EQUAL(Requests[i]->GetHttpCode(), 200);
- UNIT_ASSERT_EQUAL(Requests[i]->GetResponseBody(), TEST_OK_RECV);
- }
- Env->TestSync.CheckAndIncrement(0);
- return nullptr;
- }
- THttpClientEnv* const Env;
- const TIpPort ServerPort;
- const ERequestType ReqType;
- TVector<TSimpleSharedPtr<THttpFuture>> Requests;
- };
- } // anonymous namespace
- Y_UNIT_TEST_SUITE(RainCheckHttpClient) {
- static const TIpPort SERVER_PORT = 4000;
- Y_UNIT_TEST(Simple) {
- // TODO: randomize port
- if (!IsFixedPortTestAllowed()) {
- return;
- }
- TSimpleServer server;
- NNeh::IServicesRef runner = RunServer(SERVER_PORT, server);
- THttpClientEnv env;
- TIntrusivePtr<TSimpleTaskRunner> task = env.SpawnTask<THttpClientTask>(TTaskParam(SERVER_PORT, RT_HTTP_GET));
- env.TestSync.WaitForAndIncrement(1);
- }
- Y_UNIT_TEST(SimplePost) {
- // TODO: randomize port
- if (!IsFixedPortTestAllowed()) {
- return;
- }
- TSimpleServer server;
- NNeh::IServicesRef runner = RunServer(SERVER_PORT, server);
- THttpClientEnv env;
- TIntrusivePtr<TSimpleTaskRunner> task = env.SpawnTask<THttpClientTask>(TTaskParam(SERVER_PORT, RT_HTTP_POST));
- env.TestSync.WaitForAndIncrement(1);
- }
- Y_UNIT_TEST(HttpCodeExtraction) {
- // Find "request failed(" string, then copy len("HTTP/1.X NNN") chars and try to convert NNN to HTTP code.
- #define CHECK_VALID_LINE(line, code) \
- UNIT_ASSERT_NO_EXCEPTION(TryGetHttpCodeFromErrorDescription(line)); \
- UNIT_ASSERT(!!TryGetHttpCodeFromErrorDescription(line)); \
- UNIT_ASSERT_EQUAL(*TryGetHttpCodeFromErrorDescription(line), code)
- CHECK_VALID_LINE(TStringBuf("library/cpp/neh/http.cpp:<LINE>: request failed(HTTP/1.0 200 Some random message"), 200);
- CHECK_VALID_LINE(TStringBuf("library/cpp/neh/http.cpp:<LINE>: request failed(HTTP/1.0 404 Some random message"), 404);
- CHECK_VALID_LINE(TStringBuf("request failed(HTTP/1.0 100 Some random message"), 100);
- CHECK_VALID_LINE(TStringBuf("request failed(HTTP/1.0 105)"), 105);
- CHECK_VALID_LINE(TStringBuf("request failed(HTTP/1.1 2004 Some random message"), 200);
- #undef CHECK_VALID_LINE
- #define CHECK_INVALID_LINE(line) \
- UNIT_ASSERT_NO_EXCEPTION(TryGetHttpCodeFromErrorDescription(line)); \
- UNIT_ASSERT(!TryGetHttpCodeFromErrorDescription(line))
- CHECK_INVALID_LINE(TStringBuf("library/cpp/neh/http.cpp:<LINE>: request failed(HTTP/1.1 1 Some random message"));
- CHECK_INVALID_LINE(TStringBuf("request failed(HTTP/1.0 asdf Some random message"));
- CHECK_INVALID_LINE(TStringBuf("HTTP/1.0 200 Some random message"));
- CHECK_INVALID_LINE(TStringBuf("request failed(HTTP/1.0 2x00 Some random message"));
- CHECK_INVALID_LINE(TStringBuf("HTTP/1.0 200 Some random message"));
- CHECK_INVALID_LINE(TStringBuf("HTTP/1.0 200"));
- CHECK_INVALID_LINE(TStringBuf("request failed(HTTP/1.1 3334 Some random message"));
- #undef CHECK_INVALID_LINE
- }
- }
|