Commit 73c7980c authored by James Willcox's avatar James Willcox
Browse files

Bug 1536044 - Fully disable jacoco builds for Android r=agi

Differential Revision: https://phabricator.services.mozilla.com/D25216

--HG--
extra : moz-landing-system : lando
parent c8617bd9
Loading
Loading
Loading
Loading
+0 −48
Original line number Diff line number Diff line
@@ -514,51 +514,3 @@ android.applicationVariants.all { variant ->
    tasks["compile${productFlavor}${buildType}UnitTestSources"].dependsOn(tasks["merge${productFlavor}${buildType}Assets"])
}
apply from: "${topsrcdir}/mobile/android/gradle/jacoco_dependencies.gradle"
if (project.hasProperty('enable_code_coverage')) {
    apply from: "${topsrcdir}/mobile/android/gradle/jacoco_for_junit.gradle"
}


// Set up code coverage for tests on emulators.
if (mozconfig.substs.MOZ_JAVA_CODE_COVERAGE) {
    android {
        jacoco {
            version = "$jacoco_version"
        }
        buildTypes {
            debug {
                testCoverageEnabled true
            }
        }
    }

    dependencies {
        // This is required both in the instrumented application classes and the test classes,
        // so `api` has to be used instead of `androidTestImplementation`.
        api "org.jacoco:org.jacoco.agent:$jacoco_version:runtime"
    }

    // Generate tasks to archive compiled classfiles for later use with JaCoCo report generation.
    // One of these tasks is used by `mach android archive-coverage-artifacts`.
    android.applicationVariants.all { variant ->
        def name = variant.name
        def compileTask = tasks.getByName("compile${name.capitalize()}JavaWithJavac")
        task "archiveClassfiles${name.capitalize()}"(type: Zip, dependsOn: compileTask) {
            description = "Archive compiled classfiles for $name in order to export them as code coverage artifacts."
            def fileFilter = ['**/androidTest/**',
                              '**/test/**',
                              '**/R.class',
                              '**/R$*.class',
                              '**/BuildConfig.*',
                              '**/Manifest*.*',
                              '**/*Test*.*',
                              'android/**/*.*']
            from fileTree(dir: compileTask.destinationDir, excludes: fileFilter)
            destinationDir = file("${buildDir}/coverage")
            // Note: This task assumes only one variant of archiveClassfiles* will be used.
            // Running multiple variants of this task will overwrite the output archive.
            archiveName = 'target.app_classfiles.zip'
        }
    }
}
+0 −3
Original line number Diff line number Diff line
@@ -33,9 +33,6 @@ ac_add_options --target=arm-linux-androideabi

ac_add_options --with-branding=mobile/android/branding/nightly

# Pull code coverage dependencies too.
ac_add_options --enable-java-coverage

export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
export MOZ_ANDROID_MMA=1
+0 −92
Original line number Diff line number Diff line
@@ -17,33 +17,9 @@ Collecting and exporting code coverage information
Relevant tools and libraries
----------------------------

JaCoCo_ is the tool used to gather code coverage data. JaCoCo uses class file
instrumentation to record execution coverage data. It has two operating modes:

- `online instrumentation`_: Class files are instrumented on-the-fly using a so
  called Java agent. The JaCoCo agent collects execution information and dumps
  it on request or when the JVM exits. This method is used for test suites
  which run on the JVM (generally, `*UnitTest` Gradle tasks).
- `offline instrumentation`_: At runtime the pre-instrumented classes needs be
  on the classpath instead of the original classes. In addition,
  `jacocoagent.jar` must be put on the classpath. This method is used for test
  suites with run on the Android emulator (generally, `*AndroidTest` Gradle
  tasks, including `robocop`).

JaCoCo is integrated with Gradle in two ways: a Gradle plugin (activated in the
``build.gradle`` file as a top-level ``apply plugin: 'jacoco'``), and an
Android-specific Gradle plugin, activated with ``android { buildTypes { debug {
testCoverageEnabled true } } }``. These two methods of activating JaCoCo have a
different syntax of choosing the JaCoCo tool version, and both should be
configured to use the same version. See the
``mobile/android/geckoview/build.gradle`` file for example usage.

grcov_ is a tool implemented in Rust that transforms code coverage reports
between formats. Among others, it supports reading JaCoCo XML reports.

.. _JaCoCo: https://www.eclemma.org/jacoco/
.. _online instrumentation: https://www.jacoco.org/jacoco/trunk/doc/agent.html
.. _offline instrumentation: https://www.jacoco.org/jacoco/trunk/doc/offline.html
.. _grcov: https://github.com/mozilla/grcov/

Generating the coverage report artifacts
@@ -63,71 +39,3 @@ job. It is also responsible for running ``grcov`` after the tests are finished,
to convert and merge the coverage reports.

.. _ActiveData: https://wiki.mozilla.org/EngineeringProductivity/Projects/ActiveData

Code coverage for android-test
===============================

The `android-test` suite is a JUnit test suite that runs locally on the
host's JVM. It can be run with ``mach android test``. The test suite is
implemented as a build task, defined at
``taskcluster/ci/build/android-stuff.yml``.

To collect code coverage from this suite, a duplicate build task is defined,
called `android-test-ccov`. It can be run with ``mach android test-ccov``.

The mach subcommand is responsible for downloading and running `grcov`,
instead of the ``CodeCoverageMixin`` class. This is because the
`android-test-ccov` task is a build task (not a test task), so it doesn't use
mozharness to run the tests.


Code coverage for geckoview-junit
==================================

