forked from mirrors/gecko-dev
		
	 b6fe4bc8c8
			
		
	
	
		b6fe4bc8c8
		
	
	
	
	
		
			
			Update the "Running Tests" section of the Reftests documentation. Differential Revision: https://phabricator.services.mozilla.com/D161799
		
			
				
	
	
		
			763 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			763 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| Layout Engine Visual Tests (reftest)
 | |
| ====================================
 | |
| 
 | |
| Layout Engine Visual Tests (reftest)
 | |
| L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
 | |
| July 19, 2006
 | |
| 
 | |
| This code is designed to run tests of Mozilla's layout engine.  These
 | |
| tests consist of an HTML (or other format) file along with a reference
 | |
| in the same format.  The tests are run based on a manifest file, and for
 | |
| each test, PASS or FAIL is reported, and UNEXPECTED is reported if the
 | |
| result (PASS or FAIL) was not the expected result noted in the manifest.
 | |
| 
 | |
| Images of the display of both tests are captured, and most test types
 | |
| involve comparing these images (e.g., test types == or !=) to determine
 | |
| whether the test passed.  The captures of the tests are taken in a
 | |
| viewport that is 800 pixels wide and 1000 pixels tall, so any content
 | |
| outside that area will be ignored (except for any scrollbars that are
 | |
| displayed).  Ideally, however, tests should be written so that they fit
 | |
| within 600x600, since we may in the future want to switch to 600x600 to
 | |
| match http://lists.w3.org/Archives/Public/www-style/2012Sep/0562.html .
 | |
| 
 | |
| Why this way?
 | |
| -------------
 | |
| 
 | |
| Writing HTML tests where the reference rendering is also in HTML is
 | |
| harder than simply writing bits of HTML that can be regression-tested by
 | |
| comparing the rendering of an older build to that of a newer build
 | |
| (perhaps using stored reference images from the older build).  However,
 | |
| comparing across time has major disadvantages:
 | |
| 
 | |
|  * Comparisons across time either require two runs for every test, or
 | |
|    they require stored reference images appropriate for the platform and
 | |
|    configuration (often limiting testing to a very specific
 | |
|    configuration).
 | |
| 
 | |
|  * Comparisons across time may fail due to expected changes, for
 | |
|    example, changes in the default style sheet for HTML, changes in the
 | |
|    appearance of form controls, or changes in default preferences like
 | |
|    default font size or default colors.
 | |
| 
 | |
| Using tests for which the pass criteria were explicitly chosen allows
 | |
| running tests at any time to see whether they still pass.
 | |
| 
 | |
| Manifest Format
 | |
| ---------------
 | |
| 
 | |
| The test manifest format is a plain text file.  A line starting with a
 | |
| ``"#"`` is a comment.  Lines may be commented using whitespace followed by
 | |
| a ``"#"`` and the comment.  Each non-blank line (after removal of comments)
 | |
| must be one of the following:
 | |
| 
 | |
| Inclusion of another manifest
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
|    ``<skip-type>* include <relative_path>``
 | |
| 
 | |
|    ``<skip-type>`` is one of the skip or skip-if items (see their definitions
 | |
|    in ``<failure-type>`` below). If any of the skip types evaluate to true (i.e.
 | |
|    they are a plain ``skip`` or they are a ``skip-if`` with a condition that
 | |
|    evaluates to true), then the include statement is skipped. Otherwise,
 | |
|    reftests in the specified manifest are included in the set of reftests
 | |
|    that are run.
 | |
| 
 | |
| A test item
 | |
| ~~~~~~~~~~~
 | |
| 
 | |
|    ``[ <failure-type> | <preference> ]* [<http>] <type> <url> <url_ref>``
 | |
| 
 | |
|    where
 | |
| 
 | |
|    a. ``<failure-type>`` (optional) is one of the following:
 | |
| 
 | |
|       ``fails``
 | |
|           The test passes if the images of the two renderings DO NOT meet the
 | |
|           conditions specified in the ``<type>``.
 | |
| 
 | |
|       ``fails-if(condition)``
 | |
|           If the condition is met, the test passes if the images of the two
 | |
|           renderings DO NOT meet the conditions of ``<type>``. If the condition
 | |
|           is not met, the test passes if the conditions of ``<type>`` are met.
 | |
| 
 | |
|       ``needs-focus``
 | |
|           The test fails or times out if the reftest window is not focused.
 | |
| 
 | |
|       ``random``
 | |
|           The results of the test are random and therefore not to be considered in the output.
 | |
| 
 | |
|       ``random-if(condition)``
 | |
|           The results of the test are random if a given condition is met.
 | |
| 
 | |
|       ``silentfail``
 | |
