diff options
author | Hannah von Reth <hannah.vonreth@owncloud.com> | 2022-04-05 14:05:15 +0300 |
---|---|---|
committer | Hannah von Reth <hannah.vonreth@owncloud.com> | 2022-04-05 14:05:15 +0300 |
commit | a0349a9e2396964e09936978c7b3f1a87bd5975b (patch) | |
tree | 445b70b10a387e12f347b2d020feed914572a241 /test | |
parent | 2e7d662091076fb7bfb39b04f5c8dd1c5b53ca2f (diff) | |
parent | 89fd49a3a6a383436c019be864ba7e1777c2c051 (diff) |
Merge remote-tracking branch 'origin/2.10'
Diffstat (limited to 'test')
-rw-r--r-- | test/gui/drone/comment.sh | 6 | ||||
-rw-r--r-- | test/gui/drone/notification_template.sh | 9 | ||||
-rw-r--r-- | test/gui/shared/scripts/bdd_hooks.py | 15 | ||||
-rw-r--r-- | test/gui/shared/scripts/helpers/SetupClientHelper.py | 66 | ||||
-rw-r--r-- | test/gui/shared/scripts/helpers/StacktraceHelper.py | 67 |
5 files changed, 95 insertions, 68 deletions
diff --git a/test/gui/drone/comment.sh b/test/gui/drone/comment.sh index 730a84324..550098075 100644 --- a/test/gui/drone/comment.sh +++ b/test/gui/drone/comment.sh @@ -23,6 +23,12 @@ else echo "Server Logs: (${CACHE_ENDPOINT}/${CACHE_BUCKET}/$2/$3/guiReportUpload/serverlog.log)" >> $1/comments.file fi + # if there is stacktrace file then add to the comment + if [[ -f $1/stacktrace.log ]]; then + echo "creating comment for stacktrace" + echo "Stacktrace: (${CACHE_ENDPOINT}/${CACHE_BUCKET}/$2/$3/guiReportUpload/stacktrace.log)" >> $1/comments.file + fi + if ! [[ $(find $1/screenshots -maxdepth 0 -empty) ]]; then echo "creating comment for screenshots" echo "Screenshots:" >> $1/comments.file diff --git a/test/gui/drone/notification_template.sh b/test/gui/drone/notification_template.sh index 714a49f6c..ed5cd73bb 100644 --- a/test/gui/drone/notification_template.sh +++ b/test/gui/drone/notification_template.sh @@ -8,11 +8,13 @@ COMMIT_SHA_SHORT=${DRONE_COMMIT:0:8} GUI_LOG="${CACHE_ENDPOINT}/${CACHE_BUCKET}/${DRONE_REPO}/${DRONE_BUILD_NUMBER}/guiReportUpload/index.html" SERVER_LOG="${CACHE_ENDPOINT}/${CACHE_BUCKET}/${DRONE_REPO}/${DRONE_BUILD_NUMBER}/guiReportUpload/serverlog.log" +STACKTRACE="${CACHE_ENDPOINT}/${CACHE_BUCKET}/${DRONE_REPO}/${DRONE_BUILD_NUMBER}/guiReportUpload/stacktrace.log" -CURL="curl --write-out "%{http_code}" --silent --output /dev/null" +CURL="curl --write-out %{http_code} --silent --output /dev/null" GUI_STATUS_CODE=$($CURL "$GUI_LOG") SERVER_STATUS_CODE=$($CURL "$SERVER_LOG") +STACKTRACE_STATUS_CODE=$($CURL "$STACKTRACE") BUILD_STATUS=":white_check_mark:Success" TEST_LOGS="" @@ -25,6 +27,9 @@ if [ "${DRONE_BUILD_STATUS}" != "success" ]; then if [[ "$GUI_STATUS_CODE" == "200" ]]; then TEST_LOGS+="\n> [GUI test log]($GUI_LOG)" fi + if [[ "$STACKTRACE_STATUS_CODE" == "200" ]]; then + TEST_LOGS+="\n> [Stacktrace]($STACKTRACE)" + fi fi -echo -e "**$BUILD_STATUS** [${DRONE_REPO}#${COMMIT_SHA_SHORT}](${DRONE_BUILD_LINK}) (${DRONE_BRANCH}) by **${DRONE_COMMIT_AUTHOR}** $TEST_LOGS" > $1/template.md
\ No newline at end of file +echo -e "**$BUILD_STATUS** [${DRONE_REPO}#${COMMIT_SHA_SHORT}](${DRONE_BUILD_LINK}) (${DRONE_BRANCH}) by **${DRONE_COMMIT_AUTHOR}** $TEST_LOGS" > "$1"/template.md
\ No newline at end of file diff --git a/test/gui/shared/scripts/bdd_hooks.py b/test/gui/shared/scripts/bdd_hooks.py index f36132868..bcdf2c1a4 100644 --- a/test/gui/shared/scripts/bdd_hooks.py +++ b/test/gui/shared/scripts/bdd_hooks.py @@ -19,6 +19,7 @@ import shutil import urllib.request import os import builtins +from helpers.StacktraceHelper import getCoredumps, generateStacktrace @OnScenarioStart @@ -64,7 +65,7 @@ def hook(context): for key, value in context.userData.items(): if value == '': context.userData[key] = DEFAULT_CONFIG[key] - elif key == 'maxSyncTimeout': + elif key == 'maxSyncTimeout' or key == 'minSyncTimeout': context.userData[key] = builtins.int(value) elif key == 'clientRootSyncPath': # make sure there is always one trailing slash @@ -93,6 +94,18 @@ def hook(context): @OnScenarioEnd def hook(context): + # search coredumps after every test scenario + # CI pipeline might fail although all tests are passing + coredumps = getCoredumps() + if coredumps: + try: + generateStacktrace(context, coredumps) + print("Stacktrace generated.") + except Exception as err: + print(err) + else: + print("No coredump found!") + # capture screenshot if there is error in the scenario execution, and if the test is being run in CI if test.resultCount("errors") > 0 and os.getenv('CI'): import gi diff --git a/test/gui/shared/scripts/helpers/SetupClientHelper.py b/test/gui/shared/scripts/helpers/SetupClientHelper.py index 19d3783dc..fb996d63e 100644 --- a/test/gui/shared/scripts/helpers/SetupClientHelper.py +++ b/test/gui/shared/scripts/helpers/SetupClientHelper.py @@ -1,10 +1,7 @@ from urllib.parse import urlparse import squish -from os import makedirs, environ +from os import makedirs from os.path import exists, join -import test -import subprocess -from configparser import ConfigParser confdir = '/tmp/bdd-tests-owncloud-client/' @@ -78,71 +75,10 @@ def startClient(context): + " --confdir " + confdir ) - squish.installEventHandler("Crash", "crashHandler") squish.snooze(1) -def crashHandler(): - # The core dump is generated in the folder /var/lib/apport/coredump/ - coredumpFolderPath = '/var/lib/apport/coredump/' - cfg = ConfigParser() - - # Select appropriate AUT binary with respect to the test run environment - try: - if environ.get('CI'): - cfg.read('/drone/src/test/gui/drone/server.ini') - - else: - from pathlib import Path - - HOME = str(Path.home()) - cfg.read(HOME + '/.squish/ver1/server.ini') - - except Exception as err: - test.log("the binary path can not be read") - test.log(err) - - owncloudBinary = cfg.get('General', 'AUT/owncloud') - owncloudBinary = owncloudBinary.replace('"', '') + '/owncloud' - - # GUI test stacktrace on crash - test.log("Started printing the GUI test stacktrace of crash") - test.log("############################################################") - test.log("Backtracking...") - test.log("%s" % test.stackTrace()) - test.log("############################################################") - test.log("Finished printing GUI test stacktrace") - - test.log("Started printing the AUT stacktrace of crash") - test.log("############################################################") - ls = subprocess.run( - ['ls', '-t', coredumpFolderPath], stdout=subprocess.PIPE - ).stdout.decode('utf-8') - coredumpFilename = ls.split('\n')[0] - test.log("located latest core dump file: %s" % coredumpFilename) - - if coredumpFilename: - test.log("Backtracking...") - test.log( - "%s" - % subprocess.run( - [ - 'gdb', - owncloudBinary, - coredumpFolderPath + coredumpFilename.strip(), - '-batch', - '-ex', - 'bt full', - ], - stdout=subprocess.PIPE, - ).stdout.decode('utf-8') - ) - - test.log("############################################################") - test.log("Finished printing AUT stacktrace") - - def getPollingInterval(): pollingInterval = '''[ownCloud] remotePollInterval={pollingInterval} diff --git a/test/gui/shared/scripts/helpers/StacktraceHelper.py b/test/gui/shared/scripts/helpers/StacktraceHelper.py new file mode 100644 index 000000000..14dc2e5c6 --- /dev/null +++ b/test/gui/shared/scripts/helpers/StacktraceHelper.py @@ -0,0 +1,67 @@ +import os +import subprocess +import glob +import re +from datetime import datetime + + +def getCoredumps(): + # read coredump location + with open("/proc/sys/kernel/core_pattern", "r") as f: + coredumpPath = f.read().strip("\n") + + # yields something like: /tmp/core-*-*-*-* + coredumpFilePattern = re.sub(r'%[a-zA-Z]{1}', '*', coredumpPath) + return glob.glob(coredumpFilePattern) + + +def generateStacktrace(context, coredumps): + message = ["###########################################"] + message.append("Scenario: " + context._data["title"]) + + for coredumpFile in coredumps: + message.append(parseStacktrace(coredumpFile)) + + message.append("###########################################") + message.append("") + message = "\n".join(message) + + stacktrace_file = os.environ.get("STACKTRACE_FILE", "../stacktrace.log") + # save stacktrace to a file + open(stacktrace_file, "a").write(message) + + +def parseStacktrace(coredumpFile): + message = [] + if coredumpFile: + coredumpFilename = os.path.basename(coredumpFile) + # example coredump file: core-1648445754-1001-11-!drone!src!build-GUI-tests!bin!owncloud + patterns = coredumpFilename.split('-') + appBinary = "-".join(patterns[4:]).replace('!', '/') + + message.append("-------------------------------------------") + message.append("Executable: " + appBinary) + message.append("Timestamp: " + str(datetime.fromtimestamp(float(patterns[1])))) + message.append("Process ID: " + patterns[2]) + message.append("Signal Number: " + patterns[3]) + message.append("-------------------------------------------") + message.append("<<<<< STACKTRACE START >>>>>") + message.append( + subprocess.run( + [ + 'gdb', + appBinary, + coredumpFile, + '-batch', + '-ex', + 'bt full', + ], + stdout=subprocess.PIPE, + ).stdout.decode('utf-8') + ) + message.append("<<<<< STACKTRACE END >>>>>") + + # remove coredump file + os.unlink(coredumpFile) + + return "\n".join(message) |