Skip to content

Commit b704508

Browse files
committed
Merge pull request godotengine#89124 from wheatear-dev/test-json-rpc
Add unit tests for JSONRPC
2 parents e73f40e + 6b4a759 commit b704508

File tree

3 files changed

+232
-0
lines changed

3 files changed

+232
-0
lines changed

modules/jsonrpc/SCsub

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ Import("env_modules")
55

66
env_jsonrpc = env_modules.Clone()
77
env_jsonrpc.add_source_files(env.modules_sources, "*.cpp")
8+
9+
if env["tests"]:
10+
env_jsonrpc.Append(CPPDEFINES=["TESTS_ENABLED"])
11+
env_jsonrpc.add_source_files(env.modules_sources, "./tests/*.cpp")
12+
13+
if env["disable_exceptions"]:
14+
env_jsonrpc.Append(CPPDEFINES=["DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS"])
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**************************************************************************/
2+
/* test_jsonrpc.cpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#include "test_jsonrpc.h"
32+
33+
#include "core/io/json.h"
34+
35+
namespace TestJSONRPC {
36+
37+
void check_error_code(const Dictionary &p_dict, const JSONRPC::ErrorCode &p_code) {
38+
CHECK(p_dict["jsonrpc"] == "2.0");
39+
REQUIRE(p_dict.has("error"));
40+
const Dictionary &err_body = p_dict["error"];
41+
const int &code = err_body["code"];
42+
CHECK(code == p_code);
43+
}
44+
45+
void check_invalid(const Dictionary &p_dict) {
46+
check_error_code(p_dict, JSONRPC::INVALID_REQUEST);
47+
}
48+
49+
void check_invalid_string(const String &p_str) {
50+
JSON json;
51+
REQUIRE(json.parse(p_str) == OK);
52+
const Dictionary &dict = json.get_data();
53+
check_invalid(dict);
54+
}
55+
56+
String TestClassJSONRPC::something(const String &p_in) {
57+
return p_in + ", please";
58+
}
59+
60+
void TestClassJSONRPC::_bind_methods() {
61+
ClassDB::bind_method(D_METHOD("something", "in"), &TestClassJSONRPC::something);
62+
}
63+
64+
void test_process_action(const Variant &p_in, const Variant &p_expected, bool p_process_array_elements) {
65+
TestClassJSONRPC json_rpc = TestClassJSONRPC();
66+
const Variant &observed = json_rpc.process_action(p_in, p_process_array_elements);
67+
CHECK(observed == p_expected);
68+
}
69+
70+
void test_process_string(const String &p_in, const String &p_expected) {
71+
TestClassJSONRPC json_rpc = TestClassJSONRPC();
72+
const String &out_str = json_rpc.process_string(p_in);
73+
CHECK(out_str == p_expected);
74+
}
75+
76+
void check_error_no_method(const Dictionary &p_dict) {
77+
check_error_code(p_dict, JSONRPC::METHOD_NOT_FOUND);
78+
}
79+
80+
void test_process_action_bad_method(const Dictionary &p_in) {
81+
TestClassJSONRPC json_rpc = TestClassJSONRPC();
82+
const Dictionary &out_dict = json_rpc.process_action(p_in);
83+
check_error_no_method(out_dict);
84+
}
85+
86+
} // namespace TestJSONRPC
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/**************************************************************************/
2+
/* test_jsonrpc.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#ifndef TEST_JSONRPC_H
32+
#define TEST_JSONRPC_H
33+
34+
#include "tests/test_macros.h"
35+
#include "tests/test_utils.h"
36+
37+
#include "../jsonrpc.h"
38+
39+
namespace TestJSONRPC {
40+
41+
void check_invalid(const Dictionary &p_dict);
42+
43+
TEST_CASE("[JSONRPC] process_action invalid") {
44+
JSONRPC json_rpc = JSONRPC();
45+
46+
check_invalid(json_rpc.process_action("String is invalid"));
47+
check_invalid(json_rpc.process_action(1234));
48+
check_invalid(json_rpc.process_action(false));
49+
check_invalid(json_rpc.process_action(3.14159));
50+
}
51+
52+
void check_invalid_string(const String &p_str);
53+
54+
TEST_CASE("[JSONRPC] process_string invalid") {
55+
JSONRPC json_rpc = JSONRPC();
56+
57+
check_invalid_string(json_rpc.process_string("\"String is invalid\""));
58+
check_invalid_string(json_rpc.process_string("1234"));
59+
check_invalid_string(json_rpc.process_string("false"));
60+
check_invalid_string(json_rpc.process_string("3.14159"));
61+
}
62+
63+
class TestClassJSONRPC : public JSONRPC {
64+
GDCLASS(TestClassJSONRPC, JSONRPC)
65+
66+
public:
67+
String something(const String &p_in);
68+
69+
protected:
70+
static void _bind_methods();
71+
};
72+
73+
void test_process_action(const Variant &p_in, const Variant &p_expected, bool p_process_array_elements = false);
74+
75+
TEST_CASE("[JSONRPC] process_action Dictionary") {
76+
ClassDB::register_class<TestClassJSONRPC>();
77+
78+
Dictionary in_dict = Dictionary();
79+
in_dict["method"] = "something";
80+
in_dict["id"] = "ID";
81+
in_dict["params"] = "yes";
82+
83+
Dictionary expected_dict = Dictionary();
84+
expected_dict["jsonrpc"] = "2.0";
85+
expected_dict["id"] = "ID";
86+
expected_dict["result"] = "yes, please";
87+
88+
test_process_action(in_dict, expected_dict);
89+
}
90+
91+
TEST_CASE("[JSONRPC] process_action Array") {
92+
Array in;
93+
Dictionary in_1;
94+
in_1["method"] = "something";
95+
in_1["id"] = 1;
96+
in_1["params"] = "more";
97+
in.push_back(in_1);
98+
Dictionary in_2;
99+
in_2["method"] = "something";
100+
in_2["id"] = 2;
101+
in_2["params"] = "yes";
102+
in.push_back(in_2);
103+
104+
Array expected;
105+
Dictionary expected_1;
106+
expected_1["jsonrpc"] = "2.0";
107+
expected_1["id"] = 1;
108+
expected_1["result"] = "more, please";
109+
expected.push_back(expected_1);
110+
Dictionary expected_2;
111+
expected_2["jsonrpc"] = "2.0";
112+
expected_2["id"] = 2;
113+
expected_2["result"] = "yes, please";
114+
expected.push_back(expected_2);
115+
116+
test_process_action(in, expected, true);
117+
}
118+
119+
void test_process_string(const String &p_in, const String &p_expected);
120+
121+
TEST_CASE("[JSONRPC] process_string Dictionary") {
122+
const String in = "{\"method\":\"something\",\"id\":\"ID\",\"params\":\"yes\"}";
123+
const String expected = "{\"id\":\"ID\",\"jsonrpc\":\"2.0\",\"result\":\"yes, please\"}";
124+
125+
test_process_string(in, expected);
126+
}
127+
128+
void test_process_action_bad_method(const Dictionary &p_in);
129+
130+
TEST_CASE("[JSONRPC] process_action bad method") {
131+
Dictionary in_dict;
132+
in_dict["method"] = "nothing";
133+
134+
test_process_action_bad_method(in_dict);
135+
}
136+
137+
} // namespace TestJSONRPC
138+
139+
#endif // TEST_JSONRPC_H

0 commit comments

Comments
 (0)