blob: 886558153f2ca1cef75c93778dc135d31d280918 [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_properties.h"
#include "iceberg/test/matchers.h"
#include "iceberg/test/update_test_base.h"
namespace iceberg {
class UpdatePropertiesTest : public UpdateTestBase {};
TEST_F(UpdatePropertiesTest, EmptyUpdate) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_THAT(result.updates.empty(), true);
}
TEST_F(UpdatePropertiesTest, SetProperty) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("key1", "value1").Set("key2", "value2");
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_EQ(result.updates.size(), 2);
EXPECT_EQ(result.updates.at("key1"), "value1");
EXPECT_EQ(result.updates.at("key2"), "value2");
EXPECT_TRUE(result.removals.empty());
}
TEST_F(UpdatePropertiesTest, RemoveProperty) {
// First, add properties to remove
ICEBERG_UNWRAP_OR_FAIL(auto setup_update, table_->NewUpdateProperties());
setup_update->Set("key1", "value1").Set("key2", "value2");
EXPECT_THAT(setup_update->Commit(), IsOk());
// Reload and remove the properties
ICEBERG_UNWRAP_OR_FAIL(auto reloaded, catalog_->LoadTable(table_ident_));
ICEBERG_UNWRAP_OR_FAIL(auto update, reloaded->NewUpdateProperties());
update->Remove("key1").Remove("key2");
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_TRUE(result.updates.empty());
EXPECT_EQ(result.removals.size(), 2);
EXPECT_TRUE(result.removals.contains("key1"));
EXPECT_TRUE(result.removals.contains("key2"));
}
TEST_F(UpdatePropertiesTest, SetThenRemoveSameKey) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("key1", "value1").Remove("key1");
auto result = update->Apply();
EXPECT_THAT(result, IsError(ErrorKind::kValidationFailed));
EXPECT_THAT(result, HasErrorMessage("already marked for update"));
}
TEST_F(UpdatePropertiesTest, RemoveThenSetSameKey) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Remove("key1").Set("key1", "value1");
auto result = update->Apply();
EXPECT_THAT(result, IsError(ErrorKind::kValidationFailed));
EXPECT_THAT(result, HasErrorMessage("already marked for removal"));
}
TEST_F(UpdatePropertiesTest, SetAndRemoveDifferentKeys) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("key1", "value1").Remove("key2");
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_EQ(result.updates.size(), 1);
EXPECT_EQ(result.updates.at("key1"), "value1");
EXPECT_EQ(result.removals.size(), 1);
EXPECT_TRUE(result.removals.contains("key2"));
}
TEST_F(UpdatePropertiesTest, UpgradeFormatVersionValid) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("format-version", "3");
ICEBERG_UNWRAP_OR_FAIL(auto result, update->Apply());
EXPECT_TRUE(result.updates.empty());
EXPECT_TRUE(result.removals.empty());
ASSERT_TRUE(result.format_version.has_value());
EXPECT_EQ(result.format_version.value(), 3);
}
TEST_F(UpdatePropertiesTest, UpgradeFormatVersionInvalidString) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("format-version", "invalid");
auto result = update->Apply();
EXPECT_THAT(result, IsError(ErrorKind::kInvalidArgument));
EXPECT_THAT(result, HasErrorMessage("invalid argument"));
}
TEST_F(UpdatePropertiesTest, UpgradeFormatVersionOutOfRange) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("format-version", "5000000000");
auto result = update->Apply();
EXPECT_THAT(result, IsError(ErrorKind::kInvalidArgument));
EXPECT_THAT(result, HasErrorMessage("out of range"));
}
TEST_F(UpdatePropertiesTest, UpgradeFormatVersionUnsupported) {
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("format-version",
std::to_string(TableMetadata::kSupportedTableFormatVersion + 1));
auto result = update->Apply();
EXPECT_THAT(result, IsError(ErrorKind::kInvalidArgument));
EXPECT_THAT(result, HasErrorMessage("unsupported format version"));
}
TEST_F(UpdatePropertiesTest, CommitSuccess) {
ICEBERG_UNWRAP_OR_FAIL(auto empty_update, table_->NewUpdateProperties());
EXPECT_THAT(empty_update->Commit(), IsOk());
ICEBERG_UNWRAP_OR_FAIL(auto update, table_->NewUpdateProperties());
update->Set("new.property", "new.value");
update->Set("format-version", "3");
EXPECT_THAT(update->Commit(), IsOk());
ICEBERG_UNWRAP_OR_FAIL(auto reloaded, catalog_->LoadTable(table_ident_));
const auto& props = reloaded->properties().configs();
EXPECT_EQ(props.at("new.property"), "new.value");
const auto& format_version = reloaded->metadata()->format_version;
EXPECT_EQ(format_version, 3);
}
} // namespace iceberg