@Test
    void testGetNodeState() throws Exception {
        Set<ConfiguredNode> configuredNodes = new TreeSet<>();
        for (int i = 0; i < 10; i++)
            configuredNodes.add(new ConfiguredNode(i, false));
        FleetControllerOptions.Builder builder = defaultOptions(configuredNodes);
        builder.setMinRatioOfStorageNodesUp(0);
        builder.setMaxInitProgressTime(30000);
        builder.setStableStateTimePeriod(60000);
        setUpFleetController(timer, builder);
        setUpVdsNodes(timer);
        waitForStableSystem();

        setWantedNodeState(State.DOWN, NodeType.DISTRIBUTOR, 2);
        setWantedNodeState(State.RETIRED, NodeType.STORAGE, 2);
        setWantedNodeState(State.MAINTENANCE, NodeType.STORAGE, 7);
        waitForCompleteCycle();
        timer.advanceTime(1000000);
        waitForCompleteCycle(); // Make fleet controller notice that time has changed before any disconnects
        nodes.get(0).disconnect();
        nodes.get(3).disconnect();
        nodes.get(5).disconnect();
        waitForState("version:\\d+ distributor:10 .0.s:d .2.s:d storage:10 .1.s:m .2.s:m .7.s:m");
        timer.advanceTime(1000000);
        waitForState("version:\\d+ distributor:10 .0.s:d .2.s:d storage:10 .1.s:d .2.s:d .7.s:m");
        timer.advanceTime(1000000);
        waitForCompleteCycle(); // Make fleet controller notice that time has changed before any disconnects
        nodes.get(3).setNodeState(new NodeState(nodes.get(3).getType(), State.INITIALIZING).setInitProgress(0.2f));
        nodes.get(3).connect();
        waitForState("version:\\d+ distributor:10 .0.s:d .2.s:d storage:10 .1.s:i .1.i:0.2 .2.s:d .7.s:m");

        int rpcPort = fleetController().getRpcPort();
        Target connection = supervisor.connect(new Spec("localhost", rpcPort));
        assertTrue(connection.isValid());

        Request req = getNodeState("distributor", 0, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals(State.DOWN, NodeState.deserialize(NodeType.DISTRIBUTOR, req.returnValues().get(0).asString()).getState());
        NodeState reported = NodeState.deserialize(NodeType.DISTRIBUTOR, req.returnValues().get(1).asString());
        assertTrue(reported.getState().oneOf("d-"), req.returnValues().get(1).asString());
        assertEquals("", req.returnValues().get(2).asString());

        req = getNodeState("distributor",2, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals(State.DOWN, NodeState.deserialize(NodeType.DISTRIBUTOR, req.returnValues().get(0).asString()).getState());
        assertEquals("t:946080000", req.returnValues().get(1).asString());
        assertEquals(State.DOWN, NodeState.deserialize(NodeType.DISTRIBUTOR, req.returnValues().get(2).asString()).getState());

        req = getNodeState("distributor", 4, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals("", req.returnValues().get(0).asString());
        assertEquals("t:946080000", req.returnValues().get(1).asString());
        assertEquals("", req.returnValues().get(2).asString());

        req = getNodeState("distributor", 15, connection);
        assertEquals(ErrorCode.METHOD_FAILED, req.errorCode(), req.toString());
        assertEquals("No node distributor.15 exists in cluster mycluster", req.errorMessage());
        assertFalse(req.checkReturnTypes("ssss"), req.toString());

        req = getNodeState("storage", 1, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals("s:i i:0.2", req.returnValues().get(0).asString());
        assertEquals("s:i i:0.2", req.returnValues().get(1).asString());
        assertEquals("", req.returnValues().get(2).asString());

        req = getNodeState("storage", 2, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals(State.DOWN, NodeState.deserialize(NodeType.STORAGE, req.returnValues().get(0).asString()).getState());
        reported = NodeState.deserialize(NodeType.STORAGE, req.returnValues().get(1).asString());
        assertTrue(reported.getState().oneOf("d-"), req.returnValues().get(1).asString());
        assertEquals(State.RETIRED, NodeState.deserialize(NodeType.STORAGE, req.returnValues().get(2).asString()).getState());

        req = getNodeState("storage", 5, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals("", req.returnValues().get(0).asString());
        assertEquals("t:946080000", req.returnValues().get(1).asString());
        assertEquals("", req.returnValues().get(2).asString());

        req = getNodeState("storage", 7, connection);
        assertEquals(ErrorCode.NONE, req.errorCode(), req.toString());
        assertTrue(req.checkReturnTypes("ssss"), req.toString());
        assertEquals(State.MAINTENANCE, NodeState.deserialize(NodeType.STORAGE, req.returnValues().get(0).asString()).getState());
        assertEquals("t:946080000", req.returnValues().get(1).asString());
        assertEquals(State.MAINTENANCE, NodeState.deserialize(NodeType.STORAGE, req.returnValues().get(2).asString()).getState());
    }
Note: RpcServer is only used in unit tests

@author humbe
clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/RpcServerTest.java