Skip to content

Commit 46ca564

Browse files
JoshuaGrossfacebook-github-bot
authored andcommitted
RawPropsTest C++ unit tests (fabric)
Summary: Add RawPropsTests unit tests. The general idea is to cover the normal props use-cases and then add a few abnormal cases and some errors, to make sure nothing crashes. The final test uncovers an infinite loop in RawProp parsing. Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D18662136 fbshipit-source-id: 2f603b4c3e32f2d4334587e898ea81ad025b07b6
1 parent 088be26 commit 46ca564

File tree

2 files changed

+254
-14
lines changed

2 files changed

+254
-14
lines changed
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#include <memory>
9+
10+
#include <gtest/gtest.h>
11+
#include <react/core/ConcreteShadowNode.h>
12+
#include <react/core/ShadowNode.h>
13+
#include <react/core/propsConversions.h>
14+
15+
#include "TestComponent.h"
16+
17+
using namespace facebook::react;
18+
19+
class PropsSingleFloat : public Props {
20+
public:
21+
PropsSingleFloat() = default;
22+
PropsSingleFloat(
23+
const PropsSingleFloat &sourceProps,
24+
const RawProps &rawProps)
25+
: floatValue(convertRawProp(
26+
rawProps,
27+
"floatValue",
28+
sourceProps.floatValue,
29+
17.5)) {}
30+
31+
private:
32+
const float floatValue{17.5};
33+
};
34+
35+
class PropsSingleDouble : public Props {
36+
public:
37+
PropsSingleDouble() = default;
38+
PropsSingleDouble(
39+
const PropsSingleDouble &sourceProps,
40+
const RawProps &rawProps)
41+
: doubleValue(convertRawProp(
42+
rawProps,
43+
"doubleValue",
44+
sourceProps.doubleValue,
45+
17.5)) {}
46+
47+
private:
48+
const float doubleValue{17.5};
49+
};
50+
51+
class PropsSingleInt : public Props {
52+
public:
53+
PropsSingleInt() = default;
54+
PropsSingleInt(const PropsSingleInt &sourceProps, const RawProps &rawProps)
55+
: intValue(
56+
convertRawProp(rawProps, "intValue", sourceProps.intValue, 17)) {}
57+
58+
private:
59+
const int intValue{17};
60+
};
61+
62+
class PropsPrimitiveTypes : public Props {
63+
public:
64+
PropsPrimitiveTypes() = default;
65+
PropsPrimitiveTypes(
66+
const PropsPrimitiveTypes &sourceProps,
67+
const RawProps &rawProps)
68+
: intValue(
69+
convertRawProp(rawProps, "intValue", sourceProps.intValue, 17)),
70+
doubleValue(convertRawProp(
71+
rawProps,
72+
"doubleValue",
73+
sourceProps.doubleValue,
74+
17.56)),
75+
floatValue(convertRawProp(
76+
rawProps,
77+
"floatValue",
78+
sourceProps.floatValue,
79+
56.75)),
80+
stringValue(convertRawProp(
81+
rawProps,
82+
"stringValue",
83+
sourceProps.stringValue,
84+
"")),
85+
boolValue(convertRawProp(
86+
rawProps,
87+
"boolValue",
88+
sourceProps.boolValue,
89+
false)) {}
90+
91+
private:
92+
const int intValue{17};
93+
const double doubleValue{17.56};
94+
const float floatValue{56.75};
95+
const std::string stringValue{};
96+
const bool boolValue{false};
97+
};
98+
99+
TEST(ShadowNodeTest, handleProps) {
100+
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
101+
auto parser = RawPropsParser();
102+
parser.prepare<Props>();
103+
raw.parse(parser);
104+
105+
auto props = std::make_shared<Props>(Props(), raw);
106+
107+
// Props are not sealed after applying raw props.
108+
ASSERT_FALSE(props->getSealed());
109+
110+
ASSERT_STREQ(props->nativeId.c_str(), "abc");
111+
}
112+
113+
TEST(ShadowNodeTest, handleRawPropsSingleString) {
114+
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
115+
auto parser = RawPropsParser();
116+
parser.prepare<Props>();
117+
raw.parse(parser);
118+
119+
std::string value = (std::string)*raw.at("nativeID", nullptr, nullptr);
120+
121+
ASSERT_STREQ(value.c_str(), "abc");
122+
}
123+
124+
TEST(ShadowNodeTest, handleRawPropsSingleFloat) {
125+
const auto &raw =
126+
RawProps(folly::dynamic::object("floatValue", (float)42.42));
127+
auto parser = RawPropsParser();
128+
parser.prepare<PropsSingleFloat>();
129+
raw.parse(parser);
130+
131+
float value = (float)*raw.at("floatValue", nullptr, nullptr);
132+
133+
ASSERT_NEAR(value, 42.42, 0.00001);
134+
}
135+
136+
TEST(ShadowNodeTest, handleRawPropsSingleDouble) {
137+
const auto &raw =
138+
RawProps(folly::dynamic::object("doubleValue", (double)42.42));
139+
auto parser = RawPropsParser();
140+
parser.prepare<PropsSingleDouble>();
141+
raw.parse(parser);
142+
143+
double value = (double)*raw.at("doubleValue", nullptr, nullptr);
144+
145+
ASSERT_NEAR(value, 42.42, 0.00001);
146+
}
147+
148+
TEST(ShadowNodeTest, handleRawPropsSingleInt) {
149+
const auto &raw = RawProps(folly::dynamic::object("intValue", (int)42.42));
150+
auto parser = RawPropsParser();
151+
parser.prepare<PropsSingleInt>();
152+
raw.parse(parser);
153+
154+
int value = (int)*raw.at("intValue", nullptr, nullptr);
155+
156+
ASSERT_EQ(value, 42);
157+
}
158+
159+
TEST(ShadowNodeTest, handleRawPropsSingleIntGetManyTimes) {
160+
const auto &raw = RawProps(folly::dynamic::object("intValue", (int)42.42));
161+
auto parser = RawPropsParser();
162+
parser.prepare<PropsSingleInt>();
163+
raw.parse(parser);
164+
165+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
166+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
167+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
168+
}
169+
170+
TEST(ShadowNodeTest, handleRawPropsPrimitiveTypes) {
171+
const auto &raw = RawProps(folly::dynamic::object("intValue", (int)42)(
172+
"doubleValue", (double)17.42)("floatValue", (float)66.67)(
173+
"stringValue", "helloworld")("boolValue", true));
174+
175+
auto parser = RawPropsParser();
176+
parser.prepare<PropsPrimitiveTypes>();
177+
raw.parse(parser);
178+
179+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
180+
ASSERT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001);
181+
ASSERT_NEAR((float)*raw.at("floatValue", nullptr, nullptr), 66.67, 0.00001);
182+
ASSERT_STREQ(
183+
((std::string)*raw.at("stringValue", nullptr, nullptr)).c_str(),
184+
"helloworld");
185+
ASSERT_EQ((bool)*raw.at("boolValue", nullptr, nullptr), true);
186+
}
187+
188+
TEST(ShadowNodeTest, handleRawPropsPrimitiveTypesGetTwice) {
189+
const auto &raw = RawProps(folly::dynamic::object("intValue", (int)42)(
190+
"doubleValue", (double)17.42)("floatValue", (float)66.67)(
191+
"stringValue", "helloworld")("boolValue", true));
192+
193+
auto parser = RawPropsParser();
194+
parser.prepare<PropsPrimitiveTypes>();
195+
raw.parse(parser);
196+
197+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
198+
ASSERT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001);
199+
ASSERT_NEAR((float)*raw.at("floatValue", nullptr, nullptr), 66.67, 0.00001);
200+
ASSERT_STREQ(
201+
((std::string)*raw.at("stringValue", nullptr, nullptr)).c_str(),
202+
"helloworld");
203+
ASSERT_EQ((bool)*raw.at("boolValue", nullptr, nullptr), true);
204+
205+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
206+
ASSERT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001);
207+
ASSERT_NEAR((float)*raw.at("floatValue", nullptr, nullptr), 66.67, 0.00001);
208+
ASSERT_STREQ(
209+
((std::string)*raw.at("stringValue", nullptr, nullptr)).c_str(),
210+
"helloworld");
211+
ASSERT_EQ((bool)*raw.at("boolValue", nullptr, nullptr), true);
212+
}
213+
214+
TEST(ShadowNodeTest, handleRawPropsPrimitiveTypesGetOutOfOrder) {
215+
const auto &raw = RawProps(folly::dynamic::object("intValue", (int)42)(
216+
"doubleValue", (double)17.42)("floatValue", (float)66.67)(
217+
"stringValue", "helloworld")("boolValue", true));
218+
219+
auto parser = RawPropsParser();
220+
parser.prepare<PropsPrimitiveTypes>();
221+
raw.parse(parser);
222+
223+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
224+
ASSERT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001);
225+
ASSERT_NEAR((float)*raw.at("floatValue", nullptr, nullptr), 66.67, 0.00001);
226+
ASSERT_STREQ(
227+
((std::string)*raw.at("stringValue", nullptr, nullptr)).c_str(),
228+
"helloworld");
229+
ASSERT_EQ((bool)*raw.at("boolValue", nullptr, nullptr), true);
230+
231+
ASSERT_NEAR((double)*raw.at("doubleValue", nullptr, nullptr), 17.42, 0.0001);
232+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
233+
ASSERT_NEAR((float)*raw.at("floatValue", nullptr, nullptr), 66.67, 0.00001);
234+
ASSERT_STREQ(
235+
((std::string)*raw.at("stringValue", nullptr, nullptr)).c_str(),
236+
"helloworld");
237+
ASSERT_EQ((bool)*raw.at("boolValue", nullptr, nullptr), true);
238+
}
239+
240+
TEST(ShadowNodeTest, handleRawPropsPrimitiveTypesIncomplete) {
241+
const auto &raw = RawProps(folly::dynamic::object("intValue", (int)42));
242+
243+
auto parser = RawPropsParser();
244+
parser.prepare<PropsPrimitiveTypes>();
245+
raw.parse(parser);
246+
247+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
248+
ASSERT_EQ(raw.at("doubleValue", nullptr, nullptr), nullptr);
249+
ASSERT_EQ(raw.at("floatValue", nullptr, nullptr), nullptr);
250+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
251+
ASSERT_EQ(raw.at("stringValue", nullptr, nullptr), nullptr);
252+
ASSERT_EQ(raw.at("boolValue", nullptr, nullptr), nullptr);
253+
ASSERT_EQ((int)*raw.at("intValue", nullptr, nullptr), 42);
254+
}

ReactCommon/fabric/core/tests/ShadowNodeTest.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,6 @@
1515

1616
using namespace facebook::react;
1717

18-
TEST(ShadowNodeTest, handleProps) {
19-
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
20-
auto parser = RawPropsParser();
21-
parser.prepare<Props>();
22-
raw.parse(parser);
23-
24-
auto props = std::make_shared<Props>(Props(), raw);
25-
26-
// Props are not sealed after applying raw props.
27-
ASSERT_FALSE(props->getSealed());
28-
29-
ASSERT_STREQ(props->nativeId.c_str(), "abc");
30-
}
31-
3218
TEST(ShadowNodeTest, handleShadowNodeCreation) {
3319
auto eventDispatcher = std::shared_ptr<EventDispatcher const>();
3420
auto componentDescriptor = TestComponentDescriptor(eventDispatcher);

0 commit comments

Comments
 (0)