1717
1818package org .apache .fluss .config ;
1919
20+ import org .apache .fluss .exception .IllegalConfigurationException ;
21+
2022import org .junit .jupiter .api .Test ;
2123
24+ import java .util .Arrays ;
25+ import java .util .Collections ;
2226import java .util .Map ;
2327
2428import static org .apache .fluss .config .FlussConfigUtils .CLIENT_OPTIONS ;
2529import static org .apache .fluss .config .FlussConfigUtils .TABLE_OPTIONS ;
2630import static org .apache .fluss .config .FlussConfigUtils .extractConfigOptions ;
31+ import static org .apache .fluss .config .FlussConfigUtils .validateCoordinatorConfigs ;
32+ import static org .apache .fluss .config .FlussConfigUtils .validateTabletConfigs ;
2733import static org .assertj .core .api .Assertions .assertThat ;
34+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2835
2936/** Test for {@link FlussConfigUtils}. */
3037class FlussConfigUtilsTest {
@@ -49,4 +56,123 @@ void testExtractOptions() {
4956 });
5057 assertThat (clientOptions .size ()).isEqualTo (CLIENT_OPTIONS .size ());
5158 }
59+
60+ @ Test
61+ void testValidateCoordinatorConfigs () {
62+ // Test empty configuration
63+ Configuration emptyConf = new Configuration ();
64+ assertThatThrownBy (() -> validateCoordinatorConfigs (emptyConf ))
65+ .isInstanceOf (IllegalConfigurationException .class )
66+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIR .key ())
67+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIRS .key ())
68+ .hasMessageContaining ("must be configured" );
69+
70+ // Test configuration with only REMOTE_DATA_DIR set
71+ Configuration remoteDataDirConf = new Configuration ();
72+ remoteDataDirConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
73+ validateCoordinatorConfigs (remoteDataDirConf );
74+
75+ // Test invalid REMOTE_DATA_DIR
76+ Configuration invalidRemoteDirConf = new Configuration ();
77+ invalidRemoteDirConf .set (ConfigOptions .REMOTE_DATA_DIR , "123://invalid.com" );
78+ assertThatThrownBy (() -> validateCoordinatorConfigs (invalidRemoteDirConf ))
79+ .isInstanceOf (IllegalConfigurationException .class )
80+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIR .key ())
81+ .hasMessageContaining ("Invalid configuration for remote.data.dir" );
82+
83+ // Test configuration with only REMOTE_DATA_DIRS set
84+ Configuration remoteDataDirsConf = new Configuration ();
85+ remoteDataDirsConf .set (
86+ ConfigOptions .REMOTE_DATA_DIRS , Arrays .asList ("s3://bucket1" , "s3://bucket2" ));
87+ validateCoordinatorConfigs (remoteDataDirConf );
88+
89+ // Test REMOTE_DATA_DIRS contains invalid path
90+ Configuration invalidRemoteDirsConf = new Configuration ();
91+ invalidRemoteDirsConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
92+ invalidRemoteDirsConf .set (
93+ ConfigOptions .REMOTE_DATA_DIRS , Arrays .asList ("s3://bucket1" , "123://invalid.com" ));
94+ assertThatThrownBy (() -> validateCoordinatorConfigs (invalidRemoteDirsConf ))
95+ .isInstanceOf (IllegalConfigurationException .class )
96+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIRS .key ())
97+ .hasMessageContaining ("Invalid remote path for" );
98+
99+ // Test WEIGHTED_ROUND_ROBIN with mismatched sizes
100+ Configuration mismatchedWeightsConf = new Configuration ();
101+ mismatchedWeightsConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
102+ mismatchedWeightsConf .set (
103+ ConfigOptions .REMOTE_DATA_DIRS_STRATEGY ,
104+ ConfigOptions .RemoteDataDirStrategy .WEIGHTED_ROUND_ROBIN );
105+ mismatchedWeightsConf .set (
106+ ConfigOptions .REMOTE_DATA_DIRS , Arrays .asList ("s3://bucket1" , "s3://bucket2" ));
107+ mismatchedWeightsConf .set (
108+ ConfigOptions .REMOTE_DATA_DIRS_WEIGHTS , Collections .singletonList (1 ));
109+ assertThatThrownBy (() -> validateCoordinatorConfigs (mismatchedWeightsConf ))
110+ .isInstanceOf (IllegalConfigurationException .class )
111+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIRS_WEIGHTS .key ())
112+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIRS .key ());
113+
114+ // Test WEIGHTED_ROUND_ROBIN with matched sizes
115+ Configuration matchedWeightsConf = new Configuration ();
116+ matchedWeightsConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
117+ matchedWeightsConf .set (
118+ ConfigOptions .REMOTE_DATA_DIRS_STRATEGY ,
119+ ConfigOptions .RemoteDataDirStrategy .WEIGHTED_ROUND_ROBIN );
120+ matchedWeightsConf .set (
121+ ConfigOptions .REMOTE_DATA_DIRS , Arrays .asList ("s3://bucket1" , "s3://bucket2" ));
122+ matchedWeightsConf .set (ConfigOptions .REMOTE_DATA_DIRS_WEIGHTS , Arrays .asList (0 , 2 ));
123+ validateCoordinatorConfigs (matchedWeightsConf );
124+
125+ // Test negative weight
126+ Configuration negativeWeightConf = new Configuration ();
127+ negativeWeightConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
128+ negativeWeightConf .set (
129+ ConfigOptions .REMOTE_DATA_DIRS_STRATEGY ,
130+ ConfigOptions .RemoteDataDirStrategy .WEIGHTED_ROUND_ROBIN );
131+ negativeWeightConf .set (
132+ ConfigOptions .REMOTE_DATA_DIRS , Arrays .asList ("s3://bucket1" , "s3://bucket2" ));
133+ negativeWeightConf .set (ConfigOptions .REMOTE_DATA_DIRS_WEIGHTS , Arrays .asList (-1 , 2 ));
134+ assertThatThrownBy (() -> validateCoordinatorConfigs (negativeWeightConf ))
135+ .isInstanceOf (IllegalConfigurationException .class )
136+ .hasMessageContaining (ConfigOptions .REMOTE_DATA_DIRS_WEIGHTS .key ())
137+ .hasMessageContaining (
138+ "All weights in 'remote.data.dirs.weights' must be no less than 0" );
139+
140+ // Test invalid DEFAULT_REPLICATION_FACTOR
141+ Configuration invalidReplicationConf = new Configuration ();
142+ invalidReplicationConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
143+ invalidReplicationConf .set (ConfigOptions .DEFAULT_REPLICATION_FACTOR , 0 );
144+ assertThatThrownBy (() -> validateCoordinatorConfigs (invalidReplicationConf ))
145+ .isInstanceOf (IllegalConfigurationException .class )
146+ .hasMessageContaining (ConfigOptions .DEFAULT_REPLICATION_FACTOR .key ())
147+ .hasMessageContaining ("must be greater than or equal 1" );
148+
149+ // Test invalid KV_MAX_RETAINED_SNAPSHOTS
150+ Configuration invalidSnapshotConf = new Configuration ();
151+ invalidSnapshotConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
152+ invalidSnapshotConf .set (ConfigOptions .KV_MAX_RETAINED_SNAPSHOTS , 0 );
153+ assertThatThrownBy (() -> validateCoordinatorConfigs (invalidSnapshotConf ))
154+ .isInstanceOf (IllegalConfigurationException .class )
155+ .hasMessageContaining (ConfigOptions .KV_MAX_RETAINED_SNAPSHOTS .key ())
156+ .hasMessageContaining ("must be greater than or equal 1" );
157+
158+ // Test invalid SERVER_IO_POOL_SIZE
159+ Configuration invalidIoPoolConf = new Configuration ();
160+ invalidIoPoolConf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
161+ invalidIoPoolConf .set (ConfigOptions .SERVER_IO_POOL_SIZE , 0 );
162+ assertThatThrownBy (() -> validateCoordinatorConfigs (invalidIoPoolConf ))
163+ .isInstanceOf (IllegalConfigurationException .class )
164+ .hasMessageContaining (ConfigOptions .SERVER_IO_POOL_SIZE .key ())
165+ .hasMessageContaining ("must be greater than or equal 1" );
166+ }
167+
168+ @ Test
169+ void testValidateTabletConfigs () {
170+ Configuration conf = new Configuration ();
171+ conf .set (ConfigOptions .REMOTE_DATA_DIR , "s3://bucket/path" );
172+ conf .set (ConfigOptions .TABLET_SERVER_ID , -1 );
173+ assertThatThrownBy (() -> validateTabletConfigs (conf ))
174+ .isInstanceOf (IllegalConfigurationException .class )
175+ .hasMessageContaining (ConfigOptions .TABLET_SERVER_ID .key ())
176+ .hasMessageContaining ("it must be greater than or equal 0" );
177+ }
52178}
0 commit comments