Commit f4d50823 authored by Julien Muchembled's avatar Julien Muchembled

Initial support for NEO storage in unit tests (--neostorage option)

This only implements an equivalent of DemoStorage:
- use 'BTree' as backend storage (entirely in RAM)
- not yet compatible with --load/--save

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@45695 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 0cb50e14
...@@ -20,6 +20,7 @@ instance_home = os.environ['INSTANCE_HOME'] ...@@ -20,6 +20,7 @@ instance_home = os.environ['INSTANCE_HOME']
zserver_list = os.environ.get('zserver', '').split(',') zserver_list = os.environ.get('zserver', '').split(',')
os.environ['zserver'] = zserver_list[0] os.environ['zserver'] = zserver_list[0]
neo_storage = 'neo_storage' in os.environ
zeo_client = os.environ.get('zeo_client') zeo_client = os.environ.get('zeo_client')
if zeo_client: if zeo_client:
zeo_client = zeo_client.rsplit(':', 1) zeo_client = zeo_client.rsplit(':', 1)
...@@ -28,7 +29,8 @@ if zeo_client: ...@@ -28,7 +29,8 @@ if zeo_client:
try: try:
activity_node = int(os.environ['activity_node']) activity_node = int(os.environ['activity_node'])
except KeyError: except KeyError:
activity_node = (zeo_client or 'zeo_server' in os.environ) and 1 or None activity_node = (zeo_client or neo_storage or 'zeo_server' in os.environ
) and 1 or None
data_fs_path = os.environ.get('erp5_tests_data_fs_path', data_fs_path = os.environ.get('erp5_tests_data_fs_path',
os.path.join(instance_home, 'var', 'Data.fs')) os.path.join(instance_home, 'var', 'Data.fs'))
...@@ -88,7 +90,7 @@ for static_dir in static_dir_list: ...@@ -88,7 +90,7 @@ for static_dir in static_dir_list:
os.mkdir(static_dir) os.mkdir(static_dir)
zeo_server_pid = None zeo_server_pid = None
zeo_client_pid_list = [] node_pid_list = []
ZEvent = sys.modules.get('ZServer.PubCore.ZEvent') ZEvent = sys.modules.get('ZServer.PubCore.ZEvent')
def fork(): def fork():
...@@ -103,43 +105,61 @@ def fork(): ...@@ -103,43 +105,61 @@ def fork():
instance_random.seed(instance_random.random()) instance_random.seed(instance_random.random())
return pid return pid
while not zeo_client: def forkNodes():
if activity_node: global node_pid_list
r, zeo_client = os.pipe()
zeo_server_pid = fork()
if zeo_server_pid:
save_mysql = None
os.close(zeo_client)
zeo_client = eval(os.fdopen(r).read())
continue
else:
zeo_client_pid_list = activity_node = None
os.close(r)
signal.signal(signal.SIGINT, signal.SIG_IGN)
elif activity_node is not None:
# run ZEO server but no need to fork
zeo_server_pid = 0
if save:
Storage = FileStorage(data_fs_path)
elif load:
Storage = FileStorage(data_fs_path, read_only=True)
Storage._is_read_only = False # XXX for Zope 2.8
Storage = DemoStorage(base=Storage)
else:
Storage = DemoStorage()
break
else:
for i in xrange(1, activity_node): for i in xrange(1, activity_node):
pid = fork() pid = fork()
if not pid: if not pid:
zeo_client_pid_list = None node_pid_list = None
os.environ['zserver'] = i < len(zserver_list) and zserver_list[i] or '' os.environ['zserver'] = i < len(zserver_list) and zserver_list[i] or ''
break break
zeo_client_pid_list.append(pid) node_pid_list.append(pid)
# Zope 2.12: do not import ClientStorage before forking due to client trigger
from ZEO.ClientStorage import ClientStorage if neo_storage:
Storage = ClientStorage(zeo_client) if load or save or zeo_client:
raise Exception("--neo_storage conflicts with --load/save/zeo_client")
from neo.tests.functional import NEOCluster
neo_cluster = NEOCluster(range(2), partitions=4, adapter='BTree',
temp_dir=os.getcwd(), verbose=False)
sigint = signal.signal(signal.SIGINT, signal.SIG_IGN)
neo_cluster.start()
signal.signal(signal.SIGINT, sigint)
forkNodes()
Storage = neo_cluster.getZODBStorage()
else:
neo_cluster = None
while not zeo_client:
if activity_node:
r, zeo_client = os.pipe()
zeo_server_pid = fork()
if zeo_server_pid:
save_mysql = None
os.close(zeo_client)
zeo_client = eval(os.fdopen(r).read())
continue
else:
node_pid_list = activity_node = None
os.close(r)
signal.signal(signal.SIGINT, signal.SIG_IGN)
elif activity_node is not None:
# run ZEO server but no need to fork
zeo_server_pid = 0
if save:
Storage = FileStorage(data_fs_path)
elif load:
Storage = FileStorage(data_fs_path, read_only=True)
Storage._is_read_only = False # XXX for Zope 2.8
Storage = DemoStorage(base=Storage)
else:
Storage = DemoStorage()
break
else:
forkNodes()
# Zope 2.12: do not import ClientStorage
# before forking due to client trigger
from ZEO.ClientStorage import ClientStorage
Storage = ClientStorage(zeo_client)
if zeo_client_pid_list is not None: if node_pid_list is not None:
_print("Instance at %r loaded ... " % instance_home) _print("Instance at %r loaded ... " % instance_home)
...@@ -128,6 +128,8 @@ Options: ...@@ -128,6 +128,8 @@ Options:
Make ZServer listen on given host:port Make ZServer listen on given host:port
If used with --activity_node=, this can be a If used with --activity_node=, this can be a
comma-separated list of addresses. comma-separated list of addresses.
--neo_storage Use a volatile NEO storage instead of a DemoStorage
(not compatible with --save or --load).
--products_path=path,path Comma-separated list of products paths locations --products_path=path,path Comma-separated list of products paths locations
which shall be used in test environment. which shall be used in test environment.
--sys_path=path,path Comma-separated list of paths which will be used to --sys_path=path,path Comma-separated list of paths which will be used to
...@@ -486,12 +488,12 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None): ...@@ -486,12 +488,12 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None):
import Lifetime import Lifetime
from ZEO.ClientStorage import ClientStorage from ZEO.ClientStorage import ClientStorage
from Zope2.custom_zodb import \ from Zope2.custom_zodb import Storage, save_mysql, \
save_mysql, zeo_server_pid, zeo_client_pid_list, Storage node_pid_list, neo_cluster, zeo_server_pid
def shutdown(signum, frame, signum_set=set()): def shutdown(signum, frame, signum_set=set()):
Lifetime.shutdown(0) Lifetime.shutdown(0)
signum_set.add(signum) signum_set.add(signum)
if zeo_client_pid_list is None and len(signum_set) > 1: if node_pid_list is None and len(signum_set) > 1:
# in case of ^C, a child should also receive a SIGHUP from the parent, # in case of ^C, a child should also receive a SIGHUP from the parent,
# so we merge the first 2 different signals in a single exception # so we merge the first 2 different signals in a single exception
signum_set.remove(signal.SIGHUP) signum_set.remove(signal.SIGHUP)
...@@ -508,7 +510,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None): ...@@ -508,7 +510,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None):
or not load) or not load)
if zeo_server_pid == 0: if zeo_server_pid == 0:
suite = ZEOServerTestCase('asyncore_loop') suite = ZEOServerTestCase('asyncore_loop')
elif zeo_client_pid_list is None or not test_list: elif node_pid_list is None or not test_list:
suite = ProcessingNodeTestCase('processing_node') suite = ProcessingNodeTestCase('processing_node')
if not (dummy or load): if not (dummy or load):
_print('WARNING: either --save or --load should be used because static' _print('WARNING: either --save or --load should be used because static'
...@@ -538,7 +540,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None): ...@@ -538,7 +540,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None):
if run_only: if run_only:
ERP5TypeTestLoader.filter_test_list = None ERP5TypeTestLoader.filter_test_list = None
if zeo_client_pid_list is None: if node_pid_list is None:
result = suite() result = suite()
else: else:
if not test_list: if not test_list:
...@@ -548,16 +550,18 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None): ...@@ -548,16 +550,18 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None):
finally: finally:
ProcessingNodeTestCase.unregisterNode() ProcessingNodeTestCase.unregisterNode()
Storage.close() Storage.close()
if zeo_client_pid_list is not None: if node_pid_list is not None:
# Wait that child processes exit. Stop ZEO storage (if any) after all # Wait that child processes exit. Stop ZEO storage (if any) after all
# other nodes disconnected. # other nodes disconnected.
for pid in zeo_client_pid_list: for pid in node_pid_list:
os.kill(pid, signal.SIGHUP) os.kill(pid, signal.SIGHUP)
for pid in zeo_client_pid_list: for pid in node_pid_list:
os.waitpid(pid, 0) os.waitpid(pid, 0)
if zeo_server_pid: if zeo_server_pid:
os.kill(zeo_server_pid, signal.SIGHUP) os.kill(zeo_server_pid, signal.SIGHUP)
os.waitpid(zeo_server_pid, 0) os.waitpid(zeo_server_pid, 0)
if neo_cluster:
neo_cluster.stop()
if save: if save:
os.chdir(instance_home) os.chdir(instance_home)
...@@ -584,7 +588,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None): ...@@ -584,7 +588,7 @@ def runUnitTestList(test_list, verbosity=1, debug=0, run_only=None):
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
os.rename(static_dir, backup_path) os.rename(static_dir, backup_path)
elif zeo_client_pid_list is not None: elif node_pid_list is not None:
_print('WARNING: No static files saved. You will have to do it manually.') _print('WARNING: No static files saved. You will have to do it manually.')
return result return result
...@@ -633,6 +637,7 @@ def main(argument_list=None): ...@@ -633,6 +637,7 @@ def main(argument_list=None):
"zeo_client=", "zeo_client=",
"zeo_server=", "zeo_server=",
"zserver=", "zserver=",
"neo_storage",
"products_path=", "products_path=",
"sys_path=", "sys_path=",
"instance_home=", "instance_home=",
...@@ -732,6 +737,8 @@ def main(argument_list=None): ...@@ -732,6 +737,8 @@ def main(argument_list=None):
os.environ["zeo_server"] = arg os.environ["zeo_server"] = arg
elif opt == "--zserver": elif opt == "--zserver":
os.environ["zserver"] = arg os.environ["zserver"] = arg
elif opt == "--neo_storage":
os.environ["neo_storage"] = ""
elif opt == "--products_path": elif opt == "--products_path":
os.environ["PRODUCTS_PATH"] = arg os.environ["PRODUCTS_PATH"] = arg
elif opt == "--sys_path": elif opt == "--sys_path":
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment