1 /*
2  * Copyright (C) 2017 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 #include <array>
18 #include <cstdint>
19 
20 #include <gtest/gtest.h>
21 
22 #include "netdutils/Slice.h"
23 #include "netdutils/Status.h"
24 #include "netdutils/StatusOr.h"
25 
26 namespace android {
27 namespace netdutils {
28 
29 class SliceTest : public testing::Test {
30   protected:
31     std::array<char, 256> mRaw = {};
32 };
33 
TEST_F(SliceTest,smoke)34 TEST_F(SliceTest, smoke) {
35     Slice s1 = makeSlice(mRaw);
36     Slice s2 = makeSlice(mRaw);
37     auto p = split(s1, 14);
38     s2 = p.first; // avoid warn-unused error
39     std::stringstream ss;
40     ss << Slice();
41     EXPECT_EQ("Slice[base: 0x0, limit: 0x0, size: 0x0]", ss.str());
42     constexpr size_t kBytes = 14;
43     EXPECT_EQ(s1.base(), take(s1, kBytes).base());
44     EXPECT_EQ(kBytes, take(s1, kBytes).size());
45     EXPECT_EQ(s1.base() + kBytes, drop(s1, kBytes).base());
46     EXPECT_EQ(s1.size() - kBytes, drop(s1, kBytes).size());
47     double a = 0;
48     double b = 0;
49     int c = 0;
50     EXPECT_EQ(sizeof(a), extract(s1, a));
51     EXPECT_EQ(sizeof(a) + sizeof(b), extract(s1, a, b));
52     EXPECT_EQ(sizeof(a) + sizeof(b) + sizeof(c), extract(s1, a, b, c));
53 }
54 
TEST_F(SliceTest,constructor)55 TEST_F(SliceTest, constructor) {
56     // Expect the following lines to compile
57     Slice s1 = makeSlice(mRaw);
58     Slice s2(s1);
59     Slice s3 = s2;
60     const Slice s4(s3);
61     const Slice s5 = s4;
62     s3 = s5;
63     Slice s6(mRaw.data(), mRaw.size());
64     Slice s7(mRaw.data(), mRaw.data() + mRaw.size());
65     struct {
66       int a;
67       double b;
68       float c;
69     } anon;
70     makeSlice(anon);
71     EXPECT_EQ(reinterpret_cast<uint8_t*>(mRaw.data()), s1.base());
72     EXPECT_EQ(reinterpret_cast<uint8_t*>(mRaw.data()) + mRaw.size(), s1.limit());
73     EXPECT_EQ(mRaw.size(), s1.size());
74     EXPECT_FALSE(mRaw.empty());
75     EXPECT_TRUE(Slice().empty());
76     EXPECT_TRUE(Slice(nullptr, static_cast<size_t>(0)).empty());
77     EXPECT_TRUE(Slice(nullptr, nullptr).empty());
78 }
79 
TEST_F(SliceTest,extract)80 TEST_F(SliceTest, extract) {
81     struct A {
82         int a, b;
83         bool operator==(const A& other) const { return a == other.a && b == other.b; }
84     };
85     struct B {
86         char str[12];
87         bool b;
88         int i;
89         bool operator==(const B& other) const {
90             return b == other.b && i == other.i && 0 == strncmp(str, other.str, 12);
91         }
92     };
93 
94     A origA1 = {1, 2};
95     A origA2 = {3, 4};
96     B origB = {"hello world", true, 1234};
97 
98     // Populate buffer for extracting.
99     Slice buffer = makeSlice(mRaw);
100     copy(buffer, makeSlice(origA1));
101     copy(drop(buffer, sizeof(origA1)), makeSlice(origB));
102     copy(drop(buffer, sizeof(origA1) + sizeof(origB)), makeSlice(origA2));
103 
104     {
105         // Non-variadic extract
106         A a1{};
107         size_t len = extract(buffer, a1);
108         EXPECT_EQ(sizeof(A), len);
109         EXPECT_EQ(origA1, a1);
110     }
111 
112     {
113         // Variadic extract, 2 destinations
114         A a1{};
115         B b{};
116         size_t len = extract(buffer, a1, b);
117         EXPECT_EQ(sizeof(A) + sizeof(B), len);
118         EXPECT_EQ(origA1, a1);
119         EXPECT_EQ(origB, b);
120     }
121 
122     {
123         // Variadic extract, 3 destinations
124         A a1{}, a2{};
125         B b{};
126         size_t len = extract(buffer, a1, b, a2);
127         EXPECT_EQ(2 * sizeof(A) + sizeof(B), len);
128         EXPECT_EQ(origA1, a1);
129         EXPECT_EQ(origB, b);
130         EXPECT_EQ(origA2, a2);
131     }
132 }
133 
134 }  // namespace netdutils
135 }  // namespace android
136