Skip to content

Commit

Permalink
Add functional test for both NDK and Mapping upload
Browse files Browse the repository at this point in the history
Fix other issues from code review.
  • Loading branch information
fuzzybinary committed Feb 8, 2024
1 parent 47811a9 commit 71e285f
Show file tree
Hide file tree
Showing 8 changed files with 205 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class DdAndroidGradlePlugin @Inject constructor(
target: Project,
extension: DdExtension,
variant: ApplicationVariant,
buildIdTask: TaskProvider<GenerateBuildIdTask>,
buildIdTask: TaskProvider<GenerateBuildIdTask>
): TaskProvider<DdNdkSymbolFileUploadTask>? {
val apiKey = resolveApiKey(target)
val extensionConfiguration = resolveExtensionConfiguration(extension, variant)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,17 @@ abstract class DdFileUploadTask @Inject constructor(
val mappingFiles = getFilesList()
if (mappingFiles.isEmpty()) return

var repositories = emptyList<RepositoryInfo>()
repositoryDetector?.let {
repositories = it.detectRepositories(
sourceSetRoots,
remoteRepositoryUrl
)
}
val repositories = repositoryDetector?.detectRepositories(
sourceSetRoots,
remoteRepositoryUrl
).orEmpty()

if (repositories.isNotEmpty()) {
generateRepositoryFile(repositories)
}

val site = DatadogSite.valueOf(site)
var lastError: Exception? = null
var caughtErrors = mutableListOf<Exception>()
for (mappingFile in mappingFiles) {
LOGGER.info("Uploading ${mappingFile.fileType} file: ${mappingFile.file.absolutePath}")
try {
Expand All @@ -178,13 +176,20 @@ abstract class DdFileUploadTask @Inject constructor(
!disableGzipOption.isPresent
)
} catch (e: Exception) {
LOGGER.error("Failed to upload ${mappingFile.fileType} file", e)
lastError = e
caughtErrors.add(e)
}
}
// If any of these errored, throw the last error that occured
if (lastError != null) {
throw lastError
// If any errors occurred, throw them as a single exception
if (caughtErrors.isNotEmpty()) {
if (caughtErrors.count() == 1) {
throw caughtErrors.first()
} else {
val consolidatedError = Exception("Multiple errors occurred during upload")
caughtErrors.forEach {
consolidatedError.addSuppressed(it)
}
throw consolidatedError
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ internal abstract class DdNdkSymbolFileUploadTask @Inject constructor(

searchDirectories
.flatMap(this::findSoFiles)
.toSortedSet(compareBy { it.absolutePath })
.toSet()
.forEach { file ->
val arch = file.parentFile.name
Expand Down Expand Up @@ -72,7 +71,7 @@ internal abstract class DdNdkSymbolFileUploadTask @Inject constructor(
}

companion object {
internal const val TASK_NAME = "ddUploadNdkSymbolFiles"
internal const val TASK_NAME = "uploadNdkSymbolFiles"
internal const val KEY_NDK_SYMBOL_FILE = "ndk_symbol_file"
internal const val TYPE_NDK_SYMBOL_FILE = "ndk_symbol_file"
internal const val ENCODING = "application/octet-stream"
Expand Down Expand Up @@ -104,30 +103,29 @@ internal abstract class DdNdkSymbolFileUploadTask @Inject constructor(
}

@Suppress("MagicNumber", "ReturnCount")
private fun isAgp7OrAbove(): Boolean {
private fun isAgpAbove(major: Int, minor: Int, patch: Int): Boolean {
val version = Version.ANDROID_GRADLE_PLUGIN_VERSION
val groups = version.split(".")
if (groups.size < 3) return false
val major = groups[0].toIntOrNull()
val minor = groups[1].toIntOrNull()
val patch = groups[2].substringBefore("-").toIntOrNull()
if (major == null || minor == null || patch == null) return false
return major >= 7 && minor >= 0 && patch >= 0
val currentMajor = groups[0].toIntOrNull()
val currentMinor = groups[1].toIntOrNull()
val currentPatch = groups[2].substringBefore("-").toIntOrNull()
if (currentMajor == null || currentMinor == null || currentPatch == null) return false
return currentMajor >= major && currentMinor >= minor && currentPatch >= patch
}

private fun fixNativeOutputPath(taskFolder: File): File {
return taskFolder.parentFile.parentFile.takeIf { it.parentFile.name == "cxx" }
?: taskFolder.parentFile.parentFile.parentFile.takeIf { it.parentFile.name == "cxx" }
?: taskFolder
}

private fun getSearchDir(buildTask: TaskProvider<ExternalNativeBuildTask>, propertyName: String, providerFactory: ProviderFactory): Provider<File> {
private fun getSearchDirs(buildTask: TaskProvider<ExternalNativeBuildTask>, providerFactory: ProviderFactory): Provider<File?> {
return buildTask.flatMap { task ->
val soFolder = ExternalNativeBuildTask::class.memberProperties.find { it.name == propertyName }?.get(task)
when (soFolder) {
is File -> providerFactory.provider { fixNativeOutputPath(soFolder) }
is DirectoryProperty -> soFolder.map { fixNativeOutputPath(it.asFile) }
else -> providerFactory.provider { File("") }
// var soFolder: Provider
if (isAgpAbove(8, 0, 0)) {
task.soFolder.map { it.asFile }
} else {
val soFolder = ExternalNativeBuildTask::class.memberProperties.find { it.name == "objFolder" }?.get(task)
when (soFolder) {
is File -> providerFactory.provider { soFolder }
is DirectoryProperty -> soFolder.map { it.asFile }
else -> providerFactory.provider { null }
}
}
}
}
Expand All @@ -144,7 +142,7 @@ internal abstract class DdNdkSymbolFileUploadTask @Inject constructor(
): TaskProvider<DdNdkSymbolFileUploadTask>? {
val nativeBuildProviders = variant.externalNativeBuildProviders
if (nativeBuildProviders.isEmpty()) {
LOGGER.info("No native build tasks found for variant ${variant.name}, skipping symbol file upload.")
LOGGER.info("No native build tasks found for variant ${variant.name}, skipping NDK symbol file upload.")
return null
}

Expand All @@ -155,17 +153,14 @@ internal abstract class DdNdkSymbolFileUploadTask @Inject constructor(
val roots = mutableListOf<File>()
variant.sourceSets.forEach { it ->
roots.addAll(it.javaDirectories)
if (isAgp7OrAbove()) {
if (isAgpAbove(7, 0, 0)) {
roots.addAll(it.kotlinDirectories)
}
}
task.sourceSetRoots = roots

nativeBuildProviders.forEach { buildTask ->
val searchFiles = arrayOf(
getSearchDir(buildTask, "soFolder", providerFactory),
getSearchDir(buildTask, "objFolder", providerFactory)
)
val searchFiles = getSearchDirs(buildTask, providerFactory)

task.searchDirectories.from(searchFiles)
task.dependsOn(buildTask)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ internal class GitRepositoryDetector(
sourceSetRoots: List<File>
): List<String> {
val files = mutableListOf<String>()
LOGGER.info("Listing ${sourceSetRoots}")
sourceSetRoots.forEach { sourceSetRoot ->
LOGGER.info("Listing ${sourceSetRoot.absolutePath}")
if (sourceSetRoot.exists() && sourceSetRoot.isDirectory) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import kotlin.io.path.Path
@Extensions(
ExtendWith(ForgeExtension::class)
)
@ForgeConfiguration(Configurator::class)
@ForgeConfiguration(value = Configurator::class)
internal class DdAndroidGradlePluginFunctionalTest {
@TempDir
lateinit var testProjectDir: File
Expand Down Expand Up @@ -63,7 +63,6 @@ internal class DdAndroidGradlePluginFunctionalTest {
private var cmakeFile: File? = null
private var cppPlaceholderFile: File? = null


@StringForgery(regex = "http[s]?://github\\.com:[1-9]{2}/[a-z]+/repository\\.git")
lateinit var fakeRemoteUrl: String
private val colors = listOf("Blue", "Green")
Expand Down Expand Up @@ -945,7 +944,7 @@ internal class DdAndroidGradlePluginFunctionalTest {

// endregion

// region Symbol Upload
// region NDK Symbol Upload

@Test
fun `M not try to upload the symbol file W no cmake dependencies { using a fake API_KEY }`(forge: Forge) {
Expand Down Expand Up @@ -976,7 +975,7 @@ internal class DdAndroidGradlePluginFunctionalTest {
val version = forge.anElementFrom(versions)
val variantVersionName = version.lowercase()
val variant = "${version.lowercase()}$color"
val taskName = resolveSymbolUploadTask(variant)
val taskName = resolveNdkSymbolUploadTask(variant)

gradleRunner { withArguments("--info", ":samples:app:assembleRelease") }
.build()
Expand All @@ -996,15 +995,15 @@ internal class DdAndroidGradlePluginFunctionalTest {

assertThat(result).containsInOutput("Creating request with GZIP encoding.")

assertThat(result).containsInOutput("Uploading ndk_symbol_file file: ");
assertThat(result).containsInOutput("Uploading ndk_symbol_file file: ")

assertThat(result).containsInOutput(
"Uploading file libplaceholder.so with tags " +
"`service:com.example.variants.$variantVersionName`, " +
"`version:1.0-$variantVersionName`, " +
"`version_code:1`, " +
"`variant:$variant`, " +
"`build_id:$buildIdInOriginFile` (site=datadoghq.com):"
"`service:com.example.variants.$variantVersionName`, " +
"`version:1.0-$variantVersionName`, " +
"`version_code:1`, " +
"`variant:$variant`, " +
"`build_id:$buildIdInOriginFile` (site=datadoghq.com):"
)

for (arch in SUPPORTED_ABIS) {
Expand All @@ -1024,7 +1023,7 @@ internal class DdAndroidGradlePluginFunctionalTest {
val version = forge.anElementFrom(versions)
val variantVersionName = version.lowercase()
val variant = "${version.lowercase()}$color"
val taskName = resolveSymbolUploadTask(variant)
val taskName = resolveNdkSymbolUploadTask(variant)

gradleRunner { withArguments("--info", ":samples:app:assembleRelease") }
.build()
Expand All @@ -1044,15 +1043,15 @@ internal class DdAndroidGradlePluginFunctionalTest {

assertThat(result).containsInOutput("Creating request without GZIP encoding.")

assertThat(result).containsInOutput("Uploading ndk_symbol_file file: ");
assertThat(result).containsInOutput("Uploading ndk_symbol_file file: ")

assertThat(result).containsInOutput(
"Uploading file libplaceholder.so with tags " +
"`service:com.example.variants.$variantVersionName`, " +
"`version:1.0-$variantVersionName`, " +
"`version_code:1`, " +
"`variant:$variant`, " +
"`build_id:$buildIdInOriginFile` (site=datadoghq.com):"
"`service:com.example.variants.$variantVersionName`, " +
"`version:1.0-$variantVersionName`, " +
"`version_code:1`, " +
"`variant:$variant`, " +
"`build_id:$buildIdInOriginFile` (site=datadoghq.com):"
)

for (arch in SUPPORTED_ABIS) {
Expand All @@ -1062,10 +1061,82 @@ internal class DdAndroidGradlePluginFunctionalTest {

// endregion

@Test
fun `M try to upload the symbol file and mapping file W upload { using a fake API_KEY }`(forge: Forge) {
// Given
stubGradleBuildFromResourceFile(
"native_gradle_files/build_with_proguard_native_and_datadog_dep.gradle",
appBuildGradleFile
)
stubNativeFiles()

val color = forge.anElementFrom(colors)
val version = forge.anElementFrom(versions)
val variantVersionName = version.lowercase()
val variant = "${version.lowercase()}$color"
val ndkSymbolUploadTaskName = resolveNdkSymbolUploadTask(variant)
val mappingUploadTaskName = resolveMappingUploadTask(variant)

// When
gradleRunner { withArguments("--info", ":samples:app:assembleRelease") }
.build()

val nativeResult = gradleRunner {
withArguments(
ndkSymbolUploadTaskName,
"--info",
"--stacktrace",
"-PDD_API_KEY=fakekey"
)
}
.buildAndFail()

val mappingResult = gradleRunner {
withArguments(
mappingUploadTaskName,
"--info",
"--stacktrace",
"-PDD_API_KEY=fakekey"
)
}
.buildAndFail()

// Then
val buildIdInOriginFile = testProjectDir.findBuildIdInOriginFile(variant)

assertThat(nativeResult).containsInOutput("Creating request with GZIP encoding.")

assertThat(nativeResult).containsInOutput("Uploading ndk_symbol_file file: ")

assertThat(nativeResult).containsInOutput(
"Uploading file libplaceholder.so with tags " +
"`service:com.example.variants.$variantVersionName`, " +
"`version:1.0-$variantVersionName`, " +
"`version_code:1`, " +
"`variant:$variant`, " +
"`build_id:$buildIdInOriginFile` (site=datadoghq.com):"
)

for (arch in SUPPORTED_ABIS) {
assertThat(nativeResult).containsInOutput("extra attributes: {arch=$arch}")
}

assertThat(mappingResult).containsInOutput("Creating request with GZIP encoding.")

assertThat(mappingResult).containsInOutput(
"Uploading file jvm_mapping with tags " +
"`service:com.example.variants.$variantVersionName`, " +
"`version:1.0-$variantVersionName`, " +
"`version_code:1`, " +
"`variant:$variant`, " +
"`build_id:$buildIdInOriginFile` (site=datadoghq.com):"
)
}

// region Internal

private fun resolveMappingUploadTask(variantName: String) = "uploadMapping${variantName}Release"
private fun resolveSymbolUploadTask(variantName: String) = "ddUploadNdkSymbolFiles${variantName}Release"
private fun resolveNdkSymbolUploadTask(variantName: String) = "uploadNdkSymbolFiles${variantName}Release"

private fun stubFile(destination: File, content: String) {
with(destination.outputStream()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ internal class DdAndroidGradlePluginTest {

// Then
val allTasks = fakeProject.tasks.map { it.name }
assertThat(allTasks).contains("ddUploadNdkSymbolFiles${variantName.replaceFirstChar { capitalizeChar(it) }}")
assertThat(allTasks).contains("uploadNdkSymbolFiles${variantName.replaceFirstChar { capitalizeChar(it) }}")
}

@Test
Expand Down Expand Up @@ -531,7 +531,7 @@ internal class DdAndroidGradlePluginTest {

// Then
val allTasks = fakeProject.tasks.map { it.name }
assertThat(allTasks).allMatch { !it.startsWith("ddUploadNdkSymbolFiles") }
assertThat(allTasks).allMatch { !it.startsWith("uploadNdkSymbolFiles") }
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,6 @@ android {
multiDexEnabled = true
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile ('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

namespace = "com.example.variants"

compileOptions {
Expand Down
Loading

0 comments on commit 71e285f

Please sign in to comment.