JetBrains / skiko

Kotlin Multiplatform bindings to Skia
Apache License 2.0
1.82k stars 118 forks source link

Skiko tries to write a file to a directory that does not exist when run by Bazel on Linux #885

Closed juancnuno closed 7 months ago

juancnuno commented 7 months ago

One of our Compose tests failed with the following stack trace on Linux

$ bazel test --test_output=errors //tools/adt/idea/adt-ui-compose:intellij.android.adt.ui.compose_tests
...
There was 1 failure:
1) sampleComposeComponentTest(sample.SampleComposeComponentTest)
java.lang.ExceptionInInitializerError
    at androidx.compose.ui.test.SkikoComposeUiTest.<init>(ComposeUiTest.skikoMain.kt:130)
    at androidx.compose.ui.test.SkikoComposeUiTest.<init>(ComposeUiTest.skikoMain.kt:90)
    at androidx.compose.ui.test.junit4.DesktopComposeTestRule.<init>(DesktopComposeTestRule.desktop.kt:54)
    at androidx.compose.ui.test.junit4.DesktopComposeTestRule_desktopKt.createComposeRule(DesktopComposeTestRule.desktop.kt:41)
    at sample.SampleComposeComponentTest.<init>(SampleComposeComponentTest.kt:38)
    ... 36 trimmed
Caused by: java.io.IOException: Permission denied
    at java.base/java.io.UnixFileSystem.createFileExclusively(Native Method)
    at java.base/java.io.File.createTempFile(File.java:2170)
    at org.jetbrains.skiko.Library.unpackIfNeeded(Library.kt:37)
    at org.jetbrains.skiko.Library.findAndLoad(Library.kt:112)
    at org.jetbrains.skiko.Library.load(Library.kt:59)
    at org.jetbrains.skia.impl.Library$Companion.staticLoad(Library.jvm.kt:12)
    at org.jetbrains.skia.Surface.<clinit>(Surface.kt:539)
    ... 42 more

FAILURES!!!
Tests run: 1,  Failures: 1
...

Adding the following to the test

  private companion object {
    private val oldHome: String = System.getProperty("user.home")

    @BeforeClass
    @JvmStatic
    fun overrideUserHome() {
      System.setProperty("user.home", System.getProperty("java.io.tmpdir"))
    }

    @AfterClass
    @JvmStatic
    fun restoreUserHome() {
      System.setProperty("user.home", oldHome)
    }
  }

works around the issue

Skiko wants to write a file at Library.kt:37. When the test is run by Bazel, the destination path resolves to a directory that does not exist (because of Bazel's sandboxing or whatever). IdeaTestSuiteBase overrides user.home to java.io.tmpdir. The workaround reproduces that bit of IdeaTestSuiteBase.

rock3r commented 7 months ago

CC @igordmn -- I can repro this myself, too. Is there a way we can tell Skiko where to dump the files with a flag? That way we can solve the problem without having to have a before/after on every test suite.

igordmn commented 7 months ago

where to dump the files with a flag

There is currently no way to tell where to extract binaries (dll/so/dylib), but there is a way to use already extracted binaries.

You can extract binaries from these files:

image

Place them in ./lib/skiko, and load them from there this way:

System.setProperty("skiko.library.path", "./lib/skiko")
rock3r commented 7 months ago

Would it be hard to add a property to pick the auto-extract folder? So we don't have to reimplement the download and extract logic ourselves

igordmn commented 7 months ago

Not hard, we will do it soon

rock3r commented 7 months ago

Thanks 🙏

okushnikov commented 1 month ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.