File: misc.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (120 lines) | stat: -rw-r--r-- 4,027 bytes parent folder | download
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
    }
}