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