|           This test may fail silently, and if that happens it should count as if
 | |
|           the test passed. This is useful for cases where silent failure is the
 | |
|           intended behavior (for example, in an out of memory situation in
 | |
|           JavaScript, we stop running the script silently and immediately, in
 | |
|           hopes of reclaiming enough memory to keep the browser functioning).
 | |
| 
 | |
|       ``silentfail-if(condition)``
 | |
|           This test may fail silently if the condition is met.
 | |
| 
 | |
|       ``skip``
 | |
|           This test should not be run. This is useful when a test fails in a
 | |
|           catastrophic way, such as crashing or hanging the browser. Using
 | |
|           ``skip`` is preferred to simply commenting out the test because we
 | |
|           want to report the test failure at the end of the test run.
 | |
| 
 | |
|       ``skip-if(condition)``
 | |
|           If the condition is met, the test is not run. This is useful if, for
 | |
|           example, the test crashes only on a particular platform (i.e. it
 | |
|           allows us to get test coverage on the other platforms).
 | |
| 
 | |
|       ``slow``
 | |
|           The test may take a long time to run, so run it if slow tests are
 | |
|           either enabled or not disabled (test manifest interpreters may choose
 | |
|           whether or not to run such tests by default).
 | |
| 
 | |
|       ``slow-if(condition)``
 | |
|           If the condition is met, the test is treated as if ``slow`` had been
 | |
|           specified.  This is useful for tests which are slow only on particular
 | |
|           platforms (e.g. a test which exercised out-of-memory behavior might be
 | |
|           fast on a 32-bit system but inordinately slow on a 64-bit system).
 | |
| 
 | |
|       ``fuzzy(minDiff-maxDiff,minPixelCount-maxPixelCount)``
 | |
|           This allows a test to pass if the pixel value differences are between
 | |
|           ``minDiff`` and ``maxDiff``, inclusive, and the total number of
 | |
|           different pixels is between ``minPixelCount`` and ``maxPixelCount``,
 | |
|           inclusive. It can also be used with ``!=`` to ensure that the
 | |
|           difference is outside the specified interval. Note that with ``!=``
 | |
|           tests the minimum bounds of the ranges must be zero.
 | |
| 
 | |
|           Fuzzy tends to be used for two different sorts of cases.  The main
 | |
|           case is tests that are expected to be equal, but actually fail in a
 | |
|           minor way (e.g., an antialiasing difference), and we want to ensure
 | |
|           that the test doesn't regress further so we don't want to mark the
 | |
|           test as failing.  For these cases, test annotations should be the
 | |
|           tightest bounds possible:  if the behavior is entirely deterministic
 | |
|           this means a range like ``fuzzy(1-1,8-8)``, and if at all possible,
 | |
|           the ranges should not include 0.  In cases where the test only
 | |
|           sometimes fails, this unfortunately requires using 0 in both ranges,
 | |
|           which means that we won't get reports of an unexpected pass if the
 | |
|           problem is fixed (allowing us to remove the ``fuzzy()`` annotation
 | |
|           and expect the test to pass from then on).
 | |
| 
 | |
|           The second case where fuzzy is used is tests that are supposed
 | |
|           to allow some amount of variability (i.e., tests where the
 | |
|           specification allows variability such that we can't assert
 | |
|           that all pixels are the same).  Such tests should generally be
 | |
|           avoided (for example, by covering up the pixels that can vary
 | |
|           with another element), but when they are needed, the ranges in
 | |
|           the ``fuzzy()`` annotation should generally include 0.
 | |
| 
 | |
|       ``fuzzy-if(condition,minDiff-maxDiff,minPixelCount-maxPixelCount)``
 | |
|           If the condition is met, the test is treated as if ``fuzzy`` had been
 | |
|           specified. This is useful if there are differences on particular
 | |
|           platforms. See ``fuzzy()`` above.
 | |
| 
 | |
|       ``require-or(cond1&&cond2&&...,fallback)``
 | |
|           Require some particular setup be performed or environmental
 | |
|           condition(s) made true (eg setting debug mode) before the test
 | |
|           is run. If any condition is unknown, unimplemented, or fails,
 | |
|           revert to the fallback failure-type.
 | |
|           Example: ``require-or(debugMode,skip)``
 | |
| 
 | |
|       ``asserts(count)``
 | |
|           Loading the test and reference is known to assert exactly
 | |
|           ``count`` times.
 | |
|           NOTE: An asserts() notation with a non-zero count or maxCount
 | |
|           suppresses use of a cached canvas for the test with the
 | |
|           annotation.  However, if later occurrences of the same test
 | |
|           are not annotated, they will use the cached canvas
 | |
|           (potentially from the load that asserted).  This allows
 | |
