blob: ff123ca652b0f948cc3425992add6df253d49bad [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -Onone -o %t/main -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main
// RUN: %target-build-swift %s -O -o %t/main2 -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
// RUN: %target-codesign %t/main2
// RUN: %target-run %t/main2
// RUN: %target-build-swift %s -Ounchecked -o %t/main3 -import-objc-header %S/Inputs/enum-nonexhaustivity.h -Xfrontend -disable-objc-attr-requires-foundation-module
// RUN: %target-codesign %t/main3
// RUN: %target-run %t/main3
// REQUIRES: executable_test
import StdlibUnittest
var EnumTestSuite = TestSuite("Enums")
EnumTestSuite.test("PlainOldSwitch/NonExhaustive") {
var gotCorrectValue = false
switch getExpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
gotCorrectValue = true
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("TrapOnUnexpected/NonExhaustive")
.crashOutputMatches("'NonExhaustiveEnum(rawValue: 3)'")
.code {
expectCrashLater()
switch getUnexpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("TrapOnUnexpectedNested/NonExhaustive")
.crashOutputMatches("'(NonExhaustiveEnum, NonExhaustiveEnum)'")
.code {
expectCrashLater()
switch (getExpectedValue(), getUnexpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (_, .B):
expectUnreachable()
case (_, .A), (_, .C):
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("TrapOnUnexpectedNested2/NonExhaustive")
.crashOutputMatches("'(NonExhaustiveEnum, NonExhaustiveEnum)'")
.code {
expectCrashLater()
switch (getUnexpectedValue(), getExpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (.B, _):
expectUnreachable()
case (.A, _), (.C, _):
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("UnexpectedOkayNested/NonExhaustive") {
var gotCorrectValue = false
switch (getExpectedValue(), getUnexpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (.B, _):
gotCorrectValue = true
case (.A, _), (.C, _):
expectUnreachable()
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("UnexpectedOkayNested2/NonExhaustive") {
var gotCorrectValue = false
switch (getUnexpectedValue(), getExpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (_, .B):
gotCorrectValue = true
case (_, .A), (_, .C):
expectUnreachable()
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("Equatable/NonExhaustive") {
expectEqual(getExpectedValue(), .B)
expectNotEqual(getUnexpectedValue(), .B)
expectNotEqual(getExpectedValue(), getUnexpectedValue())
expectEqual(getUnexpectedValue(), getUnexpectedValue())
}
EnumTestSuite.test("Hashable/NonExhaustive") {
expectEqual(getExpectedValue().hashValue, NonExhaustiveEnum.B.hashValue)
expectNotEqual(getUnexpectedValue().hashValue, NonExhaustiveEnum.B.hashValue)
}
EnumTestSuite.test("PlainOldSwitch/LyingExhaustive") {
var gotCorrectValue = false
switch getExpectedLiarValue() {
case .A, .C:
expectUnreachable()
case .B:
gotCorrectValue = true
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("TrapOnUnexpected/LyingExhaustive")
.crashOutputMatches("'LyingExhaustiveEnum(rawValue: 3)'")
.code {
expectCrashLater()
switch getUnexpectedLiarValue() {
case .A, .C:
expectUnreachable()
case .B:
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("TrapOnUnexpectedNested/LyingExhaustive")
.crashOutputMatches("'(LyingExhaustiveEnum, LyingExhaustiveEnum)'")
.code {
expectCrashLater()
switch (getExpectedLiarValue(), getUnexpectedLiarValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (_, .B):
expectUnreachable()
case (_, .A), (_, .C):
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("TrapOnUnexpectedNested2/LyingExhaustive")
.crashOutputMatches("'(LyingExhaustiveEnum, LyingExhaustiveEnum)'")
.code {
expectCrashLater()
switch (getUnexpectedLiarValue(), getExpectedLiarValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (.B, _):
expectUnreachable()
case (.A, _), (.C, _):
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("UnexpectedOkayNested/LyingExhaustive") {
var gotCorrectValue = false
switch (getExpectedLiarValue(), getUnexpectedLiarValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (.B, _):
gotCorrectValue = true
case (.A, _), (.C, _):
expectUnreachable()
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("UnexpectedOkayNested2/LyingExhaustive") {
var gotCorrectValue = false
switch (getUnexpectedLiarValue(), getExpectedLiarValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (_, .B):
gotCorrectValue = true
case (_, .A), (_, .C):
expectUnreachable()
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("Equatable/LyingExhaustive") {
expectEqual(getExpectedLiarValue(), .B)
expectNotEqual(getUnexpectedLiarValue(), .B)
expectNotEqual(getExpectedLiarValue(), getUnexpectedLiarValue())
expectEqual(getUnexpectedLiarValue(), getUnexpectedLiarValue())
}
EnumTestSuite.test("Hashable/LyingExhaustive") {
expectEqual(getExpectedLiarValue().hashValue, LyingExhaustiveEnum.B.hashValue)
expectNotEqual(getUnexpectedLiarValue().hashValue, LyingExhaustiveEnum.B.hashValue)
}
#if _runtime(_ObjC)
@objc enum SwiftEnum : Int32 {
case A, B, C
@inline(never) static func getExpectedValue() -> SwiftEnum {
return .B
}
@inline(never) static func getUnexpectedValue() -> SwiftEnum {
return unsafeBitCast(-42 as Int32, to: SwiftEnum.self)
}
}
EnumTestSuite.test("PlainOldSwitch/SwiftExhaustive") {
var gotCorrectValue = false
switch SwiftEnum.getExpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
gotCorrectValue = true
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("TrapOnUnexpected/SwiftExhaustive")
.crashOutputMatches("'SwiftEnum(rawValue: -42)'")
.code {
expectCrashLater()
switch SwiftEnum.getUnexpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("TrapOnUnexpectedNested/SwiftExhaustive")
.crashOutputMatches("'(SwiftEnum, SwiftEnum)'")
.code {
expectCrashLater()
switch (SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (_, .B):
expectUnreachable()
case (_, .A), (_, .C):
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("TrapOnUnexpectedNested2/SwiftExhaustive")
.crashOutputMatches("'(SwiftEnum, SwiftEnum)'")
.code {
expectCrashLater()
switch (SwiftEnum.getUnexpectedValue(), SwiftEnum.getExpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (.B, _):
expectUnreachable()
case (.A, _), (.C, _):
expectUnreachable()
}
expectUnreachable()
}
EnumTestSuite.test("UnexpectedOkayNested/SwiftExhaustive") {
var gotCorrectValue = false
switch (SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (.B, _):
gotCorrectValue = true
case (.A, _), (.C, _):
expectUnreachable()
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("UnexpectedOkayNested2/SwiftExhaustive") {
var gotCorrectValue = false
switch (SwiftEnum.getUnexpectedValue(), SwiftEnum.getExpectedValue()) {
case (.A, .A), (.C, .C):
expectUnreachable()
case (_, .B):
gotCorrectValue = true
case (_, .A), (_, .C):
expectUnreachable()
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("Equatable/SwiftExhaustive") {
expectEqual(SwiftEnum.getExpectedValue(), .B)
expectNotEqual(SwiftEnum.getUnexpectedValue(), .B)
expectNotEqual(SwiftEnum.getExpectedValue(), SwiftEnum.getUnexpectedValue())
expectEqual(SwiftEnum.getUnexpectedValue(), SwiftEnum.getUnexpectedValue())
}
EnumTestSuite.test("Hashable/SwiftExhaustive") {
expectEqual(SwiftEnum.getExpectedValue().hashValue, SwiftEnum.B.hashValue)
expectNotEqual(SwiftEnum.getUnexpectedValue().hashValue, SwiftEnum.B.hashValue)
}
@inline(never)
func switchOnTwoThings<T>(_ a: T, _ b: SwiftEnum) {
switch (a, b) {
case (is String, _):
expectUnreachable()
case (_, .B):
return
case (_, .A), (_, .C):
expectUnreachable()
}
}
EnumTestSuite.test("Generic/Trap")
.crashOutputMatches("'(Int, SwiftEnum)'")
.code {
expectCrashLater()
switchOnTwoThings(1, SwiftEnum.getUnexpectedValue())
}
EnumTestSuite.test("Generic/Okay") {
switchOnTwoThings(1, SwiftEnum.getExpectedValue())
}
@objc enum UnsignedSwiftEnum : UInt64 {
case A, B, C
@inline(never) static func getExpectedValue() -> UnsignedSwiftEnum {
return .B
}
@inline(never) static func getUnexpectedValue() -> UnsignedSwiftEnum {
return unsafeBitCast(~(0 as UInt64), to: UnsignedSwiftEnum.self)
}
}
EnumTestSuite.test("PlainOldSwitch/LargeSwiftExhaustive") {
var gotCorrectValue = false
switch UnsignedSwiftEnum.getExpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
gotCorrectValue = true
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("TrapOnUnexpected/LargeSwiftExhaustive")
.crashOutputMatches("'UnsignedSwiftEnum(rawValue: 18446744073709551615)'")
.code {
expectCrashLater()
switch UnsignedSwiftEnum.getUnexpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
expectUnreachable()
}
expectUnreachable()
}
struct Outer {
@objc enum NestedSwiftEnum: Int32 {
case A, B, C
@inline(never) static func getExpectedValue() -> NestedSwiftEnum {
return .B
}
@inline(never) static func getUnexpectedValue() -> NestedSwiftEnum {
return unsafeBitCast(-1 as Int32, to: NestedSwiftEnum.self)
}
}
}
EnumTestSuite.test("PlainOldSwitch/NestedSwiftExhaustive") {
var gotCorrectValue = false
switch Outer.NestedSwiftEnum.getExpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
gotCorrectValue = true
}
expectTrue(gotCorrectValue)
}
EnumTestSuite.test("TrapOnUnexpected/NestedSwiftExhaustive")
.crashOutputMatches("'NestedSwiftEnum(rawValue: -1)'")
.code {
expectCrashLater()
switch Outer.NestedSwiftEnum.getUnexpectedValue() {
case .A, .C:
expectUnreachable()
case .B:
expectUnreachable()
}
expectUnreachable()
}
#endif
runAllTests()