| # Copyright (c) 2014-2015, Intel Corporation |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without modification, |
| # are permitted provided that the following conditions are met: |
| # |
| # 1. Redistributions of source code must retain the above copyright notice, this |
| # list of conditions and the following disclaimer. |
| # |
| # 2. Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation and/or |
| # other materials provided with the distribution. |
| # |
| # 3. Neither the name of the copyright holder nor the names of its contributors |
| # may be used to endorse or promote products derived from this software without |
| # specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import json |
| import logging |
| |
| |
| class Scenario: |
| |
| """ |
| Class which can handle several TestVectors and script |
| to play a complete scenario. |
| """ |
| |
| def __init__(self, |
| consoleLogger, |
| scenarioFileName, |
| actionGathererFileName, |
| testFactory, |
| testLauncher): |
| """ |
| Init function |
| |
| :param consoleLogger: console log handler |
| :type consoleLogger: Handler |
| :param scenarioFileName: name of file containing scenario description |
| :type scenarioFileName: string |
| :param actionGathererFileName: conf file which allows to reduce action repetition |
| :type actionGathererFileName: string |
| :param testFactory: the factory used to generate tests from setCriterion actions |
| :type testFactory: TestVectorFactory |
| :param testLauncher: object used to execute actions from scenarios |
| :type testLauncher: TestLauncher |
| """ |
| self.__logger = logging.getLogger(__name__) |
| self.__logger.addHandler(consoleLogger) |
| |
| self.__testFactory = testFactory |
| self.__testLauncher = testLauncher |
| |
| # Simplify the way to get an action behaviour |
| # Python way to replace switch statement but keeping the possibility |
| # to get keys (usefull in __parseScenarioActions) |
| self.__actionTypeBehaviour = { |
| "setCriterion": |
| lambda rawCriterions: |
| self.__testLauncher.executeTestVector( |
| self.__testFactory.generateTestVector(rawCriterions)), |
| "script": |
| self.__testLauncher.executeScript |
| } |
| |
| self.__scenarioActions = self.__parseScenarioActions( |
| scenarioFileName, |
| actionGathererFileName) |
| |
| def __parseScenarioActions(self, scenarioFileName, actionGathererFileName): |
| """ |
| Parse actions from a scenario. |
| Convert user-defined actions in system-known actions. |
| |
| :param scenarioFileName: name of file containing scenario description |
| :type scenarioFileName: string |
| :param actionGathererFileName: conf file which allows to reduce action repetition |
| :type actionGathererFileName: string |
| |
| :return: parsed scenario's actions with system-known types |
| :rtype: dict |
| """ |
| |
| # Parsing of Json test file |
| with open(scenarioFileName, "r") as scenarioFile: |
| scenarioActions = json.load(scenarioFile) |
| |
| # Parsing the action Gatherer file which allows defining new |
| # actions types |
| scenarioGatheredActions = {} |
| if actionGathererFileName: |
| with open(actionGathererFileName, "r") as actionGathererFile: |
| scenarioGatheredActions = json.load(actionGathererFile) |
| |
| for action in scenarioActions: |
| actionDefinedType = self.__getActionType(action) |
| if actionDefinedType in self.__actionTypeBehaviour.keys(): |
| continue |
| |
| try: |
| actionValue = action.pop(actionDefinedType) |
| actionGatherer = scenarioGatheredActions[actionDefinedType] |
| except KeyError as e: |
| self.__logger.error( |
| "Actions {} from {} file is not valid".format( |
| actionDefinedType, |
| scenarioFileName)) |
| raise e |
| |
| if self.__getActionType(actionGatherer) == "script": |
| raise UngatherableTypeException( |
| "Unable to redefine {} type, please edit your {} file".format( |
| self.__getActionType(actionGatherer), |
| actionGathererFileName)) |
| |
| # Fusion of gathered Actions and other desired actions which |
| # are directly writed in the scenario's file |
| actionValue.update(self.__getActionValue(actionGatherer)) |
| |
| # Change the user defined key which was previously popped |
| # by the known one |
| action[self.__getActionType(actionGatherer)] = actionValue |
| |
| return scenarioActions |
| |
| def __getActionType(self, action): |
| """ |
| Return the type of an action (the key) |
| An action is a dictionary with only one element |
| |
| :param action: the action you want to get the type |
| :type action: dict |
| |
| :return: the type of the desired action |
| :rtype: string |
| """ |
| return list(action.keys())[0] |
| |
| def __getActionValue(self, action): |
| """ |
| Return the Value of an action |
| An action is a dictionary with only one element |
| |
| :param action: the action you want to get the type |
| :type action: dict |
| |
| :return: the value of the desired action |
| :rtype: string or dict |
| """ |
| return list(action.values())[0] |
| |
| def play(self): |
| """ |
| Execute a Scenario |
| """ |
| |
| for action in self.__scenarioActions: |
| # Launch the adequate behaviour depending on the key of the action dict |
| # No need to try KeyError as it would have been raised during init |
| # process |
| self.__actionTypeBehaviour[self.__getActionType(action)]( |
| self.__getActionValue(action)) |
| |
| |
| class UngatherableTypeException(Exception): |
| |
| """ |
| Exception raised in case of problem with a type that the |
| user try to personalize |
| """ |
| |
| def __init__(self, msg): |
| self.__msg = msg |
| |
| def __str__(self): |
| return "Ungatherable type Error : " + self.__msg |