|           repeated use of the same test or reference to be annotated
 | |
|           correctly (which may be particularly useful when the uses are
 | |
|           in different subdirectories that can be tested independently),
 | |
|           but does not force them to be, nor does it force suppression
 | |
|           of caching for a common reference when it is the test that
 | |
|           asserts.
 | |
| 
 | |
|       ``asserts-if(condition,count)``
 | |
|           Same as above, but only if condition is true.
 | |
| 
 | |
|       ``asserts(minCount-maxCount)``
 | |
|           Loading the test and reference is known to assert between
 | |
|           minCount and maxCount times, inclusive.
 | |
|           NOTE: See above regarding canvas caching.
 | |
| 
 | |
|       ``asserts-if(condition,minCount-maxCount)``
 | |
|           Same as above, but only if condition is true.
 | |
| 
 | |
|       ``noautofuzz``
 | |
|           Disables the autofuzzing behaviour hard-coded in the reftest harness
 | |
|           for specific platform configurations. The autofuzzing is intended to
 | |
|           compensate for inherent nondeterminism that results in intermittently
 | |
|           fuzzy results (with small amounts of fuzz) across many/all tests on
 | |
|           a given platform. Specifying 'noautofuzz' on the test will disable
 | |
|           the autofuzzing for that test and require an exact match.
 | |
| 
 | |
|       Conditions are JavaScript expressions *without spaces* in them.
 | |
|       They are evaluated in a sandbox in which a limited set of
 | |
|       variables are defined.  See the BuildConditionSandbox function in
 | |
|       ``layout/tools/reftest.js`` for details.
 | |
| 
 | |
|       Examples of using conditions: ::
 | |
| 
 | |
| 
 | |
|           fails-if(winWidget) == test reference
 | |
|           asserts-if(cocoaWidget,2) load crashtest
 | |
| 
 | |
| 
 | |
|    b. ``<preference>`` (optional) is a string of the form
 | |
| 
 | |
|           ``pref(<name>,<value>)``
 | |
| 
 | |
|           ``test-pref(<name>,<value>)``
 | |
| 
 | |
|           ``ref-pref(<name>,<value>)``
 | |
| 
 | |
|       where ``<name>`` is the name of a preference setting, as seen in
 | |
|       about:config, and ``<value>`` is the value to which this preference
 | |
|       should be set. ``<value>`` may be a boolean (true/false), an integer,
 | |
|       or a quoted string *without spaces*, according to the type of the
 | |
|       preference.
 | |
| 
 | |
|       The preference will be set to the specified value prior to
 | |
|       rendering the test and/or reference canvases (pref() applies to
 | |
|       both, test-pref() only to the test, and ref-pref() only to the
 | |
|       reference), and will be restored afterwards so that following
 | |
|       tests are not affected. Note that this feature is only useful for
 | |
|       "live" preferences that take effect immediately, without requiring
 | |
|       a browser restart.
 | |
| 
 | |
|    c. ``<http>``, if present, is one of the strings (sans quotes) "HTTP" or
 | |
|       "HTTP(..)" or "HTTP(../..)" or "HTTP(../../..)", etc. , indicating that
 | |
|       the test should be run over an HTTP server because it requires certain
 | |
|       HTTP headers or a particular HTTP status.  (Don't use this if your test
 | |
|       doesn't require this functionality, because it unnecessarily slows down
 | |
|       the test.)
 | |
| 
 | |
|       With "HTTP", HTTP tests have the restriction that any resource an HTTP
 | |
|       test accesses must be accessed using a relative URL, and the test and
 | |
|       the resource must be within the directory containing the reftest
 | |
|       manifest that describes the test (or within a descendant directory).
 | |
|       The variants "HTTP(..)", etc., can be used to relax this restriction by
 | |
|       allowing resources in the parent directory, etc.
 | |
| 
 | |
|       To modify the HTTP status or headers of a resource named FOO, create a
 | |
|       sibling file named FOO^headers^ with the following contents:
 | |
| 
 | |
|       ``[<http-status>]``
 | |
| 
 | |
|       ``<http-header>*``
 | |
| 
 | |
|       ``<http-status>``
 | |
|           A line of the form "HTTP ###[ <description>]", where ### indicates
 | |
|           the desired HTTP status and <description> indicates a desired HTTP
 | |
|           status description, if any. If this line is omitted, the default is
 | |
|           "HTTP 200 OK".
 | |
| 
 | |
|       ``<http-header>``
 | |
|           A line in standard HTTP header line format, i.e.
 | |
|           "Field-Name: field-value". You may not repeat the use of a Field-Name
 | |
|           and must coalesce such headers together, and each header must be
 | |
|           specified on a single line, but otherwise the format exactly matches
 | |
