Files
swift-mirror/test/stdlib/Mirror.swift
Jordan Rose 4b8068d1df [runtime] Handle same-type constraints when resolving generic params
Generic parameters for a context are normally classified as "key",
meaning they have actual metadata provided at runtime, or non-key,
meaning they're derivable from somewhere else. However, a nested
context or constrained extension can take what would be a "key"
parameter in a parent context and make it non-key in a child context.
This messes with the mapping between the (depth, index) representation
of generic parameters and the flat list of generic arguments. Fix this
by (1) consistently substituting out extension contexts with the
contexts of the extended types, and (2) using the most nested context
to decide which parameters are key, instead of the context a parameter
was originally introduced in.

Note that (1) may have problems if/when extensions start introducing
their /own/ generic parameters. For now I tried to be consistent with
what was there.

rdar://problem/52364601
2019-07-08 17:46:14 -07:00

2009 lines
51 KiB
Swift

//===--- Mirror.swift -----------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// RUN: %empty-directory(%t)
// RUN: cp %s %t/main.swift
//
// RUN: if [ %target-runtime == "objc" ]; \
// RUN: then \
// RUN: %target-clang %S/Inputs/Mirror/Mirror.mm -c -o %t/Mirror.mm.o -g && \
// RUN: %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -I %S/Inputs/Mirror/ -Xlinker %t/Mirror.mm.o -o %t/Mirror; \
// RUN: else \
// RUN: %target-build-swift %t/main.swift %S/Inputs/Mirror/MirrorOther.swift -o %t/Mirror; \
// RUN: fi
// RUN: %target-codesign %t/Mirror
// RUN: %target-run %t/Mirror
// REQUIRES: executable_test
// REQUIRES: shell
import StdlibUnittest
var mirrors = TestSuite("Mirrors")
extension Mirror {
public var testDescription: String {
let nil_ = "nil"
return "[" +
children.lazy
.map { "\($0.0 ?? nil_): \(String(reflecting: $0.1))" }
.joined(separator: ", ")
+ "]"
}
}
mirrors.test("RandomAccessStructure") {
struct Eggs : CustomReflectable {
var customMirror: Mirror {
return Mirror(self, unlabeledChildren: ["aay", "bee", "cee"])
}
}
let x = Eggs().customMirror
expectEqual("[nil: \"aay\", nil: \"bee\", nil: \"cee\"]", x.testDescription)
}
let letters = "abcdefghijklmnopqrstuvwxyz "
func find(_ substring: String, within domain: String) -> String.Index? {
let domainCount = domain.count
let substringCount = substring.count
if (domainCount < substringCount) { return nil }
var sliceStart = domain.startIndex
var sliceEnd = domain.index(sliceStart, offsetBy: substringCount)
var i = 0
while true {
if domain[sliceStart..<sliceEnd] == substring {
return sliceStart
}
if i == domainCount - substringCount { break }
sliceStart = domain.index(after: sliceStart)
sliceEnd = domain.index(after: sliceEnd)
i += 1
}
return nil
}
mirrors.test("ForwardStructure") {
struct DoubleYou : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self,
unlabeledChildren: Set(letters),
displayStyle: .`set`)
}
}
let w = DoubleYou().customMirror
expectEqual(.`set`, w.displayStyle)
expectEqual(letters.count, numericCast(w.children.count))
// Because we don't control the order of a Set, we need to do a
// fancy dance in order to validate the result.
let description = w.testDescription
for c in letters {
let expected = "nil: \"\(c)\""
expectNotNil(find(expected, within: description))
}
}
mirrors.test("BidirectionalStructure") {
struct Why : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self,
unlabeledChildren: letters,
displayStyle: .collection)
}
}
// Test that the basics seem to work
let y = Why().customMirror
expectEqual(.`collection`, y.displayStyle)
let description = y.testDescription
expectEqual(
"[nil: \"a\", nil: \"b\", nil: \"c\", nil: \"",
description[description.startIndex..<description.firstIndex(of: "d")!])
}
mirrors.test("LabeledStructure") {
struct Zee : CustomReflectable, CustomStringConvertible {
var customMirror: Mirror {
return Mirror(self, children: ["bark": 1, "bite": 0])
}
var description: String { return "Zee" }
}
let z = Zee().customMirror
expectEqual("[bark: 1, bite: 0]", z.testDescription)
expectNil(z.displayStyle)
struct Zee2 : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self, children: ["bark": 1, "bite": 0], displayStyle: .dictionary)
}
}
let z2 = Zee2().customMirror
expectEqual(.dictionary, z2.displayStyle)
expectEqual("[bark: 1, bite: 0]", z2.testDescription)
struct Heterogeny : CustomReflectable {
var customMirror: Mirror {
return Mirror(
self, children: ["bark": 1, "bite": Zee()])
}
}
let h = Heterogeny().customMirror
expectEqual("[bark: 1, bite: Zee]", h.testDescription)
}
mirrors.test("Legacy") {
let m = Mirror(reflecting: [1, 2, 3])
expectTrue(m.subjectType == [Int].self)
let x0: [Mirror.Child] = [
(label: nil, value: 1),
(label: nil, value: 2),
(label: nil, value: 3)
]
expectFalse(
zip(x0, m.children).contains {
$0.0.value as! Int != $0.1.value as! Int
})
class B { let bx: Int = 0 }
class D : B { let dx: Int = 1 }
let mb = Mirror(reflecting: B())
func expectBMirror(
_ mb: Mirror, stackTrace: SourceLocStack = SourceLocStack(),
file: String = #file, line: UInt = #line
) {
expectTrue(mb.subjectType == B.self,
stackTrace: stackTrace, file: file, line: line)
expectNil(
mb.superclassMirror,
stackTrace: stackTrace, file: file, line: line)
expectEqual(
1, mb.children.count,
stackTrace: stackTrace, file: file, line: line)
expectEqual(
"bx", mb.children.first?.label,
stackTrace: stackTrace, file: file, line: line)
expectEqual(
0, mb.children.first?.value as? Int,
stackTrace: stackTrace, file: file, line: line)
}
expectBMirror(mb)
// Ensure that the base class instance is properly filtered out of
// the child list
do {
let md = Mirror(reflecting: D())
expectTrue(md.subjectType == D.self)
expectEqual(1, md.children.count)
expectEqual("dx", md.children.first?.label)
expectEqual(1, md.children.first?.value as? Int)
expectNotNil(md.superclassMirror)
if let mb2 = md.superclassMirror { expectBMirror(mb2) }
}
do {
// Ensure that we reflect on the dynamic type of the subject
let md = Mirror(reflecting: D() as B)
expectTrue(md.subjectType == D.self)
expectEqual(1, md.children.count)
expectEqual("dx", md.children.first?.label)
expectEqual(1, md.children.first?.value as? Int)
expectNotNil(md.superclassMirror)
if let mb2 = md.superclassMirror { expectBMirror(mb2) }
}
}
//===----------------------------------------------------------------------===//
//===--- Class Support ----------------------------------------------------===//
class DullClass {}
mirrors.test("ClassReflection") {
expectEqual(.`class`, Mirror(reflecting: DullClass()).displayStyle)
}
mirrors.test("Class/Root/Uncustomized") {
class A { var a: Int = 1 }
let a = Mirror(reflecting: A())
expectTrue(a.subjectType == A.self)
expectNil(a.superclassMirror)
expectEqual(1, a.children.count)
expectEqual("a", a.children.first!.label)
}
//===--- Generated Superclass Mirrors -------------------------------------===//
mirrors.test("Class/Root/superclass:.generated") {
class B : CustomReflectable {
var b: String = "two"
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .generated)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
expectEqual(1, b.children.count)
expectEqual("bee", b.children.first!.label)
expectEqual("two", b.children.first!.value as? String)
}
mirrors.test("class/Root/superclass:<default>") {
class C : CustomReflectable {
var c: UInt = 3
var customMirror: Mirror {
return Mirror(self, children: ["sea": c + 1])
}
}
let c = Mirror(reflecting: C())
expectTrue(c.subjectType == C.self)
expectNil(c.superclassMirror)
expectEqual(1, c.children.count)
expectEqual("sea", c.children.first!.label)
expectEqual(4, c.children.first!.value as? UInt)
}
mirrors.test("class/Plain/Plain") {
class A { var a: Int = 1 }
class B : A { var b: UInt = 42 }
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let bChild = expectNotNil(b.children.first) {
expectEqual("b", bChild.label)
expectEqual(42, bChild.value as? UInt)
}
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aChild = expectNotNil(a.children.first) {
expectEqual("a", aChild.label)
expectEqual(1, aChild.value as? Int)
expectNil(a.superclassMirror)
}
}
}
mirrors.test("class/UncustomizedSuper/Synthesized/Implicit") {
class A { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first?.label)
expectNil(a.superclassMirror)
}
}
mirrors.test("class/UncustomizedSuper/Synthesized/Explicit") {
class A { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .generated)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
expectNil(a.superclassMirror)
}
}
mirrors.test("class/CustomizedSuper/Synthesized") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class B : A {
var b: UInt = 42
// This is an unusual case: when writing override on a
// customMirror implementation you would typically want to pass
// ancestorRepresentation: .customized(super.customMirror) or, in
// rare cases, ancestorRepresentation: .Suppressed. However, it
// has an expected behavior, which we test here.
override var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
expectNil(a.superclassMirror)
}
}
#if _runtime(_ObjC)
import Foundation
import MirrorObjC
//===--- ObjC Base Classes ------------------------------------------------===//
mirrors.test("class/ObjCPlain/Plain") {
class A : NSObject { var a: Int = 1 }
class B : A { var b: UInt = 42 }
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let bChild = expectNotNil(b.children.first) {
expectEqual("b", bChild.label)
expectEqual(42, bChild.value as? UInt)
}
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aChild = expectNotNil(a.children.first) {
expectEqual("a", aChild.label)
expectEqual(1, aChild.value as? Int)
if let o = expectNotNil(a.superclassMirror) {
expectEqual("NSObject", String(reflecting: o.subjectType))
}
}
}
}
mirrors.test("class/ObjCUncustomizedSuper/Synthesized/Implicit") {
class A : NSObject { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first?.label)
if let o = expectNotNil(a.superclassMirror) {
expectTrue(o.subjectType == NSObject.self)
}
}
}
mirrors.test("class/ObjCUncustomizedSuper/Synthesized/Explicit") {
class A : NSObject { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .generated)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
if let o = expectNotNil(a.superclassMirror) {
expectTrue(o.subjectType == NSObject.self)
}
}
}
mirrors.test("class/ObjCCustomizedSuper/Synthesized") {
class A : DateFormatter, CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class B : A {
var b: UInt = 42
// This is an unusual case: when writing override on a
// customMirror implementation you would typically want to pass
// ancestorRepresentation: .customized(super.customMirror) or, in
// rare cases, ancestorRepresentation: .Suppressed. However, it
// has an expected behavior, which we test here.
override var customMirror: Mirror {
return Mirror(self, children: ["bee": b])
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("a", a.children.first!.label)
if let d = expectNotNil(a.superclassMirror) {
expectTrue(d.subjectType == DateFormatter.self)
if let f = expectNotNil(d.superclassMirror) {
expectTrue(f.subjectType == Formatter.self)
if let o = expectNotNil(f.superclassMirror) {
expectTrue(o.subjectType == NSObject.self)
expectNil(o.superclassMirror)
}
}
}
}
}
mirrors.test("ObjC") {
// Some Foundation classes lie about their ivars, which would crash
// a mirror; make sure we are not automatically exposing ivars of
// Objective-C classes from the default mirror implementation.
expectEqual(0, Mirror(reflecting: HasIVars()).children.count)
}
// rdar://problem/39629937
@objc class ObjCClass : NSObject {
let value: Int
init(value: Int) { self.value = value }
override var description: String {
return "\(value)"
}
}
struct WrapObjCClassArray {
var array: [ObjCClass]
}
mirrors.test("struct/WrapNSArray") {
let nsArray: NSArray = [
ObjCClass(value: 1), ObjCClass(value: 2),
ObjCClass(value: 3), ObjCClass(value: 4)
]
let s = String(describing: WrapObjCClassArray(array: nsArray as! [ObjCClass]))
expectEqual("WrapObjCClassArray(array: [1, 2, 3, 4])", s)
}
#endif // _runtime(_ObjC)
//===--- Suppressed Superclass Mirrors ------------------------------------===//
mirrors.test("Class/Root/NoSuperclassMirror") {
class B : CustomReflectable {
var b: String = "two"
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .suppressed)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
expectEqual(1, b.children.count)
expectEqual("bee", b.children.first!.label)
}
mirrors.test("class/UncustomizedSuper/NoSuperclassMirror") {
class A { var a: Int = 1 }
class B : A, CustomReflectable {
var b: UInt = 42
var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .suppressed)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
}
mirrors.test("class/CustomizedSuper/NoSuperclassMirror") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class B : A {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self, children: ["bee": b], ancestorRepresentation: .suppressed)
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
expectNil(b.superclassMirror)
}
//===--- Override Superclass Mirrors --------------------------------------===//
mirrors.test("class/CustomizedSuper/SuperclassCustomMirror/Direct") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
// B inherits A directly
class B : A {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self,
children: ["bee": b],
ancestorRepresentation: .customized({ super.customMirror }))
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
expectEqual("aye", a.children.first!.label)
expectNil(a.superclassMirror)
}
}
mirrors.test("class/CustomizedSuper/SuperclassCustomMirror/Indirect") {
class A : CustomReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(self, children: ["aye": a])
}
}
class X : A {}
class Y : X {}
// B inherits A indirectly through X and Y
class B : Y {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self,
children: ["bee": b],
ancestorRepresentation: .customized({ super.customMirror }))
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let y = expectNotNil(b.superclassMirror) {
expectTrue(y.subjectType == Y.self)
if let x = expectNotNil(y.superclassMirror) {
expectTrue(x.subjectType == X.self)
expectEqual(0, x.children.count)
if let a = expectNotNil(x.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aye = expectNotNil(a.children.first) {
expectEqual("aye", aye.label)
}
}
}
}
}
mirrors.test("class/CustomizedSuper/SuperclassCustomMirror/Indirect2") {
class A : CustomLeafReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(
self, children: ["aye": a])
}
}
class X : A {}
class Y : X {}
// B inherits A indirectly through X and Y
class B : Y {
var b: UInt = 42
override var customMirror: Mirror {
return Mirror(
self,
children: ["bee": b],
ancestorRepresentation: .customized({ super.customMirror }))
}
}
let b = Mirror(reflecting: B())
expectTrue(b.subjectType == B.self)
if let a = expectNotNil(b.superclassMirror) {
expectTrue(a.subjectType == A.self)
if let aye = expectNotNil(a.children.first) {
expectEqual("aye", aye.label)
}
}
}
mirrors.test("class/Cluster") {
class A : CustomLeafReflectable {
var a: Int = 1
var customMirror: Mirror {
return Mirror(
self, children: ["aye": a])
}
}
class X : A {}
class Y : X {}
let a = Mirror(reflecting: Y())
expectTrue(a.subjectType == A.self)
if let aye = expectNotNil(a.children.first) {
expectEqual("aye", aye.label)
}
}
//===--- Miscellaneous ----------------------------------------------------===//
//===----------------------------------------------------------------------===//
mirrors.test("Addressing") {
let m0 = Mirror(reflecting: [1, 2, 3])
expectEqual(1, m0.descendant(0) as? Int)
expectEqual(2, m0.descendant(1) as? Int)
expectEqual(3, m0.descendant(2) as? Int)
let m1 = Mirror(reflecting: (a: ["one", "two", "three"], 4))
let ott0 = m1.descendant(0) as? [String]
expectNotNil(ott0)
let ott1 = m1.descendant("a") as? [String]
expectNotNil(ott1)
if ott0 != nil && ott1 != nil {
expectEqualSequence(ott0!, ott1!)
}
expectEqual(4, m1.descendant(1) as? Int)
expectEqual(4, m1.descendant(".1") as? Int)
expectEqual("one", m1.descendant(0, 0) as? String)
expectEqual("two", m1.descendant(0, 1) as? String)
expectEqual("three", m1.descendant(0, 2) as? String)
expectEqual("one", m1.descendant("a", 0) as? String)
struct Zee : CustomReflectable {
var customMirror: Mirror {
return Mirror(self, children: ["bark": 1, "bite": 0])
}
}
let x = [
(a: ["one", "two", "three"], b: Zee()),
(a: ["five"], b: Zee()),
(a: [], b: Zee())]
let m = Mirror(reflecting: x)
let two = m.descendant(0, "a", 1)
expectEqual("two", two as? String)
expectEqual(1, m.descendant(1, 1, "bark") as? Int)
expectEqual(0, m.descendant(1, 1, "bite") as? Int)
expectNil(m.descendant(1, 1, "bork"))
}
mirrors.test("Invalid Path Type")
.skip(.custom(
{ _isFastAssertConfiguration() },
reason: "this trap is not guaranteed to happen in -Ounchecked"))
.code {
struct X : MirrorPath {}
let m = Mirror(reflecting: [1, 2, 3])
expectEqual(1, m.descendant(0) as? Int)
expectCrashLater()
_ = m.descendant(X())
}
mirrors.test("PlaygroundQuickLook") {
// Customization works.
struct CustomQuickie : CustomPlaygroundQuickLookable {
var customPlaygroundQuickLook: PlaygroundQuickLook {
return .point(1.25, 42)
}
}
switch PlaygroundQuickLook(reflecting: CustomQuickie()) {
case .point(1.25, 42): break
default: expectTrue(false)
}
// PlaygroundQuickLook support from Legacy Mirrors works.
switch PlaygroundQuickLook(reflecting: true) {
case .bool(true): break
default: expectTrue(false)
}
// With no Legacy Mirror QuickLook support, we fall back to
// String(reflecting: ).
struct X {}
switch PlaygroundQuickLook(reflecting: X()) {
case .text(let text):
#if _runtime(_ObjC)
// FIXME: Enable if non-objc hasSuffix is implemented.
expectTrue(text.contains(").X"), text)
#endif
default:
expectTrue(false)
}
struct Y : CustomDebugStringConvertible {
var debugDescription: String { return "Why?" }
}
switch PlaygroundQuickLook(reflecting: Y()) {
case .text("Why?"): break
default: expectTrue(false)
}
}
class Parent {}
extension Parent : _DefaultCustomPlaygroundQuickLookable {
var _defaultCustomPlaygroundQuickLook: PlaygroundQuickLook {
return .text("base")
}
}
class Child : Parent { }
class FancyChild : Parent, CustomPlaygroundQuickLookable {
var customPlaygroundQuickLook: PlaygroundQuickLook {
return .text("child")
}
}
mirrors.test("_DefaultCustomPlaygroundQuickLookable") {
// testing the workaround for custom quicklookables in subclasses
switch PlaygroundQuickLook(reflecting: Child()) {
case .text("base"): break
default: expectUnreachable("Base custom quicklookable was expected")
}
switch PlaygroundQuickLook(reflecting: FancyChild()) {
case .text("child"): break
default: expectUnreachable("FancyChild custom quicklookable was expected")
}
}
mirrors.test("String.init") {
expectEqual("42", String(42))
expectEqual("42", String("42"))
expectEqual("42", String(reflecting: 42))
expectEqual("\"42\"", String(reflecting: "42"))
}
//===--- Structs ----------------------------------------------------------===//
//===----------------------------------------------------------------------===//
struct StructWithDefaultMirror {
let s: String
init (_ s: String) {
self.s = s
}
}
mirrors.test("Struct/NonGeneric/DefaultMirror") {
do {
var output = ""
dump(StructWithDefaultMirror("123"), to: &output)
expectEqual("▿ Mirror.StructWithDefaultMirror\n - s: \"123\"\n", output)
}
do {
// Build a String around an interpolation as a way of smoke-testing that
// the internal _Mirror implementation gets memory management right.
var output = ""
dump(StructWithDefaultMirror("\(456)"), to: &output)
expectEqual("▿ Mirror.StructWithDefaultMirror\n - s: \"456\"\n", output)
}
expectEqual(
.`struct`,
Mirror(reflecting: StructWithDefaultMirror("")).displayStyle)
}
struct GenericStructWithDefaultMirror<T, U> {
let first: T
let second: U
}
mirrors.test("Struct/Generic/DefaultMirror") {
do {
var value = GenericStructWithDefaultMirror<Int, [Any?]>(
first: 123,
second: ["abc", 456, 789.25])
var output = ""
dump(value, to: &output)
let expected =
"▿ Mirror.GenericStructWithDefaultMirror<Swift.Int, Swift.Array<Swift.Optional<Any>>>\n" +
" - first: 123\n" +
" ▿ second: 3 elements\n" +
" ▿ Optional(\"abc\")\n" +
" - some: \"abc\"\n" +
" ▿ Optional(456)\n" +
" - some: 456\n" +
" ▿ Optional(789.25)\n" +
" - some: 789.25\n"
expectEqual(expected, output)
}
}
//===--- Enums ------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
enum NoPayloadEnumWithDefaultMirror {
case A, ß
}
mirrors.test("Enum/NoPayload/DefaultMirror") {
do {
let value: [NoPayloadEnumWithDefaultMirror] =
[.A, .ß]
var output = ""
dump(value, to: &output)
let expected =
"▿ 2 elements\n" +
" - Mirror.NoPayloadEnumWithDefaultMirror.A\n" +
" - Mirror.NoPayloadEnumWithDefaultMirror.ß\n"
expectEqual(expected, output)
}
}
enum SingletonNonGenericEnumWithDefaultMirror {
case OnlyOne(Int)
}
mirrors.test("Enum/SingletonNonGeneric/DefaultMirror") {
do {
let value = SingletonNonGenericEnumWithDefaultMirror.OnlyOne(5)
var output = ""
dump(value, to: &output)
let expected =
"▿ Mirror.SingletonNonGenericEnumWithDefaultMirror.OnlyOne\n" +
" - OnlyOne: 5\n"
expectEqual(expected, output)
}
}
enum SingletonGenericEnumWithDefaultMirror<T> {
case OnlyOne(T)
}
mirrors.test("Enum/SingletonGeneric/DefaultMirror") {
do {
let value = SingletonGenericEnumWithDefaultMirror.OnlyOne("IIfx")
var output = ""
dump(value, to: &output)
let expected =
"▿ Mirror.SingletonGenericEnumWithDefaultMirror<Swift.String>.OnlyOne\n" +
" - OnlyOne: \"IIfx\"\n"
expectEqual(expected, output)
}
expectEqual(0, LifetimeTracked.instances)
do {
let value = SingletonGenericEnumWithDefaultMirror.OnlyOne(
LifetimeTracked(0))
expectEqual(1, LifetimeTracked.instances)
var output = ""
dump(value, to: &output)
}
expectEqual(0, LifetimeTracked.instances)
}
enum SinglePayloadNonGenericEnumWithDefaultMirror {
case Cat
case Dog
case Volleyball(String, Int)
}
mirrors.test("Enum/SinglePayloadNonGeneric/DefaultMirror") {
do {
let value: [SinglePayloadNonGenericEnumWithDefaultMirror] =
[.Cat,
.Dog,
.Volleyball("Wilson", 2000)]
var output = ""
dump(value, to: &output)
let expected =
"▿ 3 elements\n" +
" - Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Cat\n" +
" - Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Dog\n" +
" ▿ Mirror.SinglePayloadNonGenericEnumWithDefaultMirror.Volleyball\n" +
" ▿ Volleyball: (2 elements)\n" +
" - .0: \"Wilson\"\n" +
" - .1: 2000\n"
expectEqual(expected, output)
}
}
enum SinglePayloadGenericEnumWithDefaultMirror<T, U> {
case Well
case Faucet
case Pipe(T, U)
}
mirrors.test("Enum/SinglePayloadGeneric/DefaultMirror") {
do {
let value: [SinglePayloadGenericEnumWithDefaultMirror<Int, [Int]>] =
[.Well,
.Faucet,
.Pipe(408, [415])]
var output = ""
dump(value, to: &output)
let expected =
"▿ 3 elements\n" +
" - Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Well\n" +
" - Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Faucet\n" +
" ▿ Mirror.SinglePayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.Array<Swift.Int>>.Pipe\n" +
" ▿ Pipe: (2 elements)\n" +
" - .0: 408\n" +
" ▿ .1: 1 element\n" +
" - 415\n"
expectEqual(expected, output)
}
}
enum MultiPayloadTagBitsNonGenericEnumWithDefaultMirror {
case Plus
case SE30
case Classic(mhz: Int)
case Performa(model: Int)
}
mirrors.test("Enum/MultiPayloadTagBitsNonGeneric/DefaultMirror") {
do {
let value: [MultiPayloadTagBitsNonGenericEnumWithDefaultMirror] =
[.Plus,
.SE30,
.Classic(mhz: 16),
.Performa(model: 220)]
var output = ""
dump(value, to: &output)
let expected =
"▿ 4 elements\n" +
" - Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Plus\n" +
" - Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.SE30\n" +
" ▿ Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Classic\n" +
" ▿ Classic: (1 element)\n" +
" - mhz: 16\n" +
" ▿ Mirror.MultiPayloadTagBitsNonGenericEnumWithDefaultMirror.Performa\n" +
" ▿ Performa: (1 element)\n" +
" - model: 220\n"
expectEqual(expected, output)
}
}
class Floppy {
let capacity: Int
init(capacity: Int) { self.capacity = capacity }
}
class CDROM {
let capacity: Int
init(capacity: Int) { self.capacity = capacity }
}
enum MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror {
case MacWrite
case MacPaint
case FileMaker
case ClarisWorks(floppy: Floppy)
case HyperCard(cdrom: CDROM)
}
mirrors.test("Enum/MultiPayloadSpareBitsNonGeneric/DefaultMirror") {
do {
let value: [MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror] =
[.MacWrite,
.MacPaint,
.FileMaker,
.ClarisWorks(floppy: Floppy(capacity: 800)),
.HyperCard(cdrom: CDROM(capacity: 600))]
var output = ""
dump(value, to: &output)
let expected =
"▿ 5 elements\n" +
" - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacWrite\n" +
" - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.MacPaint\n" +
" - Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.FileMaker\n" +
" ▿ Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
" ▿ ClarisWorks: (1 element)\n" +
" ▿ floppy: Mirror.Floppy #0\n" +
" - capacity: 800\n" +
" ▿ Mirror.MultiPayloadSpareBitsNonGenericEnumWithDefaultMirror.HyperCard\n" +
" ▿ HyperCard: (1 element)\n" +
" ▿ cdrom: Mirror.CDROM #1\n" +
" - capacity: 600\n"
expectEqual(expected, output)
}
}
enum MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror {
case MacWrite
case MacPaint
case FileMaker
case ClarisWorks(floppy: Bool)
case HyperCard(cdrom: Bool)
}
mirrors.test("Enum/MultiPayloadTagBitsSmallNonGeneric/DefaultMirror") {
do {
let value: [MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror] =
[.MacWrite,
.MacPaint,
.FileMaker,
.ClarisWorks(floppy: true),
.HyperCard(cdrom: false)]
var output = ""
dump(value, to: &output)
let expected =
"▿ 5 elements\n" +
" - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacWrite\n" +
" - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.MacPaint\n" +
" - Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.FileMaker\n" +
" ▿ Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.ClarisWorks\n" +
" ▿ ClarisWorks: (1 element)\n" +
" - floppy: true\n" +
" ▿ Mirror.MultiPayloadTagBitsSmallNonGenericEnumWithDefaultMirror.HyperCard\n" +
" ▿ HyperCard: (1 element)\n" +
" - cdrom: false\n"
expectEqual(expected, output)
}
}
enum MultiPayloadGenericEnumWithDefaultMirror<T, U> {
case IIe
case IIgs
case Centris(ram: T)
case Quadra(hdd: U)
case PowerBook170
case PowerBookDuo220
}
mirrors.test("Enum/MultiPayloadGeneric/DefaultMirror") {
do {
let value: [MultiPayloadGenericEnumWithDefaultMirror<Int, String>] =
[.IIe,
.IIgs,
.Centris(ram: 4096),
.Quadra(hdd: "160MB"),
.PowerBook170,
.PowerBookDuo220]
var output = ""
dump(value, to: &output)
let expected =
"▿ 6 elements\n" +
" - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIe\n" +
" - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.IIgs\n" +
" ▿ Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Centris\n" +
" ▿ Centris: (1 element)\n" +
" - ram: 4096\n" +
" ▿ Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.Quadra\n" +
" ▿ Quadra: (1 element)\n" +
" - hdd: \"160MB\"\n" +
" - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBook170\n" +
" - Mirror.MultiPayloadGenericEnumWithDefaultMirror<Swift.Int, Swift.String>.PowerBookDuo220\n"
expectEqual(expected, output)
}
expectEqual(0, LifetimeTracked.instances)
do {
let value = MultiPayloadGenericEnumWithDefaultMirror<LifetimeTracked,
LifetimeTracked>
.Quadra(hdd: LifetimeTracked(0))
expectEqual(1, LifetimeTracked.instances)
var output = ""
dump(value, to: &output)
}
expectEqual(0, LifetimeTracked.instances)
}
enum Foo<T> {
indirect case Foo(Int)
case Bar(T)
}
enum List<T> {
case Nil
indirect case Cons(first: T, rest: List<T>)
}
mirrors.test("Enum/IndirectGeneric/DefaultMirror") {
let x = Foo<String>.Foo(22)
let y = Foo<String>.Bar("twenty-two")
expectEqual("\(x)", "Foo(22)")
expectEqual("\(y)", "Bar(\"twenty-two\")")
let list = List.Cons(first: 0, rest: .Cons(first: 1, rest: .Nil))
expectEqual("Cons(first: 0, rest: Mirror.List<Swift.Int>.Cons(first: 1, rest: Mirror.List<Swift.Int>.Nil))",
"\(list)")
}
enum MyError: Error {
case myFirstError(LifetimeTracked)
}
mirrors.test("Enum/CaseName/Error") {
// Just make sure this doesn't leak.
let e: Error = MyError.myFirstError(LifetimeTracked(0))
_ = String(describing: e)
}
class Brilliant : CustomReflectable {
let first: Int
let second: String
init(_ fst: Int, _ snd: String) {
self.first = fst
self.second = snd
}
var customMirror: Mirror {
return Mirror(self, children: ["first": first, "second": second, "self": self])
}
}
//===--- Custom mirrors ---------------------------------------------------===//
//===----------------------------------------------------------------------===//
/// Subclasses inherit their parents' custom mirrors.
class Irradiant : Brilliant {
init() {
super.init(400, "")
}
}
mirrors.test("CustomMirror") {
do {
var output = ""
dump(Brilliant(123, "four five six"), to: &output)
let expected =
"▿ Mirror.Brilliant #0\n" +
" - first: 123\n" +
" - second: \"four five six\"\n" +
" ▿ self: Mirror.Brilliant #0\n"
expectEqual(expected, output)
}
do {
var output = ""
dump(Brilliant(123, "four five six"), to: &output, maxDepth: 0)
expectEqual("▹ Mirror.Brilliant #0\n", output)
}
do {
var output = ""
dump(Brilliant(123, "four five six"), to: &output, maxItems: 3)
let expected =
"▿ Mirror.Brilliant #0\n" +
" - first: 123\n" +
" - second: \"four five six\"\n" +
" (1 more child)\n"
expectEqual(expected, output)
}
do {
var output = ""
dump(Brilliant(123, "four five six"), to: &output, maxItems: 2)
let expected =
"▿ Mirror.Brilliant #0\n" +
" - first: 123\n" +
" (2 more children)\n"
expectEqual(expected, output)
}
do {
var output = ""
dump(Brilliant(123, "four five six"), to: &output, maxItems: 1)
let expected =
"▿ Mirror.Brilliant #0\n" +
" (3 children)\n"
expectEqual(expected, output)
}
}
mirrors.test("CustomMirrorIsInherited") {
do {
var output = ""
dump(Irradiant(), to: &output)
let expected =
"▿ Mirror.Brilliant #0\n" +
" - first: 400\n" +
" - second: \"\"\n" +
" ▿ self: Mirror.Brilliant #0\n"
expectEqual(expected, output)
}
}
//===--- Metatypes --------------------------------------------------------===//
//===----------------------------------------------------------------------===//
protocol SomeNativeProto {}
extension Int: SomeNativeProto {}
class SomeClass {}
mirrors.test("MetatypeMirror") {
do {
var output = ""
let concreteMetatype = Int.self
dump(concreteMetatype, to: &output)
let expectedInt = "- Swift.Int #0\n"
expectEqual(expectedInt, output)
let anyMetatype: Any.Type = Int.self
output = ""
dump(anyMetatype, to: &output)
expectEqual(expectedInt, output)
let nativeProtocolMetatype: SomeNativeProto.Type = Int.self
output = ""
dump(nativeProtocolMetatype, to: &output)
expectEqual(expectedInt, output)
let concreteClassMetatype = SomeClass.self
let expectedSomeClass = "- Mirror.SomeClass #0\n"
output = ""
dump(concreteClassMetatype, to: &output)
expectEqual(expectedSomeClass, output)
let nativeProtocolConcreteMetatype = SomeNativeProto.self
let expectedNativeProtocolConcrete = "- Mirror.SomeNativeProto #0\n"
output = ""
dump(nativeProtocolConcreteMetatype, to: &output)
expectEqual(expectedNativeProtocolConcrete, output)
}
}
//===--- Tuples -----------------------------------------------------------===//
//===----------------------------------------------------------------------===//
mirrors.test("TupleMirror") {
do {
var output = ""
let tuple =
(Brilliant(384, "seven six eight"), StructWithDefaultMirror("nine"))
dump(tuple, to: &output)
let expected =
"▿ (2 elements)\n" +
" ▿ .0: Mirror.Brilliant #0\n" +
" - first: 384\n" +
" - second: \"seven six eight\"\n" +
" ▿ self: Mirror.Brilliant #0\n" +
" ▿ .1: Mirror.StructWithDefaultMirror\n" +
" - s: \"nine\"\n"
expectEqual(expected, output)
expectEqual(.tuple, Mirror(reflecting: tuple).displayStyle)
}
do {
// A tuple of stdlib types with mirrors.
var output = ""
let tuple = (1, 2.5, false, "three")
dump(tuple, to: &output)
let expected =
"▿ (4 elements)\n" +
" - .0: 1\n" +
" - .1: 2.5\n" +
" - .2: false\n" +
" - .3: \"three\"\n"
expectEqual(expected, output)
}
do {
// A nested tuple.
var output = ""
let tuple = (1, ("Hello", "World"))
dump(tuple, to: &output)
let expected =
"▿ (2 elements)\n" +
" - .0: 1\n" +
" ▿ .1: (2 elements)\n" +
" - .0: \"Hello\"\n" +
" - .1: \"World\"\n"
expectEqual(expected, output)
}
}
//===--- Standard library types -------------------------------------------===//
//===----------------------------------------------------------------------===//
mirrors.test("String/Mirror") {
do {
var output = ""
dump("", to: &output)
let expected =
"- \"\"\n"
expectEqual(expected, output)
}
do {
// U+0061 LATIN SMALL LETTER A
// U+304B HIRAGANA LETTER KA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
// U+1F425 FRONT-FACING BABY CHICK
var output = ""
dump("\u{61}\u{304b}\u{3099}\u{1f425}", to: &output)
let expected =
"- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
expectEqual(expected, output)
}
}
mirrors.test("String.UTF8View/Mirror") {
// U+0061 LATIN SMALL LETTER A
// U+304B HIRAGANA LETTER KA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
var output = ""
dump("\u{61}\u{304b}\u{3099}".utf8, to: &output)
let expected =
"▿ UTF8View(\"\u{61}\u{304b}\u{3099}\")\n" +
" - 97\n" +
" - 227\n" +
" - 129\n" +
" - 139\n" +
" - 227\n" +
" - 130\n" +
" - 153\n"
expectEqual(expected, output)
}
mirrors.test("String.UTF16View/Mirror") {
// U+0061 LATIN SMALL LETTER A
// U+304B HIRAGANA LETTER KA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
// U+1F425 FRONT-FACING BABY CHICK
var output = ""
dump("\u{61}\u{304b}\u{3099}\u{1f425}".utf16, to: &output)
let expected =
"▿ StringUTF16(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
" - 97\n" +
" - 12363\n" +
" - 12441\n" +
" - 55357\n" +
" - 56357\n"
expectEqual(expected, output)
}
mirrors.test("String.UnicodeScalarView/Mirror") {
// U+0061 LATIN SMALL LETTER A
// U+304B HIRAGANA LETTER KA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
// U+1F425 FRONT-FACING BABY CHICK
var output = ""
dump("\u{61}\u{304b}\u{3099}\u{1f425}".unicodeScalars, to: &output)
let expected =
"▿ StringUnicodeScalarView(\"\u{61}\u{304b}\u{3099}\u{1f425}\")\n" +
" - \"\u{61}\"\n" +
" - \"\\u{304B}\"\n" +
" - \"\\u{3099}\"\n" +
" - \"\\u{0001F425}\"\n"
expectEqual(expected, output)
}
mirrors.test("Character/Mirror") {
do {
// U+0061 LATIN SMALL LETTER A
let input: Character = "\u{61}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\u{61}\"\n"
expectEqual(expected, output)
}
do {
// U+304B HIRAGANA LETTER KA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
let input: Character = "\u{304b}\u{3099}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\u{304b}\u{3099}\"\n"
expectEqual(expected, output)
}
do {
// U+1F425 FRONT-FACING BABY CHICK
let input: Character = "\u{1f425}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\u{1f425}\"\n"
expectEqual(expected, output)
}
}
mirrors.test("UnicodeScalar") {
do {
// U+0061 LATIN SMALL LETTER A
let input: UnicodeScalar = "\u{61}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\u{61}\"\n"
expectEqual(expected, output)
}
do {
// U+304B HIRAGANA LETTER KA
let input: UnicodeScalar = "\u{304b}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\\u{304B}\"\n"
expectEqual(expected, output)
}
do {
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
let input: UnicodeScalar = "\u{3099}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\\u{3099}\"\n"
expectEqual(expected, output)
}
do {
// U+1F425 FRONT-FACING BABY CHICK
let input: UnicodeScalar = "\u{1f425}"
var output = ""
dump(input, to: &output)
let expected =
"- \"\\u{0001F425}\"\n"
expectEqual(expected, output)
}
}
mirrors.test("Bool") {
do {
var output = ""
dump(false, to: &output)
let expected =
"- false\n"
expectEqual(expected, output)
}
do {
var output = ""
dump(true, to: &output)
let expected =
"- true\n"
expectEqual(expected, output)
}
}
// FIXME: these tests should cover Float80.
// FIXME: these tests should be automatically generated from the list of
// available floating point types.
mirrors.test("Float") {
do {
var output = ""
dump(Float.nan, to: &output)
let expected =
"- nan\n"
expectEqual(expected, output)
}
do {
var output = ""
dump(Float.infinity, to: &output)
let expected =
"- inf\n"
expectEqual(expected, output)
}
do {
var input: Float = 42.125
var output = ""
dump(input, to: &output)
let expected =
"- 42.125\n"
expectEqual(expected, output)
}
}
mirrors.test("Double") {
do {
var output = ""
dump(Double.nan, to: &output)
let expected =
"- nan\n"
expectEqual(expected, output)
}
do {
var output = ""
dump(Double.infinity, to: &output)
let expected =
"- inf\n"
expectEqual(expected, output)
}
do {
var input: Double = 42.125
var output = ""
dump(input, to: &output)
let expected =
"- 42.125\n"
expectEqual(expected, output)
}
}
mirrors.test("StaticString/Mirror") {
do {
var output = ""
dump("" as StaticString, to: &output)
let expected =
"- \"\"\n"
expectEqual(expected, output)
}
do {
// U+0061 LATIN SMALL LETTER A
// U+304B HIRAGANA LETTER KA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
// U+1F425 FRONT-FACING BABY CHICK
var output = ""
dump("\u{61}\u{304b}\u{3099}\u{1f425}" as StaticString, to: &output)
let expected =
"- \"\u{61}\u{304b}\u{3099}\u{1f425}\"\n"
expectEqual(expected, output)
}
}
mirrors.test("DictionaryIterator/Mirror") {
let d: [MinimalHashableValue : OpaqueValue<Int>] =
[ MinimalHashableValue(0) : OpaqueValue(0) ]
var output = ""
dump(d.makeIterator(), to: &output)
let expected =
"- Swift.Dictionary<StdlibUnittest.MinimalHashableValue, StdlibUnittest.OpaqueValue<Swift.Int>>.Iterator\n"
expectEqual(expected, output)
}
mirrors.test("SetIterator/Mirror") {
let s: Set<MinimalHashableValue> = [ MinimalHashableValue(0)]
var output = ""
dump(s.makeIterator(), to: &output)
let expected =
"- Swift.Set<StdlibUnittest.MinimalHashableValue>.Iterator\n"
expectEqual(expected, output)
}
//===--- Regressions ------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// A struct type and class type whose NominalTypeDescriptor.FieldNames
// data is exactly eight bytes long. FieldNames data of exactly
// 4 or 8 or 16 bytes was once miscompiled on arm64.
struct EightByteFieldNamesStruct {
let abcdef = 42
}
class EightByteFieldNamesClass {
let abcdef = 42
}
mirrors.test("FieldNamesBug") {
do {
let expected =
"▿ Mirror.EightByteFieldNamesStruct\n" +
" - abcdef: 42\n"
var output = ""
dump(EightByteFieldNamesStruct(), to: &output)
expectEqual(expected, output)
}
do {
let expected =
"▿ Mirror.EightByteFieldNamesClass #0\n" +
" - abcdef: 42\n"
var output = ""
dump(EightByteFieldNamesClass(), to: &output)
expectEqual(expected, output)
}
}
mirrors.test("MirrorMirror") {
var object = 1
var mirror = Mirror(reflecting: object)
var mirrorMirror = Mirror(reflecting: mirror)
expectEqual(0, mirrorMirror.children.count)
}
mirrors.test("OpaquePointer/null") {
// Don't crash on null pointers. rdar://problem/19708338
let pointer: OpaquePointer? = nil
let mirror = Mirror(reflecting: pointer)
expectEqual(0, mirror.children.count)
}
struct a<b> {
enum c{}
}
class d {}
struct e<f> {
var constraints: [Int: a<f>.c] = [:]
}
mirrors.test("GenericNestedTypeField") {
let x = e<d>()
expectTrue(type(of: Mirror(reflecting: x).children.first!.value)
== [Int: a<d>.c].self)
}
extension OtherOuter {
struct Inner {}
}
extension OtherOuterGeneric {
struct Inner<U> {}
}
mirrors.test("SymbolicReferenceInsideType") {
let s = OtherStruct(a: OtherOuter.Inner(),
b: OtherOuterGeneric<Int>.Inner<String>())
var output = ""
dump(s, to: &output)
let expected =
"▿ Mirror.OtherStruct\n" +
" - a: Mirror.OtherOuter.Inner\n" +
" - b: Mirror.OtherOuterGeneric<Swift.Int>.Inner<Swift.String>\n"
expectEqual(expected, output)
}
protocol P1 { }
protocol P2 { }
protocol P3 { }
struct ConformsToP1: P1 { }
struct ConformsToP2: P2 { }
struct ConformsToP3: P3 { }
struct OuterTwoParams<T: P1, U: P2> {}
struct ConformsToP1AndP2 : P1, P2 { }
extension OuterTwoParams where U == T {
struct InnerEqualParams<V: P3> {
var x: T
var y: U
var z: V
}
}
mirrors.test("GenericNestedWithSameTypeConstraints") {
let value = OuterTwoParams.InnerEqualParams(x: ConformsToP1AndP2(),
y: ConformsToP1AndP2(),
z: ConformsToP3())
var output = ""
dump(value, to: &output)
let expected =
"▿ (extension in Mirror):Mirror.OuterTwoParams<Mirror.ConformsToP1AndP2, Mirror.ConformsToP1AndP2>.InnerEqualParams<Mirror.ConformsToP3>\n" +
" - x: Mirror.ConformsToP1AndP2\n" +
" - y: Mirror.ConformsToP1AndP2\n" +
" - z: Mirror.ConformsToP3\n"
expectEqual(expected, output)
}
@_alignment(16) struct CustomAlignment {
var x: Int
var y: Int
}
mirrors.test("CustomAlignment") {
let value = CustomAlignment(x: 123, y: 321)
var output = ""
dump(value, to: &output)
let expected =
"▿ Mirror.CustomAlignment\n" +
" - x: 123\n" +
" - y: 321\n"
expectEqual(expected, output)
}
protocol STSTagProtocol {}
struct STSOuter : STSTagProtocol {}
enum STSContainer<T : STSTagProtocol> {
class Superclass {}
class Subclass<U>: Superclass where T == STSOuter {
class ExtraNested: Superclass {}
}
class GenericSuperclass<U> {}
class Subclass2<U>: GenericSuperclass<U> where T == STSOuter {}
class Subclass3<U: Collection>: Superclass where T == U.Element {}
class MoreNesting<X> {
class Subclass<U>: Superclass where T == STSOuter {}
}
struct Fields<U> where T == STSOuter {
var x: T?
var y: U?
}
enum Cases<U> where T == STSOuter {
case a(T)
case b(U)
}
}
// A new type with an easily-recognizable, easily-strippable suffix character.
enum STSContainer<T : STSTagProtocol> {
class Superclass {}
class GenericSuperclass<U> {}
}
extension STSContainer where T == STSOuter {
class Subclass<U>: Superclass {
class ExtraNested: Superclass {}
}
class Subclass2<U>: GenericSuperclass<U> {}
class MoreNesting<X> {
class Subclass<U>: Superclass {}
}
struct Fields<U> {
var x: T?
var y: U?
}
enum Cases<U> {
case a(T)
case b(U)
}
}
var sameTypeSuite = TestSuite("Mirrors.SameTypeConstraints")
func testSTSDump<RegularValue, ExtensionValue>(
_ regular: RegularValue,
_ ext: ExtensionValue,
_ expected: String
) {
var output = ""
dump(regular, to: &output)
expectEqual(expected, output)
func clean(_ dumpOutput: String) -> String {
// This isn't efficient but it doesn't have to be.
var result = dumpOutput
result.removeAll { $0 == "" }
if let openParenIndex = result.firstIndex(of: "(") {
if result[openParenIndex...].hasPrefix("(extension in Mirror):") {
let colonIndex = result[openParenIndex...].firstIndex(of: ":")!
result.removeSubrange(openParenIndex...colonIndex)
}
}
return result
}
var extensionOutput = ""
dump(ext, to: &extensionOutput)
expectEqual(expected, clean(extensionOutput))
}
func testSTSDump<RegularValue>(_ regular: RegularValue, _ expected: String) {
var output = ""
dump(regular, to: &output)
expectEqual(expected, output)
}
sameTypeSuite.test("Subclass") {
testSTSDump(STSContainer.Subclass<Int>(),
STSContainer.Subclass<Int>(),
"""
- Mirror.STSContainer<Mirror.STSOuter>.Subclass<Swift.Int> #0
- super: Mirror.STSContainer<Mirror.STSOuter>.Superclass\n
""")
testSTSDump(STSContainer.Subclass2<Int>(),
STSContainer.Subclass2<Int>(),
"""
- Mirror.STSContainer<Mirror.STSOuter>.Subclass2<Swift.Int> #0
- super: Mirror.STSContainer<Mirror.STSOuter>.GenericSuperclass<Swift.Int>\n
""")
testSTSDump(STSContainer.Subclass3<[STSOuter]>(),
"""
- Mirror.STSContainer<Mirror.STSOuter>.Subclass3<Swift.Array<Mirror.STSOuter>> #0
- super: Mirror.STSContainer<Mirror.STSOuter>.Superclass\n
""")
testSTSDump(STSContainer.Subclass<Int>.ExtraNested(),
STSContainer.Subclass<Int>.ExtraNested(),
"""
- Mirror.STSContainer<Mirror.STSOuter>.Subclass<Swift.Int>.ExtraNested #0
- super: Mirror.STSContainer<Mirror.STSOuter>.Superclass\n
""")
testSTSDump(STSContainer.MoreNesting<Bool>.Subclass<Int>(),
STSContainer.MoreNesting<Bool>.Subclass<Int>(),
"""
- Mirror.STSContainer<Mirror.STSOuter>.MoreNesting<Swift.Bool>.Subclass<Swift.Int> #0
- super: Mirror.STSContainer<Mirror.STSOuter>.Superclass\n
""")
}
sameTypeSuite.test("Fields") {
testSTSDump(STSContainer.Fields<Int>(),
STSContainer.Fields<Int>(),
"""
▿ Mirror.STSContainer<Mirror.STSOuter>.Fields<Swift.Int>
- x: nil
- y: nil\n
""")
}
sameTypeSuite.test("Cases") {
testSTSDump(STSContainer.Cases<Int>.a(.init()),
STSContainer.Cases<Int>.a(.init()),
"""
- Mirror.STSContainer<Mirror.STSOuter>.Cases<Swift.Int>.a\n
""")
testSTSDump(STSContainer.Cases<Int>.b(.init()),
STSContainer.Cases<Int>.b(.init()),
"""
▿ Mirror.STSContainer<Mirror.STSOuter>.Cases<Swift.Int>.b
- b: 0\n
""")
}
runAllTests()