Skip to content

Test sanitizers with build plans. #2720

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions Fixtures/Miscellaneous/DoubleFree/Package.swift

This file was deleted.

3 changes: 0 additions & 3 deletions Fixtures/Miscellaneous/DoubleFree/README.md

This file was deleted.

3 changes: 0 additions & 3 deletions Fixtures/Miscellaneous/DoubleFree/Sources/exec/main.swift

This file was deleted.

9 changes: 0 additions & 9 deletions Fixtures/Miscellaneous/DoubleFree/Sources/lib/lib.swift

This file was deleted.

8 changes: 0 additions & 8 deletions Fixtures/Miscellaneous/DoubleFree/Tests/LinuxMain.swift

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions Fixtures/Miscellaneous/ThreadRace/.gitignore

This file was deleted.

18 changes: 0 additions & 18 deletions Fixtures/Miscellaneous/ThreadRace/Package.swift

This file was deleted.

3 changes: 0 additions & 3 deletions Fixtures/Miscellaneous/ThreadRace/README.md

This file was deleted.

3 changes: 0 additions & 3 deletions Fixtures/Miscellaneous/ThreadRace/Sources/exec/main.swift

This file was deleted.

16 changes: 0 additions & 16 deletions Fixtures/Miscellaneous/ThreadRace/Sources/lib/lib.swift

This file was deleted.

8 changes: 0 additions & 8 deletions Fixtures/Miscellaneous/ThreadRace/Tests/LinuxMain.swift

This file was deleted.

This file was deleted.

This file was deleted.

67 changes: 67 additions & 0 deletions Tests/BuildTests/BuildPlanTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2351,6 +2351,73 @@ final class BuildPlanTests: XCTestCase {
let dynamicLibraryPathExtension = try result.buildProduct(for: "Library").binary.extension
XCTAssertMatch(dynamicLibraryPathExtension, "dylib")
}

func testAddressSanitizer() throws {
try sanitizerTest(.address, expectedName: "address")
}

func testThreadSanitizer() throws {
try sanitizerTest(.thread, expectedName: "thread")
}

func testUndefinedSanitizer() throws {
try sanitizerTest(.undefined, expectedName: "undefined")
}

func testScudoSanitizer() throws {
try sanitizerTest(.scudo, expectedName: "scudo")
}

private func sanitizerTest(_ sanitizer: Sanitizer, expectedName: String) throws {
let fs = InMemoryFileSystem(emptyFiles:
"/Pkg/Sources/exe/main.swift",
"/Pkg/Sources/lib/lib.swift",
"/Pkg/Sources/clib/clib.c",
"/Pkg/Sources/clib/include/clib.h"
)

let diagnostics = DiagnosticsEngine()
let graph = loadPackageGraph(fs: fs, diagnostics: diagnostics,
manifests: [
Manifest.createV4Manifest(
name: "Pkg",
path: "/Pkg",
url: "/Pkg",
packageKind: .root,
targets: [
TargetDescription(name: "exe", dependencies: ["lib", "clib"]),
TargetDescription(name: "lib", dependencies: []),
TargetDescription(name: "clib", dependencies: []),
]),
]
)
XCTAssertNoDiagnostics(diagnostics)

// Unrealistic: we can't enable all of these at once on all platforms.
// This test codifies current behaviour, not ideal behaviour, and
// may need to be amended if we change it.
var parameters = mockBuildParameters(shouldLinkStaticSwiftStdlib: true)
parameters.sanitizers = EnabledSanitizers([sanitizer])

let result = BuildPlanResult(plan: try BuildPlan(
buildParameters: parameters,
graph: graph, diagnostics: diagnostics, fileSystem: fs)
)

result.checkProductsCount(1)
result.checkTargetsCount(3)

let exe = try result.target(for: "exe").swiftTarget().compileArguments()
XCTAssertTrue(exe.contains("-sanitize=\(expectedName)"))

let lib = try result.target(for: "lib").swiftTarget().compileArguments()
XCTAssertTrue(lib.contains("-sanitize=\(expectedName)"))

let clib = try result.target(for: "clib").clangTarget().basicArguments()
XCTAssertTrue(clib.contains("-fsanitize=\(expectedName)"))

XCTAssertTrue(try result.buildProduct(for: "exe").linkArguments().contains("-sanitize=\(expectedName)"))
}
}

