### Question:
PluginDependencyUtils { public static List<PluginDescription> sortCandidates(List<PluginDescription> candidates) { MutableGraph<PluginDescription> graph = GraphBuilder.directed() .allowsSelfLoops(false) .expectedNodeCount(candidates.size()) .build(); Map<String, PluginDescription> candidateMap = Maps.uniqueIndex(candidates, PluginDescription::getId); for (PluginDescription description : candidates) { graph.addNode(description); for (PluginDependency dependency : description.getDependencies()) { PluginDescription in = candidateMap.get(dependency.getId()); if (in != null) { graph.putEdge(description, in); } } } List<PluginDescription> sorted = new ArrayList<>(); Map<PluginDescription, Mark> marks = new HashMap<>(); for (PluginDescription node : graph.nodes()) { visitNode(graph, node, marks, sorted, new ArrayDeque<>()); } return sorted; } private  PluginDependencyUtils(); static List<PluginDescription> sortCandidates(List<PluginDescription> candidates);  }### Answer:
@Test void sortCandidatesTrivial() throws Exception { List<PluginDescription> descriptionList = new ArrayList<>(); assertEquals(descriptionList, PluginDependencyUtils.sortCandidates(descriptionList)); }
@Test void sortCandidatesSingleton() throws Exception { List<PluginDescription> plugins = ImmutableList.of(NO_DEPENDENCY); assertEquals(plugins, PluginDependencyUtils.sortCandidates(plugins)); }
@Test void sortCandidatesBasicDependency() throws Exception { List<PluginDescription> plugins = ImmutableList.of(HAS_DEPENDENCY_1, NO_DEPENDENCY); List<PluginDescription> expected = ImmutableList.of(NO_DEPENDENCY, HAS_DEPENDENCY_1); assertEquals(expected, PluginDependencyUtils.sortCandidates(plugins)); }
@Test void sortCandidatesNestedDependency() throws Exception { List<PluginDescription> plugins = ImmutableList.of(HAS_DEPENDENCY_1, HAS_DEPENDENCY_2, NO_DEPENDENCY); List<PluginDescription> expected = ImmutableList.of(NO_DEPENDENCY, HAS_DEPENDENCY_1, HAS_DEPENDENCY_2); assertEquals(expected, PluginDependencyUtils.sortCandidates(plugins)); }
@Test void sortCandidatesTypical() throws Exception { List<PluginDescription> plugins = ImmutableList.of(HAS_DEPENDENCY_2, NO_DEPENDENCY_2, HAS_DEPENDENCY_1, NO_DEPENDENCY); List<PluginDescription> expected = ImmutableList.of(NO_DEPENDENCY, HAS_DEPENDENCY_1, HAS_DEPENDENCY_2, NO_DEPENDENCY_2); assertEquals(expected, PluginDependencyUtils.sortCandidates(plugins)); }
@Test void sortCandidatesMultiplePluginsDependentOnOne() throws Exception { List<PluginDescription> plugins = ImmutableList.of(HAS_DEPENDENCY_3, HAS_DEPENDENCY_1, NO_DEPENDENCY); List<PluginDescription> expected = ImmutableList.of(NO_DEPENDENCY, HAS_DEPENDENCY_3, HAS_DEPENDENCY_1); assertEquals(expected, PluginDependencyUtils.sortCandidates(plugins)); }
@Test void sortCandidatesCircularDependency() throws Exception { List<PluginDescription> descs = ImmutableList.of(CIRCULAR_DEPENDENCY_1, CIRCULAR_DEPENDENCY_2); assertThrows(IllegalStateException.class, () -> PluginDependencyUtils.sortCandidates(descs)); }