2017-10-02 19:03:43 +03:00
/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- /
/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
/ * T h i s S o u r c e C o d e F o r m i s s u b j e c t t o t h e t e r m s o f t h e M o z i l l a P u b l i c
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
"use strict" ;
2018-02-01 22:18:00 +03:00
var EXPORTED _SYMBOLS = [ "ReadTopManifest" , "CreateUrls" ] ;
2017-10-02 19:03:43 +03:00
2018-09-07 02:01:39 +03:00
Cu . import ( "resource://reftest/globals.jsm" , this ) ;
Cu . import ( "resource://reftest/reftest.jsm" , this ) ;
2018-02-28 20:51:34 +03:00
Cu . import ( "resource://gre/modules/Services.jsm" ) ;
Cu . import ( "resource://gre/modules/NetUtil.jsm" ) ;
2017-10-02 19:03:43 +03:00
const NS _SCRIPTSECURITYMANAGER _CONTRACTID = "@mozilla.org/scriptsecuritymanager;1" ;
const NS _NETWORK _PROTOCOL _CONTRACTID _PREFIX = "@mozilla.org/network/protocol;1?name=" ;
const NS _XREAPPINFO _CONTRACTID = "@mozilla.org/xre/app-info;1" ;
const RE _PROTOCOL = /^\w+:/ ;
const RE _PREF _ITEM = /^(|test-|ref-)pref\((.+?),(.*)\)$/ ;
2020-01-09 22:25:58 +03:00
function ReadTopManifest ( aFileURL , aFilter , aManifestID )
2017-10-02 19:03:43 +03:00
{
var url = g . ioService . newURI ( aFileURL ) ;
if ( ! url )
throw "Expected a file or http URL for the manifest." ;
g . manifestsLoaded = { } ;
2020-01-09 22:25:58 +03:00
ReadManifest ( url , aFilter , aManifestID ) ;
2017-10-02 19:03:43 +03:00
}
// Note: If you materially change the reftest manifest parsing,
2020-02-20 19:04:18 +03:00
// please keep the parser in layout/tools/reftest/__init__.py in sync.
2020-01-09 22:25:58 +03:00
function ReadManifest ( aURL , aFilter , aManifestID )
2017-10-02 19:03:43 +03:00
{
2018-01-11 17:53:10 +03:00
// Ensure each manifest is only read once. This assumes that manifests that
// are included with filters will be read via their include before they are
// read directly in the case of a duplicate
2017-10-02 19:03:43 +03:00
if ( g . manifestsLoaded . hasOwnProperty ( aURL . spec ) ) {
if ( g . manifestsLoaded [ aURL . spec ] === null )
return ;
else
aFilter = [ aFilter [ 0 ] , aFilter [ 1 ] , true ] ;
}
g . manifestsLoaded [ aURL . spec ] = aFilter [ 1 ] ;
2018-02-28 20:51:34 +03:00
var secMan = Cc [ NS _SCRIPTSECURITYMANAGER _CONTRACTID ]
. getService ( Ci . nsIScriptSecurityManager ) ;
2017-10-02 19:03:43 +03:00
var listURL = aURL ;
2019-11-11 18:47:36 +03:00
var channel = NetUtil . newChannel ( { uri : aURL ,
loadUsingSystemPrincipal : true } ) ;
2019-02-12 19:08:25 +03:00
var inputStream = channel . open ( ) ;
2017-10-02 19:03:43 +03:00
if ( channel instanceof Ci . nsIHttpChannel
&& channel . responseStatus != 200 ) {
g . logger . error ( "HTTP ERROR : " + channel . responseStatus ) ;
}
var streamBuf = getStreamContent ( inputStream ) ;
inputStream . close ( ) ;
var lines = streamBuf . split ( /\n|\r|\r\n/ ) ;
2019-11-11 18:47:36 +03:00
// The sandbox for fails-if(), etc., condition evaluation. This is not
// always required and so is created on demand.
var sandbox ;
function GetOrCreateSandbox ( ) {
if ( ! sandbox ) {
sandbox = BuildConditionSandbox ( aURL ) ;
}
return sandbox ;
}
2017-10-02 19:03:43 +03:00
var lineNo = 0 ;
var urlprefix = "" ;
2020-02-20 19:04:18 +03:00
var defaults = [ ] ;
2017-10-02 19:03:43 +03:00
var defaultTestPrefSettings = [ ] , defaultRefPrefSettings = [ ] ;
2017-10-31 12:44:17 +03:00
if ( g . compareRetainedDisplayLists ) {
2019-11-11 18:47:36 +03:00
AddRetainedDisplayListTestPrefs ( GetOrCreateSandbox ( ) , defaultTestPrefSettings ,
2017-10-31 12:44:17 +03:00
defaultRefPrefSettings ) ;
}
2017-10-02 19:03:43 +03:00
for ( var str of lines ) {
++ lineNo ;
if ( str . charAt ( 0 ) == "#" )
continue ; // entire line was a comment
var i = str . search ( /\s+#/ ) ;
if ( i >= 0 )
str = str . substring ( 0 , i ) ;
// strip leading and trailing whitespace
str = str . replace ( /^\s*/ , '' ) . replace ( /\s*$/ , '' ) ;
if ( ! str || str == "" )
continue ;
var items = str . split ( /\s+/ ) ; // split on whitespace
if ( items [ 0 ] == "url-prefix" ) {
if ( items . length != 2 )
throw "url-prefix requires one url in manifest file " + aURL . spec + " line " + lineNo ;
urlprefix = items [ 1 ] ;
continue ;
}
2020-02-20 19:04:18 +03:00
if ( items [ 0 ] == "defaults" ) {
items . shift ( ) ;
defaults = items ;
continue ;
}
2017-10-02 19:03:43 +03:00
var expected _status = EXPECTED _PASS ;
var allow _silent _fail = false ;
var minAsserts = 0 ;
var maxAsserts = 0 ;
var needs _focus = false ;
var slow = false ;
2020-03-09 18:20:11 +03:00
var skip = false ;
2017-10-02 19:03:43 +03:00
var testPrefSettings = defaultTestPrefSettings . concat ( ) ;
var refPrefSettings = defaultRefPrefSettings . concat ( ) ;
var fuzzy _delta = { min : 0 , max : 2 } ;
var fuzzy _pixels = { min : 0 , max : 1 } ;
var chaosMode = false ;
2018-10-01 23:25:27 +03:00
var wrCapture = { test : false , ref : false } ;
2018-01-11 17:53:10 +03:00
var nonSkipUsed = false ;
2019-07-05 00:35:04 +03:00
var noAutoFuzz = false ;
2017-10-02 19:03:43 +03:00
2020-02-20 19:04:18 +03:00
var origLength = items . length ;
items = defaults . concat ( items ) ;
2019-07-05 00:35:04 +03:00
while ( items [ 0 ] . match ( /^(fails|needs-focus|random|skip|asserts|slow|require-or|silentfail|pref|test-pref|ref-pref|fuzzy|chaos-mode|wr-capture|wr-capture-ref|noautofuzz)/ ) ) {
2017-10-02 19:03:43 +03:00
var item = items . shift ( ) ;
var stat ;
var cond ;
var m = item . match ( /^(fails|random|skip|silentfail)-if(\(.*\))$/ ) ;
if ( m ) {
stat = m [ 1 ] ;
// Note: m[2] contains the parentheses, and we want them.
2019-11-11 18:47:36 +03:00
cond = Cu . evalInSandbox ( m [ 2 ] , GetOrCreateSandbox ( ) ) ;
2017-10-02 19:03:43 +03:00
} else if ( item . match ( /^(fails|random|skip)$/ ) ) {
stat = item ;
cond = true ;
} else if ( item == "needs-focus" ) {
needs _focus = true ;
cond = false ;
} else if ( ( m = item . match ( /^asserts\((\d+)(-\d+)?\)$/ ) ) ) {
cond = false ;
minAsserts = Number ( m [ 1 ] ) ;
maxAsserts = ( m [ 2 ] == undefined ) ? minAsserts
: Number ( m [ 2 ] . substring ( 1 ) ) ;
} else if ( ( m = item . match ( /^asserts-if\((.*?),(\d+)(-\d+)?\)$/ ) ) ) {
cond = false ;
2019-11-11 18:47:36 +03:00
if ( Cu . evalInSandbox ( "(" + m [ 1 ] + ")" , GetOrCreateSandbox ( ) ) ) {
2017-10-02 19:03:43 +03:00
minAsserts = Number ( m [ 2 ] ) ;
maxAsserts =
( m [ 3 ] == undefined ) ? minAsserts
: Number ( m [ 3 ] . substring ( 1 ) ) ;
}
} else if ( item == "slow" ) {
cond = false ;
slow = true ;
} else if ( ( m = item . match ( /^require-or\((.*?)\)$/ ) ) ) {
var args = m [ 1 ] . split ( /,/ ) ;
if ( args . length != 2 ) {
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": wrong number of args to require-or" ;
}
var [ precondition _str , fallback _action ] = args ;
var preconditions = precondition _str . split ( /&&/ ) ;
cond = false ;
for ( var precondition of preconditions ) {
if ( precondition === "debugMode" ) {
// Currently unimplemented. Requires asynchronous
// JSD call + getting an event while no JS is running
stat = fallback _action ;
cond = true ;
break ;
} else if ( precondition === "true" ) {
// For testing
} else {
// Unknown precondition. Assume it is unimplemented.
stat = fallback _action ;
cond = true ;
break ;
}
}
} else if ( ( m = item . match ( /^slow-if\((.*?)\)$/ ) ) ) {
cond = false ;
2019-11-11 18:47:36 +03:00
if ( Cu . evalInSandbox ( "(" + m [ 1 ] + ")" , GetOrCreateSandbox ( ) ) )
2017-10-02 19:03:43 +03:00
slow = true ;
} else if ( item == "silentfail" ) {
cond = false ;
allow _silent _fail = true ;
} else if ( ( m = item . match ( RE _PREF _ITEM ) ) ) {
cond = false ;
2019-11-11 18:47:36 +03:00
if ( ! AddPrefSettings ( m [ 1 ] , m [ 2 ] , m [ 3 ] , GetOrCreateSandbox ( ) ,
testPrefSettings , refPrefSettings ) ) {
2017-10-02 19:03:43 +03:00
throw "Error in pref value in manifest file " + aURL . spec + " line " + lineNo ;
}
2018-08-22 05:14:03 +03:00
} else if ( ( m = item . match ( /^fuzzy\((\d+)-(\d+),(\d+)-(\d+)\)$/ ) ) ) {
2017-10-02 19:03:43 +03:00
cond = false ;
expected _status = EXPECTED _FUZZY ;
fuzzy _delta = ExtractRange ( m , 1 ) ;
fuzzy _pixels = ExtractRange ( m , 3 ) ;
2018-08-22 05:14:03 +03:00
} else if ( ( m = item . match ( /^fuzzy-if\((.*?),(\d+)-(\d+),(\d+)-(\d+)\)$/ ) ) ) {
2017-10-02 19:03:43 +03:00
cond = false ;
2019-11-11 18:47:36 +03:00
if ( Cu . evalInSandbox ( "(" + m [ 1 ] + ")" , GetOrCreateSandbox ( ) ) ) {
2017-10-02 19:03:43 +03:00
expected _status = EXPECTED _FUZZY ;
fuzzy _delta = ExtractRange ( m , 2 ) ;
fuzzy _pixels = ExtractRange ( m , 4 ) ;
}
} else if ( item == "chaos-mode" ) {
cond = false ;
chaosMode = true ;
2018-10-01 23:25:27 +03:00
} else if ( item == "wr-capture" ) {
cond = false ;
wrCapture . test = true ;
} else if ( item == "wr-capture-ref" ) {
cond = false ;
wrCapture . ref = true ;
2019-07-05 00:35:04 +03:00
} else if ( item == "noautofuzz" ) {
cond = false ;
noAutoFuzz = true ;
2017-10-02 19:03:43 +03:00
} else {
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": unexpected item " + item ;
}
2018-01-11 17:53:10 +03:00
if ( stat != "skip" ) {
nonSkipUsed = true ;
}
2017-10-02 19:03:43 +03:00
if ( cond ) {
if ( stat == "fails" ) {
expected _status = EXPECTED _FAIL ;
} else if ( stat == "random" ) {
expected _status = EXPECTED _RANDOM ;
} else if ( stat == "skip" ) {
2020-03-09 18:20:11 +03:00
skip = true ;
2017-10-02 19:03:43 +03:00
} else if ( stat == "silentfail" ) {
allow _silent _fail = true ;
}
}
}
2020-02-20 19:04:18 +03:00
if ( items . length > origLength ) {
// Implies we broke out of the loop before we finished processing
// defaults. This means defaults contained an invalid token.
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": invalid defaults token '" + items [ 0 ] + "'" ;
}
2017-10-02 19:03:43 +03:00
if ( minAsserts > maxAsserts ) {
throw "Bad range in manifest file " + aURL . spec + " line " + lineNo ;
}
var runHttp = false ;
var httpDepth ;
if ( items [ 0 ] == "HTTP" ) {
runHttp = ( aURL . scheme == "file" ) ; // We can't yet run the local HTTP server
// for non-local reftests.
httpDepth = 0 ;
items . shift ( ) ;
} else if ( items [ 0 ] . match ( /HTTP\(\.\.(\/\.\.)*\)/ ) ) {
// Accept HTTP(..), HTTP(../..), HTTP(../../..), etc.
runHttp = ( aURL . scheme == "file" ) ; // We can't yet run the local HTTP server
// for non-local reftests.
httpDepth = ( items [ 0 ] . length - 5 ) / 3 ;
items . shift ( ) ;
}
// do not prefix the url for include commands or urls specifying
// a protocol
if ( urlprefix && items [ 0 ] != "include" ) {
if ( items . length > 1 && ! items [ 1 ] . match ( RE _PROTOCOL ) ) {
items [ 1 ] = urlprefix + items [ 1 ] ;
}
if ( items . length > 2 && ! items [ 2 ] . match ( RE _PROTOCOL ) ) {
items [ 2 ] = urlprefix + items [ 2 ] ;
}
}
2019-07-08 19:37:45 +03:00
var principal = secMan . createContentPrincipal ( aURL , { } ) ;
2017-10-02 19:03:43 +03:00
if ( items [ 0 ] == "include" ) {
if ( items . length != 2 )
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": incorrect number of arguments to include" ;
if ( runHttp )
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": use of include with http" ;
2018-01-11 17:53:10 +03:00
// If the expected_status is EXPECTED_PASS (the default) then allow
2020-03-09 18:20:11 +03:00
// the include. If 'skip' is true, that means there was a skip
2018-01-11 17:53:10 +03:00
// or skip-if annotation (with a true condition) on this include
// statement, so we should skip the include. Any other expected_status
// is disallowed since it's nonintuitive as to what the intended
// effect is.
if ( nonSkipUsed ) {
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": include statement with annotation other than 'skip' or 'skip-if'" ;
2020-03-09 18:20:11 +03:00
} else if ( skip ) {
2018-01-11 17:53:10 +03:00
g . logger . info ( "Skipping included manifest at " + aURL . spec + " line " + lineNo + " due to matching skip condition" ) ;
} else {
// poor man's assertion
if ( expected _status != EXPECTED _PASS ) {
throw "Error in manifest file parsing code: we should never get expected_status=" + expected _status + " when nonSkipUsed=false (from " + aURL . spec + " line " + lineNo + ")" ;
}
var incURI = g . ioService . newURI ( items [ 1 ] , null , listURL ) ;
secMan . checkLoadURIWithPrincipal ( principal , incURI ,
2018-02-28 20:51:34 +03:00
Ci . nsIScriptSecurityManager . DISALLOW _SCRIPT ) ;
2020-01-09 22:25:58 +03:00
// Cannot use nsIFile or similar to manipulate the manifest ID; although it appears
// path-like, it does not refer to an actual path in the filesystem.
var newManifestID = aManifestID ;
var included = items [ 1 ] ;
// Remove included manifest file name.
// eg. dir1/dir2/reftest.list -> dir1/dir2
var pos = included . lastIndexOf ( "/" ) ;
if ( pos <= 0 ) {
included = "" ;
} else {
included = included . substring ( 0 , pos ) ;
}
// Simplify references to parent directories.
// eg. dir1/dir2/../dir3 -> dir1/dir3
while ( included . startsWith ( "../" ) ) {
pos = newManifestID . lastIndexOf ( "/" ) ;
if ( pos < 0 ) {
pos = 0 ;
}
newManifestID = newManifestID . substring ( 0 , pos ) ;
included = included . substring ( 3 ) ;
}
// Use a new manifest ID if the included manifest is in a different directory.
if ( included . length > 0 ) {
if ( newManifestID . length > 0 ) {
newManifestID = newManifestID + "/" + included ;
} else {
// parent directory includes may refer to the topsrcdir
newManifestID = included ;
}
}
ReadManifest ( incURI , aFilter , newManifestID ) ;
2018-01-11 17:53:10 +03:00
}
2018-02-02 00:22:55 +03:00
} else if ( items [ 0 ] == TYPE _LOAD || items [ 0 ] == TYPE _SCRIPT ) {
2018-12-11 17:06:34 +03:00
var type = items [ 0 ] ;
2017-10-02 19:03:43 +03:00
if ( items . length != 2 )
2018-12-11 17:06:34 +03:00
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": incorrect number of arguments to " + type ;
2020-03-09 18:20:11 +03:00
if ( type == TYPE _LOAD && expected _status != EXPECTED _PASS )
2017-10-02 19:03:43 +03:00
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": incorrect known failure type for load test" ;
2018-12-11 17:06:34 +03:00
AddTestItem ( { type : type ,
2017-10-02 19:03:43 +03:00
expected : expected _status ,
2018-02-02 00:22:55 +03:00
manifest : aURL . spec ,
2020-02-10 17:42:09 +03:00
manifestID : TestIdentifier ( aURL . spec , aManifestID ) ,
2017-10-02 19:03:43 +03:00
allowSilentFail : allow _silent _fail ,
minAsserts : minAsserts ,
maxAsserts : maxAsserts ,
needsFocus : needs _focus ,
slow : slow ,
2020-03-09 18:20:11 +03:00
skip : skip ,
2017-10-02 19:03:43 +03:00
prefSettings1 : testPrefSettings ,
prefSettings2 : refPrefSettings ,
fuzzyMinDelta : fuzzy _delta . min ,
fuzzyMaxDelta : fuzzy _delta . max ,
fuzzyMinPixels : fuzzy _pixels . min ,
fuzzyMaxPixels : fuzzy _pixels . max ,
2018-02-02 00:22:55 +03:00
runHttp : runHttp ,
httpDepth : httpDepth ,
url1 : items [ 1 ] ,
2017-10-02 19:03:43 +03:00
url2 : null ,
2018-10-01 23:25:27 +03:00
chaosMode : chaosMode ,
2019-07-05 00:35:04 +03:00
wrCapture : wrCapture ,
2020-01-09 22:25:58 +03:00
noAutoFuzz : noAutoFuzz } , aFilter , aManifestID ) ;
2017-10-02 19:03:43 +03:00
} else if ( items [ 0 ] == TYPE _REFTEST _EQUAL || items [ 0 ] == TYPE _REFTEST _NOTEQUAL || items [ 0 ] == TYPE _PRINT ) {
if ( items . length != 3 )
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": incorrect number of arguments to " + items [ 0 ] ;
if ( items [ 0 ] == TYPE _REFTEST _NOTEQUAL &&
expected _status == EXPECTED _FUZZY &&
( fuzzy _delta . min > 0 || fuzzy _pixels . min > 0 ) ) {
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": minimum fuzz must be zero for tests of type " + items [ 0 ] ;
}
var type = items [ 0 ] ;
2018-03-19 16:22:24 +03:00
if ( g . compareRetainedDisplayLists ) {
2017-10-02 19:03:43 +03:00
type = TYPE _REFTEST _EQUAL ;
2018-05-29 18:17:28 +03:00
// We expect twice as many assertion failures when comparing
// tests because we run each test twice.
2017-10-02 19:03:43 +03:00
minAsserts *= 2 ;
maxAsserts *= 2 ;
2018-05-29 18:17:28 +03:00
// Skip the test if it is expected to fail in both modes.
// It would unexpectedly "pass" in comparison mode mode when
// comparing the two failures, which is not a useful result.
2017-10-02 19:03:43 +03:00
if ( expected _status === EXPECTED _FAIL ||
expected _status === EXPECTED _RANDOM ) {
2020-03-09 18:20:11 +03:00
skip = true ;
2017-10-02 19:03:43 +03:00
}
}
AddTestItem ( { type : type ,
expected : expected _status ,
2018-02-02 00:22:55 +03:00
manifest : aURL . spec ,
2020-02-10 17:42:09 +03:00
manifestID : TestIdentifier ( aURL . spec , aManifestID ) ,
2017-10-02 19:03:43 +03:00
allowSilentFail : allow _silent _fail ,
minAsserts : minAsserts ,
maxAsserts : maxAsserts ,
needsFocus : needs _focus ,
slow : slow ,
2020-03-09 18:20:11 +03:00
skip : skip ,
2017-10-02 19:03:43 +03:00
prefSettings1 : testPrefSettings ,
prefSettings2 : refPrefSettings ,
fuzzyMinDelta : fuzzy _delta . min ,
fuzzyMaxDelta : fuzzy _delta . max ,
fuzzyMinPixels : fuzzy _pixels . min ,
fuzzyMaxPixels : fuzzy _pixels . max ,
2018-02-02 00:22:55 +03:00
runHttp : runHttp ,
httpDepth : httpDepth ,
url1 : items [ 1 ] ,
url2 : items [ 2 ] ,
2018-10-01 23:25:27 +03:00
chaosMode : chaosMode ,
2019-07-05 00:35:04 +03:00
wrCapture : wrCapture ,
2020-01-09 22:25:58 +03:00
noAutoFuzz : noAutoFuzz } , aFilter , aManifestID ) ;
2017-10-02 19:03:43 +03:00
} else {
throw "Error in manifest file " + aURL . spec + " line " + lineNo + ": unknown test type " + items [ 0 ] ;
}
}
}
// Read all available data from an input stream and return it
// as a string.
function getStreamContent ( inputStream )
{
var streamBuf = "" ;
2018-02-28 20:51:34 +03:00
var sis = Cc [ "@mozilla.org/scriptableinputstream;1" ] .
createInstance ( Ci . nsIScriptableInputStream ) ;
2017-10-02 19:03:43 +03:00
sis . init ( inputStream ) ;
var available ;
while ( ( available = sis . available ( ) ) != 0 ) {
streamBuf += sis . read ( available ) ;
}
return streamBuf ;
}
// Build the sandbox for fails-if(), etc., condition evaluation.
function BuildConditionSandbox ( aURL ) {
var sandbox = new Cu . Sandbox ( aURL . spec ) ;
2018-02-28 20:51:34 +03:00
var xr = Cc [ NS _XREAPPINFO _CONTRACTID ] . getService ( Ci . nsIXULRuntime ) ;
var appInfo = Cc [ NS _XREAPPINFO _CONTRACTID ] . getService ( Ci . nsIXULAppInfo ) ;
2017-10-02 19:03:43 +03:00
sandbox . isDebugBuild = g . debug . isDebugBuild ;
2020-05-28 00:22:54 +03:00
sandbox . isCoverageBuild = g . isCoverageBuild ;
2018-02-28 20:51:34 +03:00
var prefs = Cc [ "@mozilla.org/preferences-service;1" ] .
getService ( Ci . nsIPrefBranch ) ;
var env = Cc [ "@mozilla.org/process/environment;1" ] .
getService ( Ci . nsIEnvironment ) ;
2017-10-02 19:03:43 +03:00
2018-02-28 20:51:34 +03:00
sandbox . xulRuntime = Cu . cloneInto ( { widgetToolkit : xr . widgetToolkit , OS : xr . OS , XPCOMABI : xr . XPCOMABI } , sandbox ) ;
2017-10-02 19:03:43 +03:00
var testRect = g . browser . getBoundingClientRect ( ) ;
sandbox . smallScreen = false ;
if ( g . containingWindow . innerWidth < 800 || g . containingWindow . innerHeight < 1000 ) {
sandbox . smallScreen = true ;
}
2018-02-28 20:51:34 +03:00
var gfxInfo = ( NS _GFXINFO _CONTRACTID in Cc ) && Cc [ NS _GFXINFO _CONTRACTID ] . getService ( Ci . nsIGfxInfo ) ;
2017-10-02 19:03:43 +03:00
let readGfxInfo = function ( obj , key ) {
if ( g . contentGfxInfo && ( key in g . contentGfxInfo ) ) {
return g . contentGfxInfo [ key ] ;
}
return obj [ key ] ;
}
try {
sandbox . d2d = readGfxInfo ( gfxInfo , "D2DEnabled" ) ;
sandbox . dwrite = readGfxInfo ( gfxInfo , "DWriteEnabled" ) ;
2020-06-25 20:22:20 +03:00
sandbox . embeddedInFirefoxReality = readGfxInfo ( gfxInfo , "EmbeddedInFirefoxReality" ) ;
2017-10-02 19:03:43 +03:00
} catch ( e ) {
sandbox . d2d = false ;
sandbox . dwrite = false ;
2020-06-25 20:22:20 +03:00
sandbox . embeddedInFirefoxReality = false ;
2017-10-02 19:03:43 +03:00
}
var info = gfxInfo . getInfo ( ) ;
var canvasBackend = readGfxInfo ( info , "AzureCanvasBackend" ) ;
var contentBackend = readGfxInfo ( info , "AzureContentBackend" ) ;
sandbox . gpuProcess = gfxInfo . usingGPUProcess ;
sandbox . azureCairo = canvasBackend == "cairo" ;
sandbox . azureSkia = canvasBackend == "skia" ;
sandbox . skiaContent = contentBackend == "skia" ;
2019-02-28 17:59:16 +03:00
sandbox . azureSkiaGL = false ;
2017-10-02 19:03:43 +03:00
// true if we are using the same Azure backend for rendering canvas and content
sandbox . contentSameGfxBackendAsCanvas = contentBackend == canvasBackend
|| ( contentBackend == "none" && canvasBackend == "cairo" ) ;
2019-09-09 09:51:03 +03:00
sandbox . remoteCanvas = prefs . getBoolPref ( "gfx.canvas.remote" ) && sandbox . d2d && sandbox . gpuProcess ;
2017-10-02 19:03:43 +03:00
sandbox . layersGPUAccelerated =
g . windowUtils . layerManagerType != "Basic" ;
sandbox . d3d11 =
g . windowUtils . layerManagerType == "Direct3D 11" ;
sandbox . d3d9 =
g . windowUtils . layerManagerType == "Direct3D 9" ;
sandbox . layersOpenGL =
g . windowUtils . layerManagerType == "OpenGL" ;
2020-08-15 01:30:05 +03:00
sandbox . swgl =
g . windowUtils . layerManagerType == "WebRender (Software)" ;
2017-10-02 19:03:43 +03:00
sandbox . webrender =
2020-08-15 01:30:05 +03:00
g . windowUtils . layerManagerType == "WebRender" || sandbox . swgl ;
2017-10-02 19:03:43 +03:00
sandbox . layersOMTC =
g . windowUtils . layerManagerRemote == true ;
sandbox . advancedLayers =
g . windowUtils . usingAdvancedLayers == true ;
sandbox . layerChecksEnabled = ! sandbox . webrender ;
2017-09-27 07:17:11 +03:00
sandbox . retainedDisplayList =
prefs . getBoolPref ( "layout.display-list.retain" ) ;
2019-08-14 01:37:54 +03:00
sandbox . usesOverlayScrollbars = g . windowUtils . usesOverlayScrollbars ;
2017-10-02 19:03:43 +03:00
// Shortcuts for widget toolkits.
sandbox . Android = xr . OS == "Android" ;
sandbox . cocoaWidget = xr . widgetToolkit == "cocoa" ;
2019-08-21 15:25:42 +03:00
sandbox . gtkWidget = xr . widgetToolkit == "gtk" ;
2017-10-02 19:03:43 +03:00
sandbox . qtWidget = xr . widgetToolkit == "qt" ;
sandbox . winWidget = xr . widgetToolkit == "windows" ;
2017-09-14 11:01:06 +03:00
sandbox . is64Bit = xr . is64Bit ;
2019-06-11 19:06:41 +03:00
// GeckoView is currently uniquely identified by "android + e10s" but
// we might want to make this condition more precise in the future.
sandbox . geckoview = ( sandbox . Android && g . browserIsRemote ) ;
2017-10-02 19:03:43 +03:00
// Scrollbars that are semi-transparent. See bug 1169666.
2019-08-21 15:25:42 +03:00
sandbox . transparentScrollbars = xr . widgetToolkit == "gtk" ;
2017-10-02 19:03:43 +03:00
if ( sandbox . Android ) {
2018-02-28 20:51:34 +03:00
var sysInfo = Cc [ "@mozilla.org/system-info;1" ] . getService ( Ci . nsIPropertyBag2 ) ;
2017-10-02 19:03:43 +03:00
// This is currently used to distinguish Android 4.0.3 (SDK version 15)
// and later from Android 2.x
sandbox . AndroidVersion = sysInfo . getPropertyAsInt32 ( "version" ) ;
2019-11-09 01:05:50 +03:00
sandbox . emulator = readGfxInfo ( gfxInfo , "adapterDeviceID" ) . includes ( "Android Emulator" ) ;
sandbox . device = ! sandbox . emulator ;
2017-10-02 19:03:43 +03:00
}
# if MOZ _ASAN
sandbox . AddressSanitizer = true ;
# else
sandbox . AddressSanitizer = false ;
# endif
# if MOZ _WEBRTC
sandbox . webrtc = true ;
# else
sandbox . webrtc = false ;
# endif
2020-02-20 19:04:18 +03:00
let retainedDisplayListsEnabled = prefs . getBoolPref ( "layout.display-list.retain" , false ) ;
sandbox . retainedDisplayLists = retainedDisplayListsEnabled && ! g . compareRetainedDisplayLists ;
sandbox . compareRetainedDisplayLists = g . compareRetainedDisplayLists ;
2017-10-31 12:44:17 +03:00
2017-10-02 19:03:43 +03:00
# ifdef RELEASE _OR _BETA
sandbox . release _or _beta = true ;
# else
sandbox . release _or _beta = false ;
# endif
2018-02-28 20:51:34 +03:00
var hh = Cc [ NS _NETWORK _PROTOCOL _CONTRACTID _PREFIX + "http" ] .
getService ( Ci . nsIHttpProtocolHandler ) ;
2017-10-02 19:03:43 +03:00
var httpProps = [ "userAgent" , "appName" , "appVersion" , "vendor" ,
"vendorSub" , "product" , "productSub" , "platform" ,
"oscpu" , "language" , "misc" ] ;
sandbox . http = new sandbox . Object ( ) ;
httpProps . forEach ( ( x ) => sandbox . http [ x ] = hh [ x ] ) ;
// Set OSX to be the Mac OS X version, as an integer, or undefined
// for other platforms. The integer is formed by 100 times the
// major version plus the minor version, so 1006 for 10.6, 1010 for
// 10.10, etc.
var osxmatch = /Mac OS X (\d+).(\d+)$/ . exec ( hh . oscpu ) ;
sandbox . OSX = osxmatch ? parseInt ( osxmatch [ 1 ] ) * 100 + parseInt ( osxmatch [ 2 ] ) : undefined ;
// see if we have the test plugin available,
// and set a sandox prop accordingly
sandbox . haveTestPlugin = ! sandbox . Android && ! ! getTestPlugin ( "Test Plug-in" ) ;
// Set a flag on sandbox if the windows default theme is active
sandbox . windowsDefaultTheme = g . containingWindow . matchMedia ( "(-moz-windows-default-theme)" ) . matches ;
try {
2020-02-10 22:26:01 +03:00
sandbox . nativeThemePref = ! prefs . getBoolPref ( "widget.disable-native-theme-for-content" ) ;
2017-10-02 19:03:43 +03:00
} catch ( e ) {
sandbox . nativeThemePref = true ;
}
sandbox . gpuProcessForceEnabled = prefs . getBoolPref ( "layers.gpu-process.force-enabled" , false ) ;
2018-02-28 20:51:34 +03:00
sandbox . prefs = Cu . cloneInto ( {
2017-10-02 19:03:43 +03:00
getBoolPref : function ( p ) { return prefs . getBoolPref ( p ) ; } ,
getIntPref : function ( p ) { return prefs . getIntPref ( p ) ; }
} , sandbox , { cloneFunctions : true } ) ;
// Tests shouldn't care about this except for when they need to
// crash the content process
sandbox . browserIsRemote = g . browserIsRemote ;
2019-12-09 23:31:47 +03:00
sandbox . browserIsFission = g . browserIsFission ;
2017-10-02 19:03:43 +03:00
try {
2018-05-22 02:58:23 +03:00
sandbox . asyncPan = g . containingWindow . docShell . asyncPanZoomEnabled ;
2017-10-02 19:03:43 +03:00
} catch ( e ) {
sandbox . asyncPan = false ;
}
// Graphics features
sandbox . usesRepeatResampling = sandbox . d2d ;
2018-03-06 00:39:53 +03:00
// Running in a test-verify session?
sandbox . verify = prefs . getBoolPref ( "reftest.verify" , false ) ;
2019-05-24 21:41:14 +03:00
// Running with a variant enabled?
2020-09-25 05:01:15 +03:00
sandbox . fission = Services . appinfo . fissionAutostart ;
2018-10-02 20:14:41 +03:00
sandbox . serviceWorkerE10s = prefs . getBoolPref ( "dom.serviceWorkers.parent_intercept" , false ) ;
2017-10-02 19:03:43 +03:00
if ( ! g . dumpedConditionSandbox ) {
g . logger . info ( "Dumping JSON representation of sandbox" ) ;
2018-02-28 20:51:34 +03:00
g . logger . info ( JSON . stringify ( Cu . waiveXrays ( sandbox ) ) ) ;
2017-10-02 19:03:43 +03:00
g . dumpedConditionSandbox = true ;
}
return sandbox ;
}
2017-10-31 12:44:17 +03:00
function AddRetainedDisplayListTestPrefs ( aSandbox , aTestPrefSettings ,
aRefPrefSettings ) {
AddPrefSettings ( "test-" , "layout.display-list.retain" , "true" , aSandbox ,
aTestPrefSettings , aRefPrefSettings ) ;
AddPrefSettings ( "ref-" , "layout.display-list.retain" , "false" , aSandbox ,
aTestPrefSettings , aRefPrefSettings ) ;
}
2017-10-02 19:03:43 +03:00
function AddPrefSettings ( aWhere , aPrefName , aPrefValExpression , aSandbox , aTestPrefSettings , aRefPrefSettings ) {
var prefVal = Cu . evalInSandbox ( "(" + aPrefValExpression + ")" , aSandbox ) ;
var prefType ;
var valType = typeof ( prefVal ) ;
if ( valType == "boolean" ) {
prefType = PREF _BOOLEAN ;
} else if ( valType == "string" ) {
prefType = PREF _STRING ;
} else if ( valType == "number" && ( parseInt ( prefVal ) == prefVal ) ) {
prefType = PREF _INTEGER ;
} else {
return false ;
}
var setting = { name : aPrefName ,
type : prefType ,
value : prefVal } ;
2018-03-19 16:22:24 +03:00
if ( g . compareRetainedDisplayLists && aPrefName != "layout.display-list.retain" ) {
2017-10-02 19:03:43 +03:00
// ref-pref() is ignored, test-pref() and pref() are added to both
if ( aWhere != "ref-" ) {
aTestPrefSettings . push ( setting ) ;
aRefPrefSettings . push ( setting ) ;
}
} else {
if ( aWhere != "ref-" ) {
aTestPrefSettings . push ( setting ) ;
}
if ( aWhere != "test-" ) {
aRefPrefSettings . push ( setting ) ;
}
}
return true ;
}
2018-08-22 05:14:03 +03:00
function ExtractRange ( matches , startIndex ) {
2017-10-02 19:03:43 +03:00
return {
min : Number ( matches [ startIndex ] ) ,
2018-08-22 05:14:03 +03:00
max : Number ( matches [ startIndex + 1 ] )
2017-10-02 19:03:43 +03:00
} ;
}
2018-02-02 00:22:55 +03:00
function ServeTestBase ( aURL , depth ) {
2018-02-28 20:51:34 +03:00
var listURL = aURL . QueryInterface ( Ci . nsIFileURL ) ;
2017-10-02 19:03:43 +03:00
var directory = listURL . file . parent ;
// Allow serving a tree that's an ancestor of the directory containing
// the files so that they can use resources in ../ (etc.).
var dirPath = "/" ;
while ( depth > 0 ) {
dirPath = "/" + directory . leafName + dirPath ;
directory = directory . parent ;
-- depth ;
}
g . count ++ ;
var path = "/" + Date . now ( ) + "/" + g . count ;
g . server . registerDirectory ( path + "/" , directory ) ;
2018-02-28 20:51:34 +03:00
var secMan = Cc [ NS _SCRIPTSECURITYMANAGER _CONTRACTID ]
. getService ( Ci . nsIScriptSecurityManager ) ;
2017-10-02 19:03:43 +03:00
var testbase = g . ioService . newURI ( "http://localhost:" + g . httpServerPort +
path + dirPath ) ;
2019-09-27 12:48:53 +03:00
var testBasePrincipal = secMan . createContentPrincipal ( testbase , { } ) ;
2017-10-02 19:03:43 +03:00
// Give the testbase URI access to XUL and XBL
2019-09-27 12:48:53 +03:00
Services . perms . addFromPrincipal ( testBasePrincipal , "allowXULXBL" , Services . perms . ALLOW _ACTION ) ;
2018-02-02 00:22:55 +03:00
return testbase ;
}
function CreateUrls ( test ) {
2018-02-28 20:51:34 +03:00
let secMan = Cc [ NS _SCRIPTSECURITYMANAGER _CONTRACTID ]
. getService ( Ci . nsIScriptSecurityManager ) ;
2018-02-02 00:22:55 +03:00
let manifestURL = g . ioService . newURI ( test . manifest ) ;
let testbase = manifestURL ;
if ( test . runHttp )
testbase = ServeTestBase ( manifestURL , test . httpDepth )
2017-10-02 19:03:43 +03:00
function FileToURI ( file )
{
2018-02-02 00:22:55 +03:00
if ( file === null )
return file ;
2018-02-07 03:20:38 +03:00
2018-02-02 00:22:55 +03:00
var testURI = g . ioService . newURI ( file , null , testbase ) ;
2020-09-07 16:51:44 +03:00
let isChromeOrViewSource = testURI . scheme == "chrome" || testURI . scheme == "view-source" ;
let principal = isChromeOrViewSource ? secMan . getSystemPrincipal ( ) :
secMan . createContentPrincipal ( manifestURL , { } ) ;
2018-02-02 00:22:55 +03:00
secMan . checkLoadURIWithPrincipal ( principal , testURI ,
2018-02-28 20:51:34 +03:00
Ci . nsIScriptSecurityManager . DISALLOW _SCRIPT ) ;
2017-10-02 19:03:43 +03:00
return testURI ;
}
2018-02-02 00:22:55 +03:00
let files = [ test . url1 , test . url2 ] ;
[ test . url1 , test . url2 ] = files . map ( FileToURI ) ;
return test ;
2017-10-02 19:03:43 +03:00
}
2020-01-09 22:25:58 +03:00
function TestIdentifier ( aUrl , aManifestID ) {
// Construct a platform-independent and location-independent test identifier for
// a url; normally the identifier looks like a posix-compliant relative file
// path.
// Test urls may be simple file names, chrome: urls with full paths, about:blank, etc.
if ( aUrl . startsWith ( "about:" ) || aUrl . startsWith ( "data:" ) ) {
return aUrl ;
}
var pos = aUrl . lastIndexOf ( "/" ) ;
var url = ( pos < 0 ) ? aUrl : aUrl . substring ( pos + 1 ) ;
return ( aManifestID + "/" + url ) ;
}
function AddTestItem ( aTest , aFilter , aManifestID ) {
2017-10-02 19:03:43 +03:00
if ( ! aFilter )
aFilter = [ null , [ ] , false ] ;
2020-01-09 22:25:58 +03:00
var identifier = TestIdentifier ( aTest . url1 , aManifestID ) ;
if ( aTest . url2 !== null ) {
identifier = [ identifier , aTest . type , TestIdentifier ( aTest . url2 , aManifestID ) ] ;
}
2018-02-01 22:18:00 +03:00
var { url1 , url2 } = CreateUrls ( Object . assign ( { } , aTest ) ) ;
2018-02-02 00:22:55 +03:00
2017-10-02 19:03:43 +03:00
var globalFilter = aFilter [ 0 ] ;
var manifestFilter = aFilter [ 1 ] ;
var invertManifest = aFilter [ 2 ] ;
2018-06-18 16:46:27 +03:00
if ( globalFilter && ! globalFilter . test ( url1 . spec ) )
return ;
if ( manifestFilter && ! ( invertManifest ^ manifestFilter . test ( url1 . spec ) ) )
2017-10-02 19:03:43 +03:00
return ;
if ( g . focusFilterMode == FOCUS _FILTER _NEEDS _FOCUS _TESTS &&
! aTest . needsFocus )
return ;
if ( g . focusFilterMode == FOCUS _FILTER _NON _NEEDS _FOCUS _TESTS &&
aTest . needsFocus )
return ;
2020-01-09 22:25:58 +03:00
aTest . identifier = identifier ;
2017-10-02 19:03:43 +03:00
g . urls . push ( aTest ) ;
2018-06-18 15:47:29 +03:00
// Periodically log progress to avoid no-output timeout on slow platforms.
// No-output timeouts during manifest parsing have been a problem for
// jsreftests on Android/debug. Any logging resets the no-output timer,
// even debug logging which is normally not displayed.
if ( ( g . urls . length % 5000 ) == 0 )
g . logger . debug ( g . urls . length + " tests found..." ) ;
2017-10-02 19:03:43 +03:00
}