org.gradle.integtests.fixtures.BuildOperationTreeQueries.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.9.1 API redistribution.
/*
* Copyright 2020 the original author or authors.
*
* 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.
*/
package org.gradle.integtests.fixtures
import org.gradle.api.Action
import org.gradle.api.specs.Spec
import org.gradle.api.specs.Specs
import org.gradle.internal.operations.BuildOperationType
import org.gradle.internal.operations.BuildOperationTypes
import org.gradle.internal.operations.trace.BuildOperationRecord
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.regex.Pattern
abstract class BuildOperationTreeQueries {
abstract List getRoots()
abstract > BuildOperationRecord root(Class type, Spec super BuildOperationRecord> predicate = Specs.satisfyAll())
abstract > BuildOperationRecord first(Class type, Spec super BuildOperationRecord> predicate = Specs.satisfyAll())
abstract > boolean isType(BuildOperationRecord record, Class type)
abstract > List all(Class type, Spec super BuildOperationRecord> predicate = Specs.satisfyAll())
@SuppressWarnings("GrUnnecessaryPublicModifier")
public > void none(Class type, Spec super BuildOperationRecord> predicate = Specs.satisfyAll()) {
assert all(type, predicate).isEmpty()
}
@SuppressWarnings("GrUnnecessaryPublicModifier")
public > BuildOperationRecord only(Class type, Spec super BuildOperationRecord> predicate = Specs.satisfyAll()) {
def records = all(type, predicate)
assert records.size() == 1
return records.first()
}
BuildOperationRecord first(String displayName) {
firstMatchingRegex(Pattern.quote(displayName))
}
BuildOperationRecord firstMatchingRegex(String regex) {
first(Pattern.compile(regex))
}
abstract BuildOperationRecord first(Pattern displayName)
abstract List all();
List all(String displayName) {
return all(Pattern.compile(Pattern.quote(displayName)))
}
abstract List all(Pattern displayName)
BuildOperationRecord only(String displayName) {
return only(Pattern.compile(Pattern.quote(displayName)))
}
abstract BuildOperationRecord only(Pattern displayName)
abstract List parentsOf(BuildOperationRecord child)
void none(String displayName) {
none(Pattern.compile(Pattern.quote(displayName)))
}
abstract void none(Pattern displayName)
Map result(String displayName) {
first(displayName).result
}
String failure(String displayName) {
first(displayName).failure
}
boolean hasOperation(String displayName) {
first(displayName) != null
}
@SuppressWarnings("GrUnnecessaryPublicModifier")
public > boolean hasOperation(Class type) {
first(type) != null
}
@SuppressWarnings(["GrMethodMayBeStatic", "GrUnnecessaryPublicModifier"])
public > List search(BuildOperationRecord parent, Class type, Spec super BuildOperationRecord> predicate = Specs.SATISFIES_ALL) {
def detailsType = BuildOperationTypes.detailsType(type)
Spec typeSpec = {
it.detailsType && detailsType.isAssignableFrom(it.detailsType)
}
search(parent, Specs.intersect(typeSpec, predicate))
}
@SuppressWarnings(["GrMethodMayBeStatic", "GrUnnecessaryPublicModifier"])
public > List children(BuildOperationRecord parent, Class type, Spec super BuildOperationRecord> predicate = Specs.SATISFIES_ALL) {
Spec parentSpec = {
it.parentId == parent.id
}
return search(parent, type, Specs.intersect(parentSpec, predicate))
}
@SuppressWarnings("GrMethodMayBeStatic")
List search(BuildOperationRecord parent, Spec super BuildOperationRecord> predicate = Specs.SATISFIES_ALL) {
def matches = []
parent.children.each {
walk(it) {
if (predicate.isSatisfiedBy(it)) {
matches << it
}
}
}
matches
}
List progress(Class> clazz) {
return all().collect { it.progress(clazz) }.flatten()
}
void walk(Action super BuildOperationRecord> action) {
roots.each { walk(it, action) }
}
@SuppressWarnings("GrMethodMayBeStatic")
void walk(BuildOperationRecord parent, Action super BuildOperationRecord> action) {
def search = new ConcurrentLinkedQueue([parent])
def operation = search.poll()
while (operation != null) {
action.execute(operation)
search.addAll(operation.children)
operation = search.poll()
}
}
void orderedSerialSiblings(BuildOperationRecord... expectedOrder) {
def expectedOrderList = expectedOrder.toList()
assert expectedOrder*.parentId.unique().size() == 1
def startTimeOrdered = expectedOrderList.sort(false) { it.startTime }
assert expectedOrderList == startTimeOrdered
def endTimeOrdered = expectedOrderList.sort(false) { it.endTime }
assert endTimeOrdered == startTimeOrdered
}
private static class TimePoint implements Comparable {
private final boolean end
private final long time
private final BuildOperationRecord operation
TimePoint(BuildOperationRecord operation, long time) {
this(operation, time, false)
}
TimePoint(BuildOperationRecord operation, long time, boolean end) {
this.operation = operation
this.time = time
this.end = end
}
@Override
int compareTo(TimePoint o) {
if (o.time > time) {
return -1
} else if (o.time < time) {
return 1
} else {
if (end && o.end) {
return 0
} else if (end) {
return -1
} else {
return 1
}
}
}
@Override
String toString() {
if (end) {
time + "E"
} else {
time + "S"
}
}
}
/**
* Asserts that no more than maximumConcurrentOperations of the given type of build operation are executing at the same time.
*
* @param type type of build operation
* @param maximumConcurrentOperations maximum concurrent operations allowed
* @param concurrencyExpected whether or not to expect _any_ concurrency
*/
void assertConcurrentOperationsDoNotExceed(Class type, int maximumConcurrentOperations, boolean concurrencyExpected = false) {
int maxConcurrency = getMaximumConcurrentOperations(type)
assert maxConcurrency <= maximumConcurrentOperations
if (concurrencyExpected) {
assert maxConcurrency > 1: "No operations were executed concurrently"
}
}
void assertConcurrentOperationsExecuted(Class type) {
assert getMaximumConcurrentOperations(type) > 1: "No operations were executed concurrently"
}
int getMaximumConcurrentOperations(Class type) {
def highWaterPoint = 0
def allOperations = all(type)
List points = []
allOperations.each {
points.add(new TimePoint(it, it.startTime))
points.add(new TimePoint(it, it.endTime, true))
}
def concurrentOperations = []
points.sort().each {
if (it.end) {
concurrentOperations.remove(it.operation)
} else {
if ((it.operation.endTime - it.operation.startTime) > 0) {
concurrentOperations.add(it.operation)
}
}
if (concurrentOperations.size() > highWaterPoint) {
highWaterPoint = concurrentOperations.size()
}
}
return highWaterPoint
}
/**
* Return a list of operations (possibly empty) that executed concurrently with the given operation.
*/
List getOperationsConcurrentWith(Class type, BuildOperationRecord operation) {
def concurrentOperations = []
all(type).each { candidate ->
if (candidate != operation && candidate.startTime < operation.endTime && candidate.endTime > operation.startTime) {
concurrentOperations << candidate
}
}
return concurrentOperations
}
abstract void debugTree(
Spec super BuildOperationRecord> predicate = Specs.SATISFIES_ALL,
Spec super BuildOperationRecord> progressPredicate = Specs.SATISFIES_ALL
)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy