| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 <stdint.h> |
| |
| #include <string> // for ::memset() |
| #define NOMINMAX |
| #if defined(NOMINMAX) |
| // ifnore unused macro warning |
| #endif |
| #include <cstdint> |
| #include <memory> |
| |
| #include <gtest/gtest.h> |
| |
| #include <geode/CacheFactory.hpp> |
| #include <geode/DataInput.hpp> |
| |
| #include "ByteArrayFixture.hpp" |
| #include "DataInputInternal.hpp" |
| #include "DataOutputInternal.hpp" |
| #include "SerializationRegistry.hpp" |
| |
| namespace { |
| |
| using apache::geode::client::ByteArray; |
| using apache::geode::client::CacheableString; |
| using apache::geode::client::DataInputInternal; |
| using apache::geode::client::DataOutputInternal; |
| using apache::geode::client::Serializable; |
| using apache::geode::client::SerializationRegistry; |
| |
| class DataInputUnderTest : public DataInputInternal { |
| public: |
| using DataInputInternal::DataInputInternal; |
| ~DataInputUnderTest() noexcept override {} |
| |
| virtual const SerializationRegistry &getSerializationRegistry() |
| const override { |
| return m_serializationRegistry; |
| } |
| |
| private: |
| SerializationRegistry m_serializationRegistry; |
| }; |
| |
| class TestDataInput { |
| public: |
| explicit TestDataInput(const char *str) |
| : m_byteArray(ByteArray::fromString(str)), |
| m_dataInput(m_byteArray.get(), m_byteArray.size()) { |
| // NOP |
| } |
| |
| void read(uint8_t *value) { *value = m_dataInput.read(); } |
| |
| void read(int8_t *value) { *value = m_dataInput.read(); } |
| |
| void readBoolean(bool *value) { *value = m_dataInput.readBoolean(); } |
| |
| void readBytesOnly(uint8_t *buffer, uint32_t len) { |
| m_dataInput.readBytesOnly(buffer, len); |
| } |
| |
| void readBytesOnly(int8_t *buffer, uint32_t len) { |
| m_dataInput.readBytesOnly(buffer, len); |
| } |
| |
| void readBytes(uint8_t **buffer, int32_t *len) { |
| m_dataInput.readBytes(buffer, len); |
| } |
| |
| void readBytes(int8_t **buffer, int32_t *len) { |
| m_dataInput.readBytes(buffer, len); |
| } |
| |
| int16_t readInt16() { return m_dataInput.readInt16(); } |
| |
| int32_t readInt32() { return m_dataInput.readInt32(); } |
| |
| void readInt(uint64_t *value) { *value = m_dataInput.readInt64(); } |
| |
| int64_t readInt64() { return m_dataInput.readInt64(); } |
| |
| int32_t readArrayLen() { return m_dataInput.readArrayLength(); } |
| |
| int64_t readUnsignedVL() { return m_dataInput.readUnsignedVL(); } |
| |
| float readFloat() { return m_dataInput.readFloat(); } |
| |
| double readDouble() { return m_dataInput.readDouble(); } |
| |
| bool readNativeBool() { return m_dataInput.readNativeBool(); } |
| |
| int32_t readNativeInt32() { return m_dataInput.readNativeInt32(); } |
| |
| std::shared_ptr<Serializable> readDirectObject(int8_t typeId = -1) { |
| return m_dataInput.readDirectObject(typeId); |
| } |
| |
| std::shared_ptr<Serializable> readObject() { |
| return m_dataInput.readObject(); |
| } |
| |
| void readObject(std::shared_ptr<Serializable> &ptr) { |
| m_dataInput.readObject(ptr); |
| } |
| |
| std::vector<char16_t> readCharArray() { return m_dataInput.readCharArray(); } |
| |
| std::vector<std::string> readStringArray() { |
| return m_dataInput.readStringArray(); |
| } |
| |
| std::vector<bool> readBooleanArray() { |
| return m_dataInput.readBooleanArray(); |
| } |
| |
| void readArrayOfByteArrays(int8_t ***arrayofBytearr, int32_t &arrayLength, |
| int32_t **elementLength) { |
| m_dataInput.readArrayOfByteArrays(arrayofBytearr, arrayLength, |
| elementLength); |
| } |
| |
| size_t getBytesRead() const { return m_dataInput.getBytesRead(); } |
| |
| size_t getBytesRemaining() const { return m_dataInput.getBytesRemaining(); } |
| |
| void advanceCursor(int32_t offset) { m_dataInput.advanceCursor(offset); } |
| |
| void rewindCursor(int32_t offset) { m_dataInput.rewindCursor(offset); } |
| |
| void reset() { m_dataInput.reset(); } |
| |
| void setBuffer() { m_dataInput.setBuffer(); } |
| |
| template <class CharT = char, class... Tail> |
| inline std::basic_string<CharT, Tail...> readUTF() { |
| return m_dataInput.readUTF<CharT, Tail...>(); |
| } |
| |
| template <class CharT = char, class... Tail> |
| inline std::basic_string<CharT, Tail...> readString() { |
| return m_dataInput.readString<CharT, Tail...>(); |
| } |
| |
| private: |
| ByteArray m_byteArray; |
| |
| DataInputUnderTest m_dataInput; |
| }; |
| |
| class DataInputTest : public ::testing::Test, protected ByteArrayFixture { |
| public: |
| ~DataInputTest() noexcept override {} |
| }; |
| |
| TEST_F(DataInputTest, ThrowsWhenReadingInputWithSizeZero) { |
| TestDataInput dataInput(""); |
| |
| uint8_t aByte = 0U; |
| ASSERT_THROW(dataInput.read(&aByte), |
| apache::geode::client::OutOfRangeException); |
| } |
| |
| TEST_F(DataInputTest, ThrowsWhenReadingMoreBytesThanSizePassedToConstructor) { |
| TestDataInput dataInput("01"); |
| |
| uint8_t aByte = 0U; |
| dataInput.read(&aByte); |
| EXPECT_EQ(1U, aByte); |
| |
| aByte = 0U; |
| ASSERT_THROW(dataInput.read(&aByte), |
| apache::geode::client::OutOfRangeException); |
| } |
| |
| TEST_F(DataInputTest, CanReadUnsignedBytesFromInput) { |
| TestDataInput dataInput("FF00"); |
| |
| uint8_t aByte = 0U; |
| dataInput.read(&aByte); |
| EXPECT_EQ(aByte, 255); |
| |
| aByte = 0U; |
| dataInput.read(&aByte); |
| EXPECT_EQ(aByte, 0); |
| } |
| |
| TEST_F(DataInputTest, CanReadSignedBytesFromInput) { |
| TestDataInput dataInput("807F"); |
| |
| int8_t aByte = 0U; |
| dataInput.read(&aByte); |
| EXPECT_EQ(aByte, -128); |
| |
| aByte = 0; |
| dataInput.read(&aByte); |
| EXPECT_EQ(aByte, 127); |
| } |
| |
| TEST_F(DataInputTest, CanReadABooleanFromInput) { |
| bool boolArray[2] = {true, false}; |
| DataInputUnderTest dataInput(reinterpret_cast<uint8_t *>(boolArray), 2); |
| |
| auto aBool = dataInput.readBoolean(); |
| EXPECT_EQ(aBool, true); |
| |
| aBool = dataInput.readBoolean(); |
| EXPECT_EQ(aBool, false); |
| } |
| |
| TEST_F(DataInputTest, CanReadAnArrayOfBytesFromInput) { |
| TestDataInput dataInput("010203"); |
| |
| uint8_t byteArrayCopy[4]; |
| dataInput.readBytesOnly(byteArrayCopy, 3); |
| EXPECT_EQ(byteArrayCopy[0], 1); |
| EXPECT_EQ(byteArrayCopy[1], 2); |
| EXPECT_EQ(byteArrayCopy[2], 3); |
| } |
| |
| TEST_F(DataInputTest, |
| ThrowsWhenReadingMoreContinuousBytesThanSizePassedToConstructor) { |
| TestDataInput dataInput("010203"); |
| |
| // fails to read 4 bytes from 3 byte buffer |
| uint8_t byteArrayCopy[4]; |
| ASSERT_THROW(dataInput.readBytesOnly(byteArrayCopy, 4), |
| apache::geode::client::OutOfRangeException); |
| } |
| |
| TEST_F(DataInputTest, CanReadIntWithAMaxSizeUnsigned64BitIntInput) { |
| uint64_t intArray[1] = {std::numeric_limits<uint64_t>::max()}; |
| DataInputUnderTest dataInput(reinterpret_cast<uint8_t *>(intArray), |
| sizeof(intArray)); |
| |
| uint64_t aInt = dataInput.readInt64(); |
| EXPECT_EQ(aInt, std::numeric_limits<uint64_t>::max()); |
| } |
| |
| TEST_F(DataInputTest, CanReadUTFWithAnUTFStringInput) { |
| const std::string expectedString = "foobar"; |
| DataOutputInternal stream; |
| stream.writeUTF(expectedString); |
| |
| DataInputUnderTest dataInput(stream.getBufferCopy(), |
| stream.getBufferLength()); |
| auto actualString = dataInput.readUTF(); |
| |
| EXPECT_TRUE(expectedString == actualString); |
| } |
| |
| TEST_F(DataInputTest, InputResetCausesPristineRead) { |
| TestDataInput dataInput("010203"); |
| |
| // 1) read byte off buffer |
| // 2) then reset buffer back |
| uint8_t aByte = 0U; |
| dataInput.read(&aByte); |
| dataInput.reset(); |
| |
| // 3) next byte read should be start byte |
| aByte = 0U; |
| dataInput.read(&aByte); |
| EXPECT_EQ(aByte, 1); |
| } |
| |
| TEST_F(DataInputTest, InputRewindCausesReplayedRead) { |
| TestDataInput dataInput("010203"); |
| |
| uint8_t aByte = 0U; |
| dataInput.read(&aByte); |
| dataInput.read(&aByte); |
| dataInput.read(&aByte); |
| |
| dataInput.rewindCursor(1); |
| |
| dataInput.read(&aByte); |
| EXPECT_EQ(aByte, 3); |
| } |
| |
| TEST_F(DataInputTest, TestReadUint8) { |
| TestDataInput dataInput("37"); |
| uint8_t value = 0U; |
| dataInput.read(&value); |
| EXPECT_EQ((uint8_t)55U, value) << "Correct uint8_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadInt8) { |
| TestDataInput dataInput("37"); |
| int8_t value = 0; |
| dataInput.read(&value); |
| EXPECT_EQ((int8_t)55, value) << "Correct int8_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadBoolean) { |
| TestDataInput dataInput("01"); |
| bool value = false; |
| dataInput.readBoolean(&value); |
| EXPECT_EQ(true, value) << "Correct bool"; |
| } |
| |
| TEST_F(DataInputTest, TestReadUint8_tBytesOnly) { |
| TestDataInput dataInput("BABEFACE"); |
| uint8_t buffer[4]; |
| ::memset(buffer, 0U, 4 * sizeof(uint8_t)); |
| dataInput.readBytesOnly(buffer, 4); |
| EXPECT_EQ((uint8_t)186U, buffer[0]) << "Correct zeroth uint8_t"; |
| EXPECT_EQ((uint8_t)190U, buffer[1]) << "Correct first uint8_t"; |
| EXPECT_EQ((uint8_t)250U, buffer[2]) << "Correct second uint8_t"; |
| EXPECT_EQ((uint8_t)206U, buffer[3]) << "Correct third uint8_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadInt8_tBytesOnly) { |
| TestDataInput dataInput("DEADBEEF"); |
| int8_t buffer[4]; |
| ::memset(buffer, 0, 4 * sizeof(int8_t)); |
| dataInput.readBytesOnly(buffer, 4); |
| EXPECT_EQ((int8_t)-34, buffer[0]) << "Correct zeroth int8_t"; |
| EXPECT_EQ((int8_t)-83, buffer[1]) << "Correct first int8_t"; |
| EXPECT_EQ((int8_t)-66, buffer[2]) << "Correct second int8_t"; |
| EXPECT_EQ((int8_t)-17, buffer[3]) << "Correct third int8_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadUint8_tBytes) { |
| TestDataInput dataInput("04BABEFACE"); |
| uint8_t *buffer = nullptr; |
| int32_t len = 0; |
| dataInput.readBytes(&buffer, &len); |
| EXPECT_NE((uint8_t *)nullptr, buffer) << "Non-null buffer"; |
| ASSERT_EQ(4, len) << "Correct length"; |
| EXPECT_EQ((uint8_t)186U, buffer[0]) << "Correct zeroth uint8_t"; |
| EXPECT_EQ((uint8_t)190U, buffer[1]) << "Correct first uint8_t"; |
| EXPECT_EQ((uint8_t)250U, buffer[2]) << "Correct second uint8_t"; |
| EXPECT_EQ((uint8_t)206U, buffer[3]) << "Correct third uint8_t"; |
| _GEODE_SAFE_DELETE_ARRAY(buffer); |
| } |
| |
| TEST_F(DataInputTest, TestReadInt8_tBytes) { |
| TestDataInput dataInput("04DEADBEEF"); |
| int8_t *buffer = nullptr; |
| int32_t len = 0; |
| dataInput.readBytes(&buffer, &len); |
| EXPECT_NE((int8_t *)nullptr, buffer) << "Non-null buffer"; |
| ASSERT_EQ(4, len) << "Correct length"; |
| EXPECT_EQ((int8_t)-34, buffer[0]) << "Correct zeroth int8_t"; |
| EXPECT_EQ((int8_t)-83, buffer[1]) << "Correct first int8_t"; |
| EXPECT_EQ((int8_t)-66, buffer[2]) << "Correct second int8_t"; |
| EXPECT_EQ((int8_t)-17, buffer[3]) << "Correct third int8_t"; |
| _GEODE_SAFE_DELETE_ARRAY(buffer); |
| } |
| |
| TEST_F(DataInputTest, TestReadIntUint16) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| uint16_t value = dataInput.readInt16(); |
| EXPECT_EQ((uint16_t)4660U, value) << "Correct uint16_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadIntInt16) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| int16_t value = dataInput.readInt16(); |
| EXPECT_EQ((int16_t)4660, value) << "Correct int16_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadIntUint32) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| uint32_t value = dataInput.readInt32(); |
| EXPECT_EQ((uint32_t)305419896U, value) << "Correct uint32_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadIntInt32) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| int32_t value = dataInput.readInt32(); |
| EXPECT_EQ((int32_t)305419896, value) << "Correct int32_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadIntUint64) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| uint64_t value = 0U; |
| dataInput.readInt(&value); |
| EXPECT_EQ((uint64_t)1311768467463790320U, value) << "Correct uint64_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadIntInt64) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| int64_t value = dataInput.readInt64(); |
| EXPECT_EQ((int64_t)1311768467463790320, value) << "Correct int64_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadArrayLen) { |
| int32_t len = 0; |
| |
| TestDataInput dataInput0("FF12345678"); |
| len = dataInput0.readArrayLen(); |
| EXPECT_EQ(-1, len) << "Correct length for 0xFF"; |
| |
| TestDataInput dataInput1("FE12345678"); |
| len = dataInput1.readArrayLen(); |
| EXPECT_EQ(4660, len) << "Correct length for 0xFE"; |
| |
| TestDataInput dataInput2("FD12345678"); |
| len = dataInput2.readArrayLen(); |
| EXPECT_EQ(305419896, len) << "Correct length for 0xFD"; |
| |
| TestDataInput dataInput3("FC12345678"); |
| len = dataInput3.readArrayLen(); |
| EXPECT_EQ(252, len) << "Correct length for 0xFC"; |
| } |
| |
| TEST_F(DataInputTest, TestReadUnsignedVL) { |
| // DataInput::readUnsignedVL() uses a variable-length encoding |
| // that uses the top bit of a byte to indicate whether another |
| // byte follows. Thus, the 64 bits must be split into 7-bit |
| // groups and then the follow bit applied. Note that integer |
| // is encoded byte-at-a-time from the smaller end. |
| // |
| // 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 |
| // 1101 1110 1111 0000 |
| // 0 0010010 0011010 0010101 1001111 0001001 1010101 1110011 0111101 |
| // 1110000 |
| // 00 12 1A 15 4F 09 55 73 3D 70 |
| // 00 92 9A 95 CF 89 D5 F3 BD F0 |
| |
| TestDataInput dataInput("F0BDF3D589CF959A9200"); |
| int64_t value = dataInput.readUnsignedVL(); |
| EXPECT_EQ((int64_t)1311768467463790320, value) << "Correct int64_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadFloat) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| float value = dataInput.readFloat(); |
| EXPECT_FLOAT_EQ(5.6904566e-28F, value) << "Correct float"; |
| } |
| |
| TEST_F(DataInputTest, TestReadDouble) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| double value = 0.; |
| value = dataInput.readDouble(); |
| EXPECT_DOUBLE_EQ(5.626349274901198e-221, value) << "Correct double"; |
| } |
| |
| TEST_F(DataInputTest, TestReadUTFNarrow) { |
| TestDataInput dataInput( |
| "001B596F7520686164206D65206174206D65617420746F726E61646F2E"); |
| auto value = dataInput.readUTF(); |
| ASSERT_EQ(static_cast<size_t>(27), value.length()) << "Correct length"; |
| EXPECT_EQ("You had me at meat tornado.", value) << "Correct string"; |
| } |
| |
| TEST_F(DataInputTest, TestReadObjectSharedPtr) { |
| TestDataInput dataInput( |
| "57001B596F7520686164206D65206174206D65617420746F726E61646F2E"); |
| auto objptr = |
| std::dynamic_pointer_cast<CacheableString>(dataInput.readObject()); |
| EXPECT_EQ("You had me at meat tornado.", objptr->value()) |
| << "Correct const char *"; |
| } |
| |
| TEST_F(DataInputTest, TestReadNativeBool) { |
| TestDataInput dataInput("0001"); |
| const bool value = dataInput.readNativeBool(); |
| EXPECT_EQ(true, value) << "Correct bool"; |
| } |
| |
| TEST_F(DataInputTest, TestReadNativeInt32) { |
| TestDataInput dataInput("0012345678"); |
| const int32_t value = dataInput.readNativeInt32(); |
| EXPECT_EQ((int32_t)305419896, value) << "Correct int32_t"; |
| } |
| |
| TEST_F(DataInputTest, TestReadDirectObject) { |
| TestDataInput dataInput( |
| "57001B596F7520686164206D65206174206D65617420746F726E61646F2E"); |
| auto objptr = dataInput.readDirectObject(); |
| EXPECT_EQ("You had me at meat tornado.", |
| std::dynamic_pointer_cast<CacheableString>(objptr)->toString()) |
| << "Correct const char *"; |
| } |
| |
| TEST_F(DataInputTest, TestReadObjectSerializablePtr) { |
| TestDataInput dataInput( |
| "57001B596F7520686164206D65206174206D65617420746F726E61646F2E"); |
| std::shared_ptr<Serializable> objptr; |
| dataInput.readObject(objptr); |
| EXPECT_EQ("You had me at meat tornado.", |
| std::dynamic_pointer_cast<CacheableString>(objptr)->toString()) |
| << "Correct const char *"; |
| } |
| |
| TEST_F(DataInputTest, TestReadCharArray) { |
| TestDataInput dataInput( |
| "1C0059006F007500200068006100640020006D00650020006100740020006D0065006100" |
| "7400200074006F0072006E00610064006F002E0000"); |
| auto value = dataInput.readCharArray(); |
| ASSERT_EQ(static_cast<size_t>(28), value.size()) << "Correct length"; |
| EXPECT_EQ(std::u16string(u"You had me at meat tornado."), |
| std::u16string(value.data())) |
| << "Correct const char *"; |
| } |
| |
| TEST_F(DataInputTest, TestReadString) { |
| TestDataInput dataInput( |
| "57001B596F7520686164206D65206174206D65617420746F726E61646F2E"); |
| auto value = dataInput.readString(); |
| EXPECT_EQ("You had me at meat tornado.", value) << "Correct std::string"; |
| } |
| |
| TEST_F(DataInputTest, TestReadStringToUtf8String) { |
| auto expected = std::string(u8"You had me at"); |
| expected.push_back(0); |
| expected.append(u8"meat tornad\u00F6!\U000F0000"); |
| |
| TestDataInput dataInput( |
| "2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED" |
| "B080"); |
| auto str = dataInput.readString(); |
| |
| EXPECT_EQ(expected, str); |
| } |
| |
| TEST_F(DataInputTest, TestReadStringToUtf16String) { |
| auto expected = std::u16string(u"You had me at"); |
| expected.push_back(0); |
| expected.append(u"meat tornad\u00F6!\U000F0000"); |
| |
| TestDataInput dataInput( |
| "2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED" |
| "B080"); |
| auto str = dataInput.readString<char16_t>(); |
| |
| EXPECT_EQ(expected, str); |
| } |
| |
| TEST_F(DataInputTest, TestReadStringToUcs4String) { |
| auto expected = std::u32string(U"You had me at"); |
| expected.push_back(0); |
| expected.append(U"meat tornad\u00F6!\U000F0000"); |
| |
| TestDataInput dataInput( |
| "2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED" |
| "B080"); |
| auto str = dataInput.readString<char32_t>(); |
| |
| EXPECT_EQ(expected, str); |
| } |
| |
| TEST_F(DataInputTest, TestReadStringToWideString) { |
| auto expected = std::wstring(L"You had me at"); |
| expected.push_back(0); |
| expected.append(L"meat tornad\u00F6!\U000F0000"); |
| |
| TestDataInput dataInput( |
| "2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED" |
| "B080"); |
| auto str = dataInput.readString<wchar_t>(); |
| |
| EXPECT_EQ(expected, str); |
| } |
| |
| TEST_F(DataInputTest, TestReadStringArray) { |
| TestDataInput dataInput( |
| "0157001B596F7520686164206D65206174206D65617420746F726E61646F2E"); |
| auto value = dataInput.readStringArray(); |
| ASSERT_EQ(static_cast<size_t>(1), value.size()) << "Correct length"; |
| EXPECT_EQ("You had me at meat tornado.", value[0]) << "Correct char *"; |
| } |
| |
| TEST_F(DataInputTest, TestReadArrayOfByteArrays) { |
| TestDataInput dataInput("0104DEADBEEF"); |
| int8_t **arrayOfByteArrays = nullptr; |
| int32_t arrayLength = 0; |
| int32_t *elementLength = nullptr; |
| dataInput.readArrayOfByteArrays(&arrayOfByteArrays, arrayLength, |
| &elementLength); |
| EXPECT_NE((int8_t **)nullptr, arrayOfByteArrays) |
| << "Non-null array of byte arrays"; |
| ASSERT_EQ(1, arrayLength) << "Correct array length"; |
| EXPECT_NE((int8_t *)nullptr, arrayOfByteArrays[0]) |
| << "Non-null first byte array"; |
| ASSERT_EQ(4, elementLength[0]) << "Correct length"; |
| EXPECT_EQ((int8_t)-34, arrayOfByteArrays[0][0]) << "Correct zeroth int8_t"; |
| EXPECT_EQ((int8_t)-83, arrayOfByteArrays[0][1]) << "Correct first int8_t"; |
| EXPECT_EQ((int8_t)-66, arrayOfByteArrays[0][2]) << "Correct second int8_t"; |
| EXPECT_EQ((int8_t)-17, arrayOfByteArrays[0][3]) << "Correct third int8_t"; |
| _GEODE_SAFE_DELETE_ARRAY(elementLength); |
| _GEODE_SAFE_DELETE_ARRAY(arrayOfByteArrays); |
| } |
| |
| TEST_F(DataInputTest, TestGetBytesRead) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRead()) |
| << "Correct bytes read before any reads"; |
| uint8_t value = 0U; |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRead()) |
| << "Correct bytes read after half of the reads"; |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRead()) |
| << "Correct bytes read after all of the reads"; |
| } |
| |
| TEST_F(DataInputTest, TestGetBytesRemaining) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining before any reads"; |
| uint8_t value = 0U; |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after half of the reads"; |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after all of the reads"; |
| } |
| |
| TEST_F(DataInputTest, TestAdvanceCursor) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRead()) |
| << "Correct bytes read before any advancement"; |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining before any advancement"; |
| dataInput.advanceCursor(5); |
| EXPECT_EQ(static_cast<size_t>(5), dataInput.getBytesRead()) |
| << "Correct bytes read after forward advancement"; |
| EXPECT_EQ(static_cast<size_t>(3), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after forward advancement"; |
| dataInput.advanceCursor(-3); |
| EXPECT_EQ(static_cast<size_t>(2), dataInput.getBytesRead()) |
| << "Correct bytes read after rearward advancement"; |
| EXPECT_EQ(static_cast<size_t>(6), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after rearward advancement"; |
| } |
| |
| TEST_F(DataInputTest, TestRewindCursor) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRead()) |
| << "Correct bytes read before any rewinding"; |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining before any rewinding"; |
| dataInput.rewindCursor(-5); |
| EXPECT_EQ(static_cast<size_t>(5), dataInput.getBytesRead()) |
| << "Correct bytes read after forward rewinding"; |
| EXPECT_EQ(static_cast<size_t>(3), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after forward rewinding"; |
| dataInput.rewindCursor(3); |
| EXPECT_EQ(static_cast<size_t>(2), dataInput.getBytesRead()) |
| << "Correct bytes read after rearward rewinding"; |
| EXPECT_EQ(static_cast<size_t>(6), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after rearward rewinding"; |
| } |
| |
| TEST_F(DataInputTest, TestReset) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRead()) |
| << "Correct bytes read before any reads"; |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining before any reads"; |
| uint8_t value = 0U; |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRead()) |
| << "Correct bytes read after the reads"; |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after the reads"; |
| dataInput.reset(); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRead()) |
| << "Correct bytes read after the reset"; |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after the reset"; |
| } |
| |
| TEST_F(DataInputTest, TestSetBuffer) { |
| TestDataInput dataInput("123456789ABCDEF0"); |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRead()) |
| << "Correct bytes read before any reads"; |
| EXPECT_EQ(static_cast<size_t>(8), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining before any reads"; |
| uint8_t value = 0U; |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| dataInput.read(&value); |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRead()) |
| << "Correct bytes read after the reads"; |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after the reads"; |
| dataInput.setBuffer(); |
| EXPECT_EQ(static_cast<size_t>(4), dataInput.getBytesRead()) |
| << "Correct bytes read after the setting"; |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.getBytesRemaining()) |
| << "Correct bytes remaining after the setting"; |
| } |
| |
| TEST_F(DataInputTest, TestReadNullArray) { |
| TestDataInput dataInput("FF12345678"); |
| |
| EXPECT_EQ(static_cast<size_t>(0), dataInput.readBooleanArray().size()); |
| } |
| |
| } // namespace |