aboutsummaryrefslogtreecommitdiffstats
path: root/longbow/src/python/longbow-test-run.py
diff options
context:
space:
mode:
authorMichele Papalini <micpapal+fdio@cisco.com>2017-02-24 08:00:33 +0000
committerGerrit Code Review <gerrit@fd.io>2017-02-24 08:00:33 +0000
commit4df7f4cc98b6288177df256e1db70ddc3f7d00db (patch)
tree55e71277b419e4830ae641868ab8e751c8b86972 /longbow/src/python/longbow-test-run.py
parentf28308bd99381ef5f1e178e2e1f870f245e35873 (diff)
parentec688b4723a041044226358bcd4dd6e2da39da49 (diff)
Merge "Initial commit: cframework. Longbow and Libparc" into cframework/master
Diffstat (limited to 'longbow/src/python/longbow-test-run.py')
-rwxr-xr-xlongbow/src/python/longbow-test-run.py172
1 files changed, 172 insertions, 0 deletions
diff --git a/longbow/src/python/longbow-test-run.py b/longbow/src/python/longbow-test-run.py
new file mode 100755
index 00000000..77ed1f98
--- /dev/null
+++ b/longbow/src/python/longbow-test-run.py
@@ -0,0 +1,172 @@
+#! /usr/bin/env python
+# Copyright (c) 2017 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+import os
+import sys
+import re
+import pprint
+import subprocess
+import argparse
+import json
+
+class TokenParser:
+ def __init__(self, tokens=[]):
+ self.index = 0
+ self.tokens = tokens
+
+ def nextToken(self):
+ result = self.tokens[self.index]
+ self.index = self.index + 1
+ return result
+
+ def previousToken(self):
+ self.index = self.index - 1
+ result = self.tokens[self.index - 1]
+ return result
+
+ def expectedToken(self, expected):
+ token = self.nextToken()
+ if token == expected:
+ return True
+ self.index = self.index - 1
+ print "expectedToken(%s) is not the actual %s" % (expected, token)
+ return False
+
+ def end(self):
+ if self.index == len(self.tokens):
+ return True
+ return False
+
+class LongBowCodeCoverage:
+ def __init__(self):
+ return
+
+ def run(self, executableFile):
+ lines = subprocess.check_output([ "gcov", "-f", executableFile ])
+ token = map(lambda x : x.strip("'"), re.split("[ :\n]+", lines))
+ return self.parse(token)
+
+ def parseFunction(self, parser):
+ functionName = parser.nextToken()
+ parser.expectedToken("Lines")
+ parser.expectedToken("executed")
+ coverage = parser.nextToken()
+ return { "function" : functionName, "coverage" : coverage }
+
+ def parseFile(self, parser):
+ fileName = parser.nextToken()
+ parser.expectedToken("Lines")
+ parser.expectedToken("executed")
+ coverage = parser.nextToken()
+ return { "file" : fileName, "coverage" : coverage }
+
+ def parse(self, tokens):
+ parser = TokenParser(tokens)
+ functions = [ ]
+
+ while not parser.end():
+ token = parser.nextToken()
+ if (token == "Function"):
+ function = self.parseFunction(parser)
+ functions.append(function)
+ elif (token == "File"):
+ file = self.parseFile(parser)
+ pass
+
+ self.detailCoverage = { "file" : file, "functions" : functions }
+ return self.detailCoverage
+
+ def getCoverage(self):
+ result["file"]["coverage"]
+
+ def getDetailCoverage(self):
+ return self.detailCoverage
+
+
+class LongBowTestRun:
+ def __init__(self, options=[]):
+ self.options = options
+ self.mainFileName = None
+ self.exitStatus = 0
+ return
+
+ def setOptions(self, options=[]):
+ self.options = options
+ return
+
+ def getMainFileName(self):
+ return self.mainFileName
+
+ def run(self, testRunner):
+ self.mainFileName = testRunner
+ self.exitStatus = 0
+
+ try:
+ try:
+ os.remove(testRunner + ".gcda")
+ except:
+ pass
+ lines = subprocess.check_output([ testRunner ])
+ lines = re.split("[ :]+", lines)
+ self.exitStatus = 0
+ except subprocess.CalledProcessError, e:
+ self.exitStatus = e.returncode
+
+ return self.exitStatus
+
+ def report(self, detailedOutput=False, jsonOutput=False):
+ result = ""
+ if self.exitStatus == 0:
+ coverage = LongBowCodeCoverage()
+ result = coverage.run(testRunner.getMainFileName())
+
+ if detailedOutput:
+ if jsonOutput:
+ result = json.dumps(result, sort_keys=False, indent=4, separators=(',', ': '))
+ else:
+ pp = str(result)
+ pass
+ else:
+ if jsonOutput:
+ result = json.dumps(result["file"], sort_keys=False, indent=4, separators=(',', ': '))
+ else:
+ result = "PASS " + result["file"]["file"] + " " + result["file"]["coverage"]
+ else:
+ result = "FAIL " + args.testRunner
+ pass
+
+ return result
+
+
+if __name__ == '__main__':
+ testRunners = []
+ if len(sys.argv) < 2:
+ print "Usage: longbow-test-run.py testExecutable"
+ print "Run a LongBow test"
+ sys.exit(1)
+
+ parser = argparse.ArgumentParser(description='Run a LongBow Test')
+ parser.add_argument("--json", help="Produce JSON output instead of a Python dictionary.", action="store_true")
+ parser.add_argument("--detailed", help="Produce detailed output.", action="store_true")
+ parser.add_argument("testRunner", help="The name of the test executable.", nargs='+')
+ args = parser.parse_args()
+
+ testRunner = LongBowTestRun([ "--run-nonforked" ])
+
+ for test in args.testRunner:
+ exitStatus = testRunner.run(test)
+ print testRunner.report(args.detailed, args.json)
+