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.InclusiveCriterion import InclusiveCriterion 30from clientsimulator.testGenerator.TestLauncher import TestLauncher 31from clientsimulator.userInteraction.DynamicCallHelper import DynamicCallHelper 32 33 34class UserInteractor: 35 36 """ 37 Define all user interactions the program can have. 38 39 Allows to run the interactive mode and dynamics menus. 40 """ 41 42 def __init__(self, testLauncher, criterions): 43 """ 44 Init function of user interactor 45 46 :param testLauncher: object which allows to run tests 47 :type testLauncher: TestLauncher 48 """ 49 50 self.__testLauncher = testLauncher 51 self.__criterions = criterions 52 53 @classmethod 54 def getMenu(cls, options, cancelSentence="Go Back"): 55 """ 56 Dynamic Menu Generator : 57 58 :param options: list containing tuples of a) the invite string and 59 b) the function to launch 60 :type options: list 61 :param cancelSentence: title of the menu entry that will be 62 appended after the provided options, in order to exit the menu. For 63 top-level menus, it is advised to pass "Quit" as argument. 64 :type cancelSentence: string 65 """ 66 67 while True: 68 print("\nPlease Make a choice : ") 69 for numMenu, (sentenceMenu, fonc) in enumerate(options): 70 print("\t{}. {}".format(numMenu, sentenceMenu)) 71 72 # Lastly, append an option to go to the previous menu/quit 73 print("\t{}. {}".format(len(options), cancelSentence)) 74 75 choice = input("Your Choice : ") 76 try: 77 choice = int(choice) 78 if choice == len(options): 79 # The user has selected the "cancel" option 80 break 81 if choice < 0: 82 # Negative values make no sense 83 raise KeyError(choice) 84 85 options[choice][1]() 86 except (KeyError, ValueError) as e: 87 print("Invalid Choice : {}".format(e)) 88 89 def launchInteractiveMode(self): 90 """ 91 Interactive Mode : Set up a menu which allow 92 users to personnalize a Test and to Launch it 93 """ 94 optionsMenu = [ 95 ("Edit Vector", self.__editVector), 96 ("Apply Configuration", self.__applyConfiguration), 97 ("Launch Script", self.__launchScript) 98 ] 99 100 UserInteractor.getMenu(optionsMenu, "Quit") 101 102 def __applyConfiguration(self): 103 """ 104 Apply the configuration described in the 105 current criterions state. 106 """ 107 108 self.__testLauncher.executeTestVector(self.__criterions) 109 110 return True 111 112 def __launchScript(self): 113 """ 114 Display the menu which let the user choose an available 115 script to run. 116 """ 117 118 optionScript = [ 119 ("Execute {}".format(script), 120 DynamicCallHelper(self.__testLauncher.executeScript, script)) 121 for script in self.__testLauncher.scripts 122 ] 123 124 UserInteractor.getMenu(optionScript) 125 126 return True 127 128 def __setCriterion(self, criterion, value): 129 criterion.currentValue = value 130 131 def __removeCriterionValue(self, criterion, value): 132 criterion.removeValue(value) 133 134 def __editCriterion(self, criterion): 135 """ 136 Allow to change the value of a criterion through a menu. 137 138 :param criterion: the criterion to edit 139 :type criterion: Criterion 140 """ 141 142 optionEditCriterion = [] 143 for possibleValue in [x for x in criterion.allowedValues() 144 if not x in criterion.currentValue 145 and not x == criterion.noValue]: 146 optionEditCriterion.append( 147 ("Set {}".format(possibleValue), 148 DynamicCallHelper( 149 self.__setCriterion, 150 criterion, 151 possibleValue))) 152 153 if InclusiveCriterion in criterion.__class__.__bases__: 154 # Inclusive criterion : display unset value (default when empty) 155 for possibleValue in criterion.currentValue: 156 optionEditCriterion.append( 157 ("Unset {}".format(possibleValue), 158 DynamicCallHelper( 159 self.__removeCriterionValue, 160 criterion, 161 possibleValue))) 162 else: 163 # Exclusive criterion : display default value 164 optionEditCriterion.append( 165 ("Set Default", 166 DynamicCallHelper( 167 self.__setCriterion, 168 criterion, 169 criterion.noValue))) 170 171 UserInteractor.getMenu(optionEditCriterion) 172 173 return True 174 175 def __editVector(self): 176 """ 177 Allow to change the value of several criterions through a menu. 178 """ 179 180 optionEdit = [ 181 ("Edit {}".format(cri.__class__.__name__), 182 DynamicCallHelper(self.__editCriterion, cri)) 183 for cri in self.__criterions 184 ] 185 186 UserInteractor.getMenu(optionEdit) 187 188 return True 189