diff --git a/.gitignore b/.gitignore index b99d0325dc4025dc0980b3a4613e1327d3684316..cd299e2268dcf7fae5489505bbc3a1c15cbbac12 100644 --- a/.gitignore +++ b/.gitignore @@ -60,18 +60,7 @@ test/connector_c/update test/connector_c/xlog test/lib/*.pyc test/lib/*/*.pyc -test/unit/base64 -test/unit/bit_test -test/unit/bitset_basic_test -test/unit/bitset_iterator_test -test/unit/bitset_index_test -test/unit/mhash -test/unit/rlist -test/unit/rope -test/unit/rope_avl -test/unit/rope_basic -test/unit/rope_stress -test/unit/queue +test/unit/*.test test/var third_party/luajit/src/luajit third_party/luajit/lib/vmdef.lua diff --git a/src/box/box_lua.cc b/src/box/box_lua.cc index d426361ffddc1471f0ff087bd62010d9d15aa67a..4a22d69801b7d4cc0380573cc947adba44a46ed8 100644 --- a/src/box/box_lua.cc +++ b/src/box/box_lua.cc @@ -142,7 +142,8 @@ lbox_tuple_slice(struct lua_State *L) { struct tuple *tuple = lua_checktuple(L, 1); int argc = lua_gettop(L) - 1; - int start, end; + uint32_t start, end; + int offset; /* * Prepare the range. The second argument is optional. @@ -151,36 +152,45 @@ lbox_tuple_slice(struct lua_State *L) */ if (argc == 0 || argc > 2) luaL_error(L, "tuple.slice(): bad arguments"); - start = lua_tointeger(L, 2); - if (start < 0) - start += tuple->field_count; + + offset = lua_tointeger(L, 2); + if (offset >= 0 && offset < tuple->field_count) { + start = offset; + } else if (offset < 0 && -offset <= tuple->field_count) { + start = offset + tuple->field_count; + } else { + luaL_error(L, "tuple.slice(): start >= field count"); + } + if (argc == 2) { - end = lua_tointeger(L, 3); - if (end < 0) - end += tuple->field_count; - else if (end > tuple->field_count) - end = tuple->field_count; + offset = lua_tointeger(L, 3); + if (offset > 0 && offset <= tuple->field_count) { + end = offset; + } else if (offset < 0 && -offset < tuple->field_count) { + end = offset + tuple->field_count; + } else { + luaL_error(L, "tuple.slice(): end > field count"); + } } else { end = tuple->field_count; } if (end <= start) luaL_error(L, "tuple.slice(): start must be less than end"); - u32 stop = end - 1; - struct tuple_iterator it; tuple_rewind(&it, tuple); const char *field; uint32_t len; - uint32_t field_no = 0; - while ((field = tuple_next(&it, &len))) { - if (field_no >= start) { - lua_pushlstring(L, field, len); - if (field_no == stop) - break; - } + + assert(start < tuple->field_count); + uint32_t field_no = start; + field = tuple_seek(&it, start, &len); + while (field && field_no < end) { + lua_pushlstring(L, field, len); ++field_no; + field = tuple_next(&it, &len); } + assert(field_no == end); return end - start; } @@ -1176,17 +1186,11 @@ static void port_add_lua_ret(struct port *port, struct lua_State *L, int index) { struct tuple *tuple = lua_totuple(L, index); - try { - port_add_tuple(port, tuple, BOX_RETURN_TUPLE); - - if (tuple->refs == 0) - tuple_free(tuple); - } catch (...) { + auto scoped_guard = make_scoped_guard([=] { if (tuple->refs == 0) tuple_free(tuple); - - throw; - } + }); + port_add_tuple(port, tuple, BOX_RETURN_TUPLE); } /** diff --git a/src/box/port.h b/src/box/port.h index ba6e7333dae72929b0a09024f7e0d7a40821723a..cd3a8166952878a852368583ad2147d9c97639fe 100644 --- a/src/box/port.h +++ b/src/box/port.h @@ -33,6 +33,26 @@ struct tuple; struct port; +/** + * A single port represents a destination of box_process output. + * One such destination can be a Lua stack, or the binary + * protocol. + * An instance of a port is usually short lived, as it is created + * for every server request. State of the instance is represented + * by the tuples added to it. E.g.: + * + * struct port_iproto *port = port_iproto_new(...) + * for (tuple in tuples) + * port_add_tuple(tuple); + * port_eof(port); // end of request + * + * Beginning with Tarantool 1.5, tuple can have different internal + * structure and port_add_tuple() requires a double + * dispatch: first, by the type of the port the tuple is being + * added to, second, by the type of the tuple format, since the + * format defines the internal structure of the tuple. + */ + struct port_vtab { void (*add_tuple)(struct port *port, struct tuple *tuple, u32 flags); diff --git a/src/iproto.cc b/src/iproto.cc index 50fb27c9b872e8324d7a48bc22229f4b8ed593ff..d49410ccf5cbdddcd64c580c9780803b2d3b7ade 100644 --- a/src/iproto.cc +++ b/src/iproto.cc @@ -132,6 +132,12 @@ port_iproto_eof(struct port *ptr) } } +static inline void +tuple_to_iproto(struct port_iproto *port, struct tuple *tuple) +{ + obuf_dup(port->buf, &tuple->bsize, tuple_len(tuple)); +} + static void port_iproto_add_tuple(struct port *ptr, struct tuple *tuple, u32 flags) { @@ -141,7 +147,7 @@ port_iproto_add_tuple(struct port *ptr, struct tuple *tuple, u32 flags) port->svp = obuf_book(port->buf, sizeof(port->reply)); } if (flags & BOX_RETURN_TUPLE) { - obuf_dup(port->buf, &tuple->bsize, tuple_len(tuple)); + tuple_to_iproto(port, tuple); } } diff --git a/test/.gitattributes b/test/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..120b07e8db944c0d3dd22357e61acba1622d6666 --- /dev/null +++ b/test/.gitattributes @@ -0,0 +1,2 @@ +*.result diff merge=text + diff --git a/test/box/lua.result b/test/box/lua.result index 7a927c5d5bb0977bb88842597357505538b0e512..fcef60120cd3c72ca4617ee5853253f01ad7e998 100644 --- a/test/box/lua.result +++ b/test/box/lua.result @@ -1419,12 +1419,12 @@ lua floor(1.1) # Test box.tuple:slice() -lua t=box.space[0]:insert(0, '1', '2', '3', '4', '5', '6', '7') +lua t=box.tuple.new({'0', '1', '2', '3', '4', '5', '6', '7'}) --- ... lua t:slice(0) --- - - + - 0 - 1 - 2 - 3 @@ -1473,26 +1473,75 @@ lua t:slice(7) --- - 7 ... +lua t:slice(8) +--- +error: 'tuple.slice(): start >= field count' +... lua t:slice(9) --- -error: 'tuple.slice(): start must be less than end' +error: 'tuple.slice(): start >= field count' +... +lua t:slice(100500) +--- +error: 'tuple.slice(): start >= field count' ... lua t:slice(9, -1) --- -error: 'tuple.slice(): start must be less than end' +error: 'tuple.slice(): start >= field count' ... lua t:slice(6, -1) --- - 6 ... -lua t:slice(9, 10) +lua t:slice(4, 4) --- error: 'tuple.slice(): start must be less than end' ... -lua t:slice(500, 700) +lua t:slice(6, 4) --- error: 'tuple.slice(): start must be less than end' ... +lua t:slice(0, 0) +--- +error: 'tuple.slice(): end > field count' +... +lua t:slice(9, 10) +--- +error: 'tuple.slice(): start >= field count' +... +lua t:slice(-7) +--- + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 +... +lua t:slice(-8) +--- + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 +... +lua t:slice(-9) +--- +error: 'tuple.slice(): start >= field count' +... +lua t:slice(-100500) +--- +error: 'tuple.slice(): start >= field count' +... +lua t:slice(500, 700) +--- +error: 'tuple.slice(): start >= field count' +... lua box.space[0]:truncate() --- ... diff --git a/test/box/lua.test b/test/box/lua.test index b4d775bfa704d7d9996a68ef7ce2135d89d31ef4..c5f711ff0cb46229545901c8b1d2d2e41d52602d 100644 --- a/test/box/lua.test +++ b/test/box/lua.test @@ -490,7 +490,7 @@ server.deploy(init_lua=None) print """ # Test box.tuple:slice() """ -exec admin "lua t=box.space[0]:insert(0, '1', '2', '3', '4', '5', '6', '7')" +exec admin "lua t=box.tuple.new({'0', '1', '2', '3', '4', '5', '6', '7'})" exec admin "lua t:slice(0)" exec admin "lua t:slice(-1)" exec admin "lua t:slice(1)" @@ -499,10 +499,19 @@ exec admin "lua t:slice(-1, 1)" exec admin "lua t:slice(1, -1)" exec admin "lua t:slice(1, 3)" exec admin "lua t:slice(7)" +exec admin "lua t:slice(8)" exec admin "lua t:slice(9)" +exec admin "lua t:slice(100500)" exec admin "lua t:slice(9, -1)" exec admin "lua t:slice(6, -1)" +exec admin "lua t:slice(4, 4)" +exec admin "lua t:slice(6, 4)" +exec admin "lua t:slice(0, 0)" exec admin "lua t:slice(9, 10)" +exec admin "lua t:slice(-7)" +exec admin "lua t:slice(-8)" +exec admin "lua t:slice(-9)" +exec admin "lua t:slice(-100500)" exec admin "lua t:slice(500, 700)" exec admin "lua box.space[0]:truncate()" @@ -672,3 +681,4 @@ exec admin "lua box.tuple.new({false})" exec admin "lua t = box.tuple.new('abc')" exec admin "lua t" exec admin "lua t:bsize()" +exec admin silent "lua box.delete(0, 8989)" diff --git a/test/connector_c/xlog_rpl.test b/test/connector_c/xlog_rpl.test index f53063e350344442202df0b32f00c40e1cc2b1a9..5f774f785bc7ec7e841b009056badff89581d3d4 100644 --- a/test/connector_c/xlog_rpl.test +++ b/test/connector_c/xlog_rpl.test @@ -2,7 +2,7 @@ import subprocess import sys import os -from lib.tarantool_box_server import TarantoolBoxServer +from lib.tarantool_server import TarantoolServer p = subprocess.Popen([os.path.join(builddir, "test/connector_c/xlog"), os.path.abspath("connector_c/connector.xlog")], diff --git a/test/lib/server.py b/test/lib/server.py index 5730ffe979aa4a1a138528f5ee11b3b85420e8c9..8f292b14cb33b00a38aadc3ae36d96b467f1d8ca 100644 --- a/test/lib/server.py +++ b/test/lib/server.py @@ -57,17 +57,16 @@ class Server(object): replication slaves. The server is started once at the beginning of each suite, and stopped at the end.""" - def __new__(cls, core=None, module=None): + def __new__(cls, core=None): if core == None: return super(Server, cls).__new__(cls) mdlname = "lib.{0}_server".format(core) clsname = "{0}Server".format(core.title()) corecls = __import__(mdlname, fromlist=clsname).__dict__[clsname] - return corecls.__new__(corecls, core, module) + return corecls.__new__(corecls, core) - def __init__(self, core, module): + def __init__(self, core): self.core = core - self.module = module self.re_vardir_cleanup = ['*.core.*', 'core'] self.process = None self.default_config_name = None @@ -75,7 +74,7 @@ class Server(object): self.config = None self.vardir = None self.valgrind_log = "valgrind.log" - self.valgrind_sup = os.path.join("share/", "%s_%s.sup" % (core, module)) + self.valgrind_sup = os.path.join("share/", "%s.sup" % (core)) self.init_lua = None self.default_suppression_name = "valgrind.sup" self.pidfile = None @@ -89,14 +88,13 @@ class Server(object): def find_exe(self, builddir, silent=True): "Locate server executable in the build dir or in the PATH." - exe_name = self.default_bin_name() path = builddir + os.pathsep + os.environ["PATH"] if not silent: print " Looking for server binary in {0} ...".format(path) for dir in path.split(os.pathsep): - exe = os.path.join(dir, exe_name) + exe = os.path.join(dir, self.default_bin_name) if os.access(exe, os.X_OK): return exe diff --git a/test/lib/tarantool_box_server.py b/test/lib/tarantool_box_server.py deleted file mode 100644 index 1e68c5a6e953aa9179fb46af928ef80d66327485..0000000000000000000000000000000000000000 --- a/test/lib/tarantool_box_server.py +++ /dev/null @@ -1,62 +0,0 @@ -import time -import shutil -import subprocess -import yaml -import ConfigParser -from tarantool_server import TarantoolServer, TarantoolConfigFile -from admin_connection import AdminConnection -from box_connection import BoxConnection -from memcached_connection import MemcachedConnection -import time - -class TarantoolBoxServer(TarantoolServer): - def __new__(cls, core="tarantool", module="box"): - return TarantoolServer.__new__(cls) - - def __init__(self, core="tarantool", module="box"): - TarantoolServer.__init__(self, core, module) - - def configure(self, config): - TarantoolServer.configure(self, config) - with open(self.config) as fp: - dummy_section_name = "tarantool" - config = ConfigParser.ConfigParser() - config.readfp(TarantoolConfigFile(fp, dummy_section_name)) - - self.primary_port = self.get_option_int(config, dummy_section_name, "primary_port") - self.admin_port = self.get_option_int(config, dummy_section_name, "admin_port") - self.memcached_port = self.get_option_int(config, dummy_section_name, "memcached_port") - - self.port = self.admin_port - self.admin = AdminConnection("localhost", self.admin_port) - self.sql = BoxConnection("localhost", self.primary_port) - if self.memcached_port != 0: - # Run memcached client - self.memcached = MemcachedConnection('localhost', self.memcached_port) - - def get_option_int(self, config, section, option): - if config.has_option(section, option): - return config.getint(section, option) - else: - return 0 - - def init(self): - # init storage - subprocess.check_call([self.binary, "--init-storage"], - cwd = self.vardir, - # catch stdout/stderr to not clutter output - stdout = subprocess.PIPE, - stderr = subprocess.PIPE) - - def get_param(self, param): - data = self.admin.execute("show info", silent = True) - info = yaml.load(data)["info"] - return info[param] - - def wait_lsn(self, lsn): - while True: - curr_lsn = int(self.get_param("lsn")) - if (curr_lsn >= lsn): - break - time.sleep(0.01) - diff --git a/test/lib/tarantool_server.py b/test/lib/tarantool_server.py index ec9c3b527a3962adb303f3564cf08ab5617fab85..5ae0eb9f10dce8c85e29b92a932ae85352aed928 100644 --- a/test/lib/tarantool_server.py +++ b/test/lib/tarantool_server.py @@ -1,9 +1,67 @@ import os +import sys +import glob +import time +import yaml import shutil -import subprocess import pexpect +import traceback +import subprocess import ConfigParser +import pprint + +import tarantool_preprocessor + from server import Server +from box_connection import BoxConnection +from test_suite import FilteredStream, Test +from admin_connection import AdminConnection +from memcached_connection import MemcachedConnection + + +class FuncTest(Test): + def __init__(self, name, args, suite_ini): + Test.__init__(self, name, args, suite_ini) + self.name = name + self.result = name.replace(".test", ".result") + self.skip_cond = name.replace(".test", ".skipcond") + self.tmp_result = os.path.join(self.args.vardir, + os.path.basename(self.result)) + self.reject = "{0}/test/{1}".format(self.args.builddir, + name.replace(".test", ".reject")) + + def execute(self, server): + diagnostics = "unknown" + builddir = self.args.builddir + save_stdout = sys.stdout + try: + self.skip = 0 + if os.path.exists(self.skip_cond): + sys.stdout = FilteredStream(self.tmp_result) + stdout_fileno = sys.stdout.stream.fileno() + execfile(self.skip_cond, dict(locals(), **server.__dict__)) + sys.stdout.close() + sys.stdout = save_stdout + if not self.skip: + sys.stdout = FilteredStream(self.tmp_result) + stdout_fileno = sys.stdout.stream.fileno() + execfile(self.name, dict(locals(), **server.__dict__)) + self.is_executed_ok = True + except Exception as e: + traceback.print_exc(e) + diagnostics = str(e) + finally: + if sys.stdout and sys.stdout != save_stdout: + sys.stdout.close() + sys.stdout = save_stdout; + self.is_executed = True + + def __repr__(self): + return str([self.name, self.result, self.skip_cond, self.tmp_result, + self.reject]) + + __str__ = __repr__ + class TarantoolConfigFile: """ConfigParser can't read files without sections, work it around""" @@ -19,19 +77,13 @@ class TarantoolConfigFile: # tarantool.cfg puts string values in quote return self.fp.readline().replace("\"", '') - class TarantoolServer(Server): - def __new__(cls, core=None, module=None): - if module == None: - return super(Server, cls).__new__(cls) - mdlname = "lib.{0}_{1}_server".format(core, module) - clsname = "{0}{1}Server".format(core.title(), module.title()) - modulecls = __import__(mdlname, fromlist=clsname).__dict__[clsname] + def __new__(cls, core="tarantool"): + return super(Server, cls).__new__(cls) - return modulecls.__new__(modulecls, core, module) - - def __init__(self, core, module): - Server.__init__(self, core, module) + def __init__(self, core="tarantool"): + Server.__init__(self, core) + self.default_bin_name = "tarantool_box" self.default_config_name = "tarantool.cfg" self.default_init_lua_name = "init.lua" # append additional cleanup patterns @@ -43,7 +95,7 @@ class TarantoolServer(Server): '*.lua'] def find_exe(self, builddir, silent=True): - return Server.find_exe(self, "{0}/src/{1}".format(builddir, self.module), silent) + return Server.find_exe(self, "{0}/src/box/".format(builddir), silent) def configure(self, config): Server.configure(self, config) @@ -52,7 +104,24 @@ class TarantoolServer(Server): dummy_section_name = "tarantool" config = ConfigParser.ConfigParser() config.readfp(TarantoolConfigFile(fp, dummy_section_name)) + self.pidfile = config.get(dummy_section_name, "pid_file") + self.primary_port = self.get_option_int(config, dummy_section_name, "primary_port") + self.admin_port = self.get_option_int(config, dummy_section_name, "admin_port") + self.memcached_port = self.get_option_int(config, dummy_section_name, "memcached_port") + + self.port = self.admin_port + self.admin = AdminConnection("localhost", self.admin_port) + self.sql = BoxConnection("localhost", self.primary_port) + if self.memcached_port != 0: + # Run memcached client + self.memcached = MemcachedConnection('localhost', self.memcached_port) + + def find_tests(self, test_suite, suite_path): + for test_name in sorted(glob.glob(os.path.join(suite_path, "*.test"))): + for test_pattern in test_suite.args.tests: + if test_name.find(test_pattern) != -1: + test_suite.tests.append(FuncTest(test_name, test_suite.args, test_suite.ini)) def reconfigure(self, config, silent=False): if config == None: @@ -62,6 +131,32 @@ class TarantoolServer(Server): shutil.copy(self.config, os.path.join(self.vardir, self.default_config_name)) self.admin.execute("reload configuration", silent=silent) + def get_option_int(self, config, section, option): + if config.has_option(section, option): + return config.getint(section, option) + else: + return 0 + + def init(self): + # init storage + subprocess.check_call([self.binary, "--init-storage"], + cwd = self.vardir, + # catch stdout/stderr to not clutter output + stdout = subprocess.PIPE, + stderr = subprocess.PIPE) + + def get_param(self, param): + data = self.admin.execute("show info", silent = True) + info = yaml.load(data)["info"] + return info[param] + + def wait_lsn(self, lsn): + while True: + curr_lsn = int(self.get_param("lsn")) + if (curr_lsn >= lsn): + break + time.sleep(0.01) + def version(self): p = subprocess.Popen([self.binary, "--version"], cwd = self.vardir, @@ -83,7 +178,3 @@ class TarantoolServer(Server): raise RuntimeError("'--gdb' and '--start-and-exit' can't be defined together") self.server = pexpect.spawn(args[0], args[1:], cwd = self.vardir) self.server.wait() - - def default_bin_name(self): - return "{0}_{1}".format(self.core, self.module) - diff --git a/test/lib/test_suite.py b/test/lib/test_suite.py index f3dfceb55d665b356eed08884dc716bddb547fa4..768086630dfa318925523a38cdc215647789633b 100644 --- a/test/lib/test_suite.py +++ b/test/lib/test_suite.py @@ -10,6 +10,7 @@ import difflib import filecmp import shlex import time + from server import Server import tarantool_preprocessor import re @@ -35,7 +36,7 @@ class FilteredStream: for pattern, replacement in self.filters: line = re.sub(pattern, replacement, line) # don't write lines that are completely filtered out: - skipped = original_len and len(line.strip()) == 0 + skipped = original_len and not line.strip() if skipped: break if not skipped: @@ -87,8 +88,8 @@ class Test: self.skip_cond = name.replace(".test", ".skipcond") self.tmp_result = os.path.join(self.args.vardir, os.path.basename(self.result)) - self.reject = "{0}/test/{1}".format(self.args.builddir, - name.replace(".test", ".reject")) + self.reject = "{0}/test/{1}".format(self.args.builddir, + name.replace(".test", ".reject")) self.is_executed = False self.is_executed_ok = None self.is_equal_result = None @@ -109,31 +110,8 @@ class Test: diagnostics = "unknown" - save_stdout = sys.stdout builddir = self.args.builddir - try: - self.skip = 0 - if os.path.exists(self.skip_cond): - sys.stdout = FilteredStream(self.tmp_result) - stdout_fileno = sys.stdout.stream.fileno() - execfile(self.skip_cond, dict(locals(), **server.__dict__)) - sys.stdout.close() - sys.stdout = save_stdout - - - if not self.skip: - sys.stdout = FilteredStream(self.tmp_result) - stdout_fileno = sys.stdout.stream.fileno() - execfile(self.name, dict(locals(), **server.__dict__)) - self.is_executed_ok = True - except Exception as e: - traceback.print_exc(e) - diagnostics = str(e) - finally: - if sys.stdout and sys.stdout != save_stdout: - sys.stdout.close() - sys.stdout = save_stdout; - + self.execute(server) self.is_executed = True if not self.skip: @@ -148,7 +126,8 @@ class Test: if self.skip: print "[ skip ]" - + if os.path.exists(self.tmp_result): + os.remove(self.tmp_result) elif self.is_executed_ok and self.is_equal_result and self.is_valgrind_clean: print "[ pass ]" if os.path.exists(self.tmp_result): @@ -223,7 +202,6 @@ class TestSuite: self.ini = {} self.ini["core"] = "tarantool" - self.ini["module"] = "box" if os.access(suite_path, os.F_OK) == False: raise RuntimeError("Suite \"" + suite_path + \ @@ -233,68 +211,49 @@ class TestSuite: config = ConfigParser.ConfigParser() config.read(os.path.join(suite_path, "suite.ini")) self.ini.update(dict(config.items("default"))) - self.ini["config"] = os.path.join(suite_path, self.ini["config"]) - - if self.ini.has_key("init_lua"): - self.ini["init_lua"] = os.path.join(suite_path, - self.ini["init_lua"]) - else: - self.ini["init_lua"] = None - if self.ini.has_key("disabled"): - self.ini["disabled"] = dict.fromkeys(self.ini["disabled"].split(" ")) - else: - self.ini["disabled"] = dict() - - if self.ini.has_key("valgrind_disabled"): - self.ini["valgrind_disabled"] = dict.fromkeys(self.ini["valgrind_disabled"].split(" ")) - else: - self.ini["valgrind_disabled"] = dict() + for i in ["config", "init_lua"]: + self.ini[i] = os.path.join(suite_path, self.ini[i]) if i in self.ini else None + for i in ["disabled", "valgrind_disabled", "release_disabled"]: + self.ini[i] = dict.fromkeys(self.ini[i].split()) if i in self.ini else dict() - if self.ini.has_key("release_disabled"): - self.ini["release_disabled"] = dict.fromkeys(self.ini["release_disabled"].split(" ")) - else: - self.ini["release_disabled"] = dict() + try: + self.server = Server(self.ini["core"]) + self.ini["server"] = self.server + except Exception as e: + print e + raise RuntimeError("Unknown server: core = {0}".format( + self.ini["core"])) print "Collecting tests in \"" + suite_path + "\": " +\ self.ini["description"] + "." - - for test_name in glob.glob(os.path.join(suite_path, "*.test")): - for test_pattern in self.args.tests: - if test_name.find(test_pattern) != -1: - self.tests.append(Test(test_name, self.args, self.ini)) + self.server.find_tests(self, suite_path); print "Found " + str(len(self.tests)) + " tests." def run_all(self): """For each file in the test suite, run client program assuming each file represents an individual test.""" - try: - server = Server(self.ini["core"], self.ini["module"]) - except Exception as e: - print e - raise RuntimeError("Unknown server: core = {0}, module = {1}".format( - self.ini["core"], self.ini["module"])) - if len(self.tests) == 0: + if not self.tests: # noting to test, exit return 0 - server.deploy(self.ini["config"], - server.find_exe(self.args.builddir, silent=False), + self.server.deploy(self.ini["config"], + self.server.find_exe(self.args.builddir, silent=False), self.args.vardir, self.args.mem, self.args.start_and_exit, self.args.gdb, self.args.valgrind, init_lua=self.ini["init_lua"], silent=False) + if self.args.start_and_exit: print " Start and exit requested, exiting..." exit(0) - longsep = "==============================================================================" - shortsep = "------------------------------------------------------------" + longsep = '='*70 + shortsep = '-'*60 print longsep print string.ljust("TEST", 48), "RESULT" print shortsep failed_tests = [] - self.ini["server"] = server for test in self.tests: sys.stdout.write(string.ljust(test.name, 48)) @@ -302,27 +261,26 @@ class TestSuite: sys.stdout.flush() test_name = os.path.basename(test.name) - if test_name in self.ini["disabled"]: - print "[ disabled ]" - elif not server.debug and test_name in self.ini["release_disabled"]: - print "[ disabled ]" - elif self.args.valgrind and test_name in self.ini["valgrind_disabled"]: + + if (test_name in self.ini["disabled"] + or not self.server.debug and test_name in self.ini["release_disabled"] + or self.args.valgrind and test_name in self.ini["valgrind_disabled"]): print "[ disabled ]" else: - test.run(server) + test.run(self.server) if not test.passed(): failed_tests.append(test.name) print shortsep - if len(failed_tests): + if failed_tests: print "Failed {0} tests: {1}.".format(len(failed_tests), ", ".join(failed_tests)) - server.stop(silent=False) - server.cleanup() + self.server.stop(silent=False) + self.server.cleanup() - if self.args.valgrind and check_valgrind_log(server.valgrind_log): + if self.args.valgrind and check_valgrind_log(self.server.valgrind_log): print " Error! There were warnings/errors in valgrind log file:" - print_tail_n(server.valgrind_log, 20) + print_tail_n(self.server.valgrind_log, 20) return 1 return len(failed_tests) diff --git a/test/lib/unittest_server.py b/test/lib/unittest_server.py index f63b33be1f44b6b54eebf0e3972e94cdef4e40a6..24ec2597d193e81acdb8254068c5e86d48c15818 100644 --- a/test/lib/unittest_server.py +++ b/test/lib/unittest_server.py @@ -1,16 +1,70 @@ -from server import Server -import subprocess -import sys import os +import re +import sys +import traceback +import subprocess + +from subprocess import Popen, PIPE + +import tarantool_preprocessor + +from server import Server +from test_suite import FilteredStream, Test + + +class UnitTest(Test): + def __init__(self, name, args, suite_ini): + Test.__init__(self, name, args, suite_ini) + self.name = name + ".test" + self.result = name + ".result" + self.skip_cond = name + ".skipcond" + self.tmp_result = os.path.join(self.args.vardir, + os.path.basename(self.result)) + self.reject = "{0}/test/{1}".format(self.args.builddir, name + ".reject") + + def execute(self, server): + diagnostics = "unknown" + builddir = self.args.builddir + save_stdout = sys.stdout + try: + self.skip = 0 + if os.path.exists(self.skip_cond): + sys.stdout = FilteredStream(self.tmp_result) + stdout_fileno = sys.stdout.stream.fileno() + execfile(self.skip_cond, dict(locals(), **server.__dict__)) + sys.stdout.close() + sys.stdout = save_stdout + if not self.skip: + sys.stdout = FilteredStream(self.tmp_result) + stdout_fileno = sys.stdout.stream.fileno() + execs = [os.path.join(server.builddir, "test", self.name)] + proc = Popen(execs, stdout=PIPE) + sys.stdout.write(proc.communicate()[0]) + self.is_executed_ok = True + except Exception as e: + traceback.print_exc(e) + diagnostics = str(e) + finally: + if sys.stdout and sys.stdout != save_stdout: + sys.stdout.close() + sys.stdout = save_stdout; + self.is_executed = True + + def __repr__(self): + return str([self.name, self.result, self.skip_cond, self.tmp_result, + self.reject]) + + __str__ = __repr__ + class UnittestServer(Server): """A dummy server implementation for unit test suite""" - def __new__(cls, core="unittest", module="dummy"): + def __new__(cls, core="unittest"): return Server.__new__(cls) - def __init__(self, core="unittest", module="dummy"): - Server.__init__(self, core, module) + def __init__(self, core="unittest"): + Server.__init__(self, core) self.debug = False def configure(self, config): @@ -18,14 +72,8 @@ class UnittestServer(Server): def deploy(self, config=None, binary=None, vardir=None, mem=None, start_and_exit=None, gdb=None, valgrind=None, valgrind_sup=None, init_lua=None, silent=True, need_init=True): - self.vardir = vardir - def run_test(name): - p = subprocess.Popen([os.path.join(self.builddir, "test/unit", name)], stdout=subprocess.PIPE) - p.wait() - for line in p.stdout.readlines(): - sys.stdout.write(line) - self.run_test = run_test + self.vardir = vardir if not os.access(self.vardir, os.F_OK): if (self.mem == True and check_tmpfs_exists() and os.path.basename(self.vardir) == self.vardir): @@ -39,5 +87,21 @@ class UnittestServer(Server): def find_exe(self, builddir, silent=False): self.builddir = builddir + def find_tests(self, test_suite, suite_path): + def patterned(name): + for i in test_suite.args.tests: + if name.find(i) != -1: + return True + return False + + regexp = re.compile('([a-zA-Z0-9_]*).test') + for f in sorted(os.listdir(suite_path)): + if regexp.match(f): + f = os.path.join(suite_path, regexp.match(f).groups()[0]) + '.test' + if os.access(f, os.X_OK) and os.path.isfile(f) and patterned(f): + test_suite.tests.append(UnitTest(f[:-5], test_suite.args, + test_suite.ini)); + + def init(self): pass diff --git a/test/memcached/tarantool.cfg b/test/memcached/cfg/master.cfg similarity index 79% rename from test/memcached/tarantool.cfg rename to test/memcached/cfg/master.cfg index b3c09590bda0ac3e1ee14513a9863ebd7514adb5..0f83dcb1823bc095c9669de5274e848d81c8d448 100644 --- a/test/memcached/tarantool.cfg +++ b/test/memcached/cfg/master.cfg @@ -1,15 +1,18 @@ slab_alloc_arena = 0.1 pid_file = "box.pid" - logger="cat - >> tarantool.log" +bind_ipaddr="INADDR_ANY" +custom_proc_title="master" primary_port = 33013 secondary_port = 33014 admin_port = 33015 memcached_port = 33016 -rows_per_wal = 50 +replication_port = 33017 + +rows_per_wal = 200 space[0].enabled = 1 space[0].index[0].type = "HASH" diff --git a/test/memcached/tarantool_memcached_bad.cfg b/test/memcached/cfg/tarantool_memcached_bad.cfg similarity index 100% rename from test/memcached/tarantool_memcached_bad.cfg rename to test/memcached/cfg/tarantool_memcached_bad.cfg diff --git a/test/memcached/tarantool_memcached_off.cfg b/test/memcached/cfg/tarantool_memcached_off.cfg similarity index 100% rename from test/memcached/tarantool_memcached_off.cfg rename to test/memcached/cfg/tarantool_memcached_off.cfg diff --git a/test/memcached/expirations.test b/test/memcached/expirations.test index c941333f8fa1a538ef4ce59603fb7c236c419f39..5197d08aa7756a9c7209aa1aeaade2964911db3a 100644 --- a/test/memcached/expirations.test +++ b/test/memcached/expirations.test @@ -1,5 +1,24 @@ # encoding: tarantool import time +import yaml + +################################### +def wait_for_next_lsn(lsn, serv): + serv_admin = serv.admin + while True: + if get_lsn(serv) != lsn: + return lsn + time.sleep(0.01) + +def get_lsn(serv): + serv_admin = serv.admin + resp = exec serv_admin silent "lua box.info.lsn" + return yaml.load(resp)[0] + +def wait(serv = server): + lsn = get_lsn(serv) + return wait_for_next_lsn(lsn, serv) +################################### print """# expire: after 1 second""" @@ -9,7 +28,7 @@ exec memcached "set foo 0 1 6\r\nfooval\r\n" print """# foo shoud be exists""" exec memcached "get foo\r\n" -time.sleep(1.5) +wait() print """# foo shoud expired""" exec memcached "get foo\r\n" @@ -33,11 +52,10 @@ exec memcached silent "set foo 0 %d 6\r\nfooval\r\n" % expire print """# foo shoud be exists""" exec memcached "get foo\r\n" -time.sleep(2.2) +wait() print """# foo shoud expired""" exec memcached "get foo\r\n" - print """# expire: time - 20 second""" expire = time.time() - 20 @@ -47,7 +65,6 @@ exec memcached silent "set boo 0 %d 6\r\nbooval\r\n" % expire print """# foo shoud expired""" exec memcached "get boo\r\n" - print """# expire: after 2 second""" print """# add add""" @@ -56,7 +73,7 @@ exec memcached "add add 0 1 6\r\naddval\r\n" print """# readd add - shoud be fail""" exec memcached "add add 0 1 7\r\naddval1\r\n" -time.sleep(2.2) +wait() print """# readd add - shoud be success""" exec memcached "add add 0 1 7\r\naddval2\r\n" diff --git a/test/memcached/flush-all.result b/test/memcached/flush-all.result index 6722b889b4bca9cdbb3583ef7ea9bc1277ad468f..245d0f0f7421ceaef53c819f28dc51c2f9dd1bc0 100644 --- a/test/memcached/flush-all.result +++ b/test/memcached/flush-all.result @@ -19,7 +19,7 @@ VALUE foo 0 3 new END # and the other form, specifying a flush_all time... -flush_all time + 2 +flush_all time + 1 OK get foo diff --git a/test/memcached/flush-all.test b/test/memcached/flush-all.test index d7957749b7e09376e59b68c8558c1002d8a95ac2..41693ed020500708599c612e9e19197ad75a935e 100644 --- a/test/memcached/flush-all.test +++ b/test/memcached/flush-all.test @@ -1,5 +1,20 @@ # encoding: tarantool import time +import yaml + +################################### +def get_memcached_len(serv): + serv_admin = serv.admin + resp = exec serv_admin silent "lua box.space[box.cfg.memcached_space]:len()" + return yaml.load(resp)[0] + +def wait_for_empty_space(serv = server): + serv_admin = serv.admin + while True: + if get_memcached_len(serv) == 0: + return + time.sleep(0.01) +################################### print """# Test flush_all with zero delay. """ exec memcached "set foo 0 0 6\r\nfooval\r\n" @@ -12,14 +27,14 @@ exec memcached "set foo 0 0 3\r\nnew\r\n" exec memcached "get foo\r\n" print """# and the other form, specifying a flush_all time... """ -expire = time.time() + 2 -print "flush_all time + 2" +expire = time.time() + 1 +print "flush_all time + 1" print exec memcached silent "flush_all %d\r\n" % expire exec memcached "get foo\r\n" exec memcached "set foo 0 0 3\r\n123\r\n" exec memcached "get foo\r\n" -time.sleep(2.2) +wait_for_empty_space() exec memcached "get foo\r\n" # resore default suite config diff --git a/test/memcached/off.test b/test/memcached/off.test index c886dede1c5f479b6cd859cf64dd8fc2fd7676d8..d7859dabc14f667bddaf664e91d5e9c5cf70fe73 100644 --- a/test/memcached/off.test +++ b/test/memcached/off.test @@ -15,7 +15,7 @@ print """ # stop current server server.stop() # start server with memcached off -server.deploy("memcached/tarantool_memcached_off.cfg") +server.deploy("memcached/cfg/tarantool_memcached_off.cfg") # check values exec admin "show configuration" @@ -23,7 +23,7 @@ exec admin "show configuration" server.stop() # start server with memcached space conflict sys.stdout.push_filter("(/\S+)+/tarantool", "tarantool") -server.test_option("-c " + os.path.join(os.getcwd(), "memcached/tarantool_memcached_bad.cfg")) +server.test_option("-c " + os.path.join(os.getcwd(), "memcached/cfg/tarantool_memcached_bad.cfg")) sys.stdout.pop_filter() # restore default server diff --git a/test/memcached/suite.ini b/test/memcached/suite.ini index abd820de1872dcd76f93f0274895e73ac37a76fa..3c8a675998a5d0f4ceb239807d7756b892380f4d 100644 --- a/test/memcached/suite.ini +++ b/test/memcached/suite.ini @@ -1,6 +1,6 @@ [default] description = tarantool/box memcached tests -config = tarantool.cfg +config = cfg/master.cfg disabled = cas.test # put disabled in valgrind test here -valgrind_disabled = expirations.test +valgrind_disabled = expirations.test, repl.test diff --git a/test/replication/cfg/hot_standby.cfg b/test/replication/cfg/hot_standby.cfg index fc74b3539f9fe30a6b173f2f691567e6ad56d7ce..580e073cfecfae5cab5e873d8f398feda38e884b 100644 --- a/test/replication/cfg/hot_standby.cfg +++ b/test/replication/cfg/hot_standby.cfg @@ -2,8 +2,8 @@ slab_alloc_arena = 0.1 pid_file = "tarantool.pid" logger="cat - >> tarantool.log" - bind_ipaddr="INADDR_ANY" +custom_proc_title="hot_standby" wal_dir="../" snap_dir="../" @@ -11,12 +11,15 @@ snap_dir="../" primary_port = 33013 secondary_port = 33024 admin_port = 33025 +memcached_port = 33026 +replication_port=33017 -replication_port=33016 -custom_proc_title="hot_standby" space[0].enabled = 1 space[0].index[0].type = "HASH" space[0].index[0].unique = 1 space[0].index[0].key_field[0].fieldno = 0 space[0].index[0].key_field[0].type = "NUM" + +memcached_space = 2 +memcached_expire=true diff --git a/test/replication/cfg/master.cfg b/test/replication/cfg/master.cfg index 9118e6d22ee79571a91fe71a07062b6d105ad913..8069ab062c50ed765d90a02df4351c134716113d 100644 --- a/test/replication/cfg/master.cfg +++ b/test/replication/cfg/master.cfg @@ -2,15 +2,14 @@ slab_alloc_arena = 0.1 pid_file = "tarantool.pid" logger="cat - >> tarantool.log" - bind_ipaddr="INADDR_ANY" +custom_proc_title="master" primary_port = 33013 secondary_port = 33014 admin_port = 33015 - -replication_port=33016 -custom_proc_title="master" +memcached_port = 33016 +replication_port = 33017 space[0].enabled = 1 space[0].index[0].type = "HASH" @@ -18,3 +17,5 @@ space[0].index[0].unique = 1 space[0].index[0].key_field[0].fieldno = 0 space[0].index[0].key_field[0].type = "NUM" +memcached_space = 2 +memcached_expire=true diff --git a/test/replication/cfg/master_to_replica.cfg b/test/replication/cfg/master_to_replica.cfg index 5d2ae2420cc0ee1f3924074f48c8335dfa60f3e2..2428d2c393bd01bbbb12e610287351b62664d6b5 100644 --- a/test/replication/cfg/master_to_replica.cfg +++ b/test/replication/cfg/master_to_replica.cfg @@ -2,15 +2,17 @@ slab_alloc_arena = 0.1 pid_file = "tarantool.pid" logger="cat - >> tarantool.log" - bind_ipaddr="INADDR_ANY" +custom_proc_title="master" primary_port = 33013 secondary_port = 33014 admin_port = 33015 +memcached_port = 33016 + +replication_port=33017 +replication_source = "127.0.0.1:33117" -replication_port=33016 -custom_proc_title="master" space[0].enabled = 1 space[0].index[0].type = "HASH" @@ -18,4 +20,5 @@ space[0].index[0].unique = 1 space[0].index[0].key_field[0].fieldno = 0 space[0].index[0].key_field[0].type = "NUM" -replication_source = "127.0.0.1:33116" +memcached_space = 2 +memcached_expire=true diff --git a/test/replication/cfg/replica.cfg b/test/replication/cfg/replica.cfg index 271da4823e6615b384911e577df6dfffd1a34766..c214a3aef4f29c1cc19426c17a2a40d7982f14d7 100644 --- a/test/replication/cfg/replica.cfg +++ b/test/replication/cfg/replica.cfg @@ -2,15 +2,16 @@ slab_alloc_arena = 0.1 pid_file = "tarantool.pid" logger="cat - >> tarantool.log" - bind_ipaddr="INADDR_ANY" +custom_proc_title="replica" primary_port = 33113 secondary_port = 33114 admin_port = 33115 +memcached_port = 33116 -replication_port=33116 -custom_proc_title="replica" +replication_port=33117 +replication_source = 127.0.0.1:33017 space[0].enabled = 1 space[0].index[0].type = "HASH" @@ -18,4 +19,5 @@ space[0].index[0].unique = 1 space[0].index[0].key_field[0].fieldno = 0 space[0].index[0].key_field[0].type = "NUM" -replication_source = 127.0.0.1:33016 +memcached_space = 2 +memcached_expire=true diff --git a/test/replication/cfg/replica_to_master.cfg b/test/replication/cfg/replica_to_master.cfg index df97d6e341536dd90078f7c98ffa4daa4c0b03b0..1f7c10c31ea5ebb90cb2d2a92a3546520ac2969a 100644 --- a/test/replication/cfg/replica_to_master.cfg +++ b/test/replication/cfg/replica_to_master.cfg @@ -2,18 +2,20 @@ slab_alloc_arena = 0.1 pid_file = "tarantool.pid" logger="cat - >> tarantool.log" - bind_ipaddr="INADDR_ANY" +custom_proc_title="replica" primary_port = 33113 secondary_port = 33114 admin_port = 33115 - -replication_port=33116 -custom_proc_title="replica" +memcached_port = 33116 +replication_port = 33117 space[0].enabled = 1 space[0].index[0].type = "HASH" space[0].index[0].unique = 1 space[0].index[0].key_field[0].fieldno = 0 space[0].index[0].key_field[0].type = "NUM" + +memcached_space = 2 +memcached_expire=true diff --git a/test/replication/consistent.result b/test/replication/consistent.result index 24538e947d46da37728521d8564f4b7140df283c..d254e5c90726e1c8ca41df47d1e884c837232f3d 100644 --- a/test/replication/consistent.result +++ b/test/replication/consistent.result @@ -684,4 +684,4 @@ Found 1 tuple: master lsn = 61 replica lsn = 61 insert into t0 values (0, 'replica is read only') -An error occurred: ER_NONMASTER, 'Can't modify data on a replication slave. My master is: 127.0.0.1:33016' +An error occurred: ER_NONMASTER, 'Can't modify data on a replication slave. My master is: 127.0.0.1:33017' diff --git a/test/replication/consistent.test b/test/replication/consistent.test index e978c417326c3edcc6b9937e957d04027e6514d7..b537f7baf9e215e443addb6ce09c033c6248b35c 100644 --- a/test/replication/consistent.test +++ b/test/replication/consistent.test @@ -1,7 +1,7 @@ # encoding: tarantool import os import time -from lib.tarantool_box_server import TarantoolBoxServer +from lib.tarantool_server import TarantoolServer ID_BEGIN = 0 ID_STEP = 10 @@ -22,7 +22,7 @@ def select_tuples(server, begin, end): master = server # replica server -replica = TarantoolBoxServer() +replica = TarantoolServer() replica.deploy("replication/cfg/replica.cfg", replica.find_exe(self.args.builddir), os.path.join(self.args.vardir, "replica")) diff --git a/test/replication/hot_standby.test b/test/replication/hot_standby.test index 4689c4bca79301f13d156dda12531624443690aa..8f8e68cf62147f5561d544e8b3a9c083512950cb 100644 --- a/test/replication/hot_standby.test +++ b/test/replication/hot_standby.test @@ -1,21 +1,21 @@ # encoding: tarantool import os import time -from lib.tarantool_box_server import TarantoolBoxServer +from lib.tarantool_server import TarantoolServer # master server master = server master_sql = master.sql # hot standby server -hot_standby = TarantoolBoxServer() +hot_standby = TarantoolServer() hot_standby.deploy("replication/cfg/hot_standby.cfg", hot_standby.find_exe(self.args.builddir), os.path.join(self.args.vardir, "hot_standby"), need_init=False) hot_standby_sql = hot_standby.sql # replica server -replica = TarantoolBoxServer() +replica = TarantoolServer() replica.deploy("replication/cfg/replica.cfg", replica.find_exe(self.args.builddir), os.path.join(self.args.vardir, "replica")) diff --git a/test/replication/memcached.result b/test/replication/memcached.result new file mode 100644 index 0000000000000000000000000000000000000000..fb1629897d9356a340f447a1c8b9563aac0da59c --- /dev/null +++ b/test/replication/memcached.result @@ -0,0 +1,52 @@ +# set initial k-v pairs +# wait and get last k-v pair from replica +get 9 +VALUE 9 0 5 +good9 +END +# make multiple cnanges with master +# wait and get k-v's from replicas +get 1 2 3 4 5 7 8 9 10 +VALUE 1 0 8 +good1afk +VALUE 2 0 8 +kfagood2 +VALUE 3 0 2 +95 +VALUE 4 0 2 +45 +VALUE 5 0 5 +good5 +VALUE 7 0 21 +The expense of spirit +VALUE 8 0 19 +in a waste of shame +VALUE 9 0 18 +Is lust in action; +VALUE 10 0 21 +and till action, lust +END +# get deleted value +get 6 +END +# flush all k-v on master and try to get them from replica +get 10 +END +# check that expiration is working properly on replica +get 1 +VALUE 1 0 21 +The expense of spirit +END +get 1 +END +# check that expiration is working properly, when replica becomes master +reload configuration +--- +ok +... +get 1 +VALUE 1 0 21 +The expense of spirit +END +get 1 +END diff --git a/test/replication/memcached.test b/test/replication/memcached.test new file mode 100644 index 0000000000000000000000000000000000000000..0152df2e3cd20200b7f89813956dfe3cd8c5e15f --- /dev/null +++ b/test/replication/memcached.test @@ -0,0 +1,123 @@ +# encoding: tarantool +import os +import sys +import time +import yaml + +from lib.memcached_connection import MemcachedConnection +from lib.tarantool_server import TarantoolServer + +sonet = """The expense of spirit +in a waste of shame +Is lust in action; +and till action, lust""".split('\n') + +master = server +master_memcached = master.memcached + +replica = TarantoolServer() +replica.deploy("replication/cfg/replica.cfg", + replica.find_exe(self.args.builddir), + os.path.join(self.args.vardir, "replica")) +replica_memcached = replica.memcached + +################################### +def wait_for_lsn(lsn, serv): + serv_admin = serv.admin + while True: + if get_lsn(serv) == lsn: + return lsn + time.sleep(0.01) + +def wait_for_next_lsn(lsn, serv): + serv_admin = serv.admin + while True: + if get_lsn(serv) != lsn: + return lsn + time.sleep(0.01) + +def get_lsn(serv): + serv_admin = serv.admin + resp = exec serv_admin silent "lua box.info.lsn" + return yaml.load(resp)[0] + +def wait(next = False, serv_master = master, serv_replica = replica): + if next: + lsn = get_lsn(serv_replica) + return wait_for_next_lsn(lsn, serv_replica) + else: + lsn = get_lsn(serv_master) + return wait_for_lsn(lsn, serv_replica) + +def get_memcached_len(serv): + serv_admin = serv.admin + resp = exec serv_admin silent "lua box.space[box.cfg.memcached_space]:len()" + return yaml.load(resp)[0] + + +def wait_for_empty_space(serv): + serv_admin = serv.admin + while True: + if get_memcached_len(serv) == 0: + return + time.sleep(0.01) + +################################### + +print """# set initial k-v pairs""" +for i in xrange(10): + exec master_memcached silent "set %d 0 0 5\r\ngood%d\r\n" % (i, i) + +print """# wait and get last k-v pair from replica""" +wait() +exec replica_memcached "get 9\r\n" + +print """# make multiple cnanges with master""" +answer = exec master_memcached silent "gets 9\r\n" +cas = int(answer.split()[4]) +exec master_memcached silent "append 1 0 0 3\r\nafk\r\n" +exec master_memcached silent "prepend 2 0 0 3\r\nkfa\r\n" +exec master_memcached silent "set 3 0 0 2\r\n80\r\n" +exec master_memcached silent "set 4 0 0 2\r\n60\r\n" +exec master_memcached silent "delete 6\r\n" +exec master_memcached silent "replace 7 0 0 %d\r\n%s\r\n" % (len(sonet[0]), sonet[0]) +exec master_memcached silent "replace 8 0 0 %d\r\n%s\r\n" % (len(sonet[1]), sonet[1]) +exec master_memcached silent "cas 9 0 0 %d %d\r\n%s\r\n" % (len(sonet[2]), cas, sonet[2]) +exec master_memcached silent "add 10 0 0 %d\r\n%s\r\n" % (len(sonet[3]), sonet[3]) +exec master_memcached silent "incr 3 15\r\n" +exec master_memcached silent "decr 4 15\r\n" + +print """# wait and get k-v's from replicas""" +wait() +exec replica_memcached "get 1 2 3 4 5 7 8 9 10\r\n" + +print """# get deleted value""" +exec replica_memcached "get 6\r\n" + +print """# flush all k-v on master and try to get them from replica""" +exec master_memcached silent "flush_all\r\n" +wait_for_empty_space(replica) +exec replica_memcached "get 10\r\n" + + +print """# check that expiration is working properly on replica""" +exec master_memcached silent "set 1 0 1 %d\r\n%s\r\n" % (len(sonet[0]), sonet[0]) +wait() +exec replica_memcached "get 1\r\n" +wait(True) +exec replica_memcached "get 1\r\n" + +print """# check that expiration is working properly, when replica becomes master""" +exec master_memcached silent "set 1 0 1 %d\r\n%s\r\n" % (len(sonet[0]), sonet[0]) +replica.reconfigure("replication/cfg/replica_to_master.cfg") +exec replica_memcached "get 1\r\n" +wait(True) +exec replica_memcached "get 1\r\n" + + +# resore default suite config +replica.stop() +replica.cleanup(True) +master.stop() +master.deploy(self.suite_ini["config"]) +# vim: syntax=python diff --git a/test/replication/swap.test b/test/replication/swap.test index 7f47bbe5007aec017a3bf94d1f243a040a0663fd..82afc13cc29f06f27e8c4da79e66adc3c0940785 100644 --- a/test/replication/swap.test +++ b/test/replication/swap.test @@ -1,7 +1,7 @@ # encoding: tarantool import os import time -from lib.tarantool_box_server import TarantoolBoxServer +from lib.tarantool_server import TarantoolServer REPEAT = 20 ID_BEGIN = 0 @@ -23,7 +23,7 @@ def select_tuples(server, begin, end): master = server # replica server -replica = TarantoolBoxServer() +replica = TarantoolServer() replica.deploy("replication/cfg/replica.cfg", replica.find_exe(self.args.builddir), os.path.join(self.args.vardir, "replica")) diff --git a/test/share/tarantool_box.sup b/test/share/tarantool.sup similarity index 100% rename from test/share/tarantool_box.sup rename to test/share/tarantool.sup diff --git a/test/test-run.py b/test/test-run.py index 2d8428376befa4cabf27529fe7c58d074639fc27..392ac2273d8834eba8228132a74e26f8c6f0ee8f 100755 --- a/test/test-run.py +++ b/test/test-run.py @@ -24,12 +24,14 @@ __author__ = "Konstantin Osipov <kostja.osipov@gmail.com>" # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. -import argparse -import os.path import os -import time import sys +import time import string +import shutil +import os.path +import argparse + from lib.test_suite import TestSuite # @@ -58,14 +60,6 @@ class Options: suites, "box/show" will only enable tests starting with "show" in "box" suite. Default: run all tests in all specified suites.""") - parser.add_argument( - "--module", - dest = 'modules', - metavar = "module", - nargs="*", - default = ["box"], - help = "List of modules to test. Default: \"box\"") - parser.add_argument( "--suite", dest = 'suites', @@ -162,8 +156,14 @@ def main(): options = Options() oldcwd = os.getcwd() # Change the current working directory to where all test - # collections are supposed to reside. - os.chdir(os.path.dirname(sys.argv[0])) + # collections are supposed to reside + # If script executed with (python test-run.py) dirname is '' + # so we need to make it . + path = os.path.dirname(sys.argv[0]) + if not path: + path = '.' + os.chdir(path) + failed_tests = 0 try: @@ -175,13 +175,9 @@ def main(): for root, dirs, names in os.walk(os.getcwd()): if "suite.ini" in names: suite_names.append(os.path.basename(root)) - suites = [] - for suite_name in suite_names: - suite = TestSuite(suite_name, options.args) - if suite.ini["module"] not in options.args.modules: - continue - suites.append(suite) + suites = [TestSuite(suite_name, options.args) for suite_name in sorted(suite_names)] + for suite in suites: failed_tests += suite.run_all() except RuntimeError as e: diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 934e68d42dae60701eb64d45b6349016d578f32d..1b3a87cfe96f354ff9e86035b5be8d866ef0b56f 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -1,19 +1,19 @@ file(GLOB all_sources *.c *.m *.mm) set_source_files_compile_flags(${all_sources}) -add_executable(rlist rlist.c test.c) -add_executable(queue queue.c) -add_executable(mhash mhash.c) -add_executable(rope_basic rope_basic.c ${CMAKE_SOURCE_DIR}/src/rope.c) -add_executable(rope_avl rope_avl.c ${CMAKE_SOURCE_DIR}/src/rope.c) -add_executable(rope_stress rope_stress.c ${CMAKE_SOURCE_DIR}/src/rope.c) -add_executable(rope rope.c ${CMAKE_SOURCE_DIR}/src/rope.c) -add_executable(bit_test bit.c bit.c) -target_link_libraries(bit_test bit) -add_executable(bitset_basic_test bitset_basic.c) -target_link_libraries(bitset_basic_test bitset) -add_executable(bitset_iterator_test bitset_iterator.c) -target_link_libraries(bitset_iterator_test bitset) -add_executable(bitset_index_test bitset_index.c) -target_link_libraries(bitset_index_test bitset) -add_executable(base64 base64.c ${CMAKE_SOURCE_DIR}/third_party/base64.c) +add_executable(rlist.test rlist.c test.c) +add_executable(queue.test queue.c) +add_executable(mhash.test mhash.c) +add_executable(rope_basic.test rope_basic.c ${CMAKE_SOURCE_DIR}/src/rope.c) +add_executable(rope_avl.test rope_avl.c ${CMAKE_SOURCE_DIR}/src/rope.c) +add_executable(rope_stress.test rope_stress.c ${CMAKE_SOURCE_DIR}/src/rope.c) +add_executable(rope.test rope.c ${CMAKE_SOURCE_DIR}/src/rope.c) +add_executable(bit.test bit.c bit.c) +target_link_libraries(bit.test bit) +add_executable(bitset_basic.test bitset_basic.c) +target_link_libraries(bitset_basic.test bitset) +add_executable(bitset_iterator.test bitset_iterator.c) +target_link_libraries(bitset_iterator.test bitset) +add_executable(bitset_index.test bitset_index.c) +target_link_libraries(bitset_index.test bitset) +add_executable(base64.test base64.c ${CMAKE_SOURCE_DIR}/third_party/base64.c) diff --git a/test/unit/base64.test b/test/unit/base64.test deleted file mode 100644 index 0ed8d1b67d7103560b29ab48c9c8becec98619b8..0000000000000000000000000000000000000000 --- a/test/unit/base64.test +++ /dev/null @@ -1 +0,0 @@ -run_test("base64") diff --git a/test/unit/bit.test b/test/unit/bit.test deleted file mode 100644 index bd42398b072ea067924ad5ff0977c8109be9636c..0000000000000000000000000000000000000000 --- a/test/unit/bit.test +++ /dev/null @@ -1 +0,0 @@ -run_test("bit_test") diff --git a/test/unit/bitset_basic.test b/test/unit/bitset_basic.test deleted file mode 100644 index 080353944e138e8ed1fd5bb5d855c87de892c30a..0000000000000000000000000000000000000000 --- a/test/unit/bitset_basic.test +++ /dev/null @@ -1 +0,0 @@ -run_test("bitset_basic_test") diff --git a/test/unit/bitset_index.test b/test/unit/bitset_index.test deleted file mode 100644 index a7d9a5ec934971c94e78e1968aa7014b3111d0ce..0000000000000000000000000000000000000000 --- a/test/unit/bitset_index.test +++ /dev/null @@ -1 +0,0 @@ -run_test("bitset_index_test") diff --git a/test/unit/bitset_iterator.test b/test/unit/bitset_iterator.test deleted file mode 100644 index eb272521cb9be9cba2cf0389725ecafe2fc7e4b2..0000000000000000000000000000000000000000 --- a/test/unit/bitset_iterator.test +++ /dev/null @@ -1 +0,0 @@ -run_test("bitset_iterator_test") diff --git a/test/unit/mhash.test b/test/unit/mhash.test deleted file mode 100644 index a537d0bcbbeb6938ea3f119d7401096c81d194f3..0000000000000000000000000000000000000000 --- a/test/unit/mhash.test +++ /dev/null @@ -1 +0,0 @@ -run_test("mhash") diff --git a/test/unit/queue.test b/test/unit/queue.test deleted file mode 100644 index 78ef0b17533ec9c2d5085770247fc97a6f609193..0000000000000000000000000000000000000000 --- a/test/unit/queue.test +++ /dev/null @@ -1 +0,0 @@ -run_test("queue") diff --git a/test/unit/rlist.test b/test/unit/rlist.test deleted file mode 100644 index 5c8699160c2e47c699d67a94854f57394554b6d5..0000000000000000000000000000000000000000 --- a/test/unit/rlist.test +++ /dev/null @@ -1 +0,0 @@ -run_test("rlist") diff --git a/test/unit/rope.test b/test/unit/rope.test deleted file mode 100644 index 69d20903c14769eaf16b11fcfa5ee42027e8d2e1..0000000000000000000000000000000000000000 --- a/test/unit/rope.test +++ /dev/null @@ -1 +0,0 @@ -run_test("rope") diff --git a/test/unit/rope_avl.test b/test/unit/rope_avl.test deleted file mode 100644 index 416fc384267bd0b10d321702514f93cc2aa1905d..0000000000000000000000000000000000000000 --- a/test/unit/rope_avl.test +++ /dev/null @@ -1 +0,0 @@ -run_test("rope_avl") diff --git a/test/unit/rope_basic.test b/test/unit/rope_basic.test deleted file mode 100644 index ff8723e8a0cbdc70299965f88f8f8356c14faf71..0000000000000000000000000000000000000000 --- a/test/unit/rope_basic.test +++ /dev/null @@ -1 +0,0 @@ -run_test("rope_basic") diff --git a/test/unit/rope_stress.test b/test/unit/rope_stress.test deleted file mode 100644 index 6c3a3e7fc6ebeb21eaeb4d3f049c867695fac7ff..0000000000000000000000000000000000000000 --- a/test/unit/rope_stress.test +++ /dev/null @@ -1 +0,0 @@ -run_test("rope_stress") diff --git a/test/unit/suite.ini b/test/unit/suite.ini index 47106bc06f6f84d1cf4e8cae77974fae77fc076c..4d69f51aa5f459f513515612149f647ea337d22c 100644 --- a/test/unit/suite.ini +++ b/test/unit/suite.ini @@ -1,10 +1,4 @@ [default] core = unittest -module = box -description = unit tests -config = tarantool.cfg -# put disabled tests here -#disabled = xlog.test -# put disabled in valgrind test here -#valgrind_disabled = admin_coredump.test -#release_disabled = errinj.test +description = unit tests +