blob: 5010ddc7ffe1080c6028da12e5fbec85bffde7dd [file]
/*
* 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 <gtest/gtest.h>
#include <cmath>
#include <limits>
#include <vector>
#include "encoding/camel_decoder.h"
#include "encoding/camel_encoder.h"
#include "encoding/decoder_factory.h"
#include "encoding/encoder_factory.h"
namespace storage {
namespace {
void assert_double_equal(double expected, double actual) {
if (std::isnan(expected)) {
EXPECT_TRUE(std::isnan(actual));
} else {
EXPECT_EQ(std::signbit(actual), std::signbit(expected));
EXPECT_DOUBLE_EQ(actual, expected);
}
}
void round_trip(const std::vector<double>& values) {
CamelEncoder encoder;
CamelDecoder decoder;
common::ByteStream stream(1024, common::MOD_DEFAULT);
for (double value : values) {
ASSERT_EQ(encoder.encode(value, stream), common::E_OK);
}
ASSERT_EQ(encoder.flush(stream), common::E_OK);
for (double expected : values) {
ASSERT_TRUE(decoder.has_remaining(stream));
double actual = 0;
ASSERT_EQ(decoder.read_double(actual, stream), common::E_OK);
assert_double_equal(expected, actual);
}
EXPECT_FALSE(decoder.has_remaining(stream));
}
} // namespace
TEST(CamelCodecTest, DecimalAndIntegerPathRoundTrip) {
round_trip({100.0, 100.0001, 100.0002, 99.9999, -7.101, -9.101, 12345.0,
21332213.0, 0.1, 0.2, 0.3});
}
TEST(CamelCodecTest, GorillaFallbackRoundTrip) {
round_trip({std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity(), +0.0, -0.0,
std::numeric_limits<double>::min(),
-std::numeric_limits<double>::min(),
std::numeric_limits<double>::max(),
-std::numeric_limits<double>::max()});
}
TEST(CamelCodecTest, RepeatedFlushBlocksRoundTrip) {
common::ByteStream stream(1024, common::MOD_DEFAULT);
std::vector<double> values = {123.456789, 123.456789, 123.456790,
-123.456790, 0.0, -0.0};
for (int repeat = 0; repeat < 2; ++repeat) {
CamelEncoder encoder;
for (double value : values) {
ASSERT_EQ(encoder.encode(value, stream), common::E_OK);
}
ASSERT_EQ(encoder.flush(stream), common::E_OK);
}
CamelDecoder decoder;
for (int repeat = 0; repeat < 2; ++repeat) {
for (double expected : values) {
ASSERT_TRUE(decoder.has_remaining(stream));
double actual = 0;
ASSERT_EQ(decoder.read_double(actual, stream), common::E_OK);
assert_double_equal(expected, actual);
}
}
EXPECT_FALSE(decoder.has_remaining(stream));
}
TEST(CamelCodecTest, FactoryAllocatesDoubleCodecsOnly) {
Encoder* double_encoder =
EncoderFactory::alloc_value_encoder(common::CAMEL, common::DOUBLE);
Decoder* double_decoder =
DecoderFactory::alloc_value_decoder(common::CAMEL, common::DOUBLE);
Encoder* float_encoder =
EncoderFactory::alloc_value_encoder(common::CAMEL, common::FLOAT);
Decoder* float_decoder =
DecoderFactory::alloc_value_decoder(common::CAMEL, common::FLOAT);
ASSERT_NE(double_encoder, nullptr);
ASSERT_NE(double_decoder, nullptr);
EXPECT_EQ(float_encoder, nullptr);
EXPECT_EQ(float_decoder, nullptr);
EncoderFactory::free(double_encoder);
DecoderFactory::free(double_decoder);
}
} // namespace storage