|           that from HTTP itself.
 | |
| 
 | |
|       HTTP tests may also incorporate SJS files.  SJS files provide similar
 | |
|       functionality to CGI scripts, in that the response they produce can be
 | |
|       dependent on properties of the incoming request.  Currently these
 | |
|       properties are restricted to method type and headers, but eventually
 | |
|       it should be possible to examine data in the body of the request as
 | |
|       well when computing the generated response.  An SJS file is a JavaScript
 | |
|       file with a .sjs extension which defines a global `handleRequest`
 | |
|       function (called every time that file is loaded during reftests) in this
 | |
|       format: ::
 | |
| 
 | |
|           function handleRequest(request, response)
 | |
|           {
 | |
|             response.setStatusLine(request.httpVersion, 200, "OK");
 | |
| 
 | |
|             // You *probably* want this, or else you'll get bitten if you run
 | |
|             // reftest multiple times with the same profile.
 | |
|             response.setHeader("Cache-Control", "no-cache");
 | |
| 
 | |
|             response.write("any ASCII data you want");
 | |
| 
 | |
|             var outputStream = response.bodyOutputStream;
 | |
|             // ...anything else you want to do, synchronously...
 | |
|           }
 | |
| 
 | |
|       For more details on exactly which functions and properties are available
 | |
|       on request/response in handleRequest, see the nsIHttpRe(quest|sponse)
 | |
|       definitions in ``netwerk/test/httpserver/nsIHttpServer.idl``.
 | |
| 
 | |
|       HTTP tests can also make use of example.org URIs in order to test cross
 | |
|       site behaviour. "example.org/filename" will access filename in the same
 | |
|       directly as the current reftest. (Not currently implemented for android.)
 | |
| 
 | |
|    d. ``<type>`` is one of the following:
 | |
| 
 | |
|       ``==``
 | |
|           The test passes if the images of the two renderings are the SAME.
 | |
| 
 | |
|       ``!=``
 | |
|           The test passes if the images of the two renderings are DIFFERENT.
 | |
| 
 | |
|       ``load``
 | |
|           The test passes unconditionally if the page loads. url_ref must be
 | |
|           omitted, and the test cannot be marked as fails or random. (Used to
 | |
|           test for crashes, hangs, assertions, and leaks.)
 | |
| 
 | |
|       ``script``
 | |
|           The loaded page records the test's pass or failure status in a
 | |
|           JavaScript data structure accessible through the following API.
 | |
| 
 | |
|           ``getTestCases()`` returns an array of test result objects
 | |
|           representing the results of the tests performed by the page.
 | |
| 
 | |
|           Each test result object has two methods:
 | |
| 
 | |
|           ``testPassed()`` returns true if the test result object passed,
 | |
|           otherwise it returns false.
 | |
| 
 | |
|           ``testDescription()`` returns a string describing the test
 | |
|           result.
 | |
| 
 | |
|           ``url_ref`` must be omitted. The test may be marked as fails or
 | |
|           random. (Used to test the JavaScript Engine.)
 | |
| 
 | |
|       ``print``
 | |
|           The test passes if the printouts (as PDF) of the two renderings
 | |
|           are the SAME by applying the following comparisons:
 | |
| 
 | |
|             - The number of pages generated for both printouts must match.
 | |
|             - The text content of both printouts must match (rasterized text
 | |
|               does not match real text).
 | |
| 
 | |
|           You can specify a print range by setting the reftest-print-range
 | |
|           attribute on the document element. Example: ::
 | |
| 
 | |
|               <html reftest-print-range="2-3">
 | |
|               ...
 | |
| 
 | |
| 
 | |
|           The following example would lead to a single page print: ::
 | |
| 
 | |
|               <html reftest-print-range="2-2">
 | |
|               ...
 | |
| 
 | |
|           You can also print selected elements only: ::
 | |
| 
 | |
|               <html reftest-print-range="selection">
 | |
|               ...
 | |
| 
 | |
|           Make sure to include code in your test that actually selects something.
 | |
| 
 | |
|           Future additions to the set of comparisons might include:
 | |
| 
 | |
|             - Matching the paper size
 | |
|             - Validating printed headers and footers
 | |
|             - Testing (fuzzy) position of elements
 | |
|             - Testing specific print related CSS properties
 | |
| 
 | |
|           The main difference between ``print`` and ``==/!=`` reftests is that
 | |
|           ``print`` makes us compare the structure of print results (by parsing
 | |
|           the output PDF) rather than taking screenshots and comparing pixel
 | |
|           values. This allows us to test for common printing related issues
 | |
|           like text being rasterized when it shouldn't. This difference in
 | |
|           behavior is also why this is its own reftest operator, rather than
 | |
