//===--- NSNumberBridging.swift - Test bridging through NSNumber ----------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// RUN: rm -rf %t  &&  mkdir -p %t
// RUN: %gyb %s -o %t/NSValueBridging.swift
// RUN: %target-build-swift -g -module-name a %t/NSValueBridging.swift -o %t.out
// RUN: %target-run %t.out
// REQUIRES: executable_test
// REQUIRES: objc_interop


import StdlibUnittest
import Foundation
import CoreGraphics

var nsNumberBridging = TestSuite("NSNumberBridging")

func expectBridgeToNSNumber<T>(_ value: T,
                               nsNumberInitializer: (T) -> NSNumber,
                               nsNumberGetter: (NSNumber) -> T,
                               equal: (T, T) -> Bool) {
  let object = value as AnyObject
  let nsNumber = object as! NSNumber

  expectEqual(nsNumberInitializer(value), nsNumber)
  expectTrue(equal(value, nsNumberGetter(nsNumber)))
  expectTrue(equal(value, nsNumberGetter(nsNumberInitializer(value))))

  expectTrue(equal(value, object as! T))
}

%{
bridgedFixedPointTypes = [
  #Type     accessor   signed
  ("Int",    "int",    True),
  ("Int64",  "int64",  True),
  ("Int32",  "int32",  True),
  ("Int16",  "int16",  True),
  ("Int8",   "int8",   True),
  ("UInt",   "uint",   False),
  ("UInt64", "uint64", False),
  ("UInt32", "uint32", False),
  ("UInt16", "uint16", False),
  ("UInt8",  "uint8",  False),
]
}%

extension Int64 {
  init(truncatingBitPattern: UInt64) {
    self = Int64(bitPattern: truncatingBitPattern)
  }
}
extension UInt64 {
  init(truncatingBitPattern: UInt64) {
    self = truncatingBitPattern
  }
}

% for Type, accessor, isSigned in bridgedFixedPointTypes:

nsNumberBridging.test("${Type}") {
  for value in [
    0, 1, ${Type}.min, ${Type}.max,
    ${Type}(truncatingBitPattern: 0x1122_3344_5566_7788 as UInt64),
% if isSigned:
    -1,
    -${Type}(truncatingBitPattern: 0x1122_3344_5566_7788 as UInt64),
% end
  ] {
    expectBridgeToNSNumber(value,
                           nsNumberInitializer: { NSNumber(value: $0) },
                           nsNumberGetter: { $0.${accessor}Value },
                           equal: (==))
  }
}

% end

func floatsAreEquivalent(_ x: Float, _ y: Float) -> Bool {
  return x.bitPattern == y.bitPattern
}
func floatsAreEquivalent(_ x: Double, _ y: Double) -> Bool {
  return x.bitPattern == y.bitPattern
}

%{
bridgedFloatTypes = [
  #Type       accessor
  ("Float",   "float"),
  ("Double",  "double"),
]
}%

% for Type, accessor in bridgedFloatTypes:

nsNumberBridging.test("${Type}") {
  for value in [
    0, -0, 1, -1,
    ${Type}.leastNonzeroMagnitude,
    ${Type}.leastNormalMagnitude,
    ${Type}.greatestFiniteMagnitude,
    ${Type}.infinity,
    -${Type}.leastNonzeroMagnitude,
    -${Type}.leastNormalMagnitude,
    -${Type}.greatestFiniteMagnitude,
    -${Type}.infinity,
    ${Type}.nan,
  ] {
    expectBridgeToNSNumber(value,
                           nsNumberInitializer: { NSNumber(value: $0) },
                           nsNumberGetter: { $0.${accessor}Value },
                           equal: floatsAreEquivalent)
  }
}

% end

%{
allBridgedTypes = [type_name for type_name, _, _ in bridgedFixedPointTypes] + \
                  [type_name for type_name, _ in bridgedFloatTypes]
}%

% for AType in allBridgedTypes:

nsNumberBridging.test("${AType} bridged casting") {
  let original: ${AType} = 17
  let originalAny = original as Any
  let bridgedAny = original as AnyObject as Any
  expectEqual(original,        bridgedAny as! ${AType})
  expectEqual(.some(original), bridgedAny as? ${AType})
  expectEqual(original,        originalAny as! ${AType})
  expectEqual(.some(original), originalAny as? ${AType})

  let nsNumber = NSNumber(value: original)
  expectEqual(nsNumber,        bridgedAny as! NSNumber)
  expectEqual(.some(nsNumber), bridgedAny as? NSNumber)
  expectEqual(nsNumber,        originalAny as! NSNumber)
  expectEqual(.some(nsNumber), originalAny as? NSNumber)
}

%   for BType in allBridgedTypes:
%     if AType != BType:
nsNumberBridging.test("${AType} to ${BType} casting fails") {
  let original: ${AType} = 0
  let bridged = original as AnyObject as Any
  expectEqual(.none, bridged as? ${BType})
  expectCrashLater()
  _ = bridged as! ${BType}
}
%     end
%   end
% end

runAllTests()
