Produce framework tests
This commit is contained in:
@@ -75,7 +75,7 @@ allprojects {
|
||||
sourceSets {
|
||||
// backend.native/tests
|
||||
testOutputLocal {
|
||||
output.dir(rootProject.file("$testOutputRoot/local"))
|
||||
output.dir(rootProject.file("$testOutputRoot/local"))
|
||||
}
|
||||
|
||||
// backend.native/tests/external
|
||||
@@ -87,6 +87,11 @@ allprojects {
|
||||
testOutputStdlib {
|
||||
output.dir(rootProject.file("$testOutputRoot/stdlib"))
|
||||
}
|
||||
|
||||
// backend.native/tests/framework
|
||||
testOutputFramework {
|
||||
output.dir(rootProject.file("$testOutputRoot/framework"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +157,9 @@ def tasksOf(Closure<Task> filter) {
|
||||
run {
|
||||
def tasks = tasksOf { it instanceof KonanTest && it.inDevelopersRun }
|
||||
dependsOn(tasks)
|
||||
|
||||
// Add framework tests
|
||||
dependsOn(project.tasks.withType(FrameworkTest))
|
||||
}
|
||||
|
||||
// Collect results in one json.
|
||||
@@ -2645,6 +2653,41 @@ task produce_dynamic(type: DynamicKonanTest) {
|
||||
"topLevel = 777 3\n"
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sourceSet's output path as a string
|
||||
*/
|
||||
static String outputPath(SourceSet set) {
|
||||
return set.output.getDirs().getSingleFile().toString()
|
||||
}
|
||||
|
||||
if (isMac() && project.testTarget != 'wasm32') {
|
||||
def target = project.testTarget ?: 'host'
|
||||
|
||||
task testValuesFramework(type: FrameworkTest) {
|
||||
frameworkName = 'Values'
|
||||
konanArtifacts {
|
||||
framework(frameworkName, targets: [ target ]) {
|
||||
srcDir 'framework/values'
|
||||
baseDir outputPath(sourceSets.testOutputFramework) + "/$frameworkName"
|
||||
}
|
||||
}
|
||||
swiftSources = ['framework/values/values.swift']
|
||||
dependsOn "compileKonan${frameworkName}"
|
||||
}
|
||||
|
||||
task testStdlibFramework(type: FrameworkTest) {
|
||||
frameworkName = 'Stdlib'
|
||||
konanArtifacts {
|
||||
framework(frameworkName, targets: [ target ]) {
|
||||
srcDir 'framework/stdlib'
|
||||
baseDir outputPath(sourceSets.testOutputFramework) + "/$frameworkName"
|
||||
}
|
||||
}
|
||||
swiftSources = ['framework/stdlib/stdlib.swift']
|
||||
dependsOn "compileKonan${frameworkName}"
|
||||
}
|
||||
}
|
||||
|
||||
task buildKonanStdlibTests(type: BuildKonanTest) {
|
||||
outputSourceSetName = "testOutputStdlib"
|
||||
compileList = [ "stdlib_external", "testUtils.kt" ]
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
|
||||
enum TestError : Error {
|
||||
case assertFailed(String)
|
||||
case failure
|
||||
case testsFailed([String])
|
||||
}
|
||||
|
||||
// ---------------- Assertions ----------------
|
||||
|
||||
func assertEquals<T: Equatable>(actual: T, expected: T,
|
||||
_ message: String = "Assertion failed:") throws {
|
||||
if (actual != expected) {
|
||||
throw TestError.assertFailed(message + " Expected value: \(expected), but got: \(actual)")
|
||||
}
|
||||
}
|
||||
|
||||
func assertEquals<T: Equatable>(actual: [T], expected: [T],
|
||||
_ message: String = "Assertion failed: arrays not equal") throws {
|
||||
try assertEquals(actual: actual.count, expected: expected.count, "Size differs")
|
||||
try assertTrue(actual.elementsEqual(expected), "Arrays elements are not equal")
|
||||
}
|
||||
|
||||
func assertTrue(_ value: Bool, _ message: String = "Assertion failed:") throws {
|
||||
if (value != true) {
|
||||
throw TestError.assertFailed(message + " Expected value to be TRUE, but got: \(value)")
|
||||
}
|
||||
}
|
||||
|
||||
func assertFalse(_ value: Bool, _ message: String = "Assertion failed:") throws {
|
||||
if (value != false) {
|
||||
throw TestError.assertFailed(message + " Expected value to be FALSE, but got: \(value)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------- Utils --------------------
|
||||
|
||||
func withAutorelease( _ method: @escaping () throws -> Void) -> () throws -> Void {
|
||||
return { () throws -> Void in
|
||||
try autoreleasepool { try method() }
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Execution ----------------
|
||||
|
||||
private final class Statistics : CustomStringConvertible {
|
||||
var passed: [String] = []
|
||||
var failed: [String] = []
|
||||
|
||||
var description: String {
|
||||
return """
|
||||
---- RESULTS:
|
||||
PASSED: \(passed.count)
|
||||
FAILED: \(failed.count)
|
||||
"""
|
||||
}
|
||||
|
||||
static let instance = Statistics()
|
||||
|
||||
static func getInstance() -> Statistics {
|
||||
return instance
|
||||
}
|
||||
|
||||
func start(_ name: String) {
|
||||
print("---- Starting test: \(name)")
|
||||
}
|
||||
|
||||
func passed(_ name: String) {
|
||||
print("---- PASSED test: \(name)")
|
||||
passed.append(name)
|
||||
}
|
||||
|
||||
func failed(_ name: String, error: Error) {
|
||||
print("---- FAILED test: \(name) with error: \(error)")
|
||||
failed.append(name)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* TestCase represents a single test
|
||||
*/
|
||||
struct TestCase {
|
||||
let name: String
|
||||
let method: () throws -> Void
|
||||
|
||||
init(name: String, method: @escaping () throws -> Void) {
|
||||
self.name = name
|
||||
self.method = method
|
||||
}
|
||||
|
||||
func run() {
|
||||
let stats = Statistics.getInstance()
|
||||
stats.start(name)
|
||||
do {
|
||||
try method()
|
||||
stats.passed(name)
|
||||
} catch {
|
||||
stats.failed(name, error: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protocol TestProvider {
|
||||
var tests: [TestCase] { get }
|
||||
}
|
||||
|
||||
var providers: [TestProvider] = []
|
||||
|
||||
private func execute(tests: [TestCase]) {
|
||||
for test in tests {
|
||||
test.run()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point of the test
|
||||
*/
|
||||
private func main() {
|
||||
// Generated method that instantiates TestProvider
|
||||
registerProvider()
|
||||
|
||||
let stats = Statistics.getInstance()
|
||||
for pr in providers {
|
||||
execute(tests: pr.tests)
|
||||
}
|
||||
print(stats)
|
||||
|
||||
let failed = stats.failed
|
||||
if !failed.isEmpty {
|
||||
print()
|
||||
print("Tests failed:")
|
||||
for testName in failed {
|
||||
print(":: \(testName)")
|
||||
}
|
||||
abort()
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package stdlib
|
||||
|
||||
fun <K, V> isEmpty(map: Map<K, V>) = map.isEmpty()
|
||||
|
||||
fun <K, V> getKeysAsSet(map: Map<K, V>) = map.keys
|
||||
fun <K, V> getKeysAsList(map: Map<K, V>) = map.keys.toList()
|
||||
|
||||
fun <K, V> toMutableMap(map: HashMap<K, V>) = map.toMutableMap()
|
||||
|
||||
fun <E> getFirstElement(collection: Collection<E>) = collection.first()
|
||||
|
||||
class GenericExtensionClass<K, out V, out T : Map<K, V>> (private val holder: T?) {
|
||||
fun getFirstKey(): K? = holder?.entries?.first()?.key
|
||||
|
||||
fun getFirstValue() : V? {
|
||||
holder?.entries?.forEach { e -> println("KEY: ${e.key} VALUE: ${e.value}") }
|
||||
return holder?.entries?.first()?.value
|
||||
}
|
||||
}
|
||||
|
||||
fun <K, V> createPair():
|
||||
Pair<LinkedHashMap<K, V>, GenericExtensionClass<K, V, Map<K, V>>> {
|
||||
val l = createLinkedMap<K, V>()
|
||||
val g = GenericExtensionClass(l)
|
||||
return Pair(l, g)
|
||||
}
|
||||
|
||||
fun <K, V> createLinkedMap() = linkedMapOf<K, V>()
|
||||
|
||||
fun createTypedMutableMap() = linkedMapOf<Int, String>()
|
||||
|
||||
fun addSomeElementsToMap(map: MutableMap<String, Int>) {
|
||||
map.put(key = "XYZ", value = 321)
|
||||
map.put(key = "TMP", value = 451)
|
||||
}
|
||||
|
||||
fun list(vararg elements: Any?): Any = listOf(*elements)
|
||||
fun set(vararg elements: Any?): Any = setOf(*elements)
|
||||
fun map(vararg keysAndValues: Any?): Any = mutableMapOf<Any?, Any?>().apply {
|
||||
(0 until keysAndValues.size step 2).forEach {index ->
|
||||
this[keysAndValues[index]] = keysAndValues[index + 1]
|
||||
}
|
||||
}
|
||||
|
||||
fun emptyMutableList(): Any = mutableListOf<Any?>()
|
||||
fun emptyMutableSet(): Any = mutableSetOf<Any?>()
|
||||
fun emptyMutableMap(): Any = mutableMapOf<Any?, Any?>()
|
||||
|
||||
data class TripleVals<T>(val first: T, val second: T, val third: T)
|
||||
|
||||
data class TripleVars<T>(var first: T, var second: T, var third: T) {
|
||||
override fun toString(): String {
|
||||
return "[$first, $second, $third]"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Stdlib
|
||||
|
||||
extension NSEnumerator {
|
||||
func remainingObjects() -> [Any?] {
|
||||
var result = [Any?]()
|
||||
while (true) {
|
||||
if let next = self.nextObject() {
|
||||
result.append(next as AnyObject as Any?)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
class StdlibTests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
tests = [
|
||||
TestCase(name: "TestEmptyDictionary", method: withAutorelease(testEmptyDictionary)),
|
||||
TestCase(name: "TestGenericMapUsage", method: withAutorelease(testGenericMapUsage)),
|
||||
TestCase(name: "TestOrderedMapStored", method: withAutorelease(testOrderedMapStored)),
|
||||
TestCase(name: "TestTypedMapUsage", method: withAutorelease(testTypedMapUsage)),
|
||||
TestCase(name: "TestFirstElement", method: withAutorelease(testFirstElement)),
|
||||
TestCase(name: "TestAddDictionary", method: withAutorelease(testAddDictionary)),
|
||||
TestCase(name: "TestList", method: withAutorelease(testList)),
|
||||
TestCase(name: "TestMutableList", method: withAutorelease(testMutableList)),
|
||||
TestCase(name: "TestSet", method: withAutorelease(testSet)),
|
||||
TestCase(name: "TestMutableSet", method: withAutorelease(testMutableSet)),
|
||||
TestCase(name: "TestMap", method: withAutorelease(testMap)),
|
||||
TestCase(name: "TestMutableMap", method: withAutorelease(testMutableMap))
|
||||
]
|
||||
providers.append(self)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass empty dictionary to Kotlin.
|
||||
*/
|
||||
func testEmptyDictionary() throws {
|
||||
let immutableEmptyDict = [String: Int]()
|
||||
try assertTrue(Stdlib.isEmpty(map: immutableEmptyDict), "Empty dictionary")
|
||||
let keys = Stdlib.getKeysAsSet(map: immutableEmptyDict)
|
||||
try assertTrue(keys.isEmpty, "Should have empty set")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests usage of a map with generics.
|
||||
*/
|
||||
func testGenericMapUsage() throws {
|
||||
let map = Stdlib.createLinkedMap()
|
||||
map[1] = "One"
|
||||
map[10] = "Ten"
|
||||
map[11] = "Eleven"
|
||||
map["10"] = "Ten as string"
|
||||
for (k, v) in map {
|
||||
print("MAP: \(k) - \(v)")
|
||||
}
|
||||
|
||||
try assertEquals(actual: map[11] as! String, expected: "Eleven", "An element of the map for key: 11")
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks order of the underlying LinkedHashMap.
|
||||
*/
|
||||
func testOrderedMapStored() throws {
|
||||
let pair = Stdlib.createPair()
|
||||
let map = pair.first as? NSMutableDictionary
|
||||
|
||||
map?[1] = "One"
|
||||
map?[10] = "Ten"
|
||||
map?[11] = "Eleven"
|
||||
map?["10"] = "Ten as string"
|
||||
|
||||
let gen = pair.second as! StdlibGenericExtensionClass
|
||||
let value: String? = gen.getFirstValue() as? String
|
||||
try assertEquals(actual: value!, expected: "One", "First value of the map")
|
||||
|
||||
let key: Int? = gen.getFirstKey() as? Int
|
||||
try assertEquals(actual: key!, expected: 1, "First key of the map")
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests typed map created in Kotlin.
|
||||
*/
|
||||
func testTypedMapUsage() throws {
|
||||
let map = Stdlib.createTypedMutableMap()
|
||||
map[1] = "One"
|
||||
map[1.0 as Float] = "Float"
|
||||
map[11] = "Eleven"
|
||||
map["10"] = "Ten as string"
|
||||
|
||||
try assertEquals(actual: map["10"] as! String, expected: "Ten as string", "String key")
|
||||
try assertEquals(actual: map[1.0 as Float] as! String, expected: "Float", "Float key")
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first element of the collection.
|
||||
*/
|
||||
func testFirstElement() throws {
|
||||
let m = Stdlib.createTypedMutableMap()
|
||||
m[10] = "Str"
|
||||
try assertEquals(actual: Stdlib.getFirstElement(collection: m.allKeys) as! Int, expected: 10, "First key")
|
||||
|
||||
try assertEquals(actual: Stdlib.getFirstElement(collection: Stdlib.getKeysAsList(map: m as! Dictionary)) as! Int,
|
||||
expected: 10, "First key from a list")
|
||||
}
|
||||
|
||||
/**
|
||||
* Add element to dictionary in Kotlin
|
||||
*/
|
||||
func testAddDictionary() throws {
|
||||
let m = [ "ABC": 10, "CDE": 12, "FGH": 3 ]
|
||||
Stdlib.addSomeElementsToMap(map: StdlibMutableDictionary(dictionary: m))
|
||||
for (k, v) in m {
|
||||
print("MAP: \(k) - \(v)")
|
||||
}
|
||||
|
||||
var smd = StdlibMutableDictionary<NSString, NSNumber>()
|
||||
smd.setObject(333, forKey: "333" as NSString)
|
||||
try assertEquals(actual: smd.object(forKey: "333" as NSString) as! Int, expected: 333, "Add element to dict")
|
||||
|
||||
Stdlib.addSomeElementsToMap(map: smd)
|
||||
for (k, v) in smd {
|
||||
print("MAP: \(k) - \(v)")
|
||||
}
|
||||
try assertEquals(actual: smd.object(forKey: "XYZ" as NSString) as! Int, expected: 321, "Get element from Kotlin")
|
||||
}
|
||||
|
||||
func zeroTo(_ n: Int32) -> StdlibStdlibArray { return StdlibStdlibArray(size: n) { $0 } }
|
||||
|
||||
func testList() throws {
|
||||
let elements = zeroTo(5)
|
||||
elements.set(index: 1, value: nil)
|
||||
let list = Stdlib.list(elements: elements) as! NSArray
|
||||
try assertEquals(actual: list.object(at: 2) as! NSNumber, expected: NSNumber(value: 2))
|
||||
try assertEquals(actual: list.object(at: 1) as! NSNull, expected: NSNull())
|
||||
try assertEquals(actual: list.count, expected: 5)
|
||||
}
|
||||
|
||||
func testMutableList() throws {
|
||||
let kotlinList = Stdlib.emptyMutableList() as! NSMutableArray
|
||||
let nsList = NSMutableArray()
|
||||
|
||||
func apply<T : Equatable>(op: (NSMutableArray)->T) throws {
|
||||
let actual = op(kotlinList)
|
||||
let expected = op(nsList)
|
||||
try assertEquals(actual: actual, expected: expected)
|
||||
try assertEquals(actual: kotlinList, expected: nsList)
|
||||
try assertEquals(actual: kotlinList.hash, expected: nsList.hash)
|
||||
}
|
||||
|
||||
func applyVoid(op: (NSMutableArray)->Void) throws {
|
||||
op(kotlinList)
|
||||
op(nsList)
|
||||
try assertEquals(actual: kotlinList, expected: nsList)
|
||||
try assertEquals(actual: kotlinList.hash, expected: nsList.hash)
|
||||
}
|
||||
|
||||
try apply { $0.count }
|
||||
try applyVoid { $0.insert(0, at: 0) }
|
||||
try applyVoid { $0.insert(1, at: 0) }
|
||||
try applyVoid { $0.insert(2, at: 1) }
|
||||
try applyVoid { $0.removeObject(at: 0) }
|
||||
try applyVoid { $0.add("foo") }
|
||||
try applyVoid { $0.removeLastObject() }
|
||||
try applyVoid { $0.replaceObject(at: 0, with: "bar") }
|
||||
let NULL: Any? = nil
|
||||
try applyVoid { $0.add(NULL as Any) }
|
||||
try applyVoid { $0.insert(NULL as Any, at: 2) }
|
||||
try applyVoid { $0.replaceObject(at: 1, with: NULL as Any) }
|
||||
try apply { $0.count }
|
||||
}
|
||||
|
||||
func testMutableSet() throws {
|
||||
let kotlinSet = Stdlib.emptyMutableSet() as! NSMutableSet
|
||||
let nsSet = NSMutableSet()
|
||||
|
||||
func apply<T : Equatable>(op: (NSMutableSet)->T) throws {
|
||||
let actual = op(kotlinSet)
|
||||
let expected = op(nsSet)
|
||||
try assertEquals(actual: actual, expected: expected)
|
||||
try assertEquals(actual: kotlinSet, expected: nsSet)
|
||||
try assertEquals(actual: kotlinSet.hash, expected: nsSet.hash)
|
||||
}
|
||||
|
||||
func applyVoid(op: (NSMutableSet)->Void) throws {
|
||||
op(kotlinSet)
|
||||
op(nsSet)
|
||||
try assertEquals(actual: kotlinSet, expected: nsSet)
|
||||
try assertEquals(actual: kotlinSet.hash, expected: nsSet.hash)
|
||||
}
|
||||
|
||||
try apply { $0.count }
|
||||
try applyVoid { $0.add("foo") }
|
||||
try applyVoid { $0.add("bar") }
|
||||
try applyVoid { $0.remove("baz") }
|
||||
try applyVoid { $0.add("baz") }
|
||||
try applyVoid { $0.add(StdlibTripleVals(first: 1, second: 2, third: 3)) }
|
||||
try apply { $0.member(StdlibTripleVals(first: 1, second: 2, third: 3)) as! StdlibTripleVals }
|
||||
try apply { $0.member(42) == nil }
|
||||
try applyVoid { $0.remove(StdlibTripleVals(first: 1, second: 2, third: 3)) }
|
||||
|
||||
let NULL0: Any? = nil
|
||||
let NULL = NULL0 as Any
|
||||
|
||||
try applyVoid { $0.add(NULL) }
|
||||
try apply { $0.member(NULL) == nil }
|
||||
try apply { $0.member(NULL) as! NSObject }
|
||||
try applyVoid { $0.remove(NULL) }
|
||||
try apply { $0.member(NULL) == nil }
|
||||
|
||||
try apply { NSSet(array: $0.objectEnumerator().remainingObjects()) }
|
||||
|
||||
try apply { $0.count }
|
||||
}
|
||||
|
||||
func testMutableMap() throws {
|
||||
// TODO: test KotlinMutableSet/Dictionary constructors
|
||||
let kotlinMap = Stdlib.emptyMutableMap() as! NSMutableDictionary
|
||||
let nsMap = NSMutableDictionary()
|
||||
|
||||
func apply<T : Equatable>(op: (NSMutableDictionary)->T) throws {
|
||||
let actual = op(kotlinMap)
|
||||
let expected = op(nsMap)
|
||||
try assertEquals(actual: actual, expected: expected)
|
||||
try assertEquals(actual: kotlinMap, expected: nsMap)
|
||||
try assertEquals(actual: kotlinMap.hash, expected: nsMap.hash)
|
||||
}
|
||||
|
||||
func applyVoid(op: (NSMutableDictionary) throws -> Void) throws {
|
||||
try op(kotlinMap)
|
||||
try op(nsMap)
|
||||
try assertEquals(actual: kotlinMap, expected: nsMap)
|
||||
try assertEquals(actual: kotlinMap.hash, expected: nsMap.hash)
|
||||
}
|
||||
|
||||
try apply { $0.count }
|
||||
try apply { $0.object(forKey: 42) == nil }
|
||||
try applyVoid { $0.setObject(42, forKey: 42 as NSNumber) }
|
||||
try applyVoid { $0.setObject(17, forKey: "foo" as NSString) }
|
||||
let triple = StdlibTripleVals(first: 3, second: 2, third: 1)
|
||||
try applyVoid { $0.setObject("bar", forKey: triple) }
|
||||
try applyVoid { $0.removeObject(forKey: 42) }
|
||||
try apply { $0.count }
|
||||
try apply { $0.object(forKey: 42) == nil }
|
||||
try apply { $0.object(forKey: "foo") as! NSObject }
|
||||
try apply { $0.object(forKey: triple) as! NSObject }
|
||||
|
||||
try apply { NSSet(array: $0.keyEnumerator().remainingObjects()) }
|
||||
|
||||
let NULL0: Any? = nil
|
||||
let NULL = NULL0 as Any
|
||||
|
||||
try apply { $0.object(forKey: NULL) == nil }
|
||||
|
||||
|
||||
try applyVoid { $0.setObject(42, forKey: NULL as! NSCopying) }
|
||||
try applyVoid { $0.setObject(NULL, forKey: "baz" as NSString) }
|
||||
try apply { $0.object(forKey: NULL) as! NSObject }
|
||||
try apply { $0.object(forKey: "baz") as! NSObject }
|
||||
|
||||
try apply { NSSet(array: $0.keyEnumerator().remainingObjects()) }
|
||||
|
||||
try applyVoid { $0.removeObject(forKey: NULL) }
|
||||
try applyVoid { $0.removeObject(forKey: "baz") }
|
||||
|
||||
try applyVoid { $0.removeAllObjects() }
|
||||
|
||||
let myKey = MyKey()
|
||||
try applyVoid { $0.setObject(myKey, forKey: myKey) }
|
||||
try applyVoid {
|
||||
let key = $0.allKeys[0] as! MyKey
|
||||
let value = $0.allValues[0] as! MyKey
|
||||
try assertFalse(key === myKey)
|
||||
try assertTrue(value === myKey)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@objc class MyKey : NSObject, NSCopying {
|
||||
override var hash: Int {
|
||||
return 42
|
||||
}
|
||||
|
||||
override func isEqual(_ object: Any?) -> Bool {
|
||||
return object is MyKey
|
||||
}
|
||||
|
||||
func copy(with: NSZone? = nil) -> Any {
|
||||
return MyKey()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testSet() throws {
|
||||
let elements = StdlibStdlibArray(size: 2) { index in nil }
|
||||
elements.set(index: 0, value: nil)
|
||||
elements.set(index: 1, value: 42)
|
||||
let set = Stdlib.set(elements: elements) as! NSSet
|
||||
try assertEquals(actual: set.count, expected: 2)
|
||||
try assertEquals(actual: set.member(NSNull()) as! NSNull, expected: NSNull())
|
||||
try assertEquals(actual: set.member(42) as! NSNumber, expected: NSNumber(value: 42 as Int32))
|
||||
try assertTrue(set.member(17) == nil)
|
||||
try assertFalse(set.member(42) as AnyObject === NSNumber(value: 42 as Int32))
|
||||
try assertTrue(set.contains(42))
|
||||
try assertTrue(set.contains(nil as Any?))
|
||||
try assertFalse(set.contains(17))
|
||||
|
||||
try assertEquals(actual: NSSet(array: set.objectEnumerator().remainingObjects()), expected: NSSet(array: [nil, 42] as [AnyObject]))
|
||||
}
|
||||
|
||||
func testMap() throws {
|
||||
let elements = StdlibStdlibArray(size: 6) { index in nil }
|
||||
elements.set(index: 0, value: nil)
|
||||
elements.set(index: 1, value: 42)
|
||||
elements.set(index: 2, value: "foo")
|
||||
elements.set(index: 3, value: "bar")
|
||||
elements.set(index: 4, value: 42)
|
||||
elements.set(index: 5, value: nil)
|
||||
|
||||
let map = Stdlib.map(keysAndValues: elements) as! NSDictionary
|
||||
try assertEquals(actual: map.count, expected: 3)
|
||||
|
||||
try assertEquals(actual: map.object(forKey: NSNull()) as! NSNumber, expected: NSNumber(value: 42))
|
||||
try assertEquals(actual: map.object(forKey: "foo") as! String, expected: "bar")
|
||||
try assertEquals(actual: map.object(forKey: 42) as! NSNull, expected: NSNull())
|
||||
try assertTrue(map.object(forKey: "bar") == nil)
|
||||
|
||||
try assertEquals(actual: NSSet(array: map.keyEnumerator().remainingObjects()), expected: NSSet(array: [nil, 42, "foo"] as [AnyObject]))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// All classes and methods should be used in tests
|
||||
@file:Suppress("UNUSED")
|
||||
|
||||
package conversions
|
||||
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
// Constants
|
||||
const val dbl: Double = 3.14
|
||||
const val flt: Float = 2.73F
|
||||
const val integer: Int = 42
|
||||
const val longInt: Long = 1984
|
||||
|
||||
// Vars
|
||||
var intVar: Int = 451
|
||||
var str = "Kotlin String"
|
||||
var strAsAny: Any = "Kotlin String as Any"
|
||||
|
||||
// MIN/MAX values as Numbers
|
||||
var minDoubleVal: kotlin.Number = Double.MIN_VALUE
|
||||
var maxDoubleVal: kotlin.Number = Double.MAX_VALUE
|
||||
|
||||
// Infinities and NaN
|
||||
val nanDoubleVal: Double = Double.NaN
|
||||
val nanFloatVal: Float = Float.NaN
|
||||
val infDoubleVal: Double = Double.POSITIVE_INFINITY
|
||||
val infFloatVal: Float = Float.NEGATIVE_INFINITY
|
||||
|
||||
// Boolean
|
||||
val boolVal: Boolean = true
|
||||
val boolAnyVal: Any = false
|
||||
|
||||
// Lists
|
||||
val numbersList: List<Number> = listOf(1.toByte(), 2.toShort(), 13)
|
||||
val anyList: List<Any> = listOf("Str", 42, 3.14, true)
|
||||
|
||||
// lateinit
|
||||
lateinit var lateinitIntVar: Any
|
||||
|
||||
// lazy
|
||||
val lazyVal: String by lazy {
|
||||
println("Lazy value initialization")
|
||||
"Lazily initialized string"
|
||||
}
|
||||
|
||||
// Delegation
|
||||
var delegatedGlobalArray: Array<String> by DelegateClass()
|
||||
|
||||
class DelegateClass: ReadWriteProperty<Nothing?, Array<String>> {
|
||||
|
||||
private var holder: Array<String> = arrayOf("property")
|
||||
|
||||
override fun getValue(thisRef: Nothing?, property: KProperty<*>): Array<String> {
|
||||
return arrayOf("Delegated", "global", "array") + holder
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: Array<String>) {
|
||||
holder = value
|
||||
}
|
||||
}
|
||||
|
||||
// Getter with delegation
|
||||
val delegatedList: List<String>
|
||||
get() = delegatedGlobalArray.toList()
|
||||
|
||||
// Null
|
||||
val nullVal: Any? = null
|
||||
var nullVar: String? = ""
|
||||
|
||||
// Any
|
||||
var anyValue: Any = "Str"
|
||||
|
||||
// Functions
|
||||
fun emptyFun() { }
|
||||
|
||||
fun strFun(): String = "fooStr"
|
||||
|
||||
fun argsFun(i: Int, l: Long, d: Double, s: String): Any = s + i + l + d
|
||||
|
||||
fun funArgument(foo: () -> String): String = foo()
|
||||
|
||||
// Generic functions
|
||||
fun <T, R> genericFoo(t: T, foo: (T) -> R): R = foo(t)
|
||||
|
||||
fun <T : Number, R : T> fooGenericNumber(r: R, foo: (T) -> Number): Number = foo(r)
|
||||
|
||||
fun <T> varargToList(vararg args: T): List<T> = args.toList()
|
||||
|
||||
// Extensions
|
||||
fun String.subExt(i: Int): String {
|
||||
return if (i < this.length) this[i].toString() else "nothing"
|
||||
}
|
||||
|
||||
fun Any?.toString(): String = this?.toString() ?: "null"
|
||||
|
||||
fun Any?.print() = println(this.toString())
|
||||
|
||||
// Lambdas
|
||||
val sumLambda = { x: Int, y: Int -> x + y }
|
||||
|
||||
|
||||
// Inheritance
|
||||
interface I {
|
||||
fun iFun(): String = "I::iFun"
|
||||
}
|
||||
|
||||
private interface PI {
|
||||
fun piFun(): Any
|
||||
fun iFun(): String = "PI::iFun"
|
||||
}
|
||||
|
||||
class DefaultInterfaceExt : I
|
||||
|
||||
open class OpenClassI : I {
|
||||
override fun iFun(): String = "OpenClassI::iFun"
|
||||
}
|
||||
|
||||
class FinalClassExtOpen : OpenClassI() {
|
||||
override fun iFun(): String = "FinalClassExtOpen::iFun"
|
||||
}
|
||||
|
||||
open class MultiExtClass : OpenClassI(), PI {
|
||||
override fun piFun(): Any {
|
||||
return 42
|
||||
}
|
||||
|
||||
override fun iFun(): String = super<PI>.iFun()
|
||||
}
|
||||
|
||||
open class ConstrClass(open val i: Int, val s: String, val a: Any = "AnyS") : OpenClassI()
|
||||
|
||||
class ExtConstrClass(override val i: Int) : ConstrClass(i, "String") {
|
||||
override fun iFun(): String = "ExtConstrClass::iFun::$i-$s-$a"
|
||||
}
|
||||
|
||||
// Enum
|
||||
enum class Enumeration(val enumValue: Int) {
|
||||
ANSWER(42), YEAR(1984), TEMPERATURE(451)
|
||||
}
|
||||
|
||||
fun passEnum(): Enumeration {
|
||||
return Enumeration.ANSWER
|
||||
}
|
||||
|
||||
fun receiveEnum(e: Int) {
|
||||
println("ENUM got: ${get(e).enumValue}")
|
||||
}
|
||||
|
||||
fun get(value: Int): Enumeration {
|
||||
return Enumeration.values()[value]
|
||||
}
|
||||
|
||||
// Data class values and generated properties: component# and toString()
|
||||
data class TripleVals<T>(val first: T, val second: T, val third: T)
|
||||
|
||||
data class TripleVars<T>(var first: T, var second: T, var third: T) {
|
||||
override fun toString(): String {
|
||||
return "[$first, $second, $third]"
|
||||
}
|
||||
}
|
||||
|
||||
open class WithCompanionAndObject {
|
||||
companion object {
|
||||
val str = "String"
|
||||
var named: I? = Named
|
||||
}
|
||||
|
||||
object Named : OpenClassI() {
|
||||
override fun iFun(): String = "WithCompanionAndObject.Named::iFun"
|
||||
}
|
||||
}
|
||||
|
||||
fun getCompanionObject() = WithCompanionAndObject.Companion
|
||||
fun getNamedObject() = WithCompanionAndObject.Named
|
||||
fun getNamedObjectInterface(): OpenClassI = WithCompanionAndObject.Named
|
||||
|
||||
typealias EE = Enumeration
|
||||
fun EE.getAnswer() : EE = Enumeration.ANSWER
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Values
|
||||
|
||||
// -------- Tests --------
|
||||
|
||||
func testVals() throws {
|
||||
print("Values from Swift")
|
||||
let dbl = Values.dbl
|
||||
let flt = Values.flt
|
||||
let int = Values.integer
|
||||
let long = Values.longInt
|
||||
|
||||
print(dbl)
|
||||
print(flt)
|
||||
print(int)
|
||||
print(long)
|
||||
|
||||
try assertEquals(actual: dbl, expected: 3.14 as Double, "Double value isn't equal.")
|
||||
try assertEquals(actual: flt, expected: 2.73 as Float, "Float value isn't equal.")
|
||||
try assertEquals(actual: int, expected: 42)
|
||||
try assertEquals(actual: long, expected: 1984)
|
||||
}
|
||||
|
||||
func testVars() throws {
|
||||
print("Variables from Swift")
|
||||
var intVar = Values.intVar
|
||||
var strVar = Values.str
|
||||
var strAsId = Values.strAsAny
|
||||
|
||||
print(intVar)
|
||||
print(strVar)
|
||||
print(strAsId)
|
||||
|
||||
try assertEquals(actual: intVar, expected: 451)
|
||||
try assertEquals(actual: strVar, expected: "Kotlin String")
|
||||
try assertEquals(actual: strAsId as! String, expected: "Kotlin String as Any")
|
||||
|
||||
strAsId = "Swift str"
|
||||
Values.strAsAny = strAsId
|
||||
print(Values.strAsAny)
|
||||
try assertEquals(actual: Values.strAsAny as! String, expected: strAsId as! String)
|
||||
|
||||
// property with custom getter/setter backed by the Kotlin's var
|
||||
var intProp : Int32 {
|
||||
get {
|
||||
return Values.intVar * 2
|
||||
}
|
||||
set(value) {
|
||||
Values.intVar = 123 + value
|
||||
}
|
||||
}
|
||||
intProp += 10
|
||||
print(intProp)
|
||||
print(Values.intVar)
|
||||
try assertEquals(actual: Values.intVar * 2, expected: intProp, "Property backed by var")
|
||||
}
|
||||
|
||||
func testDoubles() throws {
|
||||
print("Doubles in Swift")
|
||||
let minDouble = Values.minDoubleVal as! Double
|
||||
let maxDouble = Values.maxDoubleVal as! NSNumber
|
||||
|
||||
print(minDouble)
|
||||
print(maxDouble)
|
||||
print(Values.nanDoubleVal)
|
||||
print(Values.nanFloatVal)
|
||||
print(Values.infDoubleVal)
|
||||
print(Values.infFloatVal)
|
||||
|
||||
try assertEquals(actual: minDouble, expected: Double.leastNonzeroMagnitude, "Min double")
|
||||
try assertEquals(actual: maxDouble, expected: Double.greatestFiniteMagnitude as NSNumber, "Max double")
|
||||
try assertTrue(Values.nanDoubleVal.isNaN, "NaN double")
|
||||
try assertTrue(Values.nanFloatVal.isNaN, "NaN float")
|
||||
try assertEquals(actual: Values.infDoubleVal, expected: Double.infinity, "Inf double")
|
||||
try assertEquals(actual: Values.infFloatVal, expected: -Float.infinity, "-Inf float")
|
||||
}
|
||||
|
||||
func testLists() throws {
|
||||
let numbersList = Values.numbersList
|
||||
let gold = [1, 2, 13]
|
||||
for i in 0..<gold.count {
|
||||
try assertEquals(actual: gold[i], expected: Int(numbersList[i] as! NSNumber), "Numbers list")
|
||||
}
|
||||
|
||||
let anyList = Values.anyList
|
||||
for i in anyList {
|
||||
print(i)
|
||||
}
|
||||
// try assertEquals(actual: gold, expected: anyList, "Numbers list")
|
||||
}
|
||||
|
||||
func testLazyVal() throws {
|
||||
let lazyVal = Values.lazyVal
|
||||
print(lazyVal)
|
||||
try assertEquals(actual: lazyVal, expected: "Lazily initialized string", "lazy value")
|
||||
}
|
||||
|
||||
let goldenArray = ["Delegated", "global", "array", "property"]
|
||||
|
||||
func testDelegatedProp() throws {
|
||||
let delegatedGlobalArray = Values.delegatedGlobalArray
|
||||
guard Int(delegatedGlobalArray.size) == goldenArray.count else {
|
||||
throw TestError.assertFailed("Size differs")
|
||||
}
|
||||
for i in 0..<delegatedGlobalArray.size {
|
||||
print(delegatedGlobalArray.get(index: i)!)
|
||||
}
|
||||
}
|
||||
|
||||
func testGetterDelegate() throws {
|
||||
let delegatedList = Values.delegatedList
|
||||
guard delegatedList.count == goldenArray.count else {
|
||||
throw TestError.assertFailed("Size differs")
|
||||
}
|
||||
for val in delegatedList {
|
||||
print(val)
|
||||
}
|
||||
}
|
||||
|
||||
func testNulls() throws {
|
||||
let nilVal : Any? = Values.nullVal
|
||||
try assertTrue(nilVal == nil, "Null value")
|
||||
|
||||
Values.nullVar = nil
|
||||
var nilVar : Any? = Values.nullVar
|
||||
try assertTrue(nilVar == nil, "Null variable")
|
||||
}
|
||||
|
||||
func testAnyVar() throws {
|
||||
let anyVar : Any = Values.anyValue
|
||||
print(anyVar)
|
||||
if let str = anyVar as? String {
|
||||
print(str)
|
||||
try assertEquals(actual: str, expected: "Str")
|
||||
} else {
|
||||
throw TestError.assertFailed("Incorrect type passed from Any")
|
||||
}
|
||||
}
|
||||
|
||||
func testFunctions() throws {
|
||||
let _: Any? = Values.emptyFun()
|
||||
|
||||
let str = Values.strFun()
|
||||
try assertEquals(actual: str, expected: "fooStr")
|
||||
|
||||
try assertEquals(actual: Values.argsFun(i: 10, l: 20, d: 3.5, s: "res") as! String,
|
||||
expected: "res10203.5")
|
||||
}
|
||||
|
||||
func testFuncType() throws {
|
||||
let s = "str"
|
||||
let fFunc: () -> String = { return s }
|
||||
try assertEquals(actual: Values.funArgument(foo: fFunc), expected: s, "Using function type arguments failed")
|
||||
}
|
||||
|
||||
func testGenericsFoo() throws {
|
||||
let fun = { (i: Int) -> String in return "S \(i)" }
|
||||
// wrap lambda to workaround issue with type conversion inability:
|
||||
// (Int) -> String can't be cast to (Any?) -> Any?
|
||||
let wrapper = { (t: Any?) -> Any? in return fun(t as! Int) }
|
||||
let res = Values.genericFoo(t: 42, foo: wrapper)
|
||||
try assertEquals(actual: res as! String, expected: "S 42")
|
||||
}
|
||||
|
||||
func testVararg() throws {
|
||||
let ktArray = ValuesStdlibArray(size: 3, init: { (_) -> Int in return 42 })
|
||||
let arr: [Int] = Values.varargToList(args: ktArray) as! [Int]
|
||||
try assertEquals(actual: arr, expected: [42, 42, 42])
|
||||
}
|
||||
|
||||
func testStrExtFun() throws {
|
||||
try assertEquals(actual: Values.subExt("String", i: 2), expected: "r")
|
||||
try assertEquals(actual: Values.subExt("A", i: 2), expected: "nothing")
|
||||
}
|
||||
|
||||
func testAnyToString() throws {
|
||||
try assertEquals(actual: Values.toString(nil), expected: "null")
|
||||
try assertEquals(actual: Values.toString(42), expected: "42")
|
||||
}
|
||||
|
||||
func testAnyPrint() throws {
|
||||
print("BEGIN")
|
||||
Values.print(nil)
|
||||
Values.print("Print")
|
||||
Values.print(123456789)
|
||||
Values.print(3.14)
|
||||
Values.print([3, 2, 1])
|
||||
print("END")
|
||||
}
|
||||
|
||||
func testLambda() throws {
|
||||
try assertEquals(actual: Values.sumLambda(3, 4), expected: 7)
|
||||
}
|
||||
|
||||
// -------- Tests for classes and interfaces -------
|
||||
class ValIEmptyExt : ValuesI {
|
||||
func iFun() -> String {
|
||||
return "ValIEmptyExt::iFun"
|
||||
}
|
||||
}
|
||||
|
||||
class ValIExt : ValuesI {
|
||||
func iFun() -> String {
|
||||
return "ValIExt::iFun"
|
||||
}
|
||||
}
|
||||
|
||||
func testInterfaceExtension() throws {
|
||||
try assertEquals(actual: ValIEmptyExt().iFun(), expected: "ValIEmptyExt::iFun")
|
||||
try assertEquals(actual: ValIExt().iFun(), expected: "ValIExt::iFun")
|
||||
}
|
||||
|
||||
func testClassInstances() throws {
|
||||
try assertEquals(actual: ValuesOpenClassI().iFun(), expected: "OpenClassI::iFun")
|
||||
try assertEquals(actual: ValuesDefaultInterfaceExt().iFun(), expected: "I::iFun")
|
||||
try assertEquals(actual: ValuesFinalClassExtOpen().iFun(), expected: "FinalClassExtOpen::iFun")
|
||||
try assertEquals(actual: ValuesMultiExtClass().iFun(), expected: "PI::iFun")
|
||||
try assertEquals(actual: ValuesMultiExtClass().piFun() as! Int, expected: 42)
|
||||
try assertEquals(actual: ValuesConstrClass(i: 1, s: "str", a: "Any").iFun(), expected: "OpenClassI::iFun")
|
||||
try assertEquals(actual: ValuesExtConstrClass(i: 123).iFun(), expected: "ExtConstrClass::iFun::123-String-AnyS")
|
||||
}
|
||||
|
||||
func testEnum() throws {
|
||||
try assertEquals(actual: Values.passEnum().enumValue, expected: 42)
|
||||
try assertEquals(actual: Values.passEnum().name, expected: "ANSWER")
|
||||
Values.receiveEnum(e: 1)
|
||||
}
|
||||
|
||||
func testDataClass() throws {
|
||||
let f = "1"
|
||||
let s = "2"
|
||||
let t = "3"
|
||||
|
||||
let tripleVal = ValuesTripleVals(first: f, second: s, third: t)
|
||||
try assertEquals(actual: tripleVal.first as! String, expected: f, "Data class' value")
|
||||
try assertEquals(actual: tripleVal.component2() as! String, expected: s, "Data class' component")
|
||||
print(tripleVal)
|
||||
try assertEquals(actual: String(describing: tripleVal), expected: "TripleVals(first=\(f), second=\(s), third=\(t))")
|
||||
|
||||
let tripleVar = ValuesTripleVars(first: f, second: s, third: t)
|
||||
try assertEquals(actual: tripleVar.first as! String, expected: f, "Data class' value")
|
||||
try assertEquals(actual: tripleVar.component2() as! String, expected: s, "Data class' component")
|
||||
print(tripleVar)
|
||||
try assertEquals(actual: String(describing: tripleVar), expected: "[\(f), \(s), \(t)]")
|
||||
|
||||
tripleVar.first = t
|
||||
tripleVar.second = f
|
||||
tripleVar.third = s
|
||||
try assertEquals(actual: tripleVar.component2() as! String, expected: f, "Data class' component")
|
||||
try assertEquals(actual: String(describing: tripleVar), expected: "[\(t), \(f), \(s)]")
|
||||
}
|
||||
|
||||
func testCompanionObj() throws {
|
||||
try assertEquals(actual: ValuesWithCompanionAndObjectCompanion().str, expected: "String")
|
||||
try assertEquals(actual: Values.getCompanionObject().str, expected: "String")
|
||||
|
||||
let namedFromCompanion = Values.getCompanionObject().named
|
||||
let named = Values.getNamedObject()
|
||||
try assertTrue(named === namedFromCompanion, "Should be the same Named object")
|
||||
|
||||
try assertEquals(actual: Values.getNamedObjectInterface().iFun(), expected: named.iFun(), "Named object's method")
|
||||
}
|
||||
|
||||
// -------- Execution of the test --------
|
||||
|
||||
class ValuesTests : TestProvider {
|
||||
var tests: [TestCase] = []
|
||||
|
||||
init() {
|
||||
providers.append(self)
|
||||
tests = [
|
||||
TestCase(name: "TestValues", method: withAutorelease(testVals)),
|
||||
TestCase(name: "TestVars", method: withAutorelease(testVars)),
|
||||
TestCase(name: "TestDoubles", method: withAutorelease(testDoubles)),
|
||||
TestCase(name: "TestLists", method: withAutorelease(testLists)),
|
||||
TestCase(name: "TestLazyValues", method: withAutorelease(testLazyVal)),
|
||||
TestCase(name: "TestDelegatedProperties", method: withAutorelease(testDelegatedProp)),
|
||||
TestCase(name: "TestGetterDelegate", method: withAutorelease(testGetterDelegate)),
|
||||
TestCase(name: "TestNulls", method: withAutorelease(testNulls)),
|
||||
TestCase(name: "TestAnyVar", method: withAutorelease(testAnyVar)),
|
||||
TestCase(name: "TestFunctions", method: withAutorelease(testFunctions)),
|
||||
TestCase(name: "TestFuncType", method: withAutorelease(testFuncType)),
|
||||
TestCase(name: "TestGenericsFoo", method: withAutorelease(testGenericsFoo)),
|
||||
TestCase(name: "TestVararg", method: withAutorelease(testVararg)),
|
||||
TestCase(name: "TestStringExtension", method: withAutorelease(testStrExtFun)),
|
||||
TestCase(name: "TestAnyToString", method: withAutorelease(testAnyToString)),
|
||||
TestCase(name: "TestAnyPrint", method: withAutorelease(testAnyPrint)),
|
||||
TestCase(name: "TestLambda", method: withAutorelease(testLambda)),
|
||||
TestCase(name: "TestInterfaceExtension", method: withAutorelease(testInterfaceExtension)),
|
||||
TestCase(name: "TestClassInstances", method: withAutorelease(testClassInstances)),
|
||||
TestCase(name: "TestEnum", method: withAutorelease(testEnum)),
|
||||
TestCase(name: "TestDataClass", method: withAutorelease(testDataClass)),
|
||||
TestCase(name: "TestCompanionObj", method: withAutorelease(testCompanionObj)),
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,9 @@ interface ExecutorService {
|
||||
fun execute(action: Action<in ExecSpec>): ExecResult?
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ExecutorService depending on a test target -Ptest_target
|
||||
*/
|
||||
fun create(project: Project): ExecutorService {
|
||||
val platformManager = project.rootProject.findProperty("platformManager") as PlatformManager
|
||||
val testTarget = platformManager.targetManager(project.findProperty("testTarget") as String?).target
|
||||
@@ -87,6 +90,39 @@ fun create(project: Project): ExecutorService {
|
||||
}
|
||||
}
|
||||
|
||||
data class ProcessOutput(val stdOut: String, val stdErr: String, val exitCode: Int)
|
||||
|
||||
/**
|
||||
* Runs process using a given executor.
|
||||
*
|
||||
* @param executor a method that is able to run a given executable, e.g. ExecutorService::execute
|
||||
* @param executable a process executable to be run
|
||||
* @param args arguments for a process
|
||||
*/
|
||||
fun runProcess(executor: (Action<in ExecSpec>) -> ExecResult?,
|
||||
executable: String, args: List<String>) : ProcessOutput {
|
||||
val outStream = ByteArrayOutputStream()
|
||||
val errStream = ByteArrayOutputStream()
|
||||
|
||||
val execResult = executor(Action {
|
||||
it.executable = executable
|
||||
it.args = args.toList()
|
||||
it.standardOutput = outStream
|
||||
it.errorOutput = errStream
|
||||
it.isIgnoreExitValue = true
|
||||
})
|
||||
|
||||
checkNotNull(execResult)
|
||||
|
||||
val stdOut = outStream.toString("UTF-8")
|
||||
val stdErr = errStream.toString("UTF-8")
|
||||
|
||||
return ProcessOutput(stdOut, stdErr, execResult!!.exitValue)
|
||||
}
|
||||
|
||||
fun runProcess(executor: (Action<in ExecSpec>) -> ExecResult?,
|
||||
executable: String, vararg args: String) = runProcess(executor, executable, args.toList())
|
||||
|
||||
/**
|
||||
* Executes a given action with iPhone Simulator.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.jetbrains.kotlin
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecSpec
|
||||
|
||||
import org.jetbrains.kotlin.konan.target.*
|
||||
|
||||
import java.io.FileWriter
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* Test task for -produce framework testing. Requires a framework to be built by the Konan plugin
|
||||
* with konanArtifacts { framework(frameworkName, targets: [ testTarget] ) } and a dependency set
|
||||
* according to a pattern "compileKonan${frameworkName}".
|
||||
*
|
||||
* @property swiftSources Swift-language test sources that use a given framework
|
||||
* @property frameworkName a framework name
|
||||
*/
|
||||
open class FrameworkTest : DefaultTask() {
|
||||
@Input
|
||||
lateinit var swiftSources: List<String>
|
||||
|
||||
@Input
|
||||
lateinit var frameworkName: String
|
||||
|
||||
private val testOutput by lazy {
|
||||
((project.findProperty("sourceSets") as SourceSetContainer)
|
||||
.getByName("testOutputFramework") as SourceSet).output.dirs.singleFile.absolutePath
|
||||
?: throw RuntimeException("Empty sourceSet")
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val frameworkPath = "$testOutput/$frameworkName/${project.testTarget().name}"
|
||||
|
||||
// Sign framework
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor, executable = "/usr/bin/codesign",
|
||||
args = listOf("--verbose", "-s", "-", Paths.get(frameworkPath, "$frameworkName.framework").toString()))
|
||||
check(exitCode == 0, { """
|
||||
|Codesign failed with exitCode: $exitCode
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin()
|
||||
})
|
||||
|
||||
// create a test provider and get main entry point
|
||||
val provider = Paths.get(testOutput, frameworkName, "provider.swift")
|
||||
FileWriter(provider.toFile()).use {
|
||||
it.write("""
|
||||
|// THIS IS AUTOGENERATED FILE
|
||||
|// This method is invoked by the main routine to get a list of tests
|
||||
|func registerProvider() {
|
||||
| // TODO: assuming this naming for now
|
||||
| ${frameworkName}Tests()
|
||||
|}
|
||||
""".trimMargin())
|
||||
}
|
||||
val testHome = project.file("framework").toPath()
|
||||
val swiftMain = Paths.get(testHome.toString(), "main.swift").toString()
|
||||
|
||||
// Compile swift sources
|
||||
val sources = swiftSources.map { Paths.get(it).toString() } +
|
||||
listOf(provider.toString(), swiftMain)
|
||||
val options = listOf("-g", "-Xlinker", "-rpath", "-Xlinker", frameworkPath, "-F", frameworkPath)
|
||||
val testExecutable = Paths.get(testOutput, frameworkName, "swiftTestExecutable")
|
||||
swiftc(sources, options, testExecutable)
|
||||
|
||||
runTest(testExecutable)
|
||||
}
|
||||
|
||||
private fun runTest(testExecutable: Path) {
|
||||
val executor = (project.convention.plugins["executor"] as? ExecutorService)
|
||||
?: throw RuntimeException("Executor wasn't found")
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = executor::execute,
|
||||
executable = testExecutable.toString())
|
||||
|
||||
println("""
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin())
|
||||
check(exitCode == 0, { "Execution failed with exit code: $exitCode "})
|
||||
}
|
||||
|
||||
private val localExecutor = { a: Action<in ExecSpec> -> project.exec(a) }
|
||||
|
||||
private fun Project.platformManager() = rootProject.findProperty("platformManager") as PlatformManager
|
||||
|
||||
private fun Project.testTarget() = platformManager()
|
||||
.targetManager(project.findProperty("testTarget") as String?).target
|
||||
|
||||
private fun swiftc(sources: List<String>, options: List<String>, output: Path) {
|
||||
val target = project.testTarget()
|
||||
val platform = project.platformManager().platform(target)
|
||||
assert(platform.configurables is AppleConfigurables)
|
||||
val configs = platform.configurables as AppleConfigurables
|
||||
val compiler = configs.absoluteTargetToolchain + "/usr/bin/swiftc"
|
||||
|
||||
val swiftTarget = when (target) {
|
||||
KonanTarget.IOS_X64 -> "x86_64-apple-ios" + configs.osVersionMin
|
||||
KonanTarget.IOS_ARM64 -> "arm64_64-apple-ios" + configs.osVersionMin
|
||||
KonanTarget.MACOS_X64 -> "x86_64-apple-macosx" + configs.osVersionMin
|
||||
else -> throw IllegalStateException("Test target $target is not supported")
|
||||
}
|
||||
|
||||
val args = listOf("-sdk", configs.absoluteTargetSysRoot, "-target", swiftTarget) +
|
||||
options + "-o" + output.toString() + sources
|
||||
|
||||
val (stdOut, stdErr, exitCode) = runProcess(executor = localExecutor, executable = compiler, args = args)
|
||||
|
||||
println("""
|
||||
|$compiler finished with exit code: $exitCode
|
||||
|options: ${args.joinToString(separator = " ")}
|
||||
|stdout: $stdOut
|
||||
|stderr: $stdErr
|
||||
""".trimMargin())
|
||||
check(exitCode == 0, { "Compilation failed" })
|
||||
check(output.toFile().exists(), { "Compiler swiftc hasn't produced an output file: $output" })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user