// RUN: %empty-directory(%t)
// RUN: %target-clang -fobjc-arc %S/Inputs/NSSlowString/NSSlowString.m -c -o %t/NSSlowString.o
// RUN: %target-build-swift -I %S/Inputs/NSSlowString/ %t/NSSlowString.o %s -Xfrontend -disable-access-control -o %t/String

// RUN: %target-codesign %t/String
// RUN: %target-run %t/String
// REQUIRES: executable_test
// XFAIL: interpret

// With a non-optimized stdlib the test takes very long.
// REQUIRES: optimized_stdlib

import StdlibUnittest
import StdlibCollectionUnittest

#if _runtime(_ObjC)
import NSSlowString
import Foundation  // For NSRange
#endif

#if os(Windows)
import ucrt
#endif

extension Collection {
  internal func index(_nth n: Int) -> Index {
    precondition(n >= 0)
    return index(startIndex, offsetBy: n)
  }
  internal func index(_nthLast n: Int) -> Index {
    precondition(n >= 0)
    return index(endIndex, offsetBy: -n)
  }
}

extension String {
  var nativeCapacity: Int {
    switch self._classify()._form {
      case ._native: break
      default: preconditionFailure()
    }
    return self._classify()._capacity
  }
  var capacity: Int {
    return self._classify()._capacity
  }
  var unusedCapacity: Int {
    return Swift.max(0, self._classify()._capacity - self._classify()._count)
  }
  var bufferID: ObjectIdentifier? {
    return _rawIdentifier()
  }
  func _rawIdentifier() -> ObjectIdentifier? {
    return self._classify()._objectIdentifier
  }

  var byteWidth: Int {
    return _classify()._isASCII ? 1 : 2
  }
}

extension Substring {
  var bufferID: ObjectIdentifier? {
    return base.bufferID
  }
}

// A thin wrapper around _StringGuts implementing RangeReplaceableCollection
struct StringFauxUTF16Collection: RangeReplaceableCollection, RandomAccessCollection {
  typealias Element = UTF16.CodeUnit
  typealias Index = Int
  typealias Indices = CountableRange<Int>

  init(_ guts: _StringGuts) {
    self._str = String(guts)
  }

  init() {
    self.init(_StringGuts())
  }

  var _str: String
  var _guts: _StringGuts { return _str._guts }

  var startIndex: Index { return 0 }
  var endIndex: Index { return _str.utf16.count }
  var indices: Indices { return startIndex..<endIndex }

  subscript(position: Index) -> Element {
    return _str.utf16[_str._toUTF16Index(position)]
  }

  mutating func replaceSubrange<C>(
    _ subrange: Range<Index>,
    with newElements: C
  ) where C : Collection, C.Element == Element {
    var utf16 = Array(_str.utf16)
    utf16.replaceSubrange(subrange, with: newElements)
    self._str = String(decoding: utf16, as: UTF16.self)
  }

  mutating func reserveCapacity(_ n: Int) {
    _str.reserveCapacity(n)
  }
}

var StringTests = TestSuite("StringTests")

StringTests.test("sizeof") {
#if arch(i386) || arch(arm)
  expectEqual(12, MemoryLayout<String>.size)
#else
  expectEqual(16, MemoryLayout<String>.size)
#endif
}

StringTests.test("AssociatedTypes-UTF8View") {
  typealias View = String.UTF8View
  expectCollectionAssociatedTypes(
    collectionType: View.self,
    iteratorType: View.Iterator.self,
    subSequenceType: Substring.UTF8View.self,
    indexType: View.Index.self,
    indicesType: DefaultIndices<View>.self)
}

StringTests.test("AssociatedTypes-UTF16View") {
  typealias View = String.UTF16View
  expectCollectionAssociatedTypes(
    collectionType: View.self,
    iteratorType: View.Iterator.self,
    subSequenceType: Substring.UTF16View.self,
    indexType: View.Index.self,
    indicesType: View.Indices.self)
}

StringTests.test("AssociatedTypes-UnicodeScalarView") {
  typealias View = String.UnicodeScalarView
  expectCollectionAssociatedTypes(
    collectionType: View.self,
    iteratorType: View.Iterator.self,
    subSequenceType: Substring.UnicodeScalarView.self,
    indexType: View.Index.self,
    indicesType: DefaultIndices<View>.self)
}

StringTests.test("AssociatedTypes-CharacterView") {
  expectCollectionAssociatedTypes(
    collectionType: String.self,
    iteratorType: String.Iterator.self,
    subSequenceType: Substring.self,
    indexType: String.Index.self,
    indicesType: DefaultIndices<String>.self)
}

func checkUnicodeScalarViewIteration(
    _ expectedScalars: [UInt32], _ str: String
) {
  do {
    let us = str.unicodeScalars
    var i = us.startIndex
    let end = us.endIndex
    var decoded: [UInt32] = []
    while i != end {
      expectTrue(i < us.index(after: i)) // Check for Comparable conformance
      decoded.append(us[i].value)
      i = us.index(after: i)
    }
    expectEqual(expectedScalars, decoded)
  }
  do {
    let us = str.unicodeScalars
    let start = us.startIndex
    var i = us.endIndex
    var decoded: [UInt32] = []
    while i != start {
      i = us.index(before: i)
      decoded.append(us[i].value)
    }
    expectEqual(expectedScalars, decoded)
  }
}

StringTests.test("unicodeScalars") {
  checkUnicodeScalarViewIteration([], "")
  checkUnicodeScalarViewIteration([ 0x0000 ], "\u{0000}")
  checkUnicodeScalarViewIteration([ 0x0041 ], "A")
  checkUnicodeScalarViewIteration([ 0x007f ], "\u{007f}")
  checkUnicodeScalarViewIteration([ 0x0080 ], "\u{0080}")
  checkUnicodeScalarViewIteration([ 0x07ff ], "\u{07ff}")
  checkUnicodeScalarViewIteration([ 0x0800 ], "\u{0800}")
  checkUnicodeScalarViewIteration([ 0xd7ff ], "\u{d7ff}")
  checkUnicodeScalarViewIteration([ 0x8000 ], "\u{8000}")
  checkUnicodeScalarViewIteration([ 0xe000 ], "\u{e000}")
  checkUnicodeScalarViewIteration([ 0xfffd ], "\u{fffd}")
  checkUnicodeScalarViewIteration([ 0xffff ], "\u{ffff}")
  checkUnicodeScalarViewIteration([ 0x10000 ], "\u{00010000}")
  checkUnicodeScalarViewIteration([ 0x10ffff ], "\u{0010ffff}")
}

StringTests.test("Index/Comparable") {
  let empty = ""
  expectTrue(empty.startIndex == empty.endIndex)
  expectFalse(empty.startIndex != empty.endIndex)
  expectTrue(empty.startIndex <= empty.endIndex)
  expectTrue(empty.startIndex >= empty.endIndex)
  expectFalse(empty.startIndex > empty.endIndex)
  expectFalse(empty.startIndex < empty.endIndex)

  let nonEmpty = "borkus biqualificated"
  expectFalse(nonEmpty.startIndex == nonEmpty.endIndex)
  expectTrue(nonEmpty.startIndex != nonEmpty.endIndex)
  expectTrue(nonEmpty.startIndex <= nonEmpty.endIndex)
  expectFalse(nonEmpty.startIndex >= nonEmpty.endIndex)
  expectFalse(nonEmpty.startIndex > nonEmpty.endIndex)
  expectTrue(nonEmpty.startIndex < nonEmpty.endIndex)
}

StringTests.test("Index/Hashable") {
  let s = "abcdef"
  let t = Set(s.indices)
  expectEqual(s.count, t.count)
  expectTrue(t.contains(s.startIndex))
}

StringTests.test("ForeignIndexes/Valid") {
  // It is actually unclear what the correct behavior is.  This test is just a
  // change detector.
  //
  // <rdar://problem/18037897> Design, document, implement invalidation model
  // for foreign String indexes
  do {
    let donor = "abcdef"
    let acceptor = "uvwxyz"
    expectEqual("u", acceptor[donor.startIndex])
    expectEqual("wxy",
      acceptor[donor.index(_nth: 2)..<donor.index(_nth: 5)])
  }
  do {
    let donor = "abcdef"
    let acceptor = "\u{1f601}\u{1f602}\u{1f603}"
    expectEqual("\u{1f601}", acceptor[donor.startIndex])

    // Scalar alignment fixes and checks were added in 5.1, so we don't get the
    // expected behavior on prior runtimes.
    guard _hasSwift_5_1() else { return }

    // Donor's second index is scalar-aligned in donor, but not acceptor. This
    // will trigger a stdlib assertion.
    let donorSecondIndex = donor.index(after: donor.startIndex)
    if _isStdlibInternalChecksEnabled() {
      expectCrash { _ = acceptor[donorSecondIndex] }
    } else {
      expectEqual(1, acceptor[donorSecondIndex].utf8.count)
      expectEqual(0x9F, acceptor[donorSecondIndex].utf8.first!)
    }
  }
}

StringTests.test("ForeignIndexes/UnexpectedCrash") {
  let donor = "\u{1f601}\u{1f602}\u{1f603}"
  let acceptor = "abcdef"

  // Adjust donor.startIndex to ensure it caches a stride
  let start = donor.index(before: donor.index(after: donor.startIndex))

  // Grapheme stride cache under noop scalar alignment was fixed in 5.1, so we
  // get a different answer prior.
  guard _hasSwift_5_1() else { return }

  // `start` has a cached stride greater than 1, so subscript will trigger an
  // assertion when it makes a multi-grapheme-cluster Character.
  if _isStdlibInternalChecksEnabled() {
   expectCrash { _ = acceptor[start] }
  } else {
    expectEqual("abcd", String(acceptor[start]))
  }
}

StringTests.test("ForeignIndexes/subscript(Index)/OutOfBoundsTrap") {
  let donor = "abcdef"
  let acceptor = "uvw"

  expectEqual("u", acceptor[donor.index(_nth: 0)])
  expectEqual("v", acceptor[donor.index(_nth: 1)])
  expectEqual("w", acceptor[donor.index(_nth: 2)])

  let i = donor.index(_nth: 3)
  expectCrashLater()
  _ = acceptor[i]
}

StringTests.test("String/subscript(_:Range)") {
  let s = "foobar"
  let from = s.startIndex
  let to = s.index(before: s.endIndex)
  let actual = s[from..<to]
  expectEqual("fooba", actual)
}

StringTests.test("String/subscript(_:ClosedRange)") {
  let s = "foobar"
  let from = s.startIndex
  let to = s.index(before: s.endIndex)
  let actual = s[from...to]
  expectEqual(s, actual)
}

StringTests.test("ForeignIndexes/subscript(Range)/OutOfBoundsTrap/1") {
  let donor = "abcdef"
  let acceptor = "uvw"

  expectEqual("uvw", acceptor[donor.startIndex..<donor.index(_nth: 3)])

  let r = donor.startIndex..<donor.index(_nth: 4)
  expectCrashLater()
  _ = acceptor[r]
}

StringTests.test("ForeignIndexes/subscript(Range)/OutOfBoundsTrap/2") {
  let donor = "abcdef"
  let acceptor = "uvw"

  expectEqual("uvw", acceptor[donor.startIndex..<donor.index(_nth: 3)])

  let r = donor.index(_nth: 4)..<donor.index(_nth: 5)
  expectCrashLater()
  _ = acceptor[r]
}

StringTests.test("ForeignIndexes/subscript(ClosedRange)/OutOfBoundsTrap/1") {
  let donor = "abcdef"
  let acceptor = "uvw"

  expectEqual("uvw", acceptor[donor.startIndex...donor.index(_nth: 2)])

  let r = donor.startIndex...donor.index(_nth: 3)
  expectCrashLater()
  _ = acceptor[r]
}

StringTests.test("ForeignIndexes/subscript(ClosedRange)/OutOfBoundsTrap/2") {
  let donor = "abcdef"
  let acceptor = "uvw"

  expectEqual("uvw", acceptor[donor.startIndex...donor.index(_nth: 2)])

  let r = donor.index(_nth: 3)...donor.index(_nth: 5)
  expectCrashLater()
  _ = acceptor[r]
}

StringTests.test("ForeignIndexes/replaceSubrange/OutOfBoundsTrap/1") {
  let donor = "abcdef"
  var acceptor = "uvw"

  acceptor.replaceSubrange(
    donor.startIndex..<donor.index(_nth: 1), with: "u")
  expectEqual("uvw", acceptor)

  let r = donor.startIndex..<donor.index(_nth: 4)
  expectCrashLater()
  acceptor.replaceSubrange(r, with: "")
}