|           a flavor of ``==/!=``. It would be somewhat misleading to list these
 | |
|           print reftests as ``==/!=``, because they don't actually check for
 | |
|           pixel matching.
 | |
| 
 | |
|           See the chapter about Pagination Tests if you are looking for testing
 | |
|           layout in pagination mode.
 | |
| 
 | |
|    e. ``<url>`` is either a relative file path or an absolute URL for the
 | |
|       test page
 | |
| 
 | |
|    f. ``<url_ref>`` is either a relative file path or an absolute URL for
 | |
|       the reference page
 | |
| 
 | |
|    The only difference between ``<url>`` and ``<url_ref>`` is that results of
 | |
|    the test are reported using ``<url>`` only.
 | |
| 
 | |
| Specification of a url prefix
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
|    ``url-prefix <string>``
 | |
| 
 | |
|    ``<string>`` will be prepended to relative ``<url>`` and ``<url_ref>`` for
 | |
|    all following test items in the manifest.
 | |
| 
 | |
|    ``<string>`` will not be prepended to the relative path when including
 | |
|    another manifest, e.g. ``include <relative_path>.``
 | |
| 
 | |
|    ``<string>`` will not be prepended to any ``<url>`` or ``<url_ref>`` matching
 | |
|    the pattern ``/^\w+:/``. This will prevent the prefix from being applied to
 | |
|    any absolute url containing a protocol such as ``data:``, ``about:``, or
 | |
|    ``http:``.
 | |
| 
 | |
|    While the typical use of url-prefix is expected to be as the first line of
 | |
|    a manifest, it is legal to use it anywhere in a manifest. Subsequent uses
 | |
|    of url-prefix overwrite any existing values.
 | |
| 
 | |
| Specification of defaults
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
|    ``defaults [<failure-type> | <preference> | <http>]``
 | |
| 
 | |
|    where ``<failure-type>``, ``<preference>``, and ``<http>`` are defined above.
 | |
| 
 | |
|    The default settings will be used for all following test items in the manifest.
 | |
|    Any test specific settings will override the defaults, just as later items
 | |
|    within a line override earlier ones.
 | |
| 
 | |
|    A defaults line with no settings will reset the defaults to be empty.
 | |
| 
 | |
|    As with url-prefix, defaults will often be used at the start of a manifest file
 | |
|    so that it applies to all test items, but it is legal for defaults to appear
 | |
|    anywhere in the manifest. A subsequent defaults will reset any previous default
 | |
|    settings and overwrite them with the new settings.
 | |
| 
 | |
|    It is invalid to set non-skip defaults before an include line, just as it is
 | |
|    invalid to specify non-skip settings directly on the include line itself. If a
 | |
|    manifest needs to use both defaults and include, the include should appear
 | |
|    before the defaults. If it's important to specify the include later on in the
 | |
|    manifest, a blank defaults line directly preceding the include can be used to
 | |
|    reset the defaults.
 | |
| 
 | |
| This test manifest format could be used by other harnesses, such as ones
 | |
| that do not depend on XUL, or even ones testing other layout engines.
 | |
| 
 | |
| Running Tests
 | |
| -------------
 | |
| 
 | |
| To run a given reftest use something like the following ::
 | |
| 
 | |
| ./mach reftest <path to individual test or directory>
 | |
| 
 | |
| As an example, if we wanted to run the reftests relevant to async scrolling,
 | |
| run something like the following::
 | |
| 
 | |
| ./mach reftest ./layout/reftest/async-scrolling &> reftest.out
 | |
| 
 | |
| and then search/grep reftest.out for "UNEXPECTED".
 | |
| 
 | |
| There are two scripts provided to convert the reftest.out to HTML.
 | |
| clean-reftest-output.pl converts reftest.out into simple HTML, stripping
 | |
| lines from the log that aren't relevant.  reftest-to-html.pl converts
 | |
| the output into html that makes it easier to visually check for
 | |
| failures. See :ref:`debugging failures <debugging-failures>` for
 | |
| more details on making sense of reftest results.
 | |
| 
 | |
| Testable Areas
 | |
| --------------
 | |
| 
 | |
| This framework is capable of testing many areas of the layout engine.
 | |
| It is particularly well-suited to testing dynamic change handling (by
 | |
| comparison to the static end-result as a reference) and incremental
 | |
| layout (comparison of a script-interrupted layout to one that was not).
 | |
| However, it is also possible to write tests for many other things that
 | |
| can be described in terms of equivalence, for example:
 | |
| 
 | |
|  * CSS cascading could be tested by comparing the result of a
 | |
|    complicated set of style rules that makes a word green to <span
 | |
|    style="color:green">word</span>.
 | |
