forked from swiftlang/swift-tools-support-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmisc.swift
More file actions
120 lines (108 loc) · 3.93 KB
/
Copy pathmisc.swift
File metadata and controls
120 lines (108 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
This source file is part of the Swift.org open source project
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception
See http://swift.org/LICENSE.txt for license information
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/
import func XCTest.XCTFail
import class Foundation.NSDate
import class Foundation.Thread
import TSCBasic
import TSCUtility
#if canImport(Darwin)
import class Foundation.Bundle
#endif
public enum Configuration {
case Debug
case Release
}
/// Test helper utility for executing a block with a temporary directory.
public func testWithTemporaryDirectory(
function: StaticString = #function,
body: (AbsolutePath) throws -> Void
) throws {
let cleanedFunction = function.description
.replacingOccurrences(of: "(", with: "")
.replacingOccurrences(of: ")", with: "")
.replacingOccurrences(of: ".", with: "")
.replacingOccurrences(of: ":", with: "_")
try withTemporaryDirectory(prefix: "spm-tests-\(cleanedFunction)") { tmpDirPath in
defer {
// Unblock and remove the tmp dir on deinit.
try? localFileSystem.chmod(.userWritable, path: tmpDirPath, options: [.recursive])
try? localFileSystem.removeFileTree(tmpDirPath)
}
try body(tmpDirPath)
}
}
public func systemQuietly(_ args: [String]) throws {
// Discard the output, by default.
//
// FIXME: Find a better default behavior here.
try Process.checkNonZeroExit(arguments: args)
}
public func systemQuietly(_ args: String...) throws {
try systemQuietly(args)
}
/// Temporary override environment variables
///
/// WARNING! This method is not thread-safe. POSIX environments are shared
/// between threads. This means that when this method is called simultaneously
/// from different threads, the environment will neither be setup nor restored
/// correctly.
public func withCustomEnv(_ env: [String: String], body: () throws -> Void) throws {
let state = Array(env.keys).map({ ($0, ProcessEnv.vars[$0]) })
let restore = {
for (key, value) in state {
if let value = value {
try ProcessEnv.setVar(key, value: value)
} else {
try ProcessEnv.unsetVar(key)
}
}
}
do {
for (key, value) in env {
try ProcessEnv.setVar(key, value: value)
}
try body()
} catch {
try? restore()
throw error
}
try restore()
}
/// Waits for a file to appear for around 1 second.
/// Returns true if found, false otherwise.
public func waitForFile(_ path: AbsolutePath) -> Bool {
// setting timeout for 30s as on busy systems (such as CI) this could take a while
let endTime = NSDate().timeIntervalSince1970 + 30
while NSDate().timeIntervalSince1970 < endTime {
// Sleep for a bit so we don't burn a lot of CPU.
Thread.sleep(forTimeInterval: 0.01)
if localFileSystem.exists(path) {
return true
}
}
return false
}
extension Process {
/// If the given pid is running or not.
///
/// - Parameters:
/// - pid: The pid to check.
/// - orDefunct: If set to true, the method will also check if pid is defunct and return false.
/// - Returns: True if the given pid is running.
public static func running(_ pid: ProcessID, orDefunct: Bool = false) throws -> Bool {
// Shell out to `ps -s` instead of using getpgid() as that is more deterministic on linux.
let result = try Process.popen(arguments: ["ps", "-p", String(pid)])
// If ps -p exited with return code 1, it means there is no entry for the process.
var exited = result.exitStatus == .terminated(code: 1)
if orDefunct {
// Check if the process became defunct.
exited = try exited || result.utf8Output().contains("defunct")
}
return !exited
}
}