From 790fd11d9081db9af311ccdcd2c7c67e677e7cab Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Thu, 29 Mar 2018 19:24:53 +0300 Subject: [PATCH] Freezing: fixed test and added stress test --- backend.native/tests/build.gradle | 9 +- .../tests/runtime/workers/freeze1.kt | 6 +- .../tests/runtime/workers/freeze_stress.kt | 145 ++++++++++++++++++ 3 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 backend.native/tests/runtime/workers/freeze_stress.kt diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index c267b102913..4fc9d4d1088 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -623,11 +623,16 @@ task freeze0(type: RunKonanTest) { task freeze1(type: RunKonanTest) { disabled = (project.testTarget == 'wasm32') // No exceptions on WASM. - goldValue = "OK, cannot freeze cyclic\n"+ - "OK, cannot mutate frozen\n" + goldValue = "OK, cannot mutate frozen\n" source = "runtime/workers/freeze1.kt" } +task freeze_stress(type: RunKonanTest) { + disabled = (project.testTarget == 'wasm32') // No exceptions on WASM. + goldValue = "OK\n" + source = "runtime/workers/freeze_stress.kt" +} + task superFunCall(type: RunKonanTest) { goldValue = "\n\n" source = "codegen/basics/superFunCall.kt" diff --git a/backend.native/tests/runtime/workers/freeze1.kt b/backend.native/tests/runtime/workers/freeze1.kt index fad2cfbb146..f3e17fd9d97 100644 --- a/backend.native/tests/runtime/workers/freeze1.kt +++ b/backend.native/tests/runtime/workers/freeze1.kt @@ -43,11 +43,7 @@ fun makeDiamond(): Node2 { } @Test fun runTest() { - try { - makeCycle(10).freeze() - } catch (e: FreezingException) { - println("OK, cannot freeze cyclic") - } + makeCycle(10).freeze() // Must be able to freeze diamond shaped graph. val diamond = makeDiamond().freeze() diff --git a/backend.native/tests/runtime/workers/freeze_stress.kt b/backend.native/tests/runtime/workers/freeze_stress.kt new file mode 100644 index 00000000000..72ba7464ce9 --- /dev/null +++ b/backend.native/tests/runtime/workers/freeze_stress.kt @@ -0,0 +1,145 @@ +package runtime.workers.freeze_stress + +import kotlin.test.* + +import konan.worker.* + +class Random(private var seed: Int) { + fun next(): Int { + seed = (1103515245 * seed + 12345) and 0x7fffffff + return seed + } + + fun next(maxExclusiveValue: Int) = if (maxExclusiveValue == 0) 0 else next() % maxExclusiveValue + + fun next(minInclusiveValue: Int, maxInclusiveValue: Int) = + minInclusiveValue + next(maxInclusiveValue - minInclusiveValue + 1) +} + +class Node(val id: Int) { + var numberOfEdges = 0 + + lateinit var edge0: Node + lateinit var edge1: Node + lateinit var edge2: Node + lateinit var edge3: Node + lateinit var edge4: Node + lateinit var edge5: Node + lateinit var edge6: Node + lateinit var edge7: Node + lateinit var edge8: Node + lateinit var edge9: Node + + fun addEdge(child: Node) { + when (numberOfEdges) { + 0 -> edge0 = child + 1 -> edge1 = child + 2 -> edge2 = child + 3 -> edge3 = child + 4 -> edge4 = child + 5 -> edge5 = child + 6 -> edge6 = child + 7 -> edge7 = child + 8 -> edge8 = child + 9 -> edge9 = child + else -> error("Too many edges") + } + ++numberOfEdges + } + + fun getEdges(): List { + val result = mutableListOf() + if (numberOfEdges > 0) result += edge0 + if (numberOfEdges > 1) result += edge1 + if (numberOfEdges > 2) result += edge2 + if (numberOfEdges > 3) result += edge3 + if (numberOfEdges > 4) result += edge4 + if (numberOfEdges > 5) result += edge5 + if (numberOfEdges > 6) result += edge6 + if (numberOfEdges > 7) result += edge7 + if (numberOfEdges > 8) result += edge8 + if (numberOfEdges > 9) result += edge9 + return result + } +} + +class Graph(val nodes: List, val roots: List) + +fun min(x: Int, y: Int) = if (x < y) x else y +fun max(x: Int, y: Int) = if (x > y) x else y + +val random = Random(42) + +fun generate(condensationSize: Int, branchingFactor: Int, swellingFactor: Int): Graph { + var id = 0 + val nodes = mutableListOf() + + fun genDAG(n: Int): Node { + val node = Node(id++) + nodes += node + if (n == 1) return node + val numberOfChildren = random.next(1, min(n - 1, branchingFactor)) + val used = BooleanArray(n) + val points = IntArray(numberOfChildren + 1) + points[0] = 0 + points[numberOfChildren] = n - 1 + used[0] = true + used[n - 1] = true + for (i in 1 until numberOfChildren) { + var p: Int + do { + p = random.next(1, n - 1) + } while (used[p]) + used[p] = true + points[i] = p + } + points.sort() + for (i in 1..numberOfChildren) { + val childSize = points[i] - points[i - 1] + val child = genDAG(childSize) + if (random.next(2) == 0) + node.addEdge(child) + else + child.addEdge(node) + } + return node + } + + genDAG(condensationSize) + + val numberOfEnters = IntArray(condensationSize) + for (node in nodes) + for (edge in node.getEdges()) + ++numberOfEnters[edge.id] + val roots = nodes.filter { numberOfEnters[it.id] == 0 } + for (i in 0 until condensationSize) { + val node = nodes[i] + val componentSize = random.next(1, swellingFactor) + if (componentSize == 1 && random.next(2) == 0) + continue + val component = Array(componentSize) { + if (it == 0) node else Node(id++).also { nodes += it } + } + for (j in 0 until componentSize) + component[j].addEdge(component[(j - 1 + componentSize) % componentSize]) + val numberOfAdditionalEdges = random.next((componentSize + 1) / 2) + for (j in 0 until numberOfAdditionalEdges) + component[random.next(componentSize)].addEdge(component[random.next(componentSize)]) + } + + return Graph(nodes, roots) +} + +fun freezeOneGraph() { + val graph = generate(100, 5, 20) + graph.roots.forEach { it.freeze() } + for (node in graph.nodes) + assert (node.isFrozen, { "All nodes should be frozen" }) +} + +@Test fun runTest() { + for (i in 0..1000) { + freezeOneGraph() + } + println("OK") +} \ No newline at end of file