@Test
    public void dirty_host_only_if_we_can_dirty_children() {
        NodeRepositoryTester tester = new NodeRepositoryTester();

        tester.addHost("id1", "host1", "default", NodeType.host);
        tester.addHost("id2", "host2", "default", NodeType.host);
        tester.addNode("node10", "node10", "host1", "docker", NodeType.tenant);
        tester.addNode("node11", "node11", "host1", "docker", NodeType.tenant);
        tester.addNode("node12", "node12", "host1", "docker", NodeType.tenant);
        tester.addNode("node20", "node20", "host2", "docker", NodeType.tenant);

        tester.setNodeState("node11", Node.State.ready);
        tester.setNodeState("node12", Node.State.active);
        tester.setNodeState("node20", Node.State.failed);

        assertEquals(6, tester.nodeRepository().nodes().list().size());

        // Should be OK to dirty host2 as it is in provisioned and its only child is in failed
        tester.nodeRepository().nodes().deallocateRecursively("host2", Agent.system, NodeRepositoryTest.class.getSimpleName());
        assertEquals(Set.of("host2", "node20"), filterNodes(tester, node -> node.state() == Node.State.dirty));

        // Cant dirty host1, node11 is ready and node12 is active
        try {
            tester.nodeRepository().nodes().deallocateRecursively("host1", Agent.system, NodeRepositoryTest.class.getSimpleName());
            fail("Should not be able to dirty host1");
        } catch (IllegalArgumentException ignored) { } // Expected;

        assertEquals(Set.of("host2", "node20"), filterNodes(tester, node -> node.state() == Node.State.dirty));
    }
tests basic operation of the node repository

@author bratseth
node-repository/src/test/java/com/yahoo/vespa/hosted/provision/NodeRepositoryTest.java