| The Gaudi Framework v32r1 (f65d50dc)

Public Member Functions | Static Public Attributes | Private Attributes | List of all members
GaudiTest.XMLResultStream Class Reference
Inheritance diagram for GaudiTest.XMLResultStream:
[legend]
Collaboration diagram for GaudiTest.XMLResultStream:
[legend]

## Public Member Functions
def | __init__ (self, arguments=None, **args)
def | WriteAnnotation (self, key, value)
def | WriteResult (self, result)
def | Summarize (self)

## Static Public Attributes
list | arguments

## Private Attributes
| _xmlFile
| _startTime
| _endTime
| _tree
| _site
| _Testing
| _StartDateTime
| _StartTestTime
| _TestList
| _EndDateTime
| _EndTestTime
| _ElapsedMinutes

## Detailed Description

    An 'XMLResultStream' writes its output to a Ctest XML file.

    The argument 'dir' is used to select the destination file for the XML
    report.
    The destination directory may already contain the report from a previous run
    (for example of a different package), in which case it will be overrided to
    with the new data.

Definition at line 2096 of file GaudiTest.py.

## Constructor & Destructor Documentation

## ◆ __init__()

def GaudiTest.XMLResultStream.__init__ | ( |  | self,
|  |  | arguments = `None`,
|  | ** | args
| ) |  |

    Prepare the destination directory.

    Creates the destination directory and store in it some preliminary
    annotations .

Definition at line 2123 of file GaudiTest.py.

2123 def __init__(self, arguments=None, **args):
2124 """Prepare the destination directory.
2125
2126 Creates the destination directory and store in it some preliminary
2127 annotations .
2128 """
2129 ResultStream.__init__(self, arguments, **args)
2130
2131 self._xmlFile = os.path.join(self.dir, self.prefix + 'Test.xml')
2132
2133 # add some global variable
2134 self._startTime = None
2135 self._endTime = None
2136 # Format the XML file if it not exists
2137 if not os.path.isfile(self._xmlFile):
2138 # check that the container directory exists and create it if not
2139 if not os.path.exists(os.path.dirname(self._xmlFile)):
2140 os.makedirs(os.path.dirname(self._xmlFile))
2141
2142 newdataset = ET.Element("newdataset")
2143 self._tree = ET.ElementTree(newdataset)
2144 self._tree.write(self._xmlFile)
2145 else:
2146 # Read the xml file
2147 self._tree = ET.parse(self._xmlFile)
2148 newdataset = self._tree.getroot()
2149
2150 # Find the corresponding site, if do not exist, create it
2151
2152 #site = newdataset.find('Site[@BuildStamp="'+result["qmtest.start_time"]+'"][@OSPlatform="'+os.getenv("CMTOPT")+'"]')
2153 # I don't know why this syntax doesn't work. Maybe it is because of the python version. Indeed,
2154 # This works well in the python terminal. So I have to make a for:
2155 for site in newdataset.getiterator():
2156 # and site.get("BuildStamp") == result["qmtest.start_time"] and:
2157 if site.get("OSPlatform") == os.uname()[4]:
2158 # Here we can add some variable to define the difference beetween 2 site
2159 self._site = site
2160 break
2161 else:
2162 site = None
2163
2164 if site is None:
2165 import socket
2166 import multiprocessing
2167 attrib = {
2168 "BuildName": os.getenv("CMTCONFIG"),
2169 "Name": os.uname()[1],
2170 "Generator": "QMTest " + qm.version,
2171 "OSName": os.uname()[0],
2172 "Hostname": socket.gethostname(),
2173 "OSRelease": os.uname()[2],
2174 "OSVersion": os.uname()[3],
2175 "OSPlatform": os.uname()[4],
2176 "Is64Bits": "unknown",
2177 "VendorString": "unknown",
2178 "VendorID": "unknown",
2179 "FamilyID": "unknown",
2180 "ModelID": "unknown",
2181 "ProcessorCacheSize": "unknown",
2182 "NumberOfLogicalCPU": str(multiprocessing.cpu_count()),
2183 "NumberOfPhysicalCPU": "0",
2184 "TotalVirtualMemory": "0",
2185 "TotalPhysicalMemory": "0",
2186 "LogicalProcessorsPerPhysical": "0",
2187 "ProcessorClockFrequency": "0",
2188 }
2189 self._site = ET.SubElement(newdataset, "Site", attrib)
2190 self._Testing = ET.SubElement(self._site, "Testing")
2191
2192 # Start time elements
2193 self._StartDateTime = ET.SubElement(self._Testing, "StartDateTime")
2194
2195 self._StartTestTime = ET.SubElement(self._Testing, "StartTestTime")
2196
2197 self._TestList = ET.SubElement(self._Testing, "TestList")
2198
2199 # End time elements
2200 self._EndDateTime = ET.SubElement(self._Testing, "EndDateTime")
2201
2202 self._EndTestTime = ET.SubElement(self._Testing, "EndTestTime")
2203
2204 self._ElapsedMinutes = ET.SubElement(self._Testing,
2205 "ElapsedMinutes")
2206
2207 else: # We get the elements
2208 self._Testing = self._site.find("Testing")
2209 self._StartDateTime = self._Testing.find("StartDateTime")
2210 self._StartTestTime = self._Testing.find("StartTestTime")
2211 self._TestList = self._Testing.find("TestList")
2212 self._EndDateTime = self._Testing.find("EndDateTime")
2213 self._EndTestTime = self._Testing.find("EndTestTime")
2214 self._ElapsedMinutes = self._Testing.find("ElapsedMinutes")
2215 """
2216 # Add some non-QMTest attributes
2217 if "CMTCONFIG" in os.environ:
2218 self.WriteAnnotation("cmt.cmtconfig", os.environ["CMTCONFIG"])
2219 import socket
2220 self.WriteAnnotation("hostname", socket.gethostname())
2221 """
2222

