2
Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; version 2 of the
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
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21
2
-- vim:sw=4:noexpandtab
84
64
local MYSQL_DB = os.getenv("MYSQL_DB") or "test"
85
65
local MYSQL_TEST_BIN = os.getenv("MYSQL_TEST_BIN") or "mysqltest"
86
66
local MYSQL_CLIENT_BIN = os.getenv("MYSQL_CLIENT_BIN") or "mysql"
87
local TESTS_REGEX = os.getenv("TESTS_REGEX")
90
69
-- Global variables that can be referenced from .options files
92
71
-- TODO : add HOST variables for MASTER, SLAVE, CHAIN
93
function get_port_base()
94
local port_base_start = os.getenv("MYSQL_PROXY_START_PORT") or 32768
95
local port_base_end = os.getenv("MYSQL_PROXY_END_PORT") or 65535
96
local port_interval = 64 -- let's take the base port in steps of ...
97
local range = port_base_end - port_base_start - port_interval
98
math.randomseed(posix.getpid())
99
local rand = math.floor(math.random() * (math.ceil(range / port_interval)))
100
local port_base = port_base_start + (rand * port_interval)
102
print(("... using tcp-port = %d as start port"):format(port_base))
106
local port_base = get_port_base()
108
PROXY_HOST = os.getenv("PROXY_HOST") or "127.0.0.1"
109
PROXY_PORT = os.getenv("PROXY_PORT") or tostring(port_base + 0)
110
PROXY_MASTER_PORT = os.getenv("PROXY_MASTER_PORT") or tostring(port_base + 10)
111
PROXY_SLAVE_PORT = os.getenv("PROXY_SLAVE_PORT") or tostring(port_base + 20)
112
PROXY_CHAIN_PORT = os.getenv("PROXY_CHAIN_PORT") or tostring(port_base + 30)
113
ADMIN_PORT = os.getenv("ADMIN_PORT") or tostring(port_base + 15)
114
ADMIN_MASTER_PORT = os.getenv("ADMIN_MASTER_PORT") or tostring(port_base + 25)
115
ADMIN_SLAVE_PORT = os.getenv("ADMIN_SLAVE_PORT") or tostring(port_base + 35)
116
ADMIN_CHAIN_PORT = os.getenv("ADMIN_CHAIN_PORT") or tostring(port_base + 45)
117
ADMIN_USER = os.getenv("ADMIN_USER") or "root"
118
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD") or ""
119
ADMIN_DEFAULT_SCRIPT_FILENAME = os.getenv("ADMIN_DEFAULT_SCRIPT_FILENAME") or ""
72
PROXY_HOST = os.getenv("PROXY_HOST") or "127.0.0.1"
73
PROXY_PORT = os.getenv("PROXY_PORT") or "14040"
74
PROXY_MASTER_PORT = os.getenv("PROXY_MASTER_PORT") or "14050"
75
PROXY_SLAVE_PORT = os.getenv("PROXY_SLAVE_PORT") or "14060"
76
PROXY_CHAIN_PORT = os.getenv("PROXY_CHAIN_PORT") or "14070"
77
ADMIN_PORT = os.getenv("ADMIN_PORT") or "14041"
78
ADMIN_MASTER_PORT = os.getenv("ADMIN_MASTER_PORT") or "14051"
79
ADMIN_SLAVE_PORT = os.getenv("ADMIN_SLAVE_PORT") or "14061"
80
ADMIN_CHAIN_PORT = os.getenv("ADMIN_CHAIN_PORT") or "14071"
120
81
-- local PROXY_TMP_LUASCRIPT = os.getenv("PROXY_TMP_LUASCRIPT") or "/tmp/proxy.tmp.lua"
122
83
local srcdir = os.getenv("srcdir") or testdir .. "/"
123
local top_builddir = os.getenv("top_builddir") or testdir .. "/../"
124
local builddir = os.getenv("builddir") or testdir .. "/" -- same as srcdir by default
84
local builddir = os.getenv("builddir") or testdir .. "/../"
126
86
local PROXY_TRACE = os.getenv("PROXY_TRACE") or "" -- use it to inject strace or valgrind
127
87
local PROXY_PARAMS = os.getenv("PROXY_PARAMS") or "" -- extra params
128
local PROXY_BINPATH = os.getenv("PROXY_BINPATH") or top_builddir .. "/src/mysql-proxy"
129
PROXY_LIBPATH = os.getenv("PROXY_LIBPATH") or top_builddir .. "/plugins/"
88
local PROXY_BINPATH = os.getenv("PROXY_BINPATH") or builddir .. "/src/mysql-proxy"
89
PROXY_LIBPATH = os.getenv("PROXY_LIBPATH") or builddir .. "/plugins/"
131
91
local COVERAGE_LCOV = os.getenv("COVERAGE_LCOV")
139
99
PROXY_SLAVE_PIDFILE = lfs.currentdir() .. "/mysql-proxy-test-slave.pid"
140
100
PROXY_CHAIN_PIDFILE = lfs.currentdir() .. "/mysql-proxy-test-chain.pid"
141
101
PROXY_BACKEND_PIDFILE = lfs.currentdir() .. "/mysql-proxy-test-backend.pid"
142
PROXY_TEST_BASEDIR = lfs.currentdir()
144
102
DEFAULT_SCRIPT_FILENAME = "/tmp/dummy.lua"
145
103
default_proxy_options = {
146
104
["proxy-backend-addresses"] = MYSQL_HOST .. ":" .. MYSQL_PORT,
147
105
["proxy-address"] = PROXY_HOST .. ":" .. PROXY_PORT,
148
106
["admin-address"] = PROXY_HOST .. ":" .. ADMIN_PORT,
149
["admin-username"] = ADMIN_USER,
150
["admin-password"] = ADMIN_PASSWORD,
151
["admin-lua-script"] = ADMIN_DEFAULT_SCRIPT_FILENAME,
152
107
["pid-file"] = PROXY_PIDFILE,
153
108
["proxy-lua-script"] = DEFAULT_SCRIPT_FILENAME,
154
109
["plugin-dir"] = PROXY_LIBPATH,
155
["basedir"] = PROXY_TEST_BASEDIR,
158
112
default_master_options = {
159
113
["proxy-backend-addresses"] = MYSQL_HOST .. ":" .. MYSQL_PORT,
160
114
["proxy-address"] = PROXY_HOST .. ":" .. PROXY_MASTER_PORT,
161
115
["admin-address"] = PROXY_HOST .. ":" .. ADMIN_MASTER_PORT,
162
["admin-username"] = ADMIN_USER,
163
["admin-password"] = ADMIN_PASSWORD,
164
["admin-lua-script"] = ADMIN_DEFAULT_SCRIPT_FILENAME,
165
116
["pid-file"] = PROXY_MASTER_PIDFILE,
166
117
["proxy-lua-script"] = DEFAULT_SCRIPT_FILENAME,
167
118
["plugin-dir"] = PROXY_LIBPATH,
168
["basedir"] = PROXY_TEST_BASEDIR,
171
121
default_slave_options = {
172
122
["proxy-backend-addresses"] = MYSQL_HOST .. ":" .. MYSQL_PORT,
173
123
["proxy-address"] = PROXY_HOST .. ":" .. PROXY_SLAVE_PORT,
174
124
["admin-address"] = PROXY_HOST .. ":" .. ADMIN_SLAVE_PORT,
175
["admin-username"] = ADMIN_USER,
176
["admin-password"] = ADMIN_PASSWORD,
177
["admin-lua-script"] = ADMIN_DEFAULT_SCRIPT_FILENAME,
178
125
["pid-file"] = PROXY_SLAVE_PIDFILE,
179
126
["proxy-lua-script"] = DEFAULT_SCRIPT_FILENAME,
180
127
["plugin-dir"] = PROXY_LIBPATH,
181
["basedir"] = PROXY_TEST_BASEDIR,
185
130
tests_to_skip = {}
186
131
local tests_to_skip_filename = 'tests_to_skip.lua'
187
132
local proxy_list = {}
267
212
for k, v in pairs(tbl) do
269
-- if the value is a table, repeat the option
270
if type(v) == "table" then
276
for tk, tv in pairs(values) do
277
local enc_value = tv:gsub("\\", "\\\\"):gsub("\"", "\\\"")
278
s = s .. "--" .. k .. "=\"" .. enc_value .. "\" "
213
local enc_value = v:gsub("\\", "\\\\"):gsub("\"", "\\\"")
214
s = s .. "--" .. k .. "=\"" .. enc_value .. "\" "
281
216
-- print_verbose(" option: " .. s)
303
238
return os.execute(cmdline)
308
241
function get_pid(pid_file_name)
309
-- the file may exist, but the PID may not be written yet
314
local fh = assert(io.open(pid_file_name, 'r'))
318
glib2.usleep(200 * 1000) -- wait a bit until we get some content
322
error(("reading PID from existing pid-file '%s' failed after waiting 2 sec"):format(
328
-- the PID we get here should be a number
329
assert(type(pid) == "number")
242
local fh = assert(io.open(pid_file_name, 'r'))
243
local pid = assert(fh:read() ,
244
"PID not found in " .. pid_file_name)
360
function proc_is_up(pid)
361
return os.execute("kill -0 ".. pid .." 2> /dev/null")
364
function proc_stop(pid)
365
return os.execute("kill -TERM ".. pid)
368
274
function wait_proc_down(pid_file)
370
276
local pid = get_pid(pid_file)
372
278
-- wait until the proc in the pid file is dead
373
279
-- the shutdown takes at about 500ms
374
while 0 == proc_is_up(pid) do
280
while 0 == os.execute("kill -0 ".. pid .." 2> /dev/null") do
375
281
glib2.usleep(200 * 1000) -- wait until process is gone
376
282
rounds = rounds + 1
377
283
print_verbose(("(wait_proc_down) kill-wait: %d rounds, pid=%d (%s)"):format(rounds, pid, pid_file))
684
575
-- remove the old pid-file if it exists
685
576
os.remove(proxy_options['pid-file'])
686
-- if we are supposed to listen on a UNIX socket, remove it first, because we don't clean it up on exit!
687
-- TODO: fix the code, instead of hacking around here! Bug#38415
688
if proxy_options['proxy-address'] == '/tmp/mysql-proxy-test.sock' then
689
os.remove(proxy_options['proxy-address'])
691
578
-- os.execute("head " .. proxy_options['proxy-lua-script'])
692
579
assert(os.execute( 'LUA_PATH="' .. INCLUDE_PATH .. '" ' ..
693
580
PROXY_TRACE .. " " .. PROXY_BINPATH .. " " ..
735
622
-- default backend server, and the second one (with default ports)
736
623
-- is pointing at the first proxy
625
-- @param first_lua_script
741
626
-- @param second_lua_script
742
627
-- @param use_replication uses a master proxy as backend
743
function chain_proxy (backend_lua_scripts, second_lua_script, use_replication)
746
if type(backend_lua_scripts) == "table" then
747
backends = backend_lua_scripts
749
backends = { backend_lua_scripts }
752
local backend_addresses = { }
754
for i, backend_lua_script in ipairs(backends) do
755
backend_addresses[i] = PROXY_HOST .. ":" .. (PROXY_CHAIN_PORT + i - 1)
757
backend_proxy_options = {
628
function chain_proxy (first_lua_script, second_lua_script, use_replication)
629
first_proxy_options = {
758
630
["proxy-backend-addresses"] = MYSQL_HOST .. ":" .. MYSQL_PORT,
759
["proxy-address"] = backend_addresses[i],
760
["admin-address"] = PROXY_HOST .. ":" .. (ADMIN_CHAIN_PORT + i - 1),
761
["admin-username"] = ADMIN_USER,
762
["admin-password"] = ADMIN_PASSWORD,
763
["admin-lua-script"] = ADMIN_DEFAULT_SCRIPT_FILENAME,
764
["pid-file"] = PROXY_CHAIN_PIDFILE .. i,
765
["proxy-lua-script"] = backend_lua_script or DEFAULT_SCRIPT_FILENAME,
631
["proxy-address"] = PROXY_HOST .. ":" .. PROXY_CHAIN_PORT,
632
["admin-address"] = PROXY_HOST .. ":" .. ADMIN_CHAIN_PORT,
633
["pid-file"] = PROXY_CHAIN_PIDFILE,
634
["proxy-lua-script"] = first_lua_script or DEFAULT_SCRIPT_FILENAME,
766
635
["plugin-dir"] = PROXY_LIBPATH,
767
["basedir"] = PROXY_TEST_BASEDIR,
768
["log-level"] = (VERBOSE == 4) and "debug" or "critical",
771
-- if replication was not started, then it is started here
773
if use_replication and (use_replication == true) then
774
if (proxy_list['master'] == nil) then
775
simulate_replication()
777
backend_proxy_options["proxy-backend-addresses"] = PROXY_HOST .. ':' .. PROXY_MASTER_PORT
638
-- if replication was not started, then it is started here
640
if use_replication and (use_replication == true) then
641
if (proxy_list['master'] == nil) then
642
simulate_replication()
779
start_proxy('backend_proxy' .. i, backend_proxy_options)
644
first_proxy_options["proxy-backend-addresses"] = PROXY_HOST .. ':' .. PROXY_MASTER_PORT
782
646
second_proxy_options = {
783
["proxy-backend-addresses"] = backend_addresses ,
647
["proxy-backend-addresses"] = MYSQL_HOST .. ":" .. PROXY_CHAIN_PORT ,
784
648
["proxy-address"] = PROXY_HOST .. ":" .. PROXY_PORT,
785
649
["admin-address"] = PROXY_HOST .. ":" .. ADMIN_PORT,
786
["admin-username"] = ADMIN_USER,
787
["admin-password"] = ADMIN_PASSWORD,
788
["admin-lua-script"] = ADMIN_DEFAULT_SCRIPT_FILENAME,
789
650
["pid-file"] = PROXY_PIDFILE,
790
651
["proxy-lua-script"] = second_lua_script or DEFAULT_SCRIPT_FILENAME,
791
652
["plugin-dir"] = PROXY_LIBPATH,
792
["basedir"] = PROXY_TEST_BASEDIR,
793
["log-level"] = (VERBOSE == 3) and "debug" or "critical",
654
start_proxy('first_proxy', first_proxy_options)
795
655
start_proxy('second_proxy',second_proxy_options)
815
669
-- otherwise execute all tests we can find
817
671
for i, a in ipairs(arg) do
818
local stat = assert(lfs.attributes(a))
672
local stat = lfs.attributes(a)
820
674
if file_exists(a .. '/' .. tests_to_skip_filename) then
821
675
assert(loadfile(a .. '/' .. tests_to_skip_filename))()
824
-- if it is a directory, execute all of them
825
677
if stat.mode == "directory" then
826
678
for file in lfs.dir(a .. "/t/") do
827
if not TESTS_REGEX or file:match(TESTS_REGEX) then
828
local testname = file:match("(.+\.test)$")
831
print_verbose("# >> " .. testname .. " started")
833
num_tests = num_tests + 1
834
local r, skipped = run_test("t/" .. testname, a)
836
num_passes = num_passes + 1 - skipped
838
num_fails = num_fails + 1
840
table.insert(failed_test, testname)
842
num_skipped = num_skipped + skipped
679
local testname = file:match("(.+\.test)$")
682
print_verbose("# >> " .. testname .. " started")
684
num_tests = num_tests + 1
685
local r, skipped = run_test("t/" .. testname, a)
687
num_passes = num_passes + 1 - skipped
689
num_fails = num_fails + 1
691
table.insert(failed_test, testname)
693
num_skipped = num_skipped + skipped
844
print_verbose("# << (exitcode = " .. r .. ")" )
846
if r ~= 0 and exitcode == 0 then
850
if all_ok == false and (not FORCE_ON_ERROR) then
695
print_verbose("# << (exitcode = " .. r .. ")" )
697
if r ~= 0 and exitcode == 0 then
701
if all_ok == false and (not FORCE_ON_ERROR) then
856
-- otherwise just this one test
858
-- FIXME: base/ is hard-coded for now
859
exitcode, skipped = run_test(a, "base/")
706
exitcode, skipped = run_test(a)
860
707
num_skipped = num_skipped + skipped