paparazzi
paparazzi copied to clipboard
Duplicate field name
First of all, thank you for taking the time to have a look a this 🙏🏼
Description According to the issue, when I execute the Paparazzi tasks every test fails with the same exception.
java.lang.ClassFormatError: Duplicate field name "AddContentButton_android_text" with signature "I" in class file com/jobandtalent/components/R$styleable
at java.base/java.lang.Class.getDeclaredClasses0(Native Method)
at java.base/java.lang.Class.getDeclaredClasses(Class.java:2196)
at app.cash.paparazzi.internal.PaparazziCallback.initResources(PaparazziCallback.kt:63)
at app.cash.paparazzi.Paparazzi.prepare(Paparazzi.kt:152)
at app.cash.paparazzi.Paparazzi$apply$statement$1.evaluate(Paparazzi.kt:122)
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:110)
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:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
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 com.sun.proxy.$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:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
If I look for that attribute, we can find the next:
<declare-styleable name="AddContentButton">
<attr name="android:text" />
</declare-styleable>
as soon as I remove the android namespace it starts working properly.
Just to give more context, we have an Android library module that contains some design system components. They're a mix of Composables and custom views, that's why we have custom attributes.
Any clue?
Additional information:
- Paparazzi Version: 1.0.0
- OS: Macos Monterrey
- Compile SDK:
- Gradle Version: 7.4.2
- Android Gradle Plugin Version: 7.2.1
@costular thanks for reporting! Could you take a look on paparazzi-gradle-plugin/src/test/projects
and see if you can provide a testing sample that mimics your issue?
@costular to help us effectively troubleshoot, we'll need a sample repro project. is there anything you can share either here or via DM/email?
Hey guys, I'll try to find a shareable code with the reproducible bug in order to help you out as soon as possible!
@costular have you had a chance to reproduce in something sharable?
Closing since no repro
Hi @jrodbx @fcduarte! 👋
We're also experiencing this issue at my company. I threw together a branch which reproduces the issue in the sample app in this repo:
https://github.com/cashapp/paparazzi/compare/master...martinpdd8:paparazzi:paulm/example-duplicate-field-name-error?expand=1
This yields the exception:
Duplicate field name "MyButton_android_background" with signature "I" in class file app/cash/paparazzi/sample/R$styleable
java.lang.ClassFormatError: Duplicate field name "MyButton_android_background" with signature "I" in class file app/cash/paparazzi/sample/R$styleable
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(Unknown Source)
at java.base/java.security.SecureClassLoader.defineClass(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(Unknown Source)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at java.base/java.lang.Class.getDeclaredClasses0(Native Method)
at java.base/java.lang.Class.getDeclaredClasses(Unknown Source)
at app.cash.paparazzi.internal.PaparazziCallback.initResources(PaparazziCallback.kt:64)
at app.cash.paparazzi.Paparazzi.prepare(Paparazzi.kt:151)
at app.cash.paparazzi.Paparazzi$apply$statement$1.evaluate(Paparazzi.kt:121)
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:110)
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:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
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:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
We would love to adopt paparazzi but this issue is currently blocking us. Should I open a new issue or is it possible to re-open this one?
Thanks for a really cool library by the way!
I'm taking a look into this issue. Using your provided sample, I see that the resource for MyButton is in-fact duplicated in the R.jar file that is generated in build/intermediates/compile_and_runtime_not_namespaced_r_class_jar/debugUnitTest/R.jar
public final class R {
private R() {
}
public static final class color {
public static int bolt;
public static int cameraBody;
public static int keypadDarkGrey;
public static int keypadGreen;
public static int launchBackground;
public static int vector_tint_color;
public static int vector_tint_theme_color;
private color() {
}
}
......
public static final class styleable {
public static int[] MyButton = new int[]{16842964, 16842964};
public static int MyButton_android_background;
public static int MyButton_android_background;
private styleable() {
}
}
}
Strange because in build/intermediates/compile_r_class_jar/debug/R.jar
does not have the duplicate entry.
Seems like it's an Android Gradle Plugin bug. I logged an issue here in issue tracker: https://issuetracker.google.com/issues/265713285
I also created a separate repo without paparazzi artifacts to verify the issue still occurs. https://github.com/geoff-powell/SampleUnitTestRBug
Confirmed:
$ javap -classpath sample/build/intermediates/compile_and_runtime_not_namespaced_r_class_jar/debugUnitTest/R.jar app.cash.paparazzi.sample.R\$styleable
public final class app.cash.paparazzi.sample.R$styleable {
public static int[] MyButton;
public static int MyButton_android_background;
public static int MyButton_android_background;
public static {};
}
$ javap -classpath sample/build/intermediates/compile_r_class_jar/debug/R.jar app.cash.paparazzi.sample.R\$styleable
public final class app.cash.paparazzi.sample.R$styleable {
public static int[] MyButton;
public static int MyButton_android_background;
public static {};
}
While this might be an AGP bug, we also have custom styleables in CashApp and this configuration seems to be the reason why we avoid this issue:
// in your views/composable module's build script
android {
...
testOptions {
unitTests {
includeAndroidResources true
}
}
}
I've confirmed that applying this config to @martinpdd8's repro resolves the issue.
@costular @martinpdd8 Can you try adding this snippet to your respective repos and confirm this issue as fixed? I'll leave this open and move to 1.3 milestone to unblock the 1.2 release.
Ok, closing this as resolved per the previous comment. Please file another issue (and ideally reference this one) if this has not been fixed!
Did anyone file an issue on AGP?
Looks like Geoff did: https://github.com/cashapp/paparazzi/issues/481#issuecomment-1385769818
Ah my bad, missed that link