diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2023-08-18 22:17:31 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2023-08-18 22:59:16 +0300 |
commit | 05634a3231f2bd3722106c9cb637538b96a9bcc3 (patch) | |
tree | bdeec6536aec79360d0e1f5afc47903079240d6d /library/cpp/http | |
parent | 03a6db9a9b3a7fdc7664770e0c91102dabe96a04 (diff) | |
download | ydb-05634a3231f2bd3722106c9cb637538b96a9bcc3.tar.gz |
Intermediate changes
Diffstat (limited to 'library/cpp/http')
-rw-r--r-- | library/cpp/http/server/http_ut.cpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/library/cpp/http/server/http_ut.cpp b/library/cpp/http/server/http_ut.cpp index 824741f6db..ecebca5a2b 100644 --- a/library/cpp/http/server/http_ut.cpp +++ b/library/cpp/http/server/http_ut.cpp @@ -738,4 +738,122 @@ Y_UNIT_TEST_SUITE(THttpServerTest) { } } } + + class TShooter { + public: + struct TCounters { + public: + TCounters() = default; + TCounters(const TCounters& other) + : Fail(other.Fail.load()) + , Success(other.Success.load()) + { + } + public: + std::atomic<size_t> Fail = 0; + std::atomic<size_t> Success = 0; + }; + public: + TShooter(size_t threadCount, ui16 port) + : Counters_(threadCount) + { + for (size_t i = 0; i < threadCount; ++i) { + auto func = [i, port, this] () { + for (;;) { + try { + TTestRequest r(port); + r.KeepAliveConnection = true; + for (;;) { + if (Stopped_.load()) { + return; + } + r.Execute(); + Counters_[i].Success++; + } + } catch (TSystemError& e) { + UNIT_ASSERT_C(e.Status() == ECONNRESET || e.Status() == ECONNREFUSED, CurrentExceptionMessage()); + Counters_[i].Fail++; + } catch (...) { + UNIT_ASSERT_C(false, CurrentExceptionMessage()); + } + } + }; + + Threads_.push_back(SystemThreadFactory()->Run(func)); + } + } + + void Stop() { + Stopped_.store(true); + for (auto& thread : Threads_) { + thread->Join(); + } + } + + void WaitProgress() const { + auto snapshot = Counters_; + for (;;) { + size_t haveProgress = 0; + for (size_t i = 0; i < Counters_.size(); ++i) { + haveProgress += (Counters_[i].Fail.load() + Counters_[i].Success.load()) > (snapshot[i].Fail + snapshot[i].Success); + } + + if (haveProgress == Counters_.size()) { + return; + } + Sleep(TDuration::MilliSeconds(1)); + } + } + + const auto& GetCounters() const { + return Counters_; + } + + ~TShooter() { + Stop(); + } + private: + TVector<THolder<IThreadFactory::IThread>> Threads_; + std::atomic<bool> Stopped_ = false; + TVector<TCounters> Counters_; + }; + + Y_UNIT_TEST(TestStartStop) { + TPortManager pm; + const ui16 port = pm.GetPort(); + + const size_t threadCount = 5; + TShooter shooter(threadCount, port); + + TString res = TestData(); + TEchoServer serverImpl(res); + THttpServer server(&serverImpl, THttpServer::TOptions(port).EnableKeepAlive(true)); + for (size_t i = 0; i < 100; ++i) { + UNIT_ASSERT(server.Start()); + shooter.WaitProgress(); + + { + auto before = shooter.GetCounters(); + shooter.WaitProgress(); + auto after = shooter.GetCounters(); + for (size_t i = 0; i < before.size(); ++i) { + UNIT_ASSERT(before[i].Success < after[i].Success); + UNIT_ASSERT(before[i].Fail == after[i].Fail); + } + } + + server.Stop(); + shooter.WaitProgress(); + { + auto before = shooter.GetCounters(); + shooter.WaitProgress(); + auto after = shooter.GetCounters(); + for (size_t i = 0; i < before.size(); ++i) { + UNIT_ASSERT(before[i].Success == after[i].Success); + UNIT_ASSERT(before[i].Fail < after[i].Fail); + } + } + } + + } } |