The geckoview-junit_ tests are on-device Android JUnit tests written for
GeckoView_. The tests are implemented with ``mochitest``. The automation
entry point is ``testing/mozharness/scripts/android_emulator_unittest.py``,
which then calls ``testing/mochitest/runjunit.py``. This is an out-of-tree
task, so a source tree clone is unavailable.

To generate the coverage report, we need three things:

- The classfiles before instrumentation. These are archived as a public
  artifact during build time, and downloaded on the test machine during testing
  time;
- The coverage.ec file with coverage counters. This is generated while running
  the tests on the emulator, then downloaded with ``adb pull``;
- ``jacoco-cli``, a command-line package JaCoCo component that takes the
  classfiles and the coverage counters as input and generates XML reports as
  output.

The ``mach android archive-coverage-artifacts`` command archives the
class files and exports the ``jacoco-cli`` jar file after the build is done.
These files are later saved as public artifacts of the build.

To enable offline instrumentation for the test suites, the mozconfig flag
``--enable-java-coverage`` should be set. When the flag is checked both during
build and test time. During test time, the flag instructs ``CodeCoverageMixin``
to download the coverage artifacts from the build task before the tests run,
and generate and export the reports after testing is finished. The flag also
instructs the ``runjunit.py`` script to insert the arguments ``-e coverage
true`` to ``am instrument``.

.. _GeckoView: https://wiki.mozilla.org/Mobile/GeckoView
.. _geckoview-junit: https://developer.mozilla.org/en-US/docs/Mozilla/Geckoview-Junit_Tests


Code coverage for Robocop UI tests
==================================

Robocop_ provides UI-level testing for Fennec. The tests use the same
automation scripts as geckoview-junit, only differing by the fact that they are
run by ``runrobocop.py`` instead of ``runjunit.py``.

The only notable difference from the geckoview-junit tests is that robocop
tests are run with one ``am instrument`` call per test class. This means that
one ``robocop-coverage-<test name>.ec`` file will be generated for each test
class. After the tests finish, ``jacoco-cli`` will be called on all the
resulting coverage data files.

.. _Robocop: https://wiki.mozilla.org/Auto-tools/Projects/Robocop
+0 −68
Original line number Diff line number Diff line
@@ -449,74 +449,6 @@ task("generateSDKBindings", type: JavaExec) {
    dependsOn project(':annotations').jar
}

apply from: "${topsrcdir}/mobile/android/gradle/jacoco_dependencies.gradle"
if (project.hasProperty('enable_code_coverage')) {
    apply from: "${topsrcdir}/mobile/android/gradle/jacoco_for_junit.gradle"
}

// Set up code coverage for tests on emulators.
if (mozconfig.substs.MOZ_JAVA_CODE_COVERAGE) {
    android {
        jacoco {
            version = "$jacoco_version"
        }
        buildTypes {
            debug {
                testCoverageEnabled true
            }
        }
    }

    configurations {
        // This configuration is used for dependencies that are not needed at compilation or
        // runtime, but need to be exported as artifacts of the build for usage on the testing
        // machines.
        coverageDependency
    }

    dependencies {
        // This is required both in the instrumented application classes and the test classes,
        // so `api` has to be used instead of `androidTestImplementation`.
        api "org.jacoco:org.jacoco.agent:$jacoco_version:runtime"

        coverageDependency ("org.jacoco:org.jacoco.cli:$jacoco_version:nodeps") {
            exclude group: 'org.ow2.asm', module: '*'
        }
    }

    // This task is used by `mach android archive-coverage-artifacts`.
    task copyCoverageDependencies(type: Copy) {
        from(configurations.coverageDependency) {
            include 'org.jacoco.cli-*-nodeps.jar'
            rename { _ -> 'target.jacoco-cli.jar' }
        }
        into "$buildDir/coverage"
    }

    // Generate tasks to archive compiled classfiles for later use with JaCoCo report generation.
    // One of these tasks is used by `mach android archive-coverage-artifacts`.
    android.libraryVariants.all { variant ->
        def name = variant.name
        def compileTask = tasks.getByName("compile${name.capitalize()}JavaWithJavac")
        task "archiveClassfiles${name.capitalize()}"(type: Zip, dependsOn: compileTask) {
            description = "Archive compiled classfiles for $name in order to export them as code coverage artifacts."
            def fileFilter = ['**/androidTest/**',
                              '**/test/**',
                              '**/R.class',
                              '**/R$*.class',
                              '**/BuildConfig.*',
                              '**/Manifest*.*',
                              '**/*Test*.*',
                              'android/**/*.*']
            from fileTree(dir: compileTask.destinationDir, excludes: fileFilter)
            destinationDir = file("${buildDir}/coverage")
            // Note: This task assumes only one variant of archiveClassfiles* will be used.
            // Running multiple variants of this task will overwrite the output archive.
            archiveName = 'target.geckoview_classfiles.zip'
        }
    }
}

apply plugin: 'org.mozilla.apilint'

apiLint {
+0 −9
Original line number Diff line number Diff line
@@ -205,16 +205,7 @@ def gradle_android_test_tasks(build_config):
    ]


@dependable
def gradle_android_test_ccov_report_tasks():
    '''Additional gradle tasks run by |mach android test-ccov|.'''
    return [
        'app:jacocoTestReport',
        'geckoview:jacocoTestReport',
    ]

set_config('GRADLE_ANDROID_TEST_TASKS', gradle_android_test_tasks)
set_config('GRADLE_ANDROID_TEST_CCOV_REPORT_TASKS', gradle_android_test_ccov_report_tasks)


@depends(gradle_android_build_config)
Loading