Skip to content

Commit

Permalink
Merge pull request #21 from finestructure/integration-test
Browse files Browse the repository at this point in the history
Add integration test
  • Loading branch information
finestructure authored Mar 2, 2020
2 parents 77f2337 + 5f4ba3f commit daaea7b
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
50 changes: 50 additions & 0 deletions Tests/ArenaTests/IntegrationTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// IntegrationTests.swift
// ArenaTests
//
// Created by Sven A. Schmidt on 02/03/2020.
//

@testable import ArenaCore
import XCTest


class IntegrationTests: XCTestCase {

#if swift(>=5.2)
func test_ArenaTest() throws {
try XCTSkipUnless(ProcessInfo().hostName == "luna.local", "fails on CI, only run locally")

let output = OutputListener()
output.openConsolePipe()

let arena = try Arena.parse([
"https://github.com/finestructure/[email protected]",
"--name=ArenaIntegrationTest",
"--force",
"--skip-open"])
try arena.run()

let expectation = """
🔧 resolving package dependencies
📔 libraries found: ArenaTest
🔨 building package dependencies
✅ created project in folder '../../tmp/ArenaIntegrationTest'
Run
open ../../tmp/ArenaIntegrationTest/ArenaIntegrationTest.xcworkspace
to open the project in Xcode
"""
let predicate = NSPredicate { _,_ in
output.contents == expectation
}
let exp = XCTNSPredicateExpectation(predicate: predicate, object: nil)
wait(for: [exp], timeout: 10)
XCTAssertEqual(output.contents, expectation)

output.closeConsolePipe()
}
#endif

}

100 changes: 100 additions & 0 deletions Tests/ArenaTests/OutputListener.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// OutputListener.swift
// MasKitTests
//
// Created by Ben Chatelain on 1/7/19.
// Copyright © 2019 mas-cli. All rights reserved.
//

import Foundation

/// Test helper for monitoring strings written to stdout. Modified from:
/// https://medium.com/@thesaadismail/eavesdropping-on-swifts-print-statements-57f0215efb42
class OutputListener {
/// consumes the messages on STDOUT
let inputPipe = Pipe()

/// outputs messages back to STDOUT
let outputPipe = Pipe()

/// Buffers strings written to stdout
var contents = ""

init() {
// Set up a read handler which fires when data is written to our inputPipe
inputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in
strongify(self) { context in
let data = fileHandle.availableData
if let string = String(data: data, encoding: String.Encoding.utf8) {
context.contents += string
}

// Write input back to stdout
context.outputPipe.fileHandleForWriting.write(data)
}
}
}
}

extension OutputListener {
/// Sets up the "tee" of piped output, intercepting stdout then passing it through.
///
/// ## [dup2 documentation](https://linux.die.net/man/2/dup2)
/// `int dup2(int oldfd, int newfd);`
/// `dup2()` makes `newfd` be the copy of `oldfd`, closing `newfd` first if necessary.
func openConsolePipe() {
var dupStatus: Int32

// Copy STDOUT file descriptor to outputPipe for writing strings back to STDOUT
dupStatus = dup2(stdoutFileDescriptor, outputPipe.fileHandleForWriting.fileDescriptor)
// Status should equal newfd
assert(dupStatus == outputPipe.fileHandleForWriting.fileDescriptor)

// Intercept STDOUT with inputPipe
// newFileDescriptor is the pipe's file descriptor and the old file descriptor is STDOUT_FILENO
dupStatus = dup2(inputPipe.fileHandleForWriting.fileDescriptor, stdoutFileDescriptor)
// Status should equal newfd
assert(dupStatus == stdoutFileDescriptor)

// Don't have any tests on stderr yet
// dup2(inputPipe.fileHandleForWriting.fileDescriptor, stderr)
}

/// Tears down the "tee" of piped output.
func closeConsolePipe() {
// Restore stdout
freopen("/dev/stdout", "a", stdout)

[inputPipe.fileHandleForReading, outputPipe.fileHandleForWriting].forEach { file in
file.closeFile()
}
}
}

extension OutputListener {
/// File descriptor for stdout (aka STDOUT_FILENO)
var stdoutFileDescriptor: Int32 {
return FileHandle.standardOutput.fileDescriptor
}

/// File descriptor for stderr (aka STDERR_FILENO)
var stderrFileDescriptor: Int32 {
return FileHandle.standardError.fileDescriptor
}
}


// https://medium.com/@merowing_/stop-weak-strong-dance-in-swift-3aec6d3563d4
func strongify<Context: AnyObject, Arguments>(_ context: Context?,
closure: @escaping (Context, Arguments) -> Void) -> (Arguments) -> Void {
return { [weak context] arguments in
guard let strongContext = context else { return }
closure(strongContext, arguments)
}
}

func strongify<Context: AnyObject>(_ context: Context?, closure: @escaping (Context) -> Void) {
guard let strongContext = context else { return }
closure(strongContext)
}

0 comments on commit daaea7b

Please sign in to comment.