<commit_before>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import XCTest
@testable import NIO
import NIOConcurrencyHelpers

func withPipe(_ body: (NIO.NIOFileHandle, NIO.NIOFileHandle) throws -> [NIO.NIOFileHandle]) throws {
    var fds: [Int32] = [-1, -1]
    fds.withUnsafeMutableBufferPointer { ptr in
        XCTAssertEqual(0, pipe(ptr.baseAddress!))
    }
    let readFH = NIOFileHandle(descriptor: fds[0])
    let writeFH = NIOFileHandle(descriptor: fds[1])
    var toClose: [NIOFileHandle] = [readFH, writeFH]
    var error: Error? = nil
    do {
        toClose = try body(readFH, writeFH)
    } catch let err {
        error = err
    }
    try toClose.forEach { fh in
        XCTAssertNoThrow(try fh.close())
    }
    if let error = error {
        throw error
    }
}

func withTemporaryDirectory<T>(_ body: (String) throws -> T) rethrows -> T {
    let dir = createTemporaryDirectory()
    defer {
        try? FileManager.default.removeItem(atPath: dir)
    }
    return try body(dir)
}

/// This function creates a filename that can be used for a temporary UNIX domain socket path.
///
/// If the temporary directory is too long to store a UNIX domain socket path, it will `chdir` into the temporary
/// directory and return a short-enough path. The iOS simulator is known to have too long paths.
func withTemporaryUnixDomainSocketPathName<T>(directory: String = temporaryDirectory,
                                              _ body: (String) throws -> T) throws -> T {
    // this is racy but we're trying to create the shortest possible path so we can't add a directory...
    let (fd, path) = openTemporaryFile()
    try! Posix.close(descriptor: fd)
    try! FileManager.default.removeItem(atPath: path)

    let saveCurrentDirectory = FileManager.default.currentDirectoryPath
    let restoreSavedCWD: Bool
    let shortEnoughPath: String
    do {
        _ = try SocketAddress(unixDomainSocketPath: path)
        // this seems to be short enough for a UDS
        shortEnoughPath = path
        restoreSavedCWD = false
    } catch SocketAddressError.unixDomainSocketPathTooLong {
        FileManager.default.changeCurrentDirectoryPath(URL(fileURLWithPath: path).deletingLastPathComponent().absoluteString)
        shortEnoughPath = URL(fileURLWithPath: path).lastPathComponent
        restoreSavedCWD = true
        print("WARNING: Path '\(path)' could not be used as UNIX domain socket path, using chdir & '\(shortEnoughPath)'")
    }
    defer {
        if FileManager.default.fileExists(atPath: path) {
            try? FileManager.default.removeItem(atPath: path)
        }
        if restoreSavedCWD {
            FileManager.default.changeCurrentDirectoryPath(saveCurrentDirectory)
        }
    }
    return try body(shortEnoughPath)
}

func withTemporaryFile<T>(content: String? = nil, _ body: (NIO.NIOFileHandle, String) throws -> T) rethrows -> T {
    let (fd, path) = openTemporaryFile()
    let fileHandle = NIOFileHandle(descriptor: fd)
    defer {
        XCTAssertNoThrow(try fileHandle.close())
        XCTAssertEqual(0, unlink(path))
    }
    if let content = content {
        try Array(content.utf8).withUnsafeBufferPointer { ptr in
            var toWrite = ptr.count
            var start = ptr.baseAddress!
            while toWrite > 0 {
                let res = try Posix.write(descriptor: fd, pointer: start, size: toWrite)
                switch res {
                case .processed(let written):
                    toWrite -= written
                    start = start + written
                case .wouldBlock:
                    XCTFail("unexpectedly got .wouldBlock from a file")
                    continue
                }
            }
            XCTAssertEqual(0, lseek(fd, 0, SEEK_SET))
        }
    }
    return try body(fileHandle, path)
}
var temporaryDirectory: String {
    get {
#if os(Android)
        return "/data/local/tmp"
#elseif os(Linux)
        return "/tmp"
#else
        if #available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) {
            return FileManager.default.temporaryDirectory.path
        } else {
            return "/tmp"
        }
#endif
    }
}

