Replace CompactValue with StyleValueHandle and StyleValuePool (#1534)
Summary: X-link: https://github.com/facebook/react-native/pull/42131 Pull Request resolved: https://github.com/facebook/yoga/pull/1534 Now that the storage method is a hidden implementation detail, this changes the underlying data structure used to store styles, from `CompactValue` (a customized 32-bit float with tag bits), to `StyleValuePool`. This new structure operates on 16-bit handles, and a shared small buffer. The vast majority of real-world values can be stored directly in the handle, but we allow arbitrary 32 bit (and soon 64-bit) values to be stored, where the handle then becomes an index into the styles buffer. This results in a real-world memory usage win, while also letting us store the 64-bit values we are wanting to use for math function support (compared to doubling the storage requirements). This does seem to make style reads slower, which due to their heavy frequency, does have a performance impact observable by synthetics. In an example laying out a tree of 10,000 nodes, we originally read from `StyleValuePool` 2.4 million times. This originally resulted in a ~10% regression, but when combined with the changes in the last diff, most style reads become simple bitwise operations on the handle, and we are actually 14% faster than before. | | Before | After | Δ | | `sizeof(yoga::Style)` | 208B | 144B | -64B/-31% | | `sizeof(yoga::Node)` | 640B | 576B | -64B/-10% | | `sizeof(YogaLayoutableShadowNode) ` | 920B | 856B | -64B/-7% | | `sizeof(YogaLayoutableShadowNode) + sizeof(YogaStylableProps)` | 1296B | 1168B | -128B/-10% | | `sizeof(ViewShadowNode)` | 920B | 856B | -64B/-7% | | `sizeof(ViewShadowNode) + sizeof(ViewShadowNodeProps)` | 2000B | 1872B | -128B/-6% | | "Huge nested layout" microbenchmark (M1 Ultra) | 11.5ms | 9.9ms | -1.6ms/-14% | | Quest Store C++ heap usage (avg over 10 runs) | 86.2MB | 84.9MB | -1.3MB/-1.5% | Reviewed By: joevilches Differential Revision: D52223122 fbshipit-source-id: 990f4b7e991e8e22d198ce20f7da66d9c6ba637b
This commit is contained in:
committed by
Facebook GitHub Bot
parent
395c596695
commit
67154d47a3
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#define YOGA_COMPACT_VALUE_TEST
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <yoga/style/CompactValue.h>
|
||||
#include <cmath>
|
||||
|
||||
using namespace facebook::yoga;
|
||||
|
||||
const auto tooSmall = nextafterf(CompactValue::LOWER_BOUND, -INFINITY);
|
||||
const auto tooLargePoints =
|
||||
nextafterf(CompactValue::UPPER_BOUND_POINT, INFINITY);
|
||||
const auto tooLargePercent =
|
||||
nextafterf(CompactValue::UPPER_BOUND_PERCENT, INFINITY);
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_undefined) {
|
||||
auto c = CompactValue{value::undefined()};
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_EQ(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-1.25));
|
||||
ASSERT_NE(v, value::percent(25));
|
||||
ASSERT_TRUE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_manages_infinity_as_undefined) {
|
||||
auto c = CompactValue{value::points(std::numeric_limits<float>::infinity())};
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_EQ(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-1.25));
|
||||
ASSERT_NE(v, value::percent(25));
|
||||
ASSERT_TRUE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_auto) {
|
||||
auto c = CompactValue{value::ofAuto()};
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_EQ(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-1.25));
|
||||
ASSERT_NE(v, value::percent(25));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_TRUE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_zero_points) {
|
||||
auto c = CompactValue{value::points(0)};
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(0));
|
||||
ASSERT_NE(v, value::percent(0));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_lower_bound_points) {
|
||||
auto c = CompactValue({value::points(CompactValue::LOWER_BOUND)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(CompactValue::LOWER_BOUND));
|
||||
ASSERT_NE(v, value::percent(CompactValue::LOWER_BOUND));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_negative_lower_bound_points) {
|
||||
auto c = CompactValue({value::points(-CompactValue::LOWER_BOUND)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(-CompactValue::LOWER_BOUND));
|
||||
ASSERT_NE(v, value::percent(-CompactValue::LOWER_BOUND));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_clamps_smaller_than_lower_bound_points_to_zero) {
|
||||
auto c = CompactValue({value::points(tooSmall)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(0));
|
||||
ASSERT_NE(v, value::percent(0));
|
||||
}
|
||||
|
||||
TEST(
|
||||
YogaTest,
|
||||
compact_value_clamps_greater_than_negative_lower_bound_points_to_zero) {
|
||||
auto c = CompactValue({value::points(-tooSmall)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(0));
|
||||
ASSERT_NE(v, value::percent(0));
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_upper_bound_points) {
|
||||
auto c = CompactValue({value::points(CompactValue::UPPER_BOUND_POINT)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(CompactValue::UPPER_BOUND_POINT));
|
||||
ASSERT_NE(v, value::percent(CompactValue::UPPER_BOUND_POINT));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_negative_upper_bound_points) {
|
||||
auto c = CompactValue({value::points(-CompactValue::UPPER_BOUND_POINT)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(-CompactValue::UPPER_BOUND_POINT));
|
||||
ASSERT_NE(v, value::percent(-CompactValue::UPPER_BOUND_POINT));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(
|
||||
YogaTest,
|
||||
compact_value_clamps_greater_than__upper_bound_points_to_upper_bound) {
|
||||
auto c = CompactValue({value::points(tooLargePoints)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(CompactValue::UPPER_BOUND_POINT));
|
||||
ASSERT_NE(v, value::percent(CompactValue::UPPER_BOUND_POINT));
|
||||
}
|
||||
|
||||
TEST(
|
||||
YogaTest,
|
||||
compact_value_clamps_smaller_than_negative_upper_bound_points_to_upper_bound) {
|
||||
auto c = CompactValue({value::points(-tooLargePoints)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(-CompactValue::UPPER_BOUND_POINT));
|
||||
ASSERT_NE(v, value::percent(-CompactValue::UPPER_BOUND_POINT));
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_one_point) {
|
||||
auto c = CompactValue({value::points(1)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(1));
|
||||
ASSERT_NE(v, value::percent(1));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_negative_one_point) {
|
||||
auto c = CompactValue({value::points(-1)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_EQ(v, value::points(-1));
|
||||
ASSERT_NE(v, value::percent(-1));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_zero_percent) {
|
||||
auto c = CompactValue{value::percent(0)};
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(0));
|
||||
ASSERT_EQ(v, value::percent(0));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_lower_bound_percent) {
|
||||
auto c = CompactValue({value::percent(CompactValue::LOWER_BOUND)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(CompactValue::LOWER_BOUND));
|
||||
ASSERT_EQ(v, value::percent(CompactValue::LOWER_BOUND));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_negative_lower_bound_percent) {
|
||||
auto c = CompactValue({value::percent(-CompactValue::LOWER_BOUND)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-CompactValue::LOWER_BOUND));
|
||||
ASSERT_EQ(v, value::percent(-CompactValue::LOWER_BOUND));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_clamps_smaller_than_lower_bound_percent_to_zero) {
|
||||
auto c = CompactValue({value::percent(tooSmall)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(0));
|
||||
ASSERT_EQ(v, value::percent(0));
|
||||
}
|
||||
|
||||
TEST(
|
||||
YogaTest,
|
||||
compact_value_clamps_greater_than_negative_lower_bound_percent_to_zero) {
|
||||
auto c = CompactValue({value::percent(-tooSmall)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(0));
|
||||
ASSERT_EQ(v, value::percent(0));
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_upper_bound_percent) {
|
||||
auto c = CompactValue({value::percent(CompactValue::UPPER_BOUND_PERCENT)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(CompactValue::UPPER_BOUND_PERCENT));
|
||||
ASSERT_EQ(v, value::percent(CompactValue::UPPER_BOUND_PERCENT));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_negative_upper_bound_percent) {
|
||||
auto c = CompactValue({value::percent(-CompactValue::UPPER_BOUND_PERCENT)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-CompactValue::UPPER_BOUND_PERCENT));
|
||||
ASSERT_EQ(v, value::percent(-CompactValue::UPPER_BOUND_PERCENT));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(
|
||||
YogaTest,
|
||||
compact_value_clamps_greater_than_upper_bound_percent_to_upper_bound) {
|
||||
auto c = CompactValue({value::percent(tooLargePercent)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(CompactValue::UPPER_BOUND_PERCENT));
|
||||
ASSERT_EQ(v, value::percent(CompactValue::UPPER_BOUND_PERCENT));
|
||||
}
|
||||
|
||||
TEST(
|
||||
YogaTest,
|
||||
compact_value_clamps_smaller_than_negative_upper_bound_percent_to_upper_bound) {
|
||||
auto c = CompactValue({value::percent(-tooLargePercent)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-CompactValue::UPPER_BOUND_PERCENT));
|
||||
ASSERT_EQ(v, value::percent(-CompactValue::UPPER_BOUND_PERCENT));
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_one_percent) {
|
||||
auto c = CompactValue({value::percent(1)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(1));
|
||||
ASSERT_EQ(v, value::percent(1));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
||||
|
||||
TEST(YogaTest, compact_value_can_represent_negative_one_percent) {
|
||||
auto c = CompactValue({value::percent(-1)});
|
||||
auto v = (StyleLength)c;
|
||||
ASSERT_NE(v, value::undefined());
|
||||
ASSERT_NE(v, value::ofAuto());
|
||||
ASSERT_NE(v, value::points(-1));
|
||||
ASSERT_EQ(v, value::percent(-1));
|
||||
ASSERT_FALSE(c.isUndefined());
|
||||
ASSERT_FALSE(c.isAuto());
|
||||
}
|
161
tests/SmallValueBufferTest.cpp
Normal file
161
tests/SmallValueBufferTest.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <yoga/style/SmallValueBuffer.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
constexpr size_t kBufferSize = 4;
|
||||
|
||||
TEST(SmallValueBuffer, copy_assignment_with_overflow) {
|
||||
std::array<uint16_t, kBufferSize + 1> handles;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer1;
|
||||
for (size_t i = 0; i < kBufferSize + 1; ++i) {
|
||||
handles[i] = buffer1.push(static_cast<uint32_t>(i));
|
||||
}
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer2 = buffer1;
|
||||
for (size_t i = 0; i < kBufferSize + 1; ++i) {
|
||||
EXPECT_EQ(buffer2.get32(handles[i]), i);
|
||||
}
|
||||
|
||||
auto handle = buffer1.push(42u);
|
||||
EXPECT_EQ(buffer1.get32(handle), 42);
|
||||
|
||||
EXPECT_THROW({ buffer2.get32(handle); }, std::logic_error);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, push_32) {
|
||||
uint32_t magic = 88567114u;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle = buffer.push(magic);
|
||||
EXPECT_EQ(buffer.get32(handle), magic);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, push_overflow) {
|
||||
uint32_t magic1 = 88567114u;
|
||||
uint32_t magic2 = 351012214u;
|
||||
uint32_t magic3 = 146122128u;
|
||||
uint32_t magic4 = 2171092154u;
|
||||
uint32_t magic5 = 2269016953u;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
EXPECT_EQ(buffer.get32(buffer.push(magic1)), magic1);
|
||||
EXPECT_EQ(buffer.get32(buffer.push(magic2)), magic2);
|
||||
EXPECT_EQ(buffer.get32(buffer.push(magic3)), magic3);
|
||||
EXPECT_EQ(buffer.get32(buffer.push(magic4)), magic4);
|
||||
EXPECT_EQ(buffer.get32(buffer.push(magic5)), magic5);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, push_64) {
|
||||
uint64_t magic = 118138934255546108ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle = buffer.push(magic);
|
||||
EXPECT_EQ(buffer.get64(handle), magic);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, push_64_overflow) {
|
||||
uint64_t magic1 = 1401612388342512ull;
|
||||
uint64_t magic2 = 118712305386210ull;
|
||||
uint64_t magic3 = 752431801563359011ull;
|
||||
uint64_t magic4 = 118138934255546108ull;
|
||||
uint64_t magic5 = 237115443124116111ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
EXPECT_EQ(buffer.get64(buffer.push(magic1)), magic1);
|
||||
EXPECT_EQ(buffer.get64(buffer.push(magic2)), magic2);
|
||||
EXPECT_EQ(buffer.get64(buffer.push(magic3)), magic3);
|
||||
EXPECT_EQ(buffer.get64(buffer.push(magic4)), magic4);
|
||||
EXPECT_EQ(buffer.get64(buffer.push(magic5)), magic5);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, push_64_after_32) {
|
||||
uint32_t magic32 = 88567114u;
|
||||
uint64_t magic64 = 118712305386210ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle32 = buffer.push(magic32);
|
||||
EXPECT_EQ(buffer.get32(handle32), magic32);
|
||||
|
||||
auto handle64 = buffer.push(magic64);
|
||||
EXPECT_EQ(buffer.get64(handle64), magic64);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, push_32_after_64) {
|
||||
uint32_t magic32 = 88567114u;
|
||||
uint64_t magic64 = 118712305386210ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle64 = buffer.push(magic64);
|
||||
EXPECT_EQ(buffer.get64(handle64), magic64);
|
||||
|
||||
auto handle32 = buffer.push(magic32);
|
||||
EXPECT_EQ(buffer.get32(handle32), magic32);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, replace_32_with_32) {
|
||||
uint32_t magic1 = 88567114u;
|
||||
uint32_t magic2 = 351012214u;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle = buffer.push(magic1);
|
||||
|
||||
EXPECT_EQ(buffer.get32(buffer.replace(handle, magic2)), magic2);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, replace_32_with_64) {
|
||||
uint32_t magic32 = 88567114u;
|
||||
uint64_t magic64 = 118712305386210ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle = buffer.push(magic32);
|
||||
|
||||
EXPECT_EQ(buffer.get64(buffer.replace(handle, magic64)), magic64);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, replace_32_with_64_causes_overflow) {
|
||||
uint32_t magic1 = 88567114u;
|
||||
uint32_t magic2 = 351012214u;
|
||||
uint32_t magic3 = 146122128u;
|
||||
uint32_t magic4 = 2171092154u;
|
||||
|
||||
uint64_t magic64 = 118712305386210ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle1 = buffer.push(magic1);
|
||||
buffer.push(magic2);
|
||||
buffer.push(magic3);
|
||||
buffer.push(magic4);
|
||||
|
||||
EXPECT_EQ(buffer.get64(buffer.replace(handle1, magic64)), magic64);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, replace_64_with_32) {
|
||||
uint32_t magic32 = 88567114u;
|
||||
uint64_t magic64 = 118712305386210ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle = buffer.push(magic64);
|
||||
|
||||
EXPECT_EQ(buffer.get32(buffer.replace(handle, magic32)), magic32);
|
||||
}
|
||||
|
||||
TEST(SmallValueBuffer, replace_64_with_64) {
|
||||
uint64_t magic1 = 1401612388342512ull;
|
||||
uint64_t magic2 = 118712305386210ull;
|
||||
|
||||
SmallValueBuffer<kBufferSize> buffer;
|
||||
auto handle = buffer.push(magic1);
|
||||
|
||||
EXPECT_EQ(buffer.get64(buffer.replace(handle, magic2)), magic2);
|
||||
}
|
||||
|
||||
} // namespace facebook::yoga
|
131
tests/StyleValuePoolTest.cpp
Normal file
131
tests/StyleValuePoolTest.cpp
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <yoga/style/StyleValuePool.h>
|
||||
|
||||
namespace facebook::yoga {
|
||||
|
||||
TEST(StyleValuePool, undefined_at_init) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
EXPECT_TRUE(handle.isUndefined());
|
||||
EXPECT_FALSE(handle.isDefined());
|
||||
EXPECT_EQ(pool.getLength(handle), value::undefined());
|
||||
EXPECT_EQ(pool.getNumber(handle), FloatOptional{});
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, auto_at_init) {
|
||||
StyleValuePool pool;
|
||||
auto handle = StyleValueHandle::ofAuto();
|
||||
|
||||
EXPECT_TRUE(handle.isAuto());
|
||||
EXPECT_EQ(pool.getLength(handle), value::ofAuto());
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_small_int_points) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::points(10));
|
||||
|
||||
EXPECT_EQ(pool.getLength(handle), value::points(10));
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_small_negative_int_points) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::points(-10));
|
||||
|
||||
EXPECT_EQ(pool.getLength(handle), value::points(-10));
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_small_int_percent) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::percent(10));
|
||||
|
||||
EXPECT_EQ(pool.getLength(handle), value::percent(10));
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_large_int_percent) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::percent(262144));
|
||||
|
||||
EXPECT_EQ(pool.getLength(handle), value::percent(262144));
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_large_int_after_small_int) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::percent(10));
|
||||
pool.store(handle, value::percent(262144));
|
||||
|
||||
EXPECT_EQ(pool.getLength(handle), value::percent(262144));
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_small_int_after_large_int) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::percent(262144));
|
||||
pool.store(handle, value::percent(10));
|
||||
|
||||
EXPECT_EQ(pool.getLength(handle), value::percent(10));
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_small_int_number) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, FloatOptional{10.0f});
|
||||
|
||||
EXPECT_EQ(pool.getNumber(handle), FloatOptional{10.0f});
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_undefined) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::undefined());
|
||||
|
||||
EXPECT_TRUE(handle.isUndefined());
|
||||
EXPECT_FALSE(handle.isDefined());
|
||||
EXPECT_EQ(pool.getLength(handle), value::undefined());
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_undefined_after_small_int) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::points(10));
|
||||
pool.store(handle, value::undefined());
|
||||
|
||||
EXPECT_TRUE(handle.isUndefined());
|
||||
EXPECT_FALSE(handle.isDefined());
|
||||
EXPECT_EQ(pool.getLength(handle), value::undefined());
|
||||
}
|
||||
|
||||
TEST(StyleValuePool, store_undefined_after_large_int) {
|
||||
StyleValuePool pool;
|
||||
StyleValueHandle handle;
|
||||
|
||||
pool.store(handle, value::points(262144));
|
||||
pool.store(handle, value::undefined());
|
||||
|
||||
EXPECT_TRUE(handle.isUndefined());
|
||||
EXPECT_FALSE(handle.isDefined());
|
||||
EXPECT_EQ(pool.getLength(handle), value::undefined());
|
||||
}
|
||||
|
||||
} // namespace facebook::yoga
|
Reference in New Issue
Block a user