• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2# Copyright (c) 2014-2015, Intel Corporation
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without modification,
6# are permitted provided that the following conditions are met:
7#
8# 1. Redistributions of source code must retain the above copyright notice, this
9# list of conditions and the following disclaimer.
10#
11# 2. Redistributions in binary form must reproduce the above copyright notice,
12# this list of conditions and the following disclaimer in the documentation and/or
13# other materials provided with the distribution.
14#
15# 3. Neither the name of the copyright holder nor the names of its contributors
16# may be used to endorse or promote products derived from this software without
17# specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30from clientsimulator.criterion.CriterionClassFactory import CriterionClassFactory
31from clientsimulator.testGenerator.TestVectorFactory import TestVectorFactory
32from clientsimulator.testGenerator.TestLauncher import TestLauncher
33from clientsimulator.testGenerator.SubprocessLogger import SubprocessLoggerThread
34from clientsimulator.testGenerator.SubprocessLogger import ScriptLoggerThread
35from clientsimulator.configuration.ConfigParser import ConfigParser
36from clientsimulator.scenario.Scenario import Scenario
37from clientsimulator.userInteraction.UserInteractor import UserInteractor
38from clientsimulator.userInteraction.DynamicCallHelper import DynamicCallHelper
39import argparse
40import time
41import logging
42import os
43
44
45def close(logger, testLauncher, coverage):
46    """ SIGINT Handler which clean up processes  """
47
48    # Check if some scripts are running, if this is the case
49    # we warn the user.
50    if ScriptLoggerThread.getRunningInstances():
51        try:
52            logger.info("{} \n {}".format(
53                "Some subprocesses are still running. The program will wait them before exiting.",
54                "If you really want to exit, please confirm by typing Ctrl+C again"))
55
56            # Wait for thread to terminate
57            while ScriptLoggerThread.getRunningInstances():
58                time.sleep(1)
59        except KeyboardInterrupt as e:
60            pass
61
62    # Kill subprocess (at least test-platform one)
63    SubprocessLoggerThread.closeAll()
64
65    if coverage:
66        testLauncher.generateCoverage()
67
68    logger.info("Closing")
69
70    exit(0)
71
72
73def launchScenario(
74        logger,
75        consoleLogger,
76        actionGathererFileName,
77        scenarioFileName,
78        testFactory,
79        testLauncher):
80
81    logger.info("Launching {}".format(scenarioFileName))
82
83    Scenario(consoleLogger,
84             scenarioFileName,
85             actionGathererFileName,
86             testFactory,
87             testLauncher).play()
88
89    logger.info("Scenario execution complete.")
90
91
92def main():
93
94    # Handle Arguments
95
96    parser = argparse.ArgumentParser()
97
98    parser.add_argument("test_directory", type=str, default=None,
99                        help="precise a test directory (required).")
100
101    parser.add_argument("-s", "--scenario", type=int, default=None, nargs='+',
102                        help="precise one or more scenarios to launch.")
103
104    interactiveness = parser.add_mutually_exclusive_group()
105    interactiveness.add_argument("--no-exit", action='store_true',
106                                 help="lets you interactively select more scenarios (This is"
107                                      " implicit if neither '--scenario' nor '--interactive' are "
108                                      " passed).")
109
110    interactiveness.add_argument("--interactive", action='store_true',
111                                 help="run in interactive mode (lets you select actions and scripts"
112                                 " to run).")
113
114    parser.add_argument(
115        "-v",
116        "--verbose",
117        action='store_true',
118        help="display test-platform's and scripts' log on stdout.")
119
120    parser.add_argument("-c", "--coverage", action='store_true',
121                        help="generate coverage file at end of script")
122
123    args = parser.parse_args()
124
125    # Logging Configuration
126    logger = logging.getLogger(__name__)
127
128    # Decide what to write in console depending on verbose argument
129    consoleLogger = logging.StreamHandler()
130    if args.verbose:
131        consoleLogger.setLevel(logging.DEBUG)
132    else:
133        consoleLogger.setLevel(logging.INFO)
134    logger.addHandler(consoleLogger)
135
136    # The given directory should have a conf.json file
137    if not os.path.isfile(os.path.join(args.test_directory, "conf.json")):
138        # This error will only be logged in the terminal
139        logger.error(
140            "Cannot find configuration file : conf.json in {} directory.".format(
141                args.test_directory))
142        exit(1)
143
144    try:
145        configParser = ConfigParser(
146            os.path.join(
147                args.test_directory,
148                "conf.json"),
149            args.test_directory,
150            consoleLogger)
151    except KeyError as e:
152        logger.error(
153            "Missing mandatory configuration item {} in the"
154            " conf.json file".format(e))
155        exit(1)
156
157    # Always write all log in the file
158    logging.basicConfig(level=logging.DEBUG,
159                        format='%(name)-12s %(levelname)-8s %(message)s',
160                        filename=configParser["LogFile"],
161                        filemode='w')
162
163    # Parsing criterion file and classes generation
164    logger.info("Criterion analysis")
165    classFactory = CriterionClassFactory(configParser["CriterionFile"])
166    criterionClasses = classFactory.generateCriterionClasses()
167
168    # Tests Handlers Generation
169    testFactory = TestVectorFactory(
170        criterionClasses,
171        consoleLogger)
172
173    testLauncher = TestLauncher(
174        criterionClasses,
175        configParser,
176        consoleLogger)
177
178    # Initialisation
179    testLauncher.init(criterionClasses, args.verbose)
180
181    # Launching
182    try:
183        if args.interactive:
184            # Launch Interactive Mode with default criterions values
185            UserInteractor(
186                testLauncher,
187                testFactory.generateTestVector()).launchInteractiveMode()
188        else:
189            scenarioOptions = [
190                    (scenarioFileName,
191                     DynamicCallHelper(
192                         launchScenario,
193                         logger,
194                         consoleLogger,
195                         configParser["ActionGathererFile"],
196                         os.path.join(
197                             configParser["ScenariosDirectory"], scenarioFileName),
198                         testFactory,
199                         testLauncher
200                     ))
201                for scenarioFileName in sorted(os.listdir(configParser["ScenariosDirectory"]))
202            ]
203            if args.scenario is not None:
204                for elem in args.scenario:
205                    scenarioOptions[elem][1]()
206            if (args.scenario is None) or args.no_exit:
207                # Let the user choose more scenarios after the ones chosen by command line
208                # or if none was given on the command line.
209                UserInteractor.getMenu(scenarioOptions, "Quit")
210    except KeyboardInterrupt as e:
211        close(logger, testLauncher, args.coverage)
212    else:
213        close(logger, testLauncher, args.coverage)
214
215
216if __name__ == "__main__":
217    # Execute main if the script is running as main
218    main()
219