A Gradle Plugin to build and generate benchmarking results for KMP iOS benchmarks.
* Generates Skia Dashboard compatible results.
* Automatically generates the XCode project, and runs benchmarks.
A KMP project needs to do something like:
```groovy
plugins {
id("androidx.benchmark.darwin")
}
```
and then it can use the `darwinBenchmark` block like so:
```groovy
darwinBenchmark {
// XCodegen Schema YAML
xcodeGenConfigFile = project.rootProject.file(
"benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml"
)
// XCode project name
xcodeProjectName = "benchmark-darwin-samples-xcode"
// iOS app scheme
scheme = "testapp-ios"
// ios 13, 15.2
destination = "id=7F61C467-4E4A-437C-B6EF-026FEEF3904C"
// The XCFrameworkConfig name
xcFrameworkConfig = "AndroidXDarwinSampleBenchmarks"
}
```
Test: ./gradlew --no-configuration-cache :benchmark:benchmark-darwin-samples:darwinBenchmarkResults
Example metric:
```json
{
"key": {
"testDescription": "Allocate an ArrayList of size 1000",
"metricName": "Memory Peak Physical",
"metricIdentifier": "com.apple.dt.XCTMetric_Memory.physical_peak",
"polarity": "prefers smaller",
"units": "kB"
},
"measurements": {
"stat": [
{
"value": "min",
"measurement": 0.0
},
{
"value": "median",
"measurement": 0.0
},
{
"value": "max",
"measurement": 0.0
},
{
"value": "stddev",
"measurement": 0.0
}
]
}
}
```
Bug: b/253517578
Change-Id: Id7c9cbf0e33b76566caa3d5210ad06f43109d435
diff --git a/benchmark/benchmark-darwin-gradle-plugin/README.md b/benchmark/benchmark-darwin-gradle-plugin/README.md
new file mode 100644
index 0000000..3fce72d
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/README.md
@@ -0,0 +1,70 @@
+# Introduction
+
+A Gradle Plugin to build and generate benchmarking results for KMP iOS benchmarks.
+
+* Generates Skia Dashboard compatible results.
+* Automatically generates the XCode project, and runs benchmarks on a target device running iOS
+ or macOS (simulator or physical devices).
+
+# Usage
+
+A KMP project needs to do something like:
+
+```groovy
+plugins {
+ id("androidx.benchmark.darwin")
+}
+```
+
+and then it can use the `darwinBenchmark` block like so:
+
+```groovy
+darwinBenchmark {
+ // XCodegen Schema YAML
+ xcodeGenConfigFile = project.rootProject.file(
+ "benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml"
+ )
+ // XCode project name
+ xcodeProjectName = "benchmark-darwin-samples-xcode"
+ // iOS app scheme
+ scheme = "testapp-ios"
+ // ios 13, 15.2
+ destination = "id=7F61C467-4E4A-437C-B6EF-026FEEF3904C"
+ // The XCFrameworkConfig name
+ xcFrameworkConfig = "AndroidXDarwinSampleBenchmarks"
+}
+```
+
+Example metrics look like:
+
+```json
+{
+ "key": {
+ "testDescription": "Allocate an ArrayList of size 1000",
+ "metricName": "Memory Peak Physical",
+ "metricIdentifier": "com.apple.dt.XCTMetric_Memory.physical_peak",
+ "polarity": "prefers smaller",
+ "units": "kB"
+ },
+ "measurements": {
+ "stat": [
+ {
+ "value": "min",
+ "measurement": 0.0
+ },
+ {
+ "value": "median",
+ "measurement": 0.0
+ },
+ {
+ "value": "max",
+ "measurement": 0.0
+ },
+ {
+ "value": "stddev",
+ "measurement": 0.0
+ }
+ ]
+ }
+}
+```
diff --git a/benchmark/benchmark-darwin-gradle-plugin/build.gradle b/benchmark/benchmark-darwin-gradle-plugin/build.gradle
new file mode 100644
index 0000000..4282513
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/build.gradle
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryType
+import androidx.build.SdkResourceGenerator
+
+plugins {
+ id("AndroidXPlugin")
+ id("kotlin")
+ id("java-gradle-plugin")
+}
+
+dependencies {
+ api(gradleApi())
+ implementation(libs.gson)
+ implementation(libs.apacheCommonsMath)
+ testImplementation(gradleTestKit())
+ testImplementation(libs.junit)
+ testImplementation(libs.truth)
+}
+
+SdkResourceGenerator.generateForHostTest(project)
+
+gradlePlugin {
+ plugins {
+ darwinBenchmark {
+ id = "androidx.benchmark.darwin"
+ implementationClass = "androidx.benchmark.darwin.gradle.DarwinBenchmarkPlugin"
+ }
+ }
+}
+
+androidx {
+ name = "AndroidX Benchmarks - Darwin Gradle Plugin"
+ type = LibraryType.GRADLE_PLUGIN
+ mavenGroup = LibraryGroups.BENCHMARK
+ inceptionYear = "2022"
+ description = "AndroidX Benchmarks - Darwin Gradle Plugin"
+}
+
+validatePlugins {
+ enableStricterValidation = true
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkPlugin.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkPlugin.kt
new file mode 100644
index 0000000..5974f14
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkPlugin.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+
+/**
+ * The Darwin benchmark plugin that helps run KMP benchmarks on iOS devices, and extracts benchmark
+ * results in `json`.
+ */
+class DarwinBenchmarkPlugin : Plugin<Project> {
+ override fun apply(project: Project) {
+ val extension =
+ project.extensions.create("darwinBenchmark", DarwinBenchmarkPluginExtension::class.java)
+
+ val xcodeProjectPath = extension.xcodeProjectName.flatMap { name ->
+ project.layout.buildDirectory.dir("$name.xcodeproj")
+ }
+
+ val xcResultPath = extension.xcodeProjectName.flatMap { name ->
+ project.layout.buildDirectory.dir("$name.xcresult")
+ }
+
+ val generateXCodeProjectTask = project.tasks.register(
+ GENERATE_XCODE_PROJECT_TASK, GenerateXCodeProjectTask::class.java
+ ) {
+ it.yamlFile.set(extension.xcodeGenConfigFile)
+ it.projectName.set(extension.xcodeProjectName)
+ it.xcProjectPath.set(xcodeProjectPath)
+ it.infoPlistPath.set(project.layout.buildDirectory.file("Info.plist"))
+ }
+
+ val runDarwinBenchmarks = project.tasks.register(
+ RUN_DARWIN_BENCHMARKS_TASK, RunDarwinBenchmarksTask::class.java
+ ) {
+ it.xcodeProjectPath.set(generateXCodeProjectTask.flatMap { task ->
+ task.xcProjectPath
+ })
+ it.destination.set(extension.destination)
+ it.scheme.set(extension.scheme)
+ it.xcResultPath.set(xcResultPath)
+ it.dependsOn("assemble${extension.xcFrameworkConfig.get()}ReleaseXCFramework")
+ }
+
+ project.tasks.register(
+ DARWIN_BENCHMARK_RESULTS_TASK, DarwinBenchmarkResultsTask::class.java
+ ) {
+ it.xcResultPath.set(runDarwinBenchmarks.flatMap { task ->
+ task.xcResultPath
+ })
+ it.outputFile.set(
+ project.layout.buildDirectory.file(
+ "${extension.xcodeProjectName.get()}-benchmark-result.json"
+ )
+ )
+ }
+ }
+
+ private companion object {
+ const val GENERATE_XCODE_PROJECT_TASK = "generateXCodeProject"
+ const val RUN_DARWIN_BENCHMARKS_TASK = "runDarwinBenchmarks"
+ const val DARWIN_BENCHMARK_RESULTS_TASK = "darwinBenchmarkResults"
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkPluginExtension.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkPluginExtension.kt
new file mode 100644
index 0000000..83781e8
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkPluginExtension.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle
+
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+
+/**
+ * The [DarwinBenchmarkPlugin] extension.
+ */
+abstract class DarwinBenchmarkPluginExtension {
+ /**
+ * The path to the YAML file that can be used to generate the XCode project.
+ */
+ abstract val xcodeGenConfigFile: RegularFileProperty
+
+ /**
+ * The project name as defined in the YAML file.
+ */
+ abstract val xcodeProjectName: Property<String>
+
+ /**
+ * The project scheme as defined in the YAML file that is the unit test target.
+ */
+ abstract val scheme: Property<String>
+
+ /**
+ * The benchmark device `id`.
+ * This is typically discovered by using `xcrun xctrace list devices`.
+ */
+ abstract val destination: Property<String>
+
+ /**
+ * The name of the `XCFrameworkConfig` defined in the benchmark's module build.gradle.
+ * This is used to derive the name of the `release` task to generate the `XCFramework`.
+ */
+ abstract val xcFrameworkConfig: Property<String>
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkResultsTask.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkResultsTask.kt
new file mode 100644
index 0000000..0ecdb27
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/DarwinBenchmarkResultsTask.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle
+
+import androidx.benchmark.darwin.gradle.skia.Metrics
+import androidx.benchmark.darwin.gradle.xcode.Models
+import androidx.benchmark.darwin.gradle.xcode.XcResultParser
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import javax.inject.Inject
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.InputDirectory
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.process.ExecOperations
+
+@CacheableTask
+abstract class DarwinBenchmarkResultsTask @Inject constructor(
+ private val execOperations: ExecOperations
+) : DefaultTask() {
+ @get:InputDirectory
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ abstract val xcResultPath: DirectoryProperty
+
+ @get:OutputFile
+ abstract val outputFile: RegularFileProperty
+
+ @TaskAction
+ fun benchmarkResults() {
+ val xcResultFile = xcResultPath.get().asFile
+ val parser = XcResultParser(xcResultFile) { args ->
+ val output = ByteArrayOutputStream()
+ val result = execOperations.exec { spec ->
+ spec.commandLine = args
+ spec.standardOutput = output
+ }
+ result.assertNormalExitValue()
+ output.use {
+ val input = ByteArrayInputStream(output.toByteArray())
+ input.use {
+ input.reader().readText()
+ }
+ }
+ }
+ val (record, summaries) = parser.parseResults()
+ val metrics = Metrics.buildMetrics(record, summaries)
+ val output = Models.gsonBuilder()
+ .setPrettyPrinting()
+ .create()
+ .toJson(metrics)
+
+ outputFile.get().asFile.writeText(output)
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/GenerateXCodeProjectTask.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/GenerateXCodeProjectTask.kt
new file mode 100644
index 0000000..3dec4f1
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/GenerateXCodeProjectTask.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle
+
+import java.io.File
+import javax.inject.Inject
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputFile
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.process.ExecOperations
+
+@CacheableTask
+abstract class GenerateXCodeProjectTask @Inject constructor(
+ private val execOperations: ExecOperations
+) : DefaultTask() {
+
+ @get:InputFile
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ abstract val yamlFile: RegularFileProperty
+
+ @get:Input
+ abstract val projectName: Property<String>
+
+ @get:OutputFile
+ abstract val infoPlistPath: RegularFileProperty
+
+ @get:OutputDirectory
+ abstract val xcProjectPath: DirectoryProperty
+
+ @TaskAction
+ fun buildXCodeProject() {
+ val outputFile = xcProjectPath.get().asFile
+ if (outputFile.exists()) {
+ require(outputFile.deleteRecursively()) {
+ "Unable to delete xcode project $outputFile"
+ }
+ }
+ val args = listOf(
+ "xcodegen",
+ "--spec",
+ yamlFile.get().asFile.absolutePath,
+ "--project",
+ outputFile.parent
+ )
+ val result = execOperations.exec { spec ->
+ spec.commandLine = args
+ }
+ result.assertNormalExitValue()
+ require(outputFile.exists()) {
+ "Project $projectName must match the `name` declaration in $yamlFile"
+ }
+ copyProjectMetadata()
+ }
+
+ private fun copyProjectMetadata() {
+ val sourceFile = File(yamlFile.get().asFile.parent, "Info.plist")
+ require(sourceFile.exists())
+ val targetFile = infoPlistPath.get().asFile
+ val copied = sourceFile.copyRecursively(targetFile, overwrite = true)
+ require(copied) {
+ "Unable to copy $sourceFile to $targetFile"
+ }
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/RunDarwinBenchmarksTask.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/RunDarwinBenchmarksTask.kt
new file mode 100644
index 0000000..55aec880
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/RunDarwinBenchmarksTask.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle
+
+import javax.inject.Inject
+import org.gradle.api.DefaultTask
+import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.InputDirectory
+import org.gradle.api.tasks.OutputDirectory
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.TaskAction
+import org.gradle.process.ExecOperations
+
+@CacheableTask
+abstract class RunDarwinBenchmarksTask @Inject constructor(
+ private val execOperations: ExecOperations
+) : DefaultTask() {
+ @get:InputDirectory
+ @get:PathSensitive(PathSensitivity.RELATIVE)
+ abstract val xcodeProjectPath: DirectoryProperty
+
+ @get:Input
+ abstract val destination: Property<String>
+
+ @get:Input
+ abstract val scheme: Property<String>
+
+ @get:OutputDirectory
+ abstract val xcResultPath: DirectoryProperty
+
+ @TaskAction
+ fun runBenchmarks() {
+ requireXcodeBuild()
+ val xcodeProject = xcodeProjectPath.get().asFile
+ val xcResultFile = xcResultPath.get().asFile
+ if (xcResultFile.exists()) {
+ xcResultFile.deleteRecursively()
+ }
+ val args = listOf(
+ "xcodebuild",
+ "test",
+ "-project", xcodeProject.absolutePath.toString(),
+ "-scheme", scheme.get(),
+ "-destination", destination.get(),
+ "-resultBundlePath", xcResultFile.absolutePath,
+ )
+ logger.info("Command : ${args.joinToString(" ")}")
+ val result = execOperations.exec { spec ->
+ spec.commandLine = args
+ }
+ result.assertNormalExitValue()
+ }
+
+ private fun requireXcodeBuild() {
+ val result = execOperations.exec { spec ->
+ spec.commandLine = listOf("which", "xcodebuild")
+ // Ignore exit value here to return a better exception message
+ spec.isIgnoreExitValue = true
+ }
+ require(result.exitValue == 0) {
+ "xcodebuild is missing on this machine."
+ }
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/skia/Metric.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/skia/Metric.kt
new file mode 100644
index 0000000..6bed2de
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/skia/Metric.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle.skia
+
+import androidx.benchmark.darwin.gradle.xcode.ActionTestSummary
+import androidx.benchmark.darwin.gradle.xcode.ActionsInvocationRecord
+import com.google.gson.annotations.SerializedName
+import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics
+
+/**
+ * https://skia.googlesource.com/buildbot/+/refs/heads/main/perf/FORMAT.md
+ */
+
+data class Stat(val value: String, val measurement: Double)
+data class Measurements(
+ @SerializedName("stat")
+ val stats: List<Stat>
+)
+
+data class Metric(val key: Map<String, String>, val measurements: Measurements)
+data class Metrics(val key: Map<String, String>, val results: List<Metric>) {
+ companion object {
+ fun buildMetrics(
+ record: ActionsInvocationRecord,
+ summaries: List<ActionTestSummary>
+ ): Metrics {
+ require(record.actions.actionRecords.isNotEmpty())
+ val runDestination = record.actions.actionRecords.first().runDestination
+ val metricsKeys = mapOf(
+ "destination" to runDestination.displayName.value,
+ "arch" to runDestination.targetArchitecture.value,
+ "targetSdk" to runDestination.targetSDKRecord.identifier.value,
+ "identifier" to runDestination.localComputerRecord.identifier.value,
+ "modelName" to runDestination.localComputerRecord.modelName.value,
+ "modelCode" to runDestination.localComputerRecord.modelCode.value
+ )
+ val results = summaries.flatMap { it.toMetrics() }
+ return Metrics(metricsKeys, results)
+ }
+
+ private fun ActionTestSummary.toMetrics(): List<Metric> {
+ return performanceMetrics.values.map { metricSummary ->
+ val key = mutableMapOf(
+ "testDescription" to (title() ?: "No description"),
+ "metricName" to metricSummary.displayName.value,
+ "metricIdentifier" to metricSummary.identifier.value,
+ "polarity" to metricSummary.polarity.value,
+ "units" to metricSummary.unitOfMeasurement.value,
+ )
+ val statistics = DescriptiveStatistics()
+ metricSummary.measurements.values.forEach {
+ statistics.addValue(it.value)
+ }
+ val min = Stat("min", statistics.min)
+ // The 50th percentile is the median
+ val median = Stat("median", statistics.getPercentile(50.0))
+ val max = Stat("max", statistics.max)
+ val deviation = Stat("stddev", statistics.standardDeviation)
+ Metric(key, Measurements(listOf(min, median, max, deviation)))
+ }
+ }
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/xcode/Models.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/xcode/Models.kt
new file mode 100644
index 0000000..863da27
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/xcode/Models.kt
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle.xcode
+
+import com.google.gson.Gson
+import com.google.gson.GsonBuilder
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import com.google.gson.annotations.SerializedName
+import java.lang.reflect.Type
+
+// Rather unfortunate that all values types are wrapped in a property bag containing a single
+// key called "_value". This is as per the JSON schema used by `xcresulttool`.
+
+data class StringTypedValue(
+ @SerializedName("_value") val value: String
+)
+
+data class IntTypedValue(
+ @SerializedName("_value") val value: Int
+)
+
+data class DoubleTypedValue(
+ @SerializedName("_value")
+ val value: Double
+)
+
+data class BooleanTypedValue(
+ @SerializedName("_value")
+ val value: Boolean
+)
+
+data class Metrics(
+ private val testsCount: IntTypedValue
+) {
+ fun size(): Int {
+ return testsCount.value
+ }
+}
+
+data class TestReference(
+ val id: StringTypedValue,
+)
+
+data class ActionResult(
+ private val status: StringTypedValue,
+ @SerializedName("testsRef") private val testsReference: TestReference
+) {
+ fun isSuccessful(): Boolean {
+ return status.value == "succeeded"
+ }
+
+ fun testsReferenceId(): String {
+ return testsReference.id.value
+ }
+}
+
+data class ActionPlatformRecord(
+ val identifier: StringTypedValue,
+ val userDescription: StringTypedValue,
+)
+
+data class ActionSDKRecord(
+ val name: StringTypedValue,
+ val identifier: StringTypedValue,
+ val operatingSystemVersion: StringTypedValue,
+ val isInternal: BooleanTypedValue,
+)
+
+data class ActionDeviceRecord(
+ val name: StringTypedValue,
+ val isConcreteDevice: BooleanTypedValue,
+ val operatingSystemVersion: StringTypedValue,
+ val operatingSystemVersionWithBuildNumber: StringTypedValue,
+ val nativeArchitecture: StringTypedValue,
+ val modelName: StringTypedValue,
+ val modelCode: StringTypedValue,
+ val identifier: StringTypedValue,
+ val isWireless: BooleanTypedValue,
+ val cpuKind: StringTypedValue,
+ val cpuCount: IntTypedValue?,
+ val cpuSpeedInMHz: IntTypedValue?,
+ val busSpeedInMHz: IntTypedValue?,
+ val ramSizeInMegabytes: IntTypedValue?,
+ val physicalCPUCoresPerPackage: IntTypedValue?,
+ val logicalCPUCoresPerPackage: IntTypedValue?,
+ val platformRecord: ActionPlatformRecord,
+)
+
+data class ActionRunDestinationRecord(
+ val displayName: StringTypedValue,
+ val targetArchitecture: StringTypedValue,
+ val targetDeviceRecord: ActionDeviceRecord,
+ val localComputerRecord: ActionDeviceRecord,
+ val targetSDKRecord: ActionSDKRecord,
+)
+
+data class ActionRecord(
+ val actionResult: ActionResult,
+ val runDestination: ActionRunDestinationRecord
+)
+
+data class Actions(
+ @SerializedName("_values") val actionRecords: List<ActionRecord>
+) {
+ fun testReferences(): List<String> {
+ return actionRecords.asSequence()
+ .map { it.actionResult.testsReferenceId() }
+ .toList()
+ }
+
+ fun isSuccessful(): Boolean {
+ return actionRecords.all { it.actionResult.isSuccessful() }
+ }
+}
+
+data class ActionsInvocationRecord(
+ val metrics: Metrics,
+ val actions: Actions
+)
+
+// Test Plan Summaries
+
+data class ActionTestMetadataSummary(
+ val id: StringTypedValue
+)
+
+data class TypeDefinition(
+ @SerializedName("_name")
+ val name: String
+)
+
+// Marker interface
+sealed interface ActionsTestSummaryGroupOrMeta
+
+data class ActionsTestSummaryGroupOrMetaArray(
+ @SerializedName("_values")
+ val values: List<ActionsTestSummaryGroupOrMeta>
+)
+
+data class ActionTestSummaryGroup(
+ val duration: DoubleTypedValue,
+ val identifier: StringTypedValue,
+ val name: StringTypedValue,
+ @SerializedName("subtests")
+ val subTests: ActionsTestSummaryGroupOrMetaArray
+) : ActionsTestSummaryGroupOrMeta {
+ fun summaries(): List<ActionTestSummaryMeta> {
+ return buildSummaries(mutableListOf(), this)
+ }
+
+ companion object {
+ internal fun buildSummaries(
+ summaries: MutableList<ActionTestSummaryMeta>,
+ group: ActionTestSummaryGroup
+ ): MutableList<ActionTestSummaryMeta> {
+ for (subTest in group.subTests.values) {
+ when (subTest) {
+ is ActionTestSummaryGroup -> buildSummaries(summaries, subTest)
+ is ActionTestSummaryMeta -> summaries += subTest
+ }
+ }
+ return summaries
+ }
+ }
+}
+
+data class ActionTestSummaryMeta(
+ val duration: DoubleTypedValue,
+ val identifier: StringTypedValue,
+ val name: StringTypedValue,
+ val summaryRef: ActionTestMetadataSummary,
+ val testStatus: StringTypedValue
+) : ActionsTestSummaryGroupOrMeta {
+ fun isSuccessful(): Boolean {
+ return testStatus.value == "Success"
+ }
+
+ fun summaryRefId(): String {
+ return summaryRef.id.value
+ }
+}
+
+class ActionTestSummaryDeserializer : JsonDeserializer<ActionsTestSummaryGroupOrMeta> {
+ override fun deserialize(
+ jsonElement: JsonElement,
+ typeOfT: Type,
+ context: JsonDeserializationContext
+ ): ActionsTestSummaryGroupOrMeta {
+ return if (checkType(jsonElement, ACTION_TEST_SUMMARY_GROUP)) {
+ val adapter = Models.gson().getAdapter(ActionTestSummaryGroup::class.java)
+ adapter.fromJson(jsonElement.toString())
+ } else if (checkType(jsonElement, ACTION_TEST_SUMMARY_META)) {
+ val adapter = Models.gson().getAdapter(ActionTestSummaryMeta::class.java)
+ adapter.fromJson(jsonElement.toString())
+ } else {
+ reportException(jsonElement)
+ }
+ }
+
+ private fun reportException(jsonElement: JsonElement): Nothing {
+ throw IllegalStateException("Unable to deserialize to ActionTestSummary ($jsonElement)")
+ }
+
+ companion object {
+ private const val TYPE = "_type"
+ private const val ACTION_TEST_SUMMARY_GROUP = "ActionTestSummaryGroup"
+ private const val ACTION_TEST_SUMMARY_META = "ActionTestMetadata"
+
+ internal fun checkType(jsonElement: JsonElement, name: String): Boolean {
+ if (!jsonElement.isJsonObject) return false
+ val json = jsonElement.asJsonObject
+ val jsonType: JsonElement? = json.get(TYPE)
+ if (jsonType != null && jsonType.isJsonObject) {
+ val adapter = Models.gson().getAdapter(TypeDefinition::class.java)
+ val type = adapter.fromJson(jsonType.toString())
+ return type.name == name
+ }
+ return false
+ }
+ }
+}
+
+data class ActionTestSummaryGroupArray(
+ @SerializedName("_values")
+ val values: List<ActionTestSummaryGroup>
+)
+
+data class ActionTestableSummary(
+ val diagnosticsDirectoryName: StringTypedValue,
+ val name: StringTypedValue,
+ val projectRelativePath: StringTypedValue,
+ val targetName: StringTypedValue,
+ val tests: ActionTestSummaryGroupArray
+)
+
+data class ActionTestableSummaryArray(
+ @SerializedName("_values")
+ val values: List<ActionTestableSummary>
+)
+
+data class ActionTestPlanRunSummary(
+ val testableSummaries: ActionTestableSummaryArray
+)
+
+data class ActionTestPlanSummaryArray(
+ @SerializedName("_values")
+ val values: List<ActionTestPlanRunSummary>
+)
+
+data class ActionTestPlanRunSummaries(
+ val summaries: ActionTestPlanSummaryArray
+) {
+ fun testSummaries(): List<ActionTestSummaryMeta> {
+ return summaries.values.flatMap { testPlanSummary ->
+ testPlanSummary.testableSummaries.values.flatMap { testableSummary ->
+ testableSummary.tests.values.flatMap { summaryGroup ->
+ summaryGroup.summaries()
+ }
+ }
+ }
+ }
+}
+
+// Test Metrics
+
+data class ActionTestActivitySummary(
+ val title: StringTypedValue
+)
+
+data class ActionTestActivitySummaryArray(
+ @SerializedName("_values")
+ val values: List<ActionTestActivitySummary>
+) {
+ fun title(): String? {
+ return values.firstOrNull()?.title?.value
+ }
+}
+
+data class MeasurementArray(
+ @SerializedName("_values")
+ val values: List<DoubleTypedValue>
+)
+
+data class ActionTestPerformanceMetricSummary(
+ val displayName: StringTypedValue,
+ val identifier: StringTypedValue,
+ val measurements: MeasurementArray,
+ val polarity: StringTypedValue,
+ val unitOfMeasurement: StringTypedValue,
+)
+
+data class ActionTestPerformanceMetricSummaryArray(
+ @SerializedName("_values")
+ val values: List<ActionTestPerformanceMetricSummary>
+)
+
+data class ActionTestSummary(
+ val activitySummaries: ActionTestActivitySummaryArray,
+ val name: StringTypedValue,
+ val testStatus: StringTypedValue,
+ val performanceMetrics: ActionTestPerformanceMetricSummaryArray
+) {
+ fun isSuccessful(): Boolean {
+ return testStatus.value == "Success"
+ }
+
+ fun title(): String? {
+ return activitySummaries.title()
+ }
+}
+
+object Models {
+ internal fun gsonBuilder(): GsonBuilder {
+ val builder = GsonBuilder()
+ builder.registerTypeAdapter(
+ ActionsTestSummaryGroupOrMeta::class.java,
+ ActionTestSummaryDeserializer()
+ )
+ return builder
+ }
+
+ fun gson(): Gson {
+ return gsonBuilder().create()
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/xcode/XcResultParser.kt b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/xcode/XcResultParser.kt
new file mode 100644
index 0000000..c0c3c15
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin/androidx/benchmark/darwin/gradle/xcode/XcResultParser.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.darwin.gradle.xcode
+
+import java.io.File
+
+/**
+ * Parses benchmark results from the xcresult file.
+ * @param xcResultFile The XCResult output file to parse.
+ * @param commandExecutor An executor that can invoke the `xcrun` and get the results from `stdout`.
+ */
+class XcResultParser(
+ private val xcResultFile: File,
+ private val commandExecutor: (args: List<String>) -> String
+) {
+ fun parseResults(): Pair<ActionsInvocationRecord, List<ActionTestSummary>> {
+ val json = commandExecutor(xcRunCommand())
+ val gson = Models.gson()
+ val record = gson.fromJson(json, ActionsInvocationRecord::class.java)
+ val summaries = record.actions.testReferences().flatMap { testRef ->
+ val summary = commandExecutor(xcRunCommand(testRef))
+ val testPlanSummaries = gson.fromJson(summary, ActionTestPlanRunSummaries::class.java)
+ testPlanSummaries.testSummaries().map { summaryMeta ->
+ val output = commandExecutor(xcRunCommand(summaryMeta.summaryRefId()))
+ val testSummary = gson.fromJson(output, ActionTestSummary::class.java)
+ testSummary
+ }
+ }
+ return record to summaries
+ }
+
+ /**
+ * Builds an `xcrun` command that can parse both the xcresult scaffold, and additionally
+ * traverse nested `plist`s to pull additional benchmark result metadata.
+ */
+ private fun xcRunCommand(id: String? = null): List<String> {
+ val args = mutableListOf(
+ "xcrun",
+ "xcresulttool",
+ "get",
+ "--path",
+ xcResultFile.absolutePath,
+ "--format",
+ "json"
+ )
+
+ if (!id.isNullOrEmpty()) {
+ args += listOf("--id", id)
+ }
+
+ return args
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/ModelsTest.kt b/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/ModelsTest.kt
new file mode 100644
index 0000000..663b7ea
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/ModelsTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.benchmark.darwin.gradle.xcode.ActionTestPlanRunSummaries
+import androidx.benchmark.darwin.gradle.xcode.ActionTestSummary
+import androidx.benchmark.darwin.gradle.xcode.ActionsInvocationRecord
+import androidx.benchmark.darwin.gradle.xcode.Models
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ModelsTest {
+ @Test
+ fun parseXcResultOutputs() {
+ val json = testData(XCRESULT_OUTPUT_JSON).readText()
+ val gson = Models.gson()
+ val record = gson.fromJson(json, ActionsInvocationRecord::class.java)
+ assertThat(record.actions.testReferences().size).isEqualTo(1)
+ assertThat(record.metrics.size()).isEqualTo(1)
+ assertThat(record.actions.isSuccessful()).isTrue()
+ }
+
+ @Test
+ fun parseTestsReferenceOutput() {
+ val json = testData(XC_TESTS_REFERENCE_OUTPUT_JSON).readText()
+ val gson = Models.gson()
+ val testPlanSummaries = gson.fromJson(json, ActionTestPlanRunSummaries::class.java)
+ val testSummaryMetas = testPlanSummaries.testSummaries()
+ assertThat(testSummaryMetas.size).isEqualTo(1)
+ assertThat(testSummaryMetas[0].summaryRefId()).isNotEmpty()
+ assertThat(testSummaryMetas[0].isSuccessful()).isTrue()
+ }
+
+ @Test
+ fun parseTestOutput() {
+ val json = testData(XC_TEST_OUTPUT_JSON).readText()
+ val gson = Models.gson()
+ val testSummary = gson.fromJson(json, ActionTestSummary::class.java)
+ assertThat(testSummary.title()).isNotEmpty()
+ assertThat(testSummary.isSuccessful()).isTrue()
+ }
+
+ companion object {
+ private const val XCRESULT_OUTPUT_JSON = "xcresult_output.json"
+ private const val XC_TESTS_REFERENCE_OUTPUT_JSON = "tests_reference_output.json"
+ private const val XC_TEST_OUTPUT_JSON = "test_output.json"
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/TestExtensions.kt b/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/TestExtensions.kt
new file mode 100644
index 0000000..28003fa
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/TestExtensions.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File
+
+internal fun testData(name: String): File {
+ return File("src/test/test-data", name)
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/XcResultParserTest.kt b/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/XcResultParserTest.kt
new file mode 100644
index 0000000..00468a9
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/kotlin/XcResultParserTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.benchmark.darwin.gradle.skia.Metrics
+import androidx.benchmark.darwin.gradle.xcode.Models
+import androidx.benchmark.darwin.gradle.xcode.XcResultParser
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assume.assumeTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class XcResultParserTest {
+ @Test
+ fun parseXcResultFileTest() {
+ val operatingSystem = System.getProperty("os.name")
+ // Only run this test on an `Mac OS X` machine.
+ assumeTrue(operatingSystem.contains("Mac", ignoreCase = true))
+ val xcResultFile = testData("sample-xcode.xcresult")
+ val parser = XcResultParser(xcResultFile) { args ->
+ val builder = ProcessBuilder(*args.toTypedArray())
+ val process = builder.start()
+ val resultCode = process.waitFor()
+ require(resultCode == 0) {
+ "Process terminated unexpectedly (${args.joinToString(separator = " ")})"
+ }
+ process.inputStream.use {
+ it.reader().readText()
+ }
+ }
+ val (record, summaries) = parser.parseResults()
+ // Usually corresponds to the size of the test suite
+ // In the case of KMP benchmarks, this is always 1 per module.
+ assertThat(record.actions.testReferences().size).isEqualTo(1)
+ assertThat(record.actions.isSuccessful()).isTrue()
+ // Metrics typically correspond to the number of tests
+ assertThat(record.metrics.size()).isEqualTo(2)
+ assertThat(summaries.isNotEmpty()).isTrue()
+ val metrics = Metrics.buildMetrics(record, summaries)
+ val json = Models.gsonBuilder()
+ .setPrettyPrinting()
+ .create()
+ .toJson(metrics)
+ println()
+ println(json)
+ println()
+ assertThat(json).isNotEmpty()
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/README.md b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/README.md
new file mode 100644
index 0000000..6610e6b
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/README.md
@@ -0,0 +1,18 @@
+# Test Data
+
+## [sample-xcode.xcresult](./sample-xcode.xcresult)
+
+This is an example benchmark `xcresult` directory that is the result of running an `xcodebuild`.
+
+An example invocation might look something like:
+
+```bash
+xcodebuild test -project $SRCROOT/benchmark-darwin-samples-xcode.xcodeproj \
+ -scheme testapp-ios \
+ -destination id=7F61C467-4E4A-437C-B6EF-026FEEF3904C \
+ -resultBundlePath $SRCROOT/benchmark-darwin-samples-xcode.xcresult
+```
+
+The `xcresult` output directory stores results in a nested `plist` format. Entities in the top-level
+`plist` file point to other entities stored in other`plist` files (inside the `Data` directory),
+using a unique filename identifier.
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw==
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw==
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~809cv4Ku3dnBcPFN0EL1A1xx_h4MH0THT41Rlz6CEankhzddTnjMa6CWhjt9F69jFsquD4x8Offmms1sFw6EKA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~809cv4Ku3dnBcPFN0EL1A1xx_h4MH0THT41Rlz6CEankhzddTnjMa6CWhjt9F69jFsquD4x8Offmms1sFw6EKA==
new file mode 100644
index 0000000..bf96d3c
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~809cv4Ku3dnBcPFN0EL1A1xx_h4MH0THT41Rlz6CEankhzddTnjMa6CWhjt9F69jFsquD4x8Offmms1sFw6EKA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~BVkwcGZLlAQkY6Iyxs4jrfCad9IriiNRwFgkj-q5CYa3nlIwjU66k7hfhLcnmUHGVk4q8lK8eljDDjEI2_UwrA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~BVkwcGZLlAQkY6Iyxs4jrfCad9IriiNRwFgkj-q5CYa3nlIwjU66k7hfhLcnmUHGVk4q8lK8eljDDjEI2_UwrA==
new file mode 100644
index 0000000..07b9130
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~BVkwcGZLlAQkY6Iyxs4jrfCad9IriiNRwFgkj-q5CYa3nlIwjU66k7hfhLcnmUHGVk4q8lK8eljDDjEI2_UwrA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~NcxF_MrjcLDoh1KWbeGq453YSibqfUcZRlcfxDlh1HVpo6_BqONP2ZB1AiJYY9lYfIGL1g5h3VsbOKnwGLjywQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~NcxF_MrjcLDoh1KWbeGq453YSibqfUcZRlcfxDlh1HVpo6_BqONP2ZB1AiJYY9lYfIGL1g5h3VsbOKnwGLjywQ==
new file mode 100644
index 0000000..13d30be
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~NcxF_MrjcLDoh1KWbeGq453YSibqfUcZRlcfxDlh1HVpo6_BqONP2ZB1AiJYY9lYfIGL1g5h3VsbOKnwGLjywQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~PBlxYYh3AAyWwRJ85oIfJdGUcOuzcjExLhwrde-sNFno45FanCv9KkZmQ_eAJL9BVGKBh78r4OF_Fw2MeiGPYg== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~PBlxYYh3AAyWwRJ85oIfJdGUcOuzcjExLhwrde-sNFno45FanCv9KkZmQ_eAJL9BVGKBh78r4OF_Fw2MeiGPYg==
new file mode 100644
index 0000000..3032bd0
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~PBlxYYh3AAyWwRJ85oIfJdGUcOuzcjExLhwrde-sNFno45FanCv9KkZmQ_eAJL9BVGKBh78r4OF_Fw2MeiGPYg==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~TV3vc3QcCkBeyTI4OZibWTUhnLOa2pj_khWYMDIsFQfzU1CC6gAO1HxXclYQhodcuQjZSw7GGBlpuUT8X0uctA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~TV3vc3QcCkBeyTI4OZibWTUhnLOa2pj_khWYMDIsFQfzU1CC6gAO1HxXclYQhodcuQjZSw7GGBlpuUT8X0uctA==
new file mode 100644
index 0000000..305a73b
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~TV3vc3QcCkBeyTI4OZibWTUhnLOa2pj_khWYMDIsFQfzU1CC6gAO1HxXclYQhodcuQjZSw7GGBlpuUT8X0uctA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~YK5eNAHGX7bQW65jgs2rLhWNoTj7vgF1CBLZ2k12n3svTuVa_whSNkDWJY9V9-QVC_GCh2-DzDDLoIpXvYOToA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~YK5eNAHGX7bQW65jgs2rLhWNoTj7vgF1CBLZ2k12n3svTuVa_whSNkDWJY9V9-QVC_GCh2-DzDDLoIpXvYOToA==
new file mode 100644
index 0000000..9a0adba
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~YK5eNAHGX7bQW65jgs2rLhWNoTj7vgF1CBLZ2k12n3svTuVa_whSNkDWJY9V9-QVC_GCh2-DzDDLoIpXvYOToA==
@@ -0,0 +1 @@
+[{"name":"testmanagerd.log","type":1}]
\ No newline at end of file
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~bO5MkLRUHsU78utGaMM3HVQkRM7RbYps9mAfFre5AyZnGEAQmWmCQMb2RChRtxj7aiaDPHDpQxhAswnGBW3rAA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~bO5MkLRUHsU78utGaMM3HVQkRM7RbYps9mAfFre5AyZnGEAQmWmCQMb2RChRtxj7aiaDPHDpQxhAswnGBW3rAA==
new file mode 100644
index 0000000..52a8bc8
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~bO5MkLRUHsU78utGaMM3HVQkRM7RbYps9mAfFre5AyZnGEAQmWmCQMb2RChRtxj7aiaDPHDpQxhAswnGBW3rAA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~eMJEUpMqij97v52rtaj8rSl-UZJhPmN04NCDD0JZ0cWyFbAHRCbjw5PJqWyqalQuFswnMkB6LvsT3uFLJVGVqw== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~eMJEUpMqij97v52rtaj8rSl-UZJhPmN04NCDD0JZ0cWyFbAHRCbjw5PJqWyqalQuFswnMkB6LvsT3uFLJVGVqw==
new file mode 100644
index 0000000..b385fa3
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~eMJEUpMqij97v52rtaj8rSl-UZJhPmN04NCDD0JZ0cWyFbAHRCbjw5PJqWyqalQuFswnMkB6LvsT3uFLJVGVqw==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~hncU2qbL3W7Jwz-E6zuM7ThWI10rl9EEkPM5cV70-odmasyId-QIR9ZRmIMwYF8DCechev-bgJgPAiYsyImmnQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~hncU2qbL3W7Jwz-E6zuM7ThWI10rl9EEkPM5cV70-odmasyId-QIR9ZRmIMwYF8DCechev-bgJgPAiYsyImmnQ==
new file mode 100644
index 0000000..195b954
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~hncU2qbL3W7Jwz-E6zuM7ThWI10rl9EEkPM5cV70-odmasyId-QIR9ZRmIMwYF8DCechev-bgJgPAiYsyImmnQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~l90yex7j_mtyE5LhZFKn-M7ovFj_tArzqr984SmaEo2RQ3JhValxuXW7UXxzNRGaNamX9MMhtWVxU-wT9DA6Zg== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~l90yex7j_mtyE5LhZFKn-M7ovFj_tArzqr984SmaEo2RQ3JhValxuXW7UXxzNRGaNamX9MMhtWVxU-wT9DA6Zg==
new file mode 100644
index 0000000..88dc22a
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~l90yex7j_mtyE5LhZFKn-M7ovFj_tArzqr984SmaEo2RQ3JhValxuXW7UXxzNRGaNamX9MMhtWVxU-wT9DA6Zg==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~no8uvpmY2pkdGvoMP79k6Q4ikuedatoSuF6vBG0HR8h0GsBvPND_wHS-M8mBpxtX6NzpHV4bKIhwFkxUsd7RXA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~no8uvpmY2pkdGvoMP79k6Q4ikuedatoSuF6vBG0HR8h0GsBvPND_wHS-M8mBpxtX6NzpHV4bKIhwFkxUsd7RXA==
new file mode 100644
index 0000000..c4b8635
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~no8uvpmY2pkdGvoMP79k6Q4ikuedatoSuF6vBG0HR8h0GsBvPND_wHS-M8mBpxtX6NzpHV4bKIhwFkxUsd7RXA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw==
new file mode 100644
index 0000000..47daeba
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~wV6va8rQlQLAcZ8rb5UAf1mKxaJdF9ZDlsizSwQ7FqQynxq_02ZsiipQ63-2YJ3jEODImbyk3FvKgJ2KaOPOPQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~wV6va8rQlQLAcZ8rb5UAf1mKxaJdF9ZDlsizSwQ7FqQynxq_02ZsiipQ63-2YJ3jEODImbyk3FvKgJ2KaOPOPQ==
new file mode 100644
index 0000000..ff4a430
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~wV6va8rQlQLAcZ8rb5UAf1mKxaJdF9ZDlsizSwQ7FqQynxq_02ZsiipQ63-2YJ3jEODImbyk3FvKgJ2KaOPOPQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~wpEwfbWjFv9AR7VY2bJ5g_ndbKMYwUEFGZ1w3MdarhPZE605CCX5XHRoL5cjlzYTdIpHF8aXtcLt6kz2ELrAsQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~wpEwfbWjFv9AR7VY2bJ5g_ndbKMYwUEFGZ1w3MdarhPZE605CCX5XHRoL5cjlzYTdIpHF8aXtcLt6kz2ELrAsQ==
new file mode 100644
index 0000000..70db723
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~wpEwfbWjFv9AR7VY2bJ5g_ndbKMYwUEFGZ1w3MdarhPZE605CCX5XHRoL5cjlzYTdIpHF8aXtcLt6kz2ELrAsQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~z_lmQvK-mq_MbksvJ2oEALgVyhIwk-VirNem09JWgC47IaBCD7JaSPfQeouKa8iSKUchkiKh993EavN5hgc0Mg== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~z_lmQvK-mq_MbksvJ2oEALgVyhIwk-VirNem09JWgC47IaBCD7JaSPfQeouKa8iSKUchkiKh993EavN5hgc0Mg==
new file mode 100644
index 0000000..0d78c58
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/data.0~z_lmQvK-mq_MbksvJ2oEALgVyhIwk-VirNem09JWgC47IaBCD7JaSPfQeouKa8iSKUchkiKh993EavN5hgc0Mg==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~4VqMqsI5lOfxRppnud6-VDWcNsU8J7VgFCJfW2dXPwOcAkvU-I8Um5yp9n0Zv6nr3VmcxYggaVMDFfR0U_vjKw==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~809cv4Ku3dnBcPFN0EL1A1xx_h4MH0THT41Rlz6CEankhzddTnjMa6CWhjt9F69jFsquD4x8Offmms1sFw6EKA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~809cv4Ku3dnBcPFN0EL1A1xx_h4MH0THT41Rlz6CEankhzddTnjMa6CWhjt9F69jFsquD4x8Offmms1sFw6EKA==
new file mode 100644
index 0000000..0ec3518
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~809cv4Ku3dnBcPFN0EL1A1xx_h4MH0THT41Rlz6CEankhzddTnjMa6CWhjt9F69jFsquD4x8Offmms1sFw6EKA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~BVkwcGZLlAQkY6Iyxs4jrfCad9IriiNRwFgkj-q5CYa3nlIwjU66k7hfhLcnmUHGVk4q8lK8eljDDjEI2_UwrA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~BVkwcGZLlAQkY6Iyxs4jrfCad9IriiNRwFgkj-q5CYa3nlIwjU66k7hfhLcnmUHGVk4q8lK8eljDDjEI2_UwrA==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~BVkwcGZLlAQkY6Iyxs4jrfCad9IriiNRwFgkj-q5CYa3nlIwjU66k7hfhLcnmUHGVk4q8lK8eljDDjEI2_UwrA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~NcxF_MrjcLDoh1KWbeGq453YSibqfUcZRlcfxDlh1HVpo6_BqONP2ZB1AiJYY9lYfIGL1g5h3VsbOKnwGLjywQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~NcxF_MrjcLDoh1KWbeGq453YSibqfUcZRlcfxDlh1HVpo6_BqONP2ZB1AiJYY9lYfIGL1g5h3VsbOKnwGLjywQ==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~NcxF_MrjcLDoh1KWbeGq453YSibqfUcZRlcfxDlh1HVpo6_BqONP2ZB1AiJYY9lYfIGL1g5h3VsbOKnwGLjywQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~PBlxYYh3AAyWwRJ85oIfJdGUcOuzcjExLhwrde-sNFno45FanCv9KkZmQ_eAJL9BVGKBh78r4OF_Fw2MeiGPYg== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~PBlxYYh3AAyWwRJ85oIfJdGUcOuzcjExLhwrde-sNFno45FanCv9KkZmQ_eAJL9BVGKBh78r4OF_Fw2MeiGPYg==
new file mode 100644
index 0000000..6fde618
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~PBlxYYh3AAyWwRJ85oIfJdGUcOuzcjExLhwrde-sNFno45FanCv9KkZmQ_eAJL9BVGKBh78r4OF_Fw2MeiGPYg==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~TV3vc3QcCkBeyTI4OZibWTUhnLOa2pj_khWYMDIsFQfzU1CC6gAO1HxXclYQhodcuQjZSw7GGBlpuUT8X0uctA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~TV3vc3QcCkBeyTI4OZibWTUhnLOa2pj_khWYMDIsFQfzU1CC6gAO1HxXclYQhodcuQjZSw7GGBlpuUT8X0uctA==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~TV3vc3QcCkBeyTI4OZibWTUhnLOa2pj_khWYMDIsFQfzU1CC6gAO1HxXclYQhodcuQjZSw7GGBlpuUT8X0uctA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~YK5eNAHGX7bQW65jgs2rLhWNoTj7vgF1CBLZ2k12n3svTuVa_whSNkDWJY9V9-QVC_GCh2-DzDDLoIpXvYOToA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~YK5eNAHGX7bQW65jgs2rLhWNoTj7vgF1CBLZ2k12n3svTuVa_whSNkDWJY9V9-QVC_GCh2-DzDDLoIpXvYOToA==
new file mode 100644
index 0000000..7bc9ef9c
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~YK5eNAHGX7bQW65jgs2rLhWNoTj7vgF1CBLZ2k12n3svTuVa_whSNkDWJY9V9-QVC_GCh2-DzDDLoIpXvYOToA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~bO5MkLRUHsU78utGaMM3HVQkRM7RbYps9mAfFre5AyZnGEAQmWmCQMb2RChRtxj7aiaDPHDpQxhAswnGBW3rAA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~bO5MkLRUHsU78utGaMM3HVQkRM7RbYps9mAfFre5AyZnGEAQmWmCQMb2RChRtxj7aiaDPHDpQxhAswnGBW3rAA==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~bO5MkLRUHsU78utGaMM3HVQkRM7RbYps9mAfFre5AyZnGEAQmWmCQMb2RChRtxj7aiaDPHDpQxhAswnGBW3rAA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~eMJEUpMqij97v52rtaj8rSl-UZJhPmN04NCDD0JZ0cWyFbAHRCbjw5PJqWyqalQuFswnMkB6LvsT3uFLJVGVqw== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~eMJEUpMqij97v52rtaj8rSl-UZJhPmN04NCDD0JZ0cWyFbAHRCbjw5PJqWyqalQuFswnMkB6LvsT3uFLJVGVqw==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~eMJEUpMqij97v52rtaj8rSl-UZJhPmN04NCDD0JZ0cWyFbAHRCbjw5PJqWyqalQuFswnMkB6LvsT3uFLJVGVqw==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~hncU2qbL3W7Jwz-E6zuM7ThWI10rl9EEkPM5cV70-odmasyId-QIR9ZRmIMwYF8DCechev-bgJgPAiYsyImmnQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~hncU2qbL3W7Jwz-E6zuM7ThWI10rl9EEkPM5cV70-odmasyId-QIR9ZRmIMwYF8DCechev-bgJgPAiYsyImmnQ==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~hncU2qbL3W7Jwz-E6zuM7ThWI10rl9EEkPM5cV70-odmasyId-QIR9ZRmIMwYF8DCechev-bgJgPAiYsyImmnQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~l90yex7j_mtyE5LhZFKn-M7ovFj_tArzqr984SmaEo2RQ3JhValxuXW7UXxzNRGaNamX9MMhtWVxU-wT9DA6Zg== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~l90yex7j_mtyE5LhZFKn-M7ovFj_tArzqr984SmaEo2RQ3JhValxuXW7UXxzNRGaNamX9MMhtWVxU-wT9DA6Zg==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~l90yex7j_mtyE5LhZFKn-M7ovFj_tArzqr984SmaEo2RQ3JhValxuXW7UXxzNRGaNamX9MMhtWVxU-wT9DA6Zg==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~no8uvpmY2pkdGvoMP79k6Q4ikuedatoSuF6vBG0HR8h0GsBvPND_wHS-M8mBpxtX6NzpHV4bKIhwFkxUsd7RXA== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~no8uvpmY2pkdGvoMP79k6Q4ikuedatoSuF6vBG0HR8h0GsBvPND_wHS-M8mBpxtX6NzpHV4bKIhwFkxUsd7RXA==
new file mode 100644
index 0000000..e12afe0
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~no8uvpmY2pkdGvoMP79k6Q4ikuedatoSuF6vBG0HR8h0GsBvPND_wHS-M8mBpxtX6NzpHV4bKIhwFkxUsd7RXA==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw==
new file mode 100644
index 0000000..bd95f97
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~wV6va8rQlQLAcZ8rb5UAf1mKxaJdF9ZDlsizSwQ7FqQynxq_02ZsiipQ63-2YJ3jEODImbyk3FvKgJ2KaOPOPQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~wV6va8rQlQLAcZ8rb5UAf1mKxaJdF9ZDlsizSwQ7FqQynxq_02ZsiipQ63-2YJ3jEODImbyk3FvKgJ2KaOPOPQ==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~wV6va8rQlQLAcZ8rb5UAf1mKxaJdF9ZDlsizSwQ7FqQynxq_02ZsiipQ63-2YJ3jEODImbyk3FvKgJ2KaOPOPQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~wpEwfbWjFv9AR7VY2bJ5g_ndbKMYwUEFGZ1w3MdarhPZE605CCX5XHRoL5cjlzYTdIpHF8aXtcLt6kz2ELrAsQ== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~wpEwfbWjFv9AR7VY2bJ5g_ndbKMYwUEFGZ1w3MdarhPZE605CCX5XHRoL5cjlzYTdIpHF8aXtcLt6kz2ELrAsQ==
new file mode 100644
index 0000000..a5fa9ca
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~wpEwfbWjFv9AR7VY2bJ5g_ndbKMYwUEFGZ1w3MdarhPZE605CCX5XHRoL5cjlzYTdIpHF8aXtcLt6kz2ELrAsQ==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~z_lmQvK-mq_MbksvJ2oEALgVyhIwk-VirNem09JWgC47IaBCD7JaSPfQeouKa8iSKUchkiKh993EavN5hgc0Mg== b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~z_lmQvK-mq_MbksvJ2oEALgVyhIwk-VirNem09JWgC47IaBCD7JaSPfQeouKa8iSKUchkiKh993EavN5hgc0Mg==
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Data/refs.0~z_lmQvK-mq_MbksvJ2oEALgVyhIwk-VirNem09JWgC47IaBCD7JaSPfQeouKa8iSKUchkiKh993EavN5hgc0Mg==
Binary files differ
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Info.plist b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Info.plist
new file mode 100644
index 0000000..8e63641
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/sample-xcode.xcresult/Info.plist
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>dateCreated</key>
+ <date>2022-09-23T17:38:01Z</date>
+ <key>externalLocations</key>
+ <array/>
+ <key>rootId</key>
+ <dict>
+ <key>hash</key>
+ <string>0~vcNmCXushFQo2Asf-Ddow5-J6PKttgTE0SMgzoRxYZv26906WiKBSKSrE4LJnPfLcKZXgqb8b9B9dS0xNC6phw==</string>
+ </dict>
+ <key>storage</key>
+ <dict>
+ <key>backend</key>
+ <string>fileBacked2</string>
+ <key>compression</key>
+ <string>standard</string>
+ </dict>
+ <key>version</key>
+ <dict>
+ <key>major</key>
+ <integer>3</integer>
+ <key>minor</key>
+ <integer>34</integer>
+ </dict>
+</dict>
+</plist>
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/test_output.json b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/test_output.json
new file mode 100644
index 0000000..a8287ad
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/test_output.json
@@ -0,0 +1,624 @@
+{
+ "_type" : {
+ "_name" : "ActionTestSummary",
+ "_supertype" : {
+ "_name" : "ActionTestSummaryIdentifiableObject",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ }
+ },
+ "activitySummaries" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestActivitySummary"
+ },
+ "activityType" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.xctest.activity-type.userCreated"
+ },
+ "finish" : {
+ "_type" : {
+ "_name" : "Date"
+ },
+ "_value" : "2022-09-20T15:39:30.433-0700"
+ },
+ "start" : {
+ "_type" : {
+ "_name" : "Date"
+ },
+ "_value" : "2022-09-20T15:39:30.366-0700"
+ },
+ "title" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Allocate an ArrayList of size 1000"
+ },
+ "uuid" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "660362D3-AA8A-4630-B098-780ED90922E2"
+ }
+ }
+ ]
+ },
+ "duration" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0741419792175293"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "BenchmarkTest\/runBenchmark()"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "runBenchmark()"
+ },
+ "performanceMetrics" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestPerformanceMetricSummary"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Memory Physical"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.XCTMetric_Memory.physical"
+ },
+ "maxPercentRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxPercentRelativeStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "maxStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "measurements" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8208.448"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8192.0"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8192.0"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8208.384"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8257.536"
+ }
+ ]
+ },
+ "polarity" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "prefers smaller"
+ },
+ "unitOfMeasurement" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "kB"
+ }
+ },
+ {
+ "_type" : {
+ "_name" : "ActionTestPerformanceMetricSummary"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Clock Monotonic Time"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.XCTMetric_Clock.time.monotonic"
+ },
+ "maxPercentRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxPercentRelativeStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "maxStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "measurements" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.003374259"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0011105260000000001"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0009685430000000001"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.001031847"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.006419944"
+ }
+ ]
+ },
+ "polarity" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "prefers smaller"
+ },
+ "unitOfMeasurement" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "s"
+ }
+ },
+ {
+ "_type" : {
+ "_name" : "ActionTestPerformanceMetricSummary"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "CPU Cycles"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.XCTMetric_CPU.cycles"
+ },
+ "maxPercentRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxPercentRelativeStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "maxStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "measurements" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8568.973"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "5173.538"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "4663.702"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "4684.408"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "21681.682"
+ }
+ ]
+ },
+ "polarity" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "prefers smaller"
+ },
+ "unitOfMeasurement" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "kC"
+ }
+ },
+ {
+ "_type" : {
+ "_name" : "ActionTestPerformanceMetricSummary"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "CPU Time"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.XCTMetric_CPU.time"
+ },
+ "maxPercentRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxPercentRelativeStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "maxStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "measurements" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0027404810000000003"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0016844030000000001"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0014999850000000001"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0015120390000000002"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.007035559"
+ }
+ ]
+ },
+ "polarity" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "prefers smaller"
+ },
+ "unitOfMeasurement" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "s"
+ }
+ },
+ {
+ "_type" : {
+ "_name" : "ActionTestPerformanceMetricSummary"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "CPU Instructions Retired"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.XCTMetric_CPU.instructions_retired"
+ },
+ "maxPercentRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxPercentRelativeStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "maxStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "measurements" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "16386.777"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8917.514"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8777.292"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "8398.467"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "40257.553"
+ }
+ ]
+ },
+ "polarity" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "prefers smaller"
+ },
+ "unitOfMeasurement" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "kI"
+ }
+ },
+ {
+ "_type" : {
+ "_name" : "ActionTestPerformanceMetricSummary"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Memory Peak Physical"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.dt.XCTMetric_Memory.physical_peak"
+ },
+ "maxPercentRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxPercentRelativeStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "10.0"
+ },
+ "maxRegression" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "maxStandardDeviation" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ "measurements" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ },
+ {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0"
+ }
+ ]
+ },
+ "polarity" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "prefers smaller"
+ },
+ "unitOfMeasurement" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "kB"
+ }
+ }
+ ]
+ },
+ "testStatus" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Success"
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/tests_reference_output.json b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/tests_reference_output.json
new file mode 100644
index 0000000..9b3286a
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/tests_reference_output.json
@@ -0,0 +1,277 @@
+{
+ "_type" : {
+ "_name" : "ActionTestPlanRunSummaries"
+ },
+ "summaries" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestPlanRunSummary",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Test Scheme Action"
+ },
+ "testableSummaries" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestableSummary",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ },
+ "diagnosticsDirectoryName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "testapp-ios-benchmarks-D5CA694B-66BF-479C-ABE4-0D3BDF591768-Configuration-Test Scheme Action-Iteration-1"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "testapp-ios-benchmarks"
+ },
+ "projectRelativePath" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "benchmark-darwin-sample-xcode.xcodeproj"
+ },
+ "targetName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "testapp-ios-benchmarks"
+ },
+ "testKind" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "xctest-tool hosted"
+ },
+ "testLanguage" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : ""
+ },
+ "testRegion" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : ""
+ },
+ "tests" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestSummaryGroup",
+ "_supertype" : {
+ "_name" : "ActionTestSummaryIdentifiableObject",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ }
+ },
+ "duration" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.07568299770355225"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "All tests"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "All tests"
+ },
+ "subtests" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestSummaryGroup",
+ "_supertype" : {
+ "_name" : "ActionTestSummaryIdentifiableObject",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ }
+ },
+ "duration" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.07503998279571533"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "testapp-ios-benchmarks.xctest"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "testapp-ios-benchmarks.xctest"
+ },
+ "subtests" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestSummaryGroup",
+ "_supertype" : {
+ "_name" : "ActionTestSummaryIdentifiableObject",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ }
+ },
+ "duration" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.07448196411132812"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "BenchmarkTest"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "BenchmarkTest"
+ },
+ "subtests" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionTestMetadata",
+ "_supertype" : {
+ "_name" : "ActionTestSummaryIdentifiableObject",
+ "_supertype" : {
+ "_name" : "ActionAbstractTestSummary"
+ }
+ }
+ },
+ "duration" : {
+ "_type" : {
+ "_name" : "Double"
+ },
+ "_value" : "0.0741419792175293"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "BenchmarkTest\/runBenchmark()"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "runBenchmark()"
+ },
+ "summaryRef" : {
+ "_type" : {
+ "_name" : "Reference"
+ },
+ "id" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "0~9QZnTT_BgRyY356cOax6Xlj_lclcNKu46aQPHsHicDo5aDaBNGg0f1y5hrlGl30pfE8RtG0-7IY1sZEQSgv-yA=="
+ },
+ "targetType" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActionTestSummary"
+ },
+ "supertype" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActionTestSummaryIdentifiableObject"
+ },
+ "supertype" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActionAbstractTestSummary"
+ }
+ }
+ }
+ }
+ },
+ "testStatus" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Success"
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
diff --git a/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/xcresult_output.json b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/xcresult_output.json
new file mode 100644
index 0000000..bedddde
--- /dev/null
+++ b/benchmark/benchmark-darwin-gradle-plugin/src/test/test-data/xcresult_output.json
@@ -0,0 +1,502 @@
+{
+ "_type" : {
+ "_name" : "ActionsInvocationRecord"
+ },
+ "actions" : {
+ "_type" : {
+ "_name" : "Array"
+ },
+ "_values" : [
+ {
+ "_type" : {
+ "_name" : "ActionRecord"
+ },
+ "actionResult" : {
+ "_type" : {
+ "_name" : "ActionResult"
+ },
+ "coverage" : {
+ "_type" : {
+ "_name" : "CodeCoverageInfo"
+ }
+ },
+ "diagnosticsRef" : {
+ "_type" : {
+ "_name" : "Reference"
+ },
+ "id" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "0~jAQXUmgyNkmcnoWDboB4OeaM0-whlsynWt0yZ3wo4KvsnpcYa713pAK1NtXSCTE8Uc0lFtZHoOCqewug4plRDQ=="
+ }
+ },
+ "issues" : {
+ "_type" : {
+ "_name" : "ResultIssueSummaries"
+ }
+ },
+ "logRef" : {
+ "_type" : {
+ "_name" : "Reference"
+ },
+ "id" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "0~Qjtn8Ykt-p4Y2zYr6DbsVuygoZGAblK7Eph8ZFqa-w0iUTl09NihLHxd7DNfeeR1B0dwrjrN5Fvx_yZPpHvUjQ=="
+ },
+ "targetType" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActivityLogSection"
+ }
+ }
+ },
+ "metrics" : {
+ "_type" : {
+ "_name" : "ResultMetrics"
+ },
+ "testsCount" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "1"
+ }
+ },
+ "resultName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "action"
+ },
+ "status" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "succeeded"
+ },
+ "testsRef" : {
+ "_type" : {
+ "_name" : "Reference"
+ },
+ "id" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "0~CRExaYFNITauPqprkYOVFcX44BiMR7Y5SK7vYQTvwKNnaF1--St6QQlAOz693pVVLLQkXitHdwytuCOA_J3AmA=="
+ },
+ "targetType" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActionTestPlanRunSummaries"
+ }
+ }
+ }
+ },
+ "buildResult" : {
+ "_type" : {
+ "_name" : "ActionResult"
+ },
+ "coverage" : {
+ "_type" : {
+ "_name" : "CodeCoverageInfo"
+ }
+ },
+ "issues" : {
+ "_type" : {
+ "_name" : "ResultIssueSummaries"
+ }
+ },
+ "logRef" : {
+ "_type" : {
+ "_name" : "Reference"
+ },
+ "id" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "0~o__Z27AtErlXE6_lRzQF5cFdk50BUQF_aPv-O8Qsdvi5HMz3kXluFX3_xOAAfqzm0-YWnbEyrw1wXekD7fMHEw=="
+ },
+ "targetType" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActivityLogSection"
+ }
+ }
+ },
+ "metrics" : {
+ "_type" : {
+ "_name" : "ResultMetrics"
+ }
+ },
+ "resultName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "build"
+ },
+ "status" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "succeeded"
+ }
+ },
+ "endedTime" : {
+ "_type" : {
+ "_name" : "Date"
+ },
+ "_value" : "2022-09-20T15:39:30.709-0700"
+ },
+ "runDestination" : {
+ "_type" : {
+ "_name" : "ActionRunDestinationRecord"
+ },
+ "displayName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "iPhone 13"
+ },
+ "localComputerRecord" : {
+ "_type" : {
+ "_name" : "ActionDeviceRecord"
+ },
+ "busSpeedInMHz" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "cpuCount" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "1"
+ },
+ "cpuKind" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Apple M1 Pro"
+ },
+ "cpuSpeedInMHz" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "00006000-000239D03CE2801E"
+ },
+ "isConcreteDevice" : {
+ "_type" : {
+ "_name" : "Bool"
+ },
+ "_value" : "true"
+ },
+ "logicalCPUCoresPerPackage" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "10"
+ },
+ "modelCode" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "MacBookPro18,1"
+ },
+ "modelName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "MacBook Pro"
+ },
+ "modelUTI" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.macbookpro-16-2021"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "My Mac"
+ },
+ "nativeArchitecture" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "arm64e"
+ },
+ "operatingSystemVersion" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "12.6"
+ },
+ "operatingSystemVersionWithBuildNumber" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "12.6 (21G115)"
+ },
+ "physicalCPUCoresPerPackage" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "10"
+ },
+ "platformRecord" : {
+ "_type" : {
+ "_name" : "ActionPlatformRecord"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.platform.macosx"
+ },
+ "userDescription" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "macOS"
+ }
+ },
+ "ramSizeInMegabytes" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "16384"
+ }
+ },
+ "targetArchitecture" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "arm64"
+ },
+ "targetDeviceRecord" : {
+ "_type" : {
+ "_name" : "ActionDeviceRecord"
+ },
+ "busSpeedInMHz" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "cpuCount" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "cpuSpeedInMHz" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "7F61C467-4E4A-437C-B6EF-026FEEF3904C"
+ },
+ "isConcreteDevice" : {
+ "_type" : {
+ "_name" : "Bool"
+ },
+ "_value" : "true"
+ },
+ "logicalCPUCoresPerPackage" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "modelCode" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "iPhone14,5"
+ },
+ "modelName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "iPhone 13"
+ },
+ "modelUTI" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.iphone-13-1"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "iPhone 13"
+ },
+ "nativeArchitecture" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "arm64"
+ },
+ "operatingSystemVersion" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "15.2"
+ },
+ "operatingSystemVersionWithBuildNumber" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "15.2 (19C51)"
+ },
+ "physicalCPUCoresPerPackage" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ },
+ "platformRecord" : {
+ "_type" : {
+ "_name" : "ActionPlatformRecord"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "com.apple.platform.iphonesimulator"
+ },
+ "userDescription" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "iOS Simulator"
+ }
+ },
+ "ramSizeInMegabytes" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "0"
+ }
+ },
+ "targetSDKRecord" : {
+ "_type" : {
+ "_name" : "ActionSDKRecord"
+ },
+ "identifier" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "iphonesimulator15.2"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Simulator - iOS 15.2"
+ },
+ "operatingSystemVersion" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "15.2"
+ }
+ }
+ },
+ "schemeCommandName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Test"
+ },
+ "schemeTaskName" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "BuildAndAction"
+ },
+ "startedTime" : {
+ "_type" : {
+ "_name" : "Date"
+ },
+ "_value" : "2022-09-20T15:38:15.930-0700"
+ },
+ "title" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "Testing project benchmark-darwin-sample-xcode with scheme testapp-ios"
+ }
+ }
+ ]
+ },
+ "issues" : {
+ "_type" : {
+ "_name" : "ResultIssueSummaries"
+ }
+ },
+ "metadataRef" : {
+ "_type" : {
+ "_name" : "Reference"
+ },
+ "id" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "0~9QqgSKuPd_WJ00r0MtQ53EH7hHP4lpwwOlDne6b7j-OjJ6jPH5Vm31modXkV3kE_g1-SD2HbuvM_J1hZSGH-mw=="
+ },
+ "targetType" : {
+ "_type" : {
+ "_name" : "TypeDefinition"
+ },
+ "name" : {
+ "_type" : {
+ "_name" : "String"
+ },
+ "_value" : "ActionsInvocationMetadata"
+ }
+ }
+ },
+ "metrics" : {
+ "_type" : {
+ "_name" : "ResultMetrics"
+ },
+ "testsCount" : {
+ "_type" : {
+ "_name" : "Int"
+ },
+ "_value" : "1"
+ }
+ }
+}
diff --git a/benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml b/benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml
index bece70f..b0e054a 100644
--- a/benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml
+++ b/benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml
@@ -1,6 +1,6 @@
# XCodeGen for the :benchmark:benchmark-darwin-samples module..
-name: benchmark-darwin-sample-xcode
+name: benchmark-darwin-samples-xcode
targets:
testapp-ios:
@@ -13,19 +13,9 @@
scheme:
testTargets:
- testapp-ios-benchmarks
- preActions:
- - name: build AndroidXDarwinSampleBenchmarks.xcframework
- basedOnDependencyAnalysis: false
- settingsTarget: testapp-ios
- script: |
- cd ${PROJECT_DIR}/../..
- ANDROIDX_PROJECTS=KMP ./gradlew :benchmark:benchmark-darwin-samples:assembleAndroidXDarwinSampleBenchmarksReleaseXCFramework \
- --no-configuration-cache < /dev/null
- outputFiles:
- - "${PROJECT_DIR}/../../../../out/androidx/benchmark/benchmark-darwin-samples/build/XCFrameworks/release/AndroidXDarwinSampleBenchmarks.xcframework"
gatherCoverageData: false
dependencies:
- - framework: "${PROJECT_DIR}/../../../../out/androidx/benchmark/benchmark-darwin-samples/build/XCFrameworks/release/AndroidXDarwinSampleBenchmarks.xcframework"
+ - framework: "${PROJECT_DIR}/../../../../androidx/benchmark/benchmark-darwin-samples/build/XCFrameworks/release/AndroidXDarwinSampleBenchmarks.xcframework"
settings:
PRODUCT_NAME: testapp-ios
diff --git a/benchmark/benchmark-darwin-samples/build.gradle b/benchmark/benchmark-darwin-samples/build.gradle
index f31dd41..80282e3 100644
--- a/benchmark/benchmark-darwin-samples/build.gradle
+++ b/benchmark/benchmark-darwin-samples/build.gradle
@@ -3,6 +3,7 @@
plugins {
id("AndroidXPlugin")
+ id("androidx.benchmark.darwin")
}
androidXMultiplatform {
@@ -46,6 +47,17 @@
}
}
+darwinBenchmark {
+ xcodeGenConfigFile = project.rootProject.file(
+ "benchmark/benchmark-darwin-samples-xcode/xcodegen-project.yml"
+ )
+ xcodeProjectName = "benchmark-darwin-samples-xcode"
+ scheme = "testapp-ios"
+ // ios 13, 15.2
+ destination = "id=7F61C467-4E4A-437C-B6EF-026FEEF3904C"
+ xcFrameworkConfig = "AndroidXDarwinSampleBenchmarks"
+}
+
androidx {
name = "AndroidX Benchmarks - Darwin Samples"
mavenGroup = LibraryGroups.BENCHMARK
diff --git a/buildSrc/public/build.gradle b/buildSrc/public/build.gradle
index f98bc4c..e37e156 100644
--- a/buildSrc/public/build.gradle
+++ b/buildSrc/public/build.gradle
@@ -4,6 +4,9 @@
main.java.srcDirs += "${supportRootFolder}/benchmark/gradle-plugin/src/main/kotlin"
main.resources.srcDirs += "${supportRootFolder}/benchmark/gradle-plugin/src/main/resources"
+ main.java.srcDirs += "${supportRootFolder}/benchmark/benchmark-darwin-gradle-plugin/src/main/kotlin"
+ main.resources.srcDirs += "${supportRootFolder}/benchmark/benchmark-darwin-gradle-plugin/src/main/resources"
+
main.java.srcDirs += "${supportRootFolder}/inspection/inspection-gradle-plugin/src/main/kotlin"
main.resources.srcDirs += "${supportRootFolder}/inspection/inspection-gradle-plugin/src/main" +
"/resources"
@@ -15,6 +18,11 @@
"src/main/kotlin"
}
+dependencies {
+ // This is for androidx.benchmark.darwin
+ implementation(libs.apacheCommonsMath)
+}
+
gradlePlugin {
plugins {
benchmark {
@@ -25,5 +33,9 @@
id = "androidx.inspection"
implementationClass = "androidx.inspection.gradle.InspectionPlugin"
}
+ darwinBenchmark {
+ id = "androidx.benchmark.darwin"
+ implementationClass = "androidx.benchmark.darwin.gradle.DarwinBenchmarkPlugin"
+ }
}
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6bef6a7..5fd4854 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -82,6 +82,7 @@
apacheAnt = { module = "org.apache.ant:ant", version = "1.10.11" }
apacheCommonsCodec = { module = "commons-codec:commons-codec", version = "1.15" }
apacheCommonIo = { module = "commons-io:commons-io", version = "2.4" }
+apacheCommonsMath = { module = "org.apache.commons:commons-math3", version = "3.6.1" }
assertj = { module = "org.assertj:assertj-core", version = "3.23.1" }
asm = { module = "org.ow2.asm:asm", version.ref = "asm"}
asmCommons = { module = "org.ow2.asm:asm-commons", version.ref = "asm"}
diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys
index 6334dd7..787b19f 100644
--- a/gradle/verification-keyring.keys
+++ b/gradle/verification-keyring.keys
@@ -4496,6 +4496,42 @@
-----END PGP PUBLIC KEY BLOCK-----
+pub 64A16FAAEC16A4BE
+uid Evan Ward <evanward@apache.org>
+
+sub 1E8F1D57A4450BCB
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFbqsT0BCADwERe1Rc9qNWwXOvwZHsjauVDy0TpqNVY8I3S+OYm4rX1dkjyh
++6bTEH1ys6bKevvR+PLhYzTGKboHnMT0RIINY/DQQSzHr/GRyCiiRlRvULbt9Fnz
+kJJDgH2BcbNSmWJlrCqYk+E3GAyQial+szkEZED+02wXHsbs0z3vozjQGHy0RVOj
+Gc5Shwk7Hr/F3vw9EQKa1nNffWmcGEx9B+WcC9ALPVd/fpQVXvlqfbi+kaIbqv2x
+NHQr7BL8j3SpN6vhfZM/3zeghlxQ5HYWER983XwkmvbNdMxt5HWsMKWZ0utt4ocK
+TnQP8NFGlPWEQhPvRRFNb9BI0wvGD0NUb1gjABEBAAG0H0V2YW4gV2FyZCA8ZXZh
+bndhcmRAYXBhY2hlLm9yZz6JATkEEwECACMFAlbqsT0CGwMHCwkIBwMCAQYVCAIJ
+CgsEFgIDAQIeAQIXgAAKCRBkoW+q7BakvnygB/41oiYgfDqkG5srQ4nC7jE0Pe5V
+MnuLVHqsfJBGPvt2tz5+Z1ciIFFwUi/xsafX5DhC+FVOOGdeEnkKnskPBOI7uMFh
+v/s90lbhNV62LfwcS9hptE4qn0JTg7mYiiL0Zue99mlkeP105+GlMmvH5q54X2Le
+hIDBVR8DehL8ZqZCvNEVK1ftpx45mvF/4yh0YK0oVuCAAzwF9+6OxeWTCUTRHTZC
+4CWjtXKUHMq4nTRSp0wGdqd5UV0VbMn0bKTkhgRNCJAKyFw6lJ0FZWwmuG28T0s+
+bKuRAJHTAZmSM7UmBnKo22t9whNcozcqxWhK1lcS4OWEArXpCKxAx4kXmbwnuQEN
+BFbqsT0BCADj5dHK9K27rmkFscDY6x53w4L/X6AYKmVu7Qol7VhR+1WtZXgxZaLM
+xDxj5RK4sNOIqh6R3vEMlAVS+iYbzahI/A0fcSciCoLCgjJKCR3STnTu2k0D/MO0
+la+wF/bGPa0UADGIJLRCjalkl5uv4c7zZbyLnRl8a9XSc81cp2WJTxafZJlJkFOU
+4cyewwFuH0pwMvc9Wmwhkh5IeBF6w8Asj77M5bzJINXYxtKMGYA506609HrvN0+r
+obfgx4Aqy4hGKsqXMsSZiuPDvbdtH3gIRV8NPdYRq+dQg/gv222Y3G1xprDVbl1A
+1CCHlaUqT2lIFPovjoB2O2SBeX9xKRJzABEBAAGJAR8EGAECAAkFAlbqsT0CGwwA
+CgkQZKFvquwWpL4yawf/WDI4VqLkR9RqaX3am/kS8481pZPWZUlCCL7jONB7X7eG
+Bit/FjmQWzfL5nWAEB5qhm2qqCgvgtPmVxCrQLECVmaGmDFmhGIFh8TQsYvQJPK6
+HZDxZj97lUKsG/ojOY4ZArvZnsXBU6C963QUZF+P5UL52n1pE/ByMV1R3enEfrYI
+X+wZslOx5uRFOR8dgUpG/ohh2vkFCaKD6KJQHm6C5lGBgUNqGMFxp1nknKJaNqYq
+jvippm6KcocWARfTHx6Xm3mBqxigmpsalUKAGpjcsxsIEY6jnnN/5i5y1XeokTY8
+6fqEt2OSFSkWiApqq6lxMRluTiq33bSquTxSomKfQQ==
+=PImz
+-----END PGP PUBLIC KEY BLOCK-----
+
+
pub 6525FD70CC303655
uid Stephane Nicoll <snicoll@apache.org>
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 805dbeb..f5b29b5 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -146,6 +146,7 @@
<trusted-key id="3f36885c24df4b75" group="org.mozilla"/>
<trusted-key id="3faad2cd5ecbb314" group="org.apache.commons"/>
<trusted-key id="41321490758aad6f" group="org.codehaus.groovy"/>
+ <trusted-key id="41a1a08c62fca78b79d3081164a16faaec16a4be" group="org.apache.commons" name="commons-math3"/>
<trusted-key id="41cd49b4ef5876f9e9f691dabac30622339994c4">
<trusting group="com.google.testing.compile"/>
<trusting group="com.google.truth"/>
diff --git a/settings.gradle b/settings.gradle
index fbc4a7c..331f5c6 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -384,6 +384,7 @@
includeProject(":benchmark:benchmark-darwin", [BuildType.KMP])
includeProject(":benchmark:benchmark-darwin-core", [BuildType.KMP])
includeProject(":benchmark:benchmark-darwin-samples", [BuildType.KMP])
+includeProject(":benchmark:benchmark-darwin-gradle-plugin", [BuildType.KMP])
includeProject(":benchmark:benchmark-gradle-plugin", "benchmark/gradle-plugin", [BuildType.MAIN])
includeProject(":benchmark:benchmark-junit4")
includeProject(":benchmark:benchmark-macro", [BuildType.MAIN, BuildType.COMPOSE])