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