blob: 5ed84cc0aacdcbeeeb87988adae8f7213dd86802 [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 "iceberg/update/update_partition_statistics.h"
#include <algorithm>
#include <memory>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "iceberg/result.h"
#include "iceberg/statistics_file.h"
#include "iceberg/test/matchers.h"
#include "iceberg/test/update_test_base.h"
namespace iceberg {
class UpdatePartitionStatisticsTest : public UpdateTestBase {
protected:
// Helper function to create a partition statistics file
std::shared_ptr<PartitionStatisticsFile> MakePartitionStatisticsFile(
int64_t snapshot_id, const std::string& path, int64_t file_size = 2048) {
auto stats_file = std::make_shared<PartitionStatisticsFile>();
stats_file->snapshot_id = snapshot_id;
stats_file->path = path;
stats_file->file_size_in_bytes = file_size;
return stats_file;
}
// Helper to find partition statistics file by snapshot_id in the result vector
std::shared_ptr<PartitionStatisticsFile> FindPartitionStatistics(
const std::vector<std::pair<int64_t, std::shared_ptr<PartitionStatisticsFile>>>&
to_set,
int64_t snapshot_id) {
auto it = std::ranges::find_if(
to_set, [snapshot_id](const auto& p) { return p.first == snapshot_id; });
return it != to_set.end() ? it->second : nullptr;
}
};
TEST_F(UpdatePartitionStatisticsTest, EmptyUpdate) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_TRUE(result.to_set.empty());
EXPECT_TRUE(result.to_remove.empty());
}
TEST_F(UpdatePartitionStatisticsTest, SetPartitionStatistics) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
auto partition_stats_file = MakePartitionStatisticsFile(
1, "/warehouse/test_table/metadata/partition-stats-1.parquet");
update->SetPartitionStatistics(partition_stats_file);
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_EQ(result.to_set.size(), 1);
EXPECT_TRUE(result.to_remove.empty());
auto found = FindPartitionStatistics(result.to_set, 1);
ASSERT_NE(found, nullptr);
EXPECT_EQ(found->snapshot_id, 1);
EXPECT_EQ(found->path, "/warehouse/test_table/metadata/partition-stats-1.parquet");
EXPECT_EQ(found->file_size_in_bytes, 2048);
}
TEST_F(UpdatePartitionStatisticsTest, SetMultiplePartitionStatistics) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
auto partition_stats_file1 = MakePartitionStatisticsFile(
1, "/warehouse/test_table/metadata/partition-stats-1.parquet");
auto partition_stats_file2 = MakePartitionStatisticsFile(
2, "/warehouse/test_table/metadata/partition-stats-2.parquet", 4096);
update->SetPartitionStatistics(partition_stats_file1);
update->SetPartitionStatistics(partition_stats_file2);
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_EQ(result.to_set.size(), 2);
EXPECT_TRUE(result.to_remove.empty());
auto found1 = FindPartitionStatistics(result.to_set, 1);
ASSERT_NE(found1, nullptr);
EXPECT_EQ(found1->snapshot_id, 1);
auto found2 = FindPartitionStatistics(result.to_set, 2);
ASSERT_NE(found2, nullptr);
EXPECT_EQ(found2->snapshot_id, 2);
EXPECT_EQ(found2->file_size_in_bytes, 4096);
}
TEST_F(UpdatePartitionStatisticsTest, ReplacePartitionStatistics) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
auto partition_stats_file1 = MakePartitionStatisticsFile(
1, "/warehouse/test_table/metadata/partition-stats-1.parquet");
auto partition_stats_file2 = MakePartitionStatisticsFile(
1, "/warehouse/test_table/metadata/partition-stats-1-updated.parquet", 8192);
update->SetPartitionStatistics(partition_stats_file1);
update->SetPartitionStatistics(partition_stats_file2);
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_EQ(result.to_set.size(), 1);
EXPECT_TRUE(result.to_remove.empty());
auto found = FindPartitionStatistics(result.to_set, 1);
ASSERT_NE(found, nullptr);
EXPECT_EQ(found->path,
"/warehouse/test_table/metadata/partition-stats-1-updated.parquet");
EXPECT_EQ(found->file_size_in_bytes, 8192);
}
TEST_F(UpdatePartitionStatisticsTest, RemovePartitionStatistics) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
update->RemovePartitionStatistics(1);
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_TRUE(result.to_set.empty());
EXPECT_EQ(result.to_remove.size(), 1);
EXPECT_EQ(result.to_remove[0], 1);
}
TEST_F(UpdatePartitionStatisticsTest, SetThenRemovePartitionStatistics) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
auto partition_stats_file = MakePartitionStatisticsFile(
1, "/warehouse/test_table/metadata/partition-stats-1.parquet");
update->SetPartitionStatistics(partition_stats_file);
update->RemovePartitionStatistics(1);
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_TRUE(result.to_set.empty());
EXPECT_EQ(result.to_remove.size(), 1);
EXPECT_EQ(result.to_remove[0], 1);
}
TEST_F(UpdatePartitionStatisticsTest, SetNullPartitionStatistics) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
update->SetPartitionStatistics(nullptr);
auto result = update->Apply();
EXPECT_THAT(result, IsError(ErrorKind::kValidationFailed));
EXPECT_THAT(result, HasErrorMessage("Statistics file cannot be null"));
}
TEST_F(UpdatePartitionStatisticsTest, SetAndRemoveMixed) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdatePartitionStatistics());
auto partition_stats_file1 = MakePartitionStatisticsFile(
1, "/warehouse/test_table/metadata/partition-stats-1.parquet");
auto partition_stats_file2 = MakePartitionStatisticsFile(
2, "/warehouse/test_table/metadata/partition-stats-2.parquet");
update->SetPartitionStatistics(partition_stats_file1);
update->SetPartitionStatistics(partition_stats_file2);
update->RemovePartitionStatistics(3);
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_EQ(result.to_set.size(), 2);
EXPECT_EQ(result.to_remove.size(), 1);
EXPECT_EQ(result.to_remove[0], 3);
}
} // namespace iceberg