Open Thanasis17m opened 1 year ago
Can you provide a repro/sample?
package app.cash.paparazzi.sample
import org.junit.Test
class UnsatisfiedLinkErrorTest {
@Test fun test() {
println(android.animation.ValueAnimator())
}
}
Any updates? We also has
'java.lang.String android.os.SystemProperties.native_get(java.lang.String, java.lang.String)'
java.lang.UnsatisfiedLinkError: 'java.lang.String android.os.SystemProperties.native_get(java.lang.String, java.lang.String)'
at android.os.SystemProperties.native_get(Native Method)
at android.os.SystemProperties.native_get(SystemProperties.java:103)
I assume such errors java.lang.UnsatisfiedLinkError
could be connected with jdk11 that is used in 1.3.1 - layoutlib-native-jdk11-2022.2.1-5128371-2.jar
.
The new version requirs JAVA 17, but contains lib from jdk11
@alex-tiurin's error can be reliably reproduced with
class SystemPropertiesTest {
@Test fun boom() {
println(Build.ID) // Somehow OK
println(SystemProperties.get("ro.build.id")) // Not OK
}
}
Here's the stacktrace I was seeing inside a real project:
java.lang.UnsatisfiedLinkError: 'java.lang.String android.os.SystemProperties.native_get(java.lang.String, java.lang.String)'
at android.os.SystemProperties.native_get(Native Method)
at android.os.SystemProperties.get(SystemProperties.java:165)
at android.os._Original_Build.getString(Build.java:1491)
at android.os._Original_Build.<clinit>(Build.java:56)
at android.view.InputEventConsistencyVerifier.<clinit>(InputEventConsistencyVerifier.java:34)
at android.view.View.<init>(View.java:5255)
Where a unit test case was eventually calling down to View(context)
constructor to create an empty view.
You can get the above test case (and the one from @TWiStErRob) to pass by instead using robolectric to run the test with @RunWith(RobolectricTestRunner::class)
.
So digging into this issue, the following test fails because Paparazzi junit rule is not correctly annotated. Since layoutlib hooks haven't been set up, the following exception occurs.
I have combined your example tests to reproduce and fix this issue.
package app.cash.paparazzi.sample
import android.os.Build
import android.os.SystemProperties
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import com.android.ide.common.rendering.api.SessionParams.RenderingMode.SHRINK
import org.junit.Rule
import org.junit.Test
class UnsatisfiedLinkErrorTest {
@Test fun test() {
println(Build.ID) // Somehow OK
println(SystemProperties.get("ro.build.id")) // Not OK
println(android.animation.ValueAnimator())
}
}
package app.cash.paparazzi.sample
import android.os.Build
import android.os.SystemProperties
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import com.android.ide.common.rendering.api.SessionParams.RenderingMode.SHRINK
import org.junit.Rule
import org.junit.Test
class UnsatisfiedLinkErrorTest {
@get:Rule
val paparazzi = Paparazzi(
deviceConfig = DeviceConfig.PIXEL_3,
renderingMode = SHRINK,
showSystemUi = false
)
@Test fun test() {
println(Build.ID) // Somehow OK
println(SystemProperties.get("ro.build.id")) // Not OK
println(android.animation.ValueAnimator())
}
}
The corrective action is to instantiate the Paparazzi class and add the correct junit @Rule
annotation to it.
@get:Rule val paparazzi = Paparazzi()
Yes, but I think the test is not meant to be a Paparazzi test. This implies that if a module has Paparazzi, it cannot have any other complex tests.
Yep we talked about it on slack a bit and it spawned this agp feature request
Researching this a bit, using a modified version of the sample @TWiStErRob provided here: https://github.com/cashapp/paparazzi/issues/988#issuecomment-1632130499
class UnsatisfiedLinkErrorTest {
@Test fun test() {
ValueAnimator::class.java.declaredFields.forEach {
println("declaredField: " + it.name)
}
android.animation.ValueAnimator()
}
}
If I remove all other tests and this line from sample/build.gradle:
apply plugin: 'app.cash.paparazzi'
I get:
declaredField: INFINITE
declaredField: RESTART
declaredField: REVERSE
However, if I reapply the Paparazzi plugin, I get many more fields:
declaredField: TAG
declaredField: DEBUG
declaredField: TRACE_ANIMATION_FRACTION
declaredField: sDurationScale
declaredField: sDurationScaleChangeListeners
....
It's TRACE_ANIMATION_FRACTION
which results in the exception referenced in this issue. I understand that LayoutLib would provide a new version of ValueAnimator which provides this field, but what I don't understand is why removing Paparazzi and therefore relying on the platform type (https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/animation/ValueAnimator.java;l=83?q=ValueAnimator) wouldn't still experience this issue...
@jrodbx I think the answer is that the android.jar that is by default on the classpath is only structurally equivalent to layoutlib/real Android. Therefore it does not contain any clinit code, not private stuff because those are not part of ABI.
Related to #1149
as @TWiStErRob mentions, the issue is Android.jar classes are using Paparazzi's layoutlib implementations which requires some setup to make calls the the clinit code.
Description We have a project with multiple modules. In some of them, there are viewModel classes, in which we use the
android.animation.ValueAnimator
class to create and handle a timer.When we add to one of these modules, the paparazzi dependency, then the unit tests that test any viewModel method using the
ValueAnimator
class fail.This
UnsatisfiedLinkError
is reported:More specifically, the error is reported in the viewModel, when we call this method
ValueAnimator.ofInt(PROGRESS_MIN, PROGRESS_MAX)
We also tried adding the paparazzi dependency to other modules, where we use
ValueAnimator
similarly in viewModels and the same error was reported in the relevant unit tests.So, for some reason, when adding paparazzi dependency to a module, then all unit tests that use
ValueAnimator
in the tested method, fail.Steps to Reproduce To reproduce this, just follow the above steps.
ValueAnimator
method.UnsatisfiedLinkError
Expected behavior What we expected was, that adding the paparazzi dependency, wouldn't affect the use of the
ValueAnimator
class.Additional information: