Skip to content

Conversation

@alex-reilly-dd
Copy link

No description provided.

- Add CoverageTrait that collects isolated coverage for each test
- Automatically enforces serialized execution (LLVM counters are global)
- Resets counters before each test, writes separate .profraw files
- Add InstrProfiling.h declaring LLVM profile runtime functions
- Add tests demonstrating the functionality

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@grynspan
Copy link
Contributor

Code coverage is handled today by whatever tool hosts tests (Xcode or Swift Package Manager.) Can you explain why this is needed?

@alex-reilly-dd
Copy link
Author

@grynspan This isn't ready for review, but I'm likely going to close this and go in a different direction. If I decide to do this, I'll make sure I go through the proper channels.

Copy link
Contributor

@grynspan grynspan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. If you're not ready for a review, please make this a draft PR and we can ignore it until it's further along.

if let dir = Environment.variable(named: "COVERAGE_OUTPUT_DIR") {
return dir
}
if let cwd = swt_getEarlyCWD() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function does not do what you want. It is a helper for OpenBSD only.

//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift project authors
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure the copyright year is accurate for new files.

@@ -0,0 +1,241 @@
//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New source files need to be added to the appropriate CMakeLists.txt file(s).

/// environment variables.
private let _coverageEnabled: Bool = {
// Check for LLVM_PROFILE_FILE environment variable (set by swift test)
Environment.variable(named: "LLVM_PROFILE_FILE") != nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure to document any new environment variable usage in EnvironmentVariables.md.

try await function()
return
}
configuration.isParallelizationEnabled = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not cause the test to run serially with respect to other tests, only with respect to any subtests it contains (test functions if it is a suite, test cases if it is a test function.)

var name = test.name
if let testCase {
// Include test case ID for parameterized tests
name += "-\(testCase.id)"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string form of a test case's ID is not suitable for use as a file name. It may be arbitrarily long (too long to be represented as a filename on some systems) or may contain illegal characters.

var sanitized = ""
for char in name {
switch char {
case "/", ":", " ", "(", ")", ",", "\\", "<", ">", "\"", "|", "?", "*":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider hashing the string instead to get a statistically unique filename?

///
/// @note This function is only available when coverage instrumentation is
/// enabled. Use swt_profilerRuntimeAvailable() to check availability.
SWT_EXTERN void __llvm_profile_reset_counters(void);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we reference these functions when code is not compiled with coverage enabled?

#endif
return dlsym(handle, "__llvm_profile_reset_counters") != NULL;
#else
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need Windows support too. And we need to support building for targets that do not have a dynamic loader.

func profileFunctionsCallable() {
// Reset counters - should not crash
__llvm_profile_reset_counters()
print("Reset counters: OK")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove these print() calls.

@grynspan grynspan added enhancement New feature or request tools integration 🛠️ Integration of swift-testing into tools/IDEs public-api Affects public API traits Issues and PRs related to the trait subsystem or built-in traits labels Nov 26, 2025
@alex-reilly-dd
Copy link
Author

@grynspan This PR is a draft

@grynspan
Copy link
Contributor

You replied while I was reviewing. Sorry for the crossed wires! If you do want to pursue this change, perhaps you can join us in a Testing Workgroup meeting and explain your thinking so we can give your work the support it needs (or may need).

@alex-reilly-dd
Copy link
Author

All good! Will do. I appreciate it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request public-api Affects public API tools integration 🛠️ Integration of swift-testing into tools/IDEs traits Issues and PRs related to the trait subsystem or built-in traits

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants