1# Copyright (c) 2014-2015, Intel Corporation 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without modification, 5# are permitted provided that the following conditions are met: 6# 7# 1. Redistributions of source code must retain the above copyright notice, this 8# list of conditions and the following disclaimer. 9# 10# 2. Redistributions in binary form must reproduce the above copyright notice, 11# this list of conditions and the following disclaimer in the documentation and/or 12# other materials provided with the distribution. 13# 14# 3. Neither the name of the copyright holder nor the names of its contributors 15# may be used to endorse or promote products derived from this software without 16# specific prior written permission. 17# 18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29from clientsimulator.criterion.ExclusiveCriterion import ExclusiveCriterion 30from clientsimulator.configuration.ConfigParser import ConfigParser 31from clientsimulator.testGenerator.SubprocessLogger import SubprocessLoggerThread 32from clientsimulator.testGenerator.SubprocessLogger import ScriptLoggerThread 33import logging 34import json 35import time 36import os 37 38 39class TestLauncher: 40 41 """ Class which interacts with the system to launch tests """ 42 43 def __init__(self, 44 criterionClasses, 45 configParser, 46 consoleLogger): 47 """ 48 Here we create commands to launch thanks to the config Parser 49 50 :param criterionClasses: runtime generated criterion classes 51 :type criterionClasses: list of types 52 :param configParser: object which allows to get config parameters 53 :type configParser: ConfigParser 54 :param consoleLogger: console log handler 55 :type consoleLogger: Handler 56 """ 57 self.__criterionClasses = criterionClasses 58 self.__configParser = configParser 59 60 # Prepare basic commands 61 halCommand = ["remote-process", 62 "localhost", 63 configParser["TestPlatformPort"]] 64 setCriteriaCommand = halCommand + ["setCriterionState"] 65 testPlatformHostCommand = ["remote-process", 66 "localhost", 67 configParser["TestPlatformPort"]] 68 69 self.__logFileName = configParser["LogFile"] 70 71 # Commands 72 self.__startTestPlatformCmd = [configParser["PrefixCommand"], 73 "test-platform", 74 configParser["PfwConfFile"], 75 configParser["TestPlatformPort"]] 76 77 self.__createCriterionCmd = [configParser["PrefixCommand"]] 78 self.__createCriterionCmd.extend(testPlatformHostCommand) 79 80 self.__startPseudoHALCmd = [configParser["PrefixCommand"]] 81 self.__startPseudoHALCmd.extend(testPlatformHostCommand) 82 self.__startPseudoHALCmd.append("start") 83 84 self.__setCriterionCmd = [configParser["PrefixCommand"]] 85 self.__setCriterionCmd.extend(setCriteriaCommand) 86 87 self.__applyConfigurationsCmd = [configParser["PrefixCommand"]] 88 self.__applyConfigurationsCmd.extend(halCommand) 89 self.__applyConfigurationsCmd.append("applyConfigurations") 90 91 # Command used to generate coverage 92 self.__coverageCmd = [ 93 "eval", 94 os.path.join(configParser["CoverageDir"], "aplog2coverage.sh"), 95 "-d", 96 configParser["PfwDomainConfFile"], 97 "-e.", 98 self.__logFileName, 99 "-f", 100 "-o", 101 configParser["CoverageFile"] 102 ] 103 104 # Prepare script Commands 105 # Loading possible scripts 106 self.__rawScripts = {} 107 if configParser["ScriptsFile"]: 108 with open(configParser["ScriptsFile"], 'r') as scriptFile: 109 self.__rawScripts = json.load(scriptFile) 110 111 self.__availableLaunchType = ["asynchronous", "synchronous"] 112 113 self.__consoleLogger = consoleLogger 114 self.__logger = logging.getLogger(__name__) 115 self.__logger.addHandler(consoleLogger) 116 117 @property 118 def scripts(self): 119 return self.__rawScripts.keys() 120 121 def init(self, criterionClasses, isVerbose): 122 """ Initialise the Pseudo HAL """ 123 124 self.__logger.info("Pseudo Hal Initialisation") 125 # Test platform is launched asynchronously and not as script 126 self.__call_process(self.__startTestPlatformCmd, True) 127 # wait Initialisation 128 time.sleep(1) 129 130 for criterionClass in criterionClasses: 131 if ExclusiveCriterion in criterionClass.__bases__: 132 createSlctCriterionCmd = "createExclusiveSelectionCriterionFromStateList" 133 else: 134 createSlctCriterionCmd = "createInclusiveSelectionCriterionFromStateList" 135 136 createCriterionArgs = [ 137 createSlctCriterionCmd, 138 criterionClass.__name__] + criterionClass.allowedValues() 139 140 self.__call_process( 141 self.__createCriterionCmd + createCriterionArgs) 142 143 self.__call_process(self.__startPseudoHALCmd) 144 145 def executeTestVector(self, criterions): 146 """ Launch the Test """ 147 for criterion in criterions: 148 if ExclusiveCriterion in criterion.__class__.__bases__: 149 criterionValue = [criterion.currentValue] 150 else: 151 criterionValue = criterion.currentValue 152 # If no value given, we add "" to the command to set the default state 153 criterionValueArg = list(criterionValue) if list(criterionValue) else ["\"\""] 154 setCriterionArgs = [criterion.__class__.__name__] + criterionValueArg 155 self.__call_process(self.__setCriterionCmd + setCriterionArgs) 156 157 # Applying conf 158 self.__call_process(self.__applyConfigurationsCmd) 159 160 def executeScript(self, scriptName): 161 """ Launching desired test scripts """ 162 163 (script, launchType) = self.__rawScripts[scriptName] 164 165 if not launchType in self.__availableLaunchType: 166 errorMessage = "Launch type ({}) for script {} isn't recognized. ".format( 167 launchType, 168 scriptName) 169 errorMessage += "Default value ({}) has been applied.".format( 170 self.__availableLaunchType[0]) 171 172 self.__logger.error(errorMessage) 173 launchType = self.__availableLaunchType[0] 174 175 # Create and launch the command to use the desired script 176 # A script's path is absolute or relative to the "ScriptsFile" file. 177 self.__call_process( 178 ["eval", os.path.join( 179 os.path.dirname(self.__configParser["ScriptsFile"]), 180 script)], 181 launchType == self.__availableLaunchType[0], 182 True) 183 184 def generateCoverage(self): 185 """ Launch Coverage Tool on generated Log and save results in dedicated file """ 186 self.__logger.debug("Generating coverage file") 187 self.__call_process(self.__coverageCmd) 188 189 def __call_process(self, cmd, isAsynchronous=False, isScriptThread=False): 190 """ Private function which call a shell command """ 191 192 if isScriptThread: 193 self.__logger.info("Launching script : {}".format(' '.join(cmd))) 194 launcher = ScriptLoggerThread(cmd, self.__consoleLogger) 195 else: 196 self.__logger.debug("Launching command : {}".format(' '.join(cmd))) 197 launcher = SubprocessLoggerThread(cmd, self.__consoleLogger) 198 199 launcher.start() 200 201 if not isAsynchronous: 202 # if the process is synchronous, we wait him before continuing 203 launcher.join() 204