diff --git a/hudi-common/src/main/java/org/apache/hudi/common/config/HoodieConfig.java b/hudi-common/src/main/java/org/apache/hudi/common/config/HoodieConfig.java index 7345f94229869..a48e4202bf962 100644 --- a/hudi-common/src/main/java/org/apache/hudi/common/config/HoodieConfig.java +++ b/hudi-common/src/main/java/org/apache/hudi/common/config/HoodieConfig.java @@ -70,7 +70,13 @@ public void setDefaultValue(ConfigProperty configProperty) { if (configProperty.getInferFunc().isPresent()) { inferValue = configProperty.getInferFunc().get().apply(this); } - props.setProperty(configProperty.key(), inferValue.isPresent() ? inferValue.get().toString() : configProperty.defaultValue().toString()); + if (inferValue.isPresent() || configProperty.hasDefaultValue()) { + props.setProperty( + configProperty.key(), + inferValue.isPresent() + ? inferValue.get().toString() + : configProperty.defaultValue().toString()); + } } } @@ -114,7 +120,7 @@ protected void setDefaults(String configClassName) { .forEach(f -> { try { ConfigProperty cfgProp = (ConfigProperty) f.get("null"); - if (cfgProp.hasDefaultValue()) { + if (cfgProp.hasDefaultValue() || cfgProp.getInferFunc().isPresent()) { setDefaultValue(cfgProp); } } catch (IllegalAccessException e) { diff --git a/hudi-common/src/test/java/org/apache/hudi/common/config/HoodieTestFakeConfig.java b/hudi-common/src/test/java/org/apache/hudi/common/config/HoodieTestFakeConfig.java new file mode 100644 index 0000000000000..95e213268a3e5 --- /dev/null +++ b/hudi-common/src/test/java/org/apache/hudi/common/config/HoodieTestFakeConfig.java @@ -0,0 +1,96 @@ +/* + * 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. + */ + +package org.apache.hudi.common.config; + +import java.util.Properties; + +/** + * A config class extending {@link HoodieConfig} for testing only. + */ +public class HoodieTestFakeConfig extends HoodieConfig { + + public static ConfigProperty FAKE_STRING_CONFIG = TestConfigProperty.FAKE_STRING_CONFIG; + public static ConfigProperty FAKE_INTEGER_CONFIG = TestConfigProperty.FAKE_INTEGER_CONFIG; + public static ConfigProperty FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER + = TestConfigProperty.FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER; + public static ConfigProperty FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY + = TestConfigProperty.FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY; + + private HoodieTestFakeConfig() { + super(); + } + + private HoodieTestFakeConfig(Properties props) { + super(props); + } + + public String getFakeString() { + return getString(FAKE_STRING_CONFIG); + } + + public int getFakeInteger() { + return getInt(FAKE_INTEGER_CONFIG); + } + + public String getFakeStringNoDefaultWithInfer() { + return getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER); + } + + public String getFakeStringNoDefaultWithInferEmpty() { + return getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY); + } + + public static HoodieTestFakeConfig.Builder newBuilder() { + return new Builder(); + } + + public static class Builder { + private final HoodieTestFakeConfig config = new HoodieTestFakeConfig(); + + public Builder withFakeString(String value) { + config.setValue(FAKE_STRING_CONFIG, value); + return this; + } + + public Builder withFakeInteger(int value) { + config.setValue(FAKE_INTEGER_CONFIG, String.valueOf(value)); + return this; + } + + public Builder withFakeStringNoDefaultWithInfer(String value) { + config.setValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER, value); + return this; + } + + public Builder withFakeStringNoDefaultWithInferEmpty(String value) { + config.setValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY, value); + return this; + } + + public HoodieTestFakeConfig build() { + setDefaults(); + return new HoodieTestFakeConfig(config.getProps()); + } + + private void setDefaults() { + config.setDefaults(HoodieTestFakeConfig.class.getName()); + } + } +} diff --git a/hudi-common/src/test/java/org/apache/hudi/common/config/TestConfigProperty.java b/hudi-common/src/test/java/org/apache/hudi/common/config/TestConfigProperty.java index 091209c56bc5e..584edfe60b948 100644 --- a/hudi-common/src/test/java/org/apache/hudi/common/config/TestConfigProperty.java +++ b/hudi-common/src/test/java/org/apache/hudi/common/config/TestConfigProperty.java @@ -60,6 +60,29 @@ public class TestConfigProperty extends HoodieConfig { }) .withDocumentation("Fake config only for testing"); + public static ConfigProperty FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER = ConfigProperty + .key("test.fake.string.config.no_default_with_infer") + .noDefaultValue() + .withInferFunction(p -> { + if (p.getStringOrDefault(FAKE_STRING_CONFIG).equals("value1")) { + return Option.of("value2"); + } + return Option.of("value3"); + }) + .withDocumentation("Fake config with infer function and without default only for testing"); + + public static ConfigProperty FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY = ConfigProperty + .key("test.fake.string.config.no_default_with_infer_empty") + .noDefaultValue() + .withInferFunction(p -> { + if (p.getStringOrDefault(FAKE_STRING_CONFIG).equals("value1")) { + return Option.of("value10"); + } + return Option.empty(); + }) + .withDocumentation("Fake config with infer function that ca return empty value " + + "and without default only for testing"); + @Test public void testGetTypedValue() { HoodieConfig hoodieConfig = new HoodieConfig(); @@ -112,11 +135,30 @@ public void testInference() { hoodieConfig2.setValue(FAKE_STRING_CONFIG, "5"); hoodieConfig2.setDefaultValue(FAKE_INTEGER_CONFIG); assertEquals(100, hoodieConfig2.getInt(FAKE_INTEGER_CONFIG)); + + HoodieConfig hoodieConfig3 = new HoodieConfig(); + hoodieConfig3.setValue(FAKE_STRING_CONFIG, "value1"); + hoodieConfig3.setDefaultValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER); + hoodieConfig3.setDefaultValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY); + assertEquals("value2", hoodieConfig3.getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER)); + assertEquals("value10", hoodieConfig3.getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY)); + + HoodieConfig hoodieConfig4 = new HoodieConfig(); + hoodieConfig4.setValue(FAKE_STRING_CONFIG, "other"); + hoodieConfig4.setDefaultValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER); + assertEquals("value3", hoodieConfig4.getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER)); + assertEquals(null, hoodieConfig4.getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY)); + + HoodieConfig hoodieConfig5 = new HoodieConfig(); + hoodieConfig5.setValue(FAKE_STRING_CONFIG, "other"); + hoodieConfig5.setValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER, "value4"); + hoodieConfig5.setDefaultValue(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER); + assertEquals("value4", hoodieConfig5.getString(FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER)); } @Test public void testSetDefaults() { setDefaults(this.getClass().getName()); - assertEquals(3, getProps().size()); + assertEquals(4, getProps().size()); } } diff --git a/hudi-common/src/test/java/org/apache/hudi/common/config/TestHoodieConfig.java b/hudi-common/src/test/java/org/apache/hudi/common/config/TestHoodieConfig.java new file mode 100644 index 0000000000000..58e21d202e968 --- /dev/null +++ b/hudi-common/src/test/java/org/apache/hudi/common/config/TestHoodieConfig.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.hudi.common.config; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Tests {@link HoodieConfig}. + */ +public class TestHoodieConfig { + @Test + public void testHoodieConfig() { + // Case 1: defaults and infer function are used + HoodieTestFakeConfig config1 = HoodieTestFakeConfig.newBuilder().build(); + assertEquals("1", config1.getFakeString()); + assertEquals(0, config1.getFakeInteger()); + assertEquals("value3", config1.getFakeStringNoDefaultWithInfer()); + assertEquals(null, config1.getFakeStringNoDefaultWithInferEmpty()); + + // Case 2: FAKE_STRING_CONFIG is set. FAKE_INTEGER_CONFIG, + // FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER, and + // FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY are inferred + HoodieTestFakeConfig config2 = HoodieTestFakeConfig.newBuilder() + .withFakeString("value1").build(); + assertEquals("value1", config2.getFakeString()); + assertEquals(0, config2.getFakeInteger()); + assertEquals("value2", config2.getFakeStringNoDefaultWithInfer()); + assertEquals("value10", config2.getFakeStringNoDefaultWithInferEmpty()); + + // Case 3: FAKE_STRING_CONFIG is set to a different value. FAKE_INTEGER_CONFIG, + // FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER, and + // FAKE_STRING_CONFIG_NO_DEFAULT_WITH_INFER_EMPTY are inferred + HoodieTestFakeConfig config3 = HoodieTestFakeConfig.newBuilder() + .withFakeString("5").build(); + assertEquals("5", config3.getFakeString()); + assertEquals(100, config3.getFakeInteger()); + assertEquals("value3", config3.getFakeStringNoDefaultWithInfer()); + assertEquals(null, config3.getFakeStringNoDefaultWithInferEmpty()); + + // Case 4: all configs are set. No default or infer function should be used + HoodieTestFakeConfig config4 = HoodieTestFakeConfig.newBuilder() + .withFakeString("5") + .withFakeInteger(200) + .withFakeStringNoDefaultWithInfer("xyz") + .withFakeStringNoDefaultWithInferEmpty("uvw").build(); + assertEquals("5", config4.getFakeString()); + assertEquals(200, config4.getFakeInteger()); + assertEquals("xyz", config4.getFakeStringNoDefaultWithInfer()); + assertEquals("uvw", config4.getFakeStringNoDefaultWithInferEmpty()); + } +}