blob: f08ed7fbbb69529b28d507cc31d2e968aa5d2358 [file] [log] [blame]
/*
* Copyright 2024-present Alibaba Inc.
*
* 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 "paimon/data/blob.h"
#include "gtest/gtest.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::test {
class BlobTest : public ::testing::Test {
public:
void SetUp() override {
pool_ = GetDefaultPool();
dir_ = UniqueTestDirectory::Create();
ASSERT_TRUE(dir_);
uri_ = dir_->Str() + "/file.blob";
file_system_ = std::make_shared<LocalFileSystem>();
ASSERT_OK(file_system_->WriteFile(uri_, "abcdefghijklmn", true));
}
void TearDown() override {}
private:
std::shared_ptr<MemoryPool> pool_;
std::unique_ptr<UniqueTestDirectory> dir_;
std::shared_ptr<FileSystem> file_system_;
std::string uri_;
};
TEST_F(BlobTest, TestSimple) {
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> blob, Blob::FromPath(uri_));
auto serialized = blob->ToDescriptor(pool_);
ASSERT_OK_AND_ASSIGN(auto restored_blob,
Blob::FromDescriptor(serialized->data(), serialized->size()));
ASSERT_EQ(*restored_blob->ToDescriptor(pool_), *serialized);
ASSERT_OK_AND_ASSIGN(auto input_stream, restored_blob->NewInputStream(file_system_));
ASSERT_EQ(uri_, restored_blob->Uri());
std::string str(14, '\0');
ASSERT_OK(input_stream->Read(str.data(), str.size()));
ASSERT_EQ("abcdefghijklmn", str);
}
TEST_F(BlobTest, TestInvalidParameters) {
// Test null file system in NewInputStream
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> blob, Blob::FromPath(uri_));
ASSERT_NOK_WITH_MSG(blob->NewInputStream(nullptr), "file system is nullptr");
// Test invalid descriptor
std::string invalid_bytes = "invalid_descriptor_bytes";
ASSERT_NOK(Blob::FromDescriptor(invalid_bytes.data(), invalid_bytes.size()));
}
TEST_F(BlobTest, TestRoundTripConsistency) {
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> original_blob,
Blob::FromPath(uri_, /*offset=*/1, /*length=*/5));
auto first_descriptor = original_blob->ToDescriptor(pool_);
ASSERT_OK_AND_ASSIGN(auto restored_blob,
Blob::FromDescriptor(first_descriptor->data(), first_descriptor->size()));
auto second_descriptor = restored_blob->ToDescriptor(pool_);
ASSERT_EQ(*first_descriptor, *second_descriptor);
// Verify scheme consistency
ASSERT_EQ(original_blob->Uri(), restored_blob->Uri());
}
TEST_F(BlobTest, TestInputStreamCreation) {
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> blob, Blob::FromPath(uri_));
ASSERT_OK_AND_ASSIGN(auto input_stream, blob->NewInputStream(file_system_));
ASSERT_TRUE(input_stream);
// Test reading from the input stream
std::string buffer(14, '\0');
ASSERT_OK_AND_ASSIGN(auto bytes_read, input_stream->Read(buffer.data(), buffer.size()));
ASSERT_EQ(14, bytes_read);
ASSERT_EQ("abcdefghijklmn", buffer);
}
TEST_F(BlobTest, TestBoundaryConditions) {
// Test with empty path
ASSERT_NOK_WITH_MSG(Blob::FromPath(""), "path is an empty string");
// Test with very large offset and length values
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> blob,
Blob::FromPath(uri_, /*offset=*/INT64_MAX, /*length=*/1));
auto serialized = blob->ToDescriptor(pool_);
ASSERT_OK_AND_ASSIGN(auto restored_blob,
Blob::FromDescriptor(serialized->data(), serialized->size()));
ASSERT_EQ(*restored_blob->ToDescriptor(pool_), *serialized);
}
TEST_F(BlobTest, TestNewInputStreamWithOffsetAndLength) {
// Create blob with offset=2, length=6 (should read "cdefgh")
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> blob,
Blob::FromPath(uri_, /*offset=*/2, /*length=*/6));
ASSERT_OK_AND_ASSIGN(auto input_stream, blob->NewInputStream(file_system_));
ASSERT_TRUE(input_stream);
ASSERT_OK_AND_ASSIGN(uint64_t length, input_stream->Length());
ASSERT_EQ(6, length);
// Test reading with offset and length applied
std::string buffer(6, '\0');
ASSERT_OK_AND_ASSIGN(auto bytes_read, input_stream->Read(buffer.data(), buffer.size()));
ASSERT_EQ(6, bytes_read);
ASSERT_EQ("cdefgh", buffer);
}
TEST_F(BlobTest, TestNewInputStreamWithDynamicLength) {
// Create blob with offset=2, dynamic length (-1 means read to end)
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Blob> blob,
Blob::FromPath(uri_, /*offset=*/2, /*length=*/-1));
ASSERT_OK_AND_ASSIGN(auto input_stream, blob->NewInputStream(file_system_));
ASSERT_TRUE(input_stream);
ASSERT_OK_AND_ASSIGN(uint64_t length, input_stream->Length());
ASSERT_EQ(12, length);
// Test reading from offset to end (should read "cdefghijklmn")
std::string buffer(12, '\0');
ASSERT_OK_AND_ASSIGN(auto bytes_read, input_stream->Read(buffer.data(), buffer.size()));
ASSERT_EQ(12, bytes_read);
ASSERT_EQ("cdefghijklmn", buffer);
}
} // namespace paimon::test