@@ -85,3 +85,225 @@ pub fn validate(project: &Project, plan: &InfraPlan) -> Result<(), ValidationErr
8585
8686 Ok ( ( ) )
8787}
88+
89+ #[ cfg( test) ]
90+ mod tests {
91+ use super :: * ;
92+ use crate :: framework:: core:: infrastructure:: table:: { Column , ColumnType , OrderBy , Table } ;
93+ use crate :: framework:: core:: infrastructure_map:: {
94+ InfrastructureMap , PrimitiveSignature , PrimitiveTypes ,
95+ } ;
96+ use crate :: framework:: core:: partial_infrastructure_map:: LifeCycle ;
97+ use crate :: framework:: core:: plan:: InfraPlan ;
98+ use crate :: framework:: versions:: Version ;
99+ use crate :: infrastructure:: olap:: clickhouse:: config:: { ClickHouseConfig , ClusterConfig } ;
100+ use crate :: project:: { Project , ProjectFeatures } ;
101+ use std:: collections:: HashMap ;
102+ use std:: path:: PathBuf ;
103+
104+ fn create_test_project ( clusters : Option < Vec < ClusterConfig > > ) -> Project {
105+ Project {
106+ language : crate :: framework:: languages:: SupportedLanguages :: Typescript ,
107+ redpanda_config : crate :: infrastructure:: stream:: kafka:: models:: KafkaConfig :: default ( ) ,
108+ clickhouse_config : ClickHouseConfig {
109+ db_name : "local" . to_string ( ) ,
110+ user : "default" . to_string ( ) ,
111+ password : "" . to_string ( ) ,
112+ use_ssl : false ,
113+ host : "localhost" . to_string ( ) ,
114+ host_port : 18123 ,
115+ native_port : 9000 ,
116+ host_data_path : None ,
117+ additional_databases : vec ! [ ] ,
118+ clusters,
119+ } ,
120+ http_server_config : crate :: cli:: local_webserver:: LocalWebserverConfig :: default ( ) ,
121+ redis_config : crate :: infrastructure:: redis:: redis_client:: RedisConfig :: default ( ) ,
122+ git_config : crate :: utilities:: git:: GitConfig :: default ( ) ,
123+ temporal_config :
124+ crate :: infrastructure:: orchestration:: temporal:: TemporalConfig :: default ( ) ,
125+ state_config : crate :: project:: StateConfig :: default ( ) ,
126+ migration_config : crate :: project:: MigrationConfig :: default ( ) ,
127+ language_project_config : crate :: project:: LanguageProjectConfig :: default ( ) ,
128+ project_location : PathBuf :: from ( "/test" ) ,
129+ is_production : false ,
130+ supported_old_versions : HashMap :: new ( ) ,
131+ jwt : None ,
132+ authentication : crate :: project:: AuthenticationConfig :: default ( ) ,
133+ features : ProjectFeatures :: default ( ) ,
134+ load_infra : None ,
135+ typescript_config : crate :: project:: TypescriptConfig :: default ( ) ,
136+ source_dir : crate :: project:: default_source_dir ( ) ,
137+ }
138+ }
139+
140+ fn create_test_table ( name : & str , cluster_name : Option < String > ) -> Table {
141+ Table {
142+ name : name. to_string ( ) ,
143+ columns : vec ! [ Column {
144+ name: "id" . to_string( ) ,
145+ data_type: ColumnType :: String ,
146+ required: true ,
147+ unique: false ,
148+ primary_key: true ,
149+ default : None ,
150+ annotations: vec![ ] ,
151+ comment: None ,
152+ ttl: None ,
153+ } ] ,
154+ order_by : OrderBy :: Fields ( vec ! [ "id" . to_string( ) ] ) ,
155+ partition_by : None ,
156+ sample_by : None ,
157+ engine : None ,
158+ version : Some ( Version :: from_string ( "1.0.0" . to_string ( ) ) ) ,
159+ source_primitive : PrimitiveSignature {
160+ name : name. to_string ( ) ,
161+ primitive_type : PrimitiveTypes :: DataModel ,
162+ } ,
163+ metadata : None ,
164+ life_cycle : LifeCycle :: FullyManaged ,
165+ engine_params_hash : None ,
166+ table_settings : None ,
167+ indexes : vec ! [ ] ,
168+ database : None ,
169+ table_ttl_setting : None ,
170+ cluster_name,
171+ }
172+ }
173+
174+ fn create_test_plan ( tables : Vec < Table > ) -> InfraPlan {
175+ let mut table_map = HashMap :: new ( ) ;
176+ for table in tables {
177+ table_map. insert ( format ! ( "local_{}" , table. name) , table) ;
178+ }
179+
180+ InfraPlan {
181+ target_infra_map : InfrastructureMap {
182+ default_database : "local" . to_string ( ) ,
183+ tables : table_map,
184+ topics : HashMap :: new ( ) ,
185+ api_endpoints : HashMap :: new ( ) ,
186+ views : HashMap :: new ( ) ,
187+ topic_to_table_sync_processes : HashMap :: new ( ) ,
188+ topic_to_topic_sync_processes : HashMap :: new ( ) ,
189+ function_processes : HashMap :: new ( ) ,
190+ block_db_processes : crate :: framework:: core:: infrastructure:: olap_process:: OlapProcess { } ,
191+ consumption_api_web_server : crate :: framework:: core:: infrastructure:: consumption_webserver:: ConsumptionApiWebServer { } ,
192+ orchestration_workers : HashMap :: new ( ) ,
193+ sql_resources : HashMap :: new ( ) ,
194+ workflows : HashMap :: new ( ) ,
195+ web_apps : HashMap :: new ( ) ,
196+ } ,
197+ changes : Default :: default ( ) ,
198+ }
199+ }
200+
201+ #[ test]
202+ fn test_validate_no_clusters_defined_but_table_references_one ( ) {
203+ let project = create_test_project ( None ) ;
204+ let table = create_test_table ( "test_table" , Some ( "test_cluster" . to_string ( ) ) ) ;
205+ let plan = create_test_plan ( vec ! [ table] ) ;
206+
207+ let result = validate ( & project, & plan) ;
208+
209+ assert ! ( result. is_err( ) ) ;
210+ match result {
211+ Err ( ValidationError :: ClusterValidation ( msg) ) => {
212+ assert ! ( msg. contains( "test_table" ) ) ;
213+ assert ! ( msg. contains( "test_cluster" ) ) ;
214+ assert ! ( msg. contains( "no clusters are defined" ) ) ;
215+ }
216+ _ => panic ! ( "Expected ClusterValidation error" ) ,
217+ }
218+ }
219+
220+ #[ test]
221+ fn test_validate_table_references_undefined_cluster ( ) {
222+ let project = create_test_project ( Some ( vec ! [
223+ ClusterConfig {
224+ name: "cluster_a" . to_string( ) ,
225+ } ,
226+ ClusterConfig {
227+ name: "cluster_b" . to_string( ) ,
228+ } ,
229+ ] ) ) ;
230+ let table = create_test_table ( "test_table" , Some ( "cluster_c" . to_string ( ) ) ) ;
231+ let plan = create_test_plan ( vec ! [ table] ) ;
232+
233+ let result = validate ( & project, & plan) ;
234+
235+ assert ! ( result. is_err( ) ) ;
236+ match result {
237+ Err ( ValidationError :: ClusterValidation ( msg) ) => {
238+ assert ! ( msg. contains( "test_table" ) ) ;
239+ assert ! ( msg. contains( "cluster_c" ) ) ;
240+ assert ! ( msg. contains( "cluster_a" ) ) ;
241+ assert ! ( msg. contains( "cluster_b" ) ) ;
242+ }
243+ _ => panic ! ( "Expected ClusterValidation error" ) ,
244+ }
245+ }
246+
247+ #[ test]
248+ fn test_validate_table_references_valid_cluster ( ) {
249+ let project = create_test_project ( Some ( vec ! [ ClusterConfig {
250+ name: "test_cluster" . to_string( ) ,
251+ } ] ) ) ;
252+ let table = create_test_table ( "test_table" , Some ( "test_cluster" . to_string ( ) ) ) ;
253+ let plan = create_test_plan ( vec ! [ table] ) ;
254+
255+ let result = validate ( & project, & plan) ;
256+
257+ assert ! ( result. is_ok( ) ) ;
258+ }
259+
260+ #[ test]
261+ fn test_validate_table_with_no_cluster_is_allowed ( ) {
262+ let project = create_test_project ( Some ( vec ! [ ClusterConfig {
263+ name: "test_cluster" . to_string( ) ,
264+ } ] ) ) ;
265+ let table = create_test_table ( "test_table" , None ) ;
266+ let plan = create_test_plan ( vec ! [ table] ) ;
267+
268+ let result = validate ( & project, & plan) ;
269+
270+ assert ! ( result. is_ok( ) ) ;
271+ }
272+
273+ #[ test]
274+ fn test_validate_multiple_tables_different_clusters ( ) {
275+ let project = create_test_project ( Some ( vec ! [
276+ ClusterConfig {
277+ name: "cluster_a" . to_string( ) ,
278+ } ,
279+ ClusterConfig {
280+ name: "cluster_b" . to_string( ) ,
281+ } ,
282+ ] ) ) ;
283+ let table1 = create_test_table ( "table1" , Some ( "cluster_a" . to_string ( ) ) ) ;
284+ let table2 = create_test_table ( "table2" , Some ( "cluster_b" . to_string ( ) ) ) ;
285+ let plan = create_test_plan ( vec ! [ table1, table2] ) ;
286+
287+ let result = validate ( & project, & plan) ;
288+
289+ assert ! ( result. is_ok( ) ) ;
290+ }
291+
292+ #[ test]
293+ fn test_validate_empty_clusters_list ( ) {
294+ let project = create_test_project ( Some ( vec ! [ ] ) ) ;
295+ let table = create_test_table ( "test_table" , Some ( "test_cluster" . to_string ( ) ) ) ;
296+ let plan = create_test_plan ( vec ! [ table] ) ;
297+
298+ let result = validate ( & project, & plan) ;
299+
300+ assert ! ( result. is_err( ) ) ;
301+ match result {
302+ Err ( ValidationError :: ClusterValidation ( msg) ) => {
303+ assert ! ( msg. contains( "test_table" ) ) ;
304+ assert ! ( msg. contains( "test_cluster" ) ) ;
305+ }
306+ _ => panic ! ( "Expected ClusterValidation error" ) ,
307+ }
308+ }
309+ }
0 commit comments