blob: 177939427a7ef5f15cac318a98e40cf77b0b0ada [file] [log] [blame]
// 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 <deque>
#include <string>
#include <gtest/gtest.h>
#include <stout/error.hpp>
#include <stout/gtest.hpp>
#include <stout/recordio.hpp>
#include <stout/some.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>
using std::deque;
using std::string;
template <typename T>
bool operator==(Try<T> lhs, Try<T> rhs)
{
if (lhs.isSome() != rhs.isSome()) {
return false;
}
if (lhs.isSome()) {
return lhs.get() == rhs.get();
}
return lhs.error() == rhs.error();
}
template <typename T>
bool operator!=(Try<T> lhs, Try<T> rhs)
{
return !(lhs == rhs);
}
template <typename T>
bool operator==(deque<T> rhs, deque<T> lhs)
{
if (rhs.size() != lhs.size()) {
return false;
}
auto it1 = rhs.begin();
auto it2 = lhs.begin();
while (it1 != rhs.end()) {
if (*it1 != *it2) {
return false;
}
++it1;
++it2;
}
return true;
}
TEST(RecordIOTest, Encoder)
{
recordio::Encoder<string> encoder(strings::upper);
string data;
data += encoder.encode("hello!");
data += encoder.encode("");
data += encoder.encode(" ");
data += encoder.encode("13 characters");
EXPECT_EQ(
"6\nHELLO!"
"0\n"
"1\n "
"13\n13 CHARACTERS",
data);
// Make sure these can be decoded.
recordio::Decoder<string> decoder(
[=](const string& data) {
return Try<string>(strings::lower(data));
});
deque<Try<string>> records;
records.push_back("hello!");
records.push_back("");
records.push_back(" ");
records.push_back("13 characters");
EXPECT_SOME_EQ(records, decoder.decode(data));
}
TEST(RecordIOTest, Decoder)
{
// Deserializing brings to lower case, but add an
// error case to test deserialization failures.
auto deserialize = [](const string& data) -> Try<string> {
if (data == "error") {
return Error("error");
}
return strings::lower(data);
};
recordio::Decoder<string> decoder(deserialize);
deque<Try<string>> records;
// Empty data should not result in an error.
records.clear();
EXPECT_SOME_EQ(records, decoder.decode(""));
// Should decode more than 1 record when possible.
records.clear();
records.push_back("hello!");
records.push_back("");
records.push_back(" ");
EXPECT_SOME_EQ(records, decoder.decode("6\nHELLO!0\n1\n "));
// An entry which cannot be decoded should not
// fail the decoder permanently.
records.clear();
records.push_back(Error("error"));
EXPECT_SOME_EQ(records, decoder.decode("5\nerror"));
// Record should only be decoded once complete.
records.clear();
EXPECT_SOME_EQ(records, decoder.decode("1"));
EXPECT_SOME_EQ(records, decoder.decode("3"));
EXPECT_SOME_EQ(records, decoder.decode("\n"));
EXPECT_SOME_EQ(records, decoder.decode("13 CHARACTER"));
records.clear();
records.push_back("13 characters");
EXPECT_SOME_EQ(records, decoder.decode("S"));
// If the format is bad, the decoder should fail permanently.
EXPECT_ERROR(decoder.decode("not a number\n"));
EXPECT_ERROR(decoder.decode("1\n"));
}