Skip to content

Commit 866b28a

Browse files
authored
Propagate method async-ness during test discovery (#258)
* Sync with main to pick up the Swift async symbol property definition. * Extend `IndexStore.TestCaseClass` to include information about `async` test methods. * Model as a struct instead of enum for easier future expansion. * Take isAsync into account when comparing. * Tweak argument name for clarity.
1 parent 3f23be3 commit 866b28a

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

Sources/TSCUtility/IndexStore.swift

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,19 @@ import TSCBasic
1414
public final class IndexStore {
1515

1616
public struct TestCaseClass {
17+
public struct TestMethod: Hashable, Comparable {
18+
public let name: String
19+
public let isAsync: Bool
20+
21+
public static func < (lhs: IndexStore.TestCaseClass.TestMethod, rhs: IndexStore.TestCaseClass.TestMethod) -> Bool {
22+
return (lhs.name, (lhs.isAsync ? 1 : 0)) < (rhs.name, (rhs.isAsync ? 1 : 0))
23+
}
24+
}
25+
1726
public var name: String
1827
public var module: String
19-
public var methods: [String]
28+
public var testMethods: [TestMethod]
29+
@available(*, deprecated, message: "use testMethods instead") public var methods: [String]
2030
}
2131

2232
fileprivate var impl: IndexStoreImpl { _impl as! IndexStoreImpl }
@@ -90,15 +100,16 @@ private final class IndexStoreImpl {
90100
let recordReader = try api.call{ fn.record_reader_create(store, record, &$0) }
91101

92102
class TestCaseBuilder {
93-
var classToMethods: [String: Set<String>] = [:]
103+
var classToMethods: [String: Set<TestCaseClass.TestMethod>] = [:]
94104

95-
func add(klass: String, method: String) {
96-
classToMethods[klass, default: []].insert(method)
105+
func add(className: String, method: TestCaseClass.TestMethod) {
106+
classToMethods[className, default: []].insert(method)
97107
}
98108

99109
func build() -> [TestCaseClass] {
100110
return classToMethods.map {
101-
TestCaseClass(name: $0.key, module: "", methods: $0.value.sorted())
111+
let testMethods = Array($0.value).sorted()
112+
return TestCaseClass(name: $0.key, module: "", testMethods: testMethods, methods: testMethods.map(\.name))
102113
}
103114
}
104115
}
@@ -112,9 +123,9 @@ private final class IndexStoreImpl {
112123

113124
// Get the symbol.
114125
let sym = fn.occurrence_get_symbol(occ)
115-
126+
let symbolProperties = fn.symbol_get_properties(sym)
116127
// We only care about symbols that are marked unit tests and are instance methods.
117-
if fn.symbol_get_properties(sym) != UInt64(INDEXSTORE_SYMBOL_PROPERTY_UNITTEST.rawValue) {
128+
if symbolProperties & UInt64(INDEXSTORE_SYMBOL_PROPERTY_UNITTEST.rawValue) == 0 {
118129
return true
119130
}
120131
if fn.symbol_get_kind(sym) != INDEXSTORE_SYMBOL_KIND_INSTANCEMETHOD {
@@ -140,8 +151,9 @@ private final class IndexStoreImpl {
140151
}
141152

142153
if !className.instance.isEmpty {
143-
let testMethod = fn.symbol_get_name(sym).str
144-
builder.instance.add(klass: className.instance, method: testMethod)
154+
let methodName = fn.symbol_get_name(sym).str
155+
let isAsync = symbolProperties & UInt64(INDEXSTORE_SYMBOL_PROPERTY_SWIFT_ASYNC.rawValue) != 0
156+
builder.instance.add(className: className.instance, method: TestCaseClass.TestMethod(name: methodName, isAsync: isAsync))
145157
}
146158

147159
return true

Sources/TSCclibc/include/indexstore_functions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ typedef enum {
168168
INDEXSTORE_SYMBOL_PROPERTY_GKINSPECTABLE = 1 << 6,
169169
INDEXSTORE_SYMBOL_PROPERTY_LOCAL = 1 << 7,
170170
INDEXSTORE_SYMBOL_PROPERTY_PROTOCOL_INTERFACE = 1 << 8,
171+
INDEXSTORE_SYMBOL_PROPERTY_SWIFT_ASYNC = 1 << 16,
171172
} indexstore_symbol_property_t;
172173

173174
typedef enum {

0 commit comments

Comments
 (0)