StringTests.test("ForeignIndexes/replaceSubrange/OutOfBoundsTrap/2") {
  let donor = "abcdef"
  var acceptor = "uvw"

  acceptor.replaceSubrange(
    donor.startIndex..<donor.index(_nth: 1), with: "u")
  expectEqual("uvw", acceptor)

  let r = donor.index(_nth: 4)..<donor.index(_nth: 5)
  expectCrashLater()
  acceptor.replaceSubrange(r, with: "")
}

StringTests.test("ForeignIndexes/removeAt/OutOfBoundsTrap") {
  do {
    let donor = "abcdef"
    var acceptor = "uvw"

    let removed = acceptor.remove(at: donor.startIndex)
    expectEqual("u", removed)
    expectEqual("vw", acceptor)
  }

  let donor = "abcdef"
  var acceptor = "uvw"

  let i = donor.index(_nth: 4)
  expectCrashLater()
  acceptor.remove(at: i)
}

StringTests.test("ForeignIndexes/removeSubrange/OutOfBoundsTrap/1") {
  do {
    let donor = "abcdef"
    var acceptor = "uvw"

    acceptor.removeSubrange(
      donor.startIndex..<donor.index(after: donor.startIndex))
    expectEqual("vw", acceptor)
  }

  let donor = "abcdef"
  var acceptor = "uvw"

  let r = donor.startIndex..<donor.index(_nth: 4)
  expectCrashLater()
  acceptor.removeSubrange(r)
}

StringTests.test("ForeignIndexes/removeSubrange/OutOfBoundsTrap/2") {
  let donor = "abcdef"
  var acceptor = "uvw"

  let r = donor.index(_nth: 4)..<donor.index(_nth: 5)
  expectCrashLater()
  acceptor.removeSubrange(r)
}

StringTests.test("hasPrefix")
  .skip(.nativeRuntime("String.hasPrefix undefined without _runtime(_ObjC)"))
  .code {
#if _runtime(_ObjC)
  expectTrue("".hasPrefix(""))
  expectFalse("".hasPrefix("a"))
  expectTrue("a".hasPrefix(""))
  expectTrue("a".hasPrefix("a"))

  // U+0301 COMBINING ACUTE ACCENT
  // U+00E1 LATIN SMALL LETTER A WITH ACUTE
  expectFalse("abc".hasPrefix("a\u{0301}"))
  expectFalse("a\u{0301}bc".hasPrefix("a"))
  expectTrue("\u{00e1}bc".hasPrefix("a\u{0301}"))
  expectTrue("a\u{0301}bc".hasPrefix("\u{00e1}"))
#else
  expectUnreachable()
#endif
}

StringTests.test("literalConcatenation") {
  do {
    // UnicodeScalarLiteral + UnicodeScalarLiteral
    var s = "1" + "2"
    expectType(String.self, &s)
    expectEqual("12", s)
  }
  do {
    // UnicodeScalarLiteral + ExtendedGraphemeClusterLiteral
    var s = "1" + "a\u{0301}"
    expectType(String.self, &s)
    expectEqual("1a\u{0301}", s)
  }
  do {
    // UnicodeScalarLiteral + StringLiteral
    var s = "1" + "xyz"
    expectType(String.self, &s)
    expectEqual("1xyz", s)
  }

  do {
    // ExtendedGraphemeClusterLiteral + UnicodeScalar
    var s = "a\u{0301}" + "z"
    expectType(String.self, &s)
    expectEqual("a\u{0301}z", s)
  }
  do {
    // ExtendedGraphemeClusterLiteral + ExtendedGraphemeClusterLiteral
    var s = "a\u{0301}" + "e\u{0302}"
    expectType(String.self, &s)
    expectEqual("a\u{0301}e\u{0302}", s)
  }
  do {
    // ExtendedGraphemeClusterLiteral + StringLiteral
    var s = "a\u{0301}" + "xyz"
    expectType(String.self, &s)
    expectEqual("a\u{0301}xyz", s)
  }

  do {
    // StringLiteral + UnicodeScalar
    var s = "xyz" + "1"
    expectType(String.self, &s)
    expectEqual("xyz1", s)
  }
  do {
    // StringLiteral + ExtendedGraphemeClusterLiteral
    var s = "xyz" + "a\u{0301}"
    expectType(String.self, &s)
    expectEqual("xyza\u{0301}", s)
  }
  do {
    // StringLiteral + StringLiteral
    var s = "xyz" + "abc"
    expectType(String.self, &s)
    expectEqual("xyzabc", s)
  }
}

StringTests.test("substringDoesNotCopy/Swift3")
  .xfail(.always("Swift 3 compatibility: Self-sliced Strings are copied"))
  .code {

  let size = 16
  for sliceStart in [0, 2, 8, size] {
    for sliceEnd in [0, 2, 8, sliceStart + 1] {
      if sliceStart > size || sliceEnd > size || sliceEnd < sliceStart {
        continue
      }
      var s0 = String(repeating: "x", count: size)
      let originalIdentity = s0.bufferID
      s0 = String(s0[s0.index(_nth: sliceStart)..<s0.index(_nth: sliceEnd)])
      expectEqual(originalIdentity, s0.bufferID)
    }
  }
}

StringTests.test("substringDoesNotCopy/Swift4") {

  let size = 16
  for sliceStart in [0, 2, 8, size] {
    for sliceEnd in [0, 2, 8, sliceStart + 1] {
      if sliceStart > size || sliceEnd > size || sliceEnd < sliceStart {
        continue
      }
      let s0 = String(repeating: "x", count: size)
      let originalIdentity = s0.bufferID
      let s1 = s0[s0.index(_nth: sliceStart)..<s0.index(_nth: sliceEnd)]
      expectEqual(s1.bufferID, originalIdentity)
    }
  }
}

StringTests.test("appendToEmptyString") {
  let x = "Bumfuzzle"
  expectNil(x.bufferID)

  // Appending to empty string literal should replace it.
  var a1 = ""
  a1 += x
  expectNil(a1.bufferID)

  // Appending to native string should keep the existing buffer.
  var b1 = ""
  b1.reserveCapacity(20)
  let b1ID = b1.bufferID
  b1 += x
  expectEqual(b1.bufferID, b1ID)

  // .append(_:) should have the same behavior as +=
  var a2 = ""
  a2.append(x)
  expectNil(a2.bufferID)

  var b2 = ""
  b2.reserveCapacity(20)
  let b2ID = b2.bufferID
  b2.append(x)
  expectEqual(b2.bufferID, b2ID)
}

StringTests.test("Swift3Slice/Empty") {
  let size = 16
  let s = String(repeating: "x", count: size)
  expectNotNil(s.bufferID)
  for i in 0 ... size {
    let slice = s[s.index(_nth: i)..<s.index(_nth: i)]
    // Empty substrings still have indices relative to their base and can refer
    // to the whole string. If the whole string has storage, so should its
    // substring.
    expectNotNil(slice.bufferID)
  }
}

StringTests.test("Swift3Slice/Full") {
  let size = 16
  let s = String(repeating: "x", count: size)
  let slice = s[s.startIndex..<s.endIndex]
  // Most Swift 3 substrings are extracted into their own buffer,
  // but if the substring covers the full original string, it is used instead.
  expectEqual(slice.bufferID, s.bufferID)
}

StringTests.test("appendToSubstring") {
  for initialSize in 1..<16 {
    for sliceStart in [0, 2, 8, initialSize] {
      for sliceEnd in [0, 2, 8, sliceStart + 1] {
        if sliceStart > initialSize || sliceEnd > initialSize ||
          sliceEnd < sliceStart {
          continue
        }
        var s0 = String(repeating: "x", count: initialSize)
        s0 = String(s0[s0.index(_nth: sliceStart)..<s0.index(_nth: sliceEnd)])
        s0 += "x"
        expectEqual(
          String(
            repeating: "x",
            count: sliceEnd - sliceStart + 1),
          s0)
      }
    }
  }
}

StringTests.test("appendToSubstringBug")
  .xfail(.always("Swift 3 compatibility: Self-sliced Strings are copied"))
  .code {
  // String used to have a heap overflow bug when one attempted to append to a
  // substring that pointed to the end of a string buffer.
  //
  //                           Unused capacity
  //                           VVV
  // String buffer [abcdefghijk   ]
  //                      ^    ^
  //                      +----+
  // Substring -----------+
  //
  // In the example above, there are only three elements of unused capacity.
  // The bug was that the implementation mistakenly assumed 9 elements of
  // unused capacity (length of the prefix "abcdef" plus truly unused elements
  // at the end).

  func stringWithUnusedCapacity() -> (String, Int) {
    var s0 = String(repeating: "x", count: 17)
    if s0.unusedCapacity == 0 { s0 += "y" }
    let cap = s0.unusedCapacity
    expectNotEqual(0, cap)

    // This sorta checks for the original bug
    expectEqual(
      cap, String(s0[s0.index(_nth: 1)..<s0.endIndex]).unusedCapacity)

    return (s0, cap)
  }

  do {
    var (s, _) = { ()->(String, Int) in
      let (s0, unused) = stringWithUnusedCapacity()
      return (String(s0[s0.index(_nth: 5)..<s0.endIndex]), unused)
    }()
    let originalID = s.bufferID
    // Appending to a String always results in storage that
    // starts at the beginning of its native buffer
    s += "z"
    expectNotEqual(originalID, s.bufferID)
  }

  do {
    var (s, _) = { ()->(Substring, Int) in
      let (s0, unused) = stringWithUnusedCapacity()
      return (s0[s0.index(_nth: 5)..<s0.endIndex], unused)
    }()
    let originalID = s.bufferID
    // FIXME: Ideally, appending to a Substring with a unique buffer reference
    // does not reallocate unless necessary.  Today, however, it appears to do
    // so unconditionally unless the slice falls at the beginning of its buffer.
    s += "z"
    expectNotEqual(originalID, s.bufferID)
  }

  // Try again at the beginning of the buffer
  do {
    var (s, unused) = { ()->(Substring, Int) in
      let (s0, unused) = stringWithUnusedCapacity()
      return (s0[...], unused)
    }()
    let originalID = s.bufferID
    s += "z"
    expectEqual(originalID, s.bufferID)
    s += String(repeating: "z", count: unused - 1)
    expectEqual(originalID, s.bufferID)
    s += "."
    expectNotEqual(originalID, s.bufferID)
    unused += 0 // warning suppression
  }
}

