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

Paparazzi does not follow TestTaskReports configuration #1825

Open
SimonMarquis opened this issue Feb 6, 2025 · 4 comments
Open

Paparazzi does not follow TestTaskReports configuration #1825

SimonMarquis opened this issue Feb 6, 2025 · 4 comments
Labels
enhancement New feature or request

Comments

@SimonMarquis
Copy link
Contributor

We are trying to disable the HTML test report that is generated whenever Paparazzi runs.
It is currently not very helpful (for us) and it is unfortunately the source of OOMs (unless we crank up the allowed max heap size) when it tries to write content of the .temp.png file to build/reports/paparazzi/*.

Stacktrace…

Current thread (0x0000000134009200):  JavaThread "Test worker"        [_thread_in_vm, id=5891, stack(0x000000016b380000,0x000000016b583000) (2060K)]

Stack: [0x000000016b380000,0x000000016b583000],  sp=0x000000016b580780,  free space=2049k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.dylib+0xa731a4]  VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x53c  (debug.cpp:271)
V  [libjvm.dylib+0x2e34c0]  DebuggingContext::~DebuggingContext()+0x0
V  [libjvm.dylib+0x2e3920]  report_java_out_of_memory(char const*)+0xf8
V  [libjvm.dylib+0x7a1908]  MemAllocator::Allocation::check_out_of_memory()+0x90
V  [libjvm.dylib+0x7a24f4]  MemAllocator::allocate() const+0xf4
V  [libjvm.dylib+0x3b311c]  CollectedHeap::array_allocate(Klass*, unsigned long, int, bool, JavaThread*)+0x34
V  [libjvm.dylib+0x8b5d98]  OptoRuntime::new_array_C(Klass*, int, JavaThread*)+0x60
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
v  ~RuntimeStub::_new_array_Java 0x000000014f649fb8
J 17602 c2 okio.SegmentPool.take()Lokio/Segment; (71 bytes) @ 0x000000015024d7e0 [0x000000015024d300+0x00000000000004e0]
J 17714% c2 app.cash.paparazzi.internal.apng.ApngWriter.encodeBytes(Ljava/awt/image/BufferedImage;Lokio/BufferedSink;Ljava/awt/Rectangle;)V (174 bytes) @ 0x000000014ffb343c [0x000000014ffb2bc0+0x000000000000087c]
j  app.cash.paparazzi.internal.apng.ApngWriter.writeIDAT$lambda$5(Lapp/cash/paparazzi/internal/apng/ApngWriter;Ljava/awt/image/BufferedImage;Lokio/Buffer;)Lkotlin/Unit;+36
j  app.cash.paparazzi.internal.apng.ApngWriter$$Lambda+0x00000070014b5800.invoke(Ljava/lang/Object;)Ljava/lang/Object;+12
j  app.cash.paparazzi.internal.apng.ApngWriter.writeChunk(Lokio/BufferedSink;Lapp/cash/paparazzi/internal/apng/PngConstants$Header;Lkotlin/jvm/functions/Function1;)V+12
j  app.cash.paparazzi.internal.apng.ApngWriter.writeIDAT(Lokio/BufferedSink;Ljava/awt/image/BufferedImage;)V+12
j  app.cash.paparazzi.internal.apng.ApngWriter.close()V+144
j  app.cash.paparazzi.HtmlReportWriter$newFrameHandler$1.close()V+17
J 15087 c1 kotlin.io.CloseableKt.closeFinally(Ljava/io/Closeable;Ljava/lang/Throwable;)V (35 bytes) @ 0x00000001486d3708 [0x00000001486d3680+0x0000000000000088]
j  app.cash.paparazzi.Paparazzi.snapshot(Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V+67

Gradle Test tasks have some properties to disable reports. And it would be great if Paparazzi would use this option, or offer a similar solution to disable its HTML report:

android {
    testOptions.unitTests.all {
       it.reports.html.required = false
    }
}

As an example, in one of our modules, we are generating 2 screenshots, and we had to bump the heap size to ~1G to not trigger the OOM.
And the files size are not that large (although the resolution of the first image is quite big):

01847473a905521a29a26652f52dde5897c97a76.png: 593 KB
PNG image data, 1440 x 14012, 8-bit/color RGBA, non-interlaced
611007f511d6aeb42111045ee6618ddf65f4b314.png: 190 KB
PNG image data, 1440 x 3120, 8-bit/color RGBA, non-interlaced
@SimonMarquis SimonMarquis added the enhancement New feature or request label Feb 6, 2025
@geoff-powell
Copy link
Collaborator

Yep, 1G heap probably isn't enough to snapshot a view that large without resizing. Also this looks like you are generating a video using paparazzi.gif as I see app.cash.paparazzi.internal.apng.ApngWriter in the stacktrace provided.
PNG image data, 1440 x 14012, 8-bit/color RGBA, non-interlaced

Paparazzi html reports are in addition to junit test reports.

As I am not sure that field should disabled reports for paparazzi as well junit repots, I agree that providing a way to disable the html report gen would be helpful.

@SimonMarquis
Copy link
Contributor Author

1G heap probably isn't enough to snapshot a view that large without resizing

Is this because the intermediate representation of the image data is an uncompressed bitmap? ((8+8+8+8) * 1440 * 14012 is still only ~80MB).

Also this looks like you are generating a video using paparazzi.gif

No we are not 😅 ApngWriter is used for both images and videos:

val snapshotDir = if (fps == -1) imagesDirectory else videosDirectory
val goldenDir = if (fps == -1) goldenImagesDirectory else goldenVideosDirectory
val hashes = mutableListOf<String>()
val snapshotTmpFile = File(snapshotDir, snapshot.toFileName(extension = "temp.png"))
val writer = ApngWriter(snapshotTmpFile.path.toPath(), fps)

@geoff-powell
Copy link
Collaborator

Gotcha, yep I didn't have a chance to look at the code but that makes sense it uses the APNG writer. 😆

Is this because the intermediate representation of the image data is an uncompressed bitmap? ((8+8+8+8) * 1440 * 14012 is still only ~80MB).

Potentially, I would need to dig in.

Could you provide a project reproducing this issue. It would be very helpful 🙏🏽

@SimonMarquis
Copy link
Contributor Author

@geoff-powell here is a reproduced:

You can run the following test:

gradlew :paparazzi-gradle-plugin:test --tests app.cash.paparazzi.gradle.PaparazziPluginTest.verifyMemory --rerun

The recordPaparazziDebug task will fail with the OOM, while the verifyPaparazziDebug will succeed. You can switch the behavior in the PaparazziPluginTest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants