Skip to content

Commit d8a12fa

Browse files
committed
[Common][Server] Adapt and add test cases
1 parent 70bda8f commit d8a12fa

File tree

3 files changed

+377
-24
lines changed

3 files changed

+377
-24
lines changed

fluss-common/src/main/java/com/alibaba/fluss/config/GlobalConfiguration.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.alibaba.fluss.config;
1818

1919
import com.alibaba.fluss.annotation.Internal;
20-
import com.alibaba.fluss.annotation.VisibleForTesting;
2120
import com.alibaba.fluss.exception.IllegalConfigurationException;
2221

2322
import org.slf4j.Logger;
@@ -50,8 +49,8 @@ public class GlobalConfiguration {
5049

5150
private static final Logger LOG = LoggerFactory.getLogger(GlobalConfiguration.class);
5251

53-
@VisibleForTesting
54-
public static final String[] FLUSS_CONF_FILENAME = new String[] {"server.yaml", "common.yaml"};
52+
private static final String[] FLUSS_CONF_FILENAMES =
53+
new String[] {"server.yaml", "common.yaml"};
5554

5655
// --------------------------------------------------------------------------------------------
5756

@@ -136,28 +135,28 @@ public static Configuration loadConfiguration(
136135
}
137136

138137
// get Fluss yaml configuration files from dir
139-
final File serverYamlFile = new File(confDirFile, FLUSS_CONF_FILENAME[0]);
140-
final File commonYamlFile = new File(confDirFile, FLUSS_CONF_FILENAME[1]);
138+
final File serverYamlFile = new File(confDirFile, FLUSS_CONF_FILENAMES[0]);
139+
final File commonYamlFile = new File(confDirFile, FLUSS_CONF_FILENAMES[1]);
141140

142141
// 1. check if old and new configuration files are mixed which is not supported
143142
if (serverYamlFile.exists() && commonYamlFile.exists()) {
144143
throw new IllegalConfigurationException(
145144
"Only one of "
146-
+ FLUSS_CONF_FILENAME[0]
145+
+ FLUSS_CONF_FILENAMES[0]
147146
+ " and "
148-
+ FLUSS_CONF_FILENAME[1]
147+
+ FLUSS_CONF_FILENAMES[1]
149148
+ " may be specified.");
150149
}
151150

152151
// 2. backward compatability, use server.yaml
153152
if (serverYamlFile.exists()) {
154-
yamlConfigFiles.add(new File(confDirFile, FLUSS_CONF_FILENAME[0]));
153+
yamlConfigFiles.add(new File(confDirFile, FLUSS_CONF_FILENAMES[0]));
155154
}
156155

157156
// 3. latest configuration setup: load common.yaml and additionally specified, dedicated
158157
// configuration files
159158
if (commonYamlFile.exists()) {
160-
yamlConfigFiles.add(new File(confDirFile, FLUSS_CONF_FILENAME[1]));
159+
yamlConfigFiles.add(new File(confDirFile, FLUSS_CONF_FILENAMES[1]));
161160

162161
for (String additionalDefaultFile : additionalDefaultFiles) {
163162
yamlConfigFiles.add(new File(confDirFile, additionalDefaultFile));
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright (c) 2025 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.alibaba.fluss.config;
18+
19+
import com.alibaba.fluss.exception.IllegalConfigurationException;
20+
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.io.TempDir;
23+
24+
import java.nio.file.Files;
25+
import java.nio.file.Path;
26+
import java.util.ArrayList;
27+
import java.util.Arrays;
28+
import java.util.Collections;
29+
import java.util.List;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
33+
34+
/** Tests for {@link com.alibaba.fluss.config.GlobalConfiguration}. */
35+
public class GlobalConfigurationTest {
36+
37+
private static final String OLD_COMMON_CONFIG_FILE_NAME = "server.yaml";
38+
private static final String NEW_COMMON_CONFIG_FILE_NAME = "common.yaml";
39+
40+
@Test
41+
void testLoadConfigurationWithoutAdditionalFiles(@TempDir Path tempFolder) throws Exception {
42+
String confDir = tempFolder.toAbsolutePath().toString();
43+
44+
// backward compatability for old common configuration file
45+
Path serverYaml = tempFolder.resolve(OLD_COMMON_CONFIG_FILE_NAME);
46+
Files.write(serverYaml, Collections.singleton("coordinator.host: localhost"));
47+
48+
Configuration configuration = GlobalConfiguration.loadConfiguration(confDir, null);
49+
assertThat(configuration.get(ConfigOptions.COORDINATOR_HOST)).isEqualTo("localhost");
50+
51+
// backward compatability for old common configuration file + precedence for dynamic
52+
// properties
53+
Configuration dynamicConfig = new Configuration();
54+
dynamicConfig.set(ConfigOptions.COORDINATOR_HOST, "example.com");
55+
configuration = GlobalConfiguration.loadConfiguration(confDir, dynamicConfig);
56+
assertThat(configuration.get(ConfigOptions.COORDINATOR_HOST)).isEqualTo("example.com");
57+
58+
// old and new common configuration file should not be present at the same time
59+
Path commonYaml = tempFolder.resolve(NEW_COMMON_CONFIG_FILE_NAME);
60+
Files.write(commonYaml, Collections.singleton("bind.listeners: FLUSS://localhost:9124"));
61+
assertThatThrownBy(() -> GlobalConfiguration.loadConfiguration(confDir, null))
62+
.isInstanceOf(IllegalConfigurationException.class)
63+
.hasMessageContaining("Only one of");
64+
65+
// new common configuration file
66+
Files.delete(serverYaml);
67+
configuration = GlobalConfiguration.loadConfiguration(confDir, null);
68+
assertThat(configuration.get(ConfigOptions.BIND_LISTENERS))
69+
.isEqualTo("FLUSS://localhost:9124");
70+
assertThat(configuration.get(ConfigOptions.COORDINATOR_HOST)).isEqualTo(null);
71+
72+
// new common configuration file + precedence for dynamic properties
73+
dynamicConfig = new Configuration();
74+
dynamicConfig.set(ConfigOptions.BIND_LISTENERS, "FLUSS://example.com:9124");
75+
configuration = GlobalConfiguration.loadConfiguration(confDir, dynamicConfig);
76+
assertThat(configuration.get(ConfigOptions.BIND_LISTENERS))
77+
.isEqualTo("FLUSS://example.com:9124");
78+
assertThat(configuration.get(ConfigOptions.COORDINATOR_HOST)).isEqualTo(null);
79+
}
80+
81+
@Test
82+
void testLoadConfigurationWithAdditionalFileSimple(@TempDir Path tempFolder) throws Exception {
83+
String confDir = tempFolder.toAbsolutePath().toString();
84+
85+
// additional file should be read when old config is present
86+
Path serverYaml = tempFolder.resolve(OLD_COMMON_CONFIG_FILE_NAME);
87+
Files.write(
88+
serverYaml,
89+
Arrays.asList(
90+
"remote.data.dir: /tmp/fluss-remote-data",
91+
"bind.listeners: FLUSS://localhost:9124"));
92+
Path additionalYaml = tempFolder.resolve("additional-file.yaml");
93+
Files.write(
94+
additionalYaml,
95+
Arrays.asList(
96+
"bind.listeners: FLUSS://example.com:9124",
97+
"default.replication.factor: 5"));
98+
Configuration configuration =
99+
GlobalConfiguration.loadConfiguration(
100+
confDir, Collections.singletonList("additional-file.yaml"), null);
101+
102+
assertThat(configuration.get(ConfigOptions.REMOTE_DATA_DIR))
103+
.isEqualTo("/tmp/fluss-remote-data");
104+
assertThat(configuration.get(ConfigOptions.BIND_LISTENERS))
105+
.isEqualTo("FLUSS://localhost:9124");
106+
assertThat(configuration.get(ConfigOptions.DEFAULT_REPLICATION_FACTOR))
107+
.isEqualTo(ConfigOptions.DEFAULT_REPLICATION_FACTOR.defaultValue());
108+
109+
Files.delete(serverYaml);
110+
111+
// additional file should be read when new config is present
112+
Path commonYaml = tempFolder.resolve(NEW_COMMON_CONFIG_FILE_NAME);
113+
Files.write(
114+
commonYaml,
115+
Arrays.asList(
116+
"remote.data.dir: /tmp/fluss-remote-data",
117+
"bind.listeners: FLUSS://localhost:9124"));
118+
119+
configuration =
120+
GlobalConfiguration.loadConfiguration(
121+
confDir, Collections.singletonList("additional-file.yaml"), null);
122+
123+
assertThat(configuration.get(ConfigOptions.REMOTE_DATA_DIR))
124+
.isEqualTo("/tmp/fluss-remote-data");
125+
assertThat(configuration.get(ConfigOptions.BIND_LISTENERS))
126+
.isEqualTo("FLUSS://example.com:9124");
127+
assertThat(configuration.get(ConfigOptions.DEFAULT_REPLICATION_FACTOR)).isEqualTo(5);
128+
}
129+
130+
@Test
131+
void testLoadConfigurationWithAdditionalFilesRespectsPrecedence(@TempDir Path tempFolder)
132+
throws Exception {
133+
String confDir = tempFolder.toAbsolutePath().toString();
134+
135+
ConfigOption<Integer> keyWillNotBeOverwritten =
136+
ConfigBuilder.key("willNotBeOverwritten").intType().noDefaultValue();
137+
ConfigOption<Integer> keyWillBeOverwrittenByFirstAdditionalFile =
138+
ConfigBuilder.key("willBeOverwrittenByFirstAdditionalFile")
139+
.intType()
140+
.noDefaultValue();
141+
ConfigOption<Integer> keyWillBeOverwrittenBySecondAdditionalFile =
142+
ConfigBuilder.key("willBeOverwrittenBySecondAdditionalFile")
143+
.intType()
144+
.noDefaultValue();
145+
ConfigOption<Integer> keyWillBeOverwrittenByDynamicProperty =
146+
ConfigBuilder.key("willBeOverwrittenByDynamicProperty").intType().noDefaultValue();
147+
148+
Path commonYaml = tempFolder.resolve(NEW_COMMON_CONFIG_FILE_NAME);
149+
Files.write(
150+
commonYaml,
151+
Arrays.asList(
152+
"willNotBeOverwritten: 0",
153+
"willBeOverwrittenByFirstAdditionalFile: 1",
154+
"willBeOverwrittenBySecondAdditionalFile: 2"));
155+
156+
// only common, no additional file
157+
Configuration configuration =
158+
GlobalConfiguration.loadConfiguration(confDir, Collections.emptyList(), null);
159+
assertThat(configuration.get(keyWillNotBeOverwritten)).isEqualTo(0);
160+
assertThat(configuration.get(keyWillBeOverwrittenByFirstAdditionalFile)).isEqualTo(1);
161+
assertThat(configuration.get(keyWillBeOverwrittenBySecondAdditionalFile)).isEqualTo(2);
162+
163+
// first additional file
164+
Path firstAdditionalYaml = tempFolder.resolve("first-additional.yaml");
165+
Files.write(
166+
firstAdditionalYaml,
167+
Arrays.asList(
168+
"willBeOverwrittenByFirstAdditionalFile: 11",
169+
"willBeOverwrittenByDynamicProperty: 12"));
170+
List<String> additionalFiles = new ArrayList<>(2);
171+
additionalFiles.add("first-additional.yaml");
172+
configuration = GlobalConfiguration.loadConfiguration(confDir, additionalFiles, null);
173+
assertThat(configuration.get(keyWillNotBeOverwritten)).isEqualTo(0);
174+
assertThat(configuration.get(keyWillBeOverwrittenByFirstAdditionalFile)).isEqualTo(11);
175+
assertThat(configuration.get(keyWillBeOverwrittenBySecondAdditionalFile)).isEqualTo(2);
176+
assertThat(configuration.get(keyWillBeOverwrittenByDynamicProperty)).isEqualTo(12);
177+
178+
// second additional file
179+
Path secondAdditionalYaml = tempFolder.resolve("second-additional.yaml");
180+
Files.write(
181+
secondAdditionalYaml,
182+
Collections.singleton("willBeOverwrittenBySecondAdditionalFile: 20"));
183+
additionalFiles.add("second-additional.yaml");
184+
configuration = GlobalConfiguration.loadConfiguration(confDir, additionalFiles, null);
185+
assertThat(configuration.get(keyWillNotBeOverwritten)).isEqualTo(0);
186+
assertThat(configuration.get(keyWillBeOverwrittenByFirstAdditionalFile)).isEqualTo(11);
187+
assertThat(configuration.get(keyWillBeOverwrittenBySecondAdditionalFile)).isEqualTo(20);
188+
assertThat(configuration.get(keyWillBeOverwrittenByDynamicProperty)).isEqualTo(12);
189+
190+
// dynamic property
191+
Configuration dynamicProperties = new Configuration();
192+
dynamicProperties.set(keyWillBeOverwrittenByDynamicProperty, 32);
193+
configuration =
194+
GlobalConfiguration.loadConfiguration(confDir, additionalFiles, dynamicProperties);
195+
assertThat(configuration.get(keyWillNotBeOverwritten)).isEqualTo(0);
196+
assertThat(configuration.get(keyWillBeOverwrittenByFirstAdditionalFile)).isEqualTo(11);
197+
assertThat(configuration.get(keyWillBeOverwrittenBySecondAdditionalFile)).isEqualTo(20);
198+
assertThat(configuration.get(keyWillBeOverwrittenByDynamicProperty)).isEqualTo(32);
199+
}
200+
}

0 commit comments

Comments
 (0)