1 /*
2 Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "gmock/gmock.h"
26 #include "router_component_test.h"
27 #include "tcp_port_pool.h"
28
29 using testing::StartsWith;
30
31 class RouterConfigTest : public RouterComponentTest {
32 protected:
33 TcpPortPool port_pool_;
34 };
35
36 // Bug #25800863 WRONG ERRORMSG IF DIRECTORY IS PROVIDED AS CONFIGFILE
TEST_F(RouterConfigTest,RoutingDirAsMainConfigDirectory)37 TEST_F(RouterConfigTest, RoutingDirAsMainConfigDirectory) {
38 TempDirectory config_dir;
39
40 // launch the router giving directory instead of config_name
41 auto &router = launch_router({"-c", config_dir.name()}, EXIT_FAILURE);
42
43 check_exit_code(router, EXIT_FAILURE);
44
45 EXPECT_TRUE(router.expect_output(
46 "The configuration file '" + config_dir.name() +
47 "' is expected to be a readable file, but it is a directory"));
48 }
49
50 // Bug #25800863 WRONG ERRORMSG IF DIRECTORY IS PROVIDED AS CONFIGFILE
TEST_F(RouterConfigTest,RoutingDirAsExtendedConfigDirectory)51 TEST_F(RouterConfigTest, RoutingDirAsExtendedConfigDirectory) {
52 const auto router_port = port_pool_.get_next_available();
53 const auto server_port = port_pool_.get_next_available();
54
55 const std::string routing_section =
56 "[routing:basic]\n"
57 "bind_port = " +
58 std::to_string(router_port) +
59 "\n"
60 "mode = read-write\n"
61 "destinations = 127.0.0.1:" +
62 std::to_string(server_port) + "\n";
63
64 TempDirectory conf_dir("conf");
65 TempDirectory extra_conf_dir;
66
67 std::string conf_file = create_config_file(conf_dir.name(), routing_section);
68
69 // launch the router giving directory instead of an extra config name
70 auto &router = launch_router({"-c", conf_file, "-a", extra_conf_dir.name()},
71 EXIT_FAILURE);
72
73 check_exit_code(router, EXIT_FAILURE);
74
75 EXPECT_TRUE(router.expect_output(
76 "The configuration file '" + extra_conf_dir.name() +
77 "' is expected to be a readable file, but it is a directory"));
78 }
79
TEST_F(RouterConfigTest,IsExceptionThrownWhenAddTwiceTheSameSectionWithoutKey)80 TEST_F(RouterConfigTest,
81 IsExceptionThrownWhenAddTwiceTheSameSectionWithoutKey) {
82 TempDirectory conf_dir("conf");
83 const std::string conf_file =
84 create_config_file(conf_dir.name(), "[section1]\n[section1]\n");
85
86 // run the router and wait for it to exit
87 auto &router = launch_router({"-c", conf_file}, EXIT_FAILURE);
88 check_exit_code(router, EXIT_FAILURE);
89
90 EXPECT_THAT(
91 router.get_full_output(),
92 StartsWith(
93 "Error: Configuration error: Section 'section1' already exists"));
94 }
95
TEST_F(RouterConfigTest,IsExceptionThrownWhenAddTwiceTheSameSectionWithKey)96 TEST_F(RouterConfigTest, IsExceptionThrownWhenAddTwiceTheSameSectionWithKey) {
97 TempDirectory conf_dir("conf");
98 const std::string conf_file =
99 create_config_file(conf_dir.name(), "[section1:key1]\n[section1:key1]\n");
100
101 // run the router and wait for it to exit
102 auto &router = launch_router({"-c", conf_file}, EXIT_FAILURE);
103 check_exit_code(router, EXIT_FAILURE);
104
105 EXPECT_THAT(router.get_full_output(),
106 StartsWith("Error: Configuration error: Section 'section1:key1' "
107 "already exists"));
108 }
109
TEST_F(RouterConfigTest,IsExceptionThrownWhenTheSameOptionsTwiceInASingleSection)110 TEST_F(RouterConfigTest,
111 IsExceptionThrownWhenTheSameOptionsTwiceInASingleSection) {
112 TempDirectory conf_dir("conf");
113 const std::string conf_file = create_config_file(
114 conf_dir.name(), "[section1]\ndynamic_state=a\ndynamic_state=b\n");
115
116 // run the router and wait for it to exit
117 auto &router = launch_router({"-c", conf_file}, EXIT_FAILURE);
118 check_exit_code(router, EXIT_FAILURE);
119
120 EXPECT_THAT(router.get_full_output(),
121 StartsWith("Error: Configuration error: Option 'dynamic_state' "
122 "already defined."));
123 }
124
125 #ifdef _WIN32
isRouterServiceInstalled()126 static bool isRouterServiceInstalled() {
127 SC_HANDLE service, scm;
128 bool result = false;
129
130 if ((scm = OpenSCManager(0, 0, SC_MANAGER_ENUMERATE_SERVICE))) {
131 if ((service = OpenService(scm, "MySQLRouter", SERVICE_QUERY_STATUS))) {
132 CloseServiceHandle(service);
133 result = true;
134 }
135 CloseServiceHandle(scm);
136 }
137 return result;
138 }
139
140 /**
141 * ensure that the router exits with proper error when launched with --service
142 * and the service is not installed
143 */
TEST_F(RouterConfigTest,IsErrorReturnedWhenServiceDoesNotExist)144 TEST_F(RouterConfigTest, IsErrorReturnedWhenServiceDoesNotExist) {
145 // first we need to make sure the service really is not installed on the
146 // system that the test is running on. If it is we can't do much about it and
147 // we just skip testing.
148 if (!isRouterServiceInstalled()) {
149 TempDirectory conf_dir("conf");
150 const std::string conf_file =
151 create_config_file(conf_dir.name(), "[keepalive]\ninterval = 60\n");
152
153 // run the router and wait for it to exit
154 auto &router = launch_router({"-c", conf_file, "--service"}, EXIT_FAILURE);
155 check_exit_code(router, EXIT_FAILURE);
156
157 EXPECT_THAT(router.get_full_output(),
158 StartsWith("ERROR: Could not find service 'MySQLRouter'!\n"
159 "Use --install-service or --install-service-manual "
160 "option to install the service first.\n"));
161 }
162 }
163 #endif // _WIN32
164
main(int argc,char * argv[])165 int main(int argc, char *argv[]) {
166 init_windows_sockets();
167 ProcessManager::set_origin(Path(argv[0]).dirname());
168 ::testing::InitGoogleTest(&argc, argv);
169 return RUN_ALL_TESTS();
170 }
171