Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
buenaflor committed Aug 5, 2024
1 parent d48a901 commit 690eb1b
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ internal fun Project.installSentryForCocoapods(
}

@Suppress("CyclomaticComplexMethod")
// todo: write test
internal fun Project.configureLinkingOptions(linkerExtension: LinkerExtension) {
val kmpExtension = extensions.findByName(KOTLIN_EXTENSION_NAME)
if (kmpExtension !is KotlinMultiplatformExtension || kmpExtension.targets.isEmpty() || !HostManager.hostIsMac) {
Expand All @@ -137,8 +136,6 @@ internal fun Project.configureLinkingOptions(linkerExtension: LinkerExtension) {
derivedDataPath = findDerivedDataPath(customXcodeprojPath)

Check warning on line 136 in sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt

View check run for this annotation

Codecov / codecov/patch

sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt#L135-L136

Added lines #L135 - L136 were not covered by tests
}

logger.warn("framework path: $frameworkPath")

kmpExtension.appleTargets().all { target ->
val frameworkArchitecture = target.toSentryFrameworkArchitecture() ?: run {
logger.warn("Skipping target ${target.name} - unsupported architecture.")

Check warning on line 141 in sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt

View check run for this annotation

Codecov / codecov/patch

sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt#L141

Added line #L141 was not covered by tests
Expand All @@ -148,18 +145,18 @@ internal fun Project.configureLinkingOptions(linkerExtension: LinkerExtension) {
val dynamicFrameworkPath: String
val staticFrameworkPath: String

if (frameworkPath?.isNotEmpty() == false) {
if (frameworkPath?.isNotEmpty() == true) {
dynamicFrameworkPath = frameworkPath
staticFrameworkPath = frameworkPath
} else {
@Suppress("MaxLineLength")
dynamicFrameworkPath =
"$derivedDataPath/SourcePackages/artifacts/sentry-cocoa/Sentry-Dynamic/Sentry-Dynamic.xcframework/$frameworkArchitecture"

Check warning on line 154 in sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt

View check run for this annotation

Codecov / codecov/patch

sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt#L153-L154

Added lines #L153 - L154 were not covered by tests
@Suppress("MaxLineLength")
staticFrameworkPath =
"$derivedDataPath/SourcePackages/artifacts/sentry-cocoa/Sentry/Sentry.xcframework/$frameworkArchitecture"

Check warning on line 157 in sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt

View check run for this annotation

Codecov / codecov/patch

sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt#L156-L157

Added lines #L156 - L157 were not covered by tests
}

assert(frameworkPath == "haha")
val dynamicFrameworkExists = File(dynamicFrameworkPath).exists()
val staticFrameworkExists = File(staticFrameworkPath).exists()

Expand All @@ -172,22 +169,22 @@ internal fun Project.configureLinkingOptions(linkerExtension: LinkerExtension) {
target.binaries.all binaries@{ binary ->
if (binary is TestExecutable) {
// both dynamic and static frameworks will work for tests
val frameworkPath =
val finalFrameworkPath =
if (dynamicFrameworkExists) dynamicFrameworkPath else staticFrameworkPath
binary.linkerOpts("-rpath", frameworkPath, "-F$frameworkPath")
binary.linkerOpts("-rpath", finalFrameworkPath, "-F$finalFrameworkPath")
}

if (binary is Framework) {
val frameworkPath = when {
val finalFrameworkPath = when {
binary.isStatic && staticFrameworkExists -> staticFrameworkPath
!binary.isStatic && dynamicFrameworkExists -> dynamicFrameworkPath
else -> {
logger.warn("Linking to framework failed, no sentry framework found for target ${target.name}")

Check warning on line 182 in sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt

View check run for this annotation

Codecov / codecov/patch

sentry-kotlin-multiplatform-gradle-plugin/src/main/java/io/sentry/kotlin/multiplatform/gradle/SentryPlugin.kt#L182

Added line #L182 was not covered by tests
return@binaries
}
}
binary.linkerOpts("-F$frameworkPath")
logger.info("Linked framework from $frameworkPath")
binary.linkerOpts("-F$finalFrameworkPath")
logger.info("Linked framework from $finalFrameworkPath")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package io.sentry.kotlin.multiplatform.gradle

import io.mockk.every
import io.mockk.mockk
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.process.ExecOperations
import org.gradle.process.ExecResult
import org.gradle.process.ExecSpec
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.io.ByteArrayOutputStream

class DerivedDataPathTest {

private lateinit var valueSource: DerivedDataPathValueSource
private lateinit var execOperations: ExecOperations
private lateinit var parameters: DerivedDataPathValueSource.Parameters

@BeforeEach
fun setup() {
execOperations = mockk()
parameters = mockk()

valueSource = object : DerivedDataPathValueSource() {
override val execOperations: ExecOperations = this@DerivedDataPathTest.execOperations
override fun getParameters(): Parameters {
return this@DerivedDataPathTest.parameters
}
}
}

@Test
fun `obtain should return correct derived data path`() {
val xcodebuildOutput = """
Build settings for action build and target MyTarget:
BUILD_DIR = /DerivedData/Example/Build/Products
""".trimIndent()

every { parameters.xcodeprojPath } returns mockk {
every { get() } returns "/path/to/project.xcodeproj"
}

every { execOperations.exec(any()) } answers {
val execSpecLambda = it.invocation.args[0] as Action<ExecSpec>
val mockExecSpec = mockk<ExecSpec>(relaxed = true)

val buildDirOutput = ByteArrayOutputStream()
buildDirOutput.write(xcodebuildOutput.toByteArray())

var capturedOutputStream: ByteArrayOutputStream? = null
every { mockExecSpec.commandLine }.returns(listOf())
every { mockExecSpec.setStandardOutput(any()) } answers {
capturedOutputStream = firstArg()
mockExecSpec
}

execSpecLambda.execute(mockExecSpec)

capturedOutputStream?.write(xcodebuildOutput.toByteArray())

mockk<ExecResult> {
every { exitValue } returns 0
}
}

val result = valueSource.obtain()

assertEquals("/DerivedData/Example", result)
}

@Test
fun `obtain should throw GradleException when BUILD_DIR is not found`() {
val xcodebuildOutput = "Some output without BUILD_DIR"

every { parameters.xcodeprojPath } returns mockk {
every { get() } returns "/path/to/project.xcodeproj"
}

every { execOperations.exec(any()) } answers {
val execSpecLambda = it.invocation.args[0] as Action<ExecSpec>
val mockExecSpec = mockk<ExecSpec>(relaxed = true)

val buildDirOutput = ByteArrayOutputStream()
buildDirOutput.write(xcodebuildOutput.toByteArray())

var capturedOutputStream: ByteArrayOutputStream? = null
every { mockExecSpec.commandLine }.returns(listOf())
every { mockExecSpec.setStandardOutput(any()) } answers {
capturedOutputStream = firstArg()
mockExecSpec
}

execSpecLambda.execute(mockExecSpec)

capturedOutputStream?.write(xcodebuildOutput.toByteArray())

mockk<ExecResult> {
every { exitValue } returns 0
}
}

assertThrows<GradleException> {
valueSource.obtain()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package io.sentry.kotlin.multiplatform.gradle

import org.gradle.api.plugins.ExtensionAware
import org.gradle.testfixtures.ProjectBuilder
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.File

class SentryPluginTest {
@Test
Expand Down Expand Up @@ -102,4 +105,37 @@ class SentryPluginTest {
assertNotNull(commonMainConfiguration)
assertTrue(commonMainConfiguration!!.dependencies.contains(sentryDependency))
}

@Test
fun `configureLinkingOptions sets up linker options for apple targets`(@TempDir tempDir: File) {
val project = ProjectBuilder.builder().build()

project.pluginManager.apply {
apply("org.jetbrains.kotlin.multiplatform")
apply("io.sentry.kotlin.multiplatform.gradle")
}

val kmpExtension = project.extensions.getByName("kotlin") as KotlinMultiplatformExtension
kmpExtension.apply {
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "shared"
isStatic = false
}
}
}

val file =
tempDir.resolve("test/path")
file.mkdirs()

val linkerExtension = project.extensions.getByName("linker") as LinkerExtension
linkerExtension.frameworkPath.set(file.absolutePath)

project.configureLinkingOptions(linkerExtension)
}
}

0 comments on commit 690eb1b

Please sign in to comment.