• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "FlattenableHelpersTest"
18 
19 #include <ui/FlattenableHelpers.h>
20 
21 #include <gtest/gtest.h>
22 #include <utils/Flattenable.h>
23 #include <cstdint>
24 #include <memory>
25 #include <optional>
26 #include <string>
27 #include <vector>
28 
29 namespace android {
30 
31 namespace {
32 
33 struct TestLightFlattenable : LightFlattenable<TestLightFlattenable> {
34     std::unique_ptr<int32_t> ptr;
35 
isFixedSizeandroid::__anonb0c1d3b90111::TestLightFlattenable36     bool isFixedSize() const { return true; }
getFlattenedSizeandroid::__anonb0c1d3b90111::TestLightFlattenable37     size_t getFlattenedSize() const { return sizeof(int32_t); }
38 
flattenandroid::__anonb0c1d3b90111::TestLightFlattenable39     status_t flatten(void* buffer, size_t size) const {
40         FlattenableUtils::write(buffer, size, *ptr);
41         return OK;
42     }
43 
unflattenandroid::__anonb0c1d3b90111::TestLightFlattenable44     status_t unflatten(void const* buffer, size_t size) {
45         int32_t value;
46         FlattenableUtils::read(buffer, size, value);
47         ptr = std::make_unique<int32_t>(value);
48         return OK;
49     }
50 };
51 
52 class FlattenableHelpersTest : public testing::Test {
53 public:
54     template <class T>
testWriteThenRead(const T & value,size_t bufferSize)55     void testWriteThenRead(const T& value, size_t bufferSize) {
56         std::vector<int8_t> buffer(bufferSize);
57         auto rawBuffer = reinterpret_cast<void*>(buffer.data());
58         size_t size = buffer.size();
59         ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, value));
60 
61         auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data());
62         size = buffer.size();
63         T valueRead;
64         ASSERT_EQ(OK, FlattenableHelpers::unflatten(&rawReadBuffer, &size, &valueRead));
65         EXPECT_EQ(value, valueRead);
66     }
67 
68     template <class T>
testTriviallyCopyable(const T & value)69     void testTriviallyCopyable(const T& value) {
70         testWriteThenRead(value, sizeof(T));
71     }
72 
73     template <class T>
testWriteThenRead(const T & value)74     void testWriteThenRead(const T& value) {
75         testWriteThenRead(value, FlattenableHelpers::getFlattenedSize(value));
76     }
77 };
78 
TEST_F(FlattenableHelpersTest,TriviallyCopyable)79 TEST_F(FlattenableHelpersTest, TriviallyCopyable) {
80     testTriviallyCopyable(42);
81     testTriviallyCopyable(1LL << 63);
82     testTriviallyCopyable(false);
83     testTriviallyCopyable(true);
84     testTriviallyCopyable(std::optional<int>());
85     testTriviallyCopyable(std::optional<int>(4));
86 }
87 
TEST_F(FlattenableHelpersTest,String)88 TEST_F(FlattenableHelpersTest, String) {
89     testWriteThenRead(std::string("Android"));
90     testWriteThenRead(std::string());
91 }
92 
TEST_F(FlattenableHelpersTest,Vector)93 TEST_F(FlattenableHelpersTest, Vector) {
94     testWriteThenRead(std::vector<int>({1, 2, 3}));
95     testWriteThenRead(std::vector<int>());
96 }
97 
TEST_F(FlattenableHelpersTest,OptionalOfLightFlattenable)98 TEST_F(FlattenableHelpersTest, OptionalOfLightFlattenable) {
99     std::vector<size_t> buffer;
100     constexpr int kInternalValue = 16;
101     {
102         std::optional<TestLightFlattenable> value =
103                 TestLightFlattenable{.ptr = std::make_unique<int32_t>(kInternalValue)};
104         buffer.assign(FlattenableHelpers::getFlattenedSize(value), 0);
105         void* rawBuffer = reinterpret_cast<void*>(buffer.data());
106         size_t size = buffer.size();
107         ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, value));
108     }
109 
110     const void* rawReadBuffer = reinterpret_cast<const void*>(buffer.data());
111     size_t size = buffer.size();
112     std::optional<TestLightFlattenable> valueRead;
113     ASSERT_EQ(OK, FlattenableHelpers::unflatten(&rawReadBuffer, &size, &valueRead));
114     ASSERT_TRUE(valueRead.has_value());
115     EXPECT_EQ(kInternalValue, *valueRead->ptr);
116 }
117 
TEST_F(FlattenableHelpersTest,NullOptionalOfLightFlattenable)118 TEST_F(FlattenableHelpersTest, NullOptionalOfLightFlattenable) {
119     std::vector<size_t> buffer;
120     {
121         std::optional<TestLightFlattenable> value;
122         buffer.assign(FlattenableHelpers::getFlattenedSize(value), 0);
123         void* rawBuffer = reinterpret_cast<void*>(buffer.data());
124         size_t size = buffer.size();
125         ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, value));
126     }
127 
128     const void* rawReadBuffer = reinterpret_cast<const void*>(buffer.data());
129     size_t size = buffer.size();
130     std::optional<TestLightFlattenable> valueRead;
131     ASSERT_EQ(OK, FlattenableHelpers::unflatten(&rawReadBuffer, &size, &valueRead));
132     ASSERT_FALSE(valueRead.has_value());
133 }
134 
135 // If a struct is both trivially copyable and light flattenable we should treat it
136 // as LigthFlattenable.
TEST_F(FlattenableHelpersTest,TriviallyCopyableAndLightFlattenableIsFlattenedAsLightFlattenable)137 TEST_F(FlattenableHelpersTest, TriviallyCopyableAndLightFlattenableIsFlattenedAsLightFlattenable) {
138     static constexpr int32_t kSizeTag = 1234567;
139     static constexpr int32_t kFlattenTag = 987654;
140     static constexpr int32_t kUnflattenTag = 5926582;
141 
142     struct LightFlattenableAndTriviallyCopyable
143           : LightFlattenable<LightFlattenableAndTriviallyCopyable> {
144         int32_t value;
145 
146         bool isFixedSize() const { return true; }
147         size_t getFlattenedSize() const { return kSizeTag; }
148 
149         status_t flatten(void* buffer, size_t size) const {
150             FlattenableUtils::write(buffer, size, kFlattenTag);
151             return OK;
152         }
153 
154         status_t unflatten(void const*, size_t) {
155             value = kUnflattenTag;
156             return OK;
157         }
158     };
159 
160     {
161         // Verify that getFlattenedSize uses the LightFlattenable overload
162         LightFlattenableAndTriviallyCopyable foo;
163         EXPECT_EQ(kSizeTag, FlattenableHelpers::getFlattenedSize(foo));
164     }
165 
166     {
167         // Verify that flatten uses the LightFlattenable overload
168         std::vector<int8_t> buffer(sizeof(int32_t));
169         auto rawBuffer = reinterpret_cast<void*>(buffer.data());
170         size_t size = buffer.size();
171         LightFlattenableAndTriviallyCopyable foo;
172         ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, foo));
173 
174         auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data());
175         int32_t value;
176         FlattenableHelpers::unflatten(&rawReadBuffer, &size, &value);
177         EXPECT_EQ(kFlattenTag, value);
178     }
179 
180     {
181         // Verify that unflatten uses the LightFlattenable overload
182         std::vector<int8_t> buffer(sizeof(int32_t));
183         auto rawBuffer = reinterpret_cast<void*>(buffer.data());
184         size_t size = buffer.size();
185         int32_t value = 4;
186         ASSERT_EQ(OK, FlattenableHelpers::flatten(&rawBuffer, &size, value));
187 
188         auto rawReadBuffer = reinterpret_cast<const void*>(buffer.data());
189 
190         LightFlattenableAndTriviallyCopyable foo;
191         FlattenableHelpers::unflatten(&rawReadBuffer, &size, &foo);
192         EXPECT_EQ(kUnflattenTag, foo.value);
193     }
194 }
195 
196 } // namespace
197 } // namespace android
198