## Member Function Documentation

## ◆ Summarize()

def GaudiTest.XMLResultStream.Summarize | ( |  | self | ) |

Definition at line 2384 of file GaudiTest.py.

2384 def Summarize(self):
2385
2386 # Set the final end date time
2387 self._EndTestTime.text = str(self._endTime)
2388 self._EndDateTime.text = time.strftime("%b %d %H:%M %Z",
2389 time.localtime(self._endTime))
2390
2391 # Compute the total duration
2392 if self._endTime and self._startTime:
2393 delta = self._endTime - self._startTime
2394 else:
2395 delta = 0
2396 self._ElapsedMinutes.text = str(delta / 60)
2397
2398 # Write into the file
2399 # ,True) in python 2.7 to add the xml header
2400 self._tree.write(self._xmlFile, "utf-8")

## ◆ WriteAnnotation()

def GaudiTest.XMLResultStream.WriteAnnotation | ( |  | self,
|  |  | key,
|  |  | value
| ) |  |

Definition at line 2223 of file GaudiTest.py.

2223 def WriteAnnotation(self, key, value):
2224 if key == "qmtest.run.start_time":
2225 if self._site.get("qmtest.run.start_time") is not None:
2226 return None
2227 self._site.set(str(key), str(value))
2228
Gaudi::Functional::details::get
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
Definition: FunctionalDetails.h:332

## ◆ WriteResult()

def GaudiTest.XMLResultStream.WriteResult | ( |  | self,
|  |  | result
| ) |  |

    Prepare the test result directory in the destination directory storing
    into it the result fields.
    A summary of the test result is stored both in a file in the test directory
    and in the global summary file.

Definition at line 2229 of file GaudiTest.py.

