Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.UnsatisfiedLinkError with Paparazzi tests for compose UI #1818

Open
Ruthvik36 opened this issue Jan 30, 2025 · 0 comments
Open

java.lang.UnsatisfiedLinkError with Paparazzi tests for compose UI #1818

Ruthvik36 opened this issue Jan 30, 2025 · 0 comments
Labels
bug Something isn't working

Comments

@Ruthvik36
Copy link

Ruthvik36 commented Jan 30, 2025

Description
Hi, we are using Paparazzi with Reflections API to perform snapshots tests for UI built in compose. We are using github actions for CI/CD. It was working well. We started getting the following error

com.tesco.mobile.PaparazziTest > generateSnapshots FAILED
    java.lang.UnsatisfiedLinkError at PaparazziTest.kt:49

Copying the error log

java.lang.UnsatisfiedLinkError: /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/17.0.14-7/x64/lib/libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory at java.base/jdk.internal.loader.NativeLibraries.load(Native Method) at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174) at java.base/jdk.internal.loader.NativeLibraries.findFromPaths(NativeLibraries.java:315) at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:285) at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2403) at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:818) at java.base/java.lang.System.loadLibrary(System.java:2006) at java.desktop/sun.font.FontManagerNativeLibrary$1.run(FontManagerNativeLibrary.java:58) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at java.desktop/sun.font.FontManagerNativeLibrary.<clinit>(FontManagerNativeLibrary.java:33) at java.desktop/sun.font.SunFontManager$1.run(SunFontManager.java:275) at java.desktop/sun.font.SunFontManager$1.run(SunFontManager.java:273) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at java.desktop/sun.font.SunFontManager.initStatic(SunFontManager.java:273) at java.desktop/sun.font.SunFontManager.<clinit>(SunFontManager.java:268) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:467) at java.desktop/sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83) at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) at java.desktop/sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:75) at java.desktop/java.awt.Font.getFont2D(Font.java:526) at java.desktop/java.awt.Font$FontAccessImpl.getFont2D(Font.java:265) at java.desktop/sun.font.FontUtilities.getFont2D(FontUtilities.java:151) at java.desktop/sun.java2d.SunGraphics2D.checkFontInfo(SunGraphics2D.java:672) at java.desktop/sun.java2d.SunGraphics2D.getFontInfo(SunGraphics2D.java:838) at java.desktop/sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:46) at java.desktop/sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:2938) at app.cash.paparazzi.internal.ImageUtils.assertImageSimilar(ImageUtils.kt:195) at app.cash.paparazzi.SnapshotVerifier$newFrameHandler$1.handle(SnapshotVerifier.kt:50) at app.cash.paparazzi.Paparazzi$takeSnapshots$1$2.invoke(Paparazzi.kt:313) at app.cash.paparazzi.Paparazzi$takeSnapshots$1$2.invoke(Paparazzi.kt:306) at app.cash.paparazzi.Paparazzi.withTime(Paparazzi.kt:348) at app.cash.paparazzi.Paparazzi.takeSnapshots(Paparazzi.kt:306) at app.cash.paparazzi.Paparazzi.snapshot(Paparazzi.kt:200) at app.cash.paparazzi.Paparazzi.snapshot$default(Paparazzi.kt:199) at app.cash.paparazzi.Paparazzi.snapshot(Paparazzi.kt:195) at com.tesco.mobile.PaparazziTest.snapshot(PaparazziTest.kt:49) at com.tesco.mobile.PaparazziTest.generateSnapshots(PaparazziTest.kt:39) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:569) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at app.cash.paparazzi.Paparazzi$apply$statement$1.evaluate(Paparazzi.kt:118) at app.cash.paparazzi.agent.AgentTestRule$apply$1.evaluate(AgentTestRule.kt:17) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) at org.junit.runners.ParentRunner.run(ParentRunner.java:413) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:108) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40) at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:569) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94) at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176) at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100) at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60) at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113) at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65) at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69) at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

Paparazzi Test class

`class PaparazziTest {

@get:Rule
val paparazzi: Paparazzi = Paparazzi()

@Test
fun generateSnapshots() {
    val reflections =
        Reflections("xxx.zpreview", Scanners.MethodsAnnotated)
    val methods = reflections.getMethodsAnnotatedWith(Preview::class.java)

    val composeProxy = ComposeProxy()
    for (method in methods) {
        val name = "${method.declaringClass.simpleName}_${method.name}"

        try {
            snapshot(name = name) {
                composeProxy.wrappedInstance(method).GenerateSnapshot()
            }
        } catch (e: Throwable) {
            throw RuntimeException("Error generating snapshot $name", e)
        }
    }
}

private fun snapshot(name: String, composable: @Composable () -> Unit) {
    paparazzi.snapshot(name) {
        Box {
            composable()
        }
    }
}

private interface ComposeProxyInterface {

    @Composable
    fun GenerateSnapshot()
}

@Suppress("EmptyFunctionBlock")
private class ComposeProxy : ComposeProxyInterface {
    @Composable
    override fun GenerateSnapshot() {
    }

    fun wrappedInstance(composableFunction: Method): ComposeProxyInterface {
        val proxyClass = Proxy.getProxyClass(
            ComposeProxy::class.java.classLoader,
            ComposeProxyInterface::class.java
        )

        val invocationHandler = InvocationHandler { _, _, args: Array<out Any>? ->
            composableFunction.invoke(null, *args!!)
        }

        return proxyClass
            .getConstructor(InvocationHandler::class.java)
            .newInstance(invocationHandler) as ComposeProxyInterface
    }
}

}`

Adding the yml file
`name: PR

on:
pull_request:
branches:
- 'dds-release/v*'

jobs:
snapshottests:
name: Snapshot and Unit testing
runs-on: owd-enterprise-runners
permissions:
contents: read
packages: write
steps:
- name: Setup actions.
uses: actions/checkout@v4

  - name: set up JDK 17
    uses: actions/setup-java@v4
    with:
      java-version: '17'
      distribution: 'temurin'
      
  - name: Setup Android SDK
    uses: android-actions/setup-android@07976c6290703d34c16d382cb36445f98bb43b1f

  - name: verify snapshots
    run: ./gradlew clean xxx:verifyPaparazziDebug

`

Can you please help me in fixing this error ?.

Additional information:

  • Paparazzi Version: 1.2.0
  • OS:
  • Compile SDK:
  • Gradle Version: 8.0
  • Android Gradle Plugin Version: 8.1.1

Screenshots
If applicable, add screenshots to help explain your problem.

@Ruthvik36 Ruthvik36 added the bug Something isn't working label Jan 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant