Skip to content

Commit

Permalink
Add parallel tests and avoid cross-project mutation
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielThomas committed Jun 23, 2020
1 parent a92b5a8 commit 744df81
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 36 deletions.
Expand Up @@ -59,7 +59,7 @@ class AlignRulesMultiprojectSpec extends IntegrationSpec {
}

@Unroll
def 'align rules do not interfere with a multiproject that produces the jars being aligned'() {
def 'align rules do not interfere with a multiproject that produces the jars being aligned (coreAlignment #coreAlignment, parallel #parallel)'() {
rulesJsonFile << '''\
{
"deny": [], "reject": [], "substitute": [], "replace": [],
Expand Down Expand Up @@ -104,17 +104,25 @@ class AlignRulesMultiprojectSpec extends IntegrationSpec {
'''.stripIndent()
when:
def results = runTasksSuccessfully(':b:dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment")
def tasks = [':b:dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment"]
if (parallel) {
tasks += "--parallel"
}
def results = runTasksSuccessfully(*tasks)
then:
results.standardOutput.contains('\\--- project :a\n')
where:
coreAlignment << [false, true]
coreAlignment | parallel
false | false
false | true
true | false
true | true
}
@Unroll
def 'cycle like behavior'() {
def 'cycle like behavior (coreAlignment #coreAlignment, parallel #parallel)'() {
rulesJsonFile << '''\
{
"deny": [], "reject": [], "substitute": [], "replace": [],
Expand Down Expand Up @@ -143,17 +151,25 @@ class AlignRulesMultiprojectSpec extends IntegrationSpec {
'''.stripIndent()
when:
def results = runTasksSuccessfully(':a:dependencies', ':b:dependencies', 'assemble', "-Dnebula.features.coreAlignmentSupport=$coreAlignment")
def tasks = [':a:dependencies', ':b:dependencies', 'assemble', "-Dnebula.features.coreAlignmentSupport=$coreAlignment"]
if (parallel) {
tasks += "--parallel"
}
runTasksSuccessfully(*tasks)
then:
noExceptionThrown()
where:
coreAlignment << [false, true]
coreAlignment | parallel
false | false
false | true
true | false
true | true
}
@Unroll
def 'can align project dependencies'() {
def 'can align project dependencies (coreAlignment #coreAlignment, parallel #parallel)'() {
def graph = new DependencyGraphBuilder()
.addModule('other.nebula:a:0.42.0')
.addModule('other.nebula:a:1.0.0')
Expand Down Expand Up @@ -205,19 +221,27 @@ class AlignRulesMultiprojectSpec extends IntegrationSpec {
""".stripIndent()
when:
def result = runTasksSuccessfully(':a:dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment")
def tasks = [':a:dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment"]
if (parallel) {
tasks += "--parallel"
}
def result = runTasksSuccessfully(*tasks)
then:
result.standardOutput.contains '+--- other.nebula:a:1.0.0 -> 1.1.0'
result.standardOutput.contains '+--- other.nebula:b:1.1.0'
result.standardOutput.contains '\\--- other.nebula:c:0.42.0'
where:
coreAlignment << [false, true]
coreAlignment | parallel
false | false
false | true
true | false
true | true
}
@Unroll
def 'root project can depend on subprojects'() {
def 'root project can depend on subprojects (coreAlignment #coreAlignment, parallel #parallel)'() {
def graph = new DependencyGraphBuilder()
.addModule('other.nebula:a:0.42.0')
.addModule('other.nebula:a:1.0.0')
Expand Down Expand Up @@ -276,14 +300,22 @@ class AlignRulesMultiprojectSpec extends IntegrationSpec {
""".stripIndent()
when:
def result = runTasksSuccessfully(':a:dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment")
def tasks = [':a:dependencies', '--configuration', 'compileClasspath', "-Dnebula.features.coreAlignmentSupport=$coreAlignment"]
if (parallel) {
tasks += "--parallel"
}
def result = runTasksSuccessfully(*tasks)
then:
result.standardOutput.contains '+--- other.nebula:a:1.0.0 -> 1.1.0'
result.standardOutput.contains '+--- other.nebula:b:1.1.0'
result.standardOutput.contains '\\--- other.nebula:c:0.42.0'
where:
coreAlignment << [false, true]
coreAlignment | parallel
false | false
false | true
true | false
true | true
}
}
54 changes: 30 additions & 24 deletions src/main/kotlin/nebula/plugin/resolutionrules/plugin.kt
Expand Up @@ -28,6 +28,7 @@ import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
import java.io.File
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import javax.inject.Inject
Expand Down Expand Up @@ -114,38 +115,43 @@ open class NebulaResolutionRulesExtension @Inject constructor(private val projec
var optional = ArrayList<String>()
var exclude = ArrayList<String>()

private val rulesByFile by lazy {
val rootProject = project.rootProject
check(project == rootProject) { "This should only be called on the root project extension" }
val configuration = rootProject.configurations.getByName(RESOLUTION_RULES_CONFIG_NAME)
val files = rootProject.copyConfiguration(configuration).resolve()
val mapper = objectMapper()
val rules = LinkedHashMap<String, RuleSet>()
for (file in files) {
val filename = file.name
logger.debug("nebula.resolution-rules uses: $filename")
if (filename.endsWith(ResolutionRulesPlugin.JSON_EXT)) {
rules.putRules(mapper.parseJsonFile(file))
} else if (filename.endsWith(ResolutionRulesPlugin.JAR_EXT) || filename.endsWith(ResolutionRulesPlugin.ZIP_EXT)) {
logger.info("nebula.resolution-rules is using ruleset: $filename")
ZipFile(file).use { zip ->
val entries = zip.entries()
while (entries.hasMoreElements()) {
val entry = entries.nextElement()
if (entry.name.endsWith(ResolutionRulesPlugin.JSON_EXT)) {
rules.putRules(mapper.parseJsonStream(zip, entry))
private val rulesByFile = ConcurrentHashMap<Boolean, Map<String,RuleSet>>(1)

private fun rulesByFile(resolvingProject: Project): Map<String, RuleSet> {
check(project == project.rootProject) { "This should only be called on the root project extension" }
return rulesByFile.computeIfAbsent(true) {
val configuration = project.configurations.getByName(RESOLUTION_RULES_CONFIG_NAME)
val detachedConfiguration = resolvingProject.configurations.detachedConfiguration(*configuration.dependencies.toTypedArray())
val files = detachedConfiguration.resolve()
val mapper = objectMapper()
val rules = LinkedHashMap<String, RuleSet>()
for (file in files) {
val filename = file.name
logger.debug("nebula.resolution-rules uses: $filename")
if (filename.endsWith(ResolutionRulesPlugin.JSON_EXT)) {
rules.putRules(mapper.parseJsonFile(file))
} else if (filename.endsWith(ResolutionRulesPlugin.JAR_EXT) || filename.endsWith(ResolutionRulesPlugin.ZIP_EXT)) {
logger.info("nebula.resolution-rules is using ruleset: $filename")
ZipFile(file).use { zip ->
val entries = zip.entries()
while (entries.hasMoreElements()) {
val entry = entries.nextElement()
if (entry.name.endsWith(ResolutionRulesPlugin.JSON_EXT)) {
rules.putRules(mapper.parseJsonStream(zip, entry))
}
}
}
} else {
logger.debug("Unsupported rules file extension for $file")
}
} else {
logger.debug("Unsupported rules file extension for $file")
}
rules
}
rules
}

fun ruleSet(): RuleSet {
val rulesByFile = project.rootProject.extensions.getByType(NebulaResolutionRulesExtension::class.java).rulesByFile
val extension = project.rootProject.extensions.getByType(NebulaResolutionRulesExtension::class.java)
val rulesByFile = extension.rulesByFile(project)
return rulesByFile.filterKeys { ruleSet ->
when {
ruleSet.startsWith(ResolutionRulesPlugin.OPTIONAL_PREFIX) -> {
Expand Down

0 comments on commit 744df81

Please sign in to comment.