tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

index.rst (10051B)


      1 GTest
      2 =====
      3 
      4 GTest (googletest) is Google's framework for writing C++ tests on a
      5 variety of platforms (Linux, Mac OS X, Windows, ...).
      6 Based on the xUnit architecture, it supports automatic test
      7 discovery, a rich set of assertions, user-defined assertions, death
      8 tests, fatal and non-fatal failures, value- and type-parameterized
      9 tests, various options for running the tests, and XML test report
     10 generation.
     11 
     12 Integration
     13 -----------
     14 
     15 GTest is run as a standard test task on Win/Mac/Linux and Android, under
     16 treeherder symbol 'GTest'.
     17 
     18 
     19 Running tests
     20 -------------
     21 
     22 The Firefox build process will build GTest on supported platforms as
     23 long as you don't disable tests in your mozconfig. However xul-gtest will
     24 only be built when tests are required to save an expensive second
     25 linking process.
     26 
     27 To run the unit tests use 'mach gtest' when invoking Gecko.
     28 
     29 Running selected tests
     30 ~~~~~~~~~~~~~~~~~~~~~~
     31 
     32 Tests can be selected using mach. You can also use environment variables
     33 support by GTest. See `Running Test Programs: Running a Subset of the
     34 Tests <https://github.com/google/googletest/blob/master/docs/advanced.md#running-a-subset-of-the-tests>`__
     35 for more details.
     36 
     37 ::
     38 
     39   mach gtest Moz2D.*
     40 
     41 
     42 Configuring GTest
     43 ~~~~~~~~~~~~~~~~~
     44 
     45 GTest can be controlled from other environment variables. See `Running
     46 Test Programs: Advanced
     47 Options <https://github.com/google/googletest/blob/master/docs/advanced.md#running-test-programs-advanced-options>`__
     48 for more details.
     49 
     50 
     51 Debugging a GTest Unit Test
     52 ---------------------------
     53 
     54 To debug a gtest, pass --debug to the normal command.
     55 
     56 .. code-block:: shell
     57 
     58   ./mach gtest --debug [ Prefix.Test ]
     59 
     60 If that doesn't work, you can try running the firefox binary under the
     61 debugger with the MOZ_RUN_GTEST environment variable set to 1.
     62 
     63 .. code-block:: shell
     64 
     65   MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb]
     66 
     67 .. warning::
     68 
     69   Don't forget to build + run 'mach gtest' to relink when using
     70   MOZ_RUN_GTEST since it's not part of a top level build.
     71 
     72 Note that this will load an alternate libxul - the one which has the
     73 test code built in, which resides in a gtest/subdirectory of your
     74 objdir. This gtest-enabled libxul is not built as part of the regular
     75 build, so you must ensure that it is built before running the above
     76 command. A simple way to do this is to just run "mach gtest" which will
     77 rebuild libxul and run the tests. You can also extract the commands
     78 needed to just rebuild that libxul `from
     79 mach <https://hg.mozilla.org/mozilla-central/file/3673d2c688b4/python/mozbuild/mozbuild/mach_commands.py#l486>`__
     80 and run those directly. Finally, note that you may have to run through
     81 the tests once for gdb to load all the relevant libraries and for
     82 breakpoint symbols to resolve properly.
     83 
     84 Note that you can debug a subset of the tests (including a single test)
     85 by using the GTEST_FILTER environment variable:
     86 
     87 .. code-block:: shell
     88 
     89   GTEST_FILTER='AsyncPanZoom*' MOZ_RUN_GTEST=1 ./mach run --debug [--debugger gdb]
     90 
     91 
     92 Debugging with Xcode
     93 ~~~~~~~~~~~~~~~~~~~~
     94 
     95 See :ref:`Debugging On macOS` for initial
     96 setup. You'll likely want to create a separate scheme for running GTest
     97 ("Product" > "Scheme" > "New Scheme…"). In addition to GTEST_FILTER, Set
     98 the following environment variables:
     99 
    100 ::
    101 
    102   MOZ_XRE_DIR=/path-to-object-directory/obj-ff-dbg/dist/bin
    103   MOZ_RUN_GTEST=True
    104 
    105 and under the "Options" tab for the scheme, set the working directory
    106 to:
    107 
    108 ::
    109 
    110   ☑️ Use custom working directory: /path-to-object-directory/obj-ff-dbg/_tests/gtest
    111 
    112 
    113 Debugging with Visual Studio Code
    114 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    115 
    116 Add a configuration like this to your launch.json file (you can edit it
    117 via Run / Open Configurations):
    118 
    119 ::
    120 
    121           {
    122               "name": "(gdb) Launch gtest",
    123               "type": "cppdbg",
    124               "request": "launch",
    125               "program": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/dist/bin/firefox",
    126               "args": [],
    127               "stopAtEntry": false,
    128               "cwd": "${workspaceFolder}/obj-x86_64-pc-linux-gnu/_tests/gtest",
    129               "environment": [{"name": "MOZ_RUN_GTEST", "value": "True"},
    130                               {"name": "GTEST_FILTER", "value": "AsyncPanZoom*"}],
    131               "externalConsole": false,
    132               "MIMode": "gdb",
    133               "setupCommands": [
    134                   {
    135                       "description": "Enable pretty-printing for gdb",
    136                       "text": "-enable-pretty-printing",
    137                       "ignoreFailures": true
    138                   }
    139               ]
    140           },
    141 
    142 
    143 Writing a GTest Unit Test
    144 -------------------------
    145 
    146 Most of the `GTest
    147 documentation <https://github.com/google/googletest/blob/master/googletest/README.md>`__
    148 will apply here. The `GTest
    149 primer <https://github.com/google/googletest/blob/master/docs/primer.md>`__
    150 is a recommended read.
    151 
    152 .. warning::
    153 
    154   GTest will run tests in parallel. Don't add unit tests that are not
    155   threadsafe, such as tests that require focus or use specific sockets.
    156 
    157 .. warning::
    158 
    159   GTest will run without initializing mozilla services. Initialize and
    160   tear down any dependencies you have in your test fixtures. Avoid
    161   writing integration tests and focus on testing individual units.
    162 
    163 See https://hg.mozilla.org/mozilla-central/rev/ed612eec41a44867a for an
    164 example of how to add a simple test.
    165 
    166 If you're converting an existing C++ unit test to a GTest, `this
    167 commit <https://hg.mozilla.org/mozilla-central/rev/40740cddc131>`__ may
    168 serve as a useful reference.
    169 
    170 
    171 Setting prefs for a test
    172 ~~~~~~~~~~~~~~~~~~~~~~~~
    173 
    174 If tests cover functionality that is disabled by default, you'll have to
    175 change the relevant preferences either in the individual test:
    176 
    177 ::
    178 
    179   bool oldPref = Preferences::GetBool(prefKey);
    180   Preferences::SetBool(prefKey, true);
    181   … // test code
    182   Preferences::SetBool(prefKey, oldPref);
    183 
    184 or, if it applies more broadly, the change can be applied to the whole
    185 fixture (see `the GTest
    186 docs <https://github.com/google/googletest/blob/master/googletest/README.md>`__,
    187 or
    188 `AutoInitializeImageLib <https://searchfox.org/mozilla-central/search?q=AutoInitializeImageLib%3A%3AAutoInitializeImageLib&path=>`__
    189 as an example).
    190 
    191 
    192 Adding a test to the build system
    193 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    194 
    195 Find a gtest directory appropriate for the module. If none exist create
    196 a directory using the following convention: '<submodule>/tests/gtest'.
    197 Create a moz.build file (in the newly created directory) with a module
    198 declaration, replacing gfxtest with a unique name, and set
    199 UNIFIED_SOURCES to contain all of the test file names.
    200 
    201 What we're doing here is creating a list of source files that will be
    202 compiled and linked only against the gtest version of libxul. This will
    203 let these source files call internal xul symbols without making them
    204 part of the binary we ship to users.
    205 
    206 .. code-block::
    207 
    208   # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
    209   # vim: set filetype=python:
    210   # This Source Code Form is subject to the terms of the Mozilla Public
    211   # License, v. 2.0. If a copy of the MPL was not distributed with this
    212   # file, you can obtain one at https://mozilla.org/MPL/2.0/.
    213 
    214   Library('gfxtest')
    215 
    216   UNIFIED_SOURCES = [
    217       <ListTestFiles>,
    218   ]
    219 
    220   FINAL_LIBRARY = 'xul-gtest'
    221 
    222 Update '<submodule>/moz.build' in the parent directory to build your new
    223 subdirectory in:
    224 
    225 .. code-block:: python
    226 
    227   TEST_DIRS += [
    228       "gtest",
    229   ]
    230 
    231 When adding tests to an existing moz.build file (it has FINAL_LIBRARY =
    232 'xul-gtest'), add the following. That's it--there is no test manifest
    233 required. Your tests will be automatically registered using a static
    234 constructor.
    235 
    236 .. code-block:: python
    237 
    238   UNIFIED_SOURCES = [
    239       'TestFoo.cpp',
    240   ]
    241 
    242 Notes
    243 ~~~~~
    244 
    245 The include file for the class you are testing may not need to be
    246 globally exported, but it does need to be made available to the unit
    247 test you are writing. In that case, add something like this to the
    248 Makefile.in inside of the testing directory.
    249 
    250 .. code-block:: python
    251 
    252    LOCAL_INCLUDES += [
    253        '/gfx/2d',
    254        '/gfx/2d/unittest',
    255        '/gfx/layers',
    256    ]
    257 
    258 Gtests currently run from the test package under the **GTest** symbol on
    259 `Treeherder <https://treeherder.mozilla.org/>`__ if you want to verify
    260 that your test is working. Formerly they were run under the **B**
    261 symbol, during \`make check`.
    262 
    263 
    264 MozGTestBench
    265 -------------
    266 
    267 A Mozilla GTest Microbench is just a GTest that reports the test
    268 duration to perfherder. It's an easy way to add low level performance
    269 test. Keep in mind that there's a non-zero cost to monitoring
    270 performance test so use them sparingly. You can still perform test
    271 assertions.
    272 
    273 
    274 Writing a Microbench GTest
    275 ~~~~~~~~~~~~~~~~~~~~~~~~~~
    276 
    277 Use 'MOZ_GTEST_BENCH' instead of 'TEST' to time the execution of your
    278 test. Example:
    279 
    280 .. code-block:: cpp
    281 
    282   #include "gtest/MozGTestBench.h" // For MOZ_GTEST_BENCH
    283 
    284   ...
    285 
    286   MOZ_GTEST_BENCH(GfxBench, TEST_NAME, []{
    287     // Test to time the execution
    288   });
    289 
    290 Make sure this file is registered with the file system using the
    291 instructions above. If everything worked correctly you should see this
    292 in the GTest log for your corresponding test:
    293 
    294 .. code-block:: js
    295 
    296   PERFHERDER_DATA: {"framework": {"name": "platform_microbench"}, "suites": [{"name": "GfxBench", "subtests": [{"name": "CompositorSimpleTree", "value": 252674, "lowerIsBetter": true}]}]}
    297 
    298 
    299 Sheriffing policy
    300 ~~~~~~~~~~~~~~~~~
    301 
    302 Microbench tests measure the speed of a very specific operation. A
    303 regression in a micro-benchmark may not lead to a user visible
    304 regression and should not be treated as strictly as a Talos regression.
    305 Large changes in microbench scores will also be expected when the code
    306 is directly modified and should be accepted if the developer intended to
    307 change that code. Micro-benchmarks however provide a framework for
    308 adding performance tests for platform code and regression tests for
    309 performance fixes. They will catch unintended regressions in code and
    310 when correlated with a Talos regression might indicate the source of the
    311 regression.