2229 def WriteResult(self, result):
2230 """Prepare the test result directory in the destination directory storing
2231 into it the result fields.
2232 A summary of the test result is stored both in a file in the test directory
2233 and in the global summary file.
2234 """
2235 summary = {}
2236 summary["id"] = result.GetId()
2237 summary["outcome"] = result.GetOutcome()
2238 summary["cause"] = result.GetCause()
2239 summary["fields"] = result.keys()
2240 summary["fields"].sort()
2241
2242 # Since we miss proper JSON support, I hack a bit
2243 for f in ["id", "outcome", "cause"]:
2244 summary[f] = str(summary[f])
2245 summary["fields"] = map(str, summary["fields"])
2246
2247 # format
2248 # package_Test.xml
2249
2250 if "qmtest.start_time" in summary["fields"]:
2251 haveStartDate = True
2252 else:
2253 haveStartDate = False
2254 if "qmtest.end_time" in summary["fields"]:
2255 haveEndDate = True
2256 else:
2257 haveEndDate = False
2258
2259 # writing the start date time
2260 if haveStartDate:
2261 self._startTime = calendar.timegm(
2262 time.strptime(result["qmtest.start_time"],
2263 "%Y-%m-%dT%H:%M:%SZ"))
2264 if self._StartTestTime.text is None:
2265 self._StartDateTime.text = time.strftime(
2266 "%b %d %H:%M %Z", time.localtime(self._startTime))
2267 self._StartTestTime.text = str(self._startTime)
2268 self._site.set("BuildStamp", result["qmtest.start_time"])
2269
2270 # Save the end date time in memory
2271 if haveEndDate:
2272 self._endTime = calendar.timegm(
2273 time.strptime(result["qmtest.end_time"], "%Y-%m-%dT%H:%M:%SZ"))
2274
2275 # add the current test to the test list
2276 tl = ET.Element("Test")
2277 tl.text = summary["id"]
2278 self._TestList.insert(0, tl)
2279
2280 # Fill the current test
2281 Test = ET.Element("Test")
2282 if summary["outcome"] == "PASS":
2283 Test.set("Status", "passed")
2284 elif summary["outcome"] == "FAIL":
2285 Test.set("Status", "failed")
2286 elif summary["outcome"] == "SKIPPED" or summary[
2287 "outcome"] == "UNTESTED":
2288 Test.set("Status", "skipped")
2289 elif summary["outcome"] == "ERROR":
2290 Test.set("Status", "failed")
2291 Name = ET.SubElement(
2292 Test,
2293 "Name",
2294 )
2295 Name.text = summary["id"]
2296 Results = ET.SubElement(Test, "Results")
2297
2298 # add the test after the other test
2299 self._Testing.insert(3, Test)
2300
2301 if haveStartDate and haveEndDate:
2302 # Compute the test duration
2303 delta = self._endTime - self._startTime
2304 testduration = str(delta)
2305 Testduration = ET.SubElement(Results, "NamedMeasurement")
2306 Testduration.set("name", "Execution Time")
2307 Testduration.set("type", "numeric/float")
2308 value = ET.SubElement(Testduration, "Value")
2309 value.text = testduration
2310
2311 # remove the fields that we store in a different way
2312 for n in ("qmtest.end_time", "qmtest.start_time", "qmtest.cause",
2313 "ExecTest.stdout"):
2314 if n in summary["fields"]:
2315 summary["fields"].remove(n)
2316
2317 # Here we can add some NamedMeasurment which we know the type
2318 #
2319 if "ExecTest.exit_code" in summary["fields"]:
2320 summary["fields"].remove("ExecTest.exit_code")
2321 ExitCode = ET.SubElement(Results, "NamedMeasurement")
2322 ExitCode.set("name", "exit_code")
2323 ExitCode.set("type", "numeric/integer")
2324 value = ET.SubElement(ExitCode, "Value")
2325 value.text = convert_xml_illegal_chars(
2326 result["ExecTest.exit_code"])
2327
2328 TestStartTime = ET.SubElement(Results, "NamedMeasurement")
2329 TestStartTime.set("name", "Start_Time")
2330 TestStartTime.set("type", "String")
2331 value = ET.SubElement(TestStartTime, "Value")
2332 if haveStartDate:
2333 value.text = escape_xml_illegal_chars(
2334 time.strftime("%b %d %H:%M %Z %Y",
2335 time.localtime(self._startTime)))
2336 else:
2337 value.text = ""
2338
2339 TestEndTime = ET.SubElement(Results, "NamedMeasurement")
2340 TestEndTime.set("name", "End_Time")
2341 TestEndTime.set("type", "String")
2342 value = ET.SubElement(TestEndTime, "Value")
2343 if haveStartDate:
2344 value.text = escape_xml_illegal_chars(
2345 time.strftime("%b %d %H:%M %Z %Y",
2346 time.localtime(self._endTime)))
2347 else:
2348 value.text = ""
2349
2350 if summary["cause"]:
2351 FailureCause = ET.SubElement(Results, "NamedMeasurement")
2352 FailureCause.set("name", "Cause")
2353 FailureCause.set("type", "String")
2354 value = ET.SubElement(FailureCause, "Value")
2355 value.text = escape_xml_illegal_chars(summary["cause"])
2356
2357 # Fill the result
2358 fields = {}
2359 for field in summary["fields"]:
2360 fields[field] = ET.SubElement(Results, "NamedMeasurement")
2361 fields[field].set("type", "String")
2362 fields[field].set("name", field)
2363 value = ET.SubElement(fields[field], "Value")
2364 # to escape the <pre></pre>
2365 if "<pre>" in result[field][0:6]:
2366 value.text = convert_xml_illegal_chars(result[field][5:-6])
2367 else:
2368 value.text = convert_xml_illegal_chars(result[field])
2369
2370 if result.has_key("ExecTest.stdout"): # "ExecTest.stdout" in result :
2371 Measurement = ET.SubElement(Results, "Measurement")
2372 value = ET.SubElement(Measurement, "Value")
2373 if "<pre>" in result["ExecTest.stdout"][0:6]:
2374 value.text = convert_xml_illegal_chars(
2375 result["ExecTest.stdout"][5:-6])
2376 else:
2377 value.text = convert_xml_illegal_chars(
2378 result["ExecTest.stdout"])
2379
2380 # write the file
2381 # ,True) in python 2.7 to add the xml header
2382 self._tree.write(self._xmlFile, "utf-8")
2383
Gaudi::Functional::details::insert
constexpr struct Gaudi::Functional::details::insert_t insert
GaudiTest.escape_xml_illegal_chars
def escape_xml_illegal_chars(val, replacement='?')
Definition: GaudiTest.py:368
Containers::map
struct GAUDI_API map
Parametrisation class for map-like implementation.
Definition: KeyedObjectManager.h:25
GaudiTest.convert_xml_illegal_chars
def convert_xml_illegal_chars(val)
Definition: GaudiTest.py:364