| 
 | |
|  * <canvas> compositing operators could be tested by comparing the
 | |
|    result of drawing using canvas to a block-level element with the
 | |
|    desired color as a CSS background-color.
 | |
| 
 | |
|  * CSS counters could be tested by comparing the text output by counters
 | |
|    with a page containing the text written out
 | |
| 
 | |
|  * complex margin collapsing could be tested by comparing the complex
 | |
|    case to a case where the margin is written out, or where the margin
 | |
|    space is created by an element with 'height' and transparent
 | |
|    background
 | |
| 
 | |
| When it is not possible to test by equivalence, it may be possible to
 | |
| test by non-equivalence.  For example, testing justification in cases
 | |
| with more than two words, or more than three different words, is
 | |
| difficult.  However, it is simple to test that justified text is at
 | |
| least displayed differently from left-, center-, or right-aligned text.
 | |
| 
 | |
| Writing Tests
 | |
| -------------
 | |
| 
 | |
| When writing tests for this framework, it is important for the test to
 | |
| depend only on behaviors that are known to be correct and permanent.
 | |
| For example, tests should not depend on default font sizes, default
 | |
| margins of the body element, the default style sheet used for HTML, the
 | |
| default appearance of form controls, or anything else that can be
 | |
| avoided.
 | |
| 
 | |
| In general, the best way to achieve this is to make the test and the
 | |
| reference identical in as many aspects as possible.  For example:
 | |
| 
 | |
| Good test markup: ::
 | |
| 
 | |
|     <div style="color:green"><table><tr><td><span>green
 | |
|     </span></td></tr></table></div>
 | |
| 
 | |
| Good reference markup: ::
 | |
| 
 | |
|     <div><table><tr><td><span style="color:green">green
 | |
|     </span></td></tr></table></div>
 | |
| 
 | |
| BAD reference markup: ::
 | |
| 
 | |
|     <!-- 3px matches the default cellspacing and cellpadding -->
 | |
|     <div style="color:green; padding: 3px">green
 | |
|     </div>
 | |
| 
 | |
| BAD test markup: ::
 | |
| 
 | |
|     <!-- span doesn't change the positioning, so skip it -->
 | |
|     <div style="color:green"><table><tr><td>green
 | |
|     </td></tr></table></div>
 | |
| 
 | |
| Asynchronous Tests: class="reftest-wait"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Normally reftest takes a snapshot of the given markup's rendering right
 | |
| after the load event fires for content. If your test needs to postpone
 | |
| the moment the snapshot is taken, it should make sure a class
 | |
| 'reftest-wait' is on the root element by the moment the load event
 | |
| fires. The easiest way to do this is to put it in the markup, e.g.: ::
 | |
| 
 | |
|     <html class="reftest-wait">
 | |
| 
 | |
| When your test is ready, you should remove this class from the root
 | |
| element, for example using this code: ::
 | |
| 
 | |
|     document.documentElement.className = "";
 | |
| 
 | |
| 
 | |
| Note that in layout tests it is often enough to trigger layout using ::
 | |
| 
 | |
|     document.body.offsetWidth  // HTML example
 | |
| 
 | |
| When possible, you should use this technique instead of making your
 | |
| test async.
 | |
| 
 | |
| Invalidation Tests: MozReftestInvalidate Event
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| When a test (or reference) uses reftest-wait, reftest tracks invalidation
 | |
| via MozAfterPaint and updates the test image in the same way that
 | |
| a regular window would be repainted. Therefore it is possible to test
 | |
| invalidation-related bugs by setting up initial content and then
 | |
| dynamically modifying it before removing reftest-wait. However, it is
 | |
| important to get the timing of these dynamic modifications right so that
 | |
| the test doesn't accidentally pass because a full repaint of the window
 | |
| was already pending. To help with this, reftest fires one MozReftestInvalidate
 | |
| event at the document root element for a reftest-wait test when it is safe to
 | |
| make changes that should test invalidation. The event bubbles up to the
 | |
| document and window so you can set listeners there too. For example, ::
 | |
| 
 | |
|   function doTest() {
 | |
|     document.body.style.border = "";
 | |
|     document.documentElement.removeAttribute('class');
 | |
|   }
 | |
|   document.addEventListener("MozReftestInvalidate", doTest, false);
 | |
| 
 | |
| Painting Tests: class="reftest-no-paint"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If an element shouldn't be painted, set the class "reftest-no-paint" on it
 | |
| when doing an invalidation test. Causing a repaint in your
 | |
| MozReftestInvalidate handler (for example, by changing the body's background
 | |
| colour) will accurately test whether the element is painted.
 | |
| 
 | |
