Repository: bitcoin/bitcoin
File: test/functional/interface_rpc.py (Python)

Code before:
        body = []
        response, status = send_json_rpc(self.nodes[0], body)
        assert_equal(status, 200)
        assert_equal(
            response,
            []
        )

        self.log.info("Testing default JSON-RPC 1.1 batch request...")
        body = []
        for cmd in commands:
            body.append(builder.rpc_request(cmd))
        response, status = send_json_rpc(self.nodes[0], body)
        assert_equal(status, 200)
        # JSON 1.1: Every response has a "result" and an "error"
        assert_equal(
            response,
            [
                {"result": 0, "error": None, "id": 0},
                {"result": None, "error": {"code": RPC_METHOD_NOT_FOUND, "message": "Method not found"}, "id": 1},
                {"result": "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206", "error": None, "id": 2},
                {"result": None, "error": {"code": RPC_INVALID_REQUEST, "message": "Missing method"}, "id": 3}
            ]
        )

        self.log.info("Testing basic JSON-RPC 1.0 batch request...")
        body = []
        for cmd in commands:
            body.append(builder.rpc_request(cmd, version=1))
        response, status = send_json_rpc(self.nodes[0], body)
        assert_equal(status, 200)
        # JSON 1.1: Every response has a "result" and an "error"
        assert_equal(
            response,
            [
                {"result": 0, "error": None, "id": 4},
                {"result": None, "error": {"code": RPC_METHOD_NOT_FOUND, "message": "Method not found"}, "id": 5},
                {"result": "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206", "error": None, "id": 6},
                {"result": None, "error": {"code": RPC_INVALID_REQUEST, "message": "Missing method"}, "id": 7}
            ]
        )

        self.log.info("Testing basic JSON-RPC 2.0 batch request...")
        body = []
        for cmd in commands:
            body.append(builder.rpc_request(cmd, version=2))
        response, status = send_json_rpc(self.nodes[0], body)
        assert_equal(status, 200)
        # JSON 2.0: Each response has either a "result" or an "error"
        assert_equal(
            response,

Review comment (performance):
In commit "test: cover JSONRPC 2.0 requests, batches, and notifications" (92c651394bcb1c476cc62989936edd621b5d4aa5)

This is confusing because there should be no such thing as a JSON-RPC 1.0 batch request, batches were introduced in 2.0. Also specifying req["jsonrpc"] = "1.0" is nonstandard. Would be good to clarify what behavior is standard and what is just being done for backwards compatibility.

Code after:
    def test_getrpcinfo(self):
        self.log.info("Testing getrpcinfo...")

        info = self.nodes[0].getrpcinfo()
        assert_equal(len(info['active_commands']), 1)

        command = info['active_commands'][0]
        assert_equal(command['method'], 'getrpcinfo')
        assert_greater_than_or_equal(command['duration'], 0)
        assert_equal(info['logpath'], os.path.join(self.nodes[0].chain_path, 'debug.log'))

    def test_batch_request(self, call_options):
        calls = [
            # A basic request that will work fine.
            {"method": "getblockcount"},
            # Request that will fail.  The whole batch request should still
            # work fine.
            {"method": "invalidmethod"},
            # Another call that should succeed.
            {"method": "getblockhash", "params": [0]},
            # Invalid request format
            {"pizza": "sausage"}
        ]
        results = [
            {"result": 0},
            {"error": {"code": RPC_METHOD_NOT_FOUND, "message": "Method not found"}},
            {"result": "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"},
            {"error": {"code": RPC_INVALID_REQUEST, "message": "Missing method"}},
        ]

        request = []
        response = []
        for idx, (call, result) in enumerate(zip(calls, results), 1):
            options = call_options(idx)
            if options is None:
                continue
            request.append(format_request(options, idx, call))
            r = format_response(options, idx, result)
            if r is not None:
                response.append(r)

        rpc_response, http_status = send_json_rpc(self.nodes[0], request)
        if len(response) == 0 and len(request) > 0:
            assert_equal(http_status, 204)
            assert_equal(rpc_response, None)
        else:
            assert_equal(http_status, 200)
            assert_equal(rpc_response, response)

    def test_batch_requests(self):
        self.log.info("Testing empty batch request...")