Skip to content

Commit

Permalink
Add optimized version of orderChildren to AbstractTestDescriptor
Browse files Browse the repository at this point in the history
  • Loading branch information
mpkorstanje committed Jan 31, 2025
1 parent fc69751 commit 00310ee
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
import static java.util.Collections.emptySet;
import static org.apiguardian.api.API.Status.STABLE;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.UnaryOperator;

import org.apiguardian.api.API;
import org.junit.platform.commons.util.Preconditions;
Expand Down Expand Up @@ -147,6 +150,16 @@ public void removeFromHierarchy() {
this.children.clear();
}

@Override
public void orderChildren(UnaryOperator<List<TestDescriptor>> orderer) {
Preconditions.notNull(orderer, "orderer must not be null");
Set<? extends TestDescriptor> orderedChildren = new LinkedHashSet<>(orderer.apply(new ArrayList<>(children)));
boolean unmodified = children.equals(orderedChildren);
Preconditions.condition(unmodified, "orderer may not add or remove test descriptors");
children.clear();
children.addAll(orderedChildren);
}

@Override
public Optional<? extends TestDescriptor> findByUniqueId(UniqueId uniqueId) {
Preconditions.notNull(uniqueId, "UniqueId must not be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

package org.junit.platform.engine.support.descriptor;

import static java.util.Comparator.comparing;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand All @@ -33,14 +32,12 @@
*
* @since 1.0
*/
class AbstractTestDescriptorTests {
class AbstractTestDescriptorTests implements TestDescriptorOrderChildrenTest {

private EngineDescriptor engineDescriptor;
private GroupDescriptor group1;
private GroupDescriptor group11;
private LeafDescriptor leaf111;
private LeafDescriptor leaf11;
private LeafDescriptor leaf12;

@BeforeEach
void initTree() {
Expand All @@ -52,9 +49,9 @@ void initTree() {
group11 = new GroupDescriptor(UniqueId.root("group", "group1-1"));
group1.addChild(group11);

leaf11 = new LeafDescriptor(UniqueId.root("leaf", "leaf1-1"));
var leaf11 = new LeafDescriptor(UniqueId.root("leaf", "leaf1-1"));
group1.addChild(leaf11);
leaf12 = new LeafDescriptor(UniqueId.root("leaf", "leaf1-2"));
var leaf12 = new LeafDescriptor(UniqueId.root("leaf", "leaf1-2"));
group1.addChild(leaf12);

group2.addChild(new LeafDescriptor(UniqueId.root("leaf", "leaf2-1")));
Expand All @@ -63,6 +60,11 @@ void initTree() {
group11.addChild(leaf111);
}

@Override
public TestDescriptor createEmptyTestDescriptor() {
return new GroupDescriptor(UniqueId.root("group", "1"));
}

@Test
void removeRootFromHierarchyFails() {
var e = assertThrows(JUnitException.class, () -> engineDescriptor.removeFromHierarchy());
Expand All @@ -83,61 +85,6 @@ void removeFromHierarchyClearsParentFromAllChildren() {
assertTrue(formerChildren.stream().noneMatch(d -> d.getParent().isPresent()));
}

@Test
void orderChildren() {
group1.orderChildren(children -> {
children.sort(comparing(TestDescriptor::getDisplayName).reversed());
return children;
});
// Makes the compiler happy
List<TestDescriptor> children = new ArrayList<>(group1.getChildren());
assertThat(children).containsExactly(leaf12, leaf11, group11);
}

@Test
void orderChildrenRemovesDescriptor() {
var exception = assertThrows(JUnitException.class, () -> {
group1.orderChildren(children -> {
children.removeFirst();
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
void orderChildrenAddsDescriptor() {
var exception = assertThrows(JUnitException.class, () -> {
group1.orderChildren(children -> {
children.add(new LeafDescriptor(UniqueId.root("leaf", "leaf1-3")));
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
void orderChildrenReplacesDescriptor() {
var exception = assertThrows(JUnitException.class, () -> {
group1.orderChildren(children -> {
children.set(0, new LeafDescriptor(UniqueId.root("leaf", "leaf1-3")));
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
void orderChildrenDuplicatesDescriptor() {
var exception = assertThrows(JUnitException.class, () -> {
group1.orderChildren(children -> {
children.set(1, children.getFirst());
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
void setParentToOtherInstance() {
TestDescriptor newEngine = new EngineDescriptor(UniqueId.forEngine("newEngine"), "newEngine");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.engine.support.descriptor;

import static java.util.Comparator.comparing;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.junit.platform.commons.JUnitException;
import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.UniqueId;

public interface TestDescriptorOrderChildrenTest {

/**
* @return a test descriptor without any children.
*/
TestDescriptor createEmptyTestDescriptor();

default TestDescriptor createTestDescriptorWithChildren() {
var testDescriptor = createEmptyTestDescriptor();
testDescriptor.addChild(new StubTestDescriptor(UniqueId.root("child", "1")));
testDescriptor.addChild(new StubTestDescriptor(UniqueId.root("child", "2")));
testDescriptor.addChild(new StubTestDescriptor(UniqueId.root("child", "3")));
return testDescriptor;
}

@Test
default void orderChildrenInReverseOrder() {
var testDescriptor = createTestDescriptorWithChildren();
var childrenInOriginalOrder = new ArrayList<>(testDescriptor.getChildren());
testDescriptor.orderChildren(children -> {
children.sort(comparing((TestDescriptor o) -> childrenInOriginalOrder.indexOf(o)).reversed());
return children;
});
List<TestDescriptor> children = new ArrayList<>(testDescriptor.getChildren());
assertThat(children).isEqualTo(childrenInOriginalOrder.reversed());
}

@Test
default void orderChildrenInSameOrder() {
var testDescriptor = createTestDescriptorWithChildren();
var childrenInOriginalOrder = new ArrayList<>(testDescriptor.getChildren());
testDescriptor.orderChildren(children -> {
children.sort(comparing(childrenInOriginalOrder::indexOf));
return children;
});
List<TestDescriptor> children = new ArrayList<>(testDescriptor.getChildren());
assertThat(children).isEqualTo(childrenInOriginalOrder);
}

@Test
default void orderChildrenRemovesDescriptor() {
var testDescriptor = createTestDescriptorWithChildren();
var exception = assertThrows(JUnitException.class, () -> {
testDescriptor.orderChildren(children -> {
children.removeFirst();
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
default void orderChildrenAddsDescriptor() {
var testDescriptor = createTestDescriptorWithChildren();
var exception = assertThrows(JUnitException.class, () -> {
testDescriptor.orderChildren(children -> {
children.add(new StubTestDescriptor(UniqueId.root("extra", "extra1")));
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
default void orderChildrenReplacesDescriptor() {
var testDescriptor = createTestDescriptorWithChildren();
var exception = assertThrows(JUnitException.class, () -> {
testDescriptor.orderChildren(children -> {
children.set(0, new StubTestDescriptor(UniqueId.root("replaced", "replaced1")));
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}

@Test
default void orderChildrenDuplicatesDescriptor() {
var testDescriptor = createTestDescriptorWithChildren();
var exception = assertThrows(JUnitException.class, () -> {
testDescriptor.orderChildren(children -> {
children.set(1, children.getFirst());
return children;
});
});
assertThat(exception).hasMessage("orderer may not add or remove test descriptors");
}
}

class StubTestDescriptor extends AbstractTestDescriptor {

StubTestDescriptor(UniqueId uniqueId) {
super(uniqueId, "stub: " + uniqueId);
}

@Override
public Type getType() {
return Type.TEST;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2015-2025 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package org.junit.platform.engine.support.descriptor;

import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;

import org.junit.platform.engine.TestDescriptor;
import org.junit.platform.engine.TestSource;
import org.junit.platform.engine.TestTag;
import org.junit.platform.engine.UniqueId;

class TestDescriptorTest implements TestDescriptorOrderChildrenTest {

@Override
public TestDescriptor createEmptyTestDescriptor() {
return new MinimalTestDescriptorImplementation();
}

private static class MinimalTestDescriptorImplementation implements TestDescriptor {

private final LinkedHashSet<TestDescriptor> children = new LinkedHashSet<>();

@Override
public UniqueId getUniqueId() {
return UniqueId.root("root", "value");
}

@Override
public String getDisplayName() {
return "TestDescriptorImplementation";
}

@Override
public Set<TestTag> getTags() {
return Set.of();
}

@Override
public Optional<TestSource> getSource() {
return Optional.empty();
}

@Override
public Optional<TestDescriptor> getParent() {
return Optional.empty();
}

@Override
public void setParent(TestDescriptor parent) {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public Set<? extends TestDescriptor> getChildren() {
return children;
}

@Override
public void addChild(TestDescriptor descriptor) {
children.add(descriptor);
}

@Override
public void removeChild(TestDescriptor descriptor) {
children.remove(descriptor);
}

@Override
public void removeFromHierarchy() {
throw new UnsupportedOperationException("Not implemented");
}

@Override
public Type getType() {
return Type.CONTAINER;
}

@Override
public Optional<? extends TestDescriptor> findByUniqueId(UniqueId uniqueId) {
throw new UnsupportedOperationException("Not implemented");
}
}
}

0 comments on commit 00310ee

Please sign in to comment.