// RUN: %target-run-simple-swift
// REQUIRES: long_test
// REQUIRES: executable_test
// UNSUPPORTED: CPU=armv7k

import SwiftPrivate
import StdlibUnittest

var UTF8Decoder = TestSuite("UTF8Decoder")

UTF8Decoder.test("Internal/_decodeOne") {

  // Ensure we accept all valid scalars
  func ensureValid(_ scalar: UnicodeScalar) {
    var data: UInt32 = 0
    var i: UInt32 = 0
    Swift.UTF8.encode(scalar) { cp in
      data |= UInt32(cp) << (i*8)
      i += 1
    }
    let (codePoint, _) = UTF8._decodeOne(data)
    expectEqual(scalar.value, codePoint, "data=\(asHex(data))")
  }

  for i in 0..<0xd800 { ensureValid(UnicodeScalar(i)!) }
  for i in 0xe000...0x10ffff { ensureValid(UnicodeScalar(i)!) }

  // Check number of valid/invalid sequences of different lengths
  var validLengthCounts = [ 0, 0, 0, 0, 0 ]
  var maximalSubpartCounts = [ 0, 0, 0, 0, 0 ]
  func countValidSequences(
    head: CountableClosedRange<UInt32>, tail: CountableClosedRange<UInt32>
  ) {
    for cu0 in head {
      for rest in tail {
        let data = rest << 8 | cu0
        let (codePoint, length) = UTF8._decodeOne(data)
        if codePoint != nil {
          validLengthCounts[Int(length)] += 1
        } else {
          maximalSubpartCounts[Int(length)] += 1
        }
      }
    }
  }

  countValidSequences(head: 0x00...0x7f, tail: 0...0)
  countValidSequences(head: 0xc0...0xdf, tail: 0...0xff)
  countValidSequences(head: 0xe0...0xef, tail: 0...0xffff)
  countValidSequences(head: 0xf0...0xff, tail: 0...0xffffff)

  // Valid sequences
  expectEqualSequence(validLengthCounts,
    [ 0, 0x80, 0x780, 0xf000, 0x100000 ],
    "validLengthCounts=\(validLengthCounts.map { asHex($0) })")
  // Maximal subparts of ill-formed sequences
  expectEqualSequence(maximalSubpartCounts,
    [ 0, 0xf0c5880, 0xc2d000, 0x300000, 0 ],
    "maximalSubpartCounts=\(maximalSubpartCounts.map { asHex($0) })")
}

runAllTests()