// MARK:- Test Helpers
Expand Down
48 changes: 0 additions & 48 deletions Tests/CommandsTests/RunToolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,52 +103,4 @@ final class RunToolTests: XCTestCase {
}
}
}

// Test that thread sanitizer works.
func testSanitizeThread() throws {
// FIXME: We need to figure out how to test this for linux.
#if os(macOS)
fixture(name: "Miscellaneous/ThreadRace") { path in
// Ensure that we don't abort() when we find the race. This avoids
// generating the crash report on macOS.
let env = ["TSAN_OPTIONS": "abort_on_error=0"]
let cmdline = {
try SwiftPMProduct.SwiftRun.execute(
["--sanitize=thread"], packagePath: path, env: env)
}
XCTAssertThrows(try cmdline()) { (error: SwiftPMProductError) in
switch error {
case .executionFailure(_, _, let error):
XCTAssertMatch(error, .contains("ThreadSanitizer: data race"))
return true
default:
return false
}
}
}
#endif
}

func testSanitizeScudo() throws {
// Scudo is only supported on Linux.
#if os(Linux)
fixture(name: "Miscellaneous/DoubleFree") { path in
// Ensure that we don't abort() when we find the race. This avoids
// generating the crash report on macOS.
let cmdline = {
try SwiftPMProduct.SwiftRun.execute(
["--sanitize=scudo"], packagePath: path)
}
XCTAssertThrows(try cmdline()) { (error: SwiftPMProductError) in
switch error {
case .executionFailure(_, _, let error):
XCTAssertMatch(error, .contains("invalid chunk state"))
return true
default:
return false
}
}
}
#endif
}
}
47 changes: 0 additions & 47 deletions Tests/CommandsTests/TestToolTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,6 @@ final class TestToolTests: XCTestCase {
XCTAssert(try execute(["--version"]).stdout.contains("Swift Package Manager"))
}

// Test that thread sanitizer works.
func testSanitizeThread() throws {
// FIXME: We need to figure out how to test this for linux.
// Disabled because of https://bugs.swift.org/browse/SR-7272
#if false
fixture(name: "Miscellaneous/ThreadRace") { path in
// Ensure that we don't abort() when we find the race. This avoids
// generating the crash report on macOS.
let env = ["TSAN_OPTIONS": "abort_on_error=0"]
let cmdline = {
try SwiftPMProduct.SwiftTest.execute(
["--sanitize=thread"], packagePath: path, env: env)
}
XCTAssertThrows(try cmdline()) { (error: SwiftPMProductError) in
switch error {
case .executionFailure(_, _, let error):
XCTAssertMatch(error, .contains("ThreadSanitizer: data race"))
return true
default:
return false
}
}
}
#endif
}

func testNumWorkersParallelRequeriment() throws {
// Running swift-test fixtures on linux is not yet possible.
#if os(macOS)
Expand All @@ -80,25 +54,4 @@ final class TestToolTests: XCTestCase {
}
#endif
}

func testSanitizeScudo() throws {
// This test only runs on Linux because Scudo only runs on Linux
#if os(Linux)
fixture(name: "Miscellaneous/DoubleFree") { path in
let cmdline = {
try SwiftPMProduct.SwiftTest.execute(
["--sanitize=scudo"], packagePath: path)
}
XCTAssertThrows(try cmdline()) { (error: SwiftPMProductError) in
switch error {
case .executionFailure(_, _, let error):
XCTAssertMatch(error, .contains("invalid chunk state"))
return true
default:
return false
}
}
}
#endif
}
}