Skip to content

Commit fa65693

Browse files
committed
return None for invalid separators, emit warnings for invalid input, tests for invalid input
1 parent 4782359 commit fa65693

File tree

1 file changed

+61
-19
lines changed
  • apollo-federation/src/sources/connect/json_selection/methods/public

1 file changed

+61
-19
lines changed

apollo-federation/src/sources/connect/json_selection/methods/public/join.rs

+61-19
Original file line numberDiff line numberDiff line change
@@ -27,42 +27,65 @@ fn join_method(
2727
) -> (Option<JSON>, Vec<ApplyToError>) {
2828
let mut warnings = vec![];
2929

30-
static EMPTY_STRING: String = String::new();
31-
let separator = method_args
30+
let Some(separator) = method_args
3231
.and_then(|args| args.args.first())
3332
.and_then(|s| match &**s {
3433
LitExpr::String(s) => Some(s),
3534
_ => None,
3635
})
37-
.unwrap_or_else(|| {
38-
warnings.push(ApplyToError::new(
39-
format!(
40-
"Method ->{} requires a string argument",
41-
method_name.as_ref()
42-
),
43-
input_path.to_vec(),
44-
method_name.range(),
45-
));
46-
&EMPTY_STRING
47-
});
36+
else {
37+
warnings.push(ApplyToError::new(
38+
format!(
39+
"Method ->{} requires a string argument",
40+
method_name.as_ref()
41+
),
42+
input_path.to_vec(),
43+
method_name.range(),
44+
));
45+
return (None, warnings);
46+
};
4847

49-
fn to_string(value: &JSON) -> String {
48+
fn to_string(value: &JSON) -> (String, Option<String>) {
5049
match value {
51-
JSON::Bool(b) => b.then_some("true").unwrap_or("false").to_string(),
52-
JSON::Number(number) => number.to_string(),
53-
JSON::String(byte_string) => byte_string.as_str().to_string(),
54-
JSON::Null | JSON::Array(_) | JSON::Object(_) => "".to_string(),
50+
JSON::Bool(b) => (b.then_some("true").unwrap_or("false").to_string(), None),
51+
JSON::Number(number) => (number.to_string(), None),
52+
JSON::String(byte_string) => (byte_string.as_str().to_string(), None),
53+
JSON::Null => ("".to_string(), None),
54+
JSON::Array(_) | JSON::Object(_) => (
55+
"".to_string(),
56+
Some("Method ->join requires an array of scalars values as input".to_string()),
57+
),
5558
}
5659
}
5760

5861
let joined = match data {
5962
JSON::Array(values) => values
6063
.iter()
6164
.map(to_string)
65+
.map(|(value, err)| {
66+
if let Some(err) = err {
67+
warnings.push(ApplyToError::new(
68+
err.to_string(),
69+
input_path.to_vec(),
70+
method_name.range(),
71+
));
72+
}
73+
value
74+
})
6275
.collect::<Vec<_>>()
6376
.join(separator),
6477
// Single values are emitted as strings with no separator
65-
_ => to_string(data),
78+
_ => {
79+
let (value, err) = to_string(data);
80+
if let Some(err) = err {
81+
warnings.push(ApplyToError::new(
82+
err.to_string(),
83+
input_path.to_vec(),
84+
method_name.range(),
85+
));
86+
}
87+
value
88+
}
6689
};
6790

6891
(Some(JSON::String(joined.into())), warnings)
@@ -182,6 +205,25 @@ mod tests {
182205
);
183206
}
184207

208+
#[rstest::rstest]
209+
#[case(json!({"a": 1}), json!(""), vec!["Method ->join requires an array of scalars values as input"])]
210+
#[case(json!([{"a": 1}, {"a": 2}]), json!(","), vec!["Method ->join requires an array of scalars values as input"])]
211+
#[case(json!([[1, 2]]), json!(""), vec!["Method ->join requires an array of scalars values as input"])]
212+
fn join_warnings(
213+
#[case] input: JSON,
214+
#[case] expected: JSON,
215+
#[case] expected_warnings: Vec<&str>,
216+
) {
217+
use itertools::Itertools;
218+
219+
let (result, warnings) = selection!("$->join(',')").apply_to(&input);
220+
assert_eq!(result, Some(expected));
221+
assert_eq!(
222+
warnings.iter().map(|w| w.message()).collect_vec(),
223+
expected_warnings
224+
);
225+
}
226+
185227
fn get_shape(args: Vec<WithRange<LitExpr>>, input: Shape) -> Shape {
186228
join_method_shape(
187229
&WithRange::new("join".to_string(), Some(0..7)),

0 commit comments

Comments
 (0)