blob: 7170a46a305e3c5bdc12a0fe405ddb567bf8a974 [file] [log] [blame]
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
import StdlibUnittest
var ProtocolExtensionTestSuite = TestSuite("ProtocolExtensions")
// Extend a protocol with a property.
extension Sequence {
var myCount: Int {
var result = 0
for _ in self {
result += 1
}
return result
}
}
// Extend a protocol with a function.
extension Collection {
var myIndices: Range<Index> {
return startIndex..<endIndex
}
func clone() -> Self {
return self
}
}
ProtocolExtensionTestSuite.test("Count") {
expectEqual(4, ["a", "b", "c", "d"].myCount)
expectEqual(4, ["a", "b", "c", "d"].clone().myCount)
}
extension Sequence {
public func myEnumerated() -> EnumeratedSequence<Self> {
return self.enumerated()
}
}
ProtocolExtensionTestSuite.test("Enumerated") {
var result: [(Int, String)] = []
for (index, element) in ["a", "b", "c"].myEnumerated() {
result.append((index, element))
}
expectTrue((0, "a") == result[0])
expectTrue((1, "b") == result[1])
expectTrue((2, "c") == result[2])
}
extension Sequence {
public func myReduce<T>(
_ initial: T, combine: (T, Self.Iterator.Element) -> T
) -> T {
var result = initial
for value in self {
result = combine(result, value)
}
return result
}
}
extension Sequence {
public func myZip<S : Sequence>(_ s: S) -> Zip2Sequence<Self, S> {
return zip(self, s)
}
}
ProtocolExtensionTestSuite.test("Algorithms") {
expectEqual(15, [1, 2, 3, 4, 5].myReduce(0, combine: { $0 + $1 }))
var result: [(Int, String)] = []
for (a, b) in [1, 2, 3].myZip(["a", "b", "c"]) {
result.append((a, b))
}
expectTrue((1, "a") == result[0])
expectTrue((2, "b") == result[1])
expectTrue((3, "c") == result[2])
}
// Mutating algorithms.
extension MutableCollection
where Self: RandomAccessCollection, Self.Iterator.Element : Comparable {
public mutating func myPartition() -> Index {
let first = self.first
return self.partition(by: { $0 >= first! })
}
}
extension RangeReplaceableCollection {
public func myJoin<S : Sequence>(
_ elements: S
) -> Self where S.Iterator.Element == Self {
var result = Self()
var iter = elements.makeIterator()
if let first = iter.next() {
result.append(contentsOf: first)
while let next = iter.next() {
result.append(contentsOf: self)
result.append(contentsOf: next)
}
}
return result
}
}
ProtocolExtensionTestSuite.test("MutatingAlgorithms") {
expectEqual("a,b,c", ",".myJoin(["a", "b", "c"]))
}
// Constrained extensions for specific types.
extension Collection where Self.Iterator.Element == String {
var myCommaSeparatedList: String {
if startIndex == endIndex { return "" }
var result = ""
var first = true
for x in self {
if first { first = false }
else { result += ", " }
result += x
}
return result
}
}
ProtocolExtensionTestSuite.test("ConstrainedExtension") {
expectEqual("x, y, z", ["x", "y", "z"].myCommaSeparatedList)
}
// Existentials
var runExistP1 = 0
var existP1_struct = 0
var existP1_class = 0
protocol ExistP1 {
func existP1()
}
extension ExistP1 {
func runExistP1() {
main.runExistP1 += 1
self.existP1()
}
}
struct ExistP1_Struct : ExistP1 {
func existP1() {
existP1_struct += 1
}
}
class ExistP1_Class : ExistP1 {
func existP1() {
existP1_class += 1
}
}
ProtocolExtensionTestSuite.test("Existentials") {
do {
let existP1: ExistP1 = ExistP1_Struct()
existP1.runExistP1()
expectEqual(1, runExistP1)
expectEqual(1, existP1_struct)
}
do {
let existP1 = ExistP1_Class()
existP1.runExistP1()
expectEqual(2, runExistP1)
expectEqual(1, existP1_class)
}
}
protocol P {
mutating func setValue(_ b: Bool)
func getValue() -> Bool
}
extension P {
var extValue: Bool {
get { return getValue() }
set(newValue) { setValue(newValue) }
}
}
extension Bool : P {
mutating func setValue(_ b: Bool) { self = b }
func getValue() -> Bool { return self }
}
class C : P {
var theValue: Bool = false
func setValue(_ b: Bool) { theValue = b }
func getValue() -> Bool { return theValue }
}
func toggle(_ value: inout Bool) {
value = !value
}
ProtocolExtensionTestSuite.test("ExistentialToggle") {
var p: P = true
expectTrue(p.extValue)
p.extValue = false
expectFalse(p.extValue)
toggle(&p.extValue)
expectTrue(p.extValue)
p = C()
p.extValue = true
expectTrue(p.extValue)
p.extValue = false
expectFalse(p.extValue)
toggle(&p.extValue)
expectTrue(p.extValue)
}
// Logical lvalues of existential type.
struct HasP {
var _p: P
var p: P {
get { return _p }
set { _p = newValue }
}
}
ProtocolExtensionTestSuite.test("ExistentialLValue") {
var hasP = HasP(_p: false)
hasP.p.extValue = true
expectTrue(hasP.p.extValue)
toggle(&hasP.p.extValue)
expectFalse(hasP.p.extValue)
}
var metatypes: [(Int, Any.Type)] = []
// rdar://problem/20739719
class Super: Init {
required init(x: Int) {
metatypes.append((x, type(of: self)))
}
}
class Sub: Super {}
protocol Init { init(x: Int) }
extension Init { init() { self.init(x: 17) } }
ProtocolExtensionTestSuite.test("ClassInitializer") {
_ = Super()
_ = Sub()
var sup: Super.Type = Super.self
_ = sup.init()
sup = Sub.self
_ = sup.init()
expectTrue(17 == metatypes[0].0)
expectTrue(Super.self == metatypes[0].1)
expectTrue(17 == metatypes[1].0)
expectTrue(Sub.self == metatypes[1].1)
expectTrue(17 == metatypes[2].0)
expectTrue(Super.self == metatypes[2].1)
expectTrue(17 == metatypes[3].0)
expectTrue(Sub.self == metatypes[3].1)
}
// https://bugs.swift.org/browse/SR-617
protocol SelfMetadataTest {
associatedtype T = Int
func staticTypeOfSelf() -> Any.Type
func staticTypeOfSelfTakesT(_: T) -> Any.Type
func staticTypeOfSelfCallsWitness() -> Any.Type
}
extension SelfMetadataTest {
func staticTypeOfSelf() -> Any.Type {
return Self.self
}
func staticTypeOfSelfTakesT(_: T) -> Any.Type {
return Self.self
}
func staticTypeOfSelfNotAWitness() -> Any.Type {
return Self.self
}
func staticTypeOfSelfCallsWitness() -> Any.Type {
return staticTypeOfSelf()
}
}
class SelfMetadataBase : SelfMetadataTest {}
class SelfMetadataDerived : SelfMetadataBase {}
class SelfMetadataGeneric<T> : SelfMetadataTest {}
func testSelfMetadata<T : SelfMetadataTest>(_ x: T, _ t: T.T) -> [Any.Type] {
return [x.staticTypeOfSelf(),
x.staticTypeOfSelfTakesT(t),
x.staticTypeOfSelfNotAWitness(),
x.staticTypeOfSelfCallsWitness()]
}
ProtocolExtensionTestSuite.test("WitnessSelf") {
do {
let result = testSelfMetadata(SelfMetadataBase(), 0)
expectTrue(SelfMetadataBase.self == result[0])
expectTrue(SelfMetadataBase.self == result[1])
expectTrue(SelfMetadataBase.self == result[2])
expectTrue(SelfMetadataBase.self == result[3])
}
do {
let result = testSelfMetadata(SelfMetadataDerived() as SelfMetadataBase, 0)
expectTrue(SelfMetadataBase.self == result[0])
expectTrue(SelfMetadataBase.self == result[1])
expectTrue(SelfMetadataBase.self == result[2])
expectTrue(SelfMetadataBase.self == result[3])
}
// This is the interesting case -- make sure the static type of 'Self'
// is correctly passed on from the call site to the extension method
do {
let result = testSelfMetadata(SelfMetadataDerived(), 0)
expectTrue(SelfMetadataDerived.self == result[0])
expectTrue(SelfMetadataBase.self == result[1])
expectTrue(SelfMetadataDerived.self == result[2])
expectTrue(SelfMetadataDerived.self == result[3])
}
// Make sure the calling convention works out if 'Self' is a generic
// class too.
do {
let result = testSelfMetadata(SelfMetadataGeneric<Int>(), 0)
expectTrue(SelfMetadataGeneric<Int>.self == result[0])
expectTrue(SelfMetadataGeneric<Int>.self == result[1])
expectTrue(SelfMetadataGeneric<Int>.self == result[2])
expectTrue(SelfMetadataGeneric<Int>.self == result[3])
}
}
runAllTests()