import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,153 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/MozBase.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/MozBase.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/MozBase"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/MozBase"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."

View file

@ -0,0 +1,102 @@
import argparse
import sys
import traceback
import types
from mozlog import commandline, get_default_logger
class TestAssertion(Exception):
pass
def assert_equals(a, b):
if a != b:
raise TestAssertion("%r not equal to %r" % (a, b))
def expected(status):
def inner(f):
def test_func():
f()
test_func.__name__ = f.__name__
test_func._expected = status
return test_func
return inner
def test_that_passes():
assert_equals(1, int("1"))
def test_that_fails():
assert_equals(1, int("2"))
def test_that_has_an_error():
assert_equals(2, 1 + "1")
@expected("FAIL")
def test_expected_fail():
assert_equals(2 + 2, 5)
class TestRunner(object):
def __init__(self):
self.logger = get_default_logger(component='TestRunner')
def gather_tests(self):
for item in globals().itervalues():
if isinstance(item, types.FunctionType) and item.__name__.startswith("test_"):
yield item.__name__, item
def run(self):
tests = list(self.gather_tests())
self.logger.suite_start(tests=[name for name, func in tests])
self.logger.info("Running tests")
for name, func in tests:
self.run_test(name, func)
self.logger.suite_end()
def run_test(self, name, func):
self.logger.test_start(name)
status = None
message = None
expected = func._expected if hasattr(func, "_expected") else "PASS"
try:
func()
except TestAssertion as e:
status = "FAIL"
message = e.message
except:
status = "ERROR"
message = traceback.format_exc()
else:
status = "PASS"
self.logger.test_end(name, status=status, expected=expected, message=message)
def get_parser():
parser = argparse.ArgumentParser()
return parser
def main():
parser = get_parser()
commandline.add_logging_group(parser)
args = parser.parse_args()
logger = commandline.setup_logging("structured-example", args, {"raw": sys.stdout})
runner = TestRunner()
try:
runner.run()
except:
logger.critical("Error during test run:\n%s" % traceback.format_exc())
if __name__ == "__main__":
main()

View file

@ -0,0 +1,258 @@
# -*- coding: utf-8 -*-
#
# MozBase documentation build configuration file, created by
# sphinx-quickstart on Mon Oct 22 14:02:17 2012.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
here = os.path.dirname(os.path.abspath(__file__))
parent = os.path.dirname(here)
for item in os.listdir(parent):
path = os.path.join(parent, item)
if (not os.path.isdir(path)) or (not os.path.exists(os.path.join(path, 'setup.py'))):
continue
sys.path.insert(0, path)
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.viewcode']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'MozBase'
copyright = u'2012, Mozilla Automation and Tools team'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1'
# The full version, including alpha/beta/rc tags.
release = '1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'default'
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd:
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
except ImportError:
pass
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = "mozbase documentation"
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'MozBasedoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
# 'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'MozBase.tex', u'MozBase Documentation',
u'Mozilla Automation and Tools team', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'mozbase', u'MozBase Documentation',
[u'Mozilla Automation and Tools team'], 1)
]
# If true, show URL addresses after external links.
# man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'MozBase', u'MozBase Documentation',
u'Mozilla Automation and Tools team', 'MozBase', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
# texinfo_appendices = []
# If false, no module index is generated.
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
# texinfo_show_urls = 'footnote'

View file

@ -0,0 +1,11 @@
Device management
-----------------
Mozbase provides a module called `mozdevice` for the purposes of
running automated tests or scripts on a device (e.g. an Android- or
FirefoxOS-based phone) connected to a workstation.
.. toctree::
:maxdepth: 3
mozdevice

View file

@ -0,0 +1,13 @@
Getting information on the system under test
============================================
It's often necessary to get some information about the system we're
testing, for example to turn on or off some platform specific
behaviour.
.. toctree::
:maxdepth: 2
mozinfo
moznetwork
mozversion

View file

@ -0,0 +1,57 @@
.. MozBase documentation master file, created by
sphinx-quickstart on Mon Oct 22 14:02:17 2012.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
mozbase
=======
Mozbase is a set of easy-to-use Python packages forming a supplemental standard
library for Mozilla. It provides consistency and reduces redundancy in
automation and other system-level software. All of Mozilla's test harnesses use
mozbase to some degree, including Talos_, mochitest_, reftest_, Autophone_, and
Eideticker_.
.. _Talos: https://wiki.mozilla.org/Talos
.. _mochitest: https://developer.mozilla.org/en-US/docs/Mochitest
.. _reftest: https://developer.mozilla.org/en-US/docs/Creating_reftest-based_unit_tests
.. _Autophone: https://wiki.mozilla.org/Auto-tools/Projects/AutoPhone
.. _Eideticker: https://wiki.mozilla.org/Project_Eideticker
In the course of writing automated tests at Mozilla, we found that
the same tasks came up over and over, regardless of the specific nature of
what we were testing. We figured that consolidating this code into a set of
libraries would save us a good deal of time, and so we spent some effort
factoring out the best-of-breed automation code into something we named
"mozbase" (usually written all in lower case except at the beginning of a
sentence).
This is the main documentation for users of mozbase. There is also a
project_ wiki page with notes on development practices and administration.
.. _project: https://wiki.mozilla.org/Auto-tools/Projects/Mozbase
The documentation is organized by category, then by module. Figure out what you
want to do then dive in!
.. toctree::
:maxdepth: 2
manifestparser
gettinginfo
setuprunning
mozhttpd
loggingreporting
devicemanagement
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View file

@ -0,0 +1,11 @@
Logging and reporting
=====================
Ideally output between different types of testing system should be as
uniform as possible, as well as making it easy to make things more or
less verbose. We created some libraries to make doing this easy.
.. toctree::
:maxdepth: 2
mozlog

View file

@ -0,0 +1,190 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MozBase.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MozBase.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
:end

View file

