-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce a
HookOrder
annotation to order hooks (#521)
- Loading branch information
Showing
4 changed files
with
198 additions
and
2 deletions.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
src/main/java/org/jenkins/tools/test/model/hook/HookOrder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package org.jenkins.tools.test.model.hook; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Relative order to sort hooks in. | ||
* The higher the number the higher priority the hook has. | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.TYPE) | ||
public @interface HookOrder { | ||
|
||
int order() default 0; | ||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/org/jenkins/tools/test/model/hook/HookOrderComparator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package org.jenkins.tools.test.model.hook; | ||
|
||
import java.io.Serializable; | ||
import java.util.Comparator; | ||
|
||
/** | ||
* Comparator that will order first based on the {@link HookOrder}. | ||
* Objects whose classes are missing the annotation order will be treated as if they have the default order. | ||
* Where two objects have the same order sorting will occur based on the classname. | ||
* This {@link Comparator} is not {@code null} safe. | ||
*/ | ||
public class HookOrderComparator implements Comparator<Object>, Serializable { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
@Override | ||
public int compare(Object left, Object right) { | ||
int leftOrder = getHookOrder(left); | ||
int rightOrder = getHookOrder(right); | ||
if (leftOrder < rightOrder) { | ||
return 1; | ||
} | ||
if (leftOrder > rightOrder) { | ||
return -1; | ||
} | ||
return left.getClass().getName().compareTo(right.getClass().getName()); | ||
} | ||
|
||
private static int getHookOrder(Object obj) { | ||
HookOrder hookOrder = obj.getClass().getDeclaredAnnotation(HookOrder.class); | ||
return hookOrder == null ? 0 : hookOrder.order(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
src/test/java/org/jenkins/tools/test/model/hook/HookOrderComparatorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package org.jenkins.tools.test.model.hook; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.comparator.ComparatorMatcherBuilder.comparedBy; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import org.hamcrest.collection.IsIterableContainingInOrder; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class HookOrderComparatorTest { | ||
|
||
@Test | ||
void testIndividual() { | ||
HookOrderComparator hookOrderComparator = new HookOrderComparator(); | ||
|
||
assertThat(new AlphaNoPriority(), comparedBy(hookOrderComparator).lessThan(new AlphaLowPriority())); | ||
assertThat(new AlphaNoPriority(), comparedBy(hookOrderComparator).greaterThan(new AlphaHighPriority())); | ||
|
||
assertThat(new AlphaNoPriority(), comparedBy(hookOrderComparator).lessThan(new BetaNoPriority())); | ||
assertThat(new AlphaNoPriority(), comparedBy(hookOrderComparator).lessThan(new GammaLowPriority())); | ||
|
||
assertThat(new AlphaNoPriority(), comparedBy(hookOrderComparator).comparesEqualTo(new AlphaNoPriority())); | ||
} | ||
|
||
@Test | ||
void testOrdering() { | ||
HookOrderComparator hookOrderComparator = new HookOrderComparator(); | ||
List<?> priorityList; | ||
|
||
// annotation only | ||
priorityList = toSortedList( | ||
new AlphaLowPriority(), | ||
new AlphaHighPriority(), | ||
new BetaLowPriority(), | ||
new BetaHighPriority(), | ||
new GammaLowPriority(), | ||
new GammaHighPriority()); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains( | ||
new GammaHighPriority(), | ||
new BetaHighPriority(), | ||
new AlphaHighPriority(), | ||
new AlphaLowPriority(), | ||
new BetaLowPriority(), | ||
new GammaLowPriority())); | ||
// sort is stable | ||
priorityList.sort(hookOrderComparator); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains( | ||
new GammaHighPriority(), | ||
new BetaHighPriority(), | ||
new AlphaHighPriority(), | ||
new AlphaLowPriority(), | ||
new BetaLowPriority(), | ||
new GammaLowPriority())); | ||
|
||
// no annotation - classname only | ||
priorityList = toSortedList(new GammaNoPriority(), new AlphaNoPriority(), new BetaNoPriority()); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains( | ||
new AlphaNoPriority(), new BetaNoPriority(), new GammaNoPriority())); | ||
// sort is stable | ||
priorityList.sort(hookOrderComparator); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains( | ||
new AlphaNoPriority(), new BetaNoPriority(), new GammaNoPriority())); | ||
|
||
// mix of annotation and no annotation | ||
priorityList = toSortedList(new AlphaHighPriority(), new BetaLowPriority(), new GammaNoPriority()); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains( | ||
new AlphaHighPriority(), new GammaNoPriority(), new BetaLowPriority())); | ||
// sort is stable | ||
priorityList.sort(hookOrderComparator); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains( | ||
new AlphaHighPriority(), new GammaNoPriority(), new BetaLowPriority())); | ||
|
||
// With Colliding annotations | ||
priorityList = toSortedList(new GammaHighPriority(), new DeltaCollidingHighPriority()); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains(new DeltaCollidingHighPriority(), new GammaHighPriority())); | ||
// sort is stable | ||
priorityList.sort(hookOrderComparator); | ||
assertThat( | ||
priorityList, | ||
IsIterableContainingInOrder.contains(new DeltaCollidingHighPriority(), new GammaHighPriority())); | ||
} | ||
|
||
static class Base { | ||
@Override | ||
public int hashCode() { | ||
return this.getClass().hashCode(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object arg0) { | ||
return this.getClass().equals(arg0.getClass()); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.getClass().getSimpleName(); | ||
} | ||
} | ||
|
||
private List<Object> toSortedList(Object... objects) { | ||
List<Object> l = new ArrayList<>(List.of(objects)); | ||
l.sort(new HookOrderComparator()); | ||
return l; | ||
} | ||
|
||
@HookOrder(order = -10) | ||
static class AlphaLowPriority extends Base {} | ||
|
||
static class AlphaNoPriority extends Base {} | ||
|
||
@HookOrder(order = 10) | ||
static class AlphaHighPriority extends Base {} | ||
|
||
@HookOrder(order = -20) | ||
static class BetaLowPriority extends Base {} | ||
|
||
static class BetaNoPriority extends Base {} | ||
|
||
@HookOrder(order = 20) | ||
static class BetaHighPriority extends Base {} | ||
|
||
@HookOrder(order = -30) | ||
static class GammaLowPriority extends Base {} | ||
|
||
static class GammaNoPriority extends Base {} | ||
|
||
@HookOrder(order = 30) | ||
static class GammaHighPriority extends Base {} | ||
|
||
@HookOrder(order = 30) | ||
static class DeltaCollidingHighPriority extends Base {} | ||
} |