Skip to content

Commit

Permalink
✨ Added support for parsing LogStoreManifest.plist files
Browse files Browse the repository at this point in the history
  • Loading branch information
davidahouse committed Jan 29, 2021
1 parent 8010b38 commit 7fc0bbd
Show file tree
Hide file tree
Showing 5 changed files with 983 additions and 0 deletions.
91 changes: 91 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/XCResultKit.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1230"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XCResultKit"
BuildableName = "XCResultKit"
BlueprintName = "XCResultKit"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XCResultKitTests"
BuildableName = "XCResultKitTests"
BlueprintName = "XCResultKitTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XCResultKitTests"
BuildableName = "XCResultKitTests"
BlueprintName = "XCResultKitTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XCResultKit"
BuildableName = "XCResultKit"
BlueprintName = "XCResultKit"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
59 changes: 59 additions & 0 deletions Sources/XCResultKit/LogStoreExecution.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// File.swift
//
//
// Created by David House on 1/24/21.
//

import Foundation

/// LogStoreExecution represents the details for a single test execution from Xcode
struct LogStoreExecution {
let auxiliaryLogUniqueIdentifier: String
let auxiliaryObservable: [String: String]
let className: String
let documentTypeString: String
let domainType: String
let fileName: String
let hasAuxiliaryLog: Bool
let hasCoverageData: Bool
let hasPrimaryLog: Bool
let primaryObservable: [String: String]
let schemeIdentifierContainerName: String
let schemeIdentifierSchemeName: String
let schemeIdentifierSharedScheme: Int
let signature: String
let timeStartedRecording: Double
let timeStoppedRecording: Double
let title: String
let uniqueIdentifier: String

init(_ details: [String: Any]) {
auxiliaryLogUniqueIdentifier = plistValue("auxiliaryLogUniqueIdentifier", from: details, defaultValue: "")
auxiliaryObservable = plistValue("auxiliaryObservable", from: details, defaultValue: [:])
className = plistValue("className", from: details, defaultValue: "")
documentTypeString = plistValue("documentTypeString", from: details, defaultValue: "")
domainType = plistValue("domainType", from: details, defaultValue: "")
fileName = plistValue("fileName", from: details, defaultValue: "")
hasAuxiliaryLog = plistValue("hasAuxiliaryLog", from: details, defaultValue: false)
hasCoverageData = plistValue("hasCoverageData", from: details, defaultValue: false)
hasPrimaryLog = plistValue("hasPrimaryLog", from: details, defaultValue: false)
primaryObservable = plistValue("primaryObservable", from: details, defaultValue: [:])
schemeIdentifierContainerName = plistValue("schemeIdentifierContainerName", from: details, defaultValue: "")
schemeIdentifierSchemeName = plistValue("schemeIdentifierSchemeName", from: details, defaultValue: "")
schemeIdentifierSharedScheme = plistValue("schemeIdentifierSharedScheme", from: details, defaultValue: 0)
signature = plistValue("signature", from: details, defaultValue: "")
timeStartedRecording = plistValue("timeStartedRecording", from: details, defaultValue: 0.0)
timeStoppedRecording = plistValue("timeStoppedRecording", from: details, defaultValue: 0.0)
title = plistValue("title", from: details, defaultValue: "")
uniqueIdentifier = plistValue("uniqueIdentifier", from: details, defaultValue: "")
}
}

private func plistValue<T>(_ key: String, from details: [String: Any], defaultValue: T) -> T {
if let value = details[key] as? T {
return value
} else {
return defaultValue
}
}
52 changes: 52 additions & 0 deletions Sources/XCResultKit/LogStoreManifest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// File.swift
//
//
// Created by David House on 1/24/21.
//

import Foundation

enum LogStoreManifestError: Error {
case invalidVersion
}

/// Load & parse the LogStoreManifest.plist file that can be found in the Derived Data sub folder
/// Logs/Test. This file contains information about all the test executions captured by Xcode
/// for the project.
class LogStoreManifest {

var executions: [LogStoreExecution] = []

/// Initialize with the path to the LogStoreManifest.plist
init(url: URL) throws {
if let data = try? Data(contentsOf: url),
let plist = try PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil) as? [String: Any] {
try parseExecutions(from: plist)
}
}

/// Initialize with the Data from a LogStoreManifest.plist file
init(data: Data) throws {
if let plist = try PropertyListSerialization.propertyList(from: data, options: .mutableContainers, format: nil) as? [String: Any] {
try parseExecutions(from: plist)
}
}

private func parseExecutions(from plist: [String: Any]) throws {

guard let fileVersion = plist["logFormatVersion"] as? Int, fileVersion == 10 else {
throw LogStoreManifestError.invalidVersion
}

guard let logs = plist["logs"] as? [String: Any] else {
return
}

for (_, value) in logs {
if let executionDetails = value as? [String: Any] {
executions.append(LogStoreExecution(executionDetails))
}
}
}
}
Loading

0 comments on commit 7fc0bbd

Please sign in to comment.