Skip to content

Commit 4026eba

Browse files
authored
Merge pull request #4081 from apple/swift3-SR-1988
[swift-3.0-branch] stdlib: fix incorrect distance measurement between UTF-16 indices
2 parents f4d4893 + 68afeb9 commit 4026eba

File tree

4 files changed

+153
-1
lines changed

4 files changed

+153
-1
lines changed

stdlib/private/StdlibUnittest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_swift_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STD
1515
# filename.
1616
StdlibUnittest.swift.gyb
1717

18+
CheckStrideable.swift.gyb
1819
InspectValue.cpp
1920
InspectValue.swift
2021
InterceptTraps.cpp
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
%{
14+
from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
15+
}%
16+
17+
public func checkStrideable<S : Strideable>(
18+
instances: [S],
19+
distances: [S.Stride],
20+
distanceOracle: (Int, Int) -> S.Stride,
21+
${TRACE}
22+
) {
23+
for i in instances.indices {
24+
let first = instances[i]
25+
for j in instances.indices {
26+
let second = instances[j]
27+
expectEqual(distanceOracle(i, j), first.distance(to: second))
28+
expectEqual(second, first.advanced(by: distanceOracle(i, j)))
29+
}
30+
}
31+
}
32+

stdlib/public/SDK/Foundation/ExtraStringAPIs.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ extension String.UTF16View.Index : Strideable {
2121
}
2222

2323
public func distance(to other: String.UTF16View.Index) -> Int {
24-
return other._offset.distance(to: _offset)
24+
return _offset.distance(to: other._offset)
2525
}
2626

2727
public func advanced(by n: Int) -> String.UTF16View.Index {

validation-test/stdlib/StringViews.swift

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import Swift
1616
import StdlibUnittest
17+
import StdlibCollectionUnittest
1718

1819
#if _runtime(_ObjC)
1920
// FIXME: Foundation leaks through StdlibUnittest. It adds some conformances
@@ -740,5 +741,123 @@ tests.test("UnicodeScalars->String") {
740741
}
741742
}
742743

744+
struct StringViewTest {
745+
var string: String
746+
var utf8: [UInt8]
747+
var utf16: [UInt16]
748+
var unicodeScalars: [UnicodeScalar]
749+
750+
init(string: String, utf8: [UInt8], utf16: [UInt16], utf32: [UInt32]) {
751+
self.string = string
752+
self.utf8 = utf8
753+
self.utf16 = utf16
754+
self.unicodeScalars = utf32.map { UnicodeScalar($0)! }
755+
}
756+
}
757+
758+
var stringViewTests: [StringViewTest] = [
759+
StringViewTest(
760+
string: "",
761+
utf8: [],
762+
utf16: [],
763+
utf32: []),
764+
StringViewTest(
765+
string: "\u{0000}",
766+
utf8: [0x00],
767+
utf16: [0x00],
768+
utf32: [0x00]),
769+
StringViewTest(
770+
string: "a",
771+
utf8: [0x61],
772+
utf16: [0x61],
773+
utf32: [0x61]),
774+
StringViewTest(
775+
string: "aa",
776+
utf8: [0x61, 0x61],
777+
utf16: [0x61, 0x61],
778+
utf32: [0x61, 0x61]),
779+
StringViewTest(
780+
string: "ab",
781+
utf8: [0x61, 0x62],
782+
utf16: [0x61, 0x62],
783+
utf32: [0x61, 0x62]),
784+
StringViewTest(
785+
string: "abc",
786+
utf8: [0x61, 0x62, 0x63],
787+
utf16: [0x61, 0x62, 0x63],
788+
utf32: [0x61, 0x62, 0x63]),
789+
StringViewTest(
790+
string: "\u{007f}",
791+
utf8: [0x7f],
792+
utf16: [0x7f],
793+
utf32: [0x7f]),
794+
StringViewTest(
795+
string: "\u{0430}",
796+
utf8: [0xd0, 0xb0],
797+
utf16: [0x0430],
798+
utf32: [0x0430]),
799+
StringViewTest(
800+
string: "\u{0430}\u{0431}\u{0432}",
801+
utf8: [0xd0, 0xb0, 0xd0, 0xb1, 0xd0, 0xb2],
802+
utf16: [0x0430, 0x0431, 0x0432],
803+
utf32: [0x0430, 0x0431, 0x0432]),
804+
StringViewTest(
805+
string: "\u{1f425}",
806+
utf8: [0xf0, 0x9f, 0x90, 0xa5],
807+
utf16: [0xd83d, 0xdc25],
808+
utf32: [0x1f425]),
809+
]
810+
811+
#if _runtime(_ObjC)
812+
tests.test("String.UTF16View.Index/Strideable")
813+
.forEach(in: stringViewTests) {
814+
test in
815+
816+
func allIndices<C : Collection>(of c: C) -> [C.Index]
817+
where C.Indices.Iterator.Element == C.Index
818+
{
819+
var result = Array(c.indices)
820+
result.append(c.endIndex)
821+
return result
822+
}
823+
824+
checkStrideable(
825+
instances: allIndices(of: test.string.utf16),
826+
distances: Array(0..<test.string.utf16.count),
827+
distanceOracle: { $1 - $0 })
828+
}
829+
#endif
830+
831+
tests.test("String.UTF8View/Collection")
832+
.forEach(in: stringViewTests) {
833+
test in
834+
835+
// FIXME(ABI): should be `checkBidirectionalCollection`.
836+
checkForwardCollection(test.utf8, test.string.utf8) { $0 == $1 }
837+
}
838+
839+
#if _runtime(_Native)
840+
tests.test("String.UTF16View/BidirectionalCollection")
841+
.forEach(in: stringViewTests) {
842+
test in
843+
844+
checkBidirectionalCollection(test.utf16, test.string.utf16) { $0 == $1 }
845+
}
846+
#else
847+
tests.test("String.UTF16View/RandomAccessCollection")
848+
.forEach(in: stringViewTests) {
849+
test in
850+
851+
checkRandomAccessCollection(test.utf16, test.string.utf16) { $0 == $1 }
852+
}
853+
#endif
854+
855+
tests.test("String.UTF32View/BidirectionalCollection")
856+
.forEach(in: stringViewTests) {
857+
test in
858+
859+
checkBidirectionalCollection(
860+
test.unicodeScalars, test.string.unicodeScalars) { $0 == $1 }
861+
}
743862

744863
runAllTests()

0 commit comments

Comments
 (0)