pymtt
 All Classes Namespaces Files Functions Variables Groups
combinatorial.py
Go to the documentation of this file.
1 # -*- coding: utf-8; tab-width: 4; indent-tabs-mode: f; python-indent: 4 -*-
2 #
3 # Copyright (c) 2015-2018 Intel, Inc. All rights reserved.
4 # $COPYRIGHT$
5 #
6 # Additional copyrights may follow
7 #
8 # $HEADER$
9 #
10 
11 from __future__ import print_function
12 from future import standard_library
13 standard_library.install_aliases()
14 import os
15 import sys
16 import configparser
17 import importlib
18 import logging
19 import imp
20 import datetime
21 import tempfile
22 import shutil
23 from yapsy.PluginManager import PluginManager
24 
25 from ExecutorMTTTool import *
26 
27 ## @addtogroup Tools
28 # @{
29 # @addtogroup Executor
30 # @section CombinatorialEx
31 # Combinatorial execution executor
32 # @}
34 
35  def __init__(self):
36  # initialise parent class
37  ExecutorMTTTool.__init__(self)
38  self.options = {}
39  self.parser = configparser.ConfigParser()
40  self.parser.optionxform = str
41  # Create temp directory to hold .ini files
42  self.tempDir = tempfile.mkdtemp()
43  self.baseIniFile = None
44  self.runLog = {}
45  self.iniLog = {}
46 
47  def activate(self):
48  # use the automatic procedure from IPlugin
49  IPlugin.activate(self)
50  return
51 
52  def deactivate(self):
53  IPlugin.deactivate(self)
54  return
55 
56  def print_name(self):
57  return "Combinatorial executor"
58 
59  def print_options(self, testDef, prefix):
60  lines = testDef.printOptions(self.options)
61  for line in lines:
62  print(prefix + line)
63  return
64 
65 
66  # Create .ini files for each combination to be run
67  # BaseIniFile created by TestDef ConfigTest()
68  def createIniLog(self, testDef):
69  self.baseIniFile = testDef.config
70  tempSpecialSection = {}
71  # configParser object to write individual options to files
72  writeOption = configparser.ConfigParser()
73  writeOption.optionxform = str
74  # Sort base .ini sections and write to temp files
75  for section in self.baseIniFile.sections():
76  if section == "ENV":
77  continue
78  if section.startswith("SKIP") or section.startswith("skip"):
79  # users often want to temporarily ignore a section
80  # of their test definition file, but don't want to
81  # remove it lest they forget what it did. So let
82  # them just mark the section as "skip" to be ignored
83  continue
84  self.parser.add_section(section)
85  for option in self.baseIniFile.options(section):
86  self.parser.set(section, option, self.baseIniFile.get(section, option))
87  # TODO: FIX Getting temp file in tmp dir that is not being removed
88  fd, fileName = tempfile.mkstemp(suffix=".ini", dir = self.tempDir)
89  with open(fileName, 'w') as configfile:
90  self.parser.write(configfile)
91  # Clear out parser for next section
92  self.parser.remove_section(section)
93  if "MiddlewareGet" in section:
94  self.runLog[section] = fileName
95  elif "TestRun" in section:
96  tempSpecialSection[section] = fileName
97  else:
98  self.iniLog[section] = fileName
99  # Combine TestRun and MiddlewareGet files
100  tempList = {}
101  for section in self.runLog:
102  self.parser.read(self.runLog[section])
103  for id in tempSpecialSection:
104  self.parser.read(tempSpecialSection[id])
105  fd, fileName = tempfile.mkstemp(suffix = ".ini", dir = self.tempDir)
106  with open(fileName, 'w') as configfile:
107  self.parser.write(configfile)
108  self.parser.remove_section(id)
109  tempList[fd] = fileName
110  self.parser.remove_section(section)
111  self.runLog.clear()
112  self.runLog = tempList
113  # Sort sections for comma separated values to be parsed
114  optionsCSV = {}
115  for section in self.iniLog:
116  writeOption.read(self.iniLog[section])
117  for option in writeOption.options(section):
118  if ',' in writeOption.get(section, option):
119  try:
120  if optionsCSV[section] is not None:
121  pass
122  except KeyError:
123  optionsCSV[section] = []
124  optionsCSV[section].append(option)
125  else:
126  # write option to base run files
127  for fd in self.runLog:
128  # set up parser to write to each file
129  self.parser.read(self.runLog[fd])
130  if not self.parser.has_section(section):
131  self.parser.add_section(section)
132  self.parser.set(section, option, writeOption.get(section, option))
133  # Want to overwrite file with new parser contents
134  with open(self.runLog[fd], 'w') as configfile:
135  self.parser.write(configfile)
136  # clear parser for next file
137  for sect in self.parser.sections():
138  self.parser.remove_section(sect)
139  writeOption.remove_section(section)
140  # Process CSV options
141  for section in optionsCSV:
142  self.parser.read(self.iniLog[section])
143  for option in optionsCSV[section]:
144  # Get clean list of CSV's
145  rawList = self.parser.get(section, option)
146  splitList = rawList.split(',')
147  optionList = []
148  for item in splitList:
149  optionList.append(item.strip())
150  newList = {}
151  for fd in self.runLog:
152  writeOption.read(self.runLog[fd])
153  for nextOpt in optionList:
154  try:
155  if writeOption.has_section(section):
156  pass
157  except KeyError:
158  writeOption.add_section(section)
159  writeOption.set(section, option, nextOpt)
160  fd, fileName = tempfile.mkstemp(suffix=".ini", dir = self.tempDir)
161  with open(fileName, 'w') as configfile:
162  writeOption.write(configfile)
163  newList[fd] = fileName
164  for sect in writeOption.sections():
165  writeOption.remove_section(sect)
166  # Update runLog for next pass
167  self.runLog.clear()
168  self.runLog = newList
169  self.parser.remove_section(section)
170 
171  def execute(self, testDef):
172  testDef.logger.verbose_print("ExecuteCombinatorial")
173  status = 0
174  self.createIniLog(testDef)
175  try:
176  if not self.runLog:
177  print("Error, empty run log, combinatorial executor failed")
178  sys.exit(1)
179  for nextFile in self.runLog:
180  if not os.path.isfile(self.runLog[nextFile]):
181  print("Test .ini file not found!: " + nextFile)
182  sys.exit(1)
183  testDef.configNewTest(self.runLog[nextFile])
184  sequential_status = testDef.executeTest()
185  if sequential_status != 0:
186  status = 1
187  # clean up temporary files
188  finally:
189  shutil.rmtree(self.tempDir)
190 
191  return status
192 
193