blob: f3017d5b01367187e6a14e94aa1ff01ac6dd940c [file] [log] [blame]
/*
* 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 <limits>
#include <random>
#include <gtest/gtest.h>
#include <geode/CacheFactory.hpp>
#include <geode/DataOutput.hpp>
#include "ByteArrayFixture.hpp"
#include "DataOutputInternal.hpp"
#include "SerializationRegistry.hpp"
namespace {
using apache::geode::client::ByteArray;
using apache::geode::client::Cache;
using apache::geode::client::CacheableString;
using apache::geode::client::DataOutputInternal;
using apache::geode::client::SerializationRegistry;
class TestDataOutput : public DataOutputInternal {
public:
explicit TestDataOutput(Cache*)
: DataOutputInternal(nullptr),
m_byteArray(nullptr),
m_serializationRegistry() {
// NOP
}
~TestDataOutput() noexcept override {
delete m_byteArray;
m_byteArray = nullptr;
}
const ByteArray& getByteArray() const {
if (!m_byteArray) {
m_byteArray = new ByteArray(getBuffer(), getBufferLength());
}
return *m_byteArray;
}
protected:
virtual const SerializationRegistry& getSerializationRegistry()
const override {
return m_serializationRegistry;
}
private:
mutable ByteArray* m_byteArray;
SerializationRegistry m_serializationRegistry;
};
class DataOutputTest : public ::testing::Test, public ByteArrayFixture {
public:
DataOutputTest() : m_mersennesTwister(m_randomDevice()) {
// NOP
}
virtual ~DataOutputTest() {
// NOP
}
protected:
std::random_device m_randomDevice;
std::mt19937 m_mersennesTwister;
int32_t getRandomSequenceNumber() {
// One would normally just use std::uniform_int_distribution but gcc 4.4.7
// is lacking.
const std::mt19937::result_type upperLimit =
static_cast<std::mt19937::result_type>(
std::numeric_limits<int32_t>::max());
std::mt19937::result_type result;
while (upperLimit < (result = m_mersennesTwister())) {
// Try again.
}
return static_cast<int32_t>(result);
}
};
TEST_F(DataOutputTest, TestWriteUint8) {
TestDataOutput dataOutput(nullptr);
dataOutput.write(static_cast<uint8_t>(55U));
dataOutput.write(static_cast<uint8_t>(66U));
EXPECT_BYTEARRAY_EQ("3742", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteInt8) {
TestDataOutput dataOutput(nullptr);
dataOutput.write(static_cast<int8_t>(66));
dataOutput.write(static_cast<int8_t>(55));
EXPECT_BYTEARRAY_EQ("4237", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteSequenceNumber) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeInt(static_cast<int32_t>(55));
dataOutput.writeInt(static_cast<int32_t>(17));
dataOutput.writeInt(static_cast<int32_t>(0));
dataOutput.writeInt(getRandomSequenceNumber());
dataOutput.write(static_cast<uint8_t>(0U));
EXPECT_BYTEARRAY_EQ("000000370000001100000000\\h{8}00",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteBoolean) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeBoolean(true);
dataOutput.writeBoolean(false);
EXPECT_BYTEARRAY_EQ("0100", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteBytesSigned) {
int8_t bytes[] = {0, 1, 2, 3, 4, 5, -4, -3, -2, -1, 0};
TestDataOutput dataOutput(nullptr);
dataOutput.writeBytes(bytes, 11);
EXPECT_BYTEARRAY_EQ("0B000102030405FCFDFEFF00", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteBytesOnlyUnsigned) {
uint8_t bytes[] = {0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0};
TestDataOutput dataOutput(nullptr);
dataOutput.writeBytesOnly(bytes, 11);
EXPECT_BYTEARRAY_EQ("0001020304050403020100", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteBytesOnlySigned) {
int8_t bytes[] = {0, 1, 2, 3, 4, 5, -4, -3, -2, -1, 0};
TestDataOutput dataOutput(nullptr);
dataOutput.writeBytesOnly(bytes, 11);
EXPECT_BYTEARRAY_EQ("000102030405FCFDFEFF00", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteIntUInt16) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeInt(static_cast<uint16_t>(66));
dataOutput.writeInt(static_cast<uint16_t>(55));
dataOutput.writeInt(static_cast<uint16_t>(3333));
EXPECT_BYTEARRAY_EQ("004200370D05", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteCharUInt16) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeChar(static_cast<uint16_t>(66));
dataOutput.writeChar(static_cast<uint16_t>(55));
dataOutput.writeChar(static_cast<uint16_t>(3333));
EXPECT_BYTEARRAY_EQ("004200370D05", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteIntUInt32) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeInt(static_cast<uint32_t>(3435973836));
EXPECT_BYTEARRAY_EQ("CCCCCCCC", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteIntUInt64) {
TestDataOutput dataOutput(nullptr);
uint64_t big = 13455272147882261178U;
dataOutput.writeInt(big);
EXPECT_BYTEARRAY_EQ("BABABABABABABABA", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteIntInt16) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeInt(static_cast<int16_t>(66));
dataOutput.writeInt(static_cast<int16_t>(55));
dataOutput.writeInt(static_cast<int16_t>(3333));
EXPECT_BYTEARRAY_EQ("004200370D05", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteIntInt32) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeInt(static_cast<int32_t>(3435973836));
EXPECT_BYTEARRAY_EQ("CCCCCCCC", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteIntInt64) {
TestDataOutput dataOutput(nullptr);
int64_t big = 773738426788457421;
dataOutput.writeInt(big);
EXPECT_BYTEARRAY_EQ("0ABCDEFFEDCBABCD", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteArrayLength) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeArrayLen(static_cast<int32_t>(3435973836));
EXPECT_BYTEARRAY_EQ("CC", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteFloat) {
TestDataOutput dataOutput(nullptr);
float pi = 3.14f;
dataOutput.writeFloat(pi);
EXPECT_BYTEARRAY_EQ("4048F5C3", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteDouble) {
TestDataOutput dataOutput(nullptr);
double pi = 3.14159265359;
dataOutput.writeDouble(pi);
EXPECT_BYTEARRAY_EQ("400921FB54442EEA", dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteString) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeString("You had me at meat tornado.");
EXPECT_BYTEARRAY_EQ(
"2A001B596F7520686164206D65206174206D65617420746F726E61646F2E",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteUTF) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeUTF("You had me at meat tornado.");
EXPECT_BYTEARRAY_EQ(
"001B596F7520686164206D65206174206D65617420746F726E61646F2E",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteUTFWide) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeUTF(L"You had me at meat tornado!");
EXPECT_BYTEARRAY_EQ(
"001B596F7520686164206D65206174206D65617420746F726E61646F21",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteChars) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeChars("You had me at meat tornado.");
EXPECT_BYTEARRAY_EQ(
"0059006F007500200068006100640020006D00650020006100740020006D006500610074"
"00200074006F0072006E00610064006F002E",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteStringFromUtf8String) {
TestDataOutput dataOutput(nullptr);
auto str = std::string(u8"You had me at");
str.push_back(0);
str.append(u8"meat tornad\u00F6!\U000F0000");
dataOutput.writeString(str);
EXPECT_BYTEARRAY_EQ(
"2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED"
"B080",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteStringFromUtf16String) {
TestDataOutput dataOutput(nullptr);
auto str = std::u16string(u"You had me at");
str.push_back(0);
str.append(u"meat tornad\u00F6!\U000F0000");
dataOutput.writeString(str);
EXPECT_BYTEARRAY_EQ(
"2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED"
"B080",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteStringFromUcs4String) {
TestDataOutput dataOutput(nullptr);
auto str = std::u32string(U"You had me at");
str.push_back(0);
str.append(U"meat tornad\u00F6!\U000F0000");
dataOutput.writeString(str);
EXPECT_BYTEARRAY_EQ(
"2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED"
"B080",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteStringFromWideString) {
TestDataOutput dataOutput(nullptr);
auto str = std::wstring(L"You had me at");
str.push_back(0);
str.append(L"meat tornad\u00F6!\U000F0000");
dataOutput.writeString(str);
EXPECT_BYTEARRAY_EQ(
"2A0023596F7520686164206D65206174C0806D65617420746F726E6164C3B621EDAE80ED"
"B080",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestWriteObjectSharedPtr) {
TestDataOutput dataOutput(nullptr);
auto objptr = CacheableString::create("You had me at meat tornado.");
dataOutput.writeObject(objptr);
EXPECT_BYTEARRAY_EQ(
"57001B596F7520686164206D65206174206D65617420746F726E61646F2E",
dataOutput.getByteArray());
}
TEST_F(DataOutputTest, TestCursorAdvance) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeUTF("You had me at meat tornado.");
EXPECT_BYTEARRAY_EQ(
"001B596F7520686164206D65206174206D65617420746F726E61646F2E",
dataOutput.getByteArray());
const auto originalLength = dataOutput.getBufferLength();
dataOutput.advanceCursor(2);
EXPECT_EQ((originalLength + 2), dataOutput.getBufferLength())
<< "Correct length after advance";
}
TEST_F(DataOutputTest, TestCursorNegativeAdvance) {
TestDataOutput dataOutput(nullptr);
dataOutput.writeUTF("You had me at meat tornado.");
EXPECT_BYTEARRAY_EQ(
"001B596F7520686164206D65206174206D65617420746F726E61646F2E",
dataOutput.getByteArray());
const auto originalLength = dataOutput.getBufferLength();
dataOutput.advanceCursor(-2);
EXPECT_EQ((originalLength - 2), dataOutput.getBufferLength())
<< "Correct length after negative advance";
}
} // namespace