Commit a9c8f164 authored by Benjamin Blanc's avatar Benjamin Blanc

Fix bug(s) and add a scalability unit test

parent 4d50b6ca
...@@ -475,9 +475,9 @@ branch = foo ...@@ -475,9 +475,9 @@ branch = foo
def patch_getSlaposAccountCertificate(self, *args, **kw): def patch_getSlaposAccountCertificate(self, *args, **kw):
return "Certificate" return "Certificate"
def patch_generateConfiguration(self, *args, **kw): def patch_generateConfiguration(self, *args, **kw):
return '{"configuration_list": [], "involved_nodes_computer_guid"\ return json.dumps({"configuration_list": [], "involved_nodes_computer_guid"\
: [], "error_message": "No error.", "launcher_nodes_computer_guid": {}, \ : [], "error_message": "No error.", "launcher_nodes_computer_guid": [], \
"launchable": false, "randomized_path" : "azertyuiop"}' "launchable": False, "randomized_path" : "azertyuiop"})
def patch_isMasterTestnode(self, *args, **kw): def patch_isMasterTestnode(self, *args, **kw):
return (grade == 'master') return (grade == 'master')
test_self = self test_self = self
...@@ -490,7 +490,10 @@ branch = foo ...@@ -490,7 +490,10 @@ branch = foo
config_list = [] config_list = []
# Sclalability slave testnode is not directly in charge of testsuites # Sclalability slave testnode is not directly in charge of testsuites
if my_test_type == 'ScalabilityTest' and grade == 'slave': if my_test_type == 'ScalabilityTest' and grade == 'slave':
return [] if counter == 5:
raise StopIteration
counter += 1
return json.dumps([])
def _checkExistingTestSuite(reference_set): def _checkExistingTestSuite(reference_set):
test_self.assertEquals(set(reference_set), test_self.assertEquals(set(reference_set),
...@@ -564,12 +567,7 @@ branch = foo ...@@ -564,12 +567,7 @@ branch = foo
SlapOSControler.initializeSlapOSControler = doNothing SlapOSControler.initializeSlapOSControler = doNothing
# Inside test_node a runner is created using new UnitTestRunner methods # Inside test_node a runner is created using new UnitTestRunner methods
test_node.run() test_node.run()
# Doesn't have to install sofwtare themself self.assertEquals(5, counter)
if my_test_type == 'ScalabilityTest' and grade == 'slave' :
self.assertEquals(0, counter)
else :
self.assertEquals(5, counter)
time.sleep = original_sleep time.sleep = original_sleep
# Restore old class methods # Restore old class methods
if my_test_type == "ScalabilityTest": if my_test_type == "ScalabilityTest":
...@@ -632,11 +630,11 @@ branch = foo ...@@ -632,11 +630,11 @@ branch = foo
def patch_getSlaposAccountCertificate(self, *args, **kw): def patch_getSlaposAccountCertificate(self, *args, **kw):
return "Certificate" return "Certificate"
def patch_generateConfiguration(self, *args, **kw): def patch_generateConfiguration(self, *args, **kw):
return '{"configuration_list": [], "involved_nodes_computer_guid"\ return json.dumps({"configuration_list": [], "involved_nodes_computer_guid"\
: [], "error_message": "No error.", "launcher_nodes_computer_guid": {}, \ : [], "error_message": "No error.", "launcher_nodes_computer_guid": [], \
"launchable": false, "randomized_path" : "azertyuiop"}' "launchable": False, "randomized_path" : "azertyuiop"})
def patch_isMasterTestnode(self, *args, **kw): def patch_isMasterTestnode(self, *args, **kw):
return (grade == 'master') return grade == 'master'
test_self = self test_self = self
test_result_path_root = os.path.join(test_self._temp_dir,'test/results') test_result_path_root = os.path.join(test_self._temp_dir,'test/results')
os.makedirs(test_result_path_root) os.makedirs(test_result_path_root)
...@@ -854,4 +852,85 @@ branch = foo ...@@ -854,4 +852,85 @@ branch = foo
def test_scalability_18_resetSoftwareAfterManyBuildFailures(self, my_test_type='ScalabilityTest'): def test_scalability_18_resetSoftwareAfterManyBuildFailures(self, my_test_type='ScalabilityTest'):
# TODO : write own scalability test # TODO : write own scalability test
pass pass
#TODO : add more test for scalability case
def test_zzzz_scalability_19_xxxx(self):
def patch_createTestResult(self, revision, test_name_list, node_title,
allow_restart=False, test_title=None, project_title=None):
test_result_path = os.path.join(test_result_path_root, test_title)
result = TestResultProxy(self._proxy, self._retry_time,
self._logger, test_result_path, node_title, revision)
return result
global startTestSuiteDone
startTestSuiteDone = False
def patch_startTestSuite(self,test_node_title):
config_list = []
global startTestSuiteDone
if not startTestSuiteDone:
startTestSuiteDone = True
config_list.append(test_self.getTestSuiteData(reference='foo')[0])
config_list.append(test_self.getTestSuiteData(reference='bar')[0])
else:
raise StopIteration
return json.dumps(config_list)
def patch_isMasterTestnode(self, *args, **kw):
return True
def patch_generateConfiguration(self, *args, **kw):
return json.dumps({"configuration_list": [{"ok":"ok"}], "involved_nodes_computer_guid"\
: ["COMP1", "COMP2", "COMP3"], "error_message": "No error.", "launcher_nodes_computer_guid": ["COMP1"], \
"launchable": False, "randomized_path" : "azertyuiop"})
def doNothing(self, *args, **kw):
pass
def patch_getSlaposAccountKey(self, *args, **kw):
return "key"
def patch_getSlaposAccountCertificate(self, *args, **kw):
return "Certificate"
def patch_getTestType(self, *args, **kw):
return "ScalabilityTest"
test_self = self
test_result_path_root = os.path.join(test_self._temp_dir,'test/results')
os.makedirs(test_result_path_root)
self.generateTestRepositoryList()
# Select the good runner to modify
RunnerClass = self.returnGoodClassRunner('ScalabilityTest')
# Patch methods
original_sleep = time.sleep
original_getSlaposAccountKey = TaskDistributor.getSlaposAccountKey
original_getSlaposAccountCertificate = TaskDistributor.getSlaposAccountCertificate
original_generateConfiguration = TaskDistributor.generateConfiguration
original_isMasterTestnode = TaskDistributor.isMasterTestnode
original_startTestSuite = TaskDistributor.startTestSuite
original_subscribeNode = TaskDistributor.subscribeNode
original_getTestType = TaskDistributor.getTestType
original_createTestResult = TaskDistributionTool.createTestResult
original_prepareSlapOS = RunnerClass._prepareSlapOS
original_runTestSuite = RunnerClass.runTestSuite
original_supply = SlapOSControler.supply
#
time.sleep = doNothing
TaskDistributor.getSlaposAccountKey = patch_getSlaposAccountKey
TaskDistributor.getSlaposAccountCertificate = patch_getSlaposAccountCertificate
TaskDistributor.generateConfiguration = patch_generateConfiguration
TaskDistributor.isMasterTestnode = patch_isMasterTestnode
TaskDistributor.startTestSuite = patch_startTestSuite
TaskDistributor.subscribeNode = doNothing
TaskDistributor.getTestType = patch_getTestType
TaskDistributionTool.createTestResult = patch_createTestResult
RunnerClass._prepareSlapOS = doNothing
RunnerClass.runTestSuite = doNothing
SlapOSControler.supply = doNothing
# Run
test_node = self.getTestNode()
test_node.run()
# Restore methods
TaskDistributor.getSlaposAccountKey = original_getSlaposAccountKey
TaskDistributor.getSlaposAccountCertificate = original_getSlaposAccountCertificate
TaskDistributor.generateConfiguration = original_generateConfiguration
TaskDistributor.isMasterTestnode = original_isMasterTestnode
TaskDistributor.startTestSuite = original_startTestSuite
TaskDistributionTool.createTestResult = original_createTestResult
TaskDistributionTool.subscribeNode = original_subscribeNode
TaskDistributionTool.getTestType = original_getTestType
RunnerClass._prepareSlapOS = original_prepareSlapOS
RunnerClass.runTestSuite = original_runTestSuite
SlapOSControler.supply = original_supply
time.sleep =original_sleep
...@@ -49,17 +49,18 @@ import signal ...@@ -49,17 +49,18 @@ import signal
class ScalabilityTestRunner(): class ScalabilityTestRunner():
def __init__(self, testnode): def __init__(self, testnode):
self.testnode = testnode self.testnode = testnode
self.log = self.testnode.log
self.slapos_controler = SlapOSControler.SlapOSControler( self.slapos_controler = SlapOSControler.SlapOSControler(
self.testnode.working_directory, self.testnode.working_directory,
self.testnode.config, self.testnode.config,
self.testnode.log) self.log)
# Create the slapos account configuration file and dir # Create the slapos account configuration file and dir
key = self.testnode.test_suite_portal.getSlaposAccountKey() key = self.testnode.test_suite_portal.getSlaposAccountKey()
certificate = self.testnode.test_suite_portal.getSlaposAccountCertificate() certificate = self.testnode.test_suite_portal.getSlaposAccountCertificate()
self.slapos_controler.createSlaposConfigurationFileAccount(key,certificate, self.slapos_controler.createSlaposConfigurationFileAccount(key,certificate,
self.testnode.config) self.testnode.config)
self.remaining_software_installation_dict = {} self.remaining_software_installation_dict = {}
# Protection to prevent installation of softwares after checking # Protection to prevent installation of softwares after checking
...@@ -72,7 +73,7 @@ class ScalabilityTestRunner(): ...@@ -72,7 +73,7 @@ class ScalabilityTestRunner():
""" """
A proxy to supply : Install a software on a specific node A proxy to supply : Install a software on a specific node
""" """
self.testnode.log("testnode, supply : %s %s", software_path, computer_guid) self.log("testnode, supply : %s %s", software_path, computer_guid)
if self.authorize_supply : if self.authorize_supply :
self.remaining_software_installation_dict[computer_guid] = software_path self.remaining_software_installation_dict[computer_guid] = software_path
self.slapos_controler.supply(software_path, computer_guid) self.slapos_controler.supply(software_path, computer_guid)
...@@ -94,7 +95,7 @@ class ScalabilityTestRunner(): ...@@ -94,7 +95,7 @@ class ScalabilityTestRunner():
# Dummy slapos answering # Dummy slapos answering
def _getSignal(self, signal, frame): def _getSignal(self, signal, frame):
self.testnode.log("Dummy SlapOS Master answer received.") self.log("Dummy SlapOS Master answer received.")
self.last_slapos_answer.append(True) self.last_slapos_answer.append(True)
def _prepareDummySlapOSAnswer(self): def _prepareDummySlapOSAnswer(self):
print "Dummy slapOS answer enabled, send signal to %s (=PID) to simu\ print "Dummy slapOS answer enabled, send signal to %s (=PID) to simu\
...@@ -155,21 +156,21 @@ late a SlapOS (positive) answer." %(str(os.getpid()),) ...@@ -155,21 +156,21 @@ late a SlapOS (positive) answer." %(str(os.getpid()),)
# Avoid the test if it is not launchable # Avoid the test if it is not launchable
if not self.launchable: if not self.launchable:
self.testnode.log("Test suite %s is not actually launchable with \ self.log("Test suite %s is not actually launchable with \
the current cluster configuration." %(node_test_suite.test_suite_title,)) the current cluster configuration." %(node_test_suite.test_suite_title,))
self.testnode.log("ERP5 Master indicates : %s" %(self.error_message,)) self.log("ERP5 Master indicates : %s" %(self.error_message,))
# error : wich code to return ? # error : wich code to return ?
return {'status_code' : 1} return {'status_code' : 1}
# create an obfuscated link to the testsuite directory # create an obfuscated link to the testsuite directory
self.testnode.log("self.testnode.config['software_directory']\ self.log("self.testnode.config['software_directory']\
: %s" %(self.testnode.config['software_directory'])) : %s" %(self.testnode.config['software_directory']))
self.testnode.log("self.randomized_path\ self.log("self.randomized_path\
: %s" %(self.randomized_path)) : %s" %(self.randomized_path))
path_to_suite = os.path.join( path_to_suite = os.path.join(
self.testnode.config['working_directory'], self.testnode.config['working_directory'],
node_test_suite.reference) node_test_suite.reference)
self.testnode.log("path_to_suite\ self.log("path_to_suite\
: %s" %(path_to_suite)) : %s" %(path_to_suite))
self.ofuscated_link_path = os.path.join( self.ofuscated_link_path = os.path.join(
self.testnode.config['software_directory'], self.testnode.config['software_directory'],
...@@ -181,7 +182,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),) ...@@ -181,7 +182,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),)
except : except :
raise ValueError("testnode, Unable to create symbolic link to the testsuite.") raise ValueError("testnode, Unable to create symbolic link to the testsuite.")
self.testnode.log("Sym link : %s %s" %(path_to_suite, self.ofuscated_link_path)) self.log("Sym link : %s %s" %(path_to_suite, self.ofuscated_link_path))
involved_nodes_computer_guid = test_configuration['involved_nodes_computer_guid'] involved_nodes_computer_guid = test_configuration['involved_nodes_computer_guid']
...@@ -192,7 +193,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),) ...@@ -192,7 +193,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),)
self.reachable_profile = os.path.join( self.reachable_profile = os.path.join(
"https://","["+self.testnode.config['httpd_ip']+"]"+":"+self.testnode.config['httpd_software_access_port'], "https://","["+self.testnode.config['httpd_ip']+"]"+":"+self.testnode.config['httpd_software_access_port'],
self.randomized_path, "software.cfg") self.randomized_path, "software.cfg")
self.testnode.log("Software reachable profile path is : %s " self.log("Software reachable profile path is : %s "
%(self.reachable_profile,)) %(self.reachable_profile,))
software_path_list.append(self.reachable_profile) software_path_list.append(self.reachable_profile)
# Ask for softwares installation # Ask for softwares installation
...@@ -206,7 +207,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),) ...@@ -206,7 +207,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),)
# Waiting until all softwares are installed # Waiting until all softwares are installed
while ( self.remainSoftwareToInstall() while ( self.remainSoftwareToInstall()
and (max_time > (time.time()-start_time))): and (max_time > (time.time()-start_time))):
self.testnode.log("Master testnode is waiting\ self.log("Master testnode is waiting\
for the end of all software installation (for %ss).", for the end of all software installation (for %ss).",
str(int(time.time()-start_time))) str(int(time.time()-start_time)))
time.sleep(interval_time) time.sleep(interval_time)
...@@ -215,7 +216,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),) ...@@ -215,7 +216,7 @@ late a SlapOS (positive) answer." %(str(os.getpid()),)
self._comeBackFromDummySlapOS() self._comeBackFromDummySlapOS()
if self.remainSoftwareToInstall() : if self.remainSoftwareToInstall() :
return {'status_code' : 1} return {'status_code' : 1}
self.testnode.log("Softwares installed") self.log("Softwares installed")
return {'status_code' : 0} return {'status_code' : 0}
def _cleanUpNodesInformation(self): def _cleanUpNodesInformation(self):
......
...@@ -38,6 +38,9 @@ import logging ...@@ -38,6 +38,9 @@ import logging
import string import string
import random import random
import testnodeUtils import testnodeUtils
import traceback
from ProcessManager import SubprocessError, ProcessManager, CancellationError from ProcessManager import SubprocessError, ProcessManager, CancellationError
from subprocess import CalledProcessError from subprocess import CalledProcessError
from Updater import Updater from Updater import Updater
...@@ -298,7 +301,6 @@ branch = %(branch)s ...@@ -298,7 +301,6 @@ branch = %(branch)s
test_node_slapos = SlapOSInstance() test_node_slapos = SlapOSInstance()
test_node_slapos.edit(working_directory=self.config['slapos_directory']) test_node_slapos.edit(working_directory=self.config['slapos_directory'])
## /BLOCK OK ## /BLOCK OK
try: try:
while True: while True:
try: try:
...@@ -310,9 +312,10 @@ branch = %(branch)s ...@@ -310,9 +312,10 @@ branch = %(branch)s
portal_url = config['test_suite_master_url'] portal_url = config['test_suite_master_url']
portal = taskdistribution.TaskDistributionTool(portal_url, logger=DummyLogger(log)) portal = taskdistribution.TaskDistributionTool(portal_url, logger=DummyLogger(log))
self.test_suite_portal = taskdistribution.TaskDistributor(portal_url, logger=DummyLogger(log)) self.test_suite_portal = taskdistribution.TaskDistributor(portal_url, logger=DummyLogger(log))
self.test_suite_portal.subscribeNode(config['test_node_title'], config['computer_id']) self.test_suite_portal.subscribeNode(config['test_node_title'], config['computer_id'])
test_suite_json = self.test_suite_portal.startTestSuite(config['test_node_title']) test_suite_json = self.test_suite_portal.startTestSuite(config['test_node_title'])
test_suite_data = testnodeUtils.deunicodeData(json.loads(test_suite_json)) test_suite_data = testnodeUtils.deunicodeData(json.loads(test_suite_json))
log("Got following test suite data from master : %r" % \ log("Got following test suite data from master : %r" % \
(test_suite_data,)) (test_suite_data,))
...@@ -337,8 +340,11 @@ from the distributor.") ...@@ -337,8 +340,11 @@ from the distributor.")
# master testnode gets test_suites, slaves get nothing # master testnode gets test_suites, slaves get nothing
runner.prepareSlapOSForTestNode(test_node_slapos) runner.prepareSlapOSForTestNode(test_node_slapos)
# Clean-up test suites # Clean-up test suites
self.checkOldTestSuite(test_suite_data)
self.checkOldTestSuite(test_suite_data)
for test_suite in test_suite_data: for test_suite in test_suite_data:
remote_test_result_needs_cleanup = False remote_test_result_needs_cleanup = False
node_test_suite = self.getNodeTestSuite( node_test_suite = self.getNodeTestSuite(
...@@ -360,13 +366,15 @@ from the distributor.") ...@@ -360,13 +366,15 @@ from the distributor.")
node_test_suite.project_title) node_test_suite.project_title)
remote_test_result_needs_cleanup = True remote_test_result_needs_cleanup = True
log("testnode, test_result : %r" % (test_result, )) log("testnode, test_result : %r" % (test_result, ))
if test_result is not None: if test_result is not None:
self.registerSuiteLog(test_result, node_test_suite) self.registerSuiteLog(test_result, node_test_suite)
self.checkRevision(test_result,node_test_suite) self.checkRevision(test_result,node_test_suite)
# Now prepare the installation of SlapOS and create instance # Now prepare the installation of SlapOS and create instance
status_dict = runner.prepareSlapOSForTestSuite(node_test_suite) status_dict = runner.prepareSlapOSForTestSuite(node_test_suite)
# Give some time so computer partitions may start # Give some time so computer partitions may start
# as partitions can be of any kind we have and likely will never have # as partitions can be of any kind we have and likely will never have
# a reliable way to check if they are up or not ... # a reliable way to check if they are up or not ...
...@@ -396,6 +404,9 @@ from the distributor.") ...@@ -396,6 +404,9 @@ from the distributor.")
node_test_suite.retry = True node_test_suite.retry = True
continue continue
except: except:
log("Errror")
ex_type, ex, tb = sys.exc_info()
traceback.print_tb(tb)
log("erp5testnode exception", exc_info=sys.exc_info()) log("erp5testnode exception", exc_info=sys.exc_info())
raise raise
now = time.time() now = time.time()
...@@ -407,6 +418,8 @@ from the distributor.") ...@@ -407,6 +418,8 @@ from the distributor.")
except: except:
log("Exception in error handling", exc_info=sys.exc_info()) log("Exception in error handling", exc_info=sys.exc_info())
finally: finally:
if 'tb' in locals():
del tb
# Nice way to kill *everything* generated by run process -- process # Nice way to kill *everything* generated by run process -- process
# groups working only in POSIX compilant systems # groups working only in POSIX compilant systems
# Exceptions are swallowed during cleanup phase # Exceptions are swallowed during cleanup phase
......
...@@ -4,13 +4,7 @@ import shutil ...@@ -4,13 +4,7 @@ import shutil
import string import string
def deunicodeData(data): def deunicodeData(data):
if isinstance(data, int): if isinstance(data, list):
new_data = data
elif isinstance(data, str):
new_data = data
elif isinstance(data, bool):
new_data = data
elif isinstance(data, list):
new_data = [] new_data = []
for sub_data in data: for sub_data in data:
new_data.append(deunicodeData(sub_data)) new_data.append(deunicodeData(sub_data))
......
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