C++程序  |  136行  |  3.8 KB

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <array>
#include <cstdint>

#include <gtest/gtest.h>

#include "netdutils/Slice.h"
#include "netdutils/Status.h"
#include "netdutils/StatusOr.h"

namespace android {
namespace netdutils {

class SliceTest : public testing::Test {
  protected:
    std::array<char, 256> mRaw = {};
};

TEST_F(SliceTest, smoke) {
    Slice s1 = makeSlice(mRaw);
    Slice s2 = makeSlice(mRaw);
    auto p = split(s1, 14);
    s2 = p.first; // avoid warn-unused error
    std::stringstream ss;
    ss << Slice();
    EXPECT_EQ("Slice[base: 0x0, limit: 0x0, size: 0x0]", ss.str());
    constexpr size_t kBytes = 14;
    EXPECT_EQ(s1.base(), take(s1, kBytes).base());
    EXPECT_EQ(kBytes, take(s1, kBytes).size());
    EXPECT_EQ(s1.base() + kBytes, drop(s1, kBytes).base());
    EXPECT_EQ(s1.size() - kBytes, drop(s1, kBytes).size());
    double a = 0;
    double b = 0;
    int c = 0;
    EXPECT_EQ(sizeof(a), extract(s1, a));
    EXPECT_EQ(sizeof(a) + sizeof(b), extract(s1, a, b));
    EXPECT_EQ(sizeof(a) + sizeof(b) + sizeof(c), extract(s1, a, b, c));
}

TEST_F(SliceTest, constructor) {
    // Expect the following lines to compile
    Slice s1 = makeSlice(mRaw);
    Slice s2(s1);
    Slice s3 = s2;
    const Slice s4(s3);
    const Slice s5 = s4;
    s3 = s5;
    Slice s6(mRaw.data(), mRaw.size());
    Slice s7(mRaw.data(), mRaw.data() + mRaw.size());
    struct {
      int a;
      double b;
      float c;
    } anon;
    makeSlice(anon);
    EXPECT_EQ(reinterpret_cast<uint8_t*>(mRaw.data()), s1.base());
    EXPECT_EQ(reinterpret_cast<uint8_t*>(mRaw.data()) + mRaw.size(), s1.limit());
    EXPECT_EQ(mRaw.size(), s1.size());
    EXPECT_FALSE(mRaw.empty());
    EXPECT_TRUE(Slice().empty());
    EXPECT_TRUE(Slice(nullptr, static_cast<size_t>(0)).empty());
    EXPECT_TRUE(Slice(nullptr, nullptr).empty());
}

TEST_F(SliceTest, extract) {
    struct A {
        int a, b;
        bool operator==(const A& other) const { return a == other.a && b == other.b; }
    };
    struct B {
        char str[12];
        bool b;
        int i;
        bool operator==(const B& other) const {
            return b == other.b && i == other.i && 0 == strncmp(str, other.str, 12);
        }
    };

    A origA1 = {1, 2};
    A origA2 = {3, 4};
    B origB = {"hello world", true, 1234};

    // Populate buffer for extracting.
    Slice buffer = makeSlice(mRaw);
    copy(buffer, makeSlice(origA1));
    copy(drop(buffer, sizeof(origA1)), makeSlice(origB));
    copy(drop(buffer, sizeof(origA1) + sizeof(origB)), makeSlice(origA2));

    {
        // Non-variadic extract
        A a1{};
        size_t len = extract(buffer, a1);
        EXPECT_EQ(sizeof(A), len);
        EXPECT_EQ(origA1, a1);
    }

    {
        // Variadic extract, 2 destinations
        A a1{};
        B b{};
        size_t len = extract(buffer, a1, b);
        EXPECT_EQ(sizeof(A) + sizeof(B), len);
        EXPECT_EQ(origA1, a1);
        EXPECT_EQ(origB, b);
    }

    {
        // Variadic extract, 3 destinations
        A a1{}, a2{};
        B b{};
        size_t len = extract(buffer, a1, b, a2);
        EXPECT_EQ(2 * sizeof(A) + sizeof(B), len);
        EXPECT_EQ(origA1, a1);
        EXPECT_EQ(origB, b);
        EXPECT_EQ(origA2, a2);
    }
}

}  // namespace netdutils
}  // namespace android