| /* | 
 |  * 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 |