mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Backtracing][Tests] add unit tests for coloured/uncoloured output
rdar://164624364
This commit is contained in:
38
test/Backtracing/Inputs/CrashSubprocess.swift
Normal file
38
test/Backtracing/Inputs/CrashSubprocess.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
#if os(macOS)
|
||||
internal import Darwin
|
||||
#elseif canImport(Glibc)
|
||||
internal import Glibc
|
||||
#elseif canImport(Musl)
|
||||
internal import Musl
|
||||
#endif
|
||||
|
||||
func level1() {
|
||||
level2()
|
||||
}
|
||||
|
||||
func level2() {
|
||||
level3()
|
||||
}
|
||||
|
||||
func level3() {
|
||||
level4()
|
||||
}
|
||||
|
||||
func level4() {
|
||||
level5()
|
||||
}
|
||||
|
||||
func level5() {
|
||||
print("About to crash")
|
||||
let ptr = UnsafeMutablePointer<Int>(bitPattern: 4)!
|
||||
ptr.pointee = 42
|
||||
}
|
||||
|
||||
@main
|
||||
struct Crash {
|
||||
static func main() {
|
||||
print("subprocess stdout is a tty: \(isatty(1))")
|
||||
print("subprocess stderr is a tty: \(isatty(2))")
|
||||
level1()
|
||||
}
|
||||
}
|
||||
73
test/Backtracing/TTYDetection.swift
Normal file
73
test/Backtracing/TTYDetection.swift
Normal file
@@ -0,0 +1,73 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/TTYDetection
|
||||
// RUN: %target-codesign %t/TTYDetection
|
||||
|
||||
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no %target-run %t/TTYDetection 2> %t/default-output || true) && cat %t/default-output | %FileCheck %s
|
||||
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,output-to=stderr %target-run %t/TTYDetection 2> %t/stderr-output || true) && cat %t/stderr-output | %FileCheck %s --check-prefix STDERR
|
||||
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,output-to=stdout %target-run %t/TTYDetection > %t/stdout-output || true) && cat %t/stdout-output | %FileCheck %s --check-prefix STDOUT
|
||||
|
||||
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
// UNSUPPORTED: asan
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: backtracing
|
||||
// REQUIRES: OS=macosx || OS=linux-gnu
|
||||
// COM: we should be able to add Windows to this test
|
||||
|
||||
func level1() {
|
||||
level2()
|
||||
}
|
||||
|
||||
func level2() {
|
||||
level3()
|
||||
}
|
||||
|
||||
func level3() {
|
||||
level4()
|
||||
}
|
||||
|
||||
func level4() {
|
||||
level5()
|
||||
}
|
||||
|
||||
func level5() {
|
||||
print("About to crash")
|
||||
let ptr = UnsafeMutablePointer<Int>(bitPattern: 4)!
|
||||
ptr.pointee = 42
|
||||
}
|
||||
|
||||
@main
|
||||
struct TTYDetection {
|
||||
static func main() {
|
||||
level1()
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 ***
|
||||
|
||||
// CHECK: Thread 0 {{(".*" )?}}crashed:
|
||||
|
||||
// CHECK: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in TTYDetection
|
||||
// CHECK-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in TTYDetection
|
||||
// CHECK-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in TTYDetection
|
||||
// CHECK-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in TTYDetection
|
||||
|
||||
|
||||
// STDERR: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 ***
|
||||
|
||||
// STDERR: Thread 0 {{(".*" )?}}crashed:
|
||||
|
||||
// STDERR: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in TTYDetection
|
||||
// STDERR-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in TTYDetection
|
||||
// STDERR-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in TTYDetection
|
||||
// STDERR-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in TTYDetection
|
||||
|
||||
// STDOUT: *** Program crashed: Bad pointer dereference at 0x{{0+}}4 ***
|
||||
|
||||
// STDOUT: Thread 0 {{(".*" )?}}crashed:
|
||||
|
||||
// STDOUT: 0 0x{{[0-9a-f]+}} level5() + {{[0-9]+}} in TTYDetection
|
||||
// STDOUT-NEXT: 1 [ra] 0x{{[0-9a-f]+}} level4() + {{[0-9]+}} in TTYDetection
|
||||
// STDOUT-NEXT: 2 [ra] 0x{{[0-9a-f]+}} level3() + {{[0-9]+}} in TTYDetection
|
||||
// STDOUT-NEXT: 3 [ra] 0x{{[0-9a-f]+}} level2() + {{[0-9]+}} in TTYDetection
|
||||
127
test/Backtracing/TTYDetectionColourLinux.swift
Normal file
127
test/Backtracing/TTYDetectionColourLinux.swift
Normal file
@@ -0,0 +1,127 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-build-swift %S/Inputs/CrashSubprocess.swift -parse-as-library -Onone -g -o %t/crash
|
||||
// RUN: %target-codesign %t/crash
|
||||
|
||||
// RUN: %target-build-swift %s -o %t/crash-host
|
||||
|
||||
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,interactive=no %target-run %t/crash-host %t/crash)| %FileCheck %s
|
||||
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
// UNSUPPORTED: asan
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: backtracing
|
||||
// REQUIRES: OS=linux-gnu || OS=macosx
|
||||
|
||||
// COM: this test would need significant rework on Windows/WinSDK, but is not critical function so probably not worth porting the test to that platform
|
||||
|
||||
#if os(macOS)
|
||||
internal import Darwin
|
||||
#elseif canImport(Glibc)
|
||||
internal import Glibc
|
||||
#elseif canImport(Musl)
|
||||
internal import Musl
|
||||
#endif
|
||||
|
||||
guard CommandLine.arguments.count > 1 else {
|
||||
fputs("Usage: \(CommandLine.arguments[0]) <path-to-crash>\n", stderr)
|
||||
exit(1)
|
||||
}
|
||||
|
||||
let crashPath = CommandLine.arguments[1]
|
||||
|
||||
// CHECK: host stdout is a tty: 0
|
||||
print("host stdout is a tty: \(isatty(1))")
|
||||
// (piped output on linux is fully buffered by default)
|
||||
fflush(stdout)
|
||||
|
||||
// CHECK: host stderr is a tty: 0
|
||||
print("host stderr is a tty: \(isatty(2))")
|
||||
fflush(stdout)
|
||||
|
||||
var masterFD: Int32 = 0
|
||||
var slaveFD: Int32 = 0
|
||||
|
||||
let slaveName = UnsafeMutablePointer<CChar>.allocate(capacity: 1024)
|
||||
|
||||
guard openpty(&masterFD, &slaveFD, slaveName, nil, nil) == 0 else {
|
||||
perror("openpty")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
// CHECK: slave is: /dev/{{.+}}
|
||||
print("slave is: \(String(cString: slaveName))")
|
||||
slaveName.deallocate()
|
||||
fflush(stdout)
|
||||
|
||||
// try to avoid using Foundation, use Posix primitives instead
|
||||
var childPid: pid_t = 0
|
||||
|
||||
#if os(macOS)
|
||||
var childFileActions: posix_spawn_file_actions_t?
|
||||
posix_spawn_file_actions_init(&childFileActions)
|
||||
posix_spawn_file_actions_adddup2(&childFileActions, slaveFD, STDOUT_FILENO)
|
||||
posix_spawn_file_actions_adddup2(&childFileActions, slaveFD, STDERR_FILENO)
|
||||
|
||||
guard posix_spawn(&childPid, Array<CChar>(crashPath.utf8CString), &childFileActions, nil, nil, environ) == 0 else {
|
||||
perror("unable to spawn child")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
posix_spawn_file_actions_destroy(&childFileActions)
|
||||
|
||||
#elseif os(Linux)
|
||||
var childFileActions = posix_spawn_file_actions_t()
|
||||
posix_spawn_file_actions_init(&childFileActions)
|
||||
posix_spawn_file_actions_adddup2(&childFileActions, slaveFD, STDOUT_FILENO)
|
||||
posix_spawn_file_actions_adddup2(&childFileActions, slaveFD, STDERR_FILENO)
|
||||
|
||||
var argv: [UnsafeMutablePointer<CChar>?] = [nil]
|
||||
|
||||
guard posix_spawn(&childPid, Array<CChar>(crashPath.utf8CString), &childFileActions, nil, argv, environ) == 0 else {
|
||||
perror("unable to spawn child")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
posix_spawn_file_actions_destroy(&childFileActions)
|
||||
|
||||
#endif
|
||||
|
||||
// CHECK: child pid is {{[0-9]+}}
|
||||
print("child pid is \(childPid)")
|
||||
fflush(stdout)
|
||||
|
||||
// the parent process should now close this FD as it is used by the child for stdout/stderr
|
||||
close(slaveFD)
|
||||
|
||||
// CHECK: subprocess stdout is a tty: 1
|
||||
// CHECK: subprocess stderr is a tty: 1
|
||||
|
||||
// CHECK: About to crash
|
||||
|
||||
// CHECK: 💣{{.*}}Program crashed: Bad pointer dereference at 0x{{0+}}4
|
||||
// CHECK: Thread 0 {{(".*" )?}}crashed:
|
||||
// CHECK: Backtrace took {{[0-9.]+}}s
|
||||
|
||||
// allow the child process time to start, and crash...
|
||||
sleep(1)
|
||||
|
||||
// now read the standard output and error from our master pty
|
||||
// and write it to our own standard output for scanning by FileCheck
|
||||
let bufferSize = 4096
|
||||
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
|
||||
var bytesRead = read(masterFD, buffer, bufferSize)
|
||||
|
||||
while bytesRead > 0 {
|
||||
write(1, buffer, bytesRead)
|
||||
bytesRead = read(masterFD, buffer, bufferSize)
|
||||
}
|
||||
|
||||
close(masterFD)
|
||||
buffer.deallocate()
|
||||
|
||||
// CHECK-NOT: child exited with status: 0
|
||||
var childExitStatus: Int32 = 0
|
||||
waitpid(childPid, &childExitStatus, 0)
|
||||
print("child exited with status: \(childExitStatus)")
|
||||
46
test/Backtracing/TTYDetectionColourMacOS.swift
Normal file
46
test/Backtracing/TTYDetectionColourMacOS.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-build-swift %s -parse-as-library -Onone -g -o %t/TTYDetection
|
||||
// RUN: %target-codesign %t/TTYDetection
|
||||
|
||||
// RUN: (env SWIFT_BACKTRACE=enable=yes,cache=no,interactive=no %target-run script -reF %t/script-output %t/TTYDetection || true) && cat %t/script-output | %FileCheck %s
|
||||
|
||||
|
||||
// UNSUPPORTED: use_os_stdlib
|
||||
// UNSUPPORTED: back_deployment_runtime
|
||||
// UNSUPPORTED: asan
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: backtracing
|
||||
// REQUIRES: OS=macosx
|
||||
// COM: this won't work on Windows, but is not critical function
|
||||
|
||||
func level1() {
|
||||
level2()
|
||||
}
|
||||
|
||||
func level2() {
|
||||
level3()
|
||||
}
|
||||
|
||||
func level3() {
|
||||
level4()
|
||||
}
|
||||
|
||||
func level4() {
|
||||
level5()
|
||||
}
|
||||
|
||||
func level5() {
|
||||
print("About to crash")
|
||||
let ptr = UnsafeMutablePointer<Int>(bitPattern: 4)!
|
||||
ptr.pointee = 42
|
||||
}
|
||||
|
||||
@main
|
||||
struct TTYDetection {
|
||||
static func main() {
|
||||
level1()
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: 💣{{.*}}Program crashed: Bad pointer dereference at 0x{{0+}}4
|
||||
// CHECK: Thread 0 {{(".*" )?}}crashed:
|
||||
Reference in New Issue
Block a user