func createTemporaryDirectory() -> String {
    let template = "\(temporaryDirectory)/.NIOTests-temp-dir_XXXXXX"

    var templateBytes = template.utf8 + [0]<commit_msg>fix tests in iOS Simulator (#1171)<commit_after>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import XCTest
@testable import NIO
import NIOConcurrencyHelpers

func withPipe(_ body: (NIO.NIOFileHandle, NIO.NIOFileHandle) throws -> [NIO.NIOFileHandle]) throws {
    var fds: [Int32] = [-1, -1]
    fds.withUnsafeMutableBufferPointer { ptr in
        XCTAssertEqual(0, pipe(ptr.baseAddress!))
    }
    let readFH = NIOFileHandle(descriptor: fds[0])
    let writeFH = NIOFileHandle(descriptor: fds[1])
    var toClose: [NIOFileHandle] = [readFH, writeFH]
    var error: Error? = nil
    do {
        toClose = try body(readFH, writeFH)
    } catch let err {
        error = err
    }
    try toClose.forEach { fh in
        XCTAssertNoThrow(try fh.close())
    }
    if let error = error {
        throw error
    }
}

func withTemporaryDirectory<T>(_ body: (String) throws -> T) rethrows -> T {
    let dir = createTemporaryDirectory()
    defer {
        try? FileManager.default.removeItem(atPath: dir)
    }
    return try body(dir)
}

/// This function creates a filename that can be used for a temporary UNIX domain socket path.
///
/// If the temporary directory is too long to store a UNIX domain socket path, it will `chdir` into the temporary
/// directory and return a short-enough path. The iOS simulator is known to have too long paths.
func withTemporaryUnixDomainSocketPathName<T>(directory: String = temporaryDirectory,
                                              _ body: (String) throws -> T) throws -> T {
    // this is racy but we're trying to create the shortest possible path so we can't add a directory...
    let (fd, path) = openTemporaryFile()
    try! Posix.close(descriptor: fd)
    try! FileManager.default.removeItem(atPath: path)

    let saveCurrentDirectory = FileManager.default.currentDirectoryPath
    let restoreSavedCWD: Bool
    let shortEnoughPath: String
    do {
        _ = try SocketAddress(unixDomainSocketPath: path)
        // this seems to be short enough for a UDS
        shortEnoughPath = path
        restoreSavedCWD = false
    } catch SocketAddressError.unixDomainSocketPathTooLong {
        FileManager.default.changeCurrentDirectoryPath(URL(fileURLWithPath: path).deletingLastPathComponent().absoluteString)
        shortEnoughPath = URL(fileURLWithPath: path).lastPathComponent
        restoreSavedCWD = true
        print("WARNING: Path '\(path)' could not be used as UNIX domain socket path, using chdir & '\(shortEnoughPath)'")
    }
    defer {
        if FileManager.default.fileExists(atPath: path) {
            try? FileManager.default.removeItem(atPath: path)
        }
        if restoreSavedCWD {
            FileManager.default.changeCurrentDirectoryPath(saveCurrentDirectory)
        }
    }
    return try body(shortEnoughPath)
}

func withTemporaryFile<T>(content: String? = nil, _ body: (NIO.NIOFileHandle, String) throws -> T) rethrows -> T {
    let (fd, path) = openTemporaryFile()
    let fileHandle = NIOFileHandle(descriptor: fd)
    defer {
        XCTAssertNoThrow(try fileHandle.close())
        XCTAssertEqual(0, unlink(path))
    }
    if let content = content {
        try Array(content.utf8).withUnsafeBufferPointer { ptr in
            var toWrite = ptr.count
            var start = ptr.baseAddress!
            while toWrite > 0 {
                let res = try Posix.write(descriptor: fd, pointer: start, size: toWrite)
                switch res {
                case .processed(let written):
                    toWrite -= written
                    start = start + written
                case .wouldBlock:
                    XCTFail("unexpectedly got .wouldBlock from a file")
                    continue
                }
            }
            XCTAssertEqual(0, lseek(fd, 0, SEEK_SET))
        }
    }
    return try body(fileHandle, path)
}
var temporaryDirectory: String {
    get {
#if targetEnvironment(simulator)
        // Simulator temp directories are so long (and contain the user name) that they're not usable
        // for UNIX Domain Socket paths (which are limited to 103 bytes).
        return "/tmp"
#else
#if os(Android)
        return "/data/local/tmp"
#elseif os(Linux)
        return "/tmp"
#else
        if #available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *) {
            return FileManager.default.temporaryDirectory.path
        } else {
            return "/tmp"
        }
#endif // os
#endif // targetEnvironment
    }
}

func createTemporaryDirectory() -> String {
    let template = "\(temporaryDirectory)/.NIOTests-temp-dir_XXXXXX"

    var templateBytes = template.utf8 + [0]
{'fraction_non_alphanumeric': 0.12215215622457282, 'fraction_numerical': 0.007831570382424735, 'mean_word_length': 2.2473579920739764, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '336805', 'n_tokens_mistral': 2847, 'n_tokens_neox': 2729, 'n_words': 824}