| Display List Tests: class="reftest-[no-]display-list"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These classes work similarly to reftest-no-paint, but check if the element has
 | |
| display items created or not. These classes are useful for checking the behaviour
 | |
| of retained display lists, where the display list is incrementally updated by
 | |
| changes, rather than thrown out and rebuilt from scratch.
 | |
| 
 | |
| Opaque Layer Tests: class="reftest-opaque-layer"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If an element should be assigned to a PaintedLayer that's opaque, set the class
 | |
| "reftest-opaque-layer" on it. This checks whether the layer is opaque during
 | |
| the last paint of the test, and it works whether your test is an invalidation
 | |
| test or not. In order to pass the test, the element has to have a primary
 | |
| frame, and that frame's display items must all be assigned to a single painted
 | |
| layer and no other layers, so it can't be used on elements that create stacking
 | |
| contexts (active or inactive).
 | |
| 
 | |
| Layerization Tests: reftest-assigned-layer="layer-name"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If two elements should be assigned to the same PaintedLayer, choose any string
 | |
| value as the layer name and set the attribute reftest-assigned-layer="yourname"
 | |
| on both elements. Reftest will check whether all elements with the same
 | |
| reftest-assigned-layer value share the same layer. It will also test whether
 | |
| elements with different reftest-assigned-layer values are assigned to different
 | |
| layers.
 | |
| The same restrictions as with class="reftest-opaque-layer" apply: All elements
 | |
| must have a primary frame, and that frame's display items must all be assigned
 | |
| to the same PaintedLayer and no other layers. If these requirements are not
 | |
| met, the test will fail.
 | |
| 
 | |
| Snapshot The Whole Window: class="reftest-snapshot-all"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| In a reftest-wait test, to disable testing of invalidation and force the final
 | |
| snapshot to be taken of the whole window, set the "reftest-snapshot-all"
 | |
| class on the root element.
 | |
| 
 | |
| Avoid triggering flushes: class="reftest-no-flush"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| The reftest harness normally triggers flushes by calling
 | |
| getBoundingClientRect on the root element.  If the root element of the
 | |
| test has class="reftest-no-flush", it doesn't do this.
 | |
| 
 | |
| This is useful for testing animations on the compositor thread, since
 | |
| the flushing will cause a main thread style update.
 | |
| 
 | |
| Zoom Tests: reftest-zoom="<float>"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| When the root element of a test has a "reftest-zoom" attribute, that zoom
 | |
| factor is applied when rendering the test. The corresponds to the desktop "full
 | |
| zoom" style zoom. The reftest document will be 800 device pixels wide by 1000
 | |
| device pixels high. The reftest harness assumes that the CSS pixel dimensions
 | |
| are 800/zoom and 1000/zoom. For best results therefore, choose zoom factors
 | |
| that do not require rounding when we calculate the number of appunits per
 | |
| device pixel; i.e. the zoom factor should divide 60, so 60/zoom is an integer.
 | |
| 
 | |
| Setting Scrollport Size: reftest-scrollport-w/h="<int>"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If either of the "reftest-scrollport-w" and "reftest-scrollport-h" attributes on
 | |
| the root element are non-zero, sets the scroll-position-clamping scroll-port
 | |
| size to the given size in CSS pixels. This does not affect the size of the
 | |
| snapshot that is taken.
 | |
| 
 | |
| Setting Resolution: reftest-resolution="<float>"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If the root element of a test has a "reftest-resolution" attribute, the page
 | |
| is rendered with the specified resolution (as if the user pinch-zoomed in
 | |
| to that scale). Note that the difference between reftest-async-zoom and
 | |
| reftest-resolution is that reftest-async-zoom only applies the scale in
 | |
| the compositor, while reftest-resolution causes the page to be paint at that
 | |
| resolution. This attribute can be used together with initial-scale in meta
 | |
| viewport tag, in such cases initial-scale is applied first then
 | |
| reftest-resolution changes the scale.
 | |
| 
 | |
| This attributes requires the pref apz.allow_zooming=true to have an effect.
 | |
| 
 | |
| Setting Async Scroll Mode: reftest-async-scroll attribute
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If the "reftest-async-scroll" attribute is set on the root element, we try to
 | |
| enable async scrolling and zooming for the document. This is unsupported in many
 | |
| configurations.
 | |
| 
 | |
| Setting Displayport Dimensions: reftest-displayport-x/y/w/h="<int>"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If any of the "reftest-displayport-x", "reftest-displayport-y",
 | |
| "reftest-displayport-w" and "reftest-displayport-h" attributes on the root
 | |
| element are nonzero, sets the displayport dimensions to the given bounds in
 | |
| CSS pixels. This does not affect the size of the snapshot that is taken.
 | |
| 
 | |
