ResultWriter.kt
/*
* Copyright 2019 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
import android.util.Log
import androidx.annotation.RestrictTo
import androidx.annotation.VisibleForTesting
import androidx.benchmark.json.BenchmarkData
import androidx.test.platform.app.InstrumentationRegistry
import com.squareup.moshi.Moshi
import java.io.File
import java.io.IOException
import okio.FileSystem
import okio.Path.Companion.toPath
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public object ResultWriter {
@VisibleForTesting
internal val reports = mutableListOf<BenchmarkData.TestResult>()
internal val adapter =
Moshi.Builder().build()
.adapter(BenchmarkData::class.java)
.indent(" ") // chosen for test compat, will be changed later
fun appendTestResult(testResult: BenchmarkData.TestResult) {
reports.add(testResult)
if (Arguments.outputEnable) {
// Currently, we just overwrite the whole file
// Ideally, append for efficiency
val packageName = InstrumentationRegistry.getInstrumentation()
.targetContext!!
.packageName
Outputs.writeFile(
fileName = "$packageName-benchmarkData.json",
reportOnRunEndOnly = true
) {
Log.d(
BenchmarkState.TAG,
"writing results to ${it.absolutePath}"
)
writeReport(it, reports)
}
} else {
Log.d(
BenchmarkState.TAG,
"androidx.benchmark.output.enable not set, not writing results json"
)
}
}
@VisibleForTesting
internal fun writeReport(file: File, benchmarks: List<BenchmarkData.TestResult>) {
if (!file.exists()) {
file.parentFile?.mkdirs()
try {
file.createNewFile()
} catch (exception: IOException) {
throw IOException(
"""
Failed to create file for benchmark report in:
$file.parent
Make sure the instrumentation argument additionalTestOutputDir is set
to a writable directory on device. If using a version of Android Gradle
Plugin that doesn't support additionalTestOutputDir, ensure your app's
manifest file enables legacy storage behavior by adding the
application attribute: android:requestLegacyExternalStorage="true"
""".trimIndent(),
exception
)
}
}
val benchmarkData = BenchmarkData(
context = BenchmarkData.Context(),
benchmarks = benchmarks
)
FileSystem.SYSTEM.write(file.absolutePath.toPath()) {
adapter.toJson(this, benchmarkData)
}
}
fun getParams(testName: String): Map<String, String> {
val parameterStrStart = testName.indexOf('[')
val parameterStrEnd = testName.lastIndexOf(']')
val params = HashMap<String, String>()
if (parameterStrStart >= 0 && parameterStrEnd >= 0) {
val paramListString = testName.substring(parameterStrStart + 1, parameterStrEnd)
paramListString.split(",").forEach { paramString ->
val separatorIndex = paramString.indexOfFirst { it == ':' || it == '=' }
if (separatorIndex in 1 until paramString.length - 1) {
val key = paramString.substring(0, separatorIndex)
val value = paramString.substring(separatorIndex + 1)
params[key] = value
}
}
}
return params
}
}