# Copyright (C) 2010 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import cPickle
from webkitpy.layout_tests.models import test_expectations
def is_reftest_failure(failure_list):
failure_types = [type(f) for f in failure_list]
return set((FailureReftestMismatch, FailureReftestMismatchDidNotOccur, FailureReftestNoImagesGenerated)).intersection(failure_types)
# FIXME: This is backwards. Each TestFailure subclass should know what
# test_expectation type it corresponds too. Then this method just
# collects them all from the failure list and returns the worst one.
def determine_result_type(failure_list):
"""Takes a set of test_failures and returns which result type best fits
the list of failures. "Best fits" means we use the worst type of failure.
Returns:
one of the test_expectations result types - PASS, FAIL, CRASH, etc."""
if not failure_list or len(failure_list) == 0:
return test_expectations.PASS
failure_types = [type(f) for f in failure_list]
if FailureCrash in failure_types:
return test_expectations.CRASH
elif FailureLeak in failure_types:
return test_expectations.LEAK
elif FailureTimeout in failure_types:
return test_expectations.TIMEOUT
elif FailureEarlyExit in failure_types:
return test_expectations.SKIP
elif (FailureMissingResult in failure_types or
FailureMissingImage in failure_types or
FailureMissingImageHash in failure_types or
FailureMissingAudio in failure_types):
return test_expectations.MISSING
else:
is_text_failure = (FailureTextMismatch in failure_types or
FailureTestHarnessAssertion in failure_types)
is_image_failure = (FailureImageHashIncorrect in failure_types or
FailureImageHashMismatch in failure_types)
is_audio_failure = (FailureAudioMismatch in failure_types)
if is_text_failure and is_image_failure:
return test_expectations.IMAGE_PLUS_TEXT
elif is_text_failure:
return test_expectations.TEXT
elif is_image_failure or is_reftest_failure(failure_list):
return test_expectations.IMAGE
elif is_audio_failure:
return test_expectations.AUDIO
else:
raise ValueError("unclassifiable set of failures: "
+ str(failure_types))
class TestFailure(object):
"""Abstract base class that defines the failure interface."""
@staticmethod
def loads(s):
"""Creates a TestFailure object from the specified string."""
return cPickle.loads(s)
def message(self):
"""Returns a string describing the failure in more detail."""
raise NotImplementedError
def __eq__(self, other):
return self.__class__.__name__ == other.__class__.__name__
def __ne__(self, other):
return self.__class__.__name__ != other.__class__.__name__
def __hash__(self):
return hash(self.__class__.__name__)
def dumps(self):
"""Returns the string/JSON representation of a TestFailure."""
return cPickle.dumps(self)
def driver_needs_restart(self):
"""Returns True if we should kill the driver before the next test."""
return False
class FailureTimeout(TestFailure):
def __init__(self, is_reftest=False):
super(FailureTimeout, self).__init__()
self.is_reftest = is_reftest
def message(self):
return "test timed out"
def driver_needs_restart(self):
return True
class FailureCrash(TestFailure):
def __init__(self, is_reftest=False, process_name='content_shell', pid=None):
super(FailureCrash, self).__init__()
self.process_name = process_name
self.pid = pid
self.is_reftest = is_reftest
def message(self):
if self.pid:
return "%s crashed [pid=%d]" % (self.process_name, self.pid)
return self.process_name + " crashed"
def driver_needs_restart(self):
return True
class FailureLeak(TestFailure):
def __init__(self, is_reftest=False, log=''):
super(FailureLeak, self).__init__()
self.is_reftest = is_reftest
self.log = log
def message(self):
return "leak detected: %s" % (self.log)
class FailureMissingResult(TestFailure):
def message(self):
return "-expected.txt was missing"
class FailureTestHarnessAssertion(TestFailure):
def message(self):
return "asserts failed"
class FailureTextMismatch(TestFailure):
def message(self):
return "text diff"
class FailureMissingImageHash(TestFailure):
def message(self):
return "-expected.png was missing an embedded checksum"
class FailureMissingImage(TestFailure):
def message(self):
return "-expected.png was missing"
class FailureImageHashMismatch(TestFailure):
def message(self):
return "image diff"
class FailureImageHashIncorrect(TestFailure):
def message(self):
return "-expected.png embedded checksum is incorrect"
class FailureReftestMismatch(TestFailure):
def __init__(self, reference_filename=None):
super(FailureReftestMismatch, self).__init__()
self.reference_filename = reference_filename
def message(self):
return "reference mismatch"
class FailureReftestMismatchDidNotOccur(TestFailure):
def __init__(self, reference_filename=None):
super(FailureReftestMismatchDidNotOccur, self).__init__()
self.reference_filename = reference_filename
def message(self):
return "reference mismatch didn't happen"
class FailureReftestNoImagesGenerated(TestFailure):
def __init__(self, reference_filename=None):
super(FailureReftestNoImagesGenerated, self).__init__()
self.reference_filename = reference_filename
def message(self):
return "reference didn't generate pixel results."
class FailureMissingAudio(TestFailure):
def message(self):
return "expected audio result was missing"
class FailureAudioMismatch(TestFailure):
def message(self):
return "audio mismatch"
class FailureEarlyExit(TestFailure):
def message(self):
return "skipped due to early exit"
# Convenient collection of all failure classes for anything that might
# need to enumerate over them all.
ALL_FAILURE_CLASSES = (FailureTimeout, FailureCrash, FailureMissingResult,
FailureTestHarnessAssertion,
FailureTextMismatch, FailureMissingImageHash,
FailureMissingImage, FailureImageHashMismatch,
FailureImageHashIncorrect, FailureReftestMismatch,
FailureReftestMismatchDidNotOccur, FailureReftestNoImagesGenerated,
FailureMissingAudio, FailureAudioMismatch,
FailureEarlyExit)
# -*- coding: utf-8 -*-
# $Id: failurereason.py $
"""
Test Manager - Failure Reasons.
"""
__copyright__ = \
"""
Copyright (C) 2012-2015 Oracle Corporation
This file is part of VirtualBox Open Source Edition (OSE), as
available from http://www.virtualbox.org. This file is free software;
you can redistribute it and/or modify it under the terms of the GNU
General Public License (GPL) as published by the Free Software
Foundation, in version 2 as it comes in the "COPYING" file of the
VirtualBox OSE distribution. VirtualBox OSE is distributed in the
hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
The contents of this file may alternatively be used under the terms
of the Common Development and Distribution License Version 1.0
(CDDL) only, as it comes in the "COPYING.CDDL" file of the
VirtualBox OSE distribution, in which case the provisions of the
CDDL are applicable instead of those of the GPL.
You may elect to license modified versions of this file under the
terms and conditions of either the GPL or the CDDL or both.
"""
__version__ = "$Revision: 100880 $"
# Validation Kit imports.
from testmanager.core.base import ModelDataBase, ModelLogicBase, TMExceptionBase
class FailureReasonData(ModelDataBase):
"""
Failure Reason Data.
"""
ksIdAttr = 'idFailureReason';
ksParam_idFailureReason = 'FailureReasonData_idFailureReason'
ksParam_tsEffective = 'FailureReasonData_tsEffective'
ksParam_tsExpire = 'FailureReasonData_tsExpire'
ksParam_uidAuthor = 'FailureReasonData_uidAuthor'
ksParam_idFailureCategory = 'FailureReasonData_idFailureCategory'
ksParam_sShort = 'FailureReasonData_sShort'
ksParam_sFull = 'FailureReasonData_sFull'
ksParam_iTicket = 'FailureReasonData_iTicket'
ksParam_asUrls = 'FailureReasonData_asUrls'
kasAllowNullAttributes = [ 'idFailureReason', 'tsEffective', 'tsExpire',
'uidAuthor', 'iTicket', 'asUrls' ]
def __init__(self):
ModelDataBase.__init__(self);
#
# Initialize with defaults.
# See the database for explanations of each of these fields.
#
self.idFailureReason = None
self.tsEffective = None
self.tsExpire = None
self.uidAuthor = None
self.idFailureCategory = None
self.sShort = None
self.sFull = None
self.iTicket = None
self.asUrls = None
def initFromDbRow(self, aoRow):
"""
Re-initializes the data with a row from a SELECT * FROM FailureReasons.
Returns self. Raises exception if the row is None or otherwise invalid.
"""
if aoRow is None:
raise TMExceptionBase('Failure Reason not found.');
self.idFailureReason = aoRow[0]
self.tsEffective = aoRow[1]
self.tsExpire = aoRow[2]
self.uidAuthor = aoRow[3]
self.idFailureCategory = aoRow[4]
self.sShort = aoRow[5]
self.sFull = aoRow[6]
self.iTicket = aoRow[7]
self.asUrls = aoRow[8]
return self
class FailureReasonLogic(ModelLogicBase): # pylint: disable=R0903
"""
Failure Reason logic.
"""
def fetchForListing(self, iStart, cMaxRows, tsNow):
"""
Fetches Failure Category records.
Returns an array (list) of FailureReasonData items, empty list if none.
Raises exception on error.
"""
if tsNow is None:
self._oDb.execute('SELECT *\n'
'FROM FailureReasons\n'
'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
'ORDER BY idFailureReason DESC\n'
'LIMIT %s OFFSET %s\n'
, (cMaxRows, iStart,));
else:
self._oDb.execute('SELECT *\n'
'FROM FailureReasons\n'
'WHERE tsExpire > %s\n'
' AND tsEffective <= %s\n'
'ORDER BY idFailureReason DESC\n'
'LIMIT %s OFFSET %s\n'
, (tsNow, tsNow, cMaxRows, iStart,));
aoRows = []
for aoRow in self._oDb.fetchAll():
aoRows.append(FailureReasonData().initFromDbRow(aoRow))
return aoRows
def fetchForCombo(self, tsEffective = None):
"""
Gets the list of Failure Reasons for a combo box.
Returns an array of (value [idFailureReason], drop-down-name [sShort],
hover-text [sFull]) tuples.
"""
if tsEffective is None:
self._oDb.execute('SELECT idFailureReason, sShort, sFull\n'
'FROM FailureReasons\n'
'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
'ORDER BY sShort')
else:
self._oDb.execute('SELECT idFailureReason, sShort, sFull\n'
'FROM FailureReasons\n'
'WHERE tsExpire > %s\n'
' AND tsEffective <= %s\n'
'ORDER BY sShort'
, (tsEffective, tsEffective))
return self._oDb.fetchAll()
def getById(self, idFailureReason):
"""Get Failure Reason data by idFailureReason"""
self._oDb.execute('SELECT *\n'
'FROM FailureReasons\n'
'WHERE tsExpire = \'infinity\'::timestamp\n'
' AND idFailureReason = %s;', (idFailureReason,))
aRows = self._oDb.fetchAll()
if len(aRows) not in (0, 1):
raise self._oDb.integrityException(
'Found more than one failure reasons with the same credentials. Database structure is corrupted.')
try:
return FailureReasonData().initFromDbRow(aRows[0])
except IndexError:
return None
def getIdsByCategory(self, idFailureCategory, tsEffective=None):
"""
Gets the list of Failure Ressons IDs,
all the items belong to @param idFailureCategory
"""
if tsEffective is None:
self._oDb.execute('SELECT idFailureReason\n'
'FROM FailureReasons\n'
'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
' AND idFailureCategory = %s\n'
'ORDER BY idFailureReason DESC'
, (idFailureCategory,))
else:
self._oDb.execute('SELECT idFailureReason\n'
'FROM FailureReasons\n'
'WHERE tsExpire > %s\n'
' AND tsEffective <= %s\n'
' AND idFailureCategory = %s\n'
'ORDER BY idFailureReason DESC'
, (tsEffective, tsEffective, idFailureCategory))
return self._oDb.fetchAll()
def getAll(self, tsEffective=None):
"""
Gets the list of all Failure Reasons.
Returns an array of FailureReasonData instances.
"""
if tsEffective is None:
self._oDb.execute('SELECT *\n'
'FROM FailureReasons\n'
'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
'ORDER BY idFailureReason DESC')
else:
self._oDb.execute('SELECT *\n'
'FROM FailureReasons\n'
'WHERE tsExpire > %s\n'
' AND tsEffective <= %s\n'
'ORDER BY idFailureReason DESC'
, (tsEffective, tsEffective))
aoRet = []
for aoRow in self._oDb.fetchAll():
aoRet.append(FailureReasonData().initFromDbRow(aoRow))
return aoRet
def addEntry(self, oFailureReasonData, uidAuthor, fCommit=True):
"""Add record to database"""
# Check if record with the same sShort fiels is already exists
self._oDb.execute('SELECT *\n'
'FROM FailureReasons\n'
'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
' AND sShort = %s\n',
(oFailureReasonData.sShort,))
if len(self._oDb.fetchAll()) != 0:
raise Exception('Record already exist')
# Add record
self._oDb.execute('INSERT INTO FailureReasons (\n'
' uidAuthor, idFailureCategory,'
' sShort, sFull, iTicket, asUrls'
')\n'
'VALUES (%s, %s, %s, %s, %s, %s)',
(uidAuthor,
oFailureReasonData.idFailureCategory,
oFailureReasonData.sShort,
oFailureReasonData.sFull,
oFailureReasonData.iTicket,
oFailureReasonData.asUrls))
if fCommit:
self._oDb.commit()
return True
def remove(self, uidAuthor, idFailureReason, fNeedCommit=True):
"""
Historize record
"""
self._oDb.execute('UPDATE FailureReasons\n'
'SET tsExpire = CURRENT_TIMESTAMP,\n'
' uidAuthor = %s\n'
'WHERE idFailureReason = %s\n'
' AND tsExpire = \'infinity\'::TIMESTAMP\n',
(uidAuthor, idFailureReason))
# Also historize Black List records
self._oDb.execute('UPDATE BuildBlackList\n'
'SET tsExpire = CURRENT_TIMESTAMP,\n'
' uidAuthor = %s\n'
'WHERE idFailureReason = %s\n'
' AND tsExpire = \'infinity\'::TIMESTAMP\n',
(uidAuthor, idFailureReason))
if fNeedCommit:
self._oDb.commit()
return True
def editEntry(self, oFailureReasonData, uidAuthor, fCommit=True):
"""Modify database record"""
# Check if record exists
oFailureReasonDataOld = self.getById(oFailureReasonData.idFailureReason)
if oFailureReasonDataOld is None:
raise TMExceptionBase(
'Failure Reason (id: %d) does not exist'
% oFailureReasonData.idFailureReason)
# Check if anything has been changed
if oFailureReasonData.isEqual(oFailureReasonDataOld):
return True
# Historize record
self.remove(
uidAuthor, oFailureReasonData.idFailureReason, fNeedCommit=False)
# Add new record (keeping its ID)
self._oDb.execute('INSERT INTO FailureReasons (\n'
' idFailureReason,'
' uidAuthor,'
' idFailureCategory,'
' sShort,'
' sFull,'
' iTicket,'
' asUrls'
')\n'
'VALUES (%s, %s, %s, %s, %s, %s, %s)',
(oFailureReasonData.idFailureReason,
uidAuthor,
oFailureReasonData.idFailureCategory,
oFailureReasonData.sShort,
oFailureReasonData.sFull,
oFailureReasonData.iTicket,
oFailureReasonData.asUrls
))
if fCommit:
self._oDb.commit()
return True
var successRedirect = '/';
var failureRedirect = '/signin';
var linkFailureRedirect = '/account';
module.exports = {
local: {
provider: 'local',
module: 'passport-local',
usernameField: 'email',
passwordField: 'password',
authPath: '/auth/local',
successRedirect: successRedirect,
failureRedirect: '/email-signin',
session: true,
failureFlash: true
},
'facebook-login': {
provider: 'facebook',
module: 'passport-facebook',
clientID: process.env.FACEBOOK_ID,
clientSecret: process.env.FACEBOOK_SECRET,
authPath: '/auth/facebook',
callbackURL: '/auth/facebook/callback',
callbackPath: '/auth/facebook/callback',
successRedirect: successRedirect,
failureRedirect: failureRedirect,
scope: ['email'],
failureFlash: true
},
'facebook-link': {
provider: 'facebook',
module: 'passport-facebook',
clientID: process.env.FACEBOOK_ID,
clientSecret: process.env.FACEBOOK_SECRET,
authPath: '/link/facebook',
callbackURL: '/link/facebook/callback',
callbackPath: '/link/facebook/callback',
successRedirect: successRedirect,
failureRedirect: linkFailureRedirect,
scope: ['email', 'user_likes'],
link: true,
failureFlash: true
},
'google-login': {
provider: 'google',
authScheme: 'oauth2',
module: 'passport-google-oauth2',
clientID: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
authPath: '/auth/google',
callbackURL: '/auth/google/callback',
callbackPath: '/auth/google/callback',
successRedirect: successRedirect,
failureRedirect: failureRedirect,
scope: ['email', 'profile'],
failureFlash: true
},
'google-link': {
provider: 'google',
authScheme: 'oauth2',
module: 'passport-google-oauth2',
clientID: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
authPath: '/link/google',
callbackURL: '/link/google/callback',
callbackPath: '/link/google/callback',
successRedirect: successRedirect,
failureRedirect: linkFailureRedirect,
scope: ['email', 'profile'],
link: true,
failureFlash: true
},
'twitter-login': {
provider: 'twitter',
authScheme: 'oauth',
module: 'passport-twitter',
authPath: '/auth/twitter',
callbackURL: '/auth/twitter/callback',
callbackPath: '/auth/twitter/callback',
successRedirect: successRedirect,
failureRedirect: failureRedirect,
consumerKey: process.env.TWITTER_KEY,
consumerSecret: process.env.TWITTER_SECRET,
failureFlash: true
},
'twitter-link': {
provider: 'twitter',
authScheme: 'oauth',
module: 'passport-twitter',
authPath: '/link/twitter',
callbackURL: '/link/twitter/callback',
callbackPath: '/link/twitter/callback',
successRedirect: successRedirect,
failureRedirect: linkFailureRedirect,
consumerKey: process.env.TWITTER_KEY,
consumerSecret: process.env.TWITTER_SECRET,
link: true,
failureFlash: true
},
'linkedin-login': {
provider: 'linkedin',
authScheme: 'oauth2',
module: 'passport-linkedin-oauth2',
authPath: '/auth/linkedin',
callbackURL: '/auth/linkedin/callback',
callbackPath: '/auth/linkedin/callback',
successRedirect: successRedirect,
failureRedirect: failureRedirect,
clientID: process.env.LINKEDIN_ID,
clientSecret: process.env.LINKEDIN_SECRET,
scope: ['r_basicprofile', 'r_emailaddress'],
authOptions: {
state: process.env.LINKEDIN_STATE
},
failureFlash: true
},
'linkedin-link': {
provider: 'linkedin',
authScheme: 'oauth2',
module: 'passport-linkedin-oauth2',
authPath: '/link/linkedin',
callbackURL: '/link/linkedin/callback',
callbackPath: '/link/linkedin/callback',
successRedirect: successRedirect,
failureRedirect: linkFailureRedirect,
clientID: process.env.LINKEDIN_ID,
clientSecret: process.env.LINKEDIN_SECRET,
scope: ['r_basicprofile', 'r_emailaddress'],
authOptions: {
state: process.env.LINKEDIN_STATE
},
link: true,
failureFlash: true
},
'github-login': {
provider: 'github',
authScheme: 'oauth2',
module: 'passport-github',
authPath: '/auth/github',
callbackURL: '/auth/github/callback',
callbackPath: '/auth/github/callback',
successRedirect: successRedirect,
failureRedirect: failureRedirect,
clientID: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
scope: ['email'],
failureFlash: true
},
'github-link': {
provider: 'github',
authScheme: 'oauth2',
module: 'passport-github',
authPath: '/link/github',
callbackURL: '/auth/github/callback/link',
callbackPath: '/auth/github/callback/link',
successRedirect: successRedirect,
failureRedirect: linkFailureRedirect,
clientID: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
scope: ['email'],
link: true,
failureFlash: true
}
};
/*global cordova*/
module.exports = {
connect: function (macAddress, success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "connect", [macAddress]);
},
// Android only - see http://goo.gl/1mFjZY
connectInsecure: function (macAddress, success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "connectInsecure", [macAddress]);
},
disconnect: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "disconnect", []);
},
// list bound devices
list: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "list", []);
},
isEnabled: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "isEnabled", []);
},
isConnected: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "isConnected", []);
},
// the number of bytes of data available to read is passed to the success function
available: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "available", []);
},
// read all the data in the buffer
read: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "read", []);
},
// reads the data in the buffer up to and including the delimiter
readUntil: function (delimiter, success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "readUntil", [delimiter]);
},
// writes data to the bluetooth serial port - data must be a string
write: function (data, success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "write", [data]);
},
// calls the success callback when new data is available
subscribe: function (delimiter, success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "subscribe", [delimiter]);
},
// removes data subscription
unsubscribe: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "unsubscribe", []);
},
// clears the data buffer
clear: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "clear", []);
},
// reads the RSSI of the *connected* peripherial
readRSSI: function (success, failure) {
cordova.exec(success, failure, "BluetoothSerial", "readRSSI", []);
}
};
Accelerate Your Automation Test Cycles With LambdaTest
Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.