## Member Data Documentation

## ◆ _ElapsedMinutes

GaudiTest.XMLResultStream._ElapsedMinutes
| private

Definition at line 2204 of file GaudiTest.py.

## ◆ _EndDateTime

GaudiTest.XMLResultStream._EndDateTime
| private

Definition at line 2200 of file GaudiTest.py.

## ◆ _EndTestTime

GaudiTest.XMLResultStream._EndTestTime
| private

Definition at line 2202 of file GaudiTest.py.

## ◆ _endTime

GaudiTest.XMLResultStream._endTime
| private

Definition at line 2135 of file GaudiTest.py.

## ◆ _site

GaudiTest.XMLResultStream._site
| private

Definition at line 2159 of file GaudiTest.py.

## ◆ _StartDateTime

GaudiTest.XMLResultStream._StartDateTime
| private

Definition at line 2193 of file GaudiTest.py.

## ◆ _StartTestTime

GaudiTest.XMLResultStream._StartTestTime
| private

Definition at line 2195 of file GaudiTest.py.

## ◆ _startTime

GaudiTest.XMLResultStream._startTime
| private

Definition at line 2134 of file GaudiTest.py.

## ◆ _Testing

GaudiTest.XMLResultStream._Testing
| private

Definition at line 2190 of file GaudiTest.py.

## ◆ _TestList

GaudiTest.XMLResultStream._TestList
| private

Definition at line 2197 of file GaudiTest.py.

## ◆ _tree

GaudiTest.XMLResultStream._tree
| private

Definition at line 2143 of file GaudiTest.py.

## ◆ _xmlFile

GaudiTest.XMLResultStream._xmlFile
| private

Definition at line 2131 of file GaudiTest.py.

## ◆ arguments

list GaudiTest.XMLResultStream.arguments
| static

Initial value:
= [
qm.fields.TextField(
name="dir",
title="Destination Directory",
description=,
verbatim="true",
default_value=""),
qm.fields.TextField(
name="prefix",
title="Output File Prefix",
description=,
verbatim="true",
default_value=""),
]

Definition at line 2105 of file GaudiTest.py.

The documentation for this class was generated from the following file:

- GaudiPolicy/qmtest_classes/GaudiTest.py