github.com/github.com/mattgallagher/CwlPreconditionTesting

A Mach exception handler that allows Swift precondition failures to be caught and tested.


License
ISC

Documentation

CwlPreconditionTesting

A Mach exception handler, written in Swift and Objective-C, that allows EXC_BAD_INSTRUCTION (as raised by Swift's assertionFailure/preconditionFailure/fatalError) to be caught and tested.

For an extended discussion of this code, please see the Cocoa with Love article:

Partial functions in Swift, Part 2: Catching precondition failures

Usage

The short version is:

  1. git clone https://github.com/mattgallagher/CwlPreconditionTesting.git
  2. drag the "CwlPreconditionTesting.xcodeproj" file into your project's file tree in Xcode
  3. go to your testing target's Build Phase settings and under "Target Dependencies" press the "+" button and select the relevant "CwlPreconditionTesting" target ("_iOS" or "_OSX", depending on your testing target's SDK)
  4. write import CwlPreconditionTesting at the top of any test file where you want to use catchBadInstruction (Swift should handle the linkage automatically when you do this)
  5. use the catchBadInstruction function as shown in the CwlCatchBadInstructionTests.swift tests file

Project details

The "CwlPreconditionTesting.xcodeproj" contains two targets:

  • CwlPreconditionTesting_OSX
  • CwlPreconditionTesting_iOS

both build a framework named "CwlPreconditionTesting.framework". If you're linking manually, be certain to select the "CwlPreconditionTesting.framework" from the appropriate target.

Remember: the iOS build is useful only in the simulator. All Mach exception handling code will be conditionally excluded in any device build.

Static inclusion

Due to the complications associated with needing to call into and out of Objective-C, static inclusion in other projects is not a single file nor a quick drag and drop. There's 6-8 files and you'll need to add some project settings.

All of the following files:

  • CwlCatchBadInstruction.swift
  • CwlCatchBadInstruction.h
  • CwlCatchBadInstruction.m
  • CwlCatchException.swift
  • CwlCatchException.h
  • CwlCatchException.m

need to be added to the testing target.

Your target will also need to have the following macro defined in the "Apple LLVM - Preprocessing" → "Preprocessor Macros" build setting:

PRODUCT_NAME=$(PRODUCT_NAME)

This lets the Objective-C file generate the include directive for the autogenerated Swift header so it can call back into Swift during the Mach exception handler callbacks. This macro should stay in sync if you change the target name but if you do anything else in your project that changes the name of the autogenerated Swift header independent of the target name (or you want to add spaces or other command-line complications to the target name), you'll want to update "CwlCatchBadInstruction.m" directly with the correct include directive.

Additionally, you'll need a standard Objective-C "Bridging header" for your testing target and it will need to include the following import statements:

#if defined(__x86_64__)
#import <CwlPreconditionTesting/CwlCatchBadInstruction.h>
#endif

#import <CwlPreconditionTesting/CwlCatchException.h>