Hi, I’m suffering permission denial issue when running jacoco test report task, using Android Studio.
I work on device manufacturer, so I have ongoing device can be rooted.
API level is 29
I configured jacoco with instrumented test to get coverage report.
In my build.gradle (app), I got
apply plugin: 'jacoco'
jacoco {
reportsDir = file("${buildDir}/reports")
}
task coverageReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {
group = "Reporting"
description = "Generate Jacoco coverage reports"
def coverageSourceDirs = ['src/main']
getClassDirectories().setFrom (fileTree(
dir: "${buildDir}/intermediates/classes/dev/debug",
excludes: ['**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'com/android/**/*.class']
))
getSourceDirectories().setFrom ( files(coverageSourceDirs) )
getExecutionData().setFrom (files("${buildDir}/jacoco/testDebugUnitTest.exec"))
reports {
xml.enabled = true
html.enabled = true
}
}
And in android block,
android {
buildTypes {
debug {
testCoverageEnabled true
}
}
}
When I run this command, I got internal error that indicates coverage.ec file generation failed due to permission denial from target device.
Run command
gradlew -i createDebugAndroidTestCoverageReport
In gradle console,
It start am instrument with below command and finished succesfully:
[RemoteAndroidTest]: Running am instrument -w -r -e coverageFile /data/data/PACKAGENAME/coverage.ec -e coverage true PACKAGENAME/androidx.test.runner.AndroidJUnitRunner on DEVICENAME
Starting 224 tests on DEVICENAME
...
But coverage.ec file from target device is zero-sized file.
when I start am instrument by manually:
INSTRUMENTATION_RESULT: stream=
Time: 10.697
OK (224 tests)
Error: Failed to generate Emma/JaCoCo coverage.
INSTRUMENTATION_CODE: -1
adb logcat says:
10-07 04:16:56.380 4237 4263 E CoverageListener: Failed to generate Emma/JaCoCo coverage.
10-07 04:16:56.380 4237 4263 E CoverageListener: java.lang.reflect.InvocationTargetException
10-07 04:16:56.380 4237 4263 E CoverageListener: at java.lang.reflect.Method.invoke(Native Method)
10-07 04:16:56.380 4237 4263 E CoverageListener: at androidx.test.internal.runner.listener.CoverageListener.generateCoverageReport(CoverageListener.java:101)
10-07 04:16:56.380 4237 4263 E CoverageListener: at androidx.test.internal.runner.listener.CoverageListener.instrumentationRunFinished(CoverageListener.java:70)
10-07 04:16:56.380 4237 4263 E CoverageListener: at androidx.test.internal.runner.TestExecutor.reportRunEnded(TestExecutor.java:92)
10-07 04:16:56.380 4237 4263 E CoverageListener: at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:65)
10-07 04:16:56.380 4237 4263 E CoverageListener: at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392)
10-07 04:16:56.380 4237 4263 E CoverageListener: at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2196)
10-07 04:16:56.380 4237 4263 E CoverageListener: Caused by: java.io.FileNotFoundException: /data/data/PACKAGE NAME/coverage.ec: open failed: EACCES (Permission denied)
Checked user name of process:
shell 29622 980 5 05:15:33 pts/0 00:00:00 app_process /system/bin com.android.commands.am.Am instrument -w -r -e coverageFile /data/data/PACKAGENAME/coverage.ec -e coverage true PACKAGENAME/androidx.test.runner.AndroidJUnitRunner
It runs with “shell” user, which can not access /data/data/PACKAGENAME/ directory…
drwx------ 4 system system 4096 2020-10-07 05:15 PACKAGENAME
But regardless user, it fails with permission denial.
Tried with “adb root” but nothing changes.
root 32621 32130 15 05:17:49 pts/1 00:00:00 app_process /system/bin com.android.commands.am.Am instrument -w -r -e coverageFile /data/data/PACKAGENAME/coverage.ec -e coverage true PACKAGENAME/androidx.test.runner.AndroidJUnitRunner
in Manifest, I have system uid
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:sharedUserId="android.uid.system" ...
In conclusion, it is caused because:
- JUnit runner runs with “shell” or “root” user, but directory is only opened to user “system”
So, I’m wondering if there’s any way to configure “coverageFile” argument when task runs “am instrument”.
Any tips or workaround trick will be very appreciated.
Thanks…