Merge lp:unity-scopes-api/staging into lp:unity-scopes-api
- staging
- Merge into trunk
Proposed by
Marcus Tomlinson
Status: | Merged |
---|---|
Approved by: | Paweł Stołowski |
Approved revision: | 324 |
Merged at revision: | 367 |
Proposed branch: | lp:unity-scopes-api/staging |
Merge into: | lp:unity-scopes-api |
Diff against target: |
2397 lines (+1285/-441) 31 files modified
CMakeLists.txt (+3/-3) RELEASE_NOTES.md (+7/-0) debian/VERSION (+1/-1) debian/changelog (+22/-0) debian/control.in (+1/-1) doc/tutorial.dox (+96/-1) include/unity/scopes/internal/JsonCppNode.h (+17/-10) include/unity/scopes/internal/JsonNodeInterface.h (+2/-3) include/unity/scopes/internal/JsonSettingsSchema.h (+1/-1) include/unity/scopes/internal/gobj_memory.h (+212/-0) scoperegistry/scoperegistry.cpp (+0/-1) src/scopes/CategoryRenderer.cpp (+1/-1) src/scopes/PreviewWidget.cpp (+9/-2) src/scopes/internal/JsonCppNode.cpp (+283/-200) src/scopes/internal/JsonSettingsSchema.cpp (+149/-162) src/scopes/internal/Logger.cpp (+2/-2) src/scopes/internal/RuntimeImpl.cpp (+1/-1) src/scopes/internal/ScopeConfig.cpp (+0/-2) src/scopes/internal/smartscopes/SmartScopesClient.cpp (+10/-0) src/scopes/internal/zmq_middleware/StopPublisher.cpp (+1/-1) src/scopes/testing/ScopeMetadataBuilder.cpp (+1/-3) test/copyright/check_copyright.sh (+1/-7) test/gtest/scopes/Registry/Registry_test.cpp (+0/-1) test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in (+0/-1) test/gtest/scopes/internal/CMakeLists.txt (+1/-0) test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp (+153/-17) test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp (+37/-5) test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp (+4/-4) test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt (+3/-0) test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp (+208/-0) test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp (+59/-11) |
To merge this branch: | bzr merge lp:unity-scopes-api/staging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Pending | |
Unity Team | Pending | ||
Review via email: mp+295415@code.launchpad.net |
Commit message
* Got rid of category header background, as per design (Bug #1446216).
* Re-enabled license/copyright test for xenial+.
* Removed libjson-cpp and replaced with json-glib based implementation (Bug #1360247).
* Fixed Yakkety build.
Description of the change
To post a comment you must log in.
lp:unity-scopes-api/staging
updated
- 319. By Marcus Tomlinson
-
Sync changelog
- 320. By Marcus Tomlinson
-
Update changelog and RELEASE_NOTES.md
- 321. By Marcus Tomlinson
-
Bump version
- 322. By Marcus Tomlinson
-
Merge devel
- 323. By Marcus Tomlinson
-
Merged devel
- 324. By Paweł Stołowski
-
Merged devel changes
Revision history for this message
Robert Bruce Park (robru) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2016-03-31 23:48:56 +0000 | |||
3 | +++ CMakeLists.txt 2016-06-17 07:24:44 +0000 | |||
4 | @@ -66,11 +66,11 @@ | |||
5 | 66 | pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED) | 66 | pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED) |
6 | 67 | pkg_check_modules(LTTNG_UST lttng-ust REQUIRED) | 67 | pkg_check_modules(LTTNG_UST lttng-ust REQUIRED) |
7 | 68 | pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED) | 68 | pkg_check_modules(LIBURCU_BP liburcu-bp REQUIRED) |
8 | 69 | pkg_check_modules(JSONCPP jsoncpp REQUIRED) | ||
9 | 70 | pkg_check_modules(LIBACCOUNTS libaccounts-glib REQUIRED) | 69 | pkg_check_modules(LIBACCOUNTS libaccounts-glib REQUIRED) |
10 | 71 | pkg_check_modules(LIBSIGNON libsignon-glib REQUIRED) | 70 | pkg_check_modules(LIBSIGNON libsignon-glib REQUIRED) |
11 | 72 | pkg_check_modules(ZMQLIB libzmq REQUIRED) | 71 | pkg_check_modules(ZMQLIB libzmq REQUIRED) |
12 | 73 | pkg_check_modules(NET_CPP net-cpp>=1.2.0 REQUIRED) | 72 | pkg_check_modules(NET_CPP net-cpp>=1.2.0 REQUIRED) |
13 | 73 | pkg_check_modules(JSON_GLIB json-glib-1.0 REQUIRED) | ||
14 | 74 | 74 | ||
15 | 75 | find_library(ZMQPPLIB zmqpp) | 75 | find_library(ZMQPPLIB zmqpp) |
16 | 76 | if(NOT ZMQPPLIB) | 76 | if(NOT ZMQPPLIB) |
17 | @@ -140,10 +140,10 @@ | |||
18 | 140 | ) | 140 | ) |
19 | 141 | 141 | ||
20 | 142 | set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} | 142 | set(OTHER_INCLUDE_DIRS ${OTHER_INCLUDE_DIRS} ${UNITY_API_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} |
22 | 143 | ${JSONCPP_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS} | 143 | ${JSON_GLIB_INCLUDE_DIRS} ${PROCESS_CPP_INCLUDE_DIRS} ${APPARMOR_INCLUDE_DIRS} |
23 | 144 | ${LIBACCOUNTS_INCLUDE_DIRS} ${LIBSIGNON_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS}) | 144 | ${LIBACCOUNTS_INCLUDE_DIRS} ${LIBSIGNON_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS}) |
24 | 145 | set(OTHER_LIBS ${OTHER_LIBS} ${UNITY_API_LDFLAGS} ${APPARMOR_LDFLAGS} ${LIBACCOUNTS_LIBRARIES} | 145 | set(OTHER_LIBS ${OTHER_LIBS} ${UNITY_API_LDFLAGS} ${APPARMOR_LDFLAGS} ${LIBACCOUNTS_LIBRARIES} |
26 | 146 | ${LIBSIGNON_LIBRARIES} ${Boost_LIBRARIES} ${JSONCPP_LDFLAGS} ${PROCESS_CPP_LDFLAGS} | 146 | ${LIBSIGNON_LIBRARIES} ${Boost_LIBRARIES} ${JSON_GLIB_LDFLAGS} ${PROCESS_CPP_LDFLAGS} |
27 | 147 | ${ZMQPPLIB} ${ZMQLIB_LDFLAGS} ${CAPNPLIB} ${KJLIB} ${DLLIB} ${NET_CPP_LDFLAGS} pthread) | 147 | ${ZMQPPLIB} ${ZMQLIB_LDFLAGS} ${CAPNPLIB} ${KJLIB} ${DLLIB} ${NET_CPP_LDFLAGS} pthread) |
28 | 148 | 148 | ||
29 | 149 | # Standard install paths | 149 | # Standard install paths |
30 | 150 | 150 | ||
31 | === modified file 'RELEASE_NOTES.md' | |||
32 | --- RELEASE_NOTES.md 2016-04-11 07:58:52 +0000 | |||
33 | +++ RELEASE_NOTES.md 2016-06-17 07:24:44 +0000 | |||
34 | @@ -1,6 +1,13 @@ | |||
35 | 1 | Release notes | 1 | Release notes |
36 | 2 | ============= | 2 | ============= |
37 | 3 | 3 | ||
38 | 4 | Changes in version 1.0.6 | ||
39 | 5 | ======================== | ||
40 | 6 | - Got rid of category header background, as per design (Bug #1446216). | ||
41 | 7 | - Re-enabled license/copyright test for xenial+. | ||
42 | 8 | - Removed libjson-cpp and replaced with json-glib based implementation (Bug #1360247). | ||
43 | 9 | - Fixed Yakkety build. | ||
44 | 10 | |||
45 | 4 | Changes in version 1.0.5 | 11 | Changes in version 1.0.5 |
46 | 5 | ======================== | 12 | ======================== |
47 | 6 | - Simplify debian/control munging. | 13 | - Simplify debian/control munging. |
48 | 7 | 14 | ||
49 | === modified file 'debian/VERSION' | |||
50 | --- debian/VERSION 2016-03-31 23:48:56 +0000 | |||
51 | +++ debian/VERSION 2016-06-17 07:24:44 +0000 | |||
52 | @@ -1,1 +1,1 @@ | |||
54 | 1 | 1.0.5 | 1 | 1.0.6 |
55 | 2 | 2 | ||
56 | === modified file 'debian/changelog' | |||
57 | --- debian/changelog 2016-04-13 09:51:48 +0000 | |||
58 | +++ debian/changelog 2016-06-17 07:24:44 +0000 | |||
59 | @@ -1,3 +1,25 @@ | |||
60 | 1 | unity-scopes-api (1.0.6+16.10.20160520.3-0ubuntu2) UNRELEASED; urgency=medium | ||
61 | 2 | |||
62 | 3 | * Got rid of category header background, as per design (Bug #1446216). | ||
63 | 4 | * Re-enabled license/copyright test for xenial+. | ||
64 | 5 | * Removed libjson-cpp and replaced with json-glib based implementation (Bug #1360247). | ||
65 | 6 | * Fixed Yakkety build. | ||
66 | 7 | |||
67 | 8 | -- Marcus Tomlinson <marcustomlinson@ubuntu> Mon, 23 May 2016 09:54:28 +0200 | ||
68 | 9 | |||
69 | 10 | unity-scopes-api (1.0.6+16.10.20160520.3-0ubuntu1) yakkety; urgency=medium | ||
70 | 11 | |||
71 | 12 | [ CI Train Bot ] | ||
72 | 13 | * No-change rebuild. | ||
73 | 14 | |||
74 | 15 | -- Marcus Tomlinson <marcus.tomlinson@canonical.com> Fri, 20 May 2016 14:55:39 +0000 | ||
75 | 16 | |||
76 | 17 | unity-scopes-api (1.0.5+16.04.20160413.1-0ubuntu2) yakkety; urgency=medium | ||
77 | 18 | |||
78 | 19 | * No-change rebuild of latest xenial trunk against current archive. | ||
79 | 20 | |||
80 | 21 | -- Łukasz 'sil2100' Zemczak <lukasz.zemczak@ubuntu.com> Thu, 19 May 2016 19:19:30 +0200 | ||
81 | 22 | |||
82 | 1 | unity-scopes-api (1.0.5+16.04.20160413.1-0ubuntu1) xenial; urgency=medium | 23 | unity-scopes-api (1.0.5+16.04.20160413.1-0ubuntu1) xenial; urgency=medium |
83 | 2 | 24 | ||
84 | 3 | [ Marcus Tomlinson ] | 25 | [ Marcus Tomlinson ] |
85 | 4 | 26 | ||
86 | === modified file 'debian/control.in' | |||
87 | --- debian/control.in 2016-03-16 12:35:22 +0000 | |||
88 | +++ debian/control.in 2016-06-17 07:24:44 +0000 | |||
89 | @@ -21,7 +21,7 @@ | |||
90 | 21 | libboost-thread-dev, | 21 | libboost-thread-dev, |
91 | 22 | libcapnp-dev (>= 0.4.0), | 22 | libcapnp-dev (>= 0.4.0), |
92 | 23 | libdbustest1-dev, | 23 | libdbustest1-dev, |
94 | 24 | libjsoncpp-dev, | 24 | libjson-glib-dev, |
95 | 25 | liblttng-ust-dev, | 25 | liblttng-ust-dev, |
96 | 26 | libnet-cpp-dev (>= 1.2.0), | 26 | libnet-cpp-dev (>= 1.2.0), |
97 | 27 | libprocess-cpp-dev (>= 1.0.1), | 27 | libprocess-cpp-dev (>= 1.0.1), |
98 | 28 | 28 | ||
99 | === modified file 'doc/tutorial.dox' | |||
100 | --- doc/tutorial.dox 2016-03-16 12:35:22 +0000 | |||
101 | +++ doc/tutorial.dox 2016-06-17 07:24:44 +0000 | |||
102 | @@ -636,6 +636,102 @@ | |||
103 | 636 | call to your `activate()` method. Your implementation of `activate()` should follow the same guidelines as for | 636 | call to your `activate()` method. Your implementation of `activate()` should follow the same guidelines as for |
104 | 637 | `perform_action()` (except that widget and action identifiers do not apply to result activation). | 637 | `perform_action()` (except that widget and action identifiers do not apply to result activation). |
105 | 638 | 638 | ||
106 | 639 | \paragraph resultaction Handling result action activation | ||
107 | 640 | |||
108 | 641 | Search results can embed simple action buttons (icons) in their cards. When the user taps an action icon, the scope gets notified and can update | ||
109 | 642 | the affected result card to reflect the new state. A typical use case for this is to offer "social" actions, such as thumbs up/down buttons. | ||
110 | 643 | |||
111 | 644 | The following snippet demonstrates how two actions can be added to a \link unity::scopes::CategorisedResult CategorisedResult\endlink: | ||
112 | 645 | |||
113 | 646 | \code | ||
114 | 647 | CategorisedResult res(cat); | ||
115 | 648 | res.set_uri("myuri"); | ||
116 | 649 | res.set_title("My Title"); | ||
117 | 650 | |||
118 | 651 | // Add result actions | ||
119 | 652 | VariantBuilder builder; | ||
120 | 653 | builder.add_tuple({ | ||
121 | 654 | {"id", Variant("thumbsup")}, | ||
122 | 655 | {"icon", Variant("thOff")}, | ||
123 | 656 | {"temporaryIcon", Variant("thOn")}, | ||
124 | 657 | {"label", Variant("I like it")}, | ||
125 | 658 | }); | ||
126 | 659 | builder.add_tuple({ | ||
127 | 660 | {"id", Variant("flag")}, | ||
128 | 661 | {"icon", Variant("flag")}, | ||
129 | 662 | {"temporaryIcon", Variant("flagOn")}, | ||
130 | 663 | {"label", Variant("Flag this result")}, | ||
131 | 664 | }); | ||
132 | 665 | res["social-actions"] = builder.end(); | ||
133 | 666 | \endcode | ||
134 | 667 | |||
135 | 668 | The attributes of result actions are as follows: | ||
136 | 669 | <ul> | ||
137 | 670 | <li>id - unique action identifier that will be reported to the scope. | ||
138 | 671 | <li>icon - the icon for the action button. | ||
139 | 672 | <li>temporaryIcon (optional) - defines an icon that will be shown immediately when the user taps the button, before the scope reacts to the action. | ||
140 | 673 | <li>label - the text shown next to the icon. | ||
141 | 674 | </ul> | ||
142 | 675 | |||
143 | 676 | To respond to activation of result actions, your scope must implement | ||
144 | 677 | \link unity::scopes::ScopeBase::activate_result_action ScopeBase::activate_result_action\endlink: | ||
145 | 678 | |||
146 | 679 | \code{.cpp} | ||
147 | 680 | class MyScope : public ScopeBase | ||
148 | 681 | { | ||
149 | 682 | ... | ||
150 | 683 | ActivationQueryBase::UPtr activate_result_action(Result const& result, | ||
151 | 684 | ActionMetadata const& metadata, | ||
152 | 685 | std::string const& action_id) override; | ||
153 | 686 | ... | ||
154 | 687 | } | ||
155 | 688 | \endcode | ||
156 | 689 | |||
157 | 690 | Like `search()` and `preview()`, `activate_result_action()` is a factory method. It must return an | ||
158 | 691 | instance that derives from \link unity::scopes::ActivationQueryBase ActivationQueryBase\endlink. | ||
159 | 692 | Your derived class must implement the \link unity::scopes::ActivationQueryBase::activate activate()\endlink method, | ||
160 | 693 | whose job it is to respond to the activation (that is, the user pressing action button). `activate` must return | ||
161 | 694 | an \link unity::scopes::ActivationResponse ActivationResponse\endlink, which tells the UI how it should | ||
162 | 695 | behave in response to the result action activation. For result actions the typical and recommended behavior is to update the card | ||
163 | 696 | for the result whose action was activated. | ||
164 | 697 | |||
165 | 698 | For example, here is how to update the actions of an affected card in response to a "thumbsup" action, so that tapping the "thumbsup" action button replaces that | ||
166 | 699 | button with "thumbsdown": | ||
167 | 700 | |||
168 | 701 | \code{.cpp} | ||
169 | 702 | class MyActivation : public ActivationQueryBase | ||
170 | 703 | { | ||
171 | 704 | MyActivation(Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& action_id) : | ||
172 | 705 | ActivationQueryBase(result, metadata, action_id) | ||
173 | 706 | { | ||
174 | 707 | } | ||
175 | 708 | |||
176 | 709 | virtual ActivationResponse activate() override | ||
177 | 710 | { | ||
178 | 711 | if (action_id() == "thumbsup") | ||
179 | 712 | { | ||
180 | 713 | // ... update backend data for 'thumbs up' action ... | ||
181 | 714 | |||
182 | 715 | // get the affect result and update it | ||
183 | 716 | Result updatedRes(result()); | ||
184 | 717 | VariantBuilder builder; | ||
185 | 718 | builder.add_tuple({ | ||
186 | 719 | {"id", Variant("thumbsdown")}, | ||
187 | 720 | {"icon", Variant("thOn")}, | ||
188 | 721 | {"temporaryIcon", Variant("thOff")}, | ||
189 | 722 | {"label", Variant("I don't like it")}, | ||
190 | 723 | }); | ||
191 | 724 | builder.add_tuple({ ... }) | ||
192 | 725 | updatedRes["social-actions"] = builder.end(); | ||
193 | 726 | return ActivationResponse(updatedRes); | ||
194 | 727 | } | ||
195 | 728 | |||
196 | 729 | if (action_id() == "thumbsdown") | ||
197 | 730 | ... | ||
198 | 731 | } | ||
199 | 732 | }; | ||
200 | 733 | \endcode | ||
201 | 734 | |||
202 | 639 | \paragraph export Exporting a scope | 735 | \paragraph export Exporting a scope |
203 | 640 | 736 | ||
204 | 641 | Your scope must be compiled into a `.so` shared library and, to be successfully | 737 | Your scope must be compiled into a `.so` shared library and, to be successfully |
205 | @@ -1430,7 +1526,6 @@ | |||
206 | 1430 | ForegroundColor = default text color (defaults to theme-provided foreground color) | 1526 | ForegroundColor = default text color (defaults to theme-provided foreground color) |
207 | 1431 | BackgroundColor = color of scope background (default is transparent) | 1527 | BackgroundColor = color of scope background (default is transparent) |
208 | 1432 | ShapeImages = whether to use Ubuntu-shape for all cards and artwork (defaults to true) | 1528 | ShapeImages = whether to use Ubuntu-shape for all cards and artwork (defaults to true) |
209 | 1433 | CategoryHeaderBackground = background scheme of the results categories | ||
210 | 1434 | PreviewButtonColor = color of preview buttons (defaults to theme-provided color) | 1529 | PreviewButtonColor = color of preview buttons (defaults to theme-provided color) |
211 | 1435 | LogoOverlayColor = color for the overlay in scopes overview (defaults to semi-transparent black) | 1530 | LogoOverlayColor = color for the overlay in scopes overview (defaults to semi-transparent black) |
212 | 1436 | PageHeader.Logo = image containing scope's logo | 1531 | PageHeader.Logo = image containing scope's logo |
213 | 1437 | 1532 | ||
214 | === modified file 'include/unity/scopes/internal/JsonCppNode.h' | |||
215 | --- include/unity/scopes/internal/JsonCppNode.h 2014-11-03 05:31:30 +0000 | |||
216 | +++ include/unity/scopes/internal/JsonCppNode.h 2016-06-17 07:24:44 +0000 | |||
217 | @@ -19,9 +19,15 @@ | |||
218 | 19 | #pragma once | 19 | #pragma once |
219 | 20 | 20 | ||
220 | 21 | #include <unity/scopes/internal/JsonNodeInterface.h> | 21 | #include <unity/scopes/internal/JsonNodeInterface.h> |
222 | 22 | #include <jsoncpp/json/value.h> | 22 | |
223 | 23 | #include <unity/scopes/internal/gobj_memory.h> | ||
224 | 23 | #include <unity/scopes/Variant.h> | 24 | #include <unity/scopes/Variant.h> |
225 | 24 | 25 | ||
226 | 26 | #pragma GCC diagnostic push | ||
227 | 27 | #pragma GCC diagnostic ignored "-Wold-style-cast" | ||
228 | 28 | #include <json-glib/json-glib.h> | ||
229 | 29 | #pragma GCC diagnostic pop | ||
230 | 30 | |||
231 | 25 | namespace unity | 31 | namespace unity |
232 | 26 | { | 32 | { |
233 | 27 | 33 | ||
234 | @@ -34,10 +40,11 @@ | |||
235 | 34 | class JsonCppNode : public JsonNodeInterface | 40 | class JsonCppNode : public JsonNodeInterface |
236 | 35 | { | 41 | { |
237 | 36 | public: | 42 | public: |
242 | 37 | explicit JsonCppNode(std::string const& json_string = ""); | 43 | JsonCppNode(); |
243 | 38 | explicit JsonCppNode(const Json::Value& root); | 44 | JsonCppNode(std::string const& json_string); |
244 | 39 | explicit JsonCppNode(const Variant& var); | 45 | explicit JsonCppNode(JsonNode* root); |
245 | 40 | ~JsonCppNode(); | 46 | explicit JsonCppNode(Variant const& var); |
246 | 47 | ~JsonCppNode() = default; | ||
247 | 41 | 48 | ||
248 | 42 | void clear() override; | 49 | void clear() override; |
249 | 43 | void read_json(std::string const& json_string) override; | 50 | void read_json(std::string const& json_string) override; |
250 | @@ -49,8 +56,7 @@ | |||
251 | 49 | NodeType type() const override; | 56 | NodeType type() const override; |
252 | 50 | 57 | ||
253 | 51 | std::string as_string() const override; | 58 | std::string as_string() const override; |
256 | 52 | int as_int() const override; | 59 | int64_t as_int() const override; |
255 | 53 | unsigned int as_uint() const override; | ||
257 | 54 | double as_double() const override; | 60 | double as_double() const override; |
258 | 55 | bool as_bool() const override; | 61 | bool as_bool() const override; |
259 | 56 | 62 | ||
260 | @@ -61,9 +67,10 @@ | |||
261 | 61 | JsonNodeInterface::SPtr get_node(unsigned int node_index) const override; | 67 | JsonNodeInterface::SPtr get_node(unsigned int node_index) const override; |
262 | 62 | 68 | ||
263 | 63 | private: | 69 | private: |
267 | 64 | static Json::Value from_variant(Variant const& var); | 70 | void init_from_string(std::string const& jscon_string); |
268 | 65 | static Variant to_variant(Json::Value const &val); | 71 | |
269 | 66 | Json::Value root_; | 72 | typedef std::unique_ptr<JsonNode, decltype(&json_node_free)> NodePtr; |
270 | 73 | NodePtr root_; | ||
271 | 67 | }; | 74 | }; |
272 | 68 | 75 | ||
273 | 69 | } // namespace internal | 76 | } // namespace internal |
274 | 70 | 77 | ||
275 | === modified file 'include/unity/scopes/internal/JsonNodeInterface.h' | |||
276 | --- include/unity/scopes/internal/JsonNodeInterface.h 2014-11-03 05:31:30 +0000 | |||
277 | +++ include/unity/scopes/internal/JsonNodeInterface.h 2016-06-17 07:24:44 +0000 | |||
278 | @@ -42,7 +42,7 @@ | |||
279 | 42 | 42 | ||
280 | 43 | enum NodeType | 43 | enum NodeType |
281 | 44 | { | 44 | { |
283 | 45 | Null, Array, Object, String, Int, UInt, Real, Bool | 45 | Null, Array, Object, String, Int, Real, Bool |
284 | 46 | }; | 46 | }; |
285 | 47 | 47 | ||
286 | 48 | JsonNodeInterface() = default; | 48 | JsonNodeInterface() = default; |
287 | @@ -58,8 +58,7 @@ | |||
288 | 58 | virtual NodeType type() const = 0; | 58 | virtual NodeType type() const = 0; |
289 | 59 | 59 | ||
290 | 60 | virtual std::string as_string() const = 0; | 60 | virtual std::string as_string() const = 0; |
293 | 61 | virtual int as_int() const = 0; | 61 | virtual int64_t as_int() const = 0; |
292 | 62 | virtual unsigned int as_uint() const = 0; | ||
294 | 63 | virtual double as_double() const = 0; | 62 | virtual double as_double() const = 0; |
295 | 64 | virtual bool as_bool() const = 0; | 63 | virtual bool as_bool() const = 0; |
296 | 65 | 64 | ||
297 | 66 | 65 | ||
298 | === modified file 'include/unity/scopes/internal/JsonSettingsSchema.h' | |||
299 | --- include/unity/scopes/internal/JsonSettingsSchema.h 2014-11-03 05:31:30 +0000 | |||
300 | +++ include/unity/scopes/internal/JsonSettingsSchema.h 2016-06-17 07:24:44 +0000 | |||
301 | @@ -49,7 +49,7 @@ | |||
302 | 49 | void add_location_setting() override; | 49 | void add_location_setting() override; |
303 | 50 | 50 | ||
304 | 51 | private: | 51 | private: |
306 | 52 | JsonSettingsSchema(std::string const& ini_file); | 52 | JsonSettingsSchema(std::string const& json_string); |
307 | 53 | 53 | ||
308 | 54 | JsonSettingsSchema(); | 54 | JsonSettingsSchema(); |
309 | 55 | 55 | ||
310 | 56 | 56 | ||
311 | === added file 'include/unity/scopes/internal/gobj_memory.h' | |||
312 | --- include/unity/scopes/internal/gobj_memory.h 1970-01-01 00:00:00 +0000 | |||
313 | +++ include/unity/scopes/internal/gobj_memory.h 2016-06-17 07:24:44 +0000 | |||
314 | @@ -0,0 +1,212 @@ | |||
315 | 1 | /* | ||
316 | 2 | * Copyright (C) 2013 Canonical Ltd. | ||
317 | 3 | * | ||
318 | 4 | * This program is free software: you can redistribute it and/or modify | ||
319 | 5 | * it under the terms of the GNU Lesser General Public License version 3 as | ||
320 | 6 | * published by the Free Software Foundation. | ||
321 | 7 | * | ||
322 | 8 | * This program is distributed in the hope that it will be useful, | ||
323 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
324 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
325 | 11 | * GNU Lesser General Public License for more details. | ||
326 | 12 | * | ||
327 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
328 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
329 | 15 | * | ||
330 | 16 | * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> | ||
331 | 17 | */ | ||
332 | 18 | |||
333 | 19 | #pragma once | ||
334 | 20 | |||
335 | 21 | #include <stdexcept> | ||
336 | 22 | |||
337 | 23 | #pragma GCC diagnostic push | ||
338 | 24 | #pragma GCC diagnostic ignored "-Wold-style-cast" | ||
339 | 25 | #pragma GCC diagnostic ignored "-Wcast-qual" | ||
340 | 26 | #include <glib-object.h> | ||
341 | 27 | |||
342 | 28 | namespace unity | ||
343 | 29 | { | ||
344 | 30 | |||
345 | 31 | namespace scopes | ||
346 | 32 | { | ||
347 | 33 | |||
348 | 34 | namespace internal | ||
349 | 35 | { | ||
350 | 36 | |||
351 | 37 | /** | ||
352 | 38 | * This class is meant for automatically managing the lifetime of C objects derived | ||
353 | 39 | * from gobject. Its API perfectly mirrors the API of unique_ptr except that you | ||
354 | 40 | * can't define your own deleter function as it is always g_object_unref. | ||
355 | 41 | * | ||
356 | 42 | * API/ABI stability is not guaranteed. If you need to pass the object across an ABI | ||
357 | 43 | * boundary, pass the plain gobject. | ||
358 | 44 | * | ||
359 | 45 | * This is how you would use gobj_ptr 99% of the time: | ||
360 | 46 | * | ||
361 | 47 | * gobj_ptr<GSomeType> o(g_some_type_new(...)); | ||
362 | 48 | * | ||
363 | 49 | * More specifically, the object will decrement the gobject reference count | ||
364 | 50 | * of the object it points to when it goes out of scope. It will never increment it. | ||
365 | 51 | * Thus you should only assign to it when already holding a reference. gobj_ptr | ||
366 | 52 | * will then take ownership of that particular reference. | ||
367 | 53 | * | ||
368 | 54 | * Floating gobjects can not be put in this container as they are meant to be put | ||
369 | 55 | * into native gobject aware containers immediately upon construction. Trying to insert | ||
370 | 56 | * a floating gobject into a gobj_ptr will throw an invalid_argument exception. To | ||
371 | 57 | * prevent accidental memory leaks, the floating gobject is unreffed in this case. | ||
372 | 58 | */ | ||
373 | 59 | template <typename T> | ||
374 | 60 | class gobj_ptr final | ||
375 | 61 | { | ||
376 | 62 | private: | ||
377 | 63 | T* u; | ||
378 | 64 | |||
379 | 65 | void validate_float(T* t) | ||
380 | 66 | { | ||
381 | 67 | if (t != nullptr && g_object_is_floating(G_OBJECT(t))) | ||
382 | 68 | { | ||
383 | 69 | // LCOV_EXCL_START // False negative from gcovr. | ||
384 | 70 | throw std::invalid_argument("Tried to add a floating gobject into a gobj_ptr."); | ||
385 | 71 | // LCOV_EXCL_STOP | ||
386 | 72 | } | ||
387 | 73 | } | ||
388 | 74 | |||
389 | 75 | public: | ||
390 | 76 | typedef T element_type; | ||
391 | 77 | typedef T* pointer; | ||
392 | 78 | typedef decltype(g_object_unref) deleter_type; | ||
393 | 79 | |||
394 | 80 | constexpr gobj_ptr() noexcept : u(nullptr) | ||
395 | 81 | { | ||
396 | 82 | } | ||
397 | 83 | explicit gobj_ptr(T* t) | ||
398 | 84 | : u(t) | ||
399 | 85 | { | ||
400 | 86 | // What should we do if validate throws? Unreffing unknown objs | ||
401 | 87 | // is dodgy but not unreffing runs the risk of | ||
402 | 88 | // memory leaks. Currently unrefs as u is destroyed | ||
403 | 89 | // when this exception is thrown. | ||
404 | 90 | validate_float(t); | ||
405 | 91 | } | ||
406 | 92 | constexpr gobj_ptr(std::nullptr_t) noexcept : u(nullptr){}; | ||
407 | 93 | gobj_ptr(gobj_ptr&& o) noexcept | ||
408 | 94 | { | ||
409 | 95 | u = o.u; | ||
410 | 96 | o.u = nullptr; | ||
411 | 97 | } | ||
412 | 98 | gobj_ptr(const gobj_ptr& o) | ||
413 | 99 | : u(nullptr) | ||
414 | 100 | { | ||
415 | 101 | *this = o; | ||
416 | 102 | } | ||
417 | 103 | gobj_ptr& operator=(const gobj_ptr& o) | ||
418 | 104 | { | ||
419 | 105 | if (o.u != nullptr) | ||
420 | 106 | { | ||
421 | 107 | g_object_ref(o.u); | ||
422 | 108 | } | ||
423 | 109 | reset(o.u); | ||
424 | 110 | return *this; | ||
425 | 111 | } | ||
426 | 112 | ~gobj_ptr() | ||
427 | 113 | { | ||
428 | 114 | reset(); | ||
429 | 115 | } | ||
430 | 116 | |||
431 | 117 | deleter_type& get_deleter() noexcept | ||
432 | 118 | { | ||
433 | 119 | return g_object_unref; | ||
434 | 120 | } | ||
435 | 121 | deleter_type& get_deleter() const noexcept | ||
436 | 122 | { | ||
437 | 123 | return g_object_unref; | ||
438 | 124 | } | ||
439 | 125 | |||
440 | 126 | void swap(gobj_ptr<T>& o) noexcept | ||
441 | 127 | { | ||
442 | 128 | T* tmp = u; | ||
443 | 129 | u = o.u; | ||
444 | 130 | o.u = tmp; | ||
445 | 131 | } | ||
446 | 132 | void reset(pointer p = pointer()) | ||
447 | 133 | { | ||
448 | 134 | if (u != nullptr) | ||
449 | 135 | { | ||
450 | 136 | g_object_unref(G_OBJECT(u)); | ||
451 | 137 | u = nullptr; | ||
452 | 138 | } | ||
453 | 139 | // Same throw dilemma as in pointer constructor. | ||
454 | 140 | u = p; | ||
455 | 141 | validate_float(p); | ||
456 | 142 | } | ||
457 | 143 | |||
458 | 144 | T* release() noexcept | ||
459 | 145 | { | ||
460 | 146 | T* r = u; | ||
461 | 147 | u = nullptr; | ||
462 | 148 | return r; | ||
463 | 149 | } | ||
464 | 150 | T* get() const noexcept | ||
465 | 151 | { | ||
466 | 152 | return u; | ||
467 | 153 | } | ||
468 | 154 | |||
469 | 155 | T& operator*() const | ||
470 | 156 | { | ||
471 | 157 | return *u; | ||
472 | 158 | } | ||
473 | 159 | T* operator->() const noexcept | ||
474 | 160 | { | ||
475 | 161 | return u; | ||
476 | 162 | } | ||
477 | 163 | explicit operator bool() const noexcept | ||
478 | 164 | { | ||
479 | 165 | return u != nullptr; | ||
480 | 166 | } | ||
481 | 167 | |||
482 | 168 | gobj_ptr& operator=(gobj_ptr&& o) noexcept | ||
483 | 169 | { | ||
484 | 170 | reset(); | ||
485 | 171 | u = o.u; | ||
486 | 172 | o.u = nullptr; | ||
487 | 173 | return *this; | ||
488 | 174 | } | ||
489 | 175 | gobj_ptr& operator=(std::nullptr_t) noexcept | ||
490 | 176 | { | ||
491 | 177 | reset(); | ||
492 | 178 | return *this; | ||
493 | 179 | } | ||
494 | 180 | bool operator==(const gobj_ptr<T>& o) const noexcept | ||
495 | 181 | { | ||
496 | 182 | return u == o.u; | ||
497 | 183 | } | ||
498 | 184 | bool operator!=(const gobj_ptr<T>& o) const noexcept | ||
499 | 185 | { | ||
500 | 186 | return u != o.u; | ||
501 | 187 | } | ||
502 | 188 | bool operator<(const gobj_ptr<T>& o) const noexcept | ||
503 | 189 | { | ||
504 | 190 | return u < o.u; | ||
505 | 191 | } | ||
506 | 192 | bool operator<=(const gobj_ptr<T>& o) const noexcept | ||
507 | 193 | { | ||
508 | 194 | return u <= o.u; | ||
509 | 195 | } | ||
510 | 196 | bool operator>(const gobj_ptr<T>& o) const noexcept | ||
511 | 197 | { | ||
512 | 198 | return u > o.u; | ||
513 | 199 | } | ||
514 | 200 | bool operator>=(const gobj_ptr<T>& o) const noexcept | ||
515 | 201 | { | ||
516 | 202 | return u >= o.u; | ||
517 | 203 | } | ||
518 | 204 | }; | ||
519 | 205 | |||
520 | 206 | } // namespace internal | ||
521 | 207 | |||
522 | 208 | } // namespace scopes | ||
523 | 209 | |||
524 | 210 | } // namespace unity | ||
525 | 211 | |||
526 | 212 | #pragma GCC diagnostic pop | ||
527 | 0 | 213 | ||
528 | === modified file 'scoperegistry/scoperegistry.cpp' | |||
529 | --- scoperegistry/scoperegistry.cpp 2015-09-11 07:29:12 +0000 | |||
530 | +++ scoperegistry/scoperegistry.cpp 2016-06-17 07:24:44 +0000 | |||
531 | @@ -338,7 +338,6 @@ | |||
532 | 338 | convert_relative_attribute(inner_map, "navigation-background", scope_dir); | 338 | convert_relative_attribute(inner_map, "navigation-background", scope_dir); |
533 | 339 | app_attrs["page-header"] = Variant(inner_map); | 339 | app_attrs["page-header"] = Variant(inner_map); |
534 | 340 | } | 340 | } |
535 | 341 | convert_relative_attribute(app_attrs, "category-header-background", scope_dir); | ||
536 | 342 | mi->set_appearance_attributes(app_attrs); | 341 | mi->set_appearance_attributes(app_attrs); |
537 | 343 | 342 | ||
538 | 344 | mi->set_scope_directory(scope_dir.native()); | 343 | mi->set_scope_directory(scope_dir.native()); |
539 | 345 | 344 | ||
540 | === modified file 'src/scopes/CategoryRenderer.cpp' | |||
541 | --- src/scopes/CategoryRenderer.cpp 2016-03-08 10:09:42 +0000 | |||
542 | +++ src/scopes/CategoryRenderer.cpp 2016-06-17 07:24:44 +0000 | |||
543 | @@ -66,7 +66,7 @@ | |||
544 | 66 | \arg \c card-layout Specifies layout of the individual result cards; possible values: \c "vertical" (default), \c "horizontal" | 66 | \arg \c card-layout Specifies layout of the individual result cards; possible values: \c "vertical" (default), \c "horizontal" |
545 | 67 | \arg \c card-size Size of the result cards; possible values: \c "small", \c "medium" (default), \c "large"; when using <tt>"category-layout": "vertical-journal"</tt> any integer between 12 and 38 | 67 | \arg \c card-size Size of the result cards; possible values: \c "small", \c "medium" (default), \c "large"; when using <tt>"category-layout": "vertical-journal"</tt> any integer between 12 and 38 |
546 | 68 | \arg \c overlay Overlay text data on top of the art; boolean, default false | 68 | \arg \c overlay Overlay text data on top of the art; boolean, default false |
548 | 69 | \arg \c collapsed-rows Number of result rows displayed while the category is collapsed; possible values: any non-negative integer, where 0 fully expands the category (only affects grid and vertical journal) | 69 | \arg \c collapsed-rows Number of result rows displayed while the category is collapsed; possible values: any non-negative integer, where 0 fully expands the category (only affects grid) |
549 | 70 | \arg \c card-background Background color for the cards; string; URI in the format \verbatim color:///#rrggbb \endverbatim or \verbatim color:///color_name | 70 | \arg \c card-background Background color for the cards; string; URI in the format \verbatim color:///#rrggbb \endverbatim or \verbatim color:///color_name |
550 | 71 | \endverbatim or \verbatim gradient:///#rrggbb/#rrggbb \endverbatim or an image URI (will be stretched) | 71 | \endverbatim or \verbatim gradient:///#rrggbb/#rrggbb \endverbatim or an image URI (will be stretched) |
551 | 72 | \arg \c quick-preview-type The type of media content represented by result cards, for use with inline playback; the only currently supported type is "audio". | 72 | \arg \c quick-preview-type The type of media content represented by result cards, for use with inline playback; the only currently supported type is "audio". |
552 | 73 | 73 | ||
553 | === modified file 'src/scopes/PreviewWidget.cpp' | |||
554 | --- src/scopes/PreviewWidget.cpp 2016-01-18 19:50:19 +0000 | |||
555 | +++ src/scopes/PreviewWidget.cpp 2016-06-17 07:24:44 +0000 | |||
556 | @@ -431,15 +431,18 @@ | |||
557 | 431 | \subsection expandable expandable widget | 431 | \subsection expandable expandable widget |
558 | 432 | 432 | ||
559 | 433 | The expandable widget is used to group several widgets into an expandable pane. | 433 | The expandable widget is used to group several widgets into an expandable pane. |
560 | 434 | The expandable widget can be collapsed or uncollapsed. When it's uncollapsed then | ||
561 | 435 | all the contained widgets are shown. When collapsed, only the first few widgets determined | ||
562 | 436 | by collapsed-widgets attribute are shown. | ||
563 | 434 | 437 | ||
564 | 435 | List of attributes: | 438 | List of attributes: |
565 | 436 | \arg \c title A string specifying the title | 439 | \arg \c title A string specifying the title |
567 | 437 | \arg \c collapsed-widgets Optional number of collapsed widgets (0 makes all of them visible) | 440 | \arg \c collapsed-widgets A number of widgets to show when the expandable widget is collapsed (optional). |
568 | 438 | 441 | ||
569 | 439 | \code | 442 | \code |
570 | 440 | PreviewWidget expandable("exp", "expandable"); | 443 | PreviewWidget expandable("exp", "expandable"); |
571 | 441 | expandable.add_attribute_value("title", Variant("This is an expandable widget")); | 444 | expandable.add_attribute_value("title", Variant("This is an expandable widget")); |
573 | 442 | expandable.add_attribute_value("collapsed-widgets", Variant(0)); | 445 | expandable.add_attribute_value("collapsed-widgets", Variant(2)); |
574 | 443 | 446 | ||
575 | 444 | PreviewWidget w1("w1", "text"); | 447 | PreviewWidget w1("w1", "text"); |
576 | 445 | w1.add_attribute_value("title", Variant("Subwidget 1")); | 448 | w1.add_attribute_value("title", Variant("Subwidget 1")); |
577 | @@ -447,8 +450,12 @@ | |||
578 | 447 | PreviewWidget w2("w2", "text"); | 450 | PreviewWidget w2("w2", "text"); |
579 | 448 | w2.add_attribute_value("title", Variant("Subwidget 2")); | 451 | w2.add_attribute_value("title", Variant("Subwidget 2")); |
580 | 449 | w2.add_attribute_value("text", Variant("A text")); | 452 | w2.add_attribute_value("text", Variant("A text")); |
581 | 453 | PreviewWidget w3("w3", "text"); | ||
582 | 454 | w3.add_attribute_value("title", Variant("Subwidget 3")); | ||
583 | 455 | w3.add_attribute_value("text", Variant("A text")); | ||
584 | 450 | expandable.add_widget(w1); | 456 | expandable.add_widget(w1); |
585 | 451 | expandable.add_widget(w2); | 457 | expandable.add_widget(w2); |
586 | 458 | expandable.add_widget(w3); | ||
587 | 452 | ... | 459 | ... |
588 | 453 | \endcode | 460 | \endcode |
589 | 454 | 461 | ||
590 | 455 | 462 | ||
591 | === modified file 'src/scopes/internal/JsonCppNode.cpp' | |||
592 | --- src/scopes/internal/JsonCppNode.cpp 2015-11-02 05:08:08 +0000 | |||
593 | +++ src/scopes/internal/JsonCppNode.cpp 2016-06-17 07:24:44 +0000 | |||
594 | @@ -14,316 +14,399 @@ | |||
595 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
596 | 15 | * | 15 | * |
597 | 16 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> | 16 | * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
598 | 17 | * Michi Henning <michi.henning@canonical.com> | ||
599 | 17 | */ | 18 | */ |
600 | 18 | 19 | ||
601 | 19 | #include <unity/scopes/internal/JsonCppNode.h> | 20 | #include <unity/scopes/internal/JsonCppNode.h> |
602 | 21 | |||
603 | 20 | #include <unity/UnityExceptions.h> | 22 | #include <unity/UnityExceptions.h> |
604 | 21 | #include <jsoncpp/json/reader.h> | ||
605 | 22 | #include <jsoncpp/json/writer.h> | ||
606 | 23 | #include <sstream> | ||
607 | 24 | 23 | ||
608 | 24 | using namespace std; | ||
609 | 25 | using namespace unity::scopes; | 25 | using namespace unity::scopes; |
610 | 26 | using namespace unity::scopes::internal; | 26 | using namespace unity::scopes::internal; |
611 | 27 | 27 | ||
636 | 28 | JsonCppNode::JsonCppNode(std::string const& json_string) | 28 | void JsonCppNode::init_from_string(string const& json_string) |
637 | 29 | { | 29 | { |
638 | 30 | if (!json_string.empty()) | 30 | if (json_string.find_first_not_of(" \t\n") == std::string::npos) |
639 | 31 | { | 31 | { |
640 | 32 | read_json(json_string); | 32 | throw unity::ResourceException("JsonCppNode(): empty string is not a valid JSON"); |
641 | 33 | } | 33 | } |
642 | 34 | } | 34 | |
643 | 35 | 35 | gobj_ptr<JsonParser> parser(json_parser_new()); | |
644 | 36 | JsonCppNode::JsonCppNode(const Json::Value& root) | 36 | GError *err = nullptr; |
645 | 37 | : root_(root) | 37 | if (!json_parser_load_from_data(parser.get(), json_string.c_str(), json_string.size(), &err)) |
646 | 38 | { | 38 | { |
647 | 39 | } | 39 | string msg = string("JsonCppNode(); parse error: ") + err->message; |
648 | 40 | 40 | g_error_free(err); | |
649 | 41 | JsonCppNode::JsonCppNode(const Variant& var) | 41 | throw unity::ResourceException(msg); |
650 | 42 | { | 42 | } |
651 | 43 | root_ = from_variant(var); | 43 | root_.reset(json_node_copy(json_parser_get_root(parser.get()))); |
652 | 44 | } | 44 | } |
653 | 45 | 45 | ||
654 | 46 | JsonCppNode::~JsonCppNode() | 46 | JsonCppNode::JsonCppNode() |
655 | 47 | { | 47 | : root_(json_node_alloc(), json_node_free) |
656 | 48 | } | 48 | { |
657 | 49 | 49 | json_node_init_null(root_.get()); | |
658 | 50 | Json::Value JsonCppNode::from_variant(Variant const& var) | 50 | } |
659 | 51 | { | 51 | |
660 | 52 | JsonCppNode::JsonCppNode(string const& json_string) | ||
661 | 53 | : JsonCppNode() | ||
662 | 54 | { | ||
663 | 55 | init_from_string(json_string); | ||
664 | 56 | } | ||
665 | 57 | |||
666 | 58 | JsonCppNode::JsonCppNode(JsonNode* node) | ||
667 | 59 | : root_(json_node_copy(node), json_node_free) | ||
668 | 60 | { | ||
669 | 61 | } | ||
670 | 62 | |||
671 | 63 | namespace | ||
672 | 64 | { | ||
673 | 65 | |||
674 | 66 | // Allocates a new node for each value. Caller is responsible for deallocating the root node. | ||
675 | 67 | |||
676 | 68 | JsonNode* variant_to_node(Variant const& var) | ||
677 | 69 | { | ||
678 | 70 | unique_ptr<JsonNode, decltype(&json_node_free)> node_guard(json_node_alloc(), json_node_free); | ||
679 | 71 | auto node = node_guard.get(); | ||
680 | 52 | switch (var.which()) | 72 | switch (var.which()) |
681 | 53 | { | 73 | { |
682 | 74 | case Variant::Type::Null: | ||
683 | 75 | json_node_init_null(node); | ||
684 | 76 | break; | ||
685 | 77 | case Variant::Type::Array: | ||
686 | 78 | { | ||
687 | 79 | unique_ptr<JsonArray, decltype(&json_array_unref)> array(json_array_new(), json_array_unref); | ||
688 | 80 | for (auto const& v : var.get_array()) | ||
689 | 81 | { | ||
690 | 82 | json_array_add_element(array.get(), variant_to_node(v)); | ||
691 | 83 | } | ||
692 | 84 | json_node_init_array(node, array.get()); | ||
693 | 85 | break; | ||
694 | 86 | } | ||
695 | 87 | case Variant::Type::Dict: | ||
696 | 88 | { | ||
697 | 89 | unique_ptr<JsonObject, decltype(&json_object_unref)> object(json_object_new(), json_object_unref); | ||
698 | 90 | for (auto const& v : var.get_dict()) | ||
699 | 91 | { | ||
700 | 92 | json_object_set_member(object.get(), v.first.c_str(), variant_to_node(v.second)); | ||
701 | 93 | } | ||
702 | 94 | json_node_set_object(node, object.get()); | ||
703 | 95 | break; | ||
704 | 96 | } | ||
705 | 97 | case Variant::Type::String: | ||
706 | 98 | json_node_init_string(node, var.get_string().c_str()); | ||
707 | 99 | break; | ||
708 | 54 | case Variant::Type::Int: | 100 | case Variant::Type::Int: |
710 | 55 | return Json::Value(var.get_int()); | 101 | json_node_init_int(node, int64_t(var.get_int())); |
711 | 102 | break; | ||
712 | 56 | case Variant::Type::Int64: | 103 | case Variant::Type::Int64: |
714 | 57 | return Json::Value(static_cast<Json::Int64>(var.get_int64_t())); | 104 | json_node_init_int(node, var.get_int64_t()); |
715 | 105 | break; | ||
716 | 106 | case Variant::Type::Double: | ||
717 | 107 | json_node_init_double(node, var.get_double()); | ||
718 | 108 | break; | ||
719 | 58 | case Variant::Type::Bool: | 109 | case Variant::Type::Bool: |
745 | 59 | return Json::Value(var.get_bool()); | 110 | { |
746 | 60 | case Variant::Type::String: | 111 | json_node_init_boolean(node, var.get_bool()); |
747 | 61 | return Json::Value(var.get_string()); | 112 | break; |
748 | 62 | case Variant::Type::Double: | 113 | } |
724 | 63 | return Json::Value(var.get_double()); | ||
725 | 64 | case Variant::Type::Dict: | ||
726 | 65 | { | ||
727 | 66 | Json::Value val(Json::ValueType::objectValue); | ||
728 | 67 | for (auto const& v: var.get_dict()) | ||
729 | 68 | { | ||
730 | 69 | val[v.first] = from_variant(v.second); | ||
731 | 70 | } | ||
732 | 71 | return val; | ||
733 | 72 | } | ||
734 | 73 | case Variant::Type::Array: | ||
735 | 74 | { | ||
736 | 75 | Json::Value val(Json::ValueType::arrayValue); | ||
737 | 76 | for (auto const& v: var.get_array()) | ||
738 | 77 | { | ||
739 | 78 | val.append(from_variant(v)); | ||
740 | 79 | } | ||
741 | 80 | return val; | ||
742 | 81 | } | ||
743 | 82 | case Variant::Type::Null: | ||
744 | 83 | return Json::Value(Json::ValueType::nullValue); | ||
749 | 84 | default: | 114 | default: |
756 | 85 | { | 115 | { |
757 | 86 | std::ostringstream s; | 116 | abort(); // LCOV_EXCL_LINE // Impossible |
758 | 87 | s << "JsonCppNode::from_variant(): unsupported variant type "; | 117 | } |
753 | 88 | s << static_cast<int>(var.which()); | ||
754 | 89 | throw unity::LogicException(s.str()); | ||
755 | 90 | } | ||
759 | 91 | } | 118 | } |
765 | 92 | } | 119 | return node_guard.release(); |
766 | 93 | 120 | } | |
767 | 94 | Variant JsonCppNode::to_variant(Json::Value const& value) | 121 | |
768 | 95 | { | 122 | } // namespace |
769 | 96 | switch (value.type()) | 123 | |
770 | 124 | JsonCppNode::JsonCppNode(Variant const& var) | ||
771 | 125 | : root_(variant_to_node(var), json_node_free) | ||
772 | 126 | { | ||
773 | 127 | } | ||
774 | 128 | |||
775 | 129 | #pragma GCC diagnostic push | ||
776 | 130 | #pragma GCC diagnostic ignored "-Wold-style-cast" | ||
777 | 131 | |||
778 | 132 | namespace | ||
779 | 133 | { | ||
780 | 134 | |||
781 | 135 | Variant node_to_variant(JsonNode* node); // Mutual recursion, need forward declaration. | ||
782 | 136 | |||
783 | 137 | extern "C" | ||
784 | 138 | void add_to_array(JsonArray* /* array */, guint /* index */, JsonNode* element_node, gpointer user_data) | ||
785 | 139 | { | ||
786 | 140 | VariantArray* va = reinterpret_cast<VariantArray*>(user_data); | ||
787 | 141 | va->push_back(node_to_variant(element_node)); | ||
788 | 142 | } | ||
789 | 143 | |||
790 | 144 | extern "C" | ||
791 | 145 | void add_to_map(JsonObject* /* object */, gchar const* member_name, JsonNode* member_node, gpointer user_data) | ||
792 | 146 | { | ||
793 | 147 | VariantMap* vm = reinterpret_cast<VariantMap*>(user_data); | ||
794 | 148 | (*vm)[member_name] = node_to_variant(member_node); | ||
795 | 149 | } | ||
796 | 150 | |||
797 | 151 | Variant node_to_variant(JsonNode* node) | ||
798 | 152 | { | ||
799 | 153 | switch (json_node_get_node_type(node)) | ||
800 | 97 | { | 154 | { |
802 | 98 | case Json::ValueType::nullValue: | 155 | case JSON_NODE_NULL: |
803 | 99 | return Variant::null(); | 156 | return Variant::null(); |
836 | 100 | case Json::ValueType::arrayValue: | 157 | case JSON_NODE_ARRAY: |
837 | 101 | { | 158 | { |
838 | 102 | VariantArray arr; | 159 | VariantArray va; |
839 | 103 | for (unsigned int i=0; i<value.size(); ++i) | 160 | auto array = json_node_get_array(node); |
840 | 104 | { | 161 | json_array_foreach_element(array, add_to_array, &va); |
841 | 105 | arr.push_back(to_variant(value[i])); | 162 | return Variant(va); |
842 | 106 | } | 163 | } |
843 | 107 | return Variant(arr); | 164 | case JSON_NODE_OBJECT: |
844 | 108 | } | 165 | { |
845 | 109 | case Json::ValueType::objectValue: | 166 | VariantMap vm; |
846 | 110 | { | 167 | auto object = json_node_get_object(node); |
847 | 111 | VariantMap var; | 168 | json_object_foreach_member(object, add_to_map, &vm); |
848 | 112 | for (auto const& m: value.getMemberNames()) | 169 | return Variant(vm); |
849 | 113 | { | 170 | } |
850 | 114 | var[m] = to_variant(value[m]); | 171 | case JSON_NODE_VALUE: |
851 | 115 | } | 172 | { |
852 | 116 | return Variant(var); | 173 | switch (json_node_get_value_type(node)) |
853 | 117 | } | 174 | { |
854 | 118 | case Json::ValueType::stringValue: | 175 | case G_TYPE_STRING: |
855 | 119 | return Variant(value.asString()); | 176 | return Variant(string(json_node_get_string(node))); |
856 | 120 | case Json::ValueType::intValue: | 177 | case G_TYPE_INT64: |
857 | 121 | case Json::ValueType::uintValue: | 178 | { |
858 | 122 | // this can throw std::runtime_error from jsoncpp if unsigned int to int conversion is not possible | 179 | // HACK: If the value fits into a 32-bit int, return an Int |
859 | 123 | if (value.isInt()) | 180 | // variant. Otherwise, return an Int64 variant. |
860 | 124 | { | 181 | int64_t val64 = json_node_get_int(node); |
861 | 125 | return Variant(value.asInt()); | 182 | if (val64 < INT32_MIN || val64 > INT32_MAX) |
862 | 126 | } | 183 | { |
863 | 127 | return Variant(static_cast<int64_t>(value.asInt64())); | 184 | return Variant(val64); |
864 | 128 | case Json::ValueType::realValue: | 185 | } |
865 | 129 | return Variant(value.asDouble()); | 186 | int32_t val32 = val64; |
866 | 130 | case Json::ValueType::booleanValue: | 187 | return Variant(val32); |
867 | 131 | return Variant(value.asBool()); | 188 | } |
868 | 189 | case G_TYPE_DOUBLE: | ||
869 | 190 | return Variant(json_node_get_double(node)); | ||
870 | 191 | case G_TYPE_BOOLEAN: | ||
871 | 192 | return Variant(bool(json_node_get_boolean(node))); | ||
872 | 193 | default: | ||
873 | 194 | abort(); // LCOV_EXCL_LINE // Impossible | ||
874 | 195 | } | ||
875 | 196 | } | ||
876 | 132 | default: | 197 | default: |
883 | 133 | { | 198 | abort(); // LCOV_EXCL_LINE // Impossible |
878 | 134 | std::ostringstream s; | ||
879 | 135 | s << "JsonCppNode::to_variant(): unsupported json type "; | ||
880 | 136 | s << static_cast<int>(value.type()); | ||
881 | 137 | throw unity::LogicException(s.str()); | ||
882 | 138 | } | ||
884 | 139 | } | 199 | } |
885 | 140 | } | 200 | } |
886 | 141 | 201 | ||
887 | 202 | } // namespace | ||
888 | 203 | |||
889 | 142 | Variant JsonCppNode::to_variant() const | 204 | Variant JsonCppNode::to_variant() const |
890 | 143 | { | 205 | { |
892 | 144 | return to_variant(root_); | 206 | return node_to_variant(root_.get()); |
893 | 145 | } | 207 | } |
894 | 146 | 208 | ||
895 | 147 | void JsonCppNode::clear() | 209 | void JsonCppNode::clear() |
896 | 148 | { | 210 | { |
915 | 149 | root_.clear(); | 211 | json_node_init_null(root_.get()); |
916 | 150 | } | 212 | } |
917 | 151 | 213 | ||
918 | 152 | void JsonCppNode::read_json(std::string const& json_string) | 214 | void JsonCppNode::read_json(string const& json_string) |
919 | 153 | { | 215 | { |
920 | 154 | Json::Reader reader; | 216 | init_from_string(json_string); |
921 | 155 | clear(); | 217 | } |
922 | 156 | 218 | ||
923 | 157 | if (!reader.parse(json_string, root_)) | 219 | string JsonCppNode::to_json_string() const |
924 | 158 | { | 220 | { |
925 | 159 | throw unity::ResourceException("Failed to parse json string: " + reader.getFormattedErrorMessages()); | 221 | gobj_ptr<JsonGenerator> generator(json_generator_new()); |
926 | 160 | } | 222 | json_generator_set_root(generator.get(), root_.get()); |
927 | 161 | } | 223 | |
928 | 162 | 224 | gsize len; | |
929 | 163 | std::string JsonCppNode::to_json_string() const | 225 | unique_ptr<gchar, decltype(&g_free)> data(json_generator_to_data(generator.get(), &len), g_free); |
930 | 164 | { | 226 | string result(data.get(), len); |
931 | 165 | Json::FastWriter writer; | 227 | result += '\n'; |
932 | 166 | return writer.write(root_); | 228 | return result; |
933 | 167 | } | 229 | } |
934 | 168 | 230 | ||
935 | 169 | int JsonCppNode::size() const | 231 | int JsonCppNode::size() const |
936 | 170 | { | 232 | { |
943 | 171 | return root_.size(); | 233 | switch (json_node_get_node_type(root_.get())) |
944 | 172 | } | 234 | { |
945 | 173 | 235 | case JSON_NODE_ARRAY: | |
946 | 174 | std::vector<std::string> JsonCppNode::member_names() const | 236 | { |
947 | 175 | { | 237 | auto array = json_node_get_array(root_.get()); |
948 | 176 | if (root_.type() != Json::objectValue) | 238 | return json_array_get_length(array); |
949 | 239 | } | ||
950 | 240 | case JSON_NODE_OBJECT: | ||
951 | 241 | { | ||
952 | 242 | auto object = json_node_get_object(root_.get()); | ||
953 | 243 | return json_object_get_size(object); | ||
954 | 244 | } | ||
955 | 245 | default: | ||
956 | 246 | return 0; | ||
957 | 247 | } | ||
958 | 248 | } | ||
959 | 249 | |||
960 | 250 | namespace | ||
961 | 251 | { | ||
962 | 252 | |||
963 | 253 | extern "C" | ||
964 | 254 | void add_name(JsonObject* /* object */, gchar const* member_name, JsonNode* /* member_node */, gpointer user_data) | ||
965 | 255 | { | ||
966 | 256 | vector<string>* names = reinterpret_cast<vector<string>*>(user_data); | ||
967 | 257 | names->push_back(member_name); | ||
968 | 258 | } | ||
969 | 259 | |||
970 | 260 | } | ||
971 | 261 | |||
972 | 262 | vector<string> JsonCppNode::member_names() const | ||
973 | 263 | { | ||
974 | 264 | if (!JSON_NODE_HOLDS_OBJECT(root_.get())) | ||
975 | 177 | { | 265 | { |
976 | 178 | throw unity::LogicException("Root node is not an object"); | 266 | throw unity::LogicException("Root node is not an object"); |
977 | 179 | } | 267 | } |
979 | 180 | return root_.getMemberNames(); | 268 | |
980 | 269 | vector<string> names; | ||
981 | 270 | auto object = json_node_get_object(root_.get()); | ||
982 | 271 | json_object_foreach_member(object, add_name, &names); | ||
983 | 272 | return names; | ||
984 | 181 | } | 273 | } |
985 | 182 | 274 | ||
986 | 183 | JsonNodeInterface::NodeType JsonCppNode::type() const | 275 | JsonNodeInterface::NodeType JsonCppNode::type() const |
987 | 184 | { | 276 | { |
989 | 185 | switch (root_.type()) | 277 | switch (json_node_get_node_type(root_.get())) |
990 | 186 | { | 278 | { |
992 | 187 | case Json::nullValue: | 279 | case JSON_NODE_NULL: |
993 | 188 | return Null; | 280 | return Null; |
995 | 189 | case Json::arrayValue: | 281 | case JSON_NODE_ARRAY: |
996 | 190 | return Array; | 282 | return Array; |
998 | 191 | case Json::objectValue: | 283 | case JSON_NODE_OBJECT: |
999 | 192 | return Object; | 284 | return Object; |
1010 | 193 | case Json::stringValue: | 285 | case JSON_NODE_VALUE: |
1011 | 194 | return String; | 286 | { |
1012 | 195 | case Json::intValue: | 287 | switch (json_node_get_value_type(root_.get())) |
1013 | 196 | return Int; | 288 | { |
1014 | 197 | case Json::uintValue: | 289 | case G_TYPE_STRING: |
1015 | 198 | return UInt; | 290 | return String; |
1016 | 199 | case Json::realValue: | 291 | case G_TYPE_INT64: |
1017 | 200 | return Real; | 292 | return Int; |
1018 | 201 | case Json::booleanValue: | 293 | case G_TYPE_DOUBLE: |
1019 | 202 | return Bool; | 294 | return Real; |
1020 | 295 | case G_TYPE_BOOLEAN: | ||
1021 | 296 | return Bool; | ||
1022 | 297 | default: | ||
1023 | 298 | abort(); // LCOV_EXCL_LINE // Impossible | ||
1024 | 299 | } | ||
1025 | 300 | } | ||
1026 | 203 | default: | 301 | default: |
1028 | 204 | break; | 302 | abort(); // LCOV_EXCL_LINE // Impossible |
1029 | 205 | } | 303 | } |
1030 | 206 | 304 | ||
1032 | 207 | return Null; | 305 | abort(); // LCOV_EXCL_LINE |
1033 | 208 | } | 306 | } |
1034 | 209 | 307 | ||
1036 | 210 | std::string JsonCppNode::as_string() const | 308 | string JsonCppNode::as_string() const |
1037 | 211 | { | 309 | { |
1039 | 212 | if (!root_.isConvertibleTo(Json::stringValue)) | 310 | if (JSON_NODE_HOLDS_NULL(root_.get())) |
1040 | 311 | { | ||
1041 | 312 | return string(); | ||
1042 | 313 | } | ||
1043 | 314 | if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_STRING) | ||
1044 | 213 | { | 315 | { |
1045 | 214 | throw unity::LogicException("Node does not contain a string value"); | 316 | throw unity::LogicException("Node does not contain a string value"); |
1046 | 215 | } | 317 | } |
1047 | 216 | 318 | ||
1049 | 217 | return root_.asString(); | 319 | return string(json_node_get_string(root_.get())); |
1050 | 218 | } | 320 | } |
1051 | 219 | 321 | ||
1053 | 220 | int JsonCppNode::as_int() const | 322 | int64_t JsonCppNode::as_int() const |
1054 | 221 | { | 323 | { |
1056 | 222 | if (!root_.isConvertibleTo(Json::intValue)) | 324 | if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_INT64) |
1057 | 223 | { | 325 | { |
1058 | 224 | throw unity::LogicException("Node does not contain an int value"); | 326 | throw unity::LogicException("Node does not contain an int value"); |
1059 | 225 | } | 327 | } |
1060 | 226 | 328 | ||
1072 | 227 | return root_.asInt(); | 329 | return json_node_get_int(root_.get()); |
1062 | 228 | } | ||
1063 | 229 | |||
1064 | 230 | unsigned int JsonCppNode::as_uint() const | ||
1065 | 231 | { | ||
1066 | 232 | if (!root_.isConvertibleTo(Json::uintValue)) | ||
1067 | 233 | { | ||
1068 | 234 | throw unity::LogicException("Node does not contain a unsigned int value"); | ||
1069 | 235 | } | ||
1070 | 236 | |||
1071 | 237 | return root_.asUInt(); | ||
1073 | 238 | } | 330 | } |
1074 | 239 | 331 | ||
1075 | 240 | double JsonCppNode::as_double() const | 332 | double JsonCppNode::as_double() const |
1076 | 241 | { | 333 | { |
1078 | 242 | if (!root_.isConvertibleTo(Json::realValue)) | 334 | if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_DOUBLE) |
1079 | 243 | { | 335 | { |
1080 | 244 | throw unity::LogicException("Node does not contain a double value"); | 336 | throw unity::LogicException("Node does not contain a double value"); |
1081 | 245 | } | 337 | } |
1082 | 246 | 338 | ||
1084 | 247 | return root_.asDouble(); | 339 | return json_node_get_double(root_.get()); |
1085 | 248 | } | 340 | } |
1086 | 249 | 341 | ||
1087 | 250 | bool JsonCppNode::as_bool() const | 342 | bool JsonCppNode::as_bool() const |
1088 | 251 | { | 343 | { |
1090 | 252 | if (!root_.isConvertibleTo(Json::booleanValue)) | 344 | if (!JSON_NODE_HOLDS_VALUE(root_.get()) || json_node_get_value_type(root_.get()) != G_TYPE_BOOLEAN) |
1091 | 253 | { | 345 | { |
1092 | 254 | throw unity::LogicException("Node does not contain a bool value"); | 346 | throw unity::LogicException("Node does not contain a bool value"); |
1093 | 255 | } | 347 | } |
1094 | 256 | 348 | ||
1096 | 257 | return root_.asBool(); | 349 | return json_node_get_boolean(root_.get()); |
1097 | 258 | } | 350 | } |
1098 | 259 | 351 | ||
1100 | 260 | bool JsonCppNode::has_node(std::string const& node_name) const | 352 | #pragma GCC diagnostic pop |
1101 | 353 | |||
1102 | 354 | bool JsonCppNode::has_node(string const& node_name) const | ||
1103 | 261 | { | 355 | { |
1105 | 262 | if (!root_) | 356 | if (JSON_NODE_HOLDS_NULL(root_.get())) |
1106 | 263 | { | 357 | { |
1107 | 264 | throw unity::LogicException("Current node is empty"); | 358 | throw unity::LogicException("Current node is empty"); |
1108 | 265 | } | 359 | } |
1109 | 266 | 360 | ||
1111 | 267 | if (root_.type() != Json::objectValue) | 361 | if (!JSON_NODE_HOLDS_OBJECT(root_.get())) |
1112 | 268 | { | 362 | { |
1113 | 269 | throw unity::LogicException("Root node is not an object"); | 363 | throw unity::LogicException("Root node is not an object"); |
1114 | 270 | } | 364 | } |
1115 | 271 | 365 | ||
1117 | 272 | return root_.isMember(node_name); | 366 | return json_object_has_member(json_node_get_object(root_.get()), node_name.c_str()); |
1118 | 273 | } | 367 | } |
1119 | 274 | 368 | ||
1120 | 275 | JsonNodeInterface::SPtr JsonCppNode::get_node() const | 369 | JsonNodeInterface::SPtr JsonCppNode::get_node() const |
1121 | 276 | { | 370 | { |
1123 | 277 | if (!root_) | 371 | if (JSON_NODE_HOLDS_NULL(root_.get())) |
1124 | 278 | { | 372 | { |
1125 | 279 | throw unity::LogicException("Current node is empty"); | 373 | throw unity::LogicException("Current node is empty"); |
1126 | 280 | } | 374 | } |
1127 | 281 | 375 | ||
1129 | 282 | return std::make_shared<JsonCppNode>(root_); | 376 | return make_shared<JsonCppNode>(root_.get()); |
1130 | 283 | } | 377 | } |
1131 | 284 | 378 | ||
1133 | 285 | JsonNodeInterface::SPtr JsonCppNode::get_node(std::string const& node_name) const | 379 | JsonNodeInterface::SPtr JsonCppNode::get_node(string const& node_name) const |
1134 | 286 | { | 380 | { |
1145 | 287 | if (!root_) | 381 | if (!has_node(node_name)) |
1136 | 288 | { | ||
1137 | 289 | throw unity::LogicException("Current node is empty"); | ||
1138 | 290 | } | ||
1139 | 291 | |||
1140 | 292 | if (root_.type() != Json::objectValue) | ||
1141 | 293 | { | ||
1142 | 294 | throw unity::LogicException("Root node is not an object"); | ||
1143 | 295 | } | ||
1144 | 296 | if (!root_.isMember(node_name)) | ||
1146 | 297 | { | 382 | { |
1147 | 298 | throw unity::LogicException("Node " + node_name + " does not exist"); | 383 | throw unity::LogicException("Node " + node_name + " does not exist"); |
1148 | 299 | } | 384 | } |
1149 | 300 | 385 | ||
1152 | 301 | const Json::Value& value_node = root_[node_name]; | 386 | auto object = json_node_get_object(root_.get()); |
1153 | 302 | return std::make_shared<JsonCppNode>(value_node); | 387 | auto member = json_object_get_member(object, node_name.c_str()); |
1154 | 388 | return make_shared<JsonCppNode>(member); | ||
1155 | 303 | } | 389 | } |
1156 | 304 | 390 | ||
1157 | 305 | JsonNodeInterface::SPtr JsonCppNode::get_node(unsigned int node_index) const | 391 | JsonNodeInterface::SPtr JsonCppNode::get_node(unsigned int node_index) const |
1158 | 306 | { | 392 | { |
1160 | 307 | if (!root_) | 393 | if (JSON_NODE_HOLDS_NULL(root_.get())) |
1161 | 308 | { | 394 | { |
1162 | 309 | throw unity::LogicException("Current node is empty"); | 395 | throw unity::LogicException("Current node is empty"); |
1163 | 310 | } | 396 | } |
1164 | 311 | 397 | ||
1166 | 312 | if (root_.type() != Json::arrayValue) | 398 | if (!JSON_NODE_HOLDS_ARRAY(root_.get())) |
1167 | 313 | { | 399 | { |
1168 | 314 | throw unity::LogicException("Root node is not an array"); | 400 | throw unity::LogicException("Root node is not an array"); |
1169 | 315 | } | 401 | } |
1183 | 316 | else if (node_index >= root_.size()) | 402 | |
1184 | 317 | { | 403 | auto array = json_node_get_array(root_.get()); |
1185 | 318 | throw unity::LogicException("Invalid array index"); | 404 | auto size = json_array_get_length(array); |
1186 | 319 | } | 405 | if (node_index >= size) |
1187 | 320 | 406 | { | |
1188 | 321 | const Json::Value& value_node = root_[node_index]; | 407 | throw unity::LogicException("Invalid array index: " + to_string(node_index)); |
1189 | 322 | 408 | } | |
1190 | 323 | if (!value_node) | 409 | |
1191 | 324 | { | 410 | auto element = json_array_get_element(array, node_index); |
1192 | 325 | throw unity::LogicException("Node " + std::to_string(node_index) + " does not exist"); | 411 | return make_shared<JsonCppNode>(element); |
1180 | 326 | } | ||
1181 | 327 | |||
1182 | 328 | return std::make_shared <JsonCppNode> (value_node); | ||
1193 | 329 | } | 412 | } |
1194 | 330 | 413 | ||
1195 | === modified file 'src/scopes/internal/JsonSettingsSchema.cpp' | |||
1196 | --- src/scopes/internal/JsonSettingsSchema.cpp 2015-03-02 03:59:01 +0000 | |||
1197 | +++ src/scopes/internal/JsonSettingsSchema.cpp 2016-06-17 07:24:44 +0000 | |||
1198 | @@ -19,10 +19,10 @@ | |||
1199 | 19 | #include <unity/scopes/internal/JsonSettingsSchema.h> | 19 | #include <unity/scopes/internal/JsonSettingsSchema.h> |
1200 | 20 | 20 | ||
1201 | 21 | #include <unity/scopes/internal/DfltConfig.h> | 21 | #include <unity/scopes/internal/DfltConfig.h> |
1202 | 22 | #include <unity/scopes/internal/JsonCppNode.h> | ||
1203 | 22 | 23 | ||
1204 | 23 | #include <boost/algorithm/string/predicate.hpp> | 24 | #include <boost/algorithm/string/predicate.hpp> |
1205 | 24 | #include <boost/filesystem.hpp> | 25 | #include <boost/filesystem.hpp> |
1206 | 25 | #include <jsoncpp/json/json.h> | ||
1207 | 26 | #include <unity/UnityExceptions.h> | 26 | #include <unity/UnityExceptions.h> |
1208 | 27 | 27 | ||
1209 | 28 | #include <set> | 28 | #include <set> |
1210 | @@ -52,7 +52,7 @@ | |||
1211 | 52 | public: | 52 | public: |
1212 | 53 | NONCOPYABLE(Setting); | 53 | NONCOPYABLE(Setting); |
1213 | 54 | 54 | ||
1215 | 55 | Setting(Json::Value const& v); | 55 | Setting(Variant const& v); |
1216 | 56 | Setting(string const& id, | 56 | Setting(string const& id, |
1217 | 57 | string const& type, | 57 | string const& type, |
1218 | 58 | string const& display_name, | 58 | string const& display_name, |
1219 | @@ -68,13 +68,13 @@ | |||
1220 | 68 | 68 | ||
1221 | 69 | private: | 69 | private: |
1222 | 70 | 70 | ||
1230 | 71 | Json::Value get_mandatory(Json::Value const& v, Json::StaticString const& key, Json::ValueType expected_type) const; | 71 | Variant get_mandatory(Variant const& v, string const& key, Variant::Type expected_type) const; |
1231 | 72 | void set_default_value(Json::Value const& v, Type expected_type); | 72 | void set_default_value(Variant const& v, Type expected_type); |
1232 | 73 | Variant get_bool_default(Json::Value const& v) const; | 73 | Variant get_bool_default(Variant const& v) const; |
1233 | 74 | Variant get_enum_default(Json::Value const& v); | 74 | Variant get_enum_default(Variant const& v); |
1234 | 75 | Variant get_double_default(Json::Value const& v) const; | 75 | Variant get_double_default(Variant const& v) const; |
1235 | 76 | Variant get_string_default(Json::Value const& v) const; | 76 | Variant get_string_default(Variant const& v) const; |
1236 | 77 | void set_enumerators(Json::Value const& v); | 77 | void set_enumerators(Variant const& v); |
1237 | 78 | 78 | ||
1238 | 79 | string id_; | 79 | string id_; |
1239 | 80 | string type_; | 80 | string type_; |
1240 | @@ -90,32 +90,32 @@ | |||
1241 | 90 | { "string", Setting::StringT }, | 90 | { "string", Setting::StringT }, |
1242 | 91 | }; | 91 | }; |
1243 | 92 | 92 | ||
1245 | 93 | Setting::Setting(Json::Value const& v) | 93 | Setting::Setting(Variant const& v) |
1246 | 94 | { | 94 | { |
1254 | 95 | assert(v.isObject()); | 95 | assert(v.which() == Variant::Type::Dict); |
1255 | 96 | 96 | ||
1256 | 97 | static auto const id_key = Json::StaticString("id"); | 97 | static string const id_key = "id"; |
1257 | 98 | static auto const type_key = Json::StaticString("type"); | 98 | static string const type_key = "type"; |
1258 | 99 | static auto const display_name_key = Json::StaticString("displayName"); | 99 | static string const display_name_key = "displayName"; |
1259 | 100 | 100 | ||
1260 | 101 | id_ = get_mandatory(v, id_key, Json::stringValue).asString(); | 101 | id_ = get_mandatory(v, id_key, Variant::Type::String).get_string(); |
1261 | 102 | if (id_.empty()) | 102 | if (id_.empty()) |
1262 | 103 | { | 103 | { |
1264 | 104 | throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + id_key.c_str() + "\" definition"); | 104 | throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + id_key + "\" definition"); |
1265 | 105 | } | 105 | } |
1266 | 106 | 106 | ||
1269 | 107 | auto v_type = get_mandatory(v, type_key, Json::stringValue); | 107 | auto v_type = get_mandatory(v, type_key, Variant::Type::String); |
1270 | 108 | string type_string = v_type.asString(); | 108 | string type_string = v_type.get_string(); |
1271 | 109 | auto const it = VALID_TYPES.find(type_string); | 109 | auto const it = VALID_TYPES.find(type_string); |
1272 | 110 | if (it == VALID_TYPES.end()) | 110 | if (it == VALID_TYPES.end()) |
1273 | 111 | { | 111 | { |
1276 | 112 | throw ResourceException(string("JsonSettingsSchema(): invalid \"") + type_key.c_str() + "\" setting: \"" | 112 | throw ResourceException(string("JsonSettingsSchema(): invalid \"") + type_key + "\" definition: \"" |
1277 | 113 | + type_string + "\", " "id = \"" + id_ + "\""); | 113 | + type_string + "\", " "id = \"" + id_ + "\""); |
1278 | 114 | } | 114 | } |
1279 | 115 | type_ = it->first; | 115 | type_ = it->first; |
1280 | 116 | set_default_value(v, it->second); | 116 | set_default_value(v, it->second); |
1281 | 117 | 117 | ||
1283 | 118 | display_name_ = get_mandatory(v, display_name_key, Json::stringValue).asString(); | 118 | display_name_ = get_mandatory(v, display_name_key, Variant::Type::String).get_string(); |
1284 | 119 | } | 119 | } |
1285 | 120 | 120 | ||
1286 | 121 | Setting::Setting(string const& id, | 121 | Setting::Setting(string const& id, |
1287 | @@ -131,11 +131,7 @@ | |||
1288 | 131 | assert(!id.empty()); | 131 | assert(!id.empty()); |
1289 | 132 | 132 | ||
1290 | 133 | auto const it = VALID_TYPES.find(type); | 133 | auto const it = VALID_TYPES.find(type); |
1296 | 134 | if (it == VALID_TYPES.end()) | 134 | assert(it != VALID_TYPES.end()); |
1292 | 135 | { | ||
1293 | 136 | throw ResourceException(string("JsonSettingsSchema(): invalid \"type\" definition: \"") | ||
1294 | 137 | + type + "\", setting = \"" + id_ + "\""); | ||
1295 | 138 | } | ||
1297 | 139 | type_ = it->first; | 135 | type_ = it->first; |
1298 | 140 | } | 136 | } |
1299 | 141 | 137 | ||
1300 | @@ -158,35 +154,33 @@ | |||
1301 | 158 | return Variant(schema); | 154 | return Variant(schema); |
1302 | 159 | } | 155 | } |
1303 | 160 | 156 | ||
1307 | 161 | Json::Value Setting::get_mandatory(Json::Value const& v, | 157 | Variant Setting::get_mandatory(Variant const& v, string const& key, Variant::Type expected_type) const |
1305 | 162 | Json::StaticString const& key, | ||
1306 | 163 | Json::ValueType expected_type) const | ||
1308 | 164 | { | 158 | { |
1312 | 165 | assert(v.isObject()); | 159 | assert(v.which() == Variant::Type::Dict); |
1313 | 166 | auto val = v[key]; | 160 | auto val = v.get_dict()[key]; |
1314 | 167 | if (val.isNull()) | 161 | if (val.is_null()) |
1315 | 168 | { | 162 | { |
1318 | 169 | throw ResourceException(string("JsonSettingsSchema(): missing \"") + key.c_str() + "\" definition" | 163 | throw ResourceException(string("JsonSettingsSchema(): missing \"") + key + "\" definition" |
1319 | 170 | + (!id_.empty() ? ", id = \"" + id_ + "\"" : string())); | 164 | + (!id_.empty() ? ", id = \"" + id_ + "\"" : string())); |
1320 | 171 | } | 165 | } |
1322 | 172 | if (val.type() != expected_type) | 166 | if (val.which() != expected_type) |
1323 | 173 | { | 167 | { |
1326 | 174 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + key.c_str() + "\" definition, " | 168 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + key |
1327 | 175 | + "id = \"" + id_ + "\""); | 169 | + "\" definition, " + "id = \"" + id_ + "\""); |
1328 | 176 | } | 170 | } |
1329 | 177 | return val; | 171 | return val; |
1330 | 178 | } | 172 | } |
1331 | 179 | 173 | ||
1333 | 180 | static auto const parameters_key = Json::StaticString("parameters"); | 174 | static string const parameters_key = "parameters"; |
1334 | 181 | 175 | ||
1336 | 182 | void Setting::set_default_value(Json::Value const& v, Type expected_type) | 176 | void Setting::set_default_value(Variant const& v, Type expected_type) |
1337 | 183 | { | 177 | { |
1340 | 184 | auto v_param = v[parameters_key]; | 178 | auto v_param = v.get_dict()[parameters_key]; |
1341 | 185 | if (v_param.isNull()) | 179 | if (v_param.is_null()) |
1342 | 186 | { | 180 | { |
1343 | 187 | return; | 181 | return; |
1344 | 188 | } | 182 | } |
1346 | 189 | else if (!v_param.isObject()) | 183 | else if (v_param.which() != Variant::Type::Dict) |
1347 | 190 | { | 184 | { |
1348 | 191 | throw ResourceException("JsonSettingsSchema(): expected value of type object for \"parameters\", id = \"" + id_ + "\""); | 185 | throw ResourceException("JsonSettingsSchema(): expected value of type object for \"parameters\", id = \"" + id_ + "\""); |
1349 | 192 | } | 186 | } |
1350 | @@ -219,124 +213,120 @@ | |||
1351 | 219 | } | 213 | } |
1352 | 220 | } | 214 | } |
1353 | 221 | 215 | ||
1426 | 222 | static auto const dflt_key = Json::StaticString("defaultValue"); | 216 | static string const dflt_key = "defaultValue"; |
1427 | 223 | 217 | ||
1428 | 224 | Variant Setting::get_bool_default(Json::Value const& v) const | 218 | Variant Setting::get_bool_default(Variant const& v) const |
1429 | 225 | { | 219 | { |
1430 | 226 | if (v.isNull()) // No "parameters" key | 220 | assert(!v.is_null()); |
1431 | 227 | { | 221 | |
1432 | 228 | return Variant(); | 222 | auto v_dflt = v.get_dict()[dflt_key]; |
1433 | 229 | } | 223 | if (v_dflt.is_null()) |
1434 | 230 | auto v_dflt = v[dflt_key]; | 224 | { |
1435 | 231 | if (v_dflt.isNull()) | 225 | return Variant(); // No "defaultValue" key |
1436 | 232 | { | 226 | } |
1437 | 233 | return Variant(); // No "defaultValue" key | 227 | if (v_dflt.which() != Variant::Type::Bool) |
1438 | 234 | } | 228 | { |
1439 | 235 | if (!v_dflt.isBool()) | 229 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1440 | 236 | { | 230 | + "\" definition, id = \"" + id_ + "\""); |
1441 | 237 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() | 231 | } |
1442 | 238 | + "\" definition, id = \"" + id_ + "\""); | 232 | return v_dflt; |
1443 | 239 | } | 233 | } |
1444 | 240 | return Variant(v_dflt.asBool()); | 234 | |
1445 | 241 | } | 235 | Variant Setting::get_double_default(Variant const& v) const |
1446 | 242 | 236 | { | |
1447 | 243 | Variant Setting::get_double_default(Json::Value const& v) const | 237 | assert(!v.is_null()); |
1448 | 244 | { | 238 | |
1449 | 245 | if (v.isNull()) // No "parameters" key | 239 | auto v_dflt = v.get_dict()[dflt_key]; |
1450 | 246 | { | 240 | if (v_dflt.is_null()) |
1451 | 247 | return Variant(); | 241 | { |
1452 | 248 | } | 242 | return Variant(); // No "defaultValue" key |
1453 | 249 | auto v_dflt = v[dflt_key]; | 243 | } |
1454 | 250 | if (v_dflt.isNull()) | 244 | switch (v_dflt.which()) |
1455 | 251 | { | 245 | { |
1456 | 252 | return Variant(); // No "defaultValue" key | 246 | case Variant::Type::Int: |
1457 | 253 | } | 247 | return Variant(double(v_dflt.get_int())); |
1458 | 254 | if (!v_dflt.isNumeric()) | 248 | case Variant::Type::Int64: |
1459 | 255 | { | 249 | return Variant(double(v_dflt.get_int64_t())); |
1460 | 256 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() | 250 | case Variant::Type::Double: |
1461 | 257 | + "\" definition, id = \"" + id_ + "\""); | 251 | return v_dflt; |
1462 | 258 | } | 252 | default: |
1463 | 259 | return Variant(v_dflt.asDouble()); | 253 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1464 | 260 | } | 254 | + "\" definition, id = \"" + id_ + "\""); |
1465 | 261 | 255 | } | |
1466 | 262 | Variant Setting::get_enum_default(Json::Value const& v) | 256 | } |
1467 | 263 | { | 257 | |
1468 | 264 | assert(v.isObject()); | 258 | Variant Setting::get_enum_default(Variant const& v) |
1469 | 265 | 259 | { | |
1470 | 266 | if (v.isNull()) // No "parameters" key | 260 | assert(v.which() == Variant::Type::Dict); |
1471 | 267 | { | 261 | |
1472 | 268 | throw ResourceException(string("JsonSettingsSchema(): missing \"") + parameters_key.c_str() | 262 | auto v_dflt = v.get_dict()[dflt_key]; |
1473 | 269 | + "\" definition, id = \"" + id_ + "\""); | 263 | if (v_dflt.is_null()) |
1474 | 270 | } | 264 | { |
1475 | 271 | auto v_dflt = v[dflt_key]; | 265 | return Variant(); // No "defaultValue" key |
1476 | 272 | if (v_dflt.isNull()) | 266 | } |
1477 | 273 | { | 267 | if (v_dflt.which() != Variant::Type::Int) |
1478 | 274 | return Variant(); // No "defaultValue" key | 268 | { |
1479 | 275 | } | 269 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1480 | 276 | if (!v_dflt.isInt()) | 270 | + "\" definition, id = \"" + id_ + "\""); |
1481 | 277 | { | 271 | } |
1482 | 278 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() | 272 | |
1483 | 279 | + "\" definition, id = \"" + id_ + "\""); | 273 | static string const values_key = "values"; |
1484 | 280 | } | 274 | |
1485 | 281 | 275 | auto v_vals = v.get_dict()[values_key]; | |
1486 | 282 | static auto const values_key = Json::StaticString("values"); | 276 | if (v_vals.which() != Variant::Type::Array) |
1487 | 283 | 277 | { | |
1488 | 284 | auto v_vals = v[values_key]; | 278 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + values_key |
1489 | 285 | if (!v_vals.isArray()) | 279 | + "\" definition, id = \"" + id_ + "\""); |
1490 | 286 | { | 280 | } |
1491 | 287 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + values_key.c_str() | 281 | if (v_vals.get_array().size() == 0) |
1492 | 288 | + "\" definition, id = \"" + id_ + "\""); | 282 | { |
1493 | 289 | } | 283 | throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + values_key |
1494 | 290 | if (v_vals.size() < 1) | 284 | + "\" definition, id = \"" + id_ + "\""); |
1423 | 291 | { | ||
1424 | 292 | throw ResourceException(string("JsonSettingsSchema(): invalid empty \"") + values_key.c_str() | ||
1425 | 293 | + "\" definition, id = \"" + id_ + "\""); | ||
1495 | 294 | } | 285 | } |
1496 | 295 | 286 | ||
1497 | 296 | set_enumerators(v_vals); | 287 | set_enumerators(v_vals); |
1498 | 297 | 288 | ||
1501 | 298 | auto val = v_dflt.asInt(); | 289 | auto val = v_dflt.get_int(); |
1502 | 299 | if (val < 0 || val >= static_cast<int>(v_vals.size())) | 290 | if (val < 0 || val >= static_cast<int>(v_vals.get_array().size())) |
1503 | 300 | { | 291 | { |
1506 | 301 | throw ResourceException(string("JsonSettingsSchema(): \"") + dflt_key.c_str() | 292 | throw ResourceException(string("JsonSettingsSchema(): \"") + dflt_key |
1507 | 302 | + "\" out of range, id = \"" + id_ + "\""); | 293 | + "\" out of range, id = \"" + id_ + "\""); |
1508 | 303 | } | 294 | } |
1510 | 304 | return Variant(v_dflt.asInt()); | 295 | return v_dflt; |
1511 | 305 | } | 296 | } |
1512 | 306 | 297 | ||
1514 | 307 | Variant Setting::get_string_default(Json::Value const& v) const | 298 | Variant Setting::get_string_default(Variant const& v) const |
1515 | 308 | { | 299 | { |
1522 | 309 | if (v.isNull()) // No "parameters" key | 300 | assert(!v.is_null()); |
1523 | 310 | { | 301 | |
1524 | 311 | return Variant(); | 302 | auto v_dflt = v.get_dict()[dflt_key]; |
1525 | 312 | } | 303 | if (v_dflt.is_null()) |
1520 | 313 | auto v_dflt = v[dflt_key]; | ||
1521 | 314 | if (v_dflt.isNull()) | ||
1526 | 315 | { | 304 | { |
1527 | 316 | return Variant(); // No "defaultValue" key | 305 | return Variant(); // No "defaultValue" key |
1528 | 317 | } | 306 | } |
1530 | 318 | if (!v_dflt.isString()) | 307 | if (v_dflt.which() != Variant::Type::String) |
1531 | 319 | { | 308 | { |
1534 | 320 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key.c_str() | 309 | throw ResourceException(string("JsonSettingsSchema(): invalid value type for \"") + dflt_key |
1535 | 321 | + "\" definition, id = \"" + id_ + "\""); | 310 | + "\" definition, id = \"" + id_ + "\""); |
1536 | 322 | } | 311 | } |
1538 | 323 | return Variant(v_dflt.asString()); | 312 | return v_dflt; |
1539 | 324 | } | 313 | } |
1540 | 325 | 314 | ||
1542 | 326 | void Setting::set_enumerators(Json::Value const& v) | 315 | void Setting::set_enumerators(Variant const& v) |
1543 | 327 | { | 316 | { |
1545 | 328 | assert(v.isArray()); | 317 | assert(v.which() == Variant::Type::Array); |
1546 | 329 | 318 | ||
1547 | 330 | set<string> enums_seen; | 319 | set<string> enums_seen; |
1548 | 331 | 320 | ||
1550 | 332 | for (unsigned i = 0; i < v.size(); ++i) | 321 | VariantArray va = v.get_array(); |
1551 | 322 | for (unsigned i = 0; i < va.size(); ++i) | ||
1552 | 333 | { | 323 | { |
1555 | 334 | Json::Value enumerator = v[i]; | 324 | Variant enumerator = v.get_array()[i]; |
1556 | 335 | if (!enumerator.isString()) | 325 | if (enumerator.which() != Variant::Type::String) |
1557 | 336 | { | 326 | { |
1558 | 337 | throw ResourceException(string("JsonSettingsSchema(): invalid enumerator type, id = \"") + id_ + "\""); | 327 | throw ResourceException(string("JsonSettingsSchema(): invalid enumerator type, id = \"") + id_ + "\""); |
1559 | 338 | } | 328 | } |
1561 | 339 | string enum_str = enumerator.asString(); | 329 | string enum_str = enumerator.get_string(); |
1562 | 340 | if (enum_str.empty()) | 330 | if (enum_str.empty()) |
1563 | 341 | { | 331 | { |
1564 | 342 | throw ResourceException(string("JsonSettingsSchema(): invalid empty enumerator, id = \"") + id_ + "\""); | 332 | throw ResourceException(string("JsonSettingsSchema(): invalid empty enumerator, id = \"") + id_ + "\""); |
1565 | @@ -347,7 +337,7 @@ | |||
1566 | 347 | + "\", id = \"" + id_ + "\""); | 337 | + "\", id = \"" + id_ + "\""); |
1567 | 348 | } | 338 | } |
1568 | 349 | enums_seen.insert(enum_str); | 339 | enums_seen.insert(enum_str); |
1570 | 350 | enumerators_.emplace_back(Variant(enum_str)); | 340 | enumerators_.emplace_back(enumerator); |
1571 | 351 | } | 341 | } |
1572 | 352 | } | 342 | } |
1573 | 353 | 343 | ||
1574 | @@ -367,39 +357,36 @@ | |||
1575 | 367 | { | 357 | { |
1576 | 368 | try | 358 | try |
1577 | 369 | { | 359 | { |
1597 | 370 | Json::Value root; | 360 | JsonCppNode::SPtr root = make_shared<JsonCppNode>(json_string); |
1598 | 371 | Json::Reader reader; | 361 | |
1599 | 372 | if (!reader.parse(json_string, root)) | 362 | if (root->type() != JsonNodeInterface::Array) |
1600 | 373 | { | 363 | { |
1601 | 374 | throw ResourceException("JsonSettingsSchema(): cannot parse schema: " + reader.getFormattedErrorMessages()); | 364 | if (root->type() != JsonNodeInterface::Object || !root->has_node("settings")) |
1602 | 375 | } | 365 | { |
1603 | 376 | 366 | throw ResourceException("JsonSettingsSchema(): missing \"settings\" definition"); | |
1604 | 377 | if (!root.isArray()) | 367 | } |
1605 | 378 | { | 368 | root = root->get_node("settings"); |
1606 | 379 | root = root["settings"]; | 369 | if (root->type() != JsonNodeInterface::Array) |
1607 | 380 | } | 370 | { |
1608 | 381 | if (root.isNull()) | 371 | throw ResourceException("JsonSettingsSchema(): value \"settings\" must be an array"); |
1609 | 382 | { | 372 | } |
1610 | 383 | throw ResourceException("JsonSettingsSchema(): missing \"settings\" definition"); | 373 | } |
1611 | 384 | } | 374 | |
1593 | 385 | if (!root.isArray()) | ||
1594 | 386 | { | ||
1595 | 387 | throw ResourceException("JsonSettingsSchema(): value \"settings\" must be an array"); | ||
1596 | 388 | } | ||
1612 | 389 | set<string> seen_settings; | 375 | set<string> seen_settings; |
1614 | 390 | for (unsigned i = 0; i < root.size(); ++i) | 376 | for (int i = 0; i < root->size(); ++i) |
1615 | 391 | { | 377 | { |
1617 | 392 | Setting s(root[i]); | 378 | Setting s(root->get_node(i)->to_variant()); |
1618 | 393 | if (starts_with(s.id(), "internal.")) | 379 | if (starts_with(s.id(), "internal.")) |
1619 | 394 | { | 380 | { |
1621 | 395 | throw ResourceException(string("JsonSettingsSchema(): invalid key \"") + s.id() + "\" prefixed with \"internal.\""); | 381 | throw ResourceException(string("JsonSettingsSchema(): invalid key \"") + s.id() |
1622 | 382 | + "\" prefixed with \"internal.\""); | ||
1623 | 396 | } | 383 | } |
1624 | 397 | if (seen_settings.find(s.id()) != seen_settings.end()) | 384 | if (seen_settings.find(s.id()) != seen_settings.end()) |
1625 | 398 | { | 385 | { |
1626 | 399 | throw ResourceException("JsonSettingsSchema(): duplicate definition, id = \"" + s.id() + "\""); | 386 | throw ResourceException("JsonSettingsSchema(): duplicate definition, id = \"" + s.id() + "\""); |
1627 | 400 | } | 387 | } |
1628 | 388 | seen_settings.insert(s.id()); | ||
1629 | 401 | definitions_.push_back(s.to_schema_definition()); | 389 | definitions_.push_back(s.to_schema_definition()); |
1630 | 402 | seen_settings.insert(s.id()); | ||
1631 | 403 | } | 390 | } |
1632 | 404 | } | 391 | } |
1633 | 405 | catch (ResourceException const&) | 392 | catch (ResourceException const&) |
1634 | 406 | 393 | ||
1635 | === modified file 'src/scopes/internal/Logger.cpp' | |||
1636 | --- src/scopes/internal/Logger.cpp 2016-02-22 05:00:23 +0000 | |||
1637 | +++ src/scopes/internal/Logger.cpp 2016-06-17 07:24:44 +0000 | |||
1638 | @@ -41,10 +41,10 @@ | |||
1639 | 41 | static array<string, 5> const severities = {{"INFO", "WARNING", "ERROR", "FATAL", "TRACE"}}; | 41 | static array<string, 5> const severities = {{"INFO", "WARNING", "ERROR", "FATAL", "TRACE"}}; |
1640 | 42 | 42 | ||
1641 | 43 | static array<pair<string, LoggerChannel>, int(LoggerChannel::LastChannelEnum_)> const channel_names = | 43 | static array<pair<string, LoggerChannel>, int(LoggerChannel::LastChannelEnum_)> const channel_names = |
1643 | 44 | { | 44 | { { |
1644 | 45 | pair<string, LoggerChannel>{"", LoggerChannel::DefaultChannel}, | 45 | pair<string, LoggerChannel>{"", LoggerChannel::DefaultChannel}, |
1645 | 46 | pair<string, LoggerChannel>{"IPC", LoggerChannel::IPC} | 46 | pair<string, LoggerChannel>{"IPC", LoggerChannel::IPC} |
1647 | 47 | }; | 47 | } }; |
1648 | 48 | 48 | ||
1649 | 49 | } // namespace | 49 | } // namespace |
1650 | 50 | 50 | ||
1651 | 51 | 51 | ||
1652 | === modified file 'src/scopes/internal/RuntimeImpl.cpp' | |||
1653 | --- src/scopes/internal/RuntimeImpl.cpp 2016-02-22 14:16:26 +0000 | |||
1654 | +++ src/scopes/internal/RuntimeImpl.cpp 2016-06-17 07:24:44 +0000 | |||
1655 | @@ -366,7 +366,7 @@ | |||
1656 | 366 | string settings_schema = scope_dir.native() + "/" + scope_id_ + "-settings.ini"; | 366 | string settings_schema = scope_dir.native() + "/" + scope_id_ + "-settings.ini"; |
1657 | 367 | 367 | ||
1658 | 368 | boost::system::error_code ec; | 368 | boost::system::error_code ec; |
1660 | 369 | if (boost::filesystem::exists(settings_schema, ec)) | 369 | if (boost::filesystem::exists(settings_schema, ec) && boost::filesystem::file_size(settings_schema) > 0) |
1661 | 370 | { | 370 | { |
1662 | 371 | shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema)); | 371 | shared_ptr<SettingsDB> db(SettingsDB::create_from_ini_file(settings_db, settings_schema)); |
1663 | 372 | scope_base->p->set_settings_db(db); | 372 | scope_base->p->set_settings_db(db); |
1664 | 373 | 373 | ||
1665 | === modified file 'src/scopes/internal/ScopeConfig.cpp' | |||
1666 | --- src/scopes/internal/ScopeConfig.cpp 2015-07-17 09:03:33 +0000 | |||
1667 | +++ src/scopes/internal/ScopeConfig.cpp 2016-06-17 07:24:44 +0000 | |||
1668 | @@ -67,7 +67,6 @@ | |||
1669 | 67 | const string fg_color_key = "ForegroundColor"; | 67 | const string fg_color_key = "ForegroundColor"; |
1670 | 68 | const string bg_color_key = "BackgroundColor"; | 68 | const string bg_color_key = "BackgroundColor"; |
1671 | 69 | const string shape_images_key = "ShapeImages"; | 69 | const string shape_images_key = "ShapeImages"; |
1672 | 70 | const string category_header_bg_key = "CategoryHeaderBackground"; | ||
1673 | 71 | const string preview_button_color_key = "PreviewButtonColor"; | 70 | const string preview_button_color_key = "PreviewButtonColor"; |
1674 | 72 | const string logo_overlay_color_key = "LogoOverlayColor"; | 71 | const string logo_overlay_color_key = "LogoOverlayColor"; |
1675 | 73 | const string pageheader_logo_key = "PageHeader.Logo"; | 72 | const string pageheader_logo_key = "PageHeader.Logo"; |
1676 | @@ -317,7 +316,6 @@ | |||
1677 | 317 | fg_color_key, | 316 | fg_color_key, |
1678 | 318 | bg_color_key, | 317 | bg_color_key, |
1679 | 319 | shape_images_key, | 318 | shape_images_key, |
1680 | 320 | category_header_bg_key, | ||
1681 | 321 | preview_button_color_key, | 319 | preview_button_color_key, |
1682 | 322 | logo_overlay_color_key, | 320 | logo_overlay_color_key, |
1683 | 323 | pageheader_logo_key, | 321 | pageheader_logo_key, |
1684 | 324 | 322 | ||
1685 | === modified file 'src/scopes/internal/smartscopes/SmartScopesClient.cpp' | |||
1686 | --- src/scopes/internal/smartscopes/SmartScopesClient.cpp 2016-02-25 11:40:06 +0000 | |||
1687 | +++ src/scopes/internal/smartscopes/SmartScopesClient.cpp 2016-06-17 07:24:44 +0000 | |||
1688 | @@ -592,6 +592,11 @@ | |||
1689 | 592 | 592 | ||
1690 | 593 | void SmartScopesClient::handle_line(std::string const& json, PreviewReplyHandler const& handler) | 593 | void SmartScopesClient::handle_line(std::string const& json, PreviewReplyHandler const& handler) |
1691 | 594 | { | 594 | { |
1692 | 595 | if (json.empty()) | ||
1693 | 596 | { | ||
1694 | 597 | return; | ||
1695 | 598 | } | ||
1696 | 599 | |||
1697 | 595 | JsonNodeInterface::SPtr root_node; | 600 | JsonNodeInterface::SPtr root_node; |
1698 | 596 | JsonNodeInterface::SPtr child_node; | 601 | JsonNodeInterface::SPtr child_node; |
1699 | 597 | { | 602 | { |
1700 | @@ -640,6 +645,11 @@ | |||
1701 | 640 | 645 | ||
1702 | 641 | void SmartScopesClient::handle_line(std::string const& json, SearchReplyHandler& handler) | 646 | void SmartScopesClient::handle_line(std::string const& json, SearchReplyHandler& handler) |
1703 | 642 | { | 647 | { |
1704 | 648 | if (json.empty()) | ||
1705 | 649 | { | ||
1706 | 650 | return; | ||
1707 | 651 | } | ||
1708 | 652 | |||
1709 | 643 | JsonNodeInterface::SPtr root_node; | 653 | JsonNodeInterface::SPtr root_node; |
1710 | 644 | JsonNodeInterface::SPtr child_node; | 654 | JsonNodeInterface::SPtr child_node; |
1711 | 645 | 655 | ||
1712 | 646 | 656 | ||
1713 | === modified file 'src/scopes/internal/zmq_middleware/StopPublisher.cpp' | |||
1714 | --- src/scopes/internal/zmq_middleware/StopPublisher.cpp 2014-11-18 07:04:04 +0000 | |||
1715 | +++ src/scopes/internal/zmq_middleware/StopPublisher.cpp 2016-06-17 07:24:44 +0000 | |||
1716 | @@ -121,7 +121,7 @@ | |||
1717 | 121 | s.set(zmqpp::socket_option::linger, 0); | 121 | s.set(zmqpp::socket_option::linger, 0); |
1718 | 122 | s.connect(endpoint_); | 122 | s.connect(endpoint_); |
1719 | 123 | s.subscribe(""); | 123 | s.subscribe(""); |
1721 | 124 | return move(s); | 124 | return s; |
1722 | 125 | } | 125 | } |
1723 | 126 | } | 126 | } |
1724 | 127 | } | 127 | } |
1725 | 128 | 128 | ||
1726 | === modified file 'src/scopes/testing/ScopeMetadataBuilder.cpp' | |||
1727 | --- src/scopes/testing/ScopeMetadataBuilder.cpp 2015-02-22 22:27:09 +0000 | |||
1728 | +++ src/scopes/testing/ScopeMetadataBuilder.cpp 2016-06-17 07:24:44 +0000 | |||
1729 | @@ -212,9 +212,7 @@ | |||
1730 | 212 | if (p->is_aggregator) | 212 | if (p->is_aggregator) |
1731 | 213 | impl->set_is_aggregator(*p->is_aggregator); | 213 | impl->set_is_aggregator(*p->is_aggregator); |
1732 | 214 | 214 | ||
1736 | 215 | return unity::scopes::internal::ScopeMetadataImpl::create( | 215 | return unity::scopes::internal::ScopeMetadataImpl::create(std::unique_ptr<internal::ScopeMetadataImpl>{impl}); |
1734 | 216 | std::move( | ||
1735 | 217 | std::unique_ptr<internal::ScopeMetadataImpl>{impl})); | ||
1737 | 218 | } | 216 | } |
1738 | 219 | 217 | ||
1739 | 220 | /// @endcond | 218 | /// @endcond |
1740 | 221 | 219 | ||
1741 | === modified file 'test/copyright/check_copyright.sh' | |||
1742 | --- test/copyright/check_copyright.sh 2015-11-13 06:33:11 +0000 | |||
1743 | +++ test/copyright/check_copyright.sh 2016-06-17 07:24:44 +0000 | |||
1744 | @@ -31,13 +31,7 @@ | |||
1745 | 31 | [ $# -lt 1 ] && usage | 31 | [ $# -lt 1 ] && usage |
1746 | 32 | [ $# -gt 2 ] && usage | 32 | [ $# -gt 2 ] && usage |
1747 | 33 | 33 | ||
1755 | 34 | # TODO: Temporary hack to work around broken licensecheck on xenial. Remove this once that is fixed. | 34 | ignore_pat="\\.sci$|.bzr|debian|tsan-suppress|valgrind-suppress|RELEASE_NOTES.md|partnerid|suppressions|README|_clang-format|TODO|CONFIGFILES|astyle-config|no_.*_cache|\\.txt$|\\.in$|\\.ini$|\\.xml$|\\.json$|\\.swp$|\\.gz$|\\.service$|\\.map$|\\.dox$|\\.html$|ParseArguments\\.cmake" |
1749 | 35 | distro=$(lsb_release -c -s) | ||
1750 | 36 | [ "$distro" = "xenial" ] && { | ||
1751 | 37 | exit 0 | ||
1752 | 38 | } | ||
1753 | 39 | |||
1754 | 40 | ignore_pat="\\.sci$" | ||
1756 | 41 | 35 | ||
1757 | 42 | # | 36 | # |
1758 | 43 | # We don't use the -i option of licensecheck to add ignore_dir to the pattern because Jenkins creates directories | 37 | # We don't use the -i option of licensecheck to add ignore_dir to the pattern because Jenkins creates directories |
1759 | 44 | 38 | ||
1760 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' | |||
1761 | --- test/gtest/scopes/Registry/Registry_test.cpp 2015-07-06 13:47:54 +0000 | |||
1762 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2016-06-17 07:24:44 +0000 | |||
1763 | @@ -122,7 +122,6 @@ | |||
1764 | 122 | EXPECT_EQ("fg_color", attrs["foreground-color"].get_string()); | 122 | EXPECT_EQ("fg_color", attrs["foreground-color"].get_string()); |
1765 | 123 | EXPECT_EQ("bg_color", attrs["background-color"].get_string()); | 123 | EXPECT_EQ("bg_color", attrs["background-color"].get_string()); |
1766 | 124 | EXPECT_TRUE(attrs["shape-images"].get_bool()); | 124 | EXPECT_TRUE(attrs["shape-images"].get_bool()); |
1767 | 125 | EXPECT_EQ(TEST_SCOPE_A_PATH "/cat_header_bg_scheme", attrs["category-header-background"].get_string()); | ||
1768 | 126 | EXPECT_EQ("preview_button_color", attrs["preview-button-color"].get_string()); | 125 | EXPECT_EQ("preview_button_color", attrs["preview-button-color"].get_string()); |
1769 | 127 | EXPECT_EQ("overlay_color", attrs["logo-overlay-color"].get_string()); | 126 | EXPECT_EQ("overlay_color", attrs["logo-overlay-color"].get_string()); |
1770 | 128 | auto page_hdr = attrs["page-header"].get_dict(); | 127 | auto page_hdr = attrs["page-header"].get_dict(); |
1771 | 129 | 128 | ||
1772 | === modified file 'test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in' | |||
1773 | --- test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in 2014-12-03 09:25:10 +0000 | |||
1774 | +++ test/gtest/scopes/Registry/scopes/testscopeA/testscopeA.ini.in 2016-06-17 07:24:44 +0000 | |||
1775 | @@ -16,7 +16,6 @@ | |||
1776 | 16 | ForegroundColor = fg_color | 16 | ForegroundColor = fg_color |
1777 | 17 | BackgroundColor = bg_color | 17 | BackgroundColor = bg_color |
1778 | 18 | ShapeImages = true | 18 | ShapeImages = true |
1779 | 19 | CategoryHeaderBackground = cat_header_bg_scheme | ||
1780 | 20 | PreviewButtonColor = preview_button_color | 19 | PreviewButtonColor = preview_button_color |
1781 | 21 | LogoOverlayColor = overlay_color | 20 | LogoOverlayColor = overlay_color |
1782 | 22 | PageHeader.Logo = some_url | 21 | PageHeader.Logo = some_url |
1783 | 23 | 22 | ||
1784 | === modified file 'test/gtest/scopes/internal/CMakeLists.txt' | |||
1785 | --- test/gtest/scopes/internal/CMakeLists.txt 2016-02-22 00:19:46 +0000 | |||
1786 | +++ test/gtest/scopes/internal/CMakeLists.txt 2016-06-17 07:24:44 +0000 | |||
1787 | @@ -1,6 +1,7 @@ | |||
1788 | 1 | add_subdirectory(CategoryRegistry) | 1 | add_subdirectory(CategoryRegistry) |
1789 | 2 | add_subdirectory(ConfigBase) | 2 | add_subdirectory(ConfigBase) |
1790 | 3 | add_subdirectory(DynamicLoader) | 3 | add_subdirectory(DynamicLoader) |
1791 | 4 | add_subdirectory(gobj_ptr) | ||
1792 | 4 | add_subdirectory(IniSettingsSchema) | 5 | add_subdirectory(IniSettingsSchema) |
1793 | 5 | add_subdirectory(JsonNode) | 6 | add_subdirectory(JsonNode) |
1794 | 6 | add_subdirectory(JsonSettingsSchema) | 7 | add_subdirectory(JsonSettingsSchema) |
1795 | 7 | 8 | ||
1796 | === modified file 'test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp' | |||
1797 | --- test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp 2015-11-02 03:42:05 +0000 | |||
1798 | +++ test/gtest/scopes/internal/JsonNode/JsonNode_test.cpp 2016-06-17 07:24:44 +0000 | |||
1799 | @@ -43,6 +43,35 @@ | |||
1800 | 43 | JsonNodeInterface::SPtr root_node_; | 43 | JsonNodeInterface::SPtr root_node_; |
1801 | 44 | }; | 44 | }; |
1802 | 45 | 45 | ||
1803 | 46 | TEST_F(JsonNodeTest, basic) | ||
1804 | 47 | { | ||
1805 | 48 | try | ||
1806 | 49 | { | ||
1807 | 50 | JsonCppNode node(""); | ||
1808 | 51 | FAIL(); | ||
1809 | 52 | } | ||
1810 | 53 | catch (unity::ResourceException const&) | ||
1811 | 54 | { | ||
1812 | 55 | } | ||
1813 | 56 | |||
1814 | 57 | EXPECT_EQ(0, root_node_->size()); | ||
1815 | 58 | EXPECT_EQ(JsonNodeInterface::Null, root_node_->type()); | ||
1816 | 59 | |||
1817 | 60 | auto json = root_node_->to_json_string(); | ||
1818 | 61 | EXPECT_EQ("null\n", json); | ||
1819 | 62 | |||
1820 | 63 | root_node_->read_json("42"); | ||
1821 | 64 | EXPECT_EQ(JsonNodeInterface::Int, root_node_->type()); | ||
1822 | 65 | auto n = root_node_->get_node(); | ||
1823 | 66 | EXPECT_EQ(42, n->as_int()); | ||
1824 | 67 | |||
1825 | 68 | EXPECT_THROW(root_node_->read_json(""), unity::ResourceException); | ||
1826 | 69 | EXPECT_THROW(root_node_->read_json(" "), unity::ResourceException); | ||
1827 | 70 | |||
1828 | 71 | root_node_->clear(); | ||
1829 | 72 | EXPECT_EQ(JsonNodeInterface::Null, root_node_->type()); | ||
1830 | 73 | } | ||
1831 | 74 | |||
1832 | 46 | TEST_F(JsonNodeTest, flat_values) | 75 | TEST_F(JsonNodeTest, flat_values) |
1833 | 47 | { | 76 | { |
1834 | 48 | std::string json_string = R"({ | 77 | std::string json_string = R"({ |
1835 | @@ -170,23 +199,45 @@ | |||
1836 | 170 | 199 | ||
1837 | 171 | TEST_F(JsonNodeTest, from_variant) | 200 | TEST_F(JsonNodeTest, from_variant) |
1838 | 172 | { | 201 | { |
1856 | 173 | VariantArray va({Variant(1), Variant(2), Variant(true)}); | 202 | { |
1857 | 174 | VariantMap vm; | 203 | VariantArray va({Variant(1), Variant(2), Variant(true)}); |
1858 | 175 | vm["foo"] = "bar"; | 204 | VariantMap vm; |
1859 | 176 | vm["baz"] = 1; | 205 | vm["foo"] = "bar"; |
1860 | 177 | vm["boo"] = 2.0f; | 206 | vm["baz"] = 1; |
1861 | 178 | vm["zee"] = true; | 207 | vm["boo"] = 2.0f; |
1862 | 179 | vm["wee"] = Variant(va); | 208 | vm["zee"] = true; |
1863 | 180 | 209 | vm["wee"] = Variant(va); | |
1864 | 181 | Variant var(vm); | 210 | |
1865 | 182 | JsonCppNode node(var); | 211 | Variant var(vm); |
1866 | 183 | EXPECT_EQ("bar", node.get_node("foo")->as_string()); | 212 | JsonCppNode node(var); |
1867 | 184 | EXPECT_EQ(1, node.get_node("baz")->as_int()); | 213 | EXPECT_EQ(JsonNodeInterface::Object, node.type()); |
1868 | 185 | EXPECT_TRUE(node.get_node("boo")->as_double() - 2.0f < 0.00001f); | 214 | EXPECT_EQ("bar", node.get_node("foo")->as_string()); |
1869 | 186 | EXPECT_TRUE(node.get_node("zee")->as_bool()); | 215 | EXPECT_EQ(JsonNodeInterface::String, node.get_node("foo")->type()); |
1870 | 187 | EXPECT_EQ(1, node.get_node("wee")->get_node(0)->as_int()); | 216 | EXPECT_EQ(1, node.get_node("baz")->as_int()); |
1871 | 188 | EXPECT_EQ(2, node.get_node("wee")->get_node(1)->as_int()); | 217 | EXPECT_EQ(JsonNodeInterface::Real, node.get_node("boo")->type()); |
1872 | 189 | EXPECT_TRUE(node.get_node("wee")->get_node(2)->as_bool()); | 218 | EXPECT_TRUE(node.get_node("boo")->as_double() - 2.0f < 0.00001f); |
1873 | 219 | EXPECT_EQ(JsonNodeInterface::Bool, node.get_node("zee")->type()); | ||
1874 | 220 | EXPECT_TRUE(node.get_node("zee")->as_bool()); | ||
1875 | 221 | EXPECT_EQ(JsonNodeInterface::Array, node.get_node("wee")->type()); | ||
1876 | 222 | EXPECT_EQ(1, node.get_node("wee")->get_node(0)->as_int()); | ||
1877 | 223 | EXPECT_EQ(2, node.get_node("wee")->get_node(1)->as_int()); | ||
1878 | 224 | EXPECT_TRUE(node.get_node("wee")->get_node(2)->as_bool()); | ||
1879 | 225 | } | ||
1880 | 226 | |||
1881 | 227 | { | ||
1882 | 228 | Variant var(1); | ||
1883 | 229 | JsonCppNode node(var); | ||
1884 | 230 | EXPECT_EQ(1, node.to_variant().get_int()); | ||
1885 | 231 | } | ||
1886 | 232 | |||
1887 | 233 | { | ||
1888 | 234 | Variant var(2147483648); // > 2^31 - 1 | ||
1889 | 235 | JsonCppNode node(var); | ||
1890 | 236 | EXPECT_EQ(2147483648, node.to_variant().get_int64_t()); | ||
1891 | 237 | } | ||
1892 | 238 | |||
1893 | 239 | JsonCppNode null_node((Variant())); | ||
1894 | 240 | EXPECT_EQ(JsonNodeInterface::Null, null_node.type()); | ||
1895 | 190 | } | 241 | } |
1896 | 191 | 242 | ||
1897 | 192 | TEST_F(JsonNodeTest, to_variant) | 243 | TEST_F(JsonNodeTest, to_variant) |
1898 | @@ -206,4 +257,89 @@ | |||
1899 | 206 | EXPECT_EQ("foo", arr[2].get_string()); | 257 | EXPECT_EQ("foo", arr[2].get_string()); |
1900 | 207 | } | 258 | } |
1901 | 208 | 259 | ||
1902 | 260 | TEST_F(JsonNodeTest, exceptions) | ||
1903 | 261 | { | ||
1904 | 262 | EXPECT_THROW(JsonCppNode("syntax error"), unity::ResourceException); | ||
1905 | 263 | |||
1906 | 264 | try | ||
1907 | 265 | { | ||
1908 | 266 | JsonCppNode().member_names(); | ||
1909 | 267 | FAIL(); | ||
1910 | 268 | } | ||
1911 | 269 | catch (unity::LogicException const& e) | ||
1912 | 270 | { | ||
1913 | 271 | EXPECT_STREQ("unity::LogicException: Root node is not an object", e.what()); | ||
1914 | 272 | } | ||
1915 | 273 | |||
1916 | 274 | try | ||
1917 | 275 | { | ||
1918 | 276 | JsonCppNode().has_node("x"); | ||
1919 | 277 | FAIL(); | ||
1920 | 278 | } | ||
1921 | 279 | catch (unity::LogicException const& e) | ||
1922 | 280 | { | ||
1923 | 281 | EXPECT_STREQ("unity::LogicException: Current node is empty", e.what()); | ||
1924 | 282 | } | ||
1925 | 283 | |||
1926 | 284 | try | ||
1927 | 285 | { | ||
1928 | 286 | JsonCppNode("42").as_string(); | ||
1929 | 287 | FAIL(); | ||
1930 | 288 | } | ||
1931 | 289 | catch (unity::LogicException const& e) | ||
1932 | 290 | { | ||
1933 | 291 | EXPECT_STREQ("unity::LogicException: Node does not contain a string value", e.what()); | ||
1934 | 292 | } | ||
1935 | 293 | |||
1936 | 294 | try | ||
1937 | 295 | { | ||
1938 | 296 | JsonCppNode("true").as_double(); | ||
1939 | 297 | FAIL(); | ||
1940 | 298 | } | ||
1941 | 299 | catch (unity::LogicException const& e) | ||
1942 | 300 | { | ||
1943 | 301 | EXPECT_STREQ("unity::LogicException: Node does not contain a double value", e.what()); | ||
1944 | 302 | } | ||
1945 | 303 | |||
1946 | 304 | try | ||
1947 | 305 | { | ||
1948 | 306 | JsonCppNode("true").as_int(); | ||
1949 | 307 | FAIL(); | ||
1950 | 308 | } | ||
1951 | 309 | catch (unity::LogicException const& e) | ||
1952 | 310 | { | ||
1953 | 311 | EXPECT_STREQ("unity::LogicException: Node does not contain an int value", e.what()); | ||
1954 | 312 | } | ||
1955 | 313 | |||
1956 | 314 | try | ||
1957 | 315 | { | ||
1958 | 316 | JsonCppNode("3.14").as_bool(); | ||
1959 | 317 | FAIL(); | ||
1960 | 318 | } | ||
1961 | 319 | catch (unity::LogicException const& e) | ||
1962 | 320 | { | ||
1963 | 321 | EXPECT_STREQ("unity::LogicException: Node does not contain a bool value", e.what()); | ||
1964 | 322 | } | ||
1965 | 323 | |||
1966 | 324 | try | ||
1967 | 325 | { | ||
1968 | 326 | JsonCppNode().get_node(25); | ||
1969 | 327 | FAIL(); | ||
1970 | 328 | } | ||
1971 | 329 | catch (unity::LogicException const& e) | ||
1972 | 330 | { | ||
1973 | 331 | EXPECT_STREQ("unity::LogicException: Current node is empty", e.what()); | ||
1974 | 332 | } | ||
1975 | 333 | |||
1976 | 334 | try | ||
1977 | 335 | { | ||
1978 | 336 | JsonCppNode().get_node(); | ||
1979 | 337 | FAIL(); | ||
1980 | 338 | } | ||
1981 | 339 | catch (unity::LogicException const& e) | ||
1982 | 340 | { | ||
1983 | 341 | EXPECT_STREQ("unity::LogicException: Current node is empty", e.what()); | ||
1984 | 342 | } | ||
1985 | 343 | } | ||
1986 | 344 | |||
1987 | 209 | } // namespace | 345 | } // namespace |
1988 | 210 | 346 | ||
1989 | === modified file 'test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp' | |||
1990 | --- test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp 2015-01-13 11:44:33 +0000 | |||
1991 | +++ test/gtest/scopes/internal/JsonSettingsSchema/JsonSettingsSchema_test.cpp 2016-06-17 07:24:44 +0000 | |||
1992 | @@ -22,7 +22,6 @@ | |||
1993 | 22 | #include <unity/util/FileIO.h> | 22 | #include <unity/util/FileIO.h> |
1994 | 23 | 23 | ||
1995 | 24 | #include <gtest/gtest.h> | 24 | #include <gtest/gtest.h> |
1996 | 25 | #include <jsoncpp/json/json.h> | ||
1997 | 26 | 25 | ||
1998 | 27 | using namespace unity; | 26 | using namespace unity; |
1999 | 28 | using namespace unity::scopes; | 27 | using namespace unity::scopes; |
2000 | @@ -153,6 +152,41 @@ | |||
2001 | 153 | EXPECT_EQ(Variant(), defs[10].get_dict()["defaultValue"]); | 152 | EXPECT_EQ(Variant(), defs[10].get_dict()["defaultValue"]); |
2002 | 154 | } | 153 | } |
2003 | 155 | 154 | ||
2004 | 155 | TEST(JsonSettingsSchema, integer_sizes) | ||
2005 | 156 | { | ||
2006 | 157 | char const* schema = R"delimiter( | ||
2007 | 158 | { | ||
2008 | 159 | "settings": | ||
2009 | 160 | [ | ||
2010 | 161 | { | ||
2011 | 162 | "id": "double_temp", | ||
2012 | 163 | "displayName": "floating-point default", | ||
2013 | 164 | "type": "number", | ||
2014 | 165 | "parameters": { | ||
2015 | 166 | "defaultValue": 3.14 | ||
2016 | 167 | } | ||
2017 | 168 | }, | ||
2018 | 169 | { | ||
2019 | 170 | "id": "too_old", | ||
2020 | 171 | "displayName": "won't fit into 32 bits", | ||
2021 | 172 | "type": "number", | ||
2022 | 173 | "parameters": { | ||
2023 | 174 | "defaultValue": 2147483648 | ||
2024 | 175 | } | ||
2025 | 176 | } | ||
2026 | 177 | ] | ||
2027 | 178 | } | ||
2028 | 179 | )delimiter"; | ||
2029 | 180 | |||
2030 | 181 | auto s = JsonSettingsSchema::create(schema); | ||
2031 | 182 | |||
2032 | 183 | auto defs = s->definitions(); | ||
2033 | 184 | EXPECT_EQ(2, defs.size()); | ||
2034 | 185 | |||
2035 | 186 | EXPECT_EQ(3.14, defs[0].get_dict()["defaultValue"].get_double()); | ||
2036 | 187 | EXPECT_EQ(2147483648, defs[1].get_dict()["defaultValue"].get_double()); | ||
2037 | 188 | } | ||
2038 | 189 | |||
2039 | 156 | TEST(JsonSettingsSchema, exceptions) | 190 | TEST(JsonSettingsSchema, exceptions) |
2040 | 157 | { | 191 | { |
2041 | 158 | try | 192 | try |
2042 | @@ -162,9 +196,7 @@ | |||
2043 | 162 | } | 196 | } |
2044 | 163 | catch (ResourceException const& e) | 197 | catch (ResourceException const& e) |
2045 | 164 | { | 198 | { |
2049 | 165 | EXPECT_STREQ("unity::ResourceException: JsonSettingsSchema(): cannot parse schema: * Line 1, Column 1\n" | 199 | EXPECT_STREQ("unity::ResourceException: JsonCppNode(): empty string is not a valid JSON", e.what()); |
2047 | 166 | " Syntax error: value, object or array expected.\n", | ||
2048 | 167 | e.what()); | ||
2050 | 168 | } | 200 | } |
2051 | 169 | 201 | ||
2052 | 170 | try | 202 | try |
2053 | @@ -335,7 +367,7 @@ | |||
2054 | 335 | } | 367 | } |
2055 | 336 | catch (ResourceException const& e) | 368 | catch (ResourceException const& e) |
2056 | 337 | { | 369 | { |
2058 | 338 | EXPECT_STREQ("unity::ResourceException: JsonSettingsSchema(): invalid \"type\" setting: " | 370 | EXPECT_STREQ("unity::ResourceException: JsonSettingsSchema(): invalid \"type\" definition: " |
2059 | 339 | "\"no_such_type\", id = \"x\"", | 371 | "\"no_such_type\", id = \"x\"", |
2060 | 340 | e.what()); | 372 | e.what()); |
2061 | 341 | } | 373 | } |
2062 | 342 | 374 | ||
2063 | === modified file 'test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp' | |||
2064 | --- test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp 2015-11-26 05:48:01 +0000 | |||
2065 | +++ test/gtest/scopes/internal/SettingsDB/SettingsDB_test.cpp 2016-06-17 07:24:44 +0000 | |||
2066 | @@ -22,6 +22,7 @@ | |||
2067 | 22 | 22 | ||
2068 | 23 | #include <unity/UnityExceptions.h> | 23 | #include <unity/UnityExceptions.h> |
2069 | 24 | 24 | ||
2070 | 25 | #include <boost/algorithm/string.hpp> | ||
2071 | 25 | #include <boost/regex.hpp> // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. | 26 | #include <boost/regex.hpp> // Use Boost implementation until http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53631 is fixed. |
2072 | 26 | #include <gtest/gtest.h> | 27 | #include <gtest/gtest.h> |
2073 | 27 | #include <fcntl.h> | 28 | #include <fcntl.h> |
2074 | @@ -321,10 +322,9 @@ | |||
2075 | 321 | } | 322 | } |
2076 | 322 | catch (ResourceException const& e) | 323 | catch (ResourceException const& e) |
2077 | 323 | { | 324 | { |
2082 | 324 | EXPECT_STREQ("unity::ResourceException: SettingsDB::create_from_json_string(): cannot parse schema, db = unused:\n" | 325 | EXPECT_TRUE(boost::starts_with(e.what(), |
2083 | 325 | " unity::ResourceException: JsonSettingsSchema(): cannot parse schema: * Line 1, Column 1\n" | 326 | "unity::ResourceException: SettingsDB::create_from_json_string(): cannot parse " |
2084 | 326 | " Syntax error: value, object or array expected.\n", | 327 | "schema, db = unused:")) << e.what(); |
2081 | 327 | e.what()); | ||
2085 | 328 | } | 328 | } |
2086 | 329 | 329 | ||
2087 | 330 | try | 330 | try |
2088 | 331 | 331 | ||
2089 | === added directory 'test/gtest/scopes/internal/gobj_ptr' | |||
2090 | === added file 'test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt' | |||
2091 | --- test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
2092 | +++ test/gtest/scopes/internal/gobj_ptr/CMakeLists.txt 2016-06-17 07:24:44 +0000 | |||
2093 | @@ -0,0 +1,3 @@ | |||
2094 | 1 | add_executable(gobj_ptr_test gobj_ptr_test.cpp) | ||
2095 | 2 | target_link_libraries(gobj_ptr_test ${TESTLIBS}) | ||
2096 | 3 | add_test(gobj_ptr gobj_ptr_test) | ||
2097 | 0 | 4 | ||
2098 | === added file 'test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp' | |||
2099 | --- test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp 1970-01-01 00:00:00 +0000 | |||
2100 | +++ test/gtest/scopes/internal/gobj_ptr/gobj_ptr_test.cpp 2016-06-17 07:24:44 +0000 | |||
2101 | @@ -0,0 +1,208 @@ | |||
2102 | 1 | /* | ||
2103 | 2 | * Copyright (C) 2013 Canonical Ltd. | ||
2104 | 3 | * | ||
2105 | 4 | * This program is free software: you can redistribute it and/or modify | ||
2106 | 5 | * it under the terms of the GNU Lesser General Public License version 3 as | ||
2107 | 6 | * published by the Free Software Foundation. | ||
2108 | 7 | * | ||
2109 | 8 | * This program is distributed in the hope that it will be useful, | ||
2110 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2111 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2112 | 11 | * GNU Lesser General Public License for more details. | ||
2113 | 12 | * | ||
2114 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2115 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2116 | 15 | * | ||
2117 | 16 | * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> | ||
2118 | 17 | */ | ||
2119 | 18 | |||
2120 | 19 | #pragma GCC diagnostic push | ||
2121 | 20 | #pragma GCC diagnostic ignored "-Wold-style-cast" | ||
2122 | 21 | #pragma GCC diagnostic ignored "-Wcast-qual" | ||
2123 | 22 | |||
2124 | 23 | #include <unity/scopes/internal/gobj_memory.h> | ||
2125 | 24 | #include <glib-object.h> | ||
2126 | 25 | #include <gtest/gtest.h> | ||
2127 | 26 | |||
2128 | 27 | using namespace std; | ||
2129 | 28 | using namespace unity::scopes::internal; | ||
2130 | 29 | |||
2131 | 30 | TEST(Gobj_ptr, trivial) | ||
2132 | 31 | { | ||
2133 | 32 | gobj_ptr<GObject> basic(G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr))); | ||
2134 | 33 | EXPECT_TRUE(bool(basic)); | ||
2135 | 34 | EXPECT_TRUE(G_IS_OBJECT(basic.get())); | ||
2136 | 35 | } | ||
2137 | 36 | |||
2138 | 37 | TEST(Gobj_ptr, compare) | ||
2139 | 38 | { | ||
2140 | 39 | GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2141 | 40 | GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2142 | 41 | if (o1 > o2) | ||
2143 | 42 | { | ||
2144 | 43 | std::swap(o1, o2); | ||
2145 | 44 | } | ||
2146 | 45 | ASSERT_TRUE(o1 < o2); | ||
2147 | 46 | gobj_ptr<GObject> u1(o1); | ||
2148 | 47 | gobj_ptr<GObject> u2(o2); | ||
2149 | 48 | |||
2150 | 49 | EXPECT_TRUE(!(u1 == nullptr)); | ||
2151 | 50 | EXPECT_TRUE(u1 != nullptr); | ||
2152 | 51 | EXPECT_TRUE(u1 != u2); | ||
2153 | 52 | EXPECT_TRUE(!(u1 == u2)); | ||
2154 | 53 | EXPECT_TRUE(u1 < u2); | ||
2155 | 54 | EXPECT_TRUE(!(u2 < u1)); | ||
2156 | 55 | EXPECT_TRUE(!(u1 == u2)); | ||
2157 | 56 | EXPECT_TRUE(!(u2 == u1)); | ||
2158 | 57 | EXPECT_TRUE(u1 <= u2); | ||
2159 | 58 | EXPECT_TRUE(!(u2 <= u1)); | ||
2160 | 59 | } | ||
2161 | 60 | |||
2162 | 61 | // This is its own thing due to need to avoid double release. | ||
2163 | 62 | |||
2164 | 63 | TEST(Gobj_ptr, equality) | ||
2165 | 64 | { | ||
2166 | 65 | GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2167 | 66 | gobj_ptr<GObject> u1(o); | ||
2168 | 67 | g_object_ref(o); | ||
2169 | 68 | gobj_ptr<GObject> u2(o); | ||
2170 | 69 | EXPECT_TRUE(u1 == u2); | ||
2171 | 70 | EXPECT_TRUE(u2 == u1); | ||
2172 | 71 | EXPECT_TRUE(!(u1 != u2)); | ||
2173 | 72 | EXPECT_TRUE(!(u2 != u1)); | ||
2174 | 73 | } | ||
2175 | 74 | |||
2176 | 75 | TEST(Gobj_ptr, release) | ||
2177 | 76 | { | ||
2178 | 77 | GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2179 | 78 | gobj_ptr<GObject> u(o); | ||
2180 | 79 | EXPECT_TRUE(u != nullptr); | ||
2181 | 80 | EXPECT_TRUE(u.get() != nullptr); | ||
2182 | 81 | EXPECT_TRUE(o == u.release()); | ||
2183 | 82 | EXPECT_TRUE(!u); | ||
2184 | 83 | EXPECT_TRUE(u.get() == nullptr); | ||
2185 | 84 | g_object_unref(o); | ||
2186 | 85 | } | ||
2187 | 86 | |||
2188 | 87 | TEST(Gobj_ptr, refcount) | ||
2189 | 88 | { | ||
2190 | 89 | GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2191 | 90 | EXPECT_EQ(1, o->ref_count); | ||
2192 | 91 | g_object_ref(o); | ||
2193 | 92 | |||
2194 | 93 | { | ||
2195 | 94 | EXPECT_EQ(2, o->ref_count); | ||
2196 | 95 | gobj_ptr<GObject> u(o); | ||
2197 | 96 | EXPECT_EQ(2, o->ref_count); | ||
2198 | 97 | // Now it dies and refcount is reduced. | ||
2199 | 98 | } | ||
2200 | 99 | |||
2201 | 100 | EXPECT_EQ(1, o->ref_count); | ||
2202 | 101 | g_object_unref(o); | ||
2203 | 102 | } | ||
2204 | 103 | |||
2205 | 104 | TEST(Gobj_ptr, copy) | ||
2206 | 105 | { | ||
2207 | 106 | GObject* o = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2208 | 107 | gobj_ptr<GObject> u(o); | ||
2209 | 108 | EXPECT_EQ(1, u->ref_count); | ||
2210 | 109 | gobj_ptr<GObject> u2(u); | ||
2211 | 110 | EXPECT_EQ(2, u->ref_count); | ||
2212 | 111 | gobj_ptr<GObject> u3 = u2; | ||
2213 | 112 | EXPECT_EQ(3, u->ref_count); | ||
2214 | 113 | u3.reset(); | ||
2215 | 114 | u2.reset(); | ||
2216 | 115 | EXPECT_EQ(1, u->ref_count); | ||
2217 | 116 | } | ||
2218 | 117 | |||
2219 | 118 | TEST(Gobj_ptr, swap) | ||
2220 | 119 | { | ||
2221 | 120 | GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2222 | 121 | GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2223 | 122 | gobj_ptr<GObject> u1(o1); | ||
2224 | 123 | gobj_ptr<GObject> u2(o2); | ||
2225 | 124 | |||
2226 | 125 | u1.swap(u2); | ||
2227 | 126 | EXPECT_EQ(o2, u1.get()); | ||
2228 | 127 | EXPECT_EQ(o1, u2.get()); | ||
2229 | 128 | |||
2230 | 129 | std::swap(u1, u2); | ||
2231 | 130 | EXPECT_EQ(o1, u1.get()); | ||
2232 | 131 | EXPECT_EQ(o2, u2.get()); | ||
2233 | 132 | } | ||
2234 | 133 | |||
2235 | 134 | TEST(Gobj_ptr, floating) | ||
2236 | 135 | { | ||
2237 | 136 | GObject* o = G_OBJECT(g_object_new(G_TYPE_INITIALLY_UNOWNED, nullptr)); | ||
2238 | 137 | try | ||
2239 | 138 | { | ||
2240 | 139 | gobj_ptr<GObject> u(o); | ||
2241 | 140 | FAIL(); | ||
2242 | 141 | } | ||
2243 | 142 | catch (const invalid_argument& c) | ||
2244 | 143 | { | ||
2245 | 144 | EXPECT_EQ("Tried to add a floating gobject into a gobj_ptr.", string(c.what())); | ||
2246 | 145 | } | ||
2247 | 146 | // Object accepted after sinking. | ||
2248 | 147 | g_object_ref_sink(o); | ||
2249 | 148 | gobj_ptr<GObject> u(o); | ||
2250 | 149 | } | ||
2251 | 150 | |||
2252 | 151 | TEST(Gobj_ptr, move) | ||
2253 | 152 | { | ||
2254 | 153 | GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2255 | 154 | GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2256 | 155 | g_object_ref(o1); | ||
2257 | 156 | gobj_ptr<GObject> u1(o1); | ||
2258 | 157 | gobj_ptr<GObject> u2(o2); | ||
2259 | 158 | u1 = std::move(u2); | ||
2260 | 159 | EXPECT_TRUE(u1.get() == o2); | ||
2261 | 160 | EXPECT_TRUE(!u2); | ||
2262 | 161 | EXPECT_TRUE(o1->ref_count == 1); | ||
2263 | 162 | g_object_unref(o1); | ||
2264 | 163 | } | ||
2265 | 164 | |||
2266 | 165 | TEST(Gobj_ptr, null) | ||
2267 | 166 | { | ||
2268 | 167 | GObject* o1 = NULL; | ||
2269 | 168 | GObject* o3 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2270 | 169 | gobj_ptr<GObject> u1(o1); | ||
2271 | 170 | gobj_ptr<GObject> u2(nullptr); | ||
2272 | 171 | gobj_ptr<GObject> u3(o3); | ||
2273 | 172 | |||
2274 | 173 | EXPECT_TRUE(!u1); | ||
2275 | 174 | EXPECT_TRUE(!u2); | ||
2276 | 175 | u3 = nullptr; | ||
2277 | 176 | EXPECT_TRUE(!u3); | ||
2278 | 177 | } | ||
2279 | 178 | |||
2280 | 179 | TEST(Gobj_ptr, reset) | ||
2281 | 180 | { | ||
2282 | 181 | GObject* o1 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2283 | 182 | GObject* o2 = G_OBJECT(g_object_new(G_TYPE_OBJECT, nullptr)); | ||
2284 | 183 | gobj_ptr<GObject> u(o1); | ||
2285 | 184 | |||
2286 | 185 | u.reset(o2); | ||
2287 | 186 | EXPECT_EQ(o2, u.get()); | ||
2288 | 187 | u.reset(nullptr); | ||
2289 | 188 | EXPECT_TRUE(!u); | ||
2290 | 189 | } | ||
2291 | 190 | |||
2292 | 191 | TEST(Gobj_ptr, sizeoftest) | ||
2293 | 192 | { | ||
2294 | 193 | EXPECT_EQ(sizeof(GObject*), sizeof(gobj_ptr<GObject>)); | ||
2295 | 194 | } | ||
2296 | 195 | |||
2297 | 196 | TEST(Gobj_ptr, deleter) | ||
2298 | 197 | { | ||
2299 | 198 | gobj_ptr<GObject> u1; | ||
2300 | 199 | EXPECT_TRUE(g_object_unref == u1.get_deleter()); | ||
2301 | 200 | } | ||
2302 | 201 | |||
2303 | 202 | int main(int argc, char** argv) | ||
2304 | 203 | { | ||
2305 | 204 | ::testing::InitGoogleTest(&argc, argv); | ||
2306 | 205 | return RUN_ALL_TESTS(); | ||
2307 | 206 | } | ||
2308 | 207 | |||
2309 | 208 | #pragma GCC diagnostic pop | ||
2310 | 0 | 209 | ||
2311 | === modified file 'test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp' | |||
2312 | --- test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2016-02-29 15:57:12 +0000 | |||
2313 | +++ test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2016-06-17 07:24:44 +0000 | |||
2314 | @@ -130,13 +130,41 @@ | |||
2315 | 130 | EXPECT_EQ(nullptr, scopes[2].art); | 130 | EXPECT_EQ(nullptr, scopes[2].art); |
2316 | 131 | EXPECT_FALSE(scopes[2].invisible); | 131 | EXPECT_FALSE(scopes[2].invisible); |
2317 | 132 | EXPECT_EQ(nullptr, scopes[2].appearance); | 132 | EXPECT_EQ(nullptr, scopes[2].appearance); |
2325 | 133 | EXPECT_EQ("[{\"displayName\":\"Location\",\"id\":\"location\",\"parameters\":{\"defaultValue\":" | 133 | { |
2326 | 134 | "\"London\"},\"type\":\"string\"},{\"displayName\":\"Temperature Units\",\"id\":" | 134 | JsonCppNode node(*scopes[2].settings); |
2327 | 135 | "\"unitTemp\",\"parameters\":{\"defaultValue\":1,\"values\":[\"Celsius\",\"Fahrenheit" | 135 | Variant v = node.to_variant(); |
2328 | 136 | "\"]},\"type\":\"list\"},{\"displayName\":\"Age\",\"id\":\"age\",\"parameters\":{" | 136 | |
2329 | 137 | "\"defaultValue\":23},\"type\":\"number\"},{\"displayName\":\"Enabled\",\"id\":" | 137 | VariantMap vm = v.get_array()[0].get_dict(); |
2330 | 138 | "\"enabled\",\"parameters\":{\"defaultValue\":true},\"type\":\"boolean\"}]\n", | 138 | EXPECT_EQ("Location", vm["displayName"].get_string()); |
2331 | 139 | *scopes[2].settings); | 139 | EXPECT_EQ("location", vm["id"].get_string()); |
2332 | 140 | EXPECT_EQ("string", vm["type"].get_string()); | ||
2333 | 141 | VariantMap params = vm["parameters"].get_dict(); | ||
2334 | 142 | EXPECT_EQ("London", params["defaultValue"].get_string()); | ||
2335 | 143 | |||
2336 | 144 | vm = v.get_array()[1].get_dict(); | ||
2337 | 145 | EXPECT_EQ("Temperature Units", vm["displayName"].get_string()); | ||
2338 | 146 | EXPECT_EQ("unitTemp", vm["id"].get_string()); | ||
2339 | 147 | EXPECT_EQ("list", vm["type"].get_string()); | ||
2340 | 148 | params = vm["parameters"].get_dict(); | ||
2341 | 149 | EXPECT_EQ(1, params["defaultValue"].get_int()); | ||
2342 | 150 | VariantArray choices = params["values"].get_array(); | ||
2343 | 151 | EXPECT_EQ("Celsius", choices[0].get_string()); | ||
2344 | 152 | EXPECT_EQ("Fahrenheit", choices[1].get_string()); | ||
2345 | 153 | |||
2346 | 154 | vm = v.get_array()[2].get_dict(); | ||
2347 | 155 | EXPECT_EQ("Age", vm["displayName"].get_string()); | ||
2348 | 156 | EXPECT_EQ("age", vm["id"].get_string()); | ||
2349 | 157 | EXPECT_EQ("number", vm["type"].get_string()); | ||
2350 | 158 | params = vm["parameters"].get_dict(); | ||
2351 | 159 | EXPECT_EQ(23, params["defaultValue"].get_int()); | ||
2352 | 160 | |||
2353 | 161 | vm = v.get_array()[3].get_dict(); | ||
2354 | 162 | EXPECT_EQ("Enabled", vm["displayName"].get_string()); | ||
2355 | 163 | EXPECT_EQ("enabled", vm["id"].get_string()); | ||
2356 | 164 | EXPECT_EQ("boolean", vm["type"].get_string()); | ||
2357 | 165 | params = vm["parameters"].get_dict(); | ||
2358 | 166 | EXPECT_TRUE(params["defaultValue"].get_bool()); | ||
2359 | 167 | } | ||
2360 | 140 | ASSERT_EQ(4, scopes[2].keywords.size()); | 168 | ASSERT_EQ(4, scopes[2].keywords.size()); |
2361 | 141 | EXPECT_NE(scopes[2].keywords.end(), scopes[2].keywords.find("music")); | 169 | EXPECT_NE(scopes[2].keywords.end(), scopes[2].keywords.find("music")); |
2362 | 142 | EXPECT_NE(scopes[2].keywords.end(), scopes[2].keywords.find("video")); | 170 | EXPECT_NE(scopes[2].keywords.end(), scopes[2].keywords.find("video")); |
2363 | @@ -392,10 +420,30 @@ | |||
2364 | 392 | EXPECT_EQ("widget_id_C", columns[2][2][0]); | 420 | EXPECT_EQ("widget_id_C", columns[2][2][0]); |
2365 | 393 | 421 | ||
2366 | 394 | ASSERT_EQ(3u, widgets.size()); | 422 | ASSERT_EQ(3u, widgets.size()); |
2371 | 395 | 423 | { | |
2372 | 396 | EXPECT_EQ("{\"id\":\"widget_id_A\",\"text\":\"First widget.\",\"title\":\"Widget A\",\"type\":\"text\"}\n", widgets[0]); | 424 | auto json = widgets[0]; |
2373 | 397 | EXPECT_EQ("{\"id\":\"widget_id_B\",\"text\":\"Second widget.\",\"title\":\"Widget B\",\"type\":\"text\"}\n", widgets[1]); | 425 | JsonCppNode node(json); |
2374 | 398 | EXPECT_EQ("{\"id\":\"widget_id_C\",\"text\":\"Third widget.\",\"title\":\"Widget C\",\"type\":\"text\"}\n", widgets[2]); | 426 | EXPECT_EQ("widget_id_A", node.get_node("id")->as_string()); |
2375 | 427 | EXPECT_EQ("First widget.", node.get_node("text")->as_string()); | ||
2376 | 428 | EXPECT_EQ("Widget A", node.get_node("title")->as_string()); | ||
2377 | 429 | EXPECT_EQ("text", node.get_node("type")->as_string()); | ||
2378 | 430 | } | ||
2379 | 431 | { | ||
2380 | 432 | auto json = widgets[1]; | ||
2381 | 433 | JsonCppNode node(json); | ||
2382 | 434 | EXPECT_EQ("widget_id_B", node.get_node("id")->as_string()); | ||
2383 | 435 | EXPECT_EQ("Second widget.", node.get_node("text")->as_string()); | ||
2384 | 436 | EXPECT_EQ("Widget B", node.get_node("title")->as_string()); | ||
2385 | 437 | EXPECT_EQ("text", node.get_node("type")->as_string()); | ||
2386 | 438 | } | ||
2387 | 439 | { | ||
2388 | 440 | auto json = widgets[2]; | ||
2389 | 441 | JsonCppNode node(json); | ||
2390 | 442 | EXPECT_EQ("widget_id_C", node.get_node("id")->as_string()); | ||
2391 | 443 | EXPECT_EQ("Third widget.", node.get_node("text")->as_string()); | ||
2392 | 444 | EXPECT_EQ("Widget C", node.get_node("title")->as_string()); | ||
2393 | 445 | EXPECT_EQ("text", node.get_node("type")->as_string()); | ||
2394 | 446 | } | ||
2395 | 399 | } | 447 | } |
2396 | 400 | 448 | ||
2397 | 401 | TEST_F(SmartScopesClientTest, consecutive_searches) | 449 | TEST_F(SmartScopesClientTest, consecutive_searches) |
Changelog nitpick inline.