use super::{Directory, fixture}; use dever::compiler::{build, project::Project}; #[test] fn executes_specialized_handlers_with_typed_failures_and_value_copies() { let directory = Directory::new(); let project = Project::load(&fixture().with_file_name("handler.dever")).unwrap(); let program = project.check().unwrap(); assert!( build::build( &program, &project.sources, "runOnce", &directory.0.join("invalid") ) .is_err() ); for (entry, expected) in [ ("verify", None), ( "failureEntry", Some(("Problem.Denied", "Problem.Denied(value)")), ), ( "argumentEntry", Some(("Problem.Denied", "Problem.Denied(value)")), ), ( "collectionEntry", Some(("Problem.Denied", "Problem.Denied(value)")), ), ( "faultEntry", Some(("integer arithmetic fault", "value + 1")), ), ] { let binary = build::build(&program, &project.sources, entry, &directory.0.join(entry)).unwrap(); let output = std::process::Command::new(binary).output().unwrap(); if let Some((message, needle)) = expected { assert!(!output.status.success()); assert!(output.stdout.is_empty()); let stderr = String::from_utf8(output.stderr).unwrap(); let source = &project.sources[0]; let (line, column) = source.position(source.text.find(needle).unwrap()); assert!(stderr.contains(message), "{stderr}"); assert!( stderr.contains(&format!("handler.dever:{line}:{column}:")), "{stderr}" ); } else { assert!( output.status.success(), "{}", String::from_utf8_lossy(&output.stderr) ); assert_eq!(output.stdout, b"true\n"); } } } #[test] fn handler_signatures_are_checked_before_specialization() { let directory = Directory::new(); let path = directory.0.join("handler.dever"); let source = std::fs::read_to_string(fixture().with_file_name("handler.dever")).unwrap(); let changed = source.replacen( "route: handler(value: Int) (answer: Int)", "route: handler(value: Text) (answer: Int)", 1, ); std::fs::write(&path, changed).unwrap(); assert!( Project::load(&path) .unwrap() .check() .unwrap_err() .contains("C005") ); } #[test] fn shared_error_sets_preserve_nominal_identity_and_original_locations() { let directory = Directory::new(); let project = Project::load(&fixture().with_file_name("failure_identity.dever")).unwrap(); let program = project.check().unwrap(); for (entry, failure) in [ ("verify", None), ( "forwardFirst", Some(("FirstProblem.Failed", "FirstProblem.Failed(\"first\")")), ), ( "forwardSecond", Some(("SecondProblem.Failed", "SecondProblem.Failed(\"second\")")), ), ] { let binary = build::build(&program, &project.sources, entry, &directory.0.join(entry)).unwrap(); let output = std::process::Command::new(binary).output().unwrap(); if let Some((message, needle)) = failure { assert!(!output.status.success()); assert!(output.stdout.is_empty()); let error = String::from_utf8(output.stderr).unwrap(); let source = &project.sources[0]; let (line, column) = source.position(source.text.find(needle).unwrap()); assert!(error.contains(message), "{error}"); assert!( error.contains(&format!("failure_identity.dever:{line}:{column}:")), "{error}" ); } else { assert!( output.status.success(), "{}", String::from_utf8_lossy(&output.stderr) ); assert_eq!(output.stdout, b"true\n"); } } }