@ -0,0 +1,558 @@
Managing lists of tests
=======================
.. py:currentmodule:: manifestparser
We don't always want to run all tests, all the time. Sometimes a test
may be broken, in other cases we only want to run a test on a specific
platform or build of Mozilla. To handle these cases (and more), we
created a python library to create and use test "manifests", which
codify this information.
:mod:`manifestparser` --- Create and manage test manifests
-----------------------------------------------------------
manifestparser lets you easily create and use test manifests, to
control which tests are run under what circumstances.
What manifestparser gives you:
* manifests are ordered lists of tests
* tests may have an arbitrary number of key, value pairs
* the parser returns an ordered list of test data structures, which
are just dicts with some keys. For example, a test with no
user-specified metadata looks like this:
.. code-block:: text
[{'expected': 'pass',
'path': '/home/mozilla/mozmill/src/manifestparser/manifestparser/tests/testToolbar/testBackForwardButtons.js',
'relpath': 'testToolbar/testBackForwardButtons.js',
'name': 'testBackForwardButtons.js',
'here': '/home/mozilla/mozmill/src/manifestparser/manifestparser/tests',
'manifest': '/home/mozilla/mozmill/src/manifestparser/manifestparser/tests/manifest.ini',}]
The keys displayed here (path, relpath, name, here, and manifest) are
reserved keys for manifestparser and any consuming APIs. You can add
additional key, value metadata to each test.
Why have test manifests?
````````````````````````
It is desirable to have a unified format for test manifests for testing
[mozilla-central](http://hg.mozilla.org/mozilla-central), etc.
* It is desirable to be able to selectively enable or disable tests based on platform or other conditions. This should be easy to do. Currently, since many of the harnesses just crawl directories, there is no effective way of disabling a test except for removal from mozilla-central
* It is desriable to do this in a universal way so that enabling and disabling tests as well as other tasks are easily accessible to a wider audience than just those intimately familiar with the specific test framework.
* It is desirable to have other metadata on top of the test. For instance, let's say a test is marked as skipped. It would be nice to give the reason why.
Most Mozilla test harnesses work by crawling a directory structure.
While this is straight-forward, manifests offer several practical
advantages:
* ability to turn a test off easily: if a test is broken on m-c
currently, the only way to turn it off, generally speaking, is just
removing the test. Often this is undesirable, as if the test should
be dismissed because other people want to land and it can't be
investigated in real time (is it a failure? is the test bad? is no
one around that knows the test?), then backing out a test is at best
problematic. With a manifest, a test may be disabled without
removing it from the tree and a bug filed with the appropriate
reason:
.. code-block:: text
[test_broken.js]
disabled = https://bugzilla.mozilla.org/show_bug.cgi?id=123456
* ability to run different (subsets of) tests on different
platforms. Traditionally, we've done a bit of magic or had the test
know what platform it would or would not run on. With manifests, you
can mark what platforms a test will or will not run on and change
these without changing the test.
.. code-block:: text
[test_works_on_windows_only.js]
skip-if = os != 'win'
* ability to markup tests with metadata. We have a large, complicated,
and always changing infrastructure. key, value metadata may be used
as an annotation to a test and appropriately curated and mined. For
instance, we could mark certain tests as randomorange with a bug
number, if it were desirable.
* ability to have sane and well-defined test-runs. You can keep
different manifests for different test runs and ``[include:]``
(sub)manifests as appropriate to your needs.
Manifest Format
````````
Manifests are .ini file with the section names denoting the path
relative to the manifest:
.. code-block:: text
[foo.js]
[bar.js]
[fleem.js]
The sections are read in order. In addition, tests may include
arbitrary key, value metadata to be used by the harness. You may also
have a `[DEFAULT]` section that will give key, value pairs that will
be inherited by each test unless overridden:
.. code-block:: text
[DEFAULT]
type = restart
[lilies.js]
color = white
[daffodils.js]
color = yellow
type = other
# override type from DEFAULT
[roses.js]
color = red
You can also include other manifests:
.. code-block:: text
[include:subdir/anothermanifest.ini]
And reference parent manifests to inherit keys and values from the DEFAULT
section, without adding possible included tests.
.. code-block:: text
[parent:../manifest.ini]
Manifests are included relative to the directory of the manifest with
the `[include:]` directive unless they are absolute paths.
By default you can use both '#' and ';' as comment characters. Comments
must start on a new line, inline comments are not supported.
.. code-block:: text
[roses.js]
# a valid comment
; another valid comment
color = red # not a valid comment
In the example above, the 'color' property will have the value 'red #
not a valid comment'.
Special variable server-root
````````````````````````````
There is a special variable called `server-root` used for paths on the system.
This variable is deemed a path and will be expanded into its absolute form.
Because of the inheritant nature of the key/value pairs, if one requires a
system path, it must be absolute for it to be of any use in any included file.
.. code-block:: text
[DEFAULTS]
server-root = ../data
[test1.js]
server-root = test1/data
Manifest Conditional Expressions
````````````````````````````````
The conditional expressions used in manifests are parsed using the *ExpressionParser* class.
.. autoclass:: manifestparser.ExpressionParser
Consumers of this module are expected to pass in a value dictionary
for evaluating conditional expressions. A common pattern is to pass
the dictionary from the :mod:`mozinfo` module.
Data
````
Manifest Destiny gives tests as a list of dictionaries (in python
terms).
* path: full path to the test
* relpath: relative path starting from the root directory. The root directory
is typically the location of the root manifest, or the source
repository. It can be specified at runtime by passing in `rootdir`
to `TestManifest`. Defaults to the directory containing the test's
ancestor manifest.
* name: file name of the test
* here: the parent directory of the manifest
* manifest: the path to the manifest containing the test
This data corresponds to a one-line manifest:
.. code-block:: text
[testToolbar/testBackForwardButtons.js]
If additional key, values were specified, they would be in this dict
as well.
Outside of the reserved keys, the remaining key, values
are up to convention to use. There is a (currently very minimal)
generic integration layer in manifestparser for use of all harnesses,
`manifestparser.TestManifest`.
For instance, if the 'disabled' key is present, you can get the set of
tests without disabled (various other queries are doable as well).
Since the system is convention-based, the harnesses may do whatever
they want with the data. They may ignore it completely, they may use
the provided integration layer, or they may provide their own
integration layer. This should allow whatever sort of logic is
desired. For instance, if in yourtestharness you wanted to run only on
mondays for a certain class of tests:
.. code-block:: text
tests = []
for test in manifests.tests:
if 'runOnDay' in test:
if calendar.day_name[calendar.weekday(*datetime.datetime.now().timetuple()[:3])].lower() == test['runOnDay'].lower():
tests.append(test)
else:
tests.append(test)
To recap:
* the manifests allow you to specify test data
* the parser gives you this data
* you can use it however you want or process it further as you need
Tests are denoted by sections in an .ini file (see
http://hg.mozilla.org/automation/manifestparser/file/tip/manifestparser/tests/mozmill-example.ini).
Additional manifest files may be included with an `[include:]` directive:
.. code-block:: text
[include:path-to-additional-file.manifest]
The path to included files is relative to the current manifest.
The `[DEFAULT]` section contains variables that all tests inherit from.
Included files will inherit the top-level variables but may override
in their own `[DEFAULT]` section.
manifestparser Architecture
````````````````````````````
There is a two- or three-layered approach to the manifestparser
architecture, depending on your needs:
1. ManifestParser: this is a generic parser for .ini manifests that
facilitates the `[include:]` logic and the inheritence of
metadata. Despite the internal variable being called `self.tests`
(an oversight), this layer has nothing in particular to do with tests.
2. TestManifest: this is a harness-agnostic integration layer that is
test-specific. TestManifest faciliates `skip-if` logic.
3. Optionally, a harness will have an integration layer than inherits
from TestManifest if more harness-specific customization is desired at
the manifest level.
See the source code at https://github.com/mozilla/mozbase/tree/master/manifestparser
and
https://github.com/mozilla/mozbase/blob/master/manifestparser/manifestparser.py
in particular.
Filtering Manifests
```````````````````
After creating a `TestManifest` object, all manifest files are read and a list
of test objects can be accessed via `TestManifest.tests`. However this list contains
all test objects, whether they should be run or not. Normally they need to be
filtered down only to the set of tests that should be run by the test harness.
To do this, a test harness can call `TestManifest.active_tests`:
.. code-block:: python
tests = manifest.active_tests(exists=True, disabled=True, **tags)
By default, `active_tests` runs the filters found in
:attr:`~.DEFAULT_FILTERS`. It also accepts two convenience arguments:
1. `exists`: if True (default), filter out tests that do not exist on the local file system.
2. `disabled`: if True (default), do not filter out tests containing the 'disabled' key
(which can be set by `skip-if` manually).
This works for simple cases, but there are other built-in filters, or even custom filters
that can be applied to the `TestManifest`. To do so, add the filter to `TestManifest.filters`:
.. code-block:: python
from manifestparser.filters import subsuite
import mozinfo
filters = [subsuite('devtools')]
tests = manifest.active_tests(filters=filters, **mozinfo.info)
.. automodule:: manifestparser.filters
:members:
:exclude-members: filterlist,InstanceFilter,DEFAULT_FILTERS
.. autodata:: manifestparser.filters.DEFAULT_FILTERS
:annotation:
For example, suppose we want to introduce a new key called `timeout-if` that adds a
'timeout' property to a test if a certain condition is True. The syntax in the manifest
files will look like this:
.. code-block:: text
[test_foo.py]
timeout-if = 300, os == 'win'
The value is <timeout>, <condition> where condition is the same format as the one in
`skip-if`. In the above case, if os == 'win', a timeout of 300 seconds will be
applied. Otherwise, no timeout will be applied. All we need to do is define the filter
and add it:
.. code-block:: python
from manifestparser.expression import parse
import mozinfo
def timeout_if(tests, values):
for test in tests:
if 'timeout-if' in test:
timeout, condition = test['timeout-if'].split(',', 1)
if parse(condition, **values):
test['timeout'] = timeout
yield test
tests = manifest.active_tests(filters=[timeout_if], **mozinfo.info)
Creating Manifests
``````````````````
manifestparser comes with a console script, `manifestparser create`, that
may be used to create a seed manifest structure from a directory of
files. Run `manifestparser help create` for usage information.
Copying Manifests
`````````````````
To copy tests and manifests from a source:
.. code-block:: text
manifestparser [options] copy from_manifest to_directory -tag1 -tag2 `key1=value1 key2=value2 ...
Updating Tests
``````````````
To update the tests associated with with a manifest from a source
directory:
.. code-block:: text
manifestparser [options] update manifest from_directory -tag1 -tag2 `key1=value1 `key2=value2 ...
Usage example
`````````````
Here is an example of how to create manifests for a directory tree and
update the tests listed in the manifests from an external source.
Creating Manifests
``````````````````
Let's say you want to make a series of manifests for a given directory structure containing `.js` test files:
.. code-block:: text
testing/mozmill/tests/firefox/
testing/mozmill/tests/firefox/testAwesomeBar/
testing/mozmill/tests/firefox/testPreferences/
testing/mozmill/tests/firefox/testPrivateBrowsing/
testing/mozmill/tests/firefox/testSessionStore/
testing/mozmill/tests/firefox/testTechnicalTools/
testing/mozmill/tests/firefox/testToolbar/
testing/mozmill/tests/firefox/restartTests
You can use `manifestparser create` to do this:
.. code-block:: text
$ manifestparser help create
Usage: manifestparser.py [options] create directory <directory> <...>
create a manifest from a list of directories
Options:
-p PATTERN, `pattern=PATTERN
glob pattern for files
-i IGNORE, `ignore=IGNORE
directories to ignore
-w IN_PLACE, --in-place=IN_PLACE
Write .ini files in place; filename to write to
We only want `.js` files and we want to skip the `restartTests` directory.
We also want to write a manifest per directory, so I use the `--in-place`
option to write the manifests:
.. code-block:: text
manifestparser create . -i restartTests -p '*.js' -w manifest.ini
This creates a manifest.ini per directory that we care about with the JS test files:
.. code-block:: text
testing/mozmill/tests/firefox/manifest.ini
testing/mozmill/tests/firefox/testAwesomeBar/manifest.ini
testing/mozmill/tests/firefox/testPreferences/manifest.ini
testing/mozmill/tests/firefox/testPrivateBrowsing/manifest.ini
testing/mozmill/tests/firefox/testSessionStore/manifest.ini
testing/mozmill/tests/firefox/testTechnicalTools/manifest.ini
testing/mozmill/tests/firefox/testToolbar/manifest.ini
The top-level `manifest.ini` merely has `[include:]` references to the sub manifests:
.. code-block:: text
[include:testAwesomeBar/manifest.ini]
[include:testPreferences/manifest.ini]
[include:testPrivateBrowsing/manifest.ini]
[include:testSessionStore/manifest.ini]
[include:testTechnicalTools/manifest.ini]
[include:testToolbar/manifest.ini]
Each sub-level manifest contains the (`.js`) test files relative to it.
Updating the tests from manifests
`````````````````````````````````
You may need to update tests as given in manifests from a different source directory.
`manifestparser update` was made for just this purpose:
.. code-block:: text
Usage: manifestparser [options] update manifest directory -tag1 -tag2 `key1=value1 --key2=value2 ...
update the tests as listed in a manifest from a directory
To update from a directory of tests in `~/mozmill/src/mozmill-tests/firefox/` run:
.. code-block:: text
manifestparser update manifest.ini ~/mozmill/src/mozmill-tests/firefox/
Tests
`````
manifestparser includes a suite of tests:
https://github.com/mozilla/mozbase/tree/master/manifestparsery/tests
`test_manifest.txt` is a doctest that may be helpful in figuring out
how to use the API. Tests are run via `python test.py`.
Bugs
````
Please file any bugs or feature requests at
https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=ManifestParser
Or contact jhammel @mozilla.org or in #ateam on irc.mozilla.org
CLI
```
Run `manifestparser help` for usage information.
To create a manifest from a set of directories:
.. code-block:: text
manifestparser [options] create directory <directory> <...> [create-options]
To output a manifest of tests:
.. code-block:: text
manifestparser [options] write manifest <manifest> <...> -tag1 -tag2 --key1=value1 --key2=value2 ...
To copy tests and manifests from a source:
.. code-block:: text
manifestparser [options] copy from_manifest to_manifest -tag1 -tag2 `key1=value1 key2=value2 ...
To update the tests associated with with a manifest from a source
directory:
.. code-block:: text
manifestparser [options] update manifest from_directory -tag1 -tag2 --key1=value1 --key2=value2 ...
Design Considerations
`````````````````````
Contrary to some opinion, manifestparser.py and the associated .ini
format were not magically plucked from the sky but were descended upon
through several design considerations.
* test manifests should be ordered. While python 2.6 and greater has
a ConfigParser that can use an ordered dictionary, it is a
requirement that we support python 2.4 for the build + testing
environment. To that end, a `read_ini` function was implemented
in manifestparser.py that should be the equivalent of the .ini
dialect used by ConfigParser.
* the manifest format should be easily human readable/writable. While
there was initially some thought of using JSON, there was pushback
that JSON was not easily editable. An ideal manifest format would
degenerate to a line-separated list of files. While .ini format
requires an additional `[]` per line, and while there have been
complaints about this, hopefully this is good enough.
* python does not have an in-built YAML parser. Since it was
undesirable for manifestparser.py to have any dependencies, YAML was
dismissed as a format.
* we could have used a proprietary format but decided against it.
Everyone knows .ini and there are good tools to deal with it.
However, since read_ini is the only function that transforms a
manifest to a list of key, value pairs, while the implications for
changing the format impacts downstream code, doing so should be
programmatically simple.
* there should be a single file that may easily be
transported. Traditionally, test harnesses have lived in
mozilla-central. This is less true these days and it is increasingly
likely that more tests will not live in mozilla-central going
forward. So `manifestparser.py` should be highly consumable. To
this end, it is a single file, as appropriate to mozilla-central,
which is also a working python package deployed to PyPI for easy
installation.
Historical Reference
````````````````````
Date-ordered list of links about how manifests came to be where they are today::
* https://wiki.mozilla.org/Auto-tools/Projects/UniversalManifest
* http://alice.nodelman.net/blog/post/2010/05/
* http://alice.nodelman.net/blog/post/universal-manifest-for-unit-tests-a-proposal/
* https://elvis314.wordpress.com/2010/07/05/improving-personal-hygiene-by-adjusting-mochitests/
* https://elvis314.wordpress.com/2010/07/27/types-of-data-we-care-about-in-a-manifest/
* https://bugzilla.mozilla.org/show_bug.cgi?id=585106
* http://elvis314.wordpress.com/2011/05/20/converting-xpcshell-from-listing-directories-to-a-manifest/
* https://bugzilla.mozilla.org/show_bug.cgi?id=616999
* https://developer.mozilla.org/en/Writing_xpcshell-based_unit_tests#Adding_your_tests_to_the_xpcshell_manifest

View file

@ -0,0 +1,8 @@
:mod:`mozcrash` --- Print stack traces from minidumps left behind by crashed processes
======================================================================================
Gets stack traces out of processes that have crashed and left behind
a minidump file using the Google Breakpad library.
.. automodule:: mozcrash
:members: check_for_crashes

View file

@ -0,0 +1,5 @@
:mod:`mozdebug` --- Configure and launch compatible debuggers.
======================================================================================
.. automodule:: mozdebug
:members: get_debugger_info, get_default_debugger_name, DebuggerSearch

View file

@ -0,0 +1,254 @@
:mod:`mozdevice` --- Interact with remote devices
=================================================
Mozdevice provides several interfaces to interact with a remote device
such as an Android- or FirefoxOS-based phone. It allows you to push
files to these types of devices, launch processes, and more. There are
currently two available interfaces:
* :ref:`DeviceManager`: Works either via ADB or a custom TCP protocol
(the latter requires an agent application running on the device).
* :ref:`ADB`: Uses the Android Debugger Protocol explicitly
In general, new code should use the ADB abstraction where possible as
it is simpler and more reliable.
.. automodule:: mozdevice
.. _DeviceManager:
DeviceManager interface
-----------------------
.. autoclass:: DeviceManager
Here's an example script which lists the files in '/mnt/sdcard' and sees if a
process called 'org.mozilla.fennec' is running. In this example, we're
instantiating the DeviceManagerADB implementation, but we could just
as easily have used DeviceManagerSUT (assuming the device had an agent
running speaking the SUT protocol).
::
import mozdevice
dm = mozdevice.DeviceManagerADB()
print dm.listFiles("/mnt/sdcard")
if dm.processExist("org.mozilla.fennec"):
print "Fennec is running"
Informational methods
`````````````````````
.. automethod:: DeviceManager.getInfo(self, directive=None)
.. automethod:: DeviceManager.getCurrentTime(self)
.. automethod:: DeviceManager.getIP
.. automethod:: DeviceManager.saveScreenshot
.. automethod:: DeviceManager.recordLogcat
.. automethod:: DeviceManager.getLogcat
File management methods
```````````````````````
.. autoattribute:: DeviceManager.deviceRoot
.. automethod:: DeviceManager.getDeviceRoot(self)
.. automethod:: DeviceManager.pushFile(self, localFilename, remoteFilename, retryLimit=1)
.. automethod:: DeviceManager.pushDir(self, localDirname, remoteDirname, retryLimit=1)
.. automethod:: DeviceManager.pullFile(self, remoteFilename)
.. automethod:: DeviceManager.getFile(self, remoteFilename, localFilename)
.. automethod:: DeviceManager.getDirectory(self, remoteDirname, localDirname, checkDir=True)
.. automethod:: DeviceManager.validateFile(self, remoteFilename, localFilename)
.. automethod:: DeviceManager.mkDir(self, remoteDirname)
.. automethod:: DeviceManager.mkDirs(self, filename)
.. automethod:: DeviceManager.dirExists(self, dirpath)
.. automethod:: DeviceManager.fileExists(self, filepath)
.. automethod:: DeviceManager.listFiles(self, rootdir)
.. automethod:: DeviceManager.removeFile(self, filename)
.. automethod:: DeviceManager.removeDir(self, remoteDirname)
.. automethod:: DeviceManager.chmodDir(self, remoteDirname, mask="777")
.. automethod:: DeviceManager.getTempDir(self)
Process management methods
``````````````````````````
.. automethod:: DeviceManager.shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False)
.. automethod:: DeviceManager.shellCheckOutput(self, cmd, env=None, cwd=None, timeout=None, root=False)
.. automethod:: DeviceManager.getProcessList(self)
.. automethod:: DeviceManager.processExist(self, processName)
.. automethod:: DeviceManager.killProcess(self, processName)
System control methods
``````````````````````
.. automethod:: DeviceManager.reboot(self, ipAddr=None, port=30000)
Application management methods
``````````````````````````````
.. automethod:: DeviceManager.uninstallAppAndReboot(self, appName, installPath=None)
.. automethod:: DeviceManager.installApp(self, appBundlePath, destPath=None)
.. automethod:: DeviceManager.uninstallApp(self, appName, installPath=None)
.. automethod:: DeviceManager.updateApp(self, appBundlePath, processName=None, destPath=None, ipAddr=None, port=30000)
DeviceManagerADB implementation
```````````````````````````````
.. autoclass:: mozdevice.DeviceManagerADB
DeviceManagerADB has several methods that are not present in all
DeviceManager implementations. Please do not use them in code that
is meant to be interoperable.
.. automethod:: DeviceManagerADB.forward
.. automethod:: DeviceManagerADB.remount
.. automethod:: DeviceManagerADB.devices
DeviceManagerSUT implementation
```````````````````````````````
.. autoclass:: mozdevice.DeviceManagerSUT
DeviceManagerSUT has several methods that are only used in specific
tests and are not present in all DeviceManager implementations. Please
do not use them in code that is meant to be interoperable.
.. automethod:: DeviceManagerSUT.unpackFile
.. automethod:: DeviceManagerSUT.adjustResolution
Android extensions
``````````````````
For Android, we provide two variants of the `DeviceManager` interface
with extensions useful for that platform. These classes are called
DroidADB and DroidSUT. They inherit all methods from DeviceManagerADB
and DeviceManagerSUT. Here is the interface for DroidADB:
.. automethod:: mozdevice.DroidADB.launchApplication
.. automethod:: mozdevice.DroidADB.launchFennec
.. automethod:: mozdevice.DroidADB.getInstalledApps
.. automethod:: mozdevice.DroidADB.getAppRoot
These methods are also found in the DroidSUT class.
.. _ADB:
ADB Interface
-------------
The following classes provide a basic interface to interact with the
Android Debug Tool (adb) and Android-based devices. It is intended to
provide the basis for a replacement for DeviceManager and
DeviceManagerADB.
ADBCommand
``````````
.. autoclass:: mozdevice.ADBCommand
.. automethod:: ADBCommand.command(self, cmds, timeout=None)
.. automethod:: ADBCommand.command_output(self, cmds, timeout=None)
ADBHost
```````
.. autoclass:: mozdevice.ADBHost
.. automethod:: ADBHost.command(self, cmds, timeout=None)
.. automethod:: ADBHost.command_output(self, cmds, timeout=None)
.. automethod:: ADBHost.start_server(self, timeout=None)
.. automethod:: ADBHost.kill_server(self, timeout=None)
.. automethod:: ADBHost.devices(self, timeout=None)
ADBDevice
`````````
.. autoclass:: mozdevice.ADBDevice
Host Command methods
++++++++++++++++++++
.. automethod:: ADBDevice.command(self, cmds, timeout=None)
.. automethod:: ADBDevice.command_output(self, cmds, timeout=None)
Device Shell methods
++++++++++++++++++++
.. automethod:: ADBDevice.shell(self, cmd, env=None, cwd=None, timeout=None, root=False)
.. automethod:: ADBDevice.shell_bool(self, cmd, env=None, cwd=None, timeout=None, root=False)
.. automethod:: ADBDevice.shell_output(self, cmd, env=None, cwd=None, timeout=None, root=False)
Informational methods
+++++++++++++++++++++
.. automethod:: ADBDevice.clear_logcat
.. automethod:: ADBDevice.get_battery_percentage
.. automethod:: ADBDevice.get_info
.. automethod:: ADBDevice.get_logcat
.. automethod:: ADBDevice.get_prop
.. automethod:: ADBDevice.get_state
System control methods
++++++++++++++++++++++
.. automethod:: ADBDevice.is_device_ready
.. automethod:: ADBDevice.reboot
File management methods
+++++++++++++++++++++++
.. automethod:: ADBDevice.chmod
.. automethod:: ADBDevice.cp
.. automethod:: ADBDevice.exists
.. automethod:: ADBDevice.is_dir
.. automethod:: ADBDevice.is_file
.. automethod:: ADBDevice.list_files
.. automethod:: ADBDevice.mkdir
.. automethod:: ADBDevice.mv
.. automethod:: ADBDevice.push
.. automethod:: ADBDevice.rm
.. automethod:: ADBDevice.rmdir
.. autoattribute:: ADBDevice.test_root
Process management methods
++++++++++++++++++++++++++
.. automethod:: ADBDevice.get_process_list
.. automethod:: ADBDevice.kill
.. automethod:: ADBDevice.pkill
.. automethod:: ADBDevice.process_exist
ADBAndroid
``````````
.. autoclass:: ADBAndroid
Informational methods
+++++++++++++++++++++
.. automethod:: ADBAndroid.get_battery_percentage
System control methods
++++++++++++++++++++++
.. automethod:: ADBAndroid.is_device_ready
.. automethod:: ADBAndroid.power_on
Application management methods
++++++++++++++++++++++++++++++
.. automethod:: ADBAndroid.install_app
.. automethod:: ADBAndroid.is_app_installed
.. automethod:: ADBAndroid.launch_application
.. automethod:: ADBAndroid.launch_fennec
.. automethod:: ADBAndroid.stop_application
.. automethod:: ADBAndroid.uninstall_app
.. automethod:: ADBAndroid.update_app
ADBB2G
``````
.. autoclass:: ADBB2G
Informational methods
+++++++++++++++++++++
.. automethod:: ADBB2G.get_battery_percentage
.. automethod:: ADBB2G.get_info
.. automethod:: ADBB2G.get_memory_total
ADBProcess
``````````
.. autoclass:: mozdevice.ADBProcess
ADBError
````````
.. autoexception:: mozdevice.ADBError
ADBRootError
````````````
.. autoexception:: mozdevice.ADBRootError
ADBTimeoutError
```````````````
.. autoexception:: mozdevice.ADBTimeoutError

View file

@ -0,0 +1,10 @@
:mod:`mozfile` --- File utilities for use in Mozilla testing
============================================================
mozfile is a convenience library for taking care of some common file-related
tasks in automated testing, such as extracting files or recursively removing
directories.
.. automodule:: mozfile
:members: extract, extract_tarball, extract_zip, move, remove

View file

@ -0,0 +1,22 @@
Serving up content to be consumed by the browser
================================================
.. warning:: The mozhttpd module is considered obsolete. For new code,
please use wptserve_ which can do everything mozhttpd does
and more.
.. _wptserve: https://pypi.python.org/pypi/wptserve
:mod:`mozhttpd` --- Simple webserver
------------------------------------
.. automodule:: mozhttpd
:members:
Interface
`````````
.. autoclass:: MozHttpd
:members:

View file

@ -0,0 +1,71 @@
:mod:`mozinfo` --- Get system information
=========================================
Throughout `mozmill <https://developer.mozilla.org/en/Mozmill>`_
and other Mozilla python code, checking the underlying
platform is done in many different ways. The various checks needed
lead to a lot of copy+pasting, leaving the reader to wonder....is this
specific check necessary for (e.g.) an operating system? Because
information is not consolidated, checks are not done consistently, nor
is it defined what we are checking for.
`mozinfo <https://github.com/mozilla/mozbase/tree/master/mozinfo>`_
proposes to solve this problem. mozinfo is a bridge interface,
making the underlying (complex) plethora of OS and architecture
combinations conform to a subset of values of relevance to
Mozilla software. The current implementation exposes relevant keys and
values such as: ``os``, ``version``, ``bits``, and ``processor``. Additionally, the
service pack in use is available on the windows platform.
API Usage
---------
mozinfo is a python package. Downloading the software and running
``python setup.py develop`` will allow you to do ``import mozinfo``
from python.
`mozinfo.py <https://raw.github.com/mozilla/mozbase/master/mozinfo/mozinfo/mozinfo.py>`_
is the only file contained is this package,
so if you need a single-file solution, you can just download or call
this file through the web.
The top level attributes (``os``, ``version``, ``bits``, ``processor``) are
available as module globals::
if mozinfo.os == 'win': ...
In addition, mozinfo exports a dictionary, ``mozinfo.info``, that
contain these values. mozinfo also exports:
- ``choices``: a dictionary of possible values for os, bits, and
processor
- ``main``: the console_script entry point for mozinfo
- ``unknown``: a singleton denoting a value that cannot be determined
``unknown`` has the string representation ``"UNKNOWN"``.
``unknown`` will evaluate as ``False`` in python::
if not mozinfo.os: ... # unknown!
Command Line Usage
------------------
mozinfo comes with a command line program, ``mozinfo`` which may be used to
diagnose one's current system.
Example output::
os: linux
version: Ubuntu 10.10
bits: 32
processor: x86
Three of these fields, os, bits, and processor, have a finite set of
choices. You may display the value of these choices using
``mozinfo --os``, ``mozinfo --bits``, and ``mozinfo --processor``.
``mozinfo --help`` documents command-line usage.
.. automodule:: mozinfo
:members:

View file

@ -0,0 +1,29 @@
:mod:`mozinstall` --- Install and uninstall Gecko-based applications
====================================================================
mozinstall is a small python module with several convenience methods
useful for installing and uninstalling a gecko-based application
(e.g. Firefox) on the desktop.
Simple example
--------------
::
import mozinstall
import tempfile
tempdir = tempfile.mkdtemp()
firefox_dmg = 'firefox-38.0a1.en-US.mac.dmg'
install_folder = mozinstall.install(src=firefox_dmg, dest=tempdir)
binary = mozinstall.get_binary(install_folder, 'Firefox')
# from here you can execute the binary directly
# ...
mozinstall.uninstall(install_folder)
API Documentation
-----------------
.. automodule:: mozinstall
:members: is_installer, install, get_binary, uninstall,
InstallError, InvalidBinary, InvalidSource

View file

@ -0,0 +1,486 @@
:mod:`mozlog` --- Structured logging for test output
===============================================================
:py:mod:`mozlog` is a library designed for logging the
execution and results of test harnesses. The internal data model is a
stream of JSON-compatible objects, with one object per log entry. The
default output format is line-based, with one JSON object serialized
per line.
:py:mod:`mozlog` is *not* based on the stdlib logging
module, although it shares several concepts with it.
One notable difference between this module and the standard logging
module is the way that loggers are created. The structured logging
module does not require that loggers with a specific name are
singleton objects accessed through a factory function. Instead the
``StructuredLogger`` constructor may be used directly. However all
loggers with the same name share the same internal state (the "Borg"
pattern). In particular the list of handler functions is the same for
all loggers with the same name.
Typically, you would only instantiate one logger object per
program. Two convenience methods are provided to set and get the
default logger in the program.
Logging is threadsafe, with access to handlers protected by a
``threading.Lock``. However it is `not` process-safe. This means that
applications using multiple processes, e.g. via the
``multiprocessing`` module, should arrange for all logging to happen in
a single process.
Data Format
-----------
Structured loggers produce messages in a simple format designed to be
compatible with the JSON data model. Each message is a single object,
with the type of message indicated by the ``action`` key. It is
intended that the set of ``action`` values be closed; where there are
use cases for additional values they should be integrated into this
module rather than extended in an ad-hoc way. The set of keys present
on on all messages is:
``action``
The type of the message (string).
``time``
The timestamp of the message in ms since the epoch (int).
``thread``
The name of the thread emitting the message (string).
``pid``
The pid of the process creating the message (int).
``source``
Name of the logger creating the message (string).
For each ``action`` there are is a further set of specific fields
describing the details of the event that caused the message to be
emitted:
``suite_start``
Emitted when the testsuite starts running.
``tests``
A list of test ids. Test ids can either be strings or lists of
strings (an example of the latter is reftests where the id has the
form [test_url, ref_type, ref_url]) and are assumed to be unique
within a given testsuite. In cases where the test list is not
known upfront an empty list may be passed (list).
``run_info``
An optional dictionary describing the properties of the
build and test environment. This contains the information provided
by :doc:`mozinfo <mozinfo>`, plus a boolean ``debug`` field indicating
whether the build under test is a debug build.
``suite_end``
Emitted when the testsuite is finished and no more results will be produced.
``test_start``
Emitted when a test is being started.
``test``
A unique id for the test (string or list of strings).
``path``
Optional path to the test relative to some base (typically the root of the
source tree). Mainly used when ``test`` id is not a path (string).
``test_status``
Emitted for a test which has subtests to record the result of a
single subtest.
``test``
The same unique id for the test as in the ``test_start`` message.
``subtest``
Name of the subtest (string).
``status``
Result of the test (string enum; ``PASS``, ``FAIL``, ``TIMEOUT``,
``NOTRUN``)
``expected``
Expected result of the test. Omitted if the expected result is the
same as the actual result (string enum, same as ``status``).
``test_end``
Emitted to give the result of a test with no subtests, or the status
of the overall file when there are subtests.
``test``
The same unique id for the test as in the ``test_start`` message.
``status``
Either result of the test (if there are no subtests) in which case
(string enum ``PASS``, ``FAIL``, ``TIMEOUT``, ``CRASH``,
``ASSERT``, ``SKIP``) or the status of the overall file where
there are subtests (string enum ``OK``, ``ERROR``, ``TIMEOUT``,
``CRASH``, ``ASSERT``, ``SKIP``).
``expected``
The expected status, or omitted if the expected status matches the
actual status (string enum, same as ``status``).
``process_output``
Output from a managed subprocess.
``process``
pid of the subprocess.
``command``
Command used to launch the subprocess.
``data``
Data output by the subprocess.
``log``
General human-readable logging message, used to debug the harnesses
themselves rather than to provide input to other tools.
``level``
Level of the log message (string enum ``CRITICAL``, ``ERROR``,
``WARNING``, ``INFO``, ``DEBUG``).
``message``
Text of the log message.
Testsuite Protocol
------------------
When used for testsuites, the following structured logging messages must be emitted:
* One ``suite_start`` message before any ``test_*`` messages
* One ``test_start`` message per test that is run
* One ``test_status`` message per subtest that is run. This might be
zero if the test type doesn't have the notion of subtests.
* One ``test_end`` message per test that is run, after the
``test_start`` and any ``test_status`` messages for that same test.
* One ``suite_end`` message after all ``test_*`` messages have been
emitted.
The above mandatory events may be interspersed with ``process_output``
and ``log`` events, as required.
Subtests
~~~~~~~~
The purpose of subtests is to deal with situations where a single test
produces more than one result, and the exact details of the number of
results is not known ahead of time. For example consider a test
harness that loads JavaScript-based tests in a browser. Each url
loaded would be a single test, with corresponding ``test_start`` and
``test_end`` messages. If there can be more than one JS-defined test
on a page, however, it it useful to track the results of those tests
seperately. Therefore each of those tests is a subtest, and one
``test_status`` message must be generated for each subtest result.
Subtests must have a name that is unique within their parent test.
Whether or not a test has subtests changes the meaning of the
``status`` property on the test itself. When the test does not have
any subtests, this property is the actual test result such as ``PASS``
or ``FAIL`` . When a test does have subtests, the test itself does not
have a result as-such; it isn't meaningful to describe it as having a
``PASS`` result, especially if the subtests did not all pass. Instead
this property is used to hold information about whether the test ran
without error. If no errors were detected the test must be given the
status ``OK``. Otherwise the test may get the status ``ERROR`` (for
e.g. uncaught JS exceptions), ``TIMEOUT`` (if no results were reported
in the allowed time) or ``CRASH`` (if the test caused the process
under test to crash).
StructuredLogger Objects
------------------------
.. automodule:: mozlog.structuredlog
:members: set_default_logger, get_default_logger
.. autoclass:: StructuredLogger
:members: add_handler, remove_handler, handlers, suite_start,
suite_end, test_start, test_status, test_end,
process_output, critical, error, warning, info, debug
.. autoclass:: StructuredLogFileLike
:members:
ProxyLogger Objects
-------------------
Since :func:`mozlog.structuredlog.get_default_logger` return None when
the default logger is not initialized, it is not possible to directly
use it at the module level.
With ProxyLogger, it is possible to write the following code: ::
from mozlog import get_proxy_logger
LOG = get_proxy_logger('component_name')
def my_function():
LOG.info('logging with a module level object')
.. note::
mozlog still needs to be initialized before the first call occurs
to a ProxyLogger instance, for example with
:func:`mozlog.commandline.setup_logging`.
.. automodule:: mozlog.proxy
:members: get_proxy_logger, ProxyLogger
Handlers
--------
A handler is a callable that is called for each log message produced
and is responsible for handling the processing of that
message. The typical example of this is a ``StreamHandler`` which takes
a log message, invokes a formatter which converts the log to a string,
and writes it to a file.
.. automodule:: mozlog.handlers
.. autoclass:: BaseHandler
:members:
.. autoclass:: StreamHandler
:members:
.. autoclass:: LogLevelFilter
:members:
.. autoclass:: BufferHandler
:members:
Formatters
----------
Formatters are callables that take a log message, and return either a
string representation of that message, or ``None`` if that message
should not appear in the output. This allows formatters to both
exclude certain items and create internal buffers of the output so
that, for example, a single string might be returned for a
``test_end`` message indicating the overall result of the test,
including data provided in the ``test_status`` messages.
Formatter modules are written so that they can take raw input on stdin
and write formatted output on stdout. This allows the formatters to be
invoked as part of a command line for post-processing raw log files.
.. automodule:: mozlog.formatters.base
.. autoclass:: BaseFormatter
:members:
.. automodule:: mozlog.formatters.unittest
.. autoclass:: UnittestFormatter
:members:
.. automodule:: mozlog.formatters.xunit
.. autoclass:: XUnitFormatter
:members:
.. automodule:: mozlog.formatters.html
.. autoclass:: HTMLFormatter
:members:
.. automodule:: mozlog.formatters.machformatter
.. autoclass:: MachFormatter
:members:
.. automodule:: mozlog.formatters.tbplformatter
.. autoclass:: TbplFormatter
:members:
Processing Log Files
--------------------
The ``mozlog.reader`` module provides utilities for working
with structured log files.
.. automodule:: mozlog.reader
:members:
Integration with argparse
-------------------------
The `mozlog.commandline` module provides integration with the `argparse`
module to provide uniform logging-related command line arguments to programs
using `mozlog`. Each known formatter gets a command line argument of the form
``--log-{name}``, which takes the name of a file to log to with that format,
or ``-`` to indicate stdout.
.. automodule:: mozlog.commandline
:members:
Simple Examples
---------------
Log to stdout::
from mozlog import structuredlog
from mozlog import handlers, formatters
logger = structuredlog.StructuredLogger("my-test-suite")
logger.add_handler(handlers.StreamHandler(sys.stdout,
formatters.JSONFormatter()))
logger.suite_start(["test-id-1"])
logger.test_start("test-id-1")
logger.info("This is a message with action='LOG' and level='INFO'")
logger.test_status("test-id-1", "subtest-1", "PASS")
logger.test_end("test-id-1", "OK")
logger.suite_end()
Populate an ``argparse.ArgumentParser`` with logging options, and
create a logger based on the value of those options, defaulting to
JSON output on stdout if nothing else is supplied::
import argparse
from mozlog import commandline
parser = argparse.ArgumentParser()
# Here one would populate the parser with other options
commandline.add_logging_group(parser)
args = parser.parse_args()
logger = commandline.setup_logging("testsuite-name", args, {"raw": sys.stdout})
Count the number of tests that timed out in a testsuite::
from mozlog import reader
count = 0
def handle_test_end(data):
global count
if data["status"] == "TIMEOUT":
count += 1
reader.each_log(reader.read("my_test_run.log"),
{"test_end": handle_test_end})
print count
More Complete Example
---------------------
This example shows a complete toy testharness set up to used
structured logging. It is avaliable as `structured_example.py <_static/structured_example.py>`_:
.. literalinclude:: _static/structured_example.py
Each global function with a name starting
``test_`` represents a test. A passing test returns without
throwing. A failing test throws a :py:class:`TestAssertion` exception
via the :py:func:`assert_equals` function. Throwing anything else is
considered an error in the test. There is also a :py:func:`expected`
decorator that is used to annotate tests that are expected to do
something other than pass.
The main entry point to the test runner is via that :py:func:`main`
function. This is responsible for parsing command line
arguments, and initiating the test run. Although the test harness
itself does not provide any command line arguments, the
:py:class:`ArgumentParser` object is populated by
:py:meth:`commandline.add_logging_group`, which provides a generic
set of structured logging arguments appropriate to all tools producing
structured logging.
The values of these command line arguments are used to create a
:py:class:`mozlog.StructuredLogger` object populated with the
specified handlers and formatters in
:py:func:`commandline.setup_logging`. The third argument to this
function is the default arguments to use. In this case the default
is to output raw (i.e. JSON-formatted) logs to stdout.
The main test harness is provided by the :py:class:`TestRunner`
class. This class is responsible for scheduling all the tests and
logging all the results. It is passed the :py:obj:`logger` object
created from the command line arguments. The :py:meth:`run` method
starts the test run. Before the run is started it logs a
``suite_start`` message containing the id of each test that will run,
and after the testrun is done it logs a ``suite_end`` message.
Individual tests are run in the :py:meth:`run_test` method. For each
test this logs a ``test_start`` message. It then runs the test and
logs a ``test_end`` message containing the test name, status, expected
status, and any informational message about the reason for the
result. In this test harness there are no subtests, so the
``test_end`` message has the status of the test and there are no
``test_status`` messages.
Example Output
~~~~~~~~~~~~~~
When run without providing any command line options, the raw
structured log messages are sent to stdout::
$ python structured_example.py
{"source": "structured-example", "tests": ["test_that_has_an_error", "test_that_fails", "test_expected_fail", "test_that_passes"], "thread": "MainThread", "time": 1401446682787, "action": "suite_start", "pid": 18456}
{"source": "structured-example", "thread": "MainThread", "time": 1401446682787, "action": "log", "message": "Running tests", "level": "INFO", "pid": 18456}
{"source": "structured-example", "test": "test_that_has_an_error", "thread": "MainThread", "time": 1401446682787, "action": "test_start", "pid": 18456}
{"status": "ERROR", "thread": "MainThread", "pid": 18456, "source": "structured-example", "test": "test_that_has_an_error", "time": 1401446682788, "action": "test_end", "message": "Traceback (most recent call last):\n File \"structured_example.py\", line 61, in run_test\n func()\n File \"structured_example.py\", line 31, in test_that_has_an_error\n assert_equals(2, 1 + \"1\")\nTypeError: unsupported operand type(s) for +: 'int' and 'str'\n", "expected": "PASS"}
{"source": "structured-example", "test": "test_that_fails", "thread": "MainThread", "time": 1401446682788, "action": "test_start", "pid": 18456}
{"status": "FAIL", "thread": "MainThread", "pid": 18456, "source": "structured-example", "test": "test_that_fails", "time": 1401446682788, "action": "test_end", "message": "1 not equal to 2", "expected": "PASS"}
{"source": "structured-example", "test": "test_expected_fail", "thread": "MainThread", "time": 1401446682788, "action": "test_start", "pid": 18456}
{"status": "FAIL", "thread": "MainThread", "pid": 18456, "source": "structured-example", "test": "test_expected_fail", "time": 1401446682788, "action": "test_end", "message": "4 not equal to 5"}
{"source": "structured-example", "test": "test_that_passes", "thread": "MainThread", "time": 1401446682788, "action": "test_start", "pid": 18456}
{"status": "PASS", "source": "structured-example", "test": "test_that_passes", "thread": "MainThread", "time": 1401446682789, "action": "test_end", "pid": 18456}
{"action": "suite_end", "source": "structured-example", "pid": 18456, "thread": "MainThread", "time": 1401446682789}
The structured logging module provides a number of command line
options::
$ python structured_example.py --help
usage: structured_example.py [-h] [--log-unittest LOG_UNITTEST]
[--log-raw LOG_RAW] [--log-html LOG_HTML]
[--log-xunit LOG_XUNIT]
[--log-mach LOG_MACH]
optional arguments:
-h, --help show this help message and exit
Output Logging:
Options for logging output. Each option represents a possible logging
format and takes a filename to write that format to, or '-' to write to
stdout.
--log-unittest LOG_UNITTEST
Unittest style output
--log-raw LOG_RAW Raw structured log messages
--log-html LOG_HTML HTML report
--log-xunit LOG_XUNIT
xUnit compatible XML
--log-mach LOG_MACH Human-readable output
In order to get human-readable output on stdout and the structured log
data to go to the file ``structured.log``, we would run::
$ python structured_example.py --log-mach=- --log-raw=structured.log
0:00.00 SUITE_START: MainThread 4
0:01.00 LOG: MainThread INFO Running tests
0:01.00 TEST_START: MainThread test_that_has_an_error
0:01.00 TEST_END: MainThread Harness status ERROR, expected PASS. Subtests passed 0/0. Unexpected 1
0:01.00 TEST_START: MainThread test_that_fails
0:01.00 TEST_END: MainThread Harness status FAIL, expected PASS. Subtests passed 0/0. Unexpected 1
0:01.00 TEST_START: MainThread test_expected_fail
0:02.00 TEST_END: MainThread Harness status FAIL. Subtests passed 0/0. Unexpected 0
0:02.00 TEST_START: MainThread test_that_passes
0:02.00 TEST_END: MainThread Harness status PASS. Subtests passed 0/0. Unexpected 0
0:02.00 SUITE_END: MainThread

View file

@ -0,0 +1,9 @@
:mod:`moznetwork` --- Get network information
=============================================
.. automodule:: moznetwork
.. automethod:: moznetwork.get_ip
.. autoclass:: moznetwork.NetworkError

View file

@ -0,0 +1,324 @@
:mod:`mozprocess` --- Launch and manage processes
=================================================
Mozprocess is a process-handling module that provides some additional
features beyond those available with python's subprocess:
* better handling of child processes, especially on Windows
* the ability to timeout the process after some absolute period, or some
period without any data written to stdout/stderr
* the ability to specify output handlers that will be called
for each line of output produced by the process
* the ability to specify handlers that will be called on process timeout
and normal process termination
Running a process
-----------------
mozprocess consists of two classes: ProcessHandler inherits from ProcessHandlerMixin.
Let's see how to run a process.
First, the class should be instanciated with at least one argument which is a command (or a list formed by the command followed by its arguments).
Then the process can be launched using the *run()* method.
Finally the *wait()* method will wait until end of execution.
.. code-block:: python
from mozprocess import processhandler
# under Windows replace by command = ['dir', '/a']
command = ['ls', '-l']
p = processhandler.ProcessHandler(command)
print("execute command: %s" % p.commandline)
p.run()
p.wait()
Note that using *ProcessHandler* instead of *ProcessHandlerMixin* will print the output of executed command. The attribute *commandline* provides the launched command.
Collecting process output
-------------------------
Let's now consider a basic shell script that will print numbers from 1 to 5 waiting 1 second between each.
This script will be used as a command to launch in further examples.
**proc_sleep_echo.sh**:
.. code-block:: sh
#!/bin/sh
for i in 1 2 3 4 5
do
echo $i
sleep 1
done
If you are running under Windows, you won't be able to use the previous script (unless using Cygwin).
So you'll use the following script:
**proc_sleep_echo.bat**:
.. code-block:: bat
@echo off
FOR %%A IN (1 2 3 4 5) DO (
ECHO %%A
REM if you have TIMEOUT then use it instead of PING
REM TIMEOUT /T 1 /NOBREAK
PING -n 2 127.0.0.1 > NUL
)
Mozprocess allows the specification of custom output handlers to gather process output while running.
ProcessHandler will by default write all outputs on stdout. You can also provide (to ProcessHandler or ProcessHandlerMixin) a function or a list of functions that will be used as callbacks on each output line generated by the process.
In the following example the command's output will be stored in a file *output.log* and printed in stdout:
.. code-block:: python
import sys
from mozprocess import processhandler
fd = open('output.log', 'w')
def tostdout(line):
sys.stdout.write("<%s>\n" % line)
def tofile(line):
fd.write("<%s>\n" % line)
# under Windows you'll replace by 'proc_sleep_echo.bat'
command = './proc_sleep_echo.sh'
outputs = [tostdout, tofile]
p = processhandler.ProcessHandlerMixin(command, processOutputLine=outputs)
p.run()
p.wait()
fd.close()
The process output can be saved (*obj = ProcessHandler(..., storeOutput=True)*) so as it is possible to request it (*obj.output*) at any time. Note that the default value for *stroreOutput* is *True*, so it is not necessary to provide it in the parameters.
.. code-block:: python
import time
import sys
from mozprocess import processhandler
command = './proc_sleep_echo.sh' # Windows: 'proc_sleep_echo.bat'
p = processhandler.ProcessHandler(command, storeOutput=True)
p.run()
for i in xrange(10):
print(p.output)
time.sleep(0.5)
p.wait()
In previous example, you will see the *p.output* list growing.
Execution
---------
Status
``````
It is possible to query the status of the process via *poll()* that will return None if the process is still running, 0 if it ended without failures and a negative value if it was killed by a signal (Unix-only).
.. code-block:: python
import time
import signal
from mozprocess import processhandler
command = './proc_sleep_echo.sh'
p = processhandler.ProcessHandler(command)
p.run()
time.sleep(2)
print("poll status: %s" % p.poll())
time.sleep(1)
p.kill(signal.SIGKILL)
print("poll status: %s" % p.poll())
Timeout
```````
A timeout can be provided to the *run()* method. If the process last more than timeout seconds, it will be stopped.
After execution, the property *timedOut* will be set to True if a timeout was reached.
It is also possible to provide functions (*obj = ProcessHandler[Mixin](..., onTimeout=functions)*) that will be called if the timeout was reached.
.. code-block:: python
from mozprocess import processhandler
def ontimeout():
print("REACHED TIMEOUT")
command = './proc_sleep_echo.sh' # Windows: 'proc_sleep_echo.bat'
functions = [ontimeout]
p = processhandler.ProcessHandler(command, onTimeout=functions)
p.run(timeout=2)
p.wait()
print("timedOut = %s" % p.timedOut)
By default the process will be killed on timeout but it is possible to prevent this by setting *kill_on_timeout* to *False*.
.. code-block:: python
p = processhandler.ProcessHandler(command, onTimeout=functions, kill_on_timeout=False)
p.run(timeout=2)
p.wait()
print("timedOut = %s" % p.timedOut)
In this case, no output will be available after the timeout, but the process will still be running.
Waiting
```````
It is possible to wait until the process exits as already seen with the method *wait()*, or until the end of a timeout if given. Note that in last case the process is still alive after the timeout.
.. code-block:: python
command = './proc_sleep_echo.sh' # Windows: 'proc_sleep_echo.bat'
p = processhandler.ProcessHandler(command)
p.run()
p.wait(timeout=2)
print("timedOut = %s" % p.timedOut)
p.wait()
Killing
```````
You can request to kill the process with the method *kill*. f the parameter "ignore_children" is set to False when the process handler class is initialized, all the process's children will be killed as well.
Except on Windows, you can specify the signal with which to kill method the process (e.g.: *kill(signal.SIGKILL)*).
.. code-block:: python
import time
from mozprocess import processhandler
command = './proc_sleep_echo.sh' # Windows: 'proc_sleep_echo.bat'
p = processhandler.ProcessHandler(command)
p.run()
time.sleep(2)
p.kill()
End of execution
````````````````
You can provide a function or a list of functions to call at the end of the process using the initilization parameter *onFinish*.
.. code-block:: python
from mozprocess import processhandler
def finish():
print("Finished!!")
command = './proc_sleep_echo.sh' # Windows: 'proc_sleep_echo.bat'
p = processhandler.ProcessHandler(command, onFinish=finish)
p.run()
p.wait()
Child management
----------------
Consider the following scripts:
**proc_child.sh**:
.. code-block:: sh
#!/bin/sh
for i in a b c d e
do
echo $i
sleep 1
done
**proc_parent.sh**:
.. code-block:: sh
#!/bin/sh
./proc_child.sh
for i in 1 2 3 4 5
do
echo $i
sleep 1
done
For windows users consider:
**proc_child.bat**:
.. code-block:: bat
@echo off
FOR %%A IN (a b c d e) DO (
ECHO %%A
REM TIMEOUT /T 1 /NOBREAK
PING -n 2 127.0.0.1 > NUL
)
**proc_parent.bat**:
.. code-block:: bat
@echo off
call proc_child.bat
FOR %%A IN (1 2 3 4 5) DO (
ECHO %%A
REM TIMEOUT /T 1 /NOBREAK
PING -n 2 127.0.0.1 > NUL
)
For processes that launch other processes, mozprocess allows you to get child running status, wait for child termination, and kill children.
Ignoring children
`````````````````
By default the *ignore_children* option is False. In that case, killing the main process will kill all its children at the same time.
.. code-block:: python
import time
from mozprocess import processhandler
def finish():
print("Finished")
command = './proc_parent.sh'
p = processhandler.ProcessHandler(command, ignore_children=False, onFinish=finish)
p.run()
time.sleep(2)
print("kill")
p.kill()
If *ignore_children* is set to *True*, killing will apply only to the main process that will wait children end of execution before stoping (join).
.. code-block:: python
import time
from mozprocess import processhandler
def finish():
print("Finished")
command = './proc_parent.sh'
p = processhandler.ProcessHandler(command, ignore_children=True, onFinish=finish)
p.run()
time.sleep(2)
print("kill")
p.kill()
API Documentation
-----------------
.. module:: mozprocess
.. autoclass:: ProcessHandlerMixin
:members: __init__, timedOut, commandline, run, kill, processOutputLine, onTimeout, onFinish, wait
.. autoclass:: ProcessHandler
:members:

View file

@ -0,0 +1,99 @@
:mod:`mozprofile` --- Create and modify Mozilla application profiles
====================================================================
Mozprofile_ is a python tool for creating and managing profiles for Mozilla's
applications (Firefox, Thunderbird, etc.). In addition to creating profiles,
mozprofile can install addons_ and set preferences_ Mozprofile can be utilized
from the command line or as an API.
The preferred way of setting up profile data (addons, permissions, preferences
etc) is by passing them to the profile_ constructor.
Addons
------
.. automodule:: mozprofile.addons
:members:
Addons may be installed individually or from a manifest.
Example::
from mozprofile import FirefoxProfile
# create new profile to pass to mozmill/mozrunner
profile = FirefoxProfile(addons=["adblock.xpi"])
Command Line Interface
----------------------
.. automodule:: mozprofile.cli
:members:
The profile to be operated on may be specified with the ``--profile``
switch. If a profile is not specified, one will be created in a
temporary directory which will be echoed to the terminal::
(mozmill)> mozprofile
/tmp/tmp4q1iEU.mozrunner
(mozmill)> ls /tmp/tmp4q1iEU.mozrunner
user.js
To run mozprofile from the command line enter:
``mozprofile --help`` for a list of options.
Permissions
-----------
.. automodule:: mozprofile.permissions
:members:
You can set permissions by creating a ``ServerLocations`` object that you pass
to the ``Profile`` constructor. Hosts can be added to it with
``add_host(host, port)``. ``port`` can be 0.
Preferences
-----------
.. automodule:: mozprofile.prefs
:members:
Preferences can be set in several ways:
- using the API: You can make a dictionary with the preferences and pass it to
the ``Profile`` constructor. You can also add more preferences with the
``Profile.set_preferences`` method.
- using a JSON blob file: ``mozprofile --preferences myprefs.json``
- using a ``.ini`` file: ``mozprofile --preferences myprefs.ini``
- via the command line: ``mozprofile --pref key:value --pref key:value [...]``
When setting preferences from an ``.ini`` file or the ``--pref`` switch,
the value will be interpolated as an integer or a boolean
(``true``/``false``) if possible.
Profile
--------------------
.. automodule:: mozprofile.profile
:members:
Resources
-----------
Other Mozilla programs offer additional and overlapping functionality
for profiles. There is also substantive documentation on profiles and
their management.
- ProfileManager_: XULRunner application for managing profiles. Has a GUI and CLI.
- python-profilemanager_: python CLI interface similar to ProfileManager
- profile documentation_
.. _Mozprofile: https://github.com/mozilla/mozbase/tree/master/mozprofile
.. _addons: https://developer.mozilla.org/en/addons
.. _preferences: https://developer.mozilla.org/En/A_Brief_Guide_to_Mozilla_Preferences
.. _mozprofile.profile: https://github.com/mozilla/mozbase/tree/master/mozprofile/mozprofile/profile.py
.. _AddonManager: https://github.com/mozilla/mozbase/tree/master/mozprofile/mozprofile/addons.py
.. _here: https://github.com/mozilla/mozbase/blob/master/mozprofile/mozprofile/permissions.py
.. _ProfileManager: https://developer.mozilla.org/en/Profile_Manager
.. _python-profilemanager: http://k0s.org/mozilla/hg/profilemanager/
.. _documentation: http://support.mozilla.com/en-US/kb/Profiles

View file

@ -0,0 +1,177 @@
:mod:`mozrunner` --- Manage remote and local gecko processes
============================================================
Mozrunner provides an API to manage a gecko-based application with an
arbitrary configuration profile. It currently supports local desktop
binaries such as Firefox and Thunderbird, as well as Firefox OS on
mobile devices and emulators.
Basic usage
-----------
The simplest way to use mozrunner, is to instantiate a runner, start it
and then wait for it to finish:
.. code-block:: python
from mozrunner import FirefoxRunner
binary = 'path/to/firefox/binary'
runner = FirefoxRunner(binary=binary)
runner.start()
runner.wait()
This automatically creates and uses a default mozprofile object. If you
wish to use a specialized or pre-existing profile, you can create a
:doc:`mozprofile <mozprofile>` object and pass it in:
.. code-block:: python
from mozprofile import FirefoxProfile
from mozrunner import FirefoxRunner
import os
binary = 'path/to/firefox/binary'
profile_path = 'path/to/profile'
if os.path.exists(profile_path):
profile = FirefoxProfile.clone(path_from=profile_path)
else:
profile = FirefoxProfile(profile=profile_path)
runner = FirefoxRunner(binary=binary, profile=profile)
runner.start()
runner.wait()
Handling output
---------------
By default, mozrunner dumps the output of the gecko process to standard output.
It is possible to add arbitrary output handlers by passing them in via the
`process_args` argument. Be careful, passing in a handler overrides the default
behaviour. So if you want to use a handler in addition to dumping to stdout, you
need to specify that explicitly. For example:
.. code-block:: python
from mozrunner import FirefoxRunner
def handle_output_line(line):
do_something(line)
binary = 'path/to/firefox/binary'
process_args = { 'stream': sys.stdout,
'processOutputLine': [handle_output_line] }
runner = FirefoxRunner(binary=binary, process_args=process_args)
Mozrunner uses :doc:`mozprocess <mozprocess>` to manage the underlying gecko
process and handle output. See the :doc:`mozprocess documentation <mozprocess>`
for all available arguments accepted by `process_args`.
Handling timeouts
-----------------
Sometimes gecko can hang, or maybe it is just taking too long. To handle this case you
may want to set a timeout. Mozrunner has two kinds of timeouts, the
traditional `timeout`, and the `outputTimeout`. These get passed into the
`runner.start()` method. Setting `timeout` will cause gecko to be killed after
the specified number of seconds, no matter what. Setting `outputTimeout` will cause
gecko to be killed after the specified number of seconds with no output. In both
cases the process handler's `onTimeout` callbacks will be triggered.
.. code-block:: python
from mozrunner import FirefoxRunner
def on_timeout():
print('timed out after 10 seconds with no output!')
binary = 'path/to/firefox/binary'
process_args = { 'onTimeout': on_timeout }
runner = FirefoxRunner(binary=binary, process_args=process_args)
runner.start(outputTimeout=10)
runner.wait()
The `runner.wait()` method also accepts a timeout argument. But unlike the arguments
to `runner.start()`, this one simply returns from the wait call and does not kill the
gecko process.
.. code-block:: python
runner.start(timeout=100)
waiting = 0
while runner.wait(timeout=1) is None:
waiting += 1
print("Been waiting for %d seconds so far.." % waiting)
assert waiting <= 100
Using a device runner
---------------------
The previous examples used a GeckoRuntimeRunner. If you want to control a
gecko process on a remote device, you need to use a DeviceRunner. The api is
nearly identical except you don't pass in a binary, instead you create a device
object. For example, for B2G (Firefox OS) emulators you might do:
.. code-block:: python
from mozrunner import B2GEmulatorRunner
b2g_home = 'path/to/B2G'
runner = B2GEmulatorRunner(arch='arm', b2g_home=b2g_home)
runner.start()
runner.wait()
Device runners have a `device` object. Remember that the gecko process runs on
the device. In the case of the emulator, it is possible to start the
device independently of the gecko process.
.. code-block:: python
runner.device.start() # launches the emulator (which also launches gecko)
runner.start() # stops the gecko process, installs the profile, restarts the gecko process
Runner API Documentation
------------------------
Application Runners
~~~~~~~~~~~~~~~~~~~
.. automodule:: mozrunner.runners
:members:
BaseRunner
~~~~~~~~~~
.. autoclass:: mozrunner.base.BaseRunner
:members:
GeckoRuntimeRunner
~~~~~~~~~~~~~~~~~~
.. autoclass:: mozrunner.base.GeckoRuntimeRunner
:show-inheritance:
:members:
DeviceRunner
~~~~~~~~~~~~
.. autoclass:: mozrunner.base.DeviceRunner
:show-inheritance:
:members:
Device API Documentation
------------------------
Generally using the device classes directly shouldn't be required, but in some
cases it may be desirable.
Device
~~~~~~
.. autoclass:: mozrunner.devices.Device
:members:
Emulator
~~~~~~~~
.. autoclass:: mozrunner.devices.Emulator
:show-inheritance:
:members:

View file

@ -0,0 +1,112 @@
:mod:`mozversion` --- Get application information
=================================================
`mozversion <https://github.com/mozilla/mozbase/tree/master/mozversion>`_
provides version information such as the application name and the changesets
that it has been built from. This is commonly used in reporting or for
conditional logic based on the application under test.
Note that mozversion can report the version of remote devices (e.g. Firefox OS)
but it requires the :mod:`mozdevice` dependency in that case. You can require it
along with mozversion by using the extra *device* dependency:
.. code-block:: bash
pip install mozversion[device]
API Usage
---------
.. automodule:: mozversion
:members: get_version
Examples
````````
Firefox::
import mozversion
version = mozversion.get_version(binary='/path/to/firefox-bin')
for (key, value) in sorted(version.items()):
if value:
print '%s: %s' % (key, value)
Firefox for Android::
version = mozversion.get_version(binary='path/to/firefox.apk')
print version['application_changeset'] # gets hg revision of build
FirefoxOS::
version = mozversion.get_version(sources='path/to/sources.xml', dm_type='adb')
print version['gaia_changeset'] # gets gaia git revision
Command Line Usage
------------------
mozversion comes with a command line program, ``mozversion`` which may be used to
get version information from an application.
Usage::
mozversion [options]
Options
```````
---binary
'''''''''
This is the path to the target application binary or .apk. If this is omitted
then the current directory is checked for the existance of an
application.ini file. If not found, then it is assumed the target
application is a remote Firefox OS instance.
---sources
''''''''''
The path to the sources.xml that accompanies the target application (Firefox OS
only). If this is omitted then the current directory is checked for the
existance of a sources.xml file.
Examples
````````
Firefox::
$ mozversion --binary=/path/to/firefox-bin
application_buildid: 20131205075310
application_changeset: 39faf812aaec
application_name: Firefox
application_repository: http://hg.mozilla.org/releases/mozilla-release
application_version: 26.0
platform_buildid: 20131205075310
platform_changeset: 39faf812aaec
platform_repository: http://hg.mozilla.org/releases/mozilla-release
Firefox for Android::
$ mozversion --binary=/path/to/firefox.apk
Firefox OS::
$ mozversion --sources=/path/to/sources.xml
application_buildid: 20140106040201
application_changeset: 14ac61461f2a
application_name: B2G
application_repository: http://hg.mozilla.org/mozilla-central
application_version: 29.0a1
build_changeset: 59605a7c026ff06cc1613af3938579b1dddc6cfe
device_firmware_date: 1380051975
device_firmware_version_incremental: 139
device_firmware_version_release: 4.0.4
device_id: msm7627a
gaia_changeset: 9a222ac02db176e47299bb37112ae40aeadbeca7
gaia_date: 1389005812
gecko_changeset: 3a2d8af198510726b063a217438fcf2591f4dfcf
platform_buildid: 20140106040201
platform_changeset: 14ac61461f2a
platform_repository: http://hg.mozilla.org/mozilla-central

View file

@ -0,0 +1 @@
marionette_client

View file

@ -0,0 +1,18 @@
Set up and running
------------------
Activities under this domain include installing the software, creating
a profile (a set of configuration settings), running a program in a
controlled environment such that it can be shut down safely, and
correctly handling the case where the system crashes.
.. toctree::
:maxdepth: 2
mozfile
mozinstall
mozprofile
mozprocess
mozrunner
mozcrash
mozdebug