@Test
public void testFindRoots() throws Exception {

    final String pathPrefix = "/test";
    final File tempDir = new File(testBaseDir, "testFindRoots");
    final File repoDir = new File(tempDir, "repo/segmentstore");
    final int sample = 5;
    List<String> orderedPaths = IntStream.range(0, sample).mapToObj(val -> pathPrefix + "/ordered" + val).collect(Collectors.toList());
    List<String> unorderedPaths = IntStream.range(0, sample).mapToObj(val -> pathPrefix + "/unordered" + val).collect(Collectors.toList());
    assertEquals("should generate n paths: ", sample, orderedPaths.size());
    TestUtil.prepareRepo(repoDir, session -> {
        TestUtil.installCndFromURL(session, getClass().getResource("/sling_nodetypes.cnd"));
        orderedPaths.forEach(Fun.tryOrVoid1(path ->
                JcrUtils.getOrCreateByPath(path, "nt:folder",
                        "sling:OrderedFolder", session, true)));
        unorderedPaths.forEach(Fun.tryOrVoid1(path ->
                JcrUtils.getOrCreateByPath(path, "nt:folder",
                        "sling:Folder", session, true)));
    });
    List<String> allPaths = new ArrayList<>(orderedPaths);
    allPaths.addAll(unorderedPaths);
    allPaths.add(pathPrefix);
    TestUtil.withReadOnlyFixture(repoDir, session -> {
        ChecklistExporter pathExporter = new ChecklistExporter.Builder().byPath(allPaths.toArray(new String[0])).build();
        List<ForcedRoot> byPath = pathExporter.findRoots(session);
        for (String path : unorderedPaths) {
            ForcedRoot root0 = byPath.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[path] root for path %s should not be null", path), root0);
            assertEquals(String.format("[path] root primaryType for path %s should be sling:Folder", path),
                    "sling:Folder", root0.getPrimaryType());
        }
        for (String path : orderedPaths) {
            ForcedRoot root0 = byPath.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[path] root for path %s should not be null", path), root0);
            assertEquals(String.format("[path] root primaryType for path %s should be sling:OrderedFolder", path),
                    "sling:OrderedFolder", root0.getPrimaryType());
        }
        final String queryPrefix = ISO9075.encodePath("/jcr:root" + pathPrefix);
        ChecklistExporter queryExporter = new ChecklistExporter.Builder().byQuery(queryPrefix + "//element(*, sling:Folder)").build();
        List<ForcedRoot> byQuery = queryExporter.findRoots(session);
        for (String path : unorderedPaths) {
            ForcedRoot root0 = byQuery.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[query] root for path %s should not be null", path), root0);
            assertEquals(String.format("[query] root primaryType for path %s should be sling:Folder", path),
                    "sling:Folder", root0.getPrimaryType());
        }
        for (String path : orderedPaths) {
            ForcedRoot root0 = byQuery.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[query] root for path %s should not be null", path), root0);
            assertEquals(String.format("[query] root primaryType for path %s should be sling:OrderedFolder", path),
                    "sling:OrderedFolder", root0.getPrimaryType());
        }
        ChecklistExporter ntExporter = new ChecklistExporter.Builder().byNodeType("nt:folder", "+sling:Folder").build();
        List<ForcedRoot> byNt = ntExporter.findRoots(session);
        for (String path : unorderedPaths) {
            ForcedRoot root0 = byNt.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[nodetype] root for path %s should not be null", path), root0);
            assertEquals(String.format("[nodetype] root primaryType for path %s should be sling:Folder", path),
                    "sling:Folder", root0.getPrimaryType());
        }
        for (String path : orderedPaths) {
            ForcedRoot root0 = byNt.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[nodetype] root for path %s should not be null", path), root0);
            assertEquals(String.format("[nodetype] root primaryType for path %s should be sling:OrderedFolder", path),
                    "sling:OrderedFolder", root0.getPrimaryType());
        }
        for (String path : Collections.singletonList(pathPrefix)) {
            ForcedRoot root0 = byNt.stream().filter(root -> path.equals(root.getPath())).findFirst().orElse(null);
            assertNotNull(String.format("[nodetype] root for path %s should not be null", path), root0);
            assertEquals(String.format("[nodetype] root primaryType for path %s should be nt:folder", path),
                    "nt:folder", root0.getPrimaryType());
        }
    });
}