Skip to content

Commit

Permalink
BuildArtifacts enum
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladislav Alekseev committed Nov 29, 2021
1 parent 8586f8e commit 28ac5b6
Show file tree
Hide file tree
Showing 52 changed files with 369 additions and 643 deletions.
3 changes: 1 addition & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ let package = Package(
"AppleTools",
"AppleToolsTestHelpers",
"BuildArtifacts",
"BuildArtifactsTestHelpers",
.product(name: "DateProvider", package: "CommandLineToolkit"),
.product(name: "DateProviderTestHelpers", package: "CommandLineToolkit"),
"DeveloperDirLocator",
Expand All @@ -75,7 +74,6 @@ let package = Package(
.product(name: "PathLib", package: "CommandLineToolkit"),
.product(name: "ProcessController", package: "CommandLineToolkit"),
.product(name: "ProcessControllerTestHelpers", package: "CommandLineToolkit"),
"QueueModelsTestHelpers",
"ResourceLocationResolver",
"ResourceLocationResolverTestHelpers",
"ResultStreamModels",
Expand Down Expand Up @@ -261,6 +259,7 @@ let package = Package(
dependencies: [
"BuildArtifacts",
"ResourceLocation",
"TestDiscovery",
],
path: "Tests/BuildArtifactsTestHelpers"
),
Expand Down
55 changes: 24 additions & 31 deletions Sources/AppleTools/XcTestRunFileArgument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public final class XcTestRunFileArgument: SubprocessArgument, CustomStringConver
private let path: AbsolutePath
private let resourceLocationResolver: ResourceLocationResolver
private let testContext: TestContext
private let testType: TestType
private let testingEnvironment: XcTestRunTestingEnvironment

public enum XcTestRunFileArgumentError: CustomStringConvertible, Error {
Expand All @@ -34,20 +33,18 @@ public final class XcTestRunFileArgument: SubprocessArgument, CustomStringConver
path: AbsolutePath,
resourceLocationResolver: ResourceLocationResolver,
testContext: TestContext,
testType: TestType,
testingEnvironment: XcTestRunTestingEnvironment
) {
self.buildArtifacts = buildArtifacts
self.entriesToRun = entriesToRun
self.path = path
self.resourceLocationResolver = resourceLocationResolver
self.testContext = testContext
self.testType = testType
self.testingEnvironment = testingEnvironment
}

public var description: String {
"<\(type(of: self)) tests: \(entriesToRun.map { $0.testName }), testType \(testType), environment \(testContext.environment), path: \(path)>"
"<\(type(of: self)) tests: \(entriesToRun.map { $0.testName }), environment \(testContext.environment), path: \(path)>"
}

public func stringValue() throws -> String {
Expand All @@ -61,20 +58,22 @@ public final class XcTestRunFileArgument: SubprocessArgument, CustomStringConver
}

private func createXcTestRun() throws -> XcTestRun {
let resolvableXcTestBundle = resourceLocationResolver.resolvable(withRepresentable: buildArtifacts.xcTestBundle.location)

switch testType {
case .uiTest:
return try xcTestRunForUiTesting(
resolvableXcTestBundle: resolvableXcTestBundle
)
case .logicTest:
switch buildArtifacts {
case .iosLogicTests(let xcTestBundle):
return try xcTestRunForLogicTesting(
resolvableXcTestBundle: resolvableXcTestBundle
resolvableXcTestBundle: resourceLocationResolver.resolvable(withRepresentable: xcTestBundle.location)
)
case .appTest:
case .iosApplicationTests(let xcTestBundle, let appBundle):
return try xcTestRunForApplicationTesting(
resolvableXcTestBundle: resolvableXcTestBundle
resolvableXcTestBundle: resourceLocationResolver.resolvable(withRepresentable: xcTestBundle.location),
resolvableAppBundle: resourceLocationResolver.resolvable(withRepresentable: appBundle)
)
case .iosUiTests(let xcTestBundle, let appBundle, let runner, let additionalApps):
return try xcTestRunForUiTesting(
resolvableXcTestBundle: resourceLocationResolver.resolvable(withRepresentable: xcTestBundle.location),
resolvableAppBundle: resourceLocationResolver.resolvable(withRepresentable: appBundle),
resolvableRunnerBundle: resourceLocationResolver.resolvable(withRepresentable: runner),
resolvableAdditionalAppBundles: additionalApps.map { resourceLocationResolver.resolvable(withRepresentable: $0) }
)
}
}
Expand Down Expand Up @@ -125,12 +124,10 @@ public final class XcTestRunFileArgument: SubprocessArgument, CustomStringConver
}

private func xcTestRunForApplicationTesting(
resolvableXcTestBundle: ResolvableResourceLocation
resolvableXcTestBundle: ResolvableResourceLocation,
resolvableAppBundle: ResolvableResourceLocation
) throws -> XcTestRun {
guard let representableAppBundle = buildArtifacts.appBundle else {
throw RunnerError.noAppBundleDefinedForUiOrApplicationTesting
}
let hostAppPath = try resourceLocationResolver.resolvable(resourceLocation: representableAppBundle.resourceLocation).resolve().directlyAccessibleResourcePath()
let hostAppPath = try resourceLocationResolver.resolvable(resourceLocation: resolvableAppBundle.resourceLocation).resolve().directlyAccessibleResourcePath()
let testBundlePath = try resolvableXcTestBundle.resolve().directlyAccessibleResourcePath()
let testTargetProductModuleName = try self.testTargetProductModuleName(
xcTestBundlePath: testBundlePath
Expand Down Expand Up @@ -178,19 +175,15 @@ public final class XcTestRunFileArgument: SubprocessArgument, CustomStringConver
}

private func xcTestRunForUiTesting(
resolvableXcTestBundle: ResolvableResourceLocation
resolvableXcTestBundle: ResolvableResourceLocation,
resolvableAppBundle: ResolvableResourceLocation,
resolvableRunnerBundle: ResolvableResourceLocation,
resolvableAdditionalAppBundles: [ResolvableResourceLocation]
) throws -> XcTestRun {
guard let representableAppBundle = buildArtifacts.appBundle else {
throw RunnerError.noAppBundleDefinedForUiOrApplicationTesting
}
guard let representableRunnerBundle = buildArtifacts.runner else {
throw RunnerError.noRunnerAppDefinedForUiTesting
}

let uiTargetAppPath = try resourceLocationResolver.resolvable(resourceLocation: representableAppBundle.resourceLocation).resolve().directlyAccessibleResourcePath()
let hostAppPath = try resourceLocationResolver.resolvable(resourceLocation: representableRunnerBundle.resourceLocation).resolve().directlyAccessibleResourcePath()
let uiTargetAppPath = try resourceLocationResolver.resolvable(resourceLocation: resolvableAppBundle.resourceLocation).resolve().directlyAccessibleResourcePath()
let hostAppPath = try resourceLocationResolver.resolvable(resourceLocation: resolvableRunnerBundle.resourceLocation).resolve().directlyAccessibleResourcePath()
let testBundlePath = try resolvableXcTestBundle.resolve().directlyAccessibleResourcePath()
let additionalApplicationBundlePaths: [AbsolutePath] = try buildArtifacts.additionalApplicationBundles.map {
let additionalApplicationBundlePaths: [AbsolutePath] = try resolvableAdditionalAppBundles.map {
try resourceLocationResolver.resolvable(resourceLocation: $0.resourceLocation).resolve().directlyAccessibleResourcePath()
}
let testTargetProductModuleName = try self.testTargetProductModuleName(
Expand Down
4 changes: 1 addition & 3 deletions Sources/AppleTools/XcodebuildBasedTestRunner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ public final class XcodebuildBasedTestRunner: TestRunner {
runnerWasteCollector: RunnerWasteCollector,
simulator: Simulator,
testContext: TestContext,
testRunnerStream: TestRunnerStream,
testType: TestType
testRunnerStream: TestRunnerStream
) throws -> TestRunnerInvocation {
let resultStreamFile = testContext.testRunnerWorkingDirectory.appending(component: "result_stream.json")
try fileSystem.createFile(atPath: resultStreamFile, data: nil)
Expand All @@ -61,7 +60,6 @@ public final class XcodebuildBasedTestRunner: TestRunner {
path: testContext.testRunnerWorkingDirectory.appending(component: "testrun.xctestrun"),
resourceLocationResolver: resourceLocationResolver,
testContext: testContext,
testType: testType,
testingEnvironment: XcTestRunTestingEnvironment(insertedLibraries: [])
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ public final class SingleBucketQueueRunningQueueStateProvider: RunningQueueState
for dequeuedBucket in dequeuedBuckets {
dequeuedTests.append(
key: dequeuedBucket.workerId,
elements: dequeuedBucket.enqueuedBucket.bucket.runTestsBucketPayload.testEntries.map { $0.testName }
elements: dequeuedBucket.enqueuedBucket.bucket.payload.testEntries.map { $0.testName }
)
}

return RunningQueueState(
enqueuedBucketCount: enqueuedBuckets.count,
enqueuedTests: enqueuedBuckets.flatMap { $0.bucket.runTestsBucketPayload.testEntries.map { $0.testName } },
enqueuedTests: enqueuedBuckets.flatMap { $0.bucket.payload.testEntries.map { $0.testName } },
dequeuedBucketCount: dequeuedBuckets.count,
dequeuedTests: dequeuedTests
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ public final class SingleBucketQueueStuckBucketsReenqueuer: StuckBucketsReenqueu

// Every stucked test produces a single bucket with itself
let buckets = try stuckBuckets.flatMap { stuckBucket in
try stuckBucket.bucket.runTestsBucketPayload.testEntries.map { testEntry in
try stuckBucket.bucket.payload.testEntries.map { testEntry in
try stuckBucket.bucket.with(
newBucketId: BucketId(value: uniqueIdentifierGenerator.generate()),
newRunTestsBucketPayload: stuckBucket.bucket.runTestsBucketPayload.with(
newPayload: stuckBucket.bucket.payload.with(
testEntries: [testEntry]
)
)
Expand Down
4 changes: 2 additions & 2 deletions Sources/BucketQueue/Impls/SingleBucketResultAccepter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public final class SingleBucketResultAccepter: BucketResultAccepter {
}

let actualTestEntries = Set(testingResult.unfilteredResults.map { $0.testEntry })
let expectedTestEntries = Set(dequeuedBucket.enqueuedBucket.bucket.runTestsBucketPayload.testEntries)
let expectedTestEntries = Set(dequeuedBucket.enqueuedBucket.bucket.payload.testEntries)
try reenqueueLostResults(
expectedTestEntries: expectedTestEntries,
actualTestEntries: actualTestEntries,
Expand Down Expand Up @@ -73,7 +73,7 @@ public final class SingleBucketResultAccepter: BucketResultAccepter {
logger.debug("Test result for \(bucket.bucketId) from \(workerId) contains lost test entries: \(lostTestEntries)")
let lostResult = try testHistoryTracker.accept(
testingResult: TestingResult(
testDestination: bucket.runTestsBucketPayload.testDestination,
testDestination: bucket.payload.testDestination,
unfilteredResults: lostTestEntries.map { .lost(testEntry: $0) }
),
bucket: bucket,
Expand Down
105 changes: 61 additions & 44 deletions Sources/BuildArtifacts/BuildArtifacts.swift
Original file line number Diff line number Diff line change
@@ -1,74 +1,91 @@
import Foundation

public struct BuildArtifacts: Codable, Hashable, CustomStringConvertible {
/// Location of app bundle
public let appBundle: AppBundleLocation?

/// Location of runner app build artifact (XCTRunner.app)
public let runner: RunnerAppLocation?

/// Location of xctest bundle with tests to run. Usually it is a part of Runner.app/Plugins.
public let xcTestBundle: XcTestBundle

/// Location of additional apps that can be launched diring tests.
public let additionalApplicationBundles: [AdditionalAppBundleLocation]
public enum BuildArtifacts: Codable, Hashable, CustomStringConvertible {
case iosLogicTests(
xcTestBundle: XcTestBundle
)

case iosApplicationTests(
xcTestBundle: XcTestBundle,
appBundle: AppBundleLocation
)

public init(
appBundle: AppBundleLocation?,
runner: RunnerAppLocation?,
case iosUiTests(
xcTestBundle: XcTestBundle,
additionalApplicationBundles: [AdditionalAppBundleLocation])
{
self.appBundle = appBundle
self.runner = runner
self.xcTestBundle = xcTestBundle
self.additionalApplicationBundles = additionalApplicationBundles
appBundle: AppBundleLocation,
runner: RunnerAppLocation,
additionalApplicationBundles: [AdditionalAppBundleLocation]
)

public var xcTestBundle: XcTestBundle {
switch self {
case .iosLogicTests(let xcTestBundle):
return xcTestBundle
case .iosApplicationTests(let xcTestBundle, _):
return xcTestBundle
case .iosUiTests(let xcTestBundle, _, _, _):
return xcTestBundle
}
}

private enum CodingKeys: CodingKey {
case xcTestBundle
case appBundle
case runner
case xcTestBundle
case additionalApplicationBundles
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.appBundle = try container.decodeIfPresent(AppBundleLocation.self, forKey: .appBundle)
self.runner = try container.decodeIfPresent(RunnerAppLocation.self, forKey: .runner)
self.xcTestBundle = try container.decode(XcTestBundle.self, forKey: .xcTestBundle)
let xcTestBundle = try container.decode(XcTestBundle.self, forKey: .xcTestBundle)

self.additionalApplicationBundles = try container.decodeIfPresent(
[AdditionalAppBundleLocation].self, forKey: .additionalApplicationBundles
) ?? []
if let runner = try container.decodeIfPresent(RunnerAppLocation.self, forKey: .runner) {
let appBundle = try container.decode(AppBundleLocation.self, forKey: .appBundle)
self = .iosUiTests(
xcTestBundle: xcTestBundle,
appBundle: appBundle,
runner: runner,
additionalApplicationBundles: try container.decodeIfPresent(
[AdditionalAppBundleLocation].self, forKey: .additionalApplicationBundles
) ?? []
)
} else if let appBundle = try container.decodeIfPresent(AppBundleLocation.self, forKey: .appBundle) {
self = .iosApplicationTests(
xcTestBundle: xcTestBundle,
appBundle: appBundle
)
} else {
self = .iosLogicTests(xcTestBundle: xcTestBundle)
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(xcTestBundle, forKey: .xcTestBundle)
try container.encode(additionalApplicationBundles, forKey: .additionalApplicationBundles)

if let appBundle = appBundle {
switch self {
case .iosLogicTests(let xcTestBundle):
try container.encode(xcTestBundle, forKey: .xcTestBundle)

case .iosApplicationTests(let xcTestBundle, let appBundle):
try container.encode(xcTestBundle, forKey: .xcTestBundle)
try container.encode(appBundle, forKey: .appBundle)
}

if let runner = runner {
case .iosUiTests(let xcTestBundle, let appBundle, let runner, let additionalApplicationBundles):
try container.encode(xcTestBundle, forKey: .xcTestBundle)
try container.encode(appBundle, forKey: .appBundle)
try container.encode(runner, forKey: .runner)
try container.encode(additionalApplicationBundles, forKey: .additionalApplicationBundles)
}
}

public var description: String {
var result: [String] = []
if let appBundle = appBundle {
result += ["appBundle: \(appBundle)"]
}
if let runner = runner {
result += ["runner: \(runner)"]
}
result += ["xcTestBundle: \(xcTestBundle)"]
if !additionalApplicationBundles.isEmpty {
result += ["additionalApplicationBundles: \(additionalApplicationBundles)"]
switch self {
case .iosLogicTests(let xcTestBundle):
return "iOS logic tests \(xcTestBundle)"
case .iosApplicationTests(let xcTestBundle, let appBundle):
return "iOS application tests \(xcTestBundle) \(appBundle)"
case .iosUiTests(let xcTestBundle, let appBundle, let runner, let additionalApplicationBundles):
return "iOS UI tests \(xcTestBundle) \(appBundle) \(runner) \(additionalApplicationBundles)"
}
return "<\(type(of: self)): " + result.joined(separator: " ") + ">"
}
}
2 changes: 1 addition & 1 deletion Sources/DistWorker/DistWorker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public final class DistWorker: SchedulerDataSource, SchedulerDelegate {
SchedulerBucket.from(
bucket: fetchedBucket,
testExecutionBehavior: TestExecutionBehavior(
environment: fetchedBucket.runTestsBucketPayload.testExecutionBehavior.environment,
environment: fetchedBucket.payload.testExecutionBehavior.environment,
numberOfRetries: 0
)
)
Expand Down
21 changes: 10 additions & 11 deletions Sources/EmceeLib/Commands/InitTestArgFileCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,16 @@ public final class InitTestArgFileCommand: Command {
let testArgFile = TestArgFile(
entries: [
TestArgFileEntry(
buildArtifacts: BuildArtifacts(
buildArtifacts: BuildArtifacts.iosUiTests(
xcTestBundle: XcTestBundle(
location: TestBundleLocation(
.remoteUrl(
URL(string: "http://storage.example.com/build1234/FunctionalTests.zip#FunctionalTests.xctest")!,
nil
)
),
testDiscoveryMode: .parseFunctionSymbols
),
appBundle: AppBundleLocation(
.remoteUrl(
URL(string: "http://storage.example.com/build1234/MainApp.zip#MainApp.app")!,
Expand All @@ -54,15 +63,6 @@ public final class InitTestArgFileCommand: Command {
nil
)
),
xcTestBundle: XcTestBundle(
location: TestBundleLocation(
.remoteUrl(
URL(string: "http://storage.example.com/build1234/FunctionalTests.zip#FunctionalTests.xctest")!,
nil
)
),
testDiscoveryMode: .parseFunctionSymbols
),
additionalApplicationBundles: [
AdditionalAppBundleLocation(
.remoteUrl(
Expand Down Expand Up @@ -106,7 +106,6 @@ public final class InitTestArgFileCommand: Command {
testDestination: testDestination,
testRunnerTool: TestArgFileDefaultValues.testRunnerTool,
testTimeoutConfiguration: TestArgFileDefaultValues.testTimeoutConfiguration,
testType: .uiTest,
testsToRun: [
.testName(TestName(className: "ClassName", methodName: "test")),
.testName(TestName(className: "ClassName", methodName: "testSpecificTestMethodName__youCanRepeatTestNamesMultipleTimes__toMakeTestRunSeveralTimes")),
Expand Down
Loading

0 comments on commit 28ac5b6

Please sign in to comment.