blob: e39aad6c6bc8b735e5d9a0c3f1464ffe0bf160de [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 "paimon/format/avro/avro_input_stream_impl.h"
#include <filesystem>
#include <fstream>
#include <string>
#include "gtest/gtest.h"
#include "paimon/fs/file_system.h"
#include "paimon/fs/local/local_file_system.h"
#include "paimon/memory/memory_pool.h"
#include "paimon/status.h"
#include "paimon/testing/utils/testharness.h"
namespace paimon::avro::test {
TEST(AvroInputStreamImplTest, TestNext) {
auto dir = paimon::test::UniqueTestDirectory::Create();
std::filesystem::path file_path = dir->Str() + "/file";
std::ofstream output_file(file_path);
ASSERT_TRUE(output_file.is_open());
std::string test_data = "hello world";
output_file << test_data;
output_file.close();
size_t buffer_size = 10;
std::shared_ptr<FileSystem> fs = std::make_shared<LocalFileSystem>();
ASSERT_OK_AND_ASSIGN(std::shared_ptr<InputStream> in, fs->Open(file_path));
ASSERT_OK_AND_ASSIGN(auto stream,
AvroInputStreamImpl::Create(in, buffer_size, GetDefaultPool()));
const uint8_t* data;
size_t size;
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 10);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), test_data.substr(0, 10));
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 1);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), test_data.substr(10, 1));
ASSERT_FALSE(stream->next(&data, &size));
}
TEST(AvroInputStreamImplTest, TestBackup) {
auto dir = paimon::test::UniqueTestDirectory::Create();
std::filesystem::path file_path = dir->Str() + "/file";
std::ofstream output_file(file_path);
ASSERT_TRUE(output_file.is_open());
std::string test_data = "abcdefghij";
output_file << test_data;
output_file.close();
size_t buffer_size = 10;
std::shared_ptr<FileSystem> fs = std::make_shared<LocalFileSystem>();
ASSERT_OK_AND_ASSIGN(std::shared_ptr<InputStream> in, fs->Open(file_path));
ASSERT_OK_AND_ASSIGN(auto stream,
AvroInputStreamImpl::Create(in, buffer_size, GetDefaultPool()));
const uint8_t* data;
size_t size;
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 10);
stream->backup(3);
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 3);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), "hij");
stream->backup(10);
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 10);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), test_data);
}
TEST(AvroInputStreamImplTest, TestSkip) {
auto dir = paimon::test::UniqueTestDirectory::Create();
std::filesystem::path file_path = dir->Str() + "/file";
std::ofstream output_file(file_path);
ASSERT_TRUE(output_file.is_open());
std::string test_data = "abcdefghij";
output_file << test_data;
output_file.close();
size_t buffer_size = 10;
std::shared_ptr<FileSystem> fs = std::make_shared<LocalFileSystem>();
ASSERT_OK_AND_ASSIGN(std::shared_ptr<InputStream> in, fs->Open(file_path));
ASSERT_OK_AND_ASSIGN(auto stream,
AvroInputStreamImpl::Create(in, buffer_size, GetDefaultPool()));
const uint8_t* data;
size_t size;
stream->skip(5);
ASSERT_EQ(stream->byteCount(), 5);
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 5);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), "fghij");
ASSERT_THROW(stream->skip(5), ::avro::Exception); // already eof, cannot skip more
ASSERT_EQ(stream->byteCount(), 10);
ASSERT_FALSE(stream->next(&data, &size)); // reach eof
ASSERT_THROW(stream->backup(7), ::avro::Exception); // buffer item is 5, cannot backup 7
stream->backup(4);
ASSERT_EQ(stream->byteCount(), 6);
stream->skip(2); // skip 2 bytes from the available buffer data
ASSERT_EQ(stream->byteCount(), 8);
// verify we can read the remaining 2 bytes from buffer
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 2);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), "ij");
ASSERT_EQ(stream->byteCount(), 10);
}
TEST(AvroInputStreamImplTest, TestSkipWithAvailableData) {
auto dir = paimon::test::UniqueTestDirectory::Create();
std::filesystem::path file_path = dir->Str() + "/file";
std::ofstream output_file(file_path);
ASSERT_TRUE(output_file.is_open());
std::string test_data = "abcdefghij";
output_file << test_data;
output_file.close();
size_t buffer_size = 10;
std::shared_ptr<FileSystem> fs = std::make_shared<LocalFileSystem>();
ASSERT_OK_AND_ASSIGN(std::shared_ptr<InputStream> in, fs->Open(file_path));
ASSERT_OK_AND_ASSIGN(auto stream,
AvroInputStreamImpl::Create(in, buffer_size, GetDefaultPool()));
const uint8_t* data;
size_t size;
// First, load data into buffer by calling next()
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 10);
ASSERT_EQ(stream->byteCount(), 10);
// Now backup some data to make it available in buffer
stream->backup(7);
ASSERT_EQ(stream->byteCount(), 3);
// Skip 3 bytes from the available buffer data
stream->skip(3);
ASSERT_EQ(stream->byteCount(), 6);
// Verify we can read the remaining 4 bytes from buffer
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(size, 4);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), "ghij");
ASSERT_EQ(stream->byteCount(), 10);
}
TEST(AvroInputStreamImplTest, TestSeek) {
auto dir = paimon::test::UniqueTestDirectory::Create();
std::filesystem::path file_path = dir->Str() + "/file";
std::ofstream output_file(file_path);
ASSERT_TRUE(output_file.is_open());
std::string test_data = "abcdefghij";
output_file << test_data;
output_file.close();
size_t buffer_size = 5;
std::shared_ptr<FileSystem> fs = std::make_shared<LocalFileSystem>();
ASSERT_OK_AND_ASSIGN(std::shared_ptr<InputStream> in, fs->Open(file_path));
ASSERT_OK_AND_ASSIGN(auto stream,
AvroInputStreamImpl::Create(in, buffer_size, GetDefaultPool()));
const uint8_t* data;
size_t size;
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(stream->byteCount(), 5);
ASSERT_EQ(size, 5);
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), "abcde");
stream->seek(2);
ASSERT_EQ(stream->byteCount(), 2);
// after seek, buffer will be cleared, cannot backup
ASSERT_THROW(stream->backup(2), ::avro::Exception);
ASSERT_TRUE(stream->next(&data, &size));
ASSERT_EQ(std::string(reinterpret_cast<const char*>(data), size), "cdefg");
ASSERT_EQ(stream->byteCount(), 7);
ASSERT_EQ(size, 5);
}
} // namespace paimon::avro::test