| When the "reftest-async-scroll" attribute is set on the root element, *all*
 | |
| elements in the document are checked for "reftest-displayport-x/y/w/h" and have
 | |
| displayports set on them when those attributes are present.
 | |
| 
 | |
| Testing Async Scrolling: reftest-async-scroll-x/y="<int>"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| When the "reftest-async-scroll" attribute is set on the root element, for any
 | |
| element where either the "reftest-async-scroll-x" or "reftest-async-scroll-y
 | |
| attributes are nonzero, at the end of the test take the snapshot with the given
 | |
| offset (in CSS pixels) added to the async scroll offset.
 | |
| 
 | |
| Testing Async Zooming: reftest-async-zoom="<float>"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| When the "reftest-async-zoom" attribute is present on the root element then at
 | |
| the end of the test take the snapshot with the given async zoom on top of any
 | |
| existing zoom. Content is not re-rendered at the new zoom level. This
 | |
| corresponds to the mobile style "pinch zoom" style of zoom. This is unsupported
 | |
| in many configurations, and any tests using this will probably want to have
 | |
| pref(apz.allow_zooming,true) on them.
 | |
| 
 | |
| Pagination Tests: class="reftest-paged"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Now that the patch for bug 374050 has landed
 | |
| (https://bugzilla.mozilla.org/show_bug.cgi?id=374050), it is possible to
 | |
| create reftests that run in a paginated context.
 | |
| 
 | |
| The page size used is 5in wide and 3in tall (with the default half-inch
 | |
| margins).  This is to allow tests to have less text and to make the
 | |
| entire test fit on the screen.
 | |
| 
 | |
| There is a layout/reftests/printing directory for pagination reftests; however,
 | |
| there is nothing special about this directory.  You can put pagination reftests
 | |
| anywhere that is appropriate.
 | |
| 
 | |
| The suggested first lines for any pagination test is: ::
 | |
| 
 | |
| <!DOCTYPE html><html class="reftest-paged">
 | |
| <style>html{font-size:12pt}</style>
 | |
| 
 | |
| The reftest-paged class on the root element triggers the reftest to
 | |
| switch into page mode. Fixing the font size is suggested, although not
 | |
| required, because the pages are a fixed size in inches. The switch to page mode
 | |
| happens on load if the reftest-wait class is not present; otherwise it happens
 | |
| immediately after firing the MozReftestInvalidate event.
 | |
| 
 | |
| The underlying layout support for this mode isn't really complete; it
 | |
| doesn't use exactly the same codepath as real print preview/print. In
 | |
| particular, scripting and frames are likely to cause problems; it is untested,
 | |
| though.  That said, it should be sufficient for testing layout issues related
 | |
| to pagination.
 | |
| 
 | |
| Process Crash Tests: class="reftest-expect-process-crash"
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| If you are running a test that causes a process
 | |
| under Electrolysis to crash as part of a reftest, this will cause process
 | |
| crash minidump files to be left in the profile directory.  The test
 | |
| infrastructure that runs the reftests will notice these minidump files and
 | |
| dump out information from them, and these additional error messages in the logs
 | |
| can end up erroneously being associated with other errors from the reftest run.
 | |
| They are also confusing, since the appearance of "PROCESS-CRASH" messages in
 | |
| the test run output can seem like a real problem, when in fact it is the
 | |
| expected behavior.
 | |
| 
 | |
| To indicate to the reftest framework that a test is expecting a
 | |
| process to crash, have the test include "reftest-expect-process-crash" as
 | |
| one of the root element's classes by the time the test has finished.  This will
 | |
| cause any minidump files that are generated while running the test to be removed
 | |
| and they won't cause any error messages in the test run output.
 | |
| 
 | |
| Skip Forcing A Content Process Layer-Tree Update: reftest-no-sync-layers attribute
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Normally when an multi-process reftest test ends, we force the content process
 | |
| to push a layer-tree update to the compositor before taking the snapshot.
 | |
| Setting the "reftest-no-sync-layers" attribute on the root element skips this
 | |
| step, enabling testing that layer-tree updates are being correctly generated.
 | |
| However the test must manually wait for a MozAfterPaint event before ending.
 | |
| 
 | |
| Debugging Failures
 | |
| ------------------
 | |
| 
 | |
| The Reftest Analyzer has been created to make debugging reftests a bit easier.
 | |
| If a reftest is failing, upload the log to the Reftest Analyzer to view the
 | |
| differences between the expected result and the actual outcome of the reftest.
 | |
| The Reftest Analyzer can be found at the following url:
 | |
| 
 | |
| https://hg.mozilla.org/mozilla-central/raw-file/tip/layout/tools/reftest/reftest-analyzer.xhtml
 |