diff --git a/app/build.gradle b/app/build.gradle index ba892899..17181bed 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -132,9 +132,9 @@ dependencies { androidTestImplementation project(':core-testing') } -apply plugin: 'com.jraska.module.graph' +apply plugin: 'com.jraska.module.graph.assertion' -moduleGraphRules { +modulesGraphAssert { maxHeight = 4 moduleLayersFromTheTop = [":feature", ":lib", ":core"] restrinctInLayerDependencies = [":feature", ":lib"] diff --git a/build.gradle b/build.gradle index 8f3d409f..80c26c48 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,7 @@ buildscript { classpath 'com.google.firebase:firebase-plugins:2.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'io.fabric.tools:gradle:1.27.1' + classpath 'gradle.plugin.modules-graph-assert:plugin:0.1.0' classpath 'gradle.plugin.org.jlleitschuh.gradle:ktlint-gradle:6.1.0' } } diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle deleted file mode 100644 index 4c26ab2c..00000000 --- a/buildSrc/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -buildscript { - repositories { - jcenter() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61" - } -} - -apply plugin: 'kotlin' -apply plugin: 'java-gradle-plugin' - -repositories { - jcenter() -} - -dependencies { - implementation gradleApi() - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61" - - testImplementation 'junit:junit:4.12' -} - -compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} -compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} - -gradlePlugin { - plugins { - moduleGraphAssertions { - id = 'com.jraska.module.graph' - implementationClass = 'com.jraska.module.graph.ModuleGraphAssertionsPlugin' - } - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/GradleDependencyGraphFactory.kt b/buildSrc/src/main/java/com/jraska/github/client/GradleDependencyGraphFactory.kt deleted file mode 100644 index c5ed24ef..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/GradleDependencyGraphFactory.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.jraska.github.client - -import com.jraska.github.client.graph.DependencyGraph -import org.gradle.api.Project -import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency - -object GradleDependencyGraphFactory { - - fun create(project: Project): DependencyGraph { - val dependencies = project.listDependencyPairs() - return DependencyGraph.create(dependencies) - } - - private fun Project.listDependencyPairs(): List> { - val configurationToLook = setOf("implementation", "api") - return rootProject.subprojects - .flatMap { project -> - project.configurations - .filter { configurationToLook.contains(it.name) } - .flatMap { configuration -> - configuration.dependencies.filterIsInstance(DefaultProjectDependency::class.java) - .map { it.dependencyProject } - } - .map { project.moduleDisplayName() to it.moduleDisplayName() } - } - } - - private fun Project.moduleDisplayName(): String { - return displayName.replace("project", "") - .replace("'", "") - .trim() - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/graph/DependencyGraph.kt b/buildSrc/src/main/java/com/jraska/github/client/graph/DependencyGraph.kt deleted file mode 100644 index 42e3fe95..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/graph/DependencyGraph.kt +++ /dev/null @@ -1,111 +0,0 @@ -package com.jraska.github.client.graph - -class DependencyGraph() { - private val nodes = mutableMapOf() - - fun findRoot(): Node { - require(nodes.isNotEmpty()) { "Dependency Tree is empty" } - - val rootCandidates = nodes().toMutableSet() - - nodes().flatMap { it.dependsOn } - .forEach { rootCandidates.remove(it) } - - return rootCandidates.associateBy { heightOf(it.key) } - .maxBy { it.key }!!.value - } - - fun nodes(): Collection = nodes.values - - fun longestPath(): LongestPath { - return longestPath(findRoot().key) - } - - fun longestPath(key: String): LongestPath { - val nodeNames = nodes.getValue(key) - .longestPath() - .map { it.key } - - return LongestPath(nodeNames) - } - - fun height(): Int { - return heightOf(findRoot().key) - } - - fun heightOf(key: String): Int { - return nodes.getValue(key).height() - } - - fun statistics(): GraphStatistics { - val height = height() - val edgesCount = countEdges() - return GraphStatistics( - modulesCount = nodes.size, - edgesCount = edgesCount, - height = height - ) - } - - fun subTree(key: String): DependencyGraph { - val dependencyTree = DependencyGraph() - - addConnections(nodes.getValue(key), dependencyTree) - - return dependencyTree - } - - private fun addConnections(node: Node, into: DependencyGraph) { - node.dependsOn.forEach { - into.addEdge(node.key, it.key) - addConnections(it, into) - } - } - - private fun addEdge(from: String, to: String) { - getOrCreate(from).dependsOn.add(getOrCreate(to)) - } - - private fun countEdges(): Int { - return nodes().flatMap { node -> node.dependsOn }.count() - } - - private fun getOrCreate(key: String): Node { - return nodes[key] ?: Node(key).also { nodes[key] = it } - } - - class Node(val key: String) { - val dependsOn = mutableSetOf() - - private fun isLeaf() = dependsOn.isEmpty() - - fun height(): Int { - if (isLeaf()) { - return 0 - } else { - return 1 + dependsOn.map { it.height() }.max()!! - } - } - - internal fun longestPath(): List { - if (isLeaf()) { - return listOf(this) - } else { - val path = mutableListOf(this) - - val maxHeightNode = dependsOn.maxBy { it.height() }!! - path.addAll(maxHeightNode.longestPath()) - - return path - } - } - } - - companion object { - fun create(dependencies: List>): DependencyGraph { - val graph = DependencyGraph() - dependencies.forEach { graph.addEdge(it.first, it.second) } - return graph - } - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/graph/GraphStatistics.kt b/buildSrc/src/main/java/com/jraska/github/client/graph/GraphStatistics.kt deleted file mode 100644 index 04003937..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/graph/GraphStatistics.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.jraska.github.client.graph - -data class GraphStatistics( - val modulesCount: Int, - val edgesCount: Int, - val height: Int -) diff --git a/buildSrc/src/main/java/com/jraska/github/client/graph/GraphvizWriter.kt b/buildSrc/src/main/java/com/jraska/github/client/graph/GraphvizWriter.kt deleted file mode 100644 index 4344a20c..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/graph/GraphvizWriter.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.jraska.github.client.graph - -object GraphvizWriter { - fun toGraphviz(dependencyGraph: DependencyGraph, groups: Set = emptySet()): String { - - val longestPathConnections = dependencyGraph.longestPath() - .nodeNames.zipWithNext() - .toSet() - - val stringBuilder = StringBuilder() - - stringBuilder.append("digraph G {\n") - - if(groups.isNotEmpty()) { - stringBuilder.append("ranksep = 1.5\n") - } - groups.forEach { - stringBuilder.append(generateGroup(dependencyGraph, it)) - } - - dependencyGraph.nodes().flatMap { node -> node.dependsOn.map { node.key to it.key } } - .forEach { connection -> - stringBuilder.append("\"${connection.first}\"") - .append(" -> ") - .append("\"${connection.second}\"") - - if (longestPathConnections.contains(connection)) { - stringBuilder.append(" [color=red style=bold]") - } - - stringBuilder.append("\n") - } - - stringBuilder.append("}") - - return stringBuilder.toString() - } - - private fun generateGroup(dependencyGraph: DependencyGraph, groupName: String): String { - val builder = StringBuilder() - .append("subgraph cluster_").append(groupName.replace(":", "")).appendln("{") - .appendln("style = filled;") - .appendln("color = lightgrey;") - .appendln("node[style = filled, color = white];") - .append("label = \"").append(groupName).appendln("\"") - - dependencyGraph.nodes().filter { it.key.startsWith(groupName) }.forEach { - builder.append("\"").append(it.key).appendln("\"") - } - - return builder.appendln("}") - .appendln() - .toString() - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/graph/KotlinCodeWriter.kt b/buildSrc/src/main/java/com/jraska/github/client/graph/KotlinCodeWriter.kt deleted file mode 100644 index 69194eb9..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/graph/KotlinCodeWriter.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.jraska.github.client.graph - -object KotlinCodeWriter { - const val SPACING = " " - - fun toKotlinCode(graph: DependencyGraph): String { - val pairs = graph.nodes().flatMap { node -> - node.dependsOn.map { node.key to it.key } - }.joinToString( - separator = ",\n", - prefix = "listOf(\n", - postfix = "\n)", - transform = { " \"${it.first}\" to \"${it.second}\"" }) - - return pairs - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/graph/LongestPath.kt b/buildSrc/src/main/java/com/jraska/github/client/graph/LongestPath.kt deleted file mode 100644 index 3adbcdf2..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/graph/LongestPath.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.jraska.github.client.graph - -class LongestPath( - val nodeNames: List -) { - fun pathString(): String { - return nodeNames.joinToString(" -> ") - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertLayersOrderTask.kt b/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertLayersOrderTask.kt deleted file mode 100644 index 49504034..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertLayersOrderTask.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.jraska.github.client.tasks - -import com.jraska.github.client.GradleDependencyGraphFactory -import com.jraska.github.client.graph.DependencyGraph -import org.gradle.api.DefaultTask -import org.gradle.api.GradleException -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction - -open class AssertLayersOrderTask : DefaultTask() { - @Input - lateinit var layersFromTheTop: Array - - @TaskAction - fun run() { - val modulesTree = GradleDependencyGraphFactory.create(project) - - verifyAllLayersHaveModule(modulesTree) - - val againstLayerDependencies = modulesTree.nodes() - .flatMap { parent -> parent.dependsOn.map { dependency -> parent to dependency } } - .filter { isRestrictedDependency(it) } - - if (againstLayerDependencies.isNotEmpty()) { - throw GradleException(buildErrorMessage(againstLayerDependencies)) - } - } - - private fun buildErrorMessage(againstLayerDependencies: List>): String { - val errorsMessage = againstLayerDependencies.joinToString("\n") { " Module '${it.first.key}' cannot depend on '${it.second.key}'." } - - return "Dependencies against direction of layers '${layersDependencyString()}' are not allowed. The violating dependencies are: \n$errorsMessage" - } - - private fun layersDependencyString(): String { - return layersFromTheTop.joinToString(" -> ") // for example: ":feature -> :lib -> :core" - } - - private fun verifyAllLayersHaveModule(modulesTree: DependencyGraph) { - val nodes = modulesTree.nodes() - - for (layerPrefix in layersFromTheTop) { - nodes.find { it.key.startsWith(layerPrefix) } ?: throw GradleException("There is no module, which belongs to layer '$layerPrefix'") - } - } - - private fun isRestrictedDependency(dependency: Pair): Boolean { - val higherLayerIndex = layerIndex(dependency.first.key) ?: return false - val lowerLayerIndex = layerIndex(dependency.second.key) ?: return false - - return higherLayerIndex > lowerLayerIndex - } - - private fun layerIndex(moduleName: String): Int? { - for ((index, layerPrefix) in layersFromTheTop.withIndex()) { - if (moduleName.startsWith(layerPrefix)) { - return index - } - } - - return null - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertModuleTreeHeightTask.kt b/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertModuleTreeHeightTask.kt deleted file mode 100644 index a74e05b6..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertModuleTreeHeightTask.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.jraska.github.client.tasks - -import com.jraska.github.client.GradleDependencyGraphFactory -import org.gradle.api.DefaultTask -import org.gradle.api.GradleException -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction - -open class AssertModuleTreeHeightTask : DefaultTask() { - @Input - lateinit var moduleName: String - - @Input - var maxHeight: Int = 0 - - @TaskAction - fun run() { - val modulesTree = GradleDependencyGraphFactory.create(project) - - val height = modulesTree.heightOf(moduleName) - if (height > maxHeight) { - val longestPath = modulesTree.longestPath(moduleName) - throw GradleException("Module $moduleName is allowed to have maximum height of $maxHeight, but has $height, problematic dependencies: ${longestPath.pathString()}") - } - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertNoInLayerDependencies.kt b/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertNoInLayerDependencies.kt deleted file mode 100644 index 8c77d492..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/tasks/AssertNoInLayerDependencies.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.jraska.github.client.tasks - -import com.jraska.github.client.GradleDependencyGraphFactory -import com.jraska.github.client.graph.DependencyGraph -import org.gradle.api.DefaultTask -import org.gradle.api.GradleException -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction - -open class AssertNoInLayerDependencies : DefaultTask() { - @Input - lateinit var layerPrefix: String - - @TaskAction - fun run() { - val modulesTree = GradleDependencyGraphFactory.create(project) - - val inLayerDependencies = modulesTree.nodes() - .filter { it.key.startsWith(layerPrefix) } - .ifEmpty { throw GradleException("There are no modules with prefix $layerPrefix") } - .flatMap { parent -> parent.dependsOn.map { dependency -> parent to dependency } } - .filter { it.second.key.startsWith(layerPrefix) } - - if (inLayerDependencies.isNotEmpty()) { - throw GradleException(buildErrorMessage(inLayerDependencies)) - } - } - - private fun buildErrorMessage(inLayerDependencies: List>): String { - val errorsMessage = inLayerDependencies.joinToString("\n") { " Module '${it.first.key}' cannot depend on '${it.second.key}'." } - val suggestion = "Try using interface modules to share break this dependency" - - return "Dependencies within '$layerPrefix' are not allowed. The not allowed dependencies are: \n$errorsMessage\n$suggestion" - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/tasks/GenerateModulesGraphTask.kt b/buildSrc/src/main/java/com/jraska/github/client/tasks/GenerateModulesGraphTask.kt deleted file mode 100644 index b08ff21a..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/tasks/GenerateModulesGraphTask.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.jraska.github.client.tasks - -import com.jraska.github.client.GradleDependencyGraphFactory -import com.jraska.github.client.graph.GraphvizWriter -import com.jraska.github.client.graph.KotlinCodeWriter -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction - -open class GenerateModulesGraphTask : DefaultTask() { - @Input - var layers: Array = emptyArray() - - @TaskAction - fun run() { - val allModulesTree = GradleDependencyGraphFactory.create(project) - - println(allModulesTree.statistics()) - println(GraphvizWriter.toGraphviz(allModulesTree, layers.toSet())) - } -} diff --git a/buildSrc/src/main/java/com/jraska/github/client/tasks/GenerateOneModuleGraphTask.kt b/buildSrc/src/main/java/com/jraska/github/client/tasks/GenerateOneModuleGraphTask.kt deleted file mode 100644 index d5fb555d..00000000 --- a/buildSrc/src/main/java/com/jraska/github/client/tasks/GenerateOneModuleGraphTask.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.jraska.github.client.tasks - -import com.jraska.github.client.GradleDependencyGraphFactory -import com.jraska.github.client.graph.GraphvizWriter -import org.gradle.api.DefaultTask -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.TaskAction - -open class GenerateOneModuleGraphTask : DefaultTask() { - @Input - lateinit var moduleName: String - - @TaskAction - fun run() { - val allModulesTree = GradleDependencyGraphFactory.create(project) - val moduleTree = allModulesTree.subTree(moduleName) - - println(moduleTree.statistics()) - println(GraphvizWriter.toGraphviz(moduleTree)) - } -} diff --git a/buildSrc/src/main/java/com/jraska/module/graph/Api.kt b/buildSrc/src/main/java/com/jraska/module/graph/Api.kt deleted file mode 100644 index 8024c81b..00000000 --- a/buildSrc/src/main/java/com/jraska/module/graph/Api.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.jraska.module.graph - -object Api { - object Tasks { - const val GENERATE_GRAPHVIZ = "generateModulesGrapvizText" - - const val ASSERT_ALL = "assertModulesGraph" - const val ASSERT_MAX_HEIGHT = "assertMaxHeight" - const val ASSERT_LAYER_ORDER = "assertModuleLayersOrder" - const val ASSERT_NO_IN_LAYER_PREFIX = "assertNoDependenciesWithin" - } - - const val CHECK_TASK = "check" - - const val EXTENSION_ROOT = "moduleGraphRules" -} - diff --git a/buildSrc/src/main/java/com/jraska/module/graph/GraphRulesExtension.kt b/buildSrc/src/main/java/com/jraska/module/graph/GraphRulesExtension.kt deleted file mode 100644 index 8c7200b1..00000000 --- a/buildSrc/src/main/java/com/jraska/module/graph/GraphRulesExtension.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.jraska.module.graph - -open class GraphRulesExtension { - var appModuleName = ":app" - var maxHeight: Int = 0 - var moduleLayersFromTheTop = emptyArray() - var restrinctInLayerDependencies = emptyArray() -} diff --git a/buildSrc/src/main/java/com/jraska/module/graph/ModuleGraphAssertionsPlugin.kt b/buildSrc/src/main/java/com/jraska/module/graph/ModuleGraphAssertionsPlugin.kt deleted file mode 100644 index 0565083d..00000000 --- a/buildSrc/src/main/java/com/jraska/module/graph/ModuleGraphAssertionsPlugin.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.jraska.module.graph - -import com.jraska.github.client.tasks.AssertLayersOrderTask -import com.jraska.github.client.tasks.AssertModuleTreeHeightTask -import com.jraska.github.client.tasks.AssertNoInLayerDependencies -import com.jraska.github.client.tasks.GenerateModulesGraphTask -import com.jraska.module.graph.Api.Tasks -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.language.base.plugins.LifecycleBasePlugin.VERIFICATION_GROUP -import java.util.Locale - -@Suppress("unused") // Used as plugin -class ModuleGraphAssertionsPlugin : Plugin { - - override fun apply(project: Project) { - val graphRules = project.extensions.create(GraphRulesExtension::class.java, Api.EXTENSION_ROOT, GraphRulesExtension::class.java) - - project.afterEvaluate { - addModulesAssertions(project, graphRules) - } - } - - private fun addModulesAssertions(project: Project, graphRules: GraphRulesExtension) { - project.addModuleGraphGeneration() - - val allAssertionsTask = project.tasks.create(Tasks.ASSERT_ALL) - allAssertionsTask.group = VERIFICATION_GROUP - project.tasks.find { it.name == Api.CHECK_TASK }?.dependsOn(allAssertionsTask) - - project.addMaxHeightTasks(graphRules).forEach { allAssertionsTask.dependsOn(it) } - project.addModuleLayersTasks(graphRules).forEach { allAssertionsTask.dependsOn(it) } - project.addInLayerDependencyTasks(graphRules).forEach { allAssertionsTask.dependsOn(it) } - } - - private fun Project.addModuleGraphGeneration() { - tasks.create(Tasks.GENERATE_GRAPHVIZ, GenerateModulesGraphTask::class.java) - } - - private fun Project.addMaxHeightTasks(graphRules: GraphRulesExtension): List { - if (graphRules.maxHeight <= 0) { - return emptyList() - } - - val task = tasks.create(Tasks.ASSERT_MAX_HEIGHT, AssertModuleTreeHeightTask::class.java) - task.maxHeight = graphRules.maxHeight - task.moduleName = graphRules.appModuleName - task.group = VERIFICATION_GROUP - - return listOf(task) - } - - private fun Project.addModuleLayersTasks(graphRules: GraphRulesExtension): List { - if (graphRules.moduleLayersFromTheTop.isEmpty()) { - return emptyList() - } - - val task = tasks.create(Tasks.ASSERT_LAYER_ORDER, AssertLayersOrderTask::class.java) - task.layersFromTheTop = graphRules.moduleLayersFromTheTop - task.group = VERIFICATION_GROUP - - return listOf(task) - } - - private fun Project.addInLayerDependencyTasks(graphRules: GraphRulesExtension): List { - return graphRules.restrinctInLayerDependencies.map { layerPrefix -> - val taskNameSuffix = layerPrefix.replace(":", "").capitalizeFirst() - val task = tasks.create("${Tasks.ASSERT_NO_IN_LAYER_PREFIX}$taskNameSuffix", AssertNoInLayerDependencies::class.java) - task.layerPrefix = layerPrefix - task.group = VERIFICATION_GROUP - - return@map task - } - } - - private fun String.capitalizeFirst(): String { - return this.substring(0, 1).toUpperCase(Locale.US).plus(this.substring(1)) - } -} diff --git a/buildSrc/src/test/java/com/jraska/github/client/graph/DependencyGraphTest.kt b/buildSrc/src/test/java/com/jraska/github/client/graph/DependencyGraphTest.kt deleted file mode 100644 index 93836aa8..00000000 --- a/buildSrc/src/test/java/com/jraska/github/client/graph/DependencyGraphTest.kt +++ /dev/null @@ -1,127 +0,0 @@ -package com.jraska.github.client.graph - -import org.junit.Test - -class DependencyGraphTest { - @Test - fun correctHeightIsMaintained() { - val dependencyTree = DependencyGraph.create( - listOf( - "app" to "feature", - "app" to "lib", - "feature" to "lib", - "lib" to "core" - ) - ) - - assert(dependencyTree.heightOf("app") == 3) - } - - @Test - fun findsProperLongestPath() { - val dependencyTree = DependencyGraph.create( - listOf( - "app" to "feature", - "app" to "lib", - "app" to "core", - "feature" to "lib", - "lib" to "core" - ) - ) - - assert(dependencyTree.longestPath("app").nodeNames == listOf("app", "feature", "lib", "core")) - } - - @Test - fun findsProperRoot() { - val dependencyTree = DependencyGraph.create( - listOf( - "feature" to "lib", - "lib" to "core", - "app" to "feature", - "app" to "lib", - "app" to "core" - ) - ) - - assert(dependencyTree.findRoot().key == "app") - } - - @Test - fun createSubtreeProperly() { - val dependencyTree = DependencyGraph.create( - listOf( - "feature" to "lib", - "lib" to "core", - "app" to "feature", - "feature" to "core", - "app" to "core" - ) - ) - - val subTree = dependencyTree.subTree("feature") - - assert(subTree.findRoot().key == "feature") - assert(subTree.heightOf("feature") == 2) - assert(subTree.longestPath("feature").nodeNames == listOf("feature", "lib", "core")) - } - - @Test - fun createCountStatisticsWell() { - val dependencyTree = DependencyGraph.create( - listOf( - ":app" to ":core", - ":app" to ":core-android", - ":app" to ":navigation", - ":app" to ":lib:navigation-deeplink", - ":app" to ":lib:identity", - ":app" to ":lib:dynamic-features", - ":app" to ":lib:network-status", - ":app" to ":feature:push", - ":app" to ":feature:users", - ":app" to ":feature:settings_entrance", - ":app" to ":feature:about_entrance", - ":app" to ":feature:shortcuts", - ":core-android" to ":core", - ":lib:navigation-deeplink" to ":navigation", - ":lib:navigation-deeplink" to ":core", - ":lib:identity" to ":core", - ":lib:dynamic-features" to ":core", - ":lib:dynamic-features" to ":core-android", - ":lib:network-status" to ":core", - ":lib:network-status" to ":core-android", - ":feature:push" to ":core", - ":feature:push" to ":core-android", - ":feature:push" to ":lib:identity", - ":feature:users" to ":core", - ":feature:users" to ":core-android", - ":feature:users" to ":navigation", - ":feature:settings_entrance" to ":core", - ":feature:settings_entrance" to ":core-android", - ":feature:settings_entrance" to ":lib:dynamic-features", - ":feature:about_entrance" to ":core", - ":feature:about_entrance" to ":core-android", - ":feature:about_entrance" to ":lib:dynamic-features", - ":feature:shortcuts" to ":core", - ":feature:shortcuts" to ":core-android", - ":core-testing" to ":core", - ":feature:about" to ":app", - ":feature:about" to ":core", - ":feature:about" to ":core-android", - ":feature:about" to ":navigation", - ":feature:about" to ":lib:identity", - ":feature:about" to ":lib:dynamic-features", - ":feature:settings" to ":core", - ":feature:settings" to ":core-android", - ":feature:settings" to ":lib:dynamic-features", - ":feature:settings" to ":app" - ) - ) - - val statistics = dependencyTree.statistics() - - assert(statistics.height == 5) - assert(statistics.modulesCount == 16) - assert(statistics.edgesCount == 45) - } -}