-
Notifications
You must be signed in to change notification settings - Fork 12
Add testProcess{Config} task to accept user options #581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
42d4d54
6f5c7ba
a13c32a
0a80e41
710ac93
9b9d36e
dff76a3
9e9d6a0
1d5a380
15dbbf7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -429,6 +429,116 @@ class ProfilerTestPlugin : Plugin<Project> { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Create Exec-based test task that always runs in a separate process. | ||
| * Available on all platforms. Supports -Pprofiler.options for overriding profiler settings. | ||
| * Task name: testProcess<Config> (e.g., testProcessDebug, testProcessRelease) | ||
| */ | ||
| private fun createProcessTestTask( | ||
| project: Project, | ||
| extension: ProfilerTestExtension, | ||
| testConfig: TestTaskConfiguration, | ||
| testCfg: Configuration, | ||
| sourceSets: SourceSetContainer | ||
| ) { | ||
| val taskName = "testProcess${testConfig.configName.replaceFirstChar { it.uppercase() }}" | ||
| project.tasks.register(taskName, Exec::class.java) { | ||
| val execTask = this | ||
| execTask.description = "Runs tests in separate process with ${testConfig.configName} library (supports -Pprofiler.options)" | ||
| execTask.group = "verification" | ||
| execTask.onlyIf { testConfig.isActive && !project.hasProperty("skip-tests") } | ||
|
|
||
| // Dependencies | ||
| execTask.dependsOn(project.tasks.named("compileTestJava")) | ||
| execTask.dependsOn(testCfg) | ||
| execTask.dependsOn(sourceSets.getByName("test").output) | ||
|
|
||
| // Configure at execution time to capture properties | ||
| execTask.doFirst { | ||
| execTask.executable = PlatformUtils.testJavaExecutable() | ||
|
|
||
| val allArgs = mutableListOf<String>() | ||
|
|
||
| // JVM args | ||
| allArgs.addAll(testConfig.standardJvmArgs) | ||
| // Version-gated at execution time, when the real test JVM (JAVA_TEST_HOME) is resolvable. | ||
| allArgs.addAll(carrierExportJvmArgs(project)) | ||
| if (extension.nativeLibDir.isPresent) { | ||
| allArgs.add("-Djava.library.path=${extension.nativeLibDir.get().asFile.absolutePath}") | ||
| } | ||
| allArgs.addAll(testConfig.extraJvmArgs) | ||
| allArgs.addAll(testConfig.configJvmArgs) | ||
|
|
||
| // System properties | ||
| testConfig.systemProperties.forEach { (key, value) -> | ||
| allArgs.add("-D$key=$value") | ||
| } | ||
|
|
||
| // Test filter from -Ptests property | ||
| val testsFilter = project.findProperty("tests") as String? | ||
| if (testsFilter != null) { | ||
| allArgs.add("-Dtest.filter=$testsFilter") | ||
| } | ||
|
|
||
| // Profiler options from -Pprofiler.options property | ||
| val profilerOptions = project.findProperty("profiler.options") as String? | ||
| if (profilerOptions != null) { | ||
| allArgs.add("-Dddprof.test.options=$profilerOptions") | ||
| } | ||
|
|
||
| // Classpath | ||
| allArgs.add("-cp") | ||
| allArgs.add(testConfig.testClasspath.asPath) | ||
|
|
||
| // Use custom test runner | ||
| allArgs.add("com.datadoghq.profiler.test.ProfilerTestRunner") | ||
|
|
||
| execTask.args = allArgs | ||
| } | ||
|
|
||
| // Environment variables | ||
| testConfig.environmentVariables.forEach { (key, value) -> | ||
| execTask.environment(key, value) | ||
| } | ||
|
|
||
| // Remove LD_LIBRARY_PATH to let RPATH work correctly | ||
| execTask.doFirst { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it's cleaner do not add LD_LIBRARY_PATH in the loop just above?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you check if it is still the case? I cannot find any loops.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that this loop (a few lines up): adds all environment variables to execTask. And here we are removing it again. You could just filter it in the add-loop, I think. |
||
| val currentLdLibPath = (execTask.environment["LD_LIBRARY_PATH"] as? String) ?: System.getenv("LD_LIBRARY_PATH") | ||
| if (!currentLdLibPath.isNullOrEmpty()) { | ||
| project.logger.info("Removing LD_LIBRARY_PATH to prevent cross-JDK library conflicts (was: $currentLdLibPath)") | ||
| execTask.environment.remove("LD_LIBRARY_PATH") | ||
| } | ||
| } | ||
|
|
||
| // Sanitizer conditions | ||
| when (testConfig.configName) { | ||
| "asan" -> { | ||
| execTask.onlyIf { | ||
| PlatformUtils.locateLibasan() != null && | ||
| !PlatformUtils.isTestJvmJ9() | ||
| } | ||
| // Unlike the Test task's asan variant (setForkEvery(25) above), this task | ||
| // is a single un-forked Exec process running the whole suite in one JVM — | ||
| // there is no forkEvery equivalent for Exec. An unfiltered run would | ||
| // reintroduce the late-suite OOM under ASan's -Xmx512m cap that forkEvery | ||
| // was added to avoid, so require -Ptests to bound the run instead. | ||
| execTask.doFirst { | ||
| if (project.findProperty("tests") == null) { | ||
| throw GradleException( | ||
| "$taskName requires -Ptests=<ClassName|ClassName.method> for the " + | ||
| "asan config: it runs in a single process with no forkEvery " + | ||
| "equivalent, and JFR/JMC allocations accumulate under ASan's " + | ||
| "-Xmx512m heap cap until an unfiltered run OOMs late in the suite. " + | ||
| "For full-suite ASan coverage, use the forked testAsan task instead." | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| "tsan" -> execTask.onlyIf { false } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private fun generateMultiConfigTasks(project: Project, extension: ProfilerTestExtension) { | ||
| val nativeBuildExt = project.rootProject.extensions.findByType(NativeBuildExtension::class.java) | ||
| ?: return // No native build extension, nothing to generate | ||
|
|
@@ -496,6 +606,10 @@ class ProfilerTestPlugin : Plugin<Project> { | |
| createTestTask(project, extension, testConfig, testCfg, sourceSets) | ||
| } | ||
|
|
||
| // Create process-based test task (always uses Exec, available on all platforms) | ||
| // Supports -Pprofiler.options for overriding profiler settings | ||
| createProcessTestTask(project, extension, testConfig, testCfg, sourceSets) | ||
|
|
||
| // Create application tasks for specified configs | ||
| if (configName in applicationConfigs && appMainClass.isNotEmpty()) { | ||
| // Create main configuration | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.