Skip to content

Commit

Permalink
Add function in expression
Browse files Browse the repository at this point in the history
  • Loading branch information
fabricereix committed Nov 20, 2024
1 parent 5df1431 commit 8ea4b88
Show file tree
Hide file tree
Showing 26 changed files with 296 additions and 136 deletions.
14 changes: 7 additions & 7 deletions integration/hurl/tests_failed/options_template.err
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:8:13
|
| GET http://localhost:8000/unused
Expand All @@ -7,7 +7,7 @@ error: Invalid variable type
| ^^^^^^^^ expecting boolean, actual value is integer <10>
|

error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:15:15
|
| GET http://localhost:8000/unused
Expand All @@ -16,7 +16,7 @@ error: Invalid variable type
| ^^^^^^^^^^^^ expecting integer >= -1, actual value is integer <-123>
|

error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:22:15
|
| GET http://localhost:8000/unused
Expand All @@ -25,7 +25,7 @@ error: Invalid variable type
| ^^^^^^^^^^^^ expecting integer, actual value is string <abc>
|

error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:29:11
|
| GET http://localhost:8000/unused
Expand All @@ -34,7 +34,7 @@ error: Invalid variable type
| ^^^^^ expecting integer >= -1, actual value is integer <-2>
|

error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:36:11
|
| GET http://localhost:8000/unused
Expand All @@ -43,7 +43,7 @@ error: Invalid variable type
| ^^^^^ expecting integer, actual value is string <foo>
|

error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:43:10
|
| GET http://localhost:8000/unused
Expand All @@ -52,7 +52,7 @@ error: Invalid variable type
| ^^^^^ expecting integer >= -1, actual value is integer <-2>
|

error: Invalid variable type
error: Invalid expression type
--> tests_failed/options_template.hurl:50:10
|
| GET http://localhost:8000/unused
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@
 | ^^^^ the XPath expression is not valid
 |

error: Invalid variable type
error: Invalid expression type
--> tests_failed/runner_errors.hurl:142:12
 |
 | GET http://localhost:8000/runner_errors
