@@ -11,6 +11,7 @@ pub type MetaBuiltinStmt = fn(&mut Environment<Expression>) -> Statement;
1111// Tabela estática global de metabuiltins
1212static METABUILTINS_TABLE : OnceLock < HashMap < String , MetaBuiltinStmt > > = OnceLock :: new ( ) ;
1313
14+
1415pub fn get_metabuiltins_table ( ) -> & ' static HashMap < String , MetaBuiltinStmt > {
1516 METABUILTINS_TABLE . get_or_init ( || {
1617 let mut table = HashMap :: new ( ) ;
@@ -247,4 +248,211 @@ mod tests {
247248
248249 fs:: remove_file ( test_file_path) . unwrap ( ) ;
249250 }
251+
252+ #[ test]
253+ fn test_open_builtin_write_mode_success ( ) {
254+ use std:: fs;
255+ let test_file_path = "test_write_file.txt" ;
256+ let test_content = "This is a test write." ;
257+
258+ let mut env: Environment < Expression > = Environment :: new ( ) ;
259+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( test_file_path. to_string ( ) ) ) ;
260+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "w" . to_string ( ) ) ) ;
261+ env. map_variable ( "content" . to_string ( ) , false , Expression :: CString ( test_content. to_string ( ) ) ) ;
262+
263+ let result = open_builtin ( & mut env) ;
264+
265+ match result {
266+ Statement :: Return ( expr) => {
267+ if let Expression :: CVoid = * expr {
268+ let content = fs:: read_to_string ( test_file_path) . unwrap ( ) ;
269+ assert_eq ! ( content, test_content, "File content should match" ) ;
270+ } else {
271+ panic ! ( "Expected CVoid after writing to file" ) ;
272+ }
273+ }
274+ _ => panic ! ( "Expected Statement::Return" ) ,
275+ }
276+
277+ fs:: remove_file ( test_file_path) . unwrap ( ) ;
278+ }
279+
280+ #[ test]
281+ fn test_open_builtin_append_mode_success ( ) {
282+ use std:: fs;
283+ let test_file_path = "test_append_file.txt" ;
284+ let initial_content = "Initial content.\n " ;
285+ let append_content = "This is appended content.\n " ;
286+ fs:: write ( test_file_path, initial_content) . unwrap ( ) ;
287+
288+ let mut env: Environment < Expression > = Environment :: new ( ) ;
289+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( test_file_path. to_string ( ) ) ) ;
290+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "a" . to_string ( ) ) ) ;
291+ env. map_variable ( "content" . to_string ( ) , false , Expression :: CString ( append_content. to_string ( ) ) ) ;
292+
293+ let result = open_builtin ( & mut env) ;
294+ match result {
295+ Statement :: Return ( expr) => {
296+ if let Expression :: CVoid = * expr {
297+ let content = fs:: read_to_string ( test_file_path) . unwrap ( ) ;
298+ assert ! ( content. contains( initial_content) , "File should contain initial content" ) ;
299+ assert ! ( content. contains( append_content) , "File should contain appended content" ) ;
300+ } else {
301+ panic ! ( "Expected CVoid after appending to file" ) ;
302+ }
303+ }
304+ _ => panic ! ( "Expected Statement::Return" ) ,
305+ }
306+ fs:: remove_file ( test_file_path) . unwrap ( ) ;
307+
308+ }
309+
310+ #[ test]
311+ fn test_open_builtin_unsupported_mode ( ) {
312+
313+ let mut env: Environment < Expression > = Environment :: new ( ) ;
314+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( "dummy.txt" . to_string ( ) ) ) ;
315+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "x" . to_string ( ) ) ) ; // Unsupported mode
316+
317+ let result = open_builtin ( & mut env) ;
318+
319+ match result {
320+ Statement :: Return ( expr) => {
321+ if let Expression :: CString ( msg) = * expr {
322+ assert_eq ! ( msg, "open: unsupported mode 'x'." , "Error message should match" ) ;
323+ } else {
324+ panic ! ( "Expected CString with error message" ) ;
325+ }
326+ }
327+ _ => panic ! ( "Expected Statement::Return" ) ,
328+ }
329+ }
330+
331+ #[ test]
332+ fn test_open_builtin_read_invalid_path ( ) {
333+ let mut env: Environment < Expression > = Environment :: new ( ) ;
334+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( "invalid_path.txt" . to_string ( ) ) ) ;
335+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "r" . to_string ( ) ) ) ;
336+
337+ let result = open_builtin ( & mut env) ;
338+
339+ match result {
340+ Statement :: Return ( expr) => {
341+ if let Expression :: CString ( msg) = * expr {
342+ assert ! ( msg. contains( "open: could not open 'invalid_path.txt' for reading" ) , "Error message should indicate invalid path" ) ;
343+ } else {
344+ panic ! ( "Expected CString with error message" ) ;
345+ }
346+ }
347+ _ => panic ! ( "Expected Statement::Return" ) ,
348+ }
349+
350+ }
351+
352+ #[ test]
353+ fn test_open_builtin_read_nonexistent_file ( ) {
354+ let mut env: Environment < Expression > = Environment :: new ( ) ;
355+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( "nonexistent.txt" . to_string ( ) ) ) ;
356+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "r" . to_string ( ) ) ) ;
357+
358+ let result = open_builtin ( & mut env) ;
359+
360+ match result {
361+ Statement :: Return ( expr) => {
362+ if let Expression :: CString ( msg) = * expr {
363+ assert ! ( msg. contains( "open: could not open 'nonexistent.txt' for reading" ) , "Error message should indicate file not found" ) ;
364+ } else {
365+ panic ! ( "Expected CString with error message" ) ;
366+ }
367+ }
368+ _ => panic ! ( "Expected Statement::Return" ) ,
369+ }
370+ }
371+
372+ #[ test]
373+ fn test_open_builtin_write_empty_content ( ) {
374+ use std:: fs;
375+ let test_file_path = "test_empty_write_file.txt" ;
376+
377+ let mut env: Environment < Expression > = Environment :: new ( ) ;
378+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( test_file_path. to_string ( ) ) ) ;
379+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "w" . to_string ( ) ) ) ;
380+ env. map_variable ( "content" . to_string ( ) , false , Expression :: CString ( "" . to_string ( ) ) ) ;
381+
382+ let result = open_builtin ( & mut env) ;
383+
384+ match result {
385+ Statement :: Return ( expr) => {
386+ if let Expression :: CVoid = * expr {
387+ let content = fs:: read_to_string ( test_file_path) . unwrap ( ) ;
388+ assert_eq ! ( content, "" , "File content should be empty" ) ;
389+ } else {
390+ panic ! ( "Expected CVoid after writing empty content to file" ) ;
391+ }
392+ }
393+ _ => panic ! ( "Expected Statement::Return" ) ,
394+ }
395+
396+ fs:: remove_file ( test_file_path) . unwrap ( ) ;
397+ }
398+
399+ #[ test]
400+ fn test_open_builtin_write_missing_content_argument ( ) {
401+ let mut env: Environment < Expression > = Environment :: new ( ) ;
402+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( "dummy.txt" . to_string ( ) ) ) ;
403+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "w" . to_string ( ) ) ) ;
404+
405+ let result = open_builtin ( & mut env) ;
406+
407+ match result {
408+ Statement :: Return ( expr) => {
409+ if let Expression :: CString ( msg) = * expr {
410+ assert_eq ! ( msg, "open: when using mode 'w', a third argument with the content to write is required" , "Error message should indicate missing content argument" ) ;
411+ } else {
412+ panic ! ( "Expected CString with error message" ) ;
413+ }
414+ }
415+ _ => panic ! ( "Expected Statement::Return" ) ,
416+ }
417+ }
418+
419+ #[ test]
420+ fn test_open_builtin_first_argument_not_string ( ) {
421+ let mut env: Environment < Expression > = Environment :: new ( ) ;
422+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CInt ( 42 ) ) ;
423+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "r" . to_string ( ) ) ) ;
424+
425+ let result = open_builtin ( & mut env) ;
426+
427+ match result {
428+ Statement :: Return ( expr) => {
429+ if let Expression :: CString ( msg) = * expr {
430+ assert_eq ! ( msg, "open: first argument must be a string with the file path" , "Error message should indicate invalid first argument" ) ;
431+ } else {
432+ panic ! ( "Expected CString with error message" ) ;
433+ }
434+ }
435+ _ => panic ! ( "Expected Statement::Return" ) ,
436+ }
437+ }
438+
439+ #[ test]
440+ fn test_open_builtin_append_missing_content_argument ( ) {
441+ let mut env: Environment < Expression > = Environment :: new ( ) ;
442+ env. map_variable ( "path" . to_string ( ) , false , Expression :: CString ( "dummy.txt" . to_string ( ) ) ) ;
443+ env. map_variable ( "mode" . to_string ( ) , false , Expression :: CString ( "a" . to_string ( ) ) ) ;
444+
445+ let result = open_builtin ( & mut env) ;
446+ match result {
447+ Statement :: Return ( expr) => {
448+ if let Expression :: CString ( msg) = * expr {
449+ assert_eq ! ( msg, "open: when using mode 'a', a third argument with the content to append is required" , "Error message should indicate missing content argument" ) ;
450+ } else {
451+ panic ! ( "Expected CString with error message" ) ;
452+ }
453+ }
454+ _ => panic ! ( "Expected Statement::Return" ) ,
455+ }
456+
457+ }
250458}
0 commit comments