1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault;
32 
33 #include "mongo/platform/basic.h"
34 
35 #include "boost/optional.hpp"
36 
37 #include "mongo/db/service_context_noop.h"
38 #include "mongo/transport/service_executor_adaptive.h"
39 #include "mongo/transport/service_executor_synchronous.h"
40 #include "mongo/transport/service_executor_task_names.h"
41 #include "mongo/unittest/unittest.h"
42 #include "mongo/util/log.h"
43 #include "mongo/util/scopeguard.h"
44 
45 #include <asio.hpp>
46 
47 namespace mongo {
48 namespace {
49 using namespace transport;
50 
51 struct TestOptions : public ServiceExecutorAdaptive::Options {
reservedThreadsmongo::__anondd0025430111::TestOptions52     int reservedThreads() const final {
53         return 1;
54     }
55 
workerThreadRunTimemongo::__anondd0025430111::TestOptions56     Milliseconds workerThreadRunTime() const final {
57         return Milliseconds{1000};
58     }
59 
runTimeJittermongo::__anondd0025430111::TestOptions60     int runTimeJitter() const final {
61         return 0;
62     }
63 
stuckThreadTimeoutmongo::__anondd0025430111::TestOptions64     Milliseconds stuckThreadTimeout() const final {
65         return Milliseconds{100};
66     }
67 
maxQueueLatencymongo::__anondd0025430111::TestOptions68     Microseconds maxQueueLatency() const final {
69         return duration_cast<Microseconds>(Milliseconds{5});
70     }
71 
idlePctThresholdmongo::__anondd0025430111::TestOptions72     int idlePctThreshold() const final {
73         return 0;
74     }
75 
recursionLimitmongo::__anondd0025430111::TestOptions76     int recursionLimit() const final {
77         return 0;
78     }
79 };
80 
81 class ServiceExecutorAdaptiveFixture : public unittest::Test {
82 protected:
setUp()83     void setUp() override {
84         auto scOwned = stdx::make_unique<ServiceContextNoop>();
85         setGlobalServiceContext(std::move(scOwned));
86         asioIOCtx = std::make_shared<asio::io_context>();
87 
88         auto configOwned = stdx::make_unique<TestOptions>();
89         executorConfig = configOwned.get();
90         executor = stdx::make_unique<ServiceExecutorAdaptive>(
91             getGlobalServiceContext(), asioIOCtx, std::move(configOwned));
92     }
93 
94     ServiceExecutorAdaptive::Options* executorConfig;
95     std::unique_ptr<ServiceExecutorAdaptive> executor;
96     std::shared_ptr<asio::io_context> asioIOCtx;
97 };
98 
99 class ServiceExecutorSynchronousFixture : public unittest::Test {
100 protected:
setUp()101     void setUp() override {
102         auto scOwned = stdx::make_unique<ServiceContextNoop>();
103         setGlobalServiceContext(std::move(scOwned));
104 
105         executor = stdx::make_unique<ServiceExecutorSynchronous>(getGlobalServiceContext());
106     }
107 
108     std::unique_ptr<ServiceExecutorSynchronous> executor;
109 };
110 
scheduleBasicTask(ServiceExecutor * exec,bool expectSuccess)111 void scheduleBasicTask(ServiceExecutor* exec, bool expectSuccess) {
112     stdx::condition_variable cond;
113     stdx::mutex mutex;
114     auto task = [&cond, &mutex] {
115         stdx::unique_lock<stdx::mutex> lk(mutex);
116         cond.notify_all();
117     };
118 
119     stdx::unique_lock<stdx::mutex> lk(mutex);
120     auto status = exec->schedule(
121         std::move(task), ServiceExecutor::kEmptyFlags, ServiceExecutorTaskName::kSSMStartSession);
122     if (expectSuccess) {
123         ASSERT_OK(status);
124         cond.wait(lk);
125     } else {
126         ASSERT_NOT_OK(status);
127     }
128 }
129 
TEST_F(ServiceExecutorAdaptiveFixture,BasicTaskRuns)130 TEST_F(ServiceExecutorAdaptiveFixture, BasicTaskRuns) {
131     ASSERT_OK(executor->start());
132     auto guard = MakeGuard([this] { ASSERT_OK(executor->shutdown(Milliseconds{500})); });
133 
134     scheduleBasicTask(executor.get(), true);
135 }
136 
TEST_F(ServiceExecutorAdaptiveFixture,ScheduleFailsBeforeStartup)137 TEST_F(ServiceExecutorAdaptiveFixture, ScheduleFailsBeforeStartup) {
138     scheduleBasicTask(executor.get(), false);
139 }
140 
TEST_F(ServiceExecutorSynchronousFixture,BasicTaskRuns)141 TEST_F(ServiceExecutorSynchronousFixture, BasicTaskRuns) {
142     ASSERT_OK(executor->start());
143     auto guard = MakeGuard([this] { ASSERT_OK(executor->shutdown(Milliseconds{500})); });
144 
145     scheduleBasicTask(executor.get(), true);
146 }
147 
TEST_F(ServiceExecutorSynchronousFixture,ScheduleFailsBeforeStartup)148 TEST_F(ServiceExecutorSynchronousFixture, ScheduleFailsBeforeStartup) {
149     scheduleBasicTask(executor.get(), false);
150 }
151 
152 
153 }  // namespace
154 }  // namespace mongo
155