Expand Down
31 changes: 14 additions & 17 deletions packages/hurl/src/runner/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ pub enum RunnerErrorKind {
AssertVersion {
actual: String,
},
ExpressionInvalidType {
value: String,
expecting: String,
},
/// I/O read error on `path`.
FileReadAccess {
path: PathBuf,
Expand Down Expand Up @@ -104,11 +108,7 @@ pub enum RunnerErrorKind {
TemplateVariableNotDefined {
name: String,
},
TemplateVariableInvalidType {
name: String,
value: String,
expecting: String,
},

UnrenderableVariable {
name: String,
value: String,
Expand All @@ -133,7 +133,7 @@ impl DisplaySourceError for RunnerError {
RunnerErrorKind::AssertHeaderValueError { .. } => "Assert header value".to_string(),
RunnerErrorKind::AssertStatus { .. } => "Assert status code".to_string(),
RunnerErrorKind::AssertVersion { .. } => "Assert HTTP version".to_string(),

RunnerErrorKind::ExpressionInvalidType { .. } => "Invalid expression type".to_string(),
RunnerErrorKind::FileReadAccess { .. } => "File read access".to_string(),
RunnerErrorKind::FileWriteAccess { .. } => "File write access".to_string(),
RunnerErrorKind::FilterDecode { .. } => "Filter error".to_string(),
Expand All @@ -152,9 +152,7 @@ impl DisplaySourceError for RunnerError {
}
RunnerErrorKind::QueryInvalidXml => "Invalid XML".to_string(),
RunnerErrorKind::QueryInvalidXpathEval => "Invalid XPath expression".to_string(),
RunnerErrorKind::TemplateVariableInvalidType { .. } => {
"Invalid variable type".to_string()
}

RunnerErrorKind::TemplateVariableNotDefined { .. } => "Undefined variable".to_string(),
RunnerErrorKind::UnauthorizedFileAccess { .. } => {
"Unauthorized file access".to_string()
Expand Down Expand Up @@ -208,7 +206,13 @@ impl DisplaySourceError for RunnerError {
let message = error::add_carets(message, self.source_info, content);
color_red_multiline_string(&message)
}

RunnerErrorKind::ExpressionInvalidType {
value, expecting, ..
} => {
let message = &format!("expecting {expecting}, actual value is {value}");
let message = error::add_carets(message, self.source_info, content);
color_red_multiline_string(&message)
}
RunnerErrorKind::FileReadAccess { path } => {
let message = &format!("file {} can not be read", path.to_string_lossy());
let message = error::add_carets(message, self.source_info, content);
Expand Down Expand Up @@ -289,13 +293,6 @@ impl DisplaySourceError for RunnerError {
let message = error::add_carets(message, self.source_info, content);
color_red_multiline_string(&message)
}
RunnerErrorKind::TemplateVariableInvalidType {
value, expecting, ..
} => {
let message = &format!("expecting {expecting}, actual value is {value}");
let message = error::add_carets(message, self.source_info, content);
color_red_multiline_string(&message)
}
RunnerErrorKind::TemplateVariableNotDefined { name } => {
let message = &format!("you must set the variable {name}");
let message = error::add_carets(message, self.source_info, content);
Expand Down
55 changes: 33 additions & 22 deletions packages/hurl/src/runner/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,45 +15,55 @@
* limitations under the License.
*
*/
use hurl_core::ast::Expr;
use hurl_core::ast::{Expr, ExprKind};

use crate::runner::error::{RunnerError, RunnerErrorKind};
use crate::runner::value::Value;
use crate::runner::VariableSet;

/// Evaluates the expression `expr` with `variables` map, returns a [`Value`] on success or an [`RunnerError`] .
pub fn eval(expr: &Expr, variables: &VariableSet) -> Result<Value, RunnerError> {
if let Some(value) = variables.get(expr.variable.name.as_str()) {
Ok(value.clone())
} else {
let kind = RunnerErrorKind::TemplateVariableNotDefined {
name: expr.variable.name.clone(),
};
Err(RunnerError::new(expr.variable.source_info, kind, false))
match &expr.kind {
ExprKind::Variable(variable) => {
if let Some(value) = variables.get(variable.name.as_str()) {
Ok(value.clone())
} else {
let kind = RunnerErrorKind::TemplateVariableNotDefined {
name: variable.name.clone(),
};
Err(RunnerError::new(variable.source_info, kind, false))
}
}
ExprKind::Function(_function) => todo!(),
}
}

/// Render the expression `expr` with `variables` map, returns a [`String`] on success or an [`RunnerError`] .
pub fn render(expr: &Expr, variables: &VariableSet) -> Result<String, RunnerError> {
let source_info = expr.variable.source_info;
let name = &expr.variable.name;
let value = eval(expr, variables)?;
if value.is_renderable() {
Ok(value.to_string())
} else {
let kind = RunnerErrorKind::UnrenderableVariable {
name: name.to_string(),
value: value.to_string(),
};
Err(RunnerError::new(source_info, kind, false))
match &expr.kind {
ExprKind::Variable(variable) => {
let source_info = variable.source_info;
let name = &variable.name;
let value = eval(expr, variables)?;
if value.is_renderable() {
Ok(value.to_string())
} else {
let kind = RunnerErrorKind::UnrenderableVariable {
name: name.to_string(),
value: value.to_string(),
};
Err(RunnerError::new(source_info, kind, false))
}
}
ExprKind::Function(_) => todo!(),
}
}

#[cfg(test)]
mod tests {
use super::*;
use hurl_core::{
ast::{SourceInfo, Variable},
ast::{ExprKind, SourceInfo, Variable},
reader::Pos,
};

Expand All @@ -62,10 +72,11 @@ mod tests {
let mut variables = VariableSet::new();
variables.insert("status".to_string(), Value::Bool(true));
let expr = Expr {
variable: Variable {
kind: ExprKind::Variable(Variable {
name: "status".to_string(),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
},
}),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
};
assert_eq!(eval(&expr, &variables).unwrap(), Value::Bool(true));
assert_eq!(render(&expr, &variables).unwrap(), "true");
Expand Down
12 changes: 7 additions & 5 deletions packages/hurl/src/runner/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub fn eval_json_value(
return Ok(s);
}
let kind = RunnerErrorKind::InvalidJson { value: s };
Err(RunnerError::new(expr.variable.source_info, kind, false))
Err(RunnerError::new(expr.source_info, kind, false))
}
}
}
Expand Down Expand Up @@ -198,10 +198,11 @@ mod tests {
source_info: SourceInfo::new(Pos::new(1, 15), Pos::new(1, 15)),
},
expr: Expr {
variable: Variable {
kind: ExprKind::Variable(Variable {
name: "name".to_string(),
source_info: SourceInfo::new(Pos::new(1, 15), Pos::new(1, 19)),
},
}),
source_info: SourceInfo::new(Pos::new(1, 15), Pos::new(1, 19)),
},
space1: Whitespace {
value: String::new(),
Expand Down Expand Up @@ -442,10 +443,11 @@ mod tests {
TemplateElement::Placeholder(Placeholder {
space0: whitespace(),
expr: Expr {
variable: Variable {
kind: ExprKind::Variable(Variable {
name: "quote".to_string(),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
},
}),
source_info: SourceInfo::new(Pos::new(0, 0), Pos::new(0, 0)),
},
space1: whitespace(),
}),
Expand Down
Loading

0 comments on commit 8ea4b88

Please sign in to comment.