StringTests.test("COW/removeSubrange/start") {
  var str = "12345678"
  str.reserveCapacity(1024) // Ensure on heap
  let literalIdentity = str.bufferID

  // Check literal-to-heap reallocation.
  do {
    let slice = str
    expectNotNil(literalIdentity)
    expectEqual(literalIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    expectEqual("12345678", str)
    expectEqual("12345678", slice)

    // This mutation should reallocate the string.
    str.removeSubrange(str.startIndex..<str.index(_nth: 1))
    expectNotEqual(literalIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    let heapStrIdentity = str.bufferID
    expectEqual("2345678", str)
    expectEqual("12345678", slice)

    // No more reallocations are expected.
    str.removeSubrange(str.startIndex..<str.index(_nth: 1))
    expectEqual(heapStrIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    expectEqual("345678", str)
    expectEqual("12345678", slice)
  }

  // Check heap-to-heap reallocation.
  expectEqual("345678", str)
  do {
    str.reserveCapacity(1024) // Ensure on heap
    let heapStrIdentity1 = str.bufferID

    let slice = str
    expectNotNil(heapStrIdentity1)
    expectEqual(heapStrIdentity1, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    expectEqual("345678", str)
    expectEqual("345678", slice)

    // This mutation should reallocate the string.
    str.removeSubrange(str.startIndex..<str.index(_nth: 1))
    expectNotEqual(heapStrIdentity1, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    let heapStrIdentity2 = str.bufferID
    expectEqual("45678", str)
    expectEqual("345678", slice)

    // No more reallocations are expected.
    str.removeSubrange(str.startIndex..<str.index(_nth: 1))
    expectEqual(heapStrIdentity2, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    expectEqual("5678", str)
    expectEqual("345678", slice)
  }
}

StringTests.test("COW/removeSubrange/end") {
  var str = "12345678"
  str.reserveCapacity(1024) // Ensure on heap
  let literalIdentity = str.bufferID

  // Check literal-to-heap reallocation.
  expectEqual("12345678", str)
  do {
    let slice = str
    expectNotNil(literalIdentity)
    expectEqual(literalIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    expectEqual("12345678", str)
    expectEqual("12345678", slice)

    // This mutation should reallocate the string.
    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    expectNotEqual(literalIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    let heapStrIdentity = str.bufferID
    expectEqual("1234567", str)
    expectEqual("12345678", slice)

    // No more reallocations are expected.
    str.append("x")
    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    expectEqual(heapStrIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    expectEqual("1234567", str)
    expectEqual("12345678", slice)

    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    str.append("x")
    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    expectEqual(heapStrIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    expectEqual("123456", str)
    expectEqual("12345678", slice)
  }

  // Check heap-to-heap reallocation.
  expectEqual("123456", str)
  do {
    str.reserveCapacity(1024) // Ensure on heap
    let heapStrIdentity1 = str.bufferID

    let slice = str
    expectNotNil(heapStrIdentity1)
    expectEqual(heapStrIdentity1, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    expectEqual("123456", str)
    expectEqual("123456", slice)

    // This mutation should reallocate the string.
    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    expectNotEqual(heapStrIdentity1, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    let heapStrIdentity = str.bufferID
    expectEqual("12345", str)
    expectEqual("123456", slice)

    // No more reallocations are expected.
    str.append("x")
    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    expectEqual(heapStrIdentity, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    expectEqual("12345", str)
    expectEqual("123456", slice)

    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    str.append("x")
    str.removeSubrange(str.index(_nthLast: 1)..<str.endIndex)
    expectEqual(heapStrIdentity, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)
    expectEqual("1234", str)
    expectEqual("123456", slice)
  }
}

StringTests.test("COW/replaceSubrange/end") {
  // Check literal-to-heap reallocation.
  do {
    var str = "12345678"
    str.reserveCapacity(1024) // Ensure on heap
    let literalIdentity = str.bufferID

    var slice = str[str.startIndex..<str.index(_nth: 7)]
    expectNotNil(literalIdentity)
    expectEqual(literalIdentity, str.bufferID)
    expectEqual(literalIdentity, slice.bufferID)
    expectEqual("12345678", str)
    expectEqual("1234567", slice)

    // This mutation should reallocate the string.
    slice.replaceSubrange(slice.endIndex..<slice.endIndex, with: "a")
    expectNotEqual(literalIdentity, slice.bufferID)
    expectEqual(literalIdentity, str.bufferID)
    let heapStrIdentity = slice.bufferID
    expectEqual("1234567a", slice)
    expectEqual("12345678", str)

    // No more reallocations are expected.
    slice.replaceSubrange(
      slice.index(_nthLast: 1)..<slice.endIndex, with: "b")
    expectEqual(heapStrIdentity, slice.bufferID)
    expectEqual(literalIdentity, str.bufferID)

    expectEqual("1234567b", slice)
    expectEqual("12345678", str)
  }

  // Check literal-to-heap reallocation.
  do {
    var str = "12345678"
    let literalIdentity = str.bufferID

    // Move the string to the heap.
    str.reserveCapacity(32)
    expectNotEqual(literalIdentity, str.bufferID)
    let heapStrIdentity1 = str.bufferID
    expectNotNil(heapStrIdentity1)

    // FIXME: We have to use Swift 4's Substring to get the desired storage
    // semantics; in Swift 3 mode, self-sliced strings get allocated a new
    // buffer immediately.
    var slice = str[str.startIndex..<str.index(_nth: 7)]
    expectEqual(heapStrIdentity1, str.bufferID)
    expectEqual(heapStrIdentity1, slice.bufferID)

    // This mutation should reallocate the string.
    slice.replaceSubrange(slice.endIndex..<slice.endIndex, with: "a")
    expectNotEqual(heapStrIdentity1, slice.bufferID)
    expectEqual(heapStrIdentity1, str.bufferID)
    let heapStrIdentity2 = slice.bufferID
    expectEqual("1234567a", slice)
    expectEqual("12345678", str)

    // No more reallocations are expected.
    slice.replaceSubrange(
      slice.index(_nthLast: 1)..<slice.endIndex, with: "b")
    expectEqual(heapStrIdentity2, slice.bufferID)
    expectEqual(heapStrIdentity1, str.bufferID)

    expectEqual("1234567b", slice)
    expectEqual("12345678", str)
  }
}

func asciiString<
  S: Sequence
>(_ content: S) -> String
where S.Iterator.Element == Character {
  var s = String()
  s.append(contentsOf: content)
  expectTrue(s._classify()._isASCII)
  return s
}

StringTests.test("stringGutsExtensibility")
  .skip(.nativeRuntime("Foundation dependency"))
  .code {
#if _runtime(_ObjC)
  let ascii = UTF16.CodeUnit(UnicodeScalar("X").value)
  let nonAscii = UTF16.CodeUnit(UnicodeScalar("é").value)

  for k in 0..<3 {
    for count in 1..<16 {
      for boundary in 0..<count {

        var x = (
            k == 0 ? asciiString("b")
          : k == 1 ? ("b" as NSString as String)
          : ("b" as NSMutableString as String)
        )

        if k == 0 { expectTrue(x._guts.isFastUTF8) }

        for i in 0..<count {
          x.append(String(
            decoding: repeatElement(i < boundary ? ascii : nonAscii, count: 3),
            as: UTF16.self))
        }
        // Make sure we can append pure ASCII to wide storage
        x.append(String(
          decoding: repeatElement(ascii, count: 2), as: UTF16.self))

        expectEqualSequence(
          [UTF16.CodeUnit(UnicodeScalar("b").value)]
          + Array(repeatElement(ascii, count: 3*boundary))
          + repeatElement(nonAscii, count: 3*(count - boundary))
          + repeatElement(ascii, count: 2),
          StringFauxUTF16Collection(x.utf16)
        )
      }
    }
  }
#else
  expectUnreachable()
#endif
}

StringTests.test("stringGutsReserve")
  .skip(.nativeRuntime("Foundation dependency"))
  .code {
#if _runtime(_ObjC)
  guard #available(macOS 10.13, iOS 11.0, tvOS 11.0, *) else { return }
  for k in 0...7 {
    var base: String
    var startedNative: Bool
    let shared: String = "X"

    // Managed native, unmanaged native, or small
    func isSwiftNative(_ s: String) -> Bool {
      switch s._classify()._form {
        case ._native: return true
        case ._small: return true
        case ._immortal: return true
        default: return false
      }
    }

    switch k {
    case 0: (base, startedNative) = (String(), true)
    case 1: (base, startedNative) = (asciiString("x"), true)
    case 2: (base, startedNative) = ("Ξ", true)
#if arch(i386) || arch(arm)
    case 3: (base, startedNative) = ("x" as NSString as String, false)
    case 4: (base, startedNative) = ("x" as NSMutableString as String, false)
#else
    case 3: (base, startedNative) = ("x" as NSString as String, true)
    case 4: (base, startedNative) = ("x" as NSMutableString as String, true)
#endif
    case 5: (base, startedNative) = (shared, true)
    case 6: (base, startedNative) = ("xá" as NSString as String, false)
    case 7: (base, startedNative) = ("xá" as NSMutableString as String, false)
    default:
      fatalError("case unhandled!")
    }
    expectEqual(isSwiftNative(base), startedNative)

    let originalBuffer = base.bufferID
    let isUnique = base._guts.isUniqueNative
    let startedUnique =
      startedNative &&
      base._classify()._objectIdentifier != nil &&
      isUnique

    base.reserveCapacity(16)
    // Now it's unique

    // If it was already native and unique, no reallocation
    if startedUnique && startedNative {
      expectEqual(originalBuffer, base.bufferID)
    }
    else {
      expectNotEqual(originalBuffer, base.bufferID)
    }

    // Reserving up to the capacity in a unique native buffer is a no-op
    let nativeBuffer = base.bufferID
    let currentCapacity = base.capacity
    base.reserveCapacity(currentCapacity)
    expectEqual(nativeBuffer, base.bufferID)

    // Reserving more capacity should reallocate
    base.reserveCapacity(currentCapacity + 1)
    expectNotEqual(nativeBuffer, base.bufferID)

    // None of this should change the string contents
    var expected: String
    switch k {
    case 0: expected = ""
    case 1,3,4: expected = "x"
    case 2: expected = "Ξ"
    case 5: expected = shared
    case 6,7: expected = "xá"
    default:
      fatalError("case unhandled!")
    }
    expectEqual(expected, base)
  }
#else
  expectUnreachable()
#endif
}

func makeStringGuts(_ base: String) -> _StringGuts {
  var x = String(_StringGuts())
  // make sure some - but not all - replacements will have to grow the buffer
  x.reserveCapacity(base._classify()._count * 3 / 2)
  let capacity = x.capacity
  x.append(base)
  // Widening the guts should not make it lose its capacity,
  // but the allocator may decide to get more storage.
  expectGE(x.capacity, capacity)
  return x._guts
}

StringTests.test("StringGutsReplace") {
  let narrow = "01234567890"
  let wide = "ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪ"
  for s1 in [narrow, wide] {
    for s2 in [narrow, wide] {
      let g1 = makeStringGuts(s1)
      let g2 = makeStringGuts(s2 + s2)
      checkRangeReplaceable(
        { StringFauxUTF16Collection(g1) },
        { StringFauxUTF16Collection(g2)[0..<$0] }
      )
      checkRangeReplaceable(
        { StringFauxUTF16Collection(g1) },
        { Array(StringFauxUTF16Collection(g2))[0..<$0] }
      )
    }
  }
}

StringTests.test("UnicodeScalarViewReplace") {
  let narrow = "01234567890"
  let wide = "ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪ"
  for s1 in [narrow, wide] {
    for s2 in [narrow, wide] {
      let doubleS2 = Array(String(makeStringGuts(s2 + s2)).utf16)
      checkRangeReplaceable(
        { () -> String.UnicodeScalarView in String(makeStringGuts(s1)).unicodeScalars },
        { String(decoding: doubleS2[0..<$0], as: UTF16.self).unicodeScalars }
      )
      checkRangeReplaceable(
        { String(makeStringGuts(s1)).unicodeScalars },
        { Array(String(makeStringGuts(s2 + s2)).unicodeScalars)[0..<$0] }
      )
    }
  }
}

StringTests.test("StringRRC") {
  let narrow = "01234567890"
  let wide = "ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪ"
  for s1 in [narrow, wide] {
    for s2 in [narrow, wide] {
      let doubleS2 = Array(String(makeStringGuts(s2 + s2)).utf16)
      checkRangeReplaceable(
        { () -> String in String(makeStringGuts(s1)) },
        { String(decoding: doubleS2[0..<$0], as: UTF16.self) }
      )
      checkRangeReplaceable(
        { String(makeStringGuts(s1)) },
        { Array(String(makeStringGuts(s2 + s2)))[0..<$0] }
      )
    }
  }
}

StringTests.test("reserveCapacity") {
  var s = ""
  let id0 = s.bufferID
  let oldCap = s.capacity
  let x: Character = "x" // Help the typechecker - <rdar://problem/17128913>
  s.insert(contentsOf: repeatElement(x, count: s.capacity + 1), at: s.endIndex)
  expectNotEqual(id0, s.bufferID)
  s = ""
  print("empty capacity \(s.capacity)")
  s.reserveCapacity(oldCap + 2)
  print("reserving \(oldCap + 2) [actual capacity: \(s.capacity)]")
  let id1 = s.bufferID
  s.insert(contentsOf: repeatElement(x, count: oldCap + 2), at: s.endIndex)
  print("extending by \(oldCap + 2) [actual capacity: \(s.capacity)]")
  expectEqual(id1, s.bufferID)
  s.insert(contentsOf: repeatElement(x, count: s.capacity + 100), at: s.endIndex)
  expectNotEqual(id1, s.bufferID)
}

StringTests.test("toInt") {
  expectNil(Int(""))
  expectNil(Int("+"))
  expectNil(Int("-"))
  expectEqual(20, Int("+20"))
  expectEqual(0, Int("0"))
  expectEqual(-20, Int("-20"))
  expectNil(Int("-cc20"))
  expectNil(Int("  -20"))
  expectNil(Int("  \t 20ddd"))

  expectEqual(Int.min, Int("\(Int.min)"))
  expectEqual(Int.min + 1, Int("\(Int.min + 1)"))
  expectEqual(Int.max, Int("\(Int.max)"))
  expectEqual(Int.max - 1, Int("\(Int.max - 1)"))

  expectNil(Int("\(Int.min)0"))
  expectNil(Int("\(Int.max)0"))

  // Make a String from an Int, mangle the String's characters,
  // then print if the new String is or is not still an Int.
  func testConvertabilityOfStringWithModification(
    _ initialValue: Int,
    modification: (_ chars: inout [UTF8.CodeUnit]) -> Void
  ) {
    var chars = Array(String(initialValue).utf8)
    modification(&chars)
    let str = String(decoding: chars, as: UTF8.self)
    expectNil(Int(str))
  }

  testConvertabilityOfStringWithModification(Int.min) {
    $0[2] += 1; ()  // underflow by lots
  }

  testConvertabilityOfStringWithModification(Int.max) {
    $0[1] += 1; ()  // overflow by lots
  }

  // Test values lower than min.
  do {
    let base = UInt(Int.max)
    expectEqual(Int.min + 1, Int("-\(base)"))
    expectEqual(Int.min, Int("-\(base + 1)"))
    for i in 2..<20 {
      expectNil(Int("-\(base + UInt(i))"))
    }
  }

  // Test values greater than min.
  do {
    let base = UInt(Int.max)
    for i in UInt(0)..<20 {
      expectEqual(-Int(base - i) , Int("-\(base - i)"))
    }
  }

  // Test values greater than max.
  do {
    let base = UInt(Int.max)
    expectEqual(Int.max, Int("\(base)"))
    for i in 1..<20 {
      expectNil(Int("\(base + UInt(i))"))
    }
  }

  // Test values lower than max.
  do {
    let base = Int.max
    for i in 0..<20 {
      expectEqual(base - i, Int("\(base - i)"))
    }
  }
}

// Make sure strings don't grow unreasonably quickly when appended-to
StringTests.test("growth") {
  var s = ""
  var s2 = s

  for _ in 0..<20 {
    s += "x"
    s2 = s
  }
  expectEqual(s2, s)
  expectLE(s.nativeCapacity, 40)
}

StringTests.test("Construction") {
  expectEqual("abc", String(["a", "b", "c"] as [Character]))
}

StringTests.test("Conversions") {
  // Whether we are natively ASCII or small ASCII
  func isKnownASCII(_ s: String) -> Bool {
    return s.byteWidth == 1
  }
  do {
    let c: Character = "a"
    let x = String(c)
    expectTrue(isKnownASCII(x))

    let s: String = "a"
    expectEqual(s, x)
  }

  do {
    let c: Character = "\u{B977}"
    let x = String(c)
    expectFalse(isKnownASCII(x))

    let s: String = "\u{B977}"
    expectEqual(s, x)
  }
}

#if canImport(Glibc)
  import Glibc
#endif

StringTests.test("lowercased()") {
  // Use setlocale so tolower() is correct on ASCII.
  setlocale(LC_ALL, "C")

  // Check the ASCII domain.
  let asciiDomain: [Int32] = Array(0..<128)
  expectEqualFunctionsForDomain(
    asciiDomain,
    { String(UnicodeScalar(Int(tolower($0)))!) },
    { String(UnicodeScalar(Int($0))!).lowercased() })

  expectEqual("", "".lowercased())
  expectEqual("abcd", "abCD".lowercased())
  expectEqual("абвг", "абВГ".lowercased())
  expectEqual("たちつてと", "たちつてと".lowercased())

  //
  // Special casing.
  //

  // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE
  // to lower case:
  // U+0069 LATIN SMALL LETTER I
  // U+0307 COMBINING DOT ABOVE
  expectEqual("\u{0069}\u{0307}", "\u{0130}".lowercased())

  // U+0049 LATIN CAPITAL LETTER I
  // U+0307 COMBINING DOT ABOVE
  // to lower case:
  // U+0069 LATIN SMALL LETTER I
  // U+0307 COMBINING DOT ABOVE
  expectEqual("\u{0069}\u{0307}", "\u{0049}\u{0307}".lowercased())
}

StringTests.test("uppercased()") {
  // Use setlocale so toupper() is correct on ASCII.
  setlocale(LC_ALL, "C")

  // Check the ASCII domain.
  let asciiDomain: [Int32] = Array(0..<128)
  expectEqualFunctionsForDomain(
    asciiDomain,
    { String(UnicodeScalar(Int(toupper($0)))!) },
    { String(UnicodeScalar(Int($0))!).uppercased() })

  expectEqual("", "".uppercased())
  expectEqual("ABCD", "abCD".uppercased())
  expectEqual("АБВГ", "абВГ".uppercased())
  expectEqual("たちつてと", "たちつてと".uppercased())

  //
  // Special casing.
  //

  // U+0069 LATIN SMALL LETTER I
  // to upper case:
  // U+0049 LATIN CAPITAL LETTER I
  expectEqual("\u{0049}", "\u{0069}".uppercased())

  // U+00DF LATIN SMALL LETTER SHARP S
  // to upper case:
  // U+0053 LATIN CAPITAL LETTER S
  // U+0073 LATIN SMALL LETTER S
  // But because the whole string is converted to uppercase, we just get two
  // U+0053.
  expectEqual("\u{0053}\u{0053}", "\u{00df}".uppercased())

  // U+FB01 LATIN SMALL LIGATURE FI
  // to upper case:
  // U+0046 LATIN CAPITAL LETTER F
  // U+0069 LATIN SMALL LETTER I
  // But because the whole string is converted to uppercase, we get U+0049
  // LATIN CAPITAL LETTER I.
  expectEqual("\u{0046}\u{0049}", "\u{fb01}".uppercased())
}

StringTests.test("unicodeViews") {
  // Check the UTF views work with slicing

  // U+FFFD REPLACEMENT CHARACTER
  // U+1F3C2 SNOWBOARDER
  // U+2603 SNOWMAN
  let winter = "\u{1F3C2}\u{2603}"

  // slices
  // First scalar is 4 bytes long, so this should be invalid
  expectNil(
    String(winter.utf8[
        winter.utf8.startIndex
        ..<
        winter.utf8.index(after: winter.utf8.index(after: winter.utf8.startIndex))
      ]))

  /*
  // FIXME: note changed String(describing:) results
  expectEqual(
    "\u{FFFD}",
    String(describing:
      winter.utf8[
        winter.utf8.startIndex
        ..<
        winter.utf8.index(after: winter.utf8.index(after: winter.utf8.startIndex))
      ]))
  */

  expectEqual(
    "\u{1F3C2}", String(
      winter.utf8[winter.utf8.startIndex..<winter.utf8.index(_nth: 4)]))

  expectEqual(
    "\u{1F3C2}", String(
      winter.utf16[winter.utf16.startIndex..<winter.utf16.index(_nth: 2)]))

  expectEqual(
    "\u{1F3C2}", String(
      winter.unicodeScalars[
        winter.unicodeScalars.startIndex..<winter.unicodeScalars.index(_nth: 1)
      ]))

  // views
  expectEqual(
    winter, String(
      winter.utf8[winter.utf8.startIndex..<winter.utf8.index(_nth: 7)]))

  expectEqual(
    winter, String(
      winter.utf16[winter.utf16.startIndex..<winter.utf16.index(_nth: 3)]))

  expectEqual(
    winter, String(
      winter.unicodeScalars[
        winter.unicodeScalars.startIndex..<winter.unicodeScalars.index(_nth: 2)
      ]))

  let ga = "\u{304b}\u{3099}"
  expectEqual(ga, String(ga.utf8[ga.utf8.startIndex..<ga.utf8.index(_nth: 6)]))
}

// Validate that index conversion does something useful for Cocoa
// programmers.
StringTests.test("indexConversion")
  .skip(.nativeRuntime("Foundation dependency"))
  .code {
#if _runtime(_ObjC)
  let re : NSRegularExpression
  do {
    re = try NSRegularExpression(
      pattern: "([^ ]+)er", options: NSRegularExpression.Options())
  } catch { fatalError("couldn't build regexp: \(error)") }

  let s = "go further into the larder to barter."

  var matches: [String] = []

  re.enumerateMatches(
    in: s, options: NSRegularExpression.MatchingOptions(), range: NSRange(0..<s.utf16.count)
  ) {
    result, flags, stop
  in
    let r = result!.range(at: 1)
    let start = String.Index(_encodedOffset: r.location)
    let end = String.Index(_encodedOffset: r.location + r.length)
    matches.append(String(s.utf16[start..<end])!)
  }

  expectEqual(["furth", "lard", "bart"], matches)
#else
  expectUnreachable()
#endif
}

StringTests.test("String.append(_: UnicodeScalar)") {
  var s = ""

  do {
    // U+0061 LATIN SMALL LETTER A
    let input: UnicodeScalar = "\u{61}"
    s.append(String(input))
    expectEqual(["\u{61}"], Array(s.unicodeScalars))
  }
  do {
    // U+304B HIRAGANA LETTER KA
    let input: UnicodeScalar = "\u{304b}"
    s.append(String(input))
    expectEqual(["\u{61}", "\u{304b}"], Array(s.unicodeScalars))
  }
  do {
    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
    let input: UnicodeScalar = "\u{3099}"
    s.append(String(input))
    expectEqual(["\u{61}", "\u{304b}", "\u{3099}"], Array(s.unicodeScalars))
  }
  do {
    // U+1F425 FRONT-FACING BABY CHICK
    let input: UnicodeScalar = "\u{1f425}"
    s.append(String(input))
    expectEqual(
      ["\u{61}", "\u{304b}", "\u{3099}", "\u{1f425}"],
      Array(s.unicodeScalars))
  }
}

StringTests.test("String.append(_: Character)") {
  let baseCharacters: [Character] = [
    // U+0061 LATIN SMALL LETTER A
    "\u{61}",

    // U+304B HIRAGANA LETTER KA
    // U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
    "\u{304b}\u{3099}",

    // U+3072 HIRAGANA LETTER HI
    // U+309A COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
    "\u{3072}\u{309A}",

    // U+1F425 FRONT-FACING BABY CHICK
    "\u{1f425}",

    // U+0061 LATIN SMALL LETTER A
    // U+0300 COMBINING GRAVE ACCENT
    // U+0301 COMBINING ACUTE ACCENT
    "\u{61}\u{0300}\u{0301}",

    // U+0061 LATIN SMALL LETTER A
    // U+0300 COMBINING GRAVE ACCENT
    // U+0301 COMBINING ACUTE ACCENT
    // U+0302 COMBINING CIRCUMFLEX ACCENT
    "\u{61}\u{0300}\u{0301}\u{0302}",

    // U+0061 LATIN SMALL LETTER A
    // U+0300 COMBINING GRAVE ACCENT
    // U+0301 COMBINING ACUTE ACCENT
    // U+0302 COMBINING CIRCUMFLEX ACCENT
    // U+0303 COMBINING TILDE
    "\u{61}\u{0300}\u{0301}\u{0302}\u{0303}",
  ]
  let baseStrings = [""] + baseCharacters.map { String($0) }

  for baseIdx in baseStrings.indices {
    for prefix in ["", " "] {
      let base = baseStrings[baseIdx]
      for inputIdx in baseCharacters.indices {
        let input = (prefix + String(baseCharacters[inputIdx])).last!
        var s = base
        s.append(input)
        expectEqualSequence(
          Array(base) + [input],
          Array(s),
          "baseIdx=\(baseIdx) inputIdx=\(inputIdx)")
      }
    }
  }
}

internal func decodeCString<
  C : UnicodeCodec
>(_ s: String, as codec: C.Type)
-> (result: String, repairsMade: Bool)? {
  let units = s.unicodeScalars.map({ $0.value }) + [0]
  return units.map({ C.CodeUnit($0) }).withUnsafeBufferPointer {
    String.decodeCString($0.baseAddress, as: C.self)
  }
}

StringTests.test("String.decodeCString/UTF8") {
  let actual = decodeCString("foobar", as: UTF8.self)
  expectFalse(actual!.repairsMade)
  expectEqual("foobar", actual!.result)
}

StringTests.test("String.decodeCString/UTF16") {
  let actual = decodeCString("foobar", as: UTF16.self)
  expectFalse(actual!.repairsMade)
  expectEqual("foobar", actual!.result)
}

StringTests.test("String.decodeCString/UTF32") {
  let actual = decodeCString("foobar", as: UTF32.self)
  expectFalse(actual!.repairsMade)
  expectEqual("foobar", actual!.result)
}

internal struct ReplaceSubrangeTest {
  let original: String
  let newElements: String
  let rangeSelection: RangeSelection
  let expected: String
  let closedExpected: String?
  let loc: SourceLoc

  internal init(
    original: String, newElements: String,
    rangeSelection: RangeSelection, expected: String, closedExpected: String? = nil,
    file: String = #file, line: UInt = #line
  ) {
    self.original = original
    self.newElements = newElements
    self.rangeSelection = rangeSelection
    self.expected = expected
    self.closedExpected = closedExpected
    self.loc = SourceLoc(file, line, comment: "replaceSubrange() test data")
  }
}

internal struct RemoveSubrangeTest {
  let original: String
  let rangeSelection: RangeSelection
  let expected: String
  let closedExpected: String
  let loc: SourceLoc

  internal init(
    original: String, rangeSelection: RangeSelection, expected: String,
    closedExpected: String? = nil,
    file: String = #file, line: UInt = #line
  ) {
    self.original = original
    self.rangeSelection = rangeSelection
    self.expected = expected
    self.closedExpected = closedExpected ?? expected
    self.loc = SourceLoc(file, line, comment: "replaceSubrange() test data")
  }
}

let replaceSubrangeTests = [
  ReplaceSubrangeTest(
    original: "",
    newElements: "",
    rangeSelection: .emptyRange,
    expected: ""
  ),
  ReplaceSubrangeTest(
    original: "",
    newElements: "meela",
    rangeSelection: .emptyRange,
    expected: "meela"
  ),
  ReplaceSubrangeTest(
    original: "eela",
    newElements: "m",
    rangeSelection: .leftEdge,
    expected: "meela",
    closedExpected: "mela"
  ),
  ReplaceSubrangeTest(
    original: "meel",
    newElements: "a",
    rangeSelection: .rightEdge,
    expected: "meela",
    closedExpected: "meea"
  ),
  ReplaceSubrangeTest(
    original: "a",
    newElements: "meel",
    rangeSelection: .leftEdge,
    expected: "meela",
    closedExpected: "meel"
  ),
  ReplaceSubrangeTest(
    original: "m",
    newElements: "eela",
    rangeSelection: .rightEdge,
    expected: "meela",
    closedExpected: "eela"
  ),
  ReplaceSubrangeTest(
    original: "alice",
    newElements: "bob",
    rangeSelection: .offsets(1, 1),
    expected: "aboblice",
    closedExpected: "abobice"
  ),
  ReplaceSubrangeTest(
    original: "alice",
    newElements: "bob",
    rangeSelection: .offsets(1, 2),
    expected: "abobice",
    closedExpected: "abobce"
  ),
  ReplaceSubrangeTest(
    original: "alice",
    newElements: "bob",
    rangeSelection: .offsets(1, 3),
    expected: "abobce",
    closedExpected: "abobe"
  ),
  ReplaceSubrangeTest(
    original: "alice",
    newElements: "bob",
    rangeSelection: .offsets(1, 4),
    expected: "abobe",
    closedExpected: "abob"
  ),
  ReplaceSubrangeTest(
    original: "alice",
    newElements: "bob",
    rangeSelection: .offsets(1, 5),
    expected: "abob"
  ),
  ReplaceSubrangeTest(
    original: "bob",
    newElements: "meela",
    rangeSelection: .offsets(1, 2),
    expected: "bmeelab",
    closedExpected: "bmeela"
  ),
  ReplaceSubrangeTest(
    original: "bobbobbobbobbobbobbobbobbobbob",
    newElements: "meela",
    rangeSelection: .offsets(1, 2),
    expected: "bmeelabbobbobbobbobbobbobbobbobbob",
    closedExpected: "bmeelabobbobbobbobbobbobbobbobbob"
  ),
  ReplaceSubrangeTest(
    original: "bob",
    newElements: "meelameelameelameelameela",
    rangeSelection: .offsets(1, 2),
    expected: "bmeelameelameelameelameelab",
    closedExpected: "bmeelameelameelameelameela"
  ),
]

let removeSubrangeTests = [
  RemoveSubrangeTest(
    original: "",
    rangeSelection: .emptyRange,
    expected: ""
  ),
  RemoveSubrangeTest(
    original: "a",
    rangeSelection: .middle,
    expected: ""
  ),
  RemoveSubrangeTest(
    original: "perdicus",
    rangeSelection: .leftHalf,
    expected: "icus"
  ),
  RemoveSubrangeTest(
    original: "perdicus",
    rangeSelection: .rightHalf,
    expected: "perd"
  ),
  RemoveSubrangeTest(
    original: "alice",
    rangeSelection: .middle,
    expected: "ae"
  ),
  RemoveSubrangeTest(
    original: "perdicus",
    rangeSelection: .middle,
    expected: "pes"
  ),
  RemoveSubrangeTest(
    original: "perdicus",
    rangeSelection: .offsets(1, 2),
    expected: "prdicus",
    closedExpected: "pdicus"
  ),
  RemoveSubrangeTest(
    original: "perdicus",
    rangeSelection: .offsets(3, 6),
    expected: "perus",
    closedExpected: "pers"
  ),
  RemoveSubrangeTest(
    original: "perdicusaliceandbob",
    rangeSelection: .offsets(3, 6),
    expected: "perusaliceandbob",
    closedExpected: "persaliceandbob"
  )
]

StringTests.test("String.replaceSubrange()/characters/range") {
  for test in replaceSubrangeTests {
    var theString = test.original
    let c = test.original
    let rangeToReplace = test.rangeSelection.range(in: c)
    let newCharacters : [Character] = Array(test.newElements)
    theString.replaceSubrange(rangeToReplace, with: newCharacters)
    expectEqual(
      test.expected,
      theString,
      stackTrace: SourceLocStack().with(test.loc))

    // Test unique-native optimized path
    var uniqNative = String(Array(test.original))
    uniqNative.replaceSubrange(rangeToReplace, with: newCharacters)
    expectEqual(theString, uniqNative,
      stackTrace: SourceLocStack().with(test.loc))
  }
}

StringTests.test("String.replaceSubrange()/string/range") {
  for test in replaceSubrangeTests {
    var theString = test.original
    let c = test.original
    let rangeToReplace = test.rangeSelection.range(in: c)
    theString.replaceSubrange(rangeToReplace, with: test.newElements)
    expectEqual(
      test.expected,
      theString,
      stackTrace: SourceLocStack().with(test.loc))

    // Test unique-native optimized path
    var uniqNative = String(Array(test.original))
    uniqNative.replaceSubrange(rangeToReplace, with: test.newElements)
    expectEqual(theString, uniqNative,
      stackTrace: SourceLocStack().with(test.loc))
  }
}

StringTests.test("String.replaceSubrange()/characters/closedRange") {
  for test in replaceSubrangeTests {
    guard let closedExpected = test.closedExpected else {
      continue
    }
    var theString = test.original
    let c = test.original
    let rangeToReplace = test.rangeSelection.closedRange(in: c)
    let newCharacters = Array(test.newElements)
    theString.replaceSubrange(rangeToReplace, with: newCharacters)
    expectEqual(
      closedExpected,
      theString,
      stackTrace: SourceLocStack().with(test.loc))

    // Test unique-native optimized path
    var uniqNative = String(Array(test.original))
    uniqNative.replaceSubrange(rangeToReplace, with: newCharacters)
    expectEqual(theString, uniqNative,
      stackTrace: SourceLocStack().with(test.loc))
  }
}

StringTests.test("String.replaceSubrange()/string/closedRange") {
  for test in replaceSubrangeTests {
    guard let closedExpected = test.closedExpected else {
      continue
    }
    var theString = test.original
    let c = test.original
    let rangeToReplace = test.rangeSelection.closedRange(in: c)
    theString.replaceSubrange(rangeToReplace, with: test.newElements)
    expectEqual(
      closedExpected,
      theString,
      stackTrace: SourceLocStack().with(test.loc))

    // Test unique-native optimized path
    var uniqNative = String(Array(test.original))
    uniqNative.replaceSubrange(rangeToReplace, with: test.newElements)
    expectEqual(theString, uniqNative,
      stackTrace: SourceLocStack().with(test.loc))
  }
}

StringTests.test("String.removeSubrange()/range") {
  for test in removeSubrangeTests {
    var theString = test.original
    let c = test.original
    let rangeToRemove = test.rangeSelection.range(in: c)
    theString.removeSubrange(rangeToRemove)
    expectEqual(
      test.expected,
      theString,
      stackTrace: SourceLocStack().with(test.loc))

    // Test unique-native optimized path
    var uniqNative = String(Array(test.original))
    uniqNative.removeSubrange(rangeToRemove)
    expectEqual(theString, uniqNative,
      stackTrace: SourceLocStack().with(test.loc))
  }
}

StringTests.test("String.removeSubrange()/closedRange") {
  for test in removeSubrangeTests {
    switch test.rangeSelection {
      case .emptyRange: continue
      default: break
    }
    var theString = test.original
    let c = test.original
    let rangeToRemove = test.rangeSelection.closedRange(in: c)
    theString.removeSubrange(rangeToRemove)
    expectEqual(
      test.closedExpected,
      theString,
      stackTrace: SourceLocStack().with(test.loc))

    // Test unique-native optimized path
    var uniqNative = String(Array(test.original))
    uniqNative.removeSubrange(rangeToRemove)
    expectEqual(theString, uniqNative,
      stackTrace: SourceLocStack().with(test.loc))
  }
}

//===----------------------------------------------------------------------===//
// COW(🐄) tests
//===----------------------------------------------------------------------===//

public let testSuffix = "z"
StringTests.test("COW.Smoke") {
  var s1 = "COW Smoke Cypseloides" + testSuffix
  let identity1 = s1._rawIdentifier()

  var s2 = s1
  expectEqual(identity1, s2._rawIdentifier())

  s2.append(" cryptus")
  expectTrue(identity1 != s2._rawIdentifier())

  s1.remove(at: s1.startIndex)
  expectEqual(identity1, s1._rawIdentifier())

  _fixLifetime(s1)
  _fixLifetime(s2)
}

struct COWStringTest {
  let test: String
  let name: String
}

var testCases: [COWStringTest] {
  return [ COWStringTest(test: "abcdefghijklmnopqrxtuvwxyz", name: "ASCII"),
           COWStringTest(test: "🐮🐄🤠👢🐴", name: "Unicode")
         ]
}

for test in testCases {
  StringTests.test("COW.\(test.name).IndexesDontAffectUniquenessCheck") {
    let s = test.test + testSuffix
    let identity1 = s._rawIdentifier()

    let startIndex = s.startIndex
    let endIndex = s.endIndex
    expectNotEqual(startIndex, endIndex)
    expectLT(startIndex, endIndex)
    expectLE(startIndex, endIndex)
    expectGT(endIndex, startIndex)
    expectGE(endIndex, startIndex)

    expectEqual(identity1, s._rawIdentifier())

    // Keep indexes alive during the calls above
    _fixLifetime(startIndex)
    _fixLifetime(endIndex)
  }
}

for test in testCases {
  StringTests.test("COW.\(test.name).SubscriptWithIndexDoesNotReallocate") {
    let s = test.test + testSuffix
    let identity1 = s._rawIdentifier()

    let startIndex = s.startIndex
    let empty = startIndex == s.endIndex
    expectNotEqual((s.startIndex < s.endIndex), empty)
    expectLE(s.startIndex, s.endIndex)
    expectEqual((s.startIndex >= s.endIndex), empty)
    expectGT(s.endIndex, s.startIndex)
    expectEqual(identity1, s._rawIdentifier())
  }
}

for test in testCases {
  StringTests.test("COW.\(test.name).RemoveAtDoesNotReallocate") {
    do {
      var s = test.test + testSuffix
      let identity1 = s._rawIdentifier()

      let index1 = s.startIndex
      expectEqual(identity1, s._rawIdentifier())

      let _ = s.remove(at: index1)
      expectEqual(identity1, s._rawIdentifier())
    }

    do {
      let s1 = test.test + testSuffix
      let identity1 = s1._rawIdentifier()

      var s2 = s1
      expectEqual(identity1, s1._rawIdentifier())
      expectEqual(identity1, s2._rawIdentifier())

      let index1 = s1.startIndex
      expectEqual(identity1, s1._rawIdentifier())
      expectEqual(identity1, s2._rawIdentifier())

      let _ = s2.remove(at: index1)

      expectEqual(identity1, s1._rawIdentifier())
      expectTrue(identity1 == s2._rawIdentifier())
    }
  }
}

for test in testCases {
  StringTests.test("COW.\(test.name).RemoveAtDoesNotReallocate") {
    do {
      var s = test.test + testSuffix
      expectGT(s.count, 0)

      s.removeAll()
      let identity1 = s._rawIdentifier()
      expectEqual(0, s.count)
      expectEqual(identity1, s._rawIdentifier())
    }

    do {
      var s = test.test + testSuffix
      let identity1 = s._rawIdentifier()
      expectGT(s.count, 3)

      s.removeAll(keepingCapacity: true)
      expectEqual(identity1, s._rawIdentifier())
      expectEqual(0, s.count)
    }

    do {
      let s1 = test.test + testSuffix
      let identity1 = s1._rawIdentifier()
      expectGT(s1.count, 0)

      var s2 = s1
      s2.removeAll()
      let identity2 = s2._rawIdentifier()
      expectEqual(identity1, s1._rawIdentifier())
      expectTrue(identity2 != identity1)
      expectGT(s1.count, 0)
      expectEqual(0, s2.count)

      // Keep variables alive.
      _fixLifetime(s1)
      _fixLifetime(s2)
    }

    do {
      let s1 = test.test + testSuffix
      let identity1 = s1._rawIdentifier()
      expectGT(s1.count, 0)

      var s2 = s1
      s2.removeAll(keepingCapacity: true)
      let identity2 = s2._rawIdentifier()
      expectEqual(identity1, s1._rawIdentifier())
      expectTrue(identity2 != identity1)
      expectGT(s1.count, 0)
      expectEqual(0, s2.count)

      // Keep variables alive.
      _fixLifetime(s1)
      _fixLifetime(s2)
    }
  }
}

for test in testCases {
  StringTests.test("COW.\(test.name).CountDoesNotReallocate") {
    let s = test.test + testSuffix
    let identity1 = s._rawIdentifier()

    expectGT(s.count, 0)
    expectEqual(identity1, s._rawIdentifier())
  }
}

for test in testCases {
  StringTests.test("COW.\(test.name).GenerateDoesNotReallocate") {
    let s = test.test + testSuffix
    let identity1 = s._rawIdentifier()

    var iter = s.makeIterator()
    var copy = String()
    while let value = iter.next() {
      copy.append(value)
    }
    expectEqual(copy, s)
    expectEqual(identity1, s._rawIdentifier())
  }
}

for test in testCases {
  StringTests.test("COW.\(test.name).EqualityTestDoesNotReallocate") {
    let s1 = test.test + testSuffix
    let identity1 = s1._rawIdentifier()

    var s2 = test.test + testSuffix
    let identity2 = s2._rawIdentifier()

    expectEqual(s1, s2)
    expectEqual(identity1, s1._rawIdentifier())
    expectEqual(identity2, s2._rawIdentifier())

    s2.remove(at: s2.startIndex)
    expectNotEqual(s1, s2)
    expectEqual(identity1, s1._rawIdentifier())
    expectEqual(identity2, s2._rawIdentifier())
  }
}

enum _Ordering: Int, Equatable {
  case less = -1
  case equal = 0
  case greater = 1

  var flipped: _Ordering {
    switch self {
      case .less: return .greater
      case .equal: return .equal
      case .greater: return .less
    }
  }

  init(signedNotation int: Int) {
    self = int < 0 ? .less : int == 0 ? .equal : .greater
  }
}

struct ComparisonTestCase {
  var strings: [String]
  // var test: (String, String) -> Void
  var comparison: _Ordering

  init(_ strings: [String], _ comparison: _Ordering) {
    self.strings = strings
    self.comparison = comparison
  }

  func test() {
    for pair in zip(strings, strings[1...]) {
      switch comparison {
      case .less:
        expectLT(pair.0, pair.1)
        if !pair.0.isEmpty {
          // Test mixed String/Substring
          expectTrue(pair.0.dropLast() < pair.1)
        }
      case .greater:
        expectGT(pair.0, pair.1)
        if !pair.1.isEmpty {
          // Test mixed String/Substring
          expectTrue(pair.0 > pair.1.dropLast())
        }
      case .equal:
        expectEqual(pair.0, pair.1)
        if !pair.0.isEmpty {
          // Test mixed String/Substring
          expectTrue(pair.0.dropLast() == pair.1.dropLast())
          expectFalse(pair.0.dropFirst() == pair.1)
          expectFalse(pair.0 == pair.1.dropFirst())
        }
      }
    }
  }

  func testOpaqueStrings() {
#if _runtime(_ObjC)
    let opaqueStrings = strings.map { NSSlowString(string: $0) as String }
    for pair in zip(opaqueStrings, opaqueStrings[1...]) {
      switch comparison {
      case .less:
        expectLT(pair.0, pair.1)
      case .greater:
        expectGT(pair.0, pair.1)
      case .equal:
        expectEqual(pair.0, pair.1)
      }
    }
    expectEqualSequence(strings, opaqueStrings)
#endif
  }

  func testOpaqueSubstrings() {
#if _runtime(_ObjC)
    for pair in zip(strings, strings[1...]) {
      let string1 = pair.0.dropLast()
      let string2 = pair.1
      let opaqueString = (NSSlowString(string: pair.0) as String).dropLast()

      guard string1.count > 0 else { return }

      expectEqual(string1, opaqueString)
      expectEqual(string1 < string2, opaqueString < string2)
      expectEqual(string1 > string2, opaqueString > string2)
      expectEqual(string1 == string2, opaqueString == string2)
    }
#endif
  }
}

let comparisonTestCases = [
  ComparisonTestCase(["a", "a"], .equal),
  ComparisonTestCase(["abcdefg", "abcdefg"], .equal),
  ComparisonTestCase(["", "Z", "a", "b", "c", "\u{00c5}", "á"], .less),

  ComparisonTestCase(["ábcdefg", "ábcdefgh", "ábcdefghi"], .less),
  ComparisonTestCase(["abcdefg", "abcdefgh", "abcdefghi"], .less),

  ComparisonTestCase(["á", "\u{0061}\u{0301}"], .equal),
  ComparisonTestCase(["à", "\u{0061}\u{0301}", "â", "\u{e3}", "a\u{0308}"], .less),

  // Exploding scalars AND exploding segments
  ComparisonTestCase(["\u{fa2}", "\u{fa1}\u{fb7}"], .equal),
  ComparisonTestCase([
    "\u{fa2}\u{fa2}\u{fa2}\u{fa2}",
    "\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}"
    ], .equal),
  ComparisonTestCase([
    "\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}",
    "\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}"
    ], .equal),
  ComparisonTestCase([
    "a\u{fa2}\u{fa2}a\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}\u{fa2}",
    "a\u{fa1}\u{fb7}\u{fa1}\u{fb7}a\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}\u{fa1}\u{fb7}"
    ], .equal),

  ComparisonTestCase(["a\u{301}\u{0301}", "\u{e1}"], .greater),
  ComparisonTestCase(["😀", "😀"], .equal),
  ComparisonTestCase(["\u{2f9df}", "\u{8f38}"], .equal),
  ComparisonTestCase([
    "a",
    "\u{2f9df}", // D87E DDDF as written, but normalizes to 8f38
    "\u{2f9df}\u{2f9df}", // D87E DDDF as written, but normalizes to 8f38
    "👨🏻", // D83D DC68 D83C DFFB
    "👨🏻⚕", // D83D DC68 D83C DFFB 200D 2695 FE0F
    "👩⚕", // D83D DC69 200D 2695 FE0F
    "👩🏾", // D83D DC69 D83C DFFE
    "👩🏾⚕", // D83D DC69 D83C DFFE 200D 2695 FE0F
    "😀", // D83D DE00
    "😅", // D83D DE05
    "🧀" // D83E DDC0 -- aka a really big scalar
  ], .less),

  ComparisonTestCase(["f̛̗̘̙̜̹̺̻̼͇͈͉͍͎͓͔͕͖͙͚̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗͛ͣͤͥͦ̚͘͜͟͢͝͞͠͡ͅ", "ơ̗̘̙̜̹̺̻̼͇͈͉͍͎͓͔͕͖͙͚̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗͛ͥͦͧͨͩͪͫͬͭͮ̚͘ͅ"], .less),
  ComparisonTestCase(["\u{f90b}", "\u{5587}"], .equal),

  ComparisonTestCase(["a\u{1D160}a", "a\u{1D158}\u{1D1C7}"], .less),

  ComparisonTestCase(["a\u{305}\u{315}", "a\u{315}\u{305}"], .equal),
  ComparisonTestCase(["a\u{315}bz", "a\u{315}\u{305}az"], .greater),

  ComparisonTestCase(["\u{212b}", "\u{00c5}"], .equal),
  ComparisonTestCase([
    "A",
    "a",
    "aa",
    "ae",
    "ae🧀",
    "az",
    "aze\u{300}",
    "ae\u{301}",
    "ae\u{301}ae\u{301}",
    "ae\u{301}ae\u{301}ae\u{301}",
    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
    "ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}",
    "ae\u{301}\u{302}",
    "ae\u{302}",
    "ae\u{302}{303}",
    "ae\u{302}🧀",
    "ae\u{303}",
    "x\u{0939}x",
    "x\u{0939}\u{093a}x",
    "x\u{0939}\u{093a}\u{093b}x",
    "\u{f90b}\u{f90c}\u{f90d}", // Normalizes to BMP scalars
    "\u{FFEE}", // half width CJK dot
    "🧀", // D83E DDC0 -- aka a really big scalar
  ], .less),

  ComparisonTestCase(["ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎͓͔͕͖͙͚̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ̚͘͜͟͢͝͞͠͡ͅ", "ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎͓͔͕͖͙́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗ͬͭͮ͘ͅ"], .greater),
  ComparisonTestCase(["ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎͓͔͕͖͙͚̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ̚͘͜͟͢͝͞͠͡ͅ", "aì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎͓͔͕͖͙́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗ͬͭͮ͘ͅ"], .greater),
  ComparisonTestCase(["ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎͓͔͕͖͙́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗ͬͭͮ͘ͅ", "ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎͓͔͕͖͙́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌͐͑͒͗ͬͭͮ͘ͅ"], .equal)
]

for test in comparisonTestCases {
  StringTests.test("Comparison.\(test.strings)") {
    test.test()
  }

  StringTests.test("Comparison.OpaqueString.\(test.strings)")
    .skip(.linuxAny(reason: "NSSlowString requires ObjC interop"))
    .code {
    test.testOpaqueStrings()
  }

  StringTests.test("Comparison.OpaqueSubstring.\(test.strings)")
  .skip(.linuxAny(reason: "NSSlowString requires ObjC interop"))
  .code {
    test.testOpaqueSubstrings()
  }
}

StringTests.test("Comparison.Substrings") {
  let str = "abcdefg"
  let expectedStr = "bcdef"
  let substring = str.dropFirst().dropLast()

  expectEqual(expectedStr, substring)
}

StringTests.test("Comparison.Substrings/Opaque")
.skip(.linuxAny(reason: "NSSlowString requires ObjC interop"))
.code {
#if _runtime(_ObjC)
  let str = NSSlowString(string: "abcdefg") as String
  let expectedStr = NSSlowString(string: "bcdef") as String
  let substring = str.dropFirst().dropLast()

  expectEqual(expectedStr, substring)
#endif
}

StringTests.test("NormalizationBufferCrashRegressionTest") {
  let str = "\u{0336}\u{0344}\u{0357}\u{0343}\u{0314}\u{0351}\u{0340}\u{0300}\u{0340}\u{0360}\u{0314}\u{0357}\u{0315}\u{0301}\u{0344}a"
  let set = Set([str])

  expectTrue(set.contains(str))
}

StringTests.test("NormalizationCheck") {
  let str = "\u{0336}\u{0344}\u{0357}\u{0343}\u{0314}\u{0351}\u{0340}\u{0300}\u{0340}\u{0360}\u{0314}\u{0357}\u{0315}\u{0301}\u{0344}a"
  let nfcCodeUnits = str._nfcCodeUnits
  let expectedCodeUnits: [UInt8] = [0xCC, 0xB6, 0xCC, 0x88, 0xCC, 0x81, 0xCD, 0x97, 0xCC, 0x93, 0xCC, 0x94, 0xCD, 0x91, 0xCC, 0x80, 0xCC, 0x80, 0xCC, 0x80, 0xCC, 0x94, 0xCD, 0x97, 0xCC, 0x81, 0xCC, 0x88, 0xCC, 0x81, 0xCC, 0x95, 0xCD, 0xA0, 0x61]

  expectEqual(expectedCodeUnits, nfcCodeUnits)
}

StringTests.test("NormalizationCheck/Opaque")
.skip(.linuxAny(reason: "NSSlowString requires ObjC interop"))
.code {
#if _runtime(_ObjC)
  let str = "\u{0336}\u{0344}\u{0357}\u{0343}\u{0314}\u{0351}\u{0340}\u{0300}\u{0340}\u{0360}\u{0314}\u{0357}\u{0315}\u{0301}\u{0344}a"
  let opaqueString = NSSlowString(string: str) as String
  let nfcCodeUnits = opaqueString._nfcCodeUnits
  let expectedCodeUnits: [UInt8] = [0xCC, 0xB6, 0xCC, 0x88, 0xCC, 0x81, 0xCD, 0x97, 0xCC, 0x93, 0xCC, 0x94, 0xCD, 0x91, 0xCC, 0x80, 0xCC, 0x80, 0xCC, 0x80, 0xCC, 0x94, 0xCD, 0x97, 0xCC, 0x81, 0xCC, 0x88, 0xCC, 0x81, 0xCC, 0x95, 0xCD, 0xA0, 0x61]

  expectEqual(expectedCodeUnits, nfcCodeUnits)
#endif
}

runAllTests()

{'repo_name': 'apple/swift', 'stars': '52460', 'repo_language': 'C++', 'file_name': 'comment-xml-schema.rng', 'mime_type': 'text/xml', 'hash': -637002844277647405, 'source_dataset': 'data'}


/**
 * Copyright (c) 2010-2020 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.core.io.transport.serial.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.io.transport.serial.SerialPortEvent;

/**
 * Specific serial port event implementation.
 *
 * @author Markus Rathgeb - Initial contribution
 */
@NonNullByDefault
public class SerialPortEventImpl implements SerialPortEvent {

    private final gnu.io.SerialPortEvent event;

    /**
     * Constructor.
     *
     * @param event the underlying event implementation
     */
    public SerialPortEventImpl(final gnu.io.SerialPortEvent event) {
        this.event = event;
    }

    @Override
    public int getEventType() {
        return event.getEventType();
    }

    @Override
    public boolean getNewValue() {
        return event.getNewValue();
    }
}

{'repo_name': 'openhab/openhab-core', 'stars': '325', 'repo_language': 'Java', 'file_name': 'header.txt', 'mime_type': 'text/plain', 'hash': -4587075628756233088, 'source_dataset': 'data'}


/*
 * Copyright (c) 2011-2019, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package boofcv.alg.transform.ii;

import boofcv.alg.filter.convolve.ConvolveImage;
import boofcv.alg.filter.convolve.ConvolveImageNoBorder;
import boofcv.alg.filter.kernel.KernelMath;
import boofcv.alg.misc.ImageMiscOps;
import boofcv.core.image.border.FactoryImageBorderAlgs;
import boofcv.struct.border.ImageBorder_F32;
import boofcv.struct.convolve.Kernel2D_F32;
import boofcv.struct.image.GrayF32;
import boofcv.testing.BoofTesting;
import org.junit.jupiter.api.Test;

import java.util.Random;

/**
 * @author Peter Abeles
 */
public class TestDerivativeIntegralImage {

	Random rand = new Random(234);
	int width = 30;
	int height = 40;

	@Test
		public void kernelDerivX() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int r = 1; r < 5; r++ ) {
			IntegralKernel kernelI = DerivativeIntegralImage.kernelDerivX(r,null);
			Kernel2D_F32 kernel = createDerivX(r);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void kernelDerivY() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int r = 1; r < 5; r++ ) {
			IntegralKernel kernelI = DerivativeIntegralImage.kernelDerivY(r,null);
			Kernel2D_F32 kernel = createDerivX(r);
			kernel = KernelMath.transpose(kernel);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void kernelHaarX() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int r = 1; r < 5; r++ ) {
			IntegralKernel kernelI = DerivativeIntegralImage.kernelHaarX(r,null);
			Kernel2D_F32 kernel = createHaarX(r);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void kernelHaarY() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int i = 1; i < 5; i++ ) {
			int size = i*2;
			IntegralKernel kernelI = DerivativeIntegralImage.kernelHaarY(size,null);
			Kernel2D_F32 kernel = createHaarX(size);
			kernel = KernelMath.transpose(kernel);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void kernelDerivXX() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int i = 1; i <= 5; i += 2 ) {
			int size = i*3;
			IntegralKernel kernelI = DerivativeIntegralImage.kernelDerivXX(size,null);
			Kernel2D_F32 kernel = createDerivXX(size);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void derivXX() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		for( int i = 1; i <= 5; i += 2 ) {
			int size = i*3;
			Kernel2D_F32 kernel = createDerivXX(size);
			ConvolveImageNoBorder.convolve(kernel,orig,expected);
			DerivativeIntegralImage.derivXX(integral,found,size);

			int r = size/2;
			GrayF32 a = expected.subimage(r+1,r+1,expected.width-r,expected.height-r, null);
			GrayF32 b = found.subimage(r+1,r+1,found.width-r,found.height-r, null);

			BoofTesting.assertEquals(a,b,1e-2);
		}
	}

	@Test
	public void kernelDerivYY() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int i = 1; i <= 5; i += 2 ) {
			int size = i*3;
			IntegralKernel kernelI = DerivativeIntegralImage.kernelDerivYY(size,null);
			Kernel2D_F32 kernel = createDerivXX(size);
			kernel = KernelMath.transpose(kernel);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void derivYY() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		for( int i = 1; i <= 5; i += 2 ) {
			int size = i*3;
			Kernel2D_F32 kernel = createDerivXX(size);
			kernel = KernelMath.transpose(kernel);

			ConvolveImageNoBorder.convolve(kernel,orig,expected);
			DerivativeIntegralImage.derivYY(integral,found,size);

			int r = size/2;
			GrayF32 a = expected.subimage(r+1,r+1,expected.width-r,expected.height-r, null);
			GrayF32 b = found.subimage(r+1,r+1,found.width-r,found.height-r, null);

			BoofTesting.assertEquals(a,b,1e-2);
		}
	}

	@Test
	public void kernelDerivXY() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		ImageBorder_F32 border = (ImageBorder_F32)FactoryImageBorderAlgs.value(orig, 0);

		for( int i = 1; i <= 5; i += 2 ) {
			int size = i*3;
			IntegralKernel kernelI = DerivativeIntegralImage.kernelDerivXY(size,null);
			Kernel2D_F32 kernel = createDerivXY(size);

			ConvolveImage.convolve(kernel,orig,expected,border);
			IntegralImageOps.convolve(integral,kernelI,found);

			BoofTesting.assertEquals(expected,found,1e-2);
		}
	}

	@Test
	public void derivXY() {
		GrayF32 orig = new GrayF32(width,height);
		GrayF32 integral = new GrayF32(width,height);

		ImageMiscOps.fillUniform(orig,rand,0,20);

		GrayF32 expected = new GrayF32(width,height);
		GrayF32 found = new GrayF32(width,height);

		IntegralImageOps.transform(orig,integral);

		for( int i = 1; i <= 5; i += 2 ) {
			int size = i*3;
			Kernel2D_F32 kernel = createDerivXY(size);

			ConvolveImageNoBorder.convolve(kernel,orig,expected);
			DerivativeIntegralImage.derivXY(integral,found,size);

			int r = size/2;
			GrayF32 a = expected.subimage(r+1,r+1,expected.width-r,expected.height-r, null);
			GrayF32 b = found.subimage(r+1,r+1,found.width-r,found.height-r, null);

			BoofTesting.assertEquals(a,b,1e-2);
		}
	}

	private Kernel2D_F32 createDerivX( int r ) {
		int size = r*2+1;

		Kernel2D_F32 ret = new Kernel2D_F32(size);

		for( int y = 0; y < size; y++ ) {
			for( int x = 0; x < r; x++ ) {
				ret.set(x,y,-1);
				ret.set(x+r+1,y,1);
			}
		}

		return ret;
	}

	private Kernel2D_F32 createHaarX( int r ) {
		int size = r*2;

		// TODO kernels only support odd sizes right now...  change if that changes (remove +1)
		Kernel2D_F32 ret = new Kernel2D_F32(size+1);

		for( int y = 1; y <= size; y++ ) {
			for( int x = 1; x <= r; x++ ) {
				ret.set(x,y,-1);
				ret.set(x+r,y,1);
			}
		}

		return ret;
	}

	private Kernel2D_F32 createDerivXX( int size ) {
		int blockW = size/3;
		int blockH = size-blockW-1;
		int borderY = (size-blockH)/2;

		Kernel2D_F32 ret = new Kernel2D_F32(size);

		for( int y = borderY; y < size-borderY; y++ ) {
			for( int x = 0; x < blockW; x++ ) {
				ret.set(x,y,1);
				ret.set(x+blockW*2,y,1);
			}
			for( int x = blockW; x < 2*blockW; x++ ) {
				ret.set(x,y,-2);
			}
		}
		return ret;
	}

	private Kernel2D_F32 createDerivXY( int size ) {
		int block = size/3;
		int border = (size-2*block-1)/2;

		int w = block*3;

		Kernel2D_F32 ret = new Kernel2D_F32(w);

		for( int y = border; y < border+block; y++ ) {
			for( int x = border; x < block+border; x++ ) {
				ret.set(x,y,1);
				ret.set(x+block+1,y,-1);
			}
		}
		for( int y = border+block+1; y < size-border; y++ ) {
			for( int x = border; x < block+border; x++ ) {
				ret.set(x,y,-1);
				ret.set(x+block+1,y,1);
			}
		}
		return ret;
	}
}

{'repo_name': 'lessthanoptimal/BoofCV', 'stars': '659', 'repo_language': 'Java', 'file_name': 'ExampleFxShowImage.java', 'mime_type': 'text/x-c', 'hash': 3333167241731286879, 'source_dataset': 'data'}


//
//  FirstViewController.h
//  LNPopupControllerExample
//
//  Created by Leo Natan on 7/16/15.
//  Copyright © 2015 Leo Natan. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface FirstViewController : UIViewController

@end

{'repo_name': 'LeoNatan/LNPopupController', 'stars': '2576', 'repo_language': 'Objective-C', 'file_name': 'Main.storyboard', 'mime_type': 'text/xml', 'hash': -4043620001162366765, 'source_dataset': 'data'}


<!doctype html>

    <title>Code coverage report for tcb-admin-node/src/db/serializer/update.js</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="../../../../prettify.css" />
    <link rel="stylesheet" href="../../../../base.css" />
    <meta name="viewport" content="width=device-width, initial-scale=1">

      All files / tcb-admin-node/src/db/serializer update.js

        78.72%
        Statements
        37/47

        68.97%
        Branches
        20/29

        100%
        Functions
        7/7

        78.72%
        Lines
        37/47

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
14x
14x
14x
14x
14x
14x

5x
5x

5x

5x
5x

7x

7x

5x

2x

5x
5x

5x

2x
2x

1x

1x

1x

5x
5x
7x

7x
7x
4x
4x
4x

3x
3x
3x
3x

5x

14x

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const update_1 = require("../commands/update");
const symbol_1 = require("../helper/symbol");
const type_1 = require("../utils/type");
const operator_map_1 = require("../operator-map");
const common_1 = require("./common");
class UpdateSerializer {
    constructor() {
    }
    static encode(query) {
        const stringifier = new UpdateSerializer();
        return stringifier.encodeUpdate(query);
    }
    encodeUpdate(query) {
        Iif (update_1.isUpdateCommand(query)) {
            return this.encodeUpdateCommand(query);
        }
        else Eif (type_1.getType(query) === 'object') {
            return this.encodeUpdateObject(query);
        }
        else {
            return query;
        }
    }
    encodeUpdateCommand(query) {
        Iif (query.fieldName === symbol_1.SYMBOL_UNSET_FIELD_NAME) {
            throw new Error(`Cannot encode a comparison command with unset field name`);
        }
        switch (query.operator) {
            case update_1.UPDATE_COMMANDS_LITERAL.SET:
            case update_1.UPDATE_COMMANDS_LITERAL.REMOVE:
            case update_1.UPDATE_COMMANDS_LITERAL.INC:
            case update_1.UPDATE_COMMANDS_LITERAL.MUL: {
                return this.encodeFieldUpdateCommand(query);
            }
            case update_1.UPDATE_COMMANDS_LITERAL.PUSH:
            case update_1.UPDATE_COMMANDS_LITERAL.POP:
            case update_1.UPDATE_COMMANDS_LITERAL.SHIFT:
            case update_1.UPDATE_COMMANDS_LITERAL.UNSHIFT: {
                return this.encodeArrayUpdateCommand(query);
            }
            default: {
                return this.encodeFieldUpdateCommand(query);
            }
        }
    }
    encodeFieldUpdateCommand(query) {
        const $op = operator_map_1.operatorToString(query.operator);
        switch (query.operator) {
            case update_1.UPDATE_COMMANDS_LITERAL.REMOVE: {
                return {
                    [$op]: {
                        [query.fieldName]: '',
                    },
                };
            }
            case update_1.UPDATE_COMMANDS_LITERAL.SET:
            case update_1.UPDATE_COMMANDS_LITERAL.INC:
            case update_1.UPDATE_COMMANDS_LITERAL.MUL:
            default: {
                return {
                    [$op]: {
                        [query.fieldName]: query.operands[0],
                    },
                };
            }
        }
    }
    encodeArrayUpdateCommand(query) {
        const $op = operator_map_1.operatorToString(query.operator);
        switch (query.operator) {
            case update_1.UPDATE_COMMANDS_LITERAL.PUSH: {
                const modifiers = {
                    $each: query.operands.map(common_1.encodeInternalDataType),
                };
                return {
                    [$op]: {
                        [query.fieldName]: modifiers,
                    },
                };
            }
            case update_1.UPDATE_COMMANDS_LITERAL.UNSHIFT: {
                const modifiers = {
                    $each: query.operands.map(common_1.encodeInternalDataType),
                    $position: 0,
                };
                return {
                    [$op]: {
                        [query.fieldName]: modifiers,
                    },
                };
            }
            case update_1.UPDATE_COMMANDS_LITERAL.POP: {
                return {
                    [$op]: {
                        [query.fieldName]: 1,
                    },
                };
            }
            case update_1.UPDATE_COMMANDS_LITERAL.SHIFT: {
                return {
                    [$op]: {
                        [query.fieldName]: -1,
                    },
                };
            }
            default: {
                return {
                    [$op]: {
                        [query.fieldName]: common_1.encodeInternalDataType(query.operands),
                    },
                };
            }
        }
    }
    encodeUpdateObject(query) {
        const flattened = common_1.flattenQueryObject(query);
        for (const key in flattened) {
            Iif (/^\$/.test(key))
                continue;
            let val = flattened[key];
            if (update_1.isUpdateCommand(val)) {
                flattened[key] = val._setFieldName(key);
                const condition = this.encodeUpdateCommand(flattened[key]);
                common_1.mergeConditionAfterEncode(flattened, condition, key);
            }
            else {
                flattened[key] = val = common_1.encodeInternalDataType(val);
                const $setCommand = new update_1.UpdateCommand(update_1.UPDATE_COMMANDS_LITERAL.SET, [val], key);
                const condition = this.encodeUpdateCommand($setCommand);
                common_1.mergeConditionAfterEncode(flattened, condition, key);
            }
        }
        return flattened;
    }
}
exports.UpdateSerializer = UpdateSerializer;

  Code coverage
  generated by istanbul at Tue Dec 04 2018 13:58:35 GMT+0800 (GMT+08:00)

{'repo_name': 'Voyzz/Fruit-store-mp', 'stars': '123', 'repo_language': 'JavaScript', 'file_name': 'index.js', 'mime_type': 'text/plain', 'hash': 3426800648695188465, 'source_dataset': 'data'}


//
// Created by Arseny Tolmachev on 2017/02/27.
//

#include "lattice_types.h"
#include "util/stl_util.h"

#ifdef __SSE2__
#include <emmintrin.h>
#endif

namespace jumanpp {
namespace core {
namespace analysis {

Lattice::Lattice(util::memory::PoolAlloc *alloc, const LatticeConfig &lc)
    : lconf{lc}, alloc{alloc} {}

Status Lattice::makeBoundary(const LatticeBoundaryConfig &lbc,
                             LatticeBoundary **ptr) {
  auto bnd = alloc->make<LatticeBoundary>(alloc, lconf, lbc);
  JPP_RETURN_IF_ERROR(bnd->initialize());
  this->boundaries.push_back(bnd);
  *ptr = bnd;
  return Status::Ok();
}

void Lattice::reset() { boundaries.clear(); }

void Lattice::hintSize(u32 size) { boundaries.reserve(size); }

LatticeBoundary::LatticeBoundary(util::memory::PoolAlloc *alloc,
                                 const LatticeConfig &lc,
                                 const LatticeBoundaryConfig &lbc)
    : cfg_{lbc},
      left_{alloc, lc, cfg_},
      right_{alloc, lc, cfg_},
      scores_{alloc, lc, cfg_},
      currentEnding_{0} {}

Status LatticeBoundary::initialize() { return Status::Ok(); }

void LatticeBoundary::addEnd(LatticeNodePtr nodePtr) {
  left_.endingNodes_.at(currentEnding_) = nodePtr;
  ++currentEnding_;
}

LatticeBoundaryScores::LatticeBoundaryScores(util::memory::PoolAlloc *alloc,
                                             const LatticeConfig &lc,
                                             const LatticeBoundaryConfig &lbc)
    : scoresPerItem_{lc.beamSize * lbc.endNodes * lc.scoreCnt},
      numLeft_{lbc.endNodes},
      numBeam_{lc.beamSize},
      numScorers_{lc.scoreCnt} {
  u32 num = lbc.beginNodes;
  // do allocation like this because there can be many elements
  // a single allocation of leftSize * rightSize * beamSize * numScorers can be
  // very large
  auto buffers = alloc->allocateBuf<Score *>(num);
  for (int i = 0; i < num; ++i) {
    buffers[i] = alloc->allocateArray<Score>(scoresPerItem_, 16);
  }
  scores_ = buffers;
}

inline void nonTemporalStore4(void *dest, const void *src) {
#ifdef __SSE2__
  _mm_stream_si32(reinterpret_cast<int *>(dest),
                  *reinterpret_cast<const int *>(src));
#else
  std::memcpy(dest, src, 4);
#endif
}

void LatticeBoundaryScores::importBeamScore(i32 left, i32 scorer, i32 beam,
                                            util::ArraySlice<Score> scores) {
  auto num = scores.size();
  for (int el = 0; el < num; ++el) {
    auto node = nodeScores(el);
    auto svec = node.beamLeft(beam, left);
    static_assert(sizeof(Score) == 4, "");
    // nonTemporalStore4(&svec.at(scorer), &scores.at(i));
    svec.at(scorer) = scores.at(el);
  }
}

LatticeRightBoundary::LatticeRightBoundary(util::memory::PoolAlloc *alloc,
                                           const LatticeConfig &lc,
                                           const LatticeBoundaryConfig &lbc) {
  auto rawNodes = alloc->allocateRawArray<NodeInfo>(lbc.beginNodes, 64);
  nodeInfo_ = util::MutableArraySlice<NodeInfo>{rawNodes, lbc.beginNodes};
  featurePatterns =
      alloc->allocate2d<u64>(lbc.beginNodes, lc.numFeaturePatterns, 64);
  beam =
      alloc->allocate2d<ConnectionBeamElement>(lbc.beginNodes, lc.beamSize, 64);
  entryDataStorage = alloc->allocate2d<i32>(lbc.beginNodes, lc.entrySize, 64);
}

LatticeLeftBoundary::LatticeLeftBoundary(util::memory::PoolAlloc *alloc,
                                         const LatticeConfig &lc,
                                         const LatticeBoundaryConfig &lbc) {
  endingNodes_ = alloc->allocateBuf<LatticeNodePtr>(lbc.endNodes);
  if (lc.globalBeamSize > 0) {
    globalBeam_ =
        alloc->allocateBuf<const ConnectionBeamElement *>(lc.globalBeamSize);
  }
}

void NodeScores::fill(Score v) { util::fill(beamScores_, v); }
}  // namespace analysis
}  // namespace core
}  // namespace jumanpp

{'repo_name': 'ku-nlp/jumanpp', 'stars': '221', 'repo_language': 'C++', 'file_name': 'GitVersion.cmake', 'mime_type': 'text/plain', 'hash': -5749833951212625601, 'source_dataset': 'data'}


<?xml version='1.0' encoding='UTF-8'?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.infinispan</groupId>
      <artifactId>infinispan-parent</artifactId>
      <version>12.0.0-SNAPSHOT</version>
      <relativePath>../pom.xml</relativePath>
   </parent>

   <artifactId>infinispan-objectfilter</artifactId>
   <name>Infinispan Object Querying and Filtering API</name>
   <description>Infinispan Object Querying and Filtering based on Ickle, a JP-QL subset</description>

   <dependencies>
      <dependency>
         <groupId>org.jboss.logging</groupId>
         <artifactId>jboss-logging</artifactId>
         <scope>provided</scope>
      </dependency>

      <dependency>
         <groupId>org.infinispan</groupId>
         <artifactId>infinispan-query-dsl</artifactId>
      </dependency>

      <dependency>
         <groupId>org.infinispan.protostream</groupId>
         <artifactId>protostream</artifactId>
         <optional>true</optional>
      </dependency>

      <dependency>
         <groupId>org.infinispan</groupId>
         <artifactId>infinispan-commons-test</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>org.antlr</groupId>
         <artifactId>antlr-runtime</artifactId>
         <!--  This gets shaded, so we mark it optional in order not to propagate this dependency any further -->
         <optional>true</optional>
      </dependency>

      <dependency>
         <groupId>org.assertj</groupId>
         <artifactId>assertj-core</artifactId>
         <scope>test</scope>
      </dependency>

      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
               <parallel>none</parallel>
               <groups combine.self="override">${defaultJUnitGroups}</groups>
               <excludedGroups combine.self="override">${defaultExcludedJUnitGroups}</excludedGroups>
               <disableXmlReport>false</disableXmlReport>
               <properties>
                  <!-- Deactivate the default listeners which may cause OOME. Jenkins uses the surefire generated XML file. -->
                  <usedefaultlisteners>false</usedefaultlisteners>
                  <listener>${junitListener}</listener>
               </properties>
            </configuration>
            <dependencies>
               <dependency>
                  <groupId>org.apache.maven.surefire</groupId>
                  <artifactId>surefire-junit47</artifactId>
                  <version>${version.maven.surefire}</version>
               </dependency>
            </dependencies>
         </plugin>

         <plugin>
            <groupId>org.antlr</groupId>
            <artifactId>antlr3-maven-plugin</artifactId>
            <executions>
               <execution>
                  <id>antlr3</id>
                  <phase>generate-sources</phase>
                  <goals>
                     <goal>antlr</goal>
                  </goals>
               </execution>
            </executions>
            <configuration>
               <sourceDirectory>${basedir}/src/main/antlr3</sourceDirectory>
               <outputDirectory>${project.build.directory}/generated-sources/antlr3</outputDirectory>
            </configuration>
         </plugin>

         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
               <execution>
                  <id>none-default</id>
                  <phase>package</phase>
                  <goals>
                     <goal>shade</goal>
                  </goals>
                  <configuration>
                     <finalName>${project.artifactId}-${project.version}</finalName>
                     <minimizeJar>true</minimizeJar>
                     <artifactSet>
                        <excludes>
                           <exclude>net.jcip:jcip-annotations:jar:</exclude>
                           <exclude>log4j:log4j:jar:</exclude>
                           <exclude>org.jboss.logging:jboss-logging:jar:</exclude>
                           <exclude>org.infinispan:infinispan-query-dsl:jar:</exclude>
                           <exclude>org.infinispan.protostream:protostream:jar:</exclude>
                           <exclude>org.infinispan:infinispan-component-annotations:</exclude>
                        </excludes>
                     </artifactSet>
                     <relocations>
                        <relocation>
                           <pattern>org.antlr.runtime</pattern>
                           <shadedPattern>org.infinispan.objectfilter.impl.antlr.runtime</shadedPattern>
                        </relocation>
                     </relocations>
                  </configuration>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>

   <profiles>
      <profile>
         <id>smoke</id>
         <build>
            <plugins>
               <plugin>
                  <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-surefire-plugin</artifactId>
                  <executions>
                     <execution>
                        <id>default-test</id>
                        <phase>none</phase>
                     </execution>
                  </executions>
               </plugin>
            </plugins>
         </build>
      </profile>
   </profiles>
</project>

{'repo_name': 'infinispan/infinispan', 'stars': '824', 'repo_language': 'Java', 'file_name': 'XMLTranscoderTest.java', 'mime_type': 'text/x-java', 'hash': -347824096349946496, 'source_dataset': 'data'}


/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2009-2014 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2014 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.protocols.wmi.test.stubs;

import org.opennms.protocols.wmi.wbem.OnmsWbemPropertySet;
import org.opennms.protocols.wmi.wbem.OnmsWbemProperty;
import org.opennms.protocols.wmi.WmiException;

public class OnmsWbemPropSetBiosStub implements OnmsWbemPropertySet {
    public OnmsWbemProperty releaseDate;
    public OnmsWbemPropSetBiosStub(OnmsWbemProperty prop) {
        releaseDate = prop;
    }
    @Override
    public Integer count() throws WmiException {
        return null;
    }

    @Override
    public OnmsWbemProperty get(Integer idx) throws WmiException {
        return null;
    }

    @Override
    public OnmsWbemProperty getByName(String name) throws WmiException {
        if(name.equals("ReleaseDate")) return releaseDate;
        throw new WmiException("Failed to perform WMI operation: Unknown name. [0x80020006]");
    }
}

{'repo_name': 'OpenNMS/opennms', 'stars': '506', 'repo_language': 'Java', 'file_name': 'ReportParameterBuilder.java', 'mime_type': 'text/x-java', 'hash': -2400247818604046000, 'source_dataset': 'data'}


/*
Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/

body
{
    /* Font */
    font-family: Arial, Verdana, sans-serif;
    font-size: 12px;

    /* Text color */
    color: #222;

    /* Remove the background color to make it transparent */
    background-color: #fff;
}

ol,ul,dl
{
    /* IE7: reset rtl list margin. (#7334) */
    *margin-right:0px;
    /* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/
    padding:0 40px;
}

{'repo_name': 'pH7Software/pH7-Social-Dating-CMS', 'stars': '602', 'repo_language': 'PHP', 'file_name': 'mailcheck.license.txt', 'mime_type': 'text/plain', 'hash': -3741853623847075323, 'source_dataset': 'data'}