C++程序  |  147行  |  4.11 KB

/*
 * Copyright (C) 2018 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 <algorithm>
#include <cstdint>
#include <utility>

#include <gtest/gtest.h>

#include "netdutils/MemBlock.h"
#include "netdutils/Slice.h"

namespace android {
namespace netdutils {

namespace {

constexpr unsigned DNS_PACKET_SIZE = 512;
constexpr int ARBITRARY_VALUE = 0x55;

MemBlock makeArbitraryMemBlock(size_t len) {
    MemBlock result(len);
    // Do some fictional work before returning.
    for (Slice slice = result.get(); !slice.empty(); slice = drop(slice, 1)) {
        slice.base()[0] = ARBITRARY_VALUE;
    }
    return result;
}

void checkAllZeros(Slice slice) {
    for (; !slice.empty(); slice = drop(slice, 1)) {
        EXPECT_EQ(0U, slice.base()[0]);
    }
}

void checkArbitraryMemBlock(const MemBlock& block, size_t expectedSize) {
    Slice slice = block.get();
    EXPECT_EQ(expectedSize, slice.size());
    EXPECT_NE(nullptr, slice.base());
    for (; !slice.empty(); slice = drop(slice, 1)) {
        EXPECT_EQ(ARBITRARY_VALUE, slice.base()[0]);
    }
}

void checkHelloMello(Slice dest, Slice src) {
    EXPECT_EQ('h', dest.base()[0]);
    EXPECT_EQ('e', dest.base()[1]);
    EXPECT_EQ('l', dest.base()[2]);
    EXPECT_EQ('l', dest.base()[3]);
    EXPECT_EQ('o', dest.base()[4]);

    src.base()[0] = 'm';
    EXPECT_EQ('h', dest.base()[0]);
}

}  // namespace

TEST(MemBlockTest, Empty) {
    MemBlock empty;
    EXPECT_TRUE(empty.get().empty());
    EXPECT_EQ(nullptr, empty.get().base());
}

TEST(MemBlockTest, ExplicitZero) {
    MemBlock zero(0);
    EXPECT_TRUE(zero.get().empty());
    EXPECT_EQ(nullptr, zero.get().base());
}

TEST(MemBlockTest, BasicAllocation) {
    MemBlock dnsPacket(DNS_PACKET_SIZE);
    Slice slice = dnsPacket.get();
    EXPECT_EQ(DNS_PACKET_SIZE, slice.size());
    // Verify the space is '\0'-initialized.
    ASSERT_NO_FATAL_FAILURE(checkAllZeros(slice));
    EXPECT_NE(nullptr, slice.base());
}

TEST(MemBlockTest, MoveConstruction) {
    MemBlock block(makeArbitraryMemBlock(DNS_PACKET_SIZE));
    ASSERT_NO_FATAL_FAILURE(checkArbitraryMemBlock(block, DNS_PACKET_SIZE));
}

TEST(MemBlockTest, MoveAssignmentOrConstruction) {
    MemBlock block = makeArbitraryMemBlock(DNS_PACKET_SIZE);
    ASSERT_NO_FATAL_FAILURE(checkArbitraryMemBlock(block, DNS_PACKET_SIZE));
}

TEST(MemBlockTest, StdMoveAssignment) {
    constexpr unsigned SIZE = 10;

    MemBlock block;
    EXPECT_TRUE(block.get().empty());
    EXPECT_EQ(nullptr, block.get().base());

    {
        MemBlock block2 = makeArbitraryMemBlock(SIZE);
        EXPECT_EQ(SIZE, block2.get().size());
        // More fictional work.
        for (unsigned i = 0; i < SIZE; i++) {
            block2.get().base()[i] = i;
        }
        block = std::move(block2);
    }

    EXPECT_EQ(SIZE, block.get().size());
    for (unsigned i = 0; i < SIZE; i++) {
        EXPECT_EQ(i, block.get().base()[i]);
    }
}

TEST(MemBlockTest, ConstructionFromSlice) {
    uint8_t data[] = {'h', 'e', 'l', 'l', 'o'};
    Slice dataSlice(Slice(data, sizeof(data) / sizeof(data[0])));

    MemBlock dataCopy(dataSlice);
    ASSERT_NO_FATAL_FAILURE(checkHelloMello(dataCopy.get(), dataSlice));
}

TEST(MemBlockTest, ImplicitCastToSlice) {
    uint8_t data[] = {'h', 'e', 'l', 'l', 'o'};
    Slice dataSlice(Slice(data, sizeof(data) / sizeof(data[0])));

    MemBlock dataCopy(dataSlice.size());
    // NOTE: no explicit MemBlock::get().
    // Verify the space is '\0'-initialized.
    ASSERT_NO_FATAL_FAILURE(checkAllZeros(dataCopy));
    copy(dataCopy, dataSlice);
    ASSERT_NO_FATAL_FAILURE(checkHelloMello(dataCopy, dataSlice));
}

}  // namespace netdutils
}  // namespace android