#![allow(clippy::approx_constant)]
mod test_helpers;
use test_helpers::TestDb;
#[test]
fn tolower_empty_string() {
assert_eq!(TestDb::new().scalar("RETURN string.lower('')"), "");
}
#[test]
fn toupper_empty_string() {
assert_eq!(TestDb::new().scalar("RETURN string.upper('')"), "");
}
#[test]
fn tolower_already_lower() {
assert_eq!(
TestDb::new().scalar("RETURN string.lower('hello')"),
"hello"
);
}
#[test]
fn toupper_already_upper() {
assert_eq!(
TestDb::new().scalar("RETURN string.upper('HELLO')"),
"HELLO"
);
}
#[test]
fn tolower_mixed_case() {
assert_eq!(
TestDb::new().scalar("RETURN string.lower('HeLLo WoRLd')"),
"hello world"
);
}
#[test]
fn tolower_null_returns_null() {
assert!(TestDb::new().scalar("RETURN string.lower(null)").is_null());
}
#[test]
fn toupper_null_returns_null() {
assert!(TestDb::new().scalar("RETURN string.upper(null)").is_null());
}
#[test]
fn trim_whitespace() {
assert_eq!(
TestDb::new().scalar("RETURN string.trim(' hello ')"),
"hello"
);
}
#[test]
fn ltrim_whitespace() {
assert_eq!(
TestDb::new().scalar("RETURN string.trim_left(' hello ')"),
"hello "
);
}
#[test]
fn rtrim_whitespace() {
assert_eq!(
TestDb::new().scalar("RETURN string.trim_right(' hello ')"),
" hello"
);
}
#[test]
fn trim_no_whitespace() {
assert_eq!(TestDb::new().scalar("RETURN string.trim('hello')"), "hello");
}
#[test]
fn trim_empty_string() {
assert_eq!(TestDb::new().scalar("RETURN string.trim('')"), "");
}
#[test]
fn trim_all_whitespace() {
assert_eq!(TestDb::new().scalar("RETURN string.trim(' ')"), "");
}
#[test]
fn trim_tabs_and_newlines() {
assert_eq!(
TestDb::new().scalar("RETURN string.trim('\t hello \n')"),
"hello"
);
}
#[test]
fn replace_basic() {
assert_eq!(
TestDb::new().scalar("RETURN string.replace('hello world', 'world', 'earth')"),
"hello earth"
);
}
#[test]
fn replace_multiple_occurrences() {
assert_eq!(
TestDb::new().scalar("RETURN string.replace('abcabc', 'a', 'x')"),
"xbcxbc"
);
}
#[test]
fn replace_no_match() {
assert_eq!(
TestDb::new().scalar("RETURN string.replace('hello', 'xyz', 'abc')"),
"hello"
);
}
#[test]
fn replace_empty_search() {
let v = TestDb::new().scalar("RETURN string.replace('ab', '', '-')");
assert_eq!(v, "-a-b-");
}
#[test]
fn replace_with_empty_replacement() {
assert_eq!(
TestDb::new().scalar("RETURN string.replace('hello', 'l', '')"),
"heo"
);
}
#[test]
fn split_basic() {
let v = TestDb::new().scalar("RETURN string.split('a,b,c', ',')");
let arr = v.as_array().unwrap();
assert_eq!(arr, &["a", "b", "c"]);
}
#[test]
fn split_no_delimiter_found() {
let v = TestDb::new().scalar("RETURN string.split('hello', ',')");
let arr = v.as_array().unwrap();
assert_eq!(arr.len(), 1);
assert_eq!(arr[0], "hello");
}
#[test]
fn split_empty_string() {
let v = TestDb::new().scalar("RETURN string.split('', ',')");
let arr = v.as_array().unwrap();
assert_eq!(arr.len(), 1);
assert_eq!(arr[0], "");
}
#[test]
fn split_consecutive_delimiters() {
let v = TestDb::new().scalar("RETURN string.split('a,,b', ',')");
let arr = v.as_array().unwrap();
assert_eq!(arr.len(), 3);
assert_eq!(arr[0], "a");
assert_eq!(arr[1], "");
assert_eq!(arr[2], "b");
}
#[test]
fn substring_basic() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('hello world', 0, 5)"),
"hello"
);
}
#[test]
fn substring_from_middle() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('hello world', 6, 5)"),
"world"
);
}
#[test]
fn substring_two_arg_to_end() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('hello world', 6)"),
"world"
);
}
#[test]
fn substring_start_beyond_length() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('hello', 100, 5)"),
""
);
}
#[test]
fn substring_length_beyond_end() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('hello', 3, 100)"),
"lo"
);
}
#[test]
fn substring_zero_length() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('hello', 0, 0)"),
""
);
}
#[test]
fn substring_uses_character_offsets_for_unicode() {
assert_eq!(
TestDb::new().scalar("RETURN string.slice('éclair', 1, 3)"),
"cla"
);
assert_eq!(
TestDb::new().scalar("RETURN string.slice('éclair', 1)"),
"clair"
);
}
#[test]
fn left_basic() {
assert_eq!(
TestDb::new().scalar("RETURN string.prefix('hello', 3)"),
"hel"
);
}
#[test]
fn left_zero() {
assert_eq!(TestDb::new().scalar("RETURN string.prefix('hello', 0)"), "");
}
#[test]
fn left_beyond_length() {
assert_eq!(
TestDb::new().scalar("RETURN string.prefix('hello', 100)"),
"hello"
);
}
#[test]
fn right_basic() {
assert_eq!(
TestDb::new().scalar("RETURN string.suffix('hello', 3)"),
"llo"
);
}
#[test]
fn right_zero() {
assert_eq!(TestDb::new().scalar("RETURN string.suffix('hello', 0)"), "");
}
#[test]
fn right_beyond_length() {
assert_eq!(
TestDb::new().scalar("RETURN string.suffix('hello', 100)"),
"hello"
);
}
#[test]
fn reverse_string() {
assert_eq!(
TestDb::new().scalar("RETURN value.reverse('hello')"),
"olleh"
);
}
#[test]
fn reverse_empty_string() {
assert_eq!(TestDb::new().scalar("RETURN value.reverse('')"), "");
}
#[test]
fn reverse_single_char() {
assert_eq!(TestDb::new().scalar("RETURN value.reverse('x')"), "x");
}
#[test]
fn reverse_palindrome() {
assert_eq!(
TestDb::new().scalar("RETURN value.reverse('racecar')"),
"racecar"
);
}
#[test]
fn size_of_string() {
assert_eq!(TestDb::new().scalar("RETURN value.size('hello')"), 5);
}
#[test]
fn size_of_empty_string() {
assert_eq!(TestDb::new().scalar("RETURN value.size('')"), 0);
}
#[test]
fn length_alias_works() {
assert_eq!(TestDb::new().scalar("RETURN value.size('hello')"), 5);
}
#[test]
fn size_of_list() {
assert_eq!(TestDb::new().scalar("RETURN value.size([1, 2, 3])"), 3);
}
#[test]
fn size_of_empty_list() {
assert_eq!(TestDb::new().scalar("RETURN value.size([])"), 0);
}
#[test]
fn abs_zero() {
assert_eq!(TestDb::new().scalar("RETURN math.abs(0)"), 0);
}
#[test]
fn abs_negative_float() {
let v = TestDb::new()
.scalar("RETURN math.abs(-3.14)")
.as_f64()
.unwrap();
assert!((v - 3.14).abs() < 0.001);
}
#[test]
fn abs_positive() {
assert_eq!(TestDb::new().scalar("RETURN math.abs(42)"), 42);
}
#[test]
fn ceil_already_integer() {
assert_eq!(TestDb::new().scalar("RETURN math.ceil(5.0)"), 5);
}
#[test]
fn ceil_positive() {
assert_eq!(TestDb::new().scalar("RETURN math.ceil(4.1)"), 5);
}
#[test]
fn ceil_negative() {
assert_eq!(TestDb::new().scalar("RETURN math.ceil(-4.9)"), -4);
}
#[test]
fn floor_positive() {
assert_eq!(TestDb::new().scalar("RETURN math.floor(4.9)"), 4);
}
#[test]
fn floor_negative() {
assert_eq!(TestDb::new().scalar("RETURN math.floor(-4.1)"), -5);
}
#[test]
fn round_half_up() {
assert_eq!(TestDb::new().scalar("RETURN math.round(2.5)"), 3);
}
#[test]
fn round_half_down() {
assert_eq!(TestDb::new().scalar("RETURN math.round(2.4)"), 2);
}
#[test]
fn sqrt_of_zero() {
let v = TestDb::new()
.scalar("RETURN math.sqrt(0)")
.as_f64()
.unwrap();
assert!(v.abs() < 0.001);
}
#[test]
fn sqrt_of_one() {
let v = TestDb::new()
.scalar("RETURN math.sqrt(1)")
.as_f64()
.unwrap();
assert!((v - 1.0).abs() < 0.001);
}
#[test]
fn sqrt_negative_null() {
assert!(TestDb::new().scalar("RETURN math.sqrt(-1)").is_null());
}
#[test]
fn sign_positive_int() {
assert_eq!(TestDb::new().scalar("RETURN math.sign(42)"), 1);
}
#[test]
fn sign_negative_int() {
assert_eq!(TestDb::new().scalar("RETURN math.sign(-42)"), -1);
}
#[test]
fn sign_zero_int() {
assert_eq!(TestDb::new().scalar("RETURN math.sign(0)"), 0);
}
#[test]
fn tostring_integer() {
assert_eq!(TestDb::new().scalar("RETURN type.cast(42, STRING)"), "42");
}
#[test]
fn tostring_negative_integer() {
assert_eq!(TestDb::new().scalar("RETURN type.cast(-7, STRING)"), "-7");
}
#[test]
fn tostring_float() {
let v = TestDb::new().scalar("RETURN type.cast(3.14, STRING)");
assert!(v.as_str().unwrap().starts_with("3.14"));
}
#[test]
fn tostring_boolean_true() {
assert_eq!(
TestDb::new().scalar("RETURN type.cast(true, STRING)"),
"true"
);
}
#[test]
fn tostring_boolean_false() {
assert_eq!(
TestDb::new().scalar("RETURN type.cast(false, STRING)"),
"false"
);
}
#[test]
fn tostring_string_passthrough() {
assert_eq!(
TestDb::new().scalar("RETURN type.cast('hello', STRING)"),
"hello"
);
}
#[test]
fn tostring_null_returns_null() {
assert!(TestDb::new()
.scalar("RETURN type.cast(null, STRING)")
.is_null());
}
#[test]
fn tointeger_string_positive() {
assert_eq!(TestDb::new().scalar("RETURN type.cast('42', INTEGER)"), 42);
}
#[test]
fn tointeger_string_negative() {
assert_eq!(TestDb::new().scalar("RETURN type.cast('-7', INTEGER)"), -7);
}
#[test]
fn tointeger_float_truncates() {
assert_eq!(TestDb::new().scalar("RETURN type.cast(3.9, INTEGER)"), 3);
}
#[test]
fn tointeger_negative_float_truncates() {
assert_eq!(TestDb::new().scalar("RETURN type.cast(-3.9, INTEGER)"), -3);
}
#[test]
fn tointeger_already_int() {
assert_eq!(TestDb::new().scalar("RETURN type.cast(42, INTEGER)"), 42);
}
#[test]
fn tointeger_null_returns_null() {
assert!(TestDb::new()
.scalar("RETURN type.cast(null, INTEGER)")
.is_null());
}
#[test]
fn tofloat_string() {
let v = TestDb::new()
.scalar("RETURN type.cast('3.14', FLOAT)")
.as_f64()
.unwrap();
assert!((v - 3.14).abs() < 0.001);
}
#[test]
fn tofloat_integer_to_float() {
let v = TestDb::new()
.scalar("RETURN type.cast(42, FLOAT)")
.as_f64()
.unwrap();
assert!((v - 42.0).abs() < 0.001);
}
#[test]
fn tofloat_already_float() {
let v = TestDb::new()
.scalar("RETURN type.cast(3.14, FLOAT)")
.as_f64()
.unwrap();
assert!((v - 3.14).abs() < 0.001);
}
#[test]
fn tofloat_null_returns_null() {
assert!(TestDb::new()
.scalar("RETURN type.cast(null, FLOAT)")
.is_null());
}
#[test]
fn coalesce_missing_property_to_default() {
let db = TestDb::new();
db.run("CREATE (:User {name: 'Alice', nickname: 'Ali'})");
db.run("CREATE (:User {name: 'Bob'})");
let rows = db.run(
"MATCH (u:User) RETURN u.name AS name, value.first_non_null(u.nickname, 'N/A') AS nick ORDER BY u.name",
);
assert_eq!(rows[0]["nick"], "Ali");
assert_eq!(rows[1]["nick"], "N/A");
}
#[test]
fn coalesce_existing_property() {
let db = TestDb::new();
db.run("CREATE (:User {name: 'Alice', nickname: 'Ali'})");
let rows = db.run("MATCH (u:User) RETURN value.first_non_null(u.nickname, 'N/A') AS nick");
assert_eq!(rows[0]["nick"], "Ali");
}
#[test]
fn keys_of_node() {
let db = TestDb::new();
db.run("CREATE (:Item {name: 'Widget', price: 42})");
let rows = db.run("MATCH (i:Item) RETURN value.keys(i) AS k");
let keys = rows[0]["k"].as_array().unwrap();
assert_eq!(keys.len(), 2);
}
#[test]
fn keys_of_relationship() {
let db = TestDb::new();
db.run("CREATE (a:Person {name:'A'})-[:KNOWS {since:2020, strength:5}]->(b:Person {name:'B'})");
let rows = db.run("MATCH ()-[r:KNOWS]->() RETURN value.keys(r) AS k");
let keys = rows[0]["k"].as_array().unwrap();
assert_eq!(keys.len(), 2);
}
#[test]
fn keys_of_empty_node() {
let db = TestDb::new();
db.run("CREATE (:Empty)");
let rows = db.run("MATCH (n:Empty) RETURN value.keys(n) AS k");
let keys = rows[0]["k"].as_array().unwrap();
assert_eq!(keys.len(), 0);
}
#[test]
fn labels_single() {
let db = TestDb::new();
db.run("CREATE (:User {name: 'Alice'})");
let rows = db.run("MATCH (n:User) RETURN node.labels(n) AS l");
let labels = rows[0]["l"].as_array().unwrap();
assert_eq!(labels.len(), 1);
assert_eq!(labels[0], "User");
}
#[test]
fn labels_multiple() {
let db = TestDb::new();
db.run("CREATE (:Person:Employee {name: 'Alice'})");
let rows = db.run("MATCH (n:Person) RETURN node.labels(n) AS l");
let labels = rows[0]["l"].as_array().unwrap();
assert_eq!(labels.len(), 2);
}
#[test]
fn type_of_relationship() {
let db = TestDb::new();
db.run("CREATE (a:A)-[:KNOWS]->(b:B)");
let rows = db.run("MATCH ()-[r]->() RETURN edge.type(r) AS t");
assert_eq!(rows[0]["t"], "KNOWS");
}
#[test]
fn id_of_node_is_integer() {
let db = TestDb::new();
db.run("CREATE (:N {name: 'x'})");
let v = db.scalar("MATCH (n:N) RETURN value.id(n) AS i");
assert!(v.is_i64());
}
#[test]
fn id_of_relationship_is_integer() {
let db = TestDb::new();
db.run("CREATE (a:A)-[:R]->(b:B)");
let v = db.scalar("MATCH ()-[r]->() RETURN value.id(r) AS i");
assert!(v.is_i64());
}
#[test]
fn timestamp_returns_positive_integer() {
let v = TestDb::new().scalar("RETURN temporal.timestamp() AS ts");
assert!(v.as_i64().unwrap() > 0);
}
#[test]
fn timestamp_is_recent() {
let v = TestDb::new().scalar("RETURN temporal.timestamp() AS ts");
let ts = v.as_i64().unwrap();
assert!(ts > 1_704_067_200_000);
}
#[test]
fn length_of_path() {
let db = TestDb::new();
db.run("CREATE (:A {id:1})-[:R]->(:B {id:2})");
let v = db.scalar("MATCH p = (:A)-[:R]->(:B) RETURN value.size(p) AS len");
assert_eq!(v, 1);
}
#[test]
fn nodes_of_path() {
let db = TestDb::new();
db.run("CREATE (:A {id:1})-[:R]->(:B {id:2})");
let rows = db.run("MATCH p = (:A)-[:R]->(:B) RETURN path.nodes(p) AS ns");
let ns = rows[0]["ns"].as_array().unwrap();
assert_eq!(ns.len(), 2);
}
#[test]
fn relationships_of_path() {
let db = TestDb::new();
db.run("CREATE (:A {id:1})-[:R {w:1}]->(:B {id:2})");
let rows = db.run("MATCH p = (:A)-[:R]->(:B) RETURN path.edges(p) AS rels");
let rels = rows[0]["rels"].as_array().unwrap();
assert_eq!(rels.len(), 1);
}
#[test]
fn count_star_empty_graph() {
let v = TestDb::new().scalar("MATCH (n:Nothing) RETURN count(*) AS c");
assert_eq!(v, 0);
}
#[test]
fn sum_empty_set() {
let v = TestDb::new().scalar("MATCH (n:Nothing) RETURN sum(n.val) AS s");
assert!(v == 0 || v.is_null());
}
#[test]
fn avg_empty_set() {
let v = TestDb::new().scalar("MATCH (n:Nothing) RETURN avg(n.val) AS a");
assert!(v.is_null());
}
#[test]
fn min_empty_set() {
let v = TestDb::new().scalar("MATCH (n:Nothing) RETURN min(n.val) AS m");
assert!(v.is_null());
}
#[test]
fn max_empty_set() {
let v = TestDb::new().scalar("MATCH (n:Nothing) RETURN max(n.val) AS m");
assert!(v.is_null());
}
#[test]
fn collect_empty_set() {
let v = TestDb::new().scalar("MATCH (n:Nothing) RETURN collect(n.val) AS c");
assert_eq!(v.as_array().unwrap().len(), 0);
}
#[test]
fn count_with_nulls() {
let db = TestDb::new();
db.run("CREATE (:Item {val: 1})");
db.run("CREATE (:Item {val: 2})");
db.run("CREATE (:Item)"); let v = db.scalar("MATCH (i:Item) RETURN count(i.val) AS c");
assert_eq!(v, 2);
}
#[test]
fn count_star_includes_nulls() {
let db = TestDb::new();
db.run("CREATE (:Item {val: 1})");
db.run("CREATE (:Item)");
let v = db.scalar("MATCH (i:Item) RETURN count(*) AS c");
assert_eq!(v, 2);
}
#[test]
fn stdev_basic() {
let db = TestDb::new();
for v in [2, 4, 4, 4, 5, 5, 7, 9] {
db.run(&format!("CREATE (:D {{val: {v}}})"));
}
let v = db.scalar("MATCH (d:D) RETURN stdev(d.val) AS s");
let s = v.as_f64().unwrap();
assert!(s > 1.5 && s < 2.5);
}
#[test]
fn percentile_cont_median() {
let db = TestDb::new();
for v in [1, 2, 3, 4, 5] {
db.run(&format!("CREATE (:D {{val: {v}}})"));
}
let v = db.scalar("MATCH (d:D) RETURN percentileCont(d.val, 0.5) AS p");
let p = v.as_f64().unwrap();
assert!((p - 3.0).abs() < 0.001);
}
#[test]
fn lpad_function() {
let v = TestDb::new().scalar("RETURN string.pad_left('42', 5, '0')");
assert_eq!(v, "00042");
}
#[test]
fn rpad_function() {
let v = TestDb::new().scalar("RETURN string.pad_right('hi', 5, '.')");
assert_eq!(v, "hi...");
}
#[test]
fn char_length_function() {
let v = TestDb::new().scalar("RETURN string.length('hello')");
assert_eq!(v, 5);
}
#[test]
fn normalize_function() {
let v = TestDb::new().scalar("RETURN string.normalize('hello')");
assert_eq!(v, "hello");
}
#[test]
fn last_function() {
let v = TestDb::new().scalar("RETURN list.last([1, 2, 3])");
assert_eq!(v, 3);
}
#[test]
fn last_of_empty_list_is_null() {
assert!(TestDb::new().scalar("RETURN list.last([])").is_null());
}
#[test]
fn list_contains_function() {
let v = TestDb::new().scalar("RETURN [1, 2, 3] CONTAINS 2");
assert_eq!(v, true);
}
#[test]
fn log_function() {
let v = TestDb::new()
.scalar("RETURN math.log(2.718281828)")
.as_f64()
.unwrap();
assert!((v - 1.0).abs() < 0.01);
}
#[test]
fn log10_function() {
let v = TestDb::new()
.scalar("RETURN math.log10(100)")
.as_f64()
.unwrap();
assert!((v - 2.0).abs() < 0.01);
}
#[test]
fn exp_function() {
let v = TestDb::new().scalar("RETURN math.exp(1)").as_f64().unwrap();
assert!((v - 2.718).abs() < 0.01);
}
#[test]
fn sin_function() {
let v = TestDb::new().scalar("RETURN math.sin(0)").as_f64().unwrap();
assert!(v.abs() < 0.001);
}
#[test]
fn cos_function() {
let v = TestDb::new().scalar("RETURN math.cos(0)").as_f64().unwrap();
assert!((v - 1.0).abs() < 0.001);
}
#[test]
fn pi_function() {
let v = TestDb::new().scalar("RETURN math.pi()").as_f64().unwrap();
assert!((v - std::f64::consts::PI).abs() < 0.0001);
}
#[test]
fn e_function() {
let v = TestDb::new().scalar("RETURN math.e()").as_f64().unwrap();
assert!((v - std::f64::consts::E).abs() < 0.0001);
}
#[test]
fn rand_function() {
let v = TestDb::new()
.scalar("RETURN math.random()")
.as_f64()
.unwrap();
assert!((0.0..1.0).contains(&v));
}
#[test]
fn nested_tolower_replace() {
assert_eq!(
TestDb::new().scalar("RETURN string.lower(string.replace('Hello World', ' ', '_'))"),
"hello_world"
);
}
#[test]
fn nested_tostring_tointeger() {
assert_eq!(
TestDb::new().scalar("RETURN type.cast(type.cast(42, STRING), INTEGER)"),
42
);
}
#[test]
fn size_of_split_result() {
assert_eq!(
TestDb::new().scalar("RETURN value.size(string.split('a.b.c', '.'))"),
3
);
}
#[test]
fn head_of_split() {
assert_eq!(
TestDb::new().scalar("RETURN list.first(string.split('hello.world', '.'))"),
"hello"
);
}
#[test]
fn tolower_on_node_property() {
let db = TestDb::new();
db.run("CREATE (:User {name: 'ALICE'})");
let rows = db.run("MATCH (u:User) RETURN string.lower(u.name) AS name");
assert_eq!(rows[0]["name"], "alice");
}
#[test]
fn size_of_node_string_property() {
let db = TestDb::new();
db.run("CREATE (:User {name: 'Alice'})");
let rows = db.run("MATCH (u:User) RETURN value.size(u.name) AS len");
assert_eq!(rows[0]["len"], 5);
}
#[test]
fn string_functions_in_where_clause() {
let db = TestDb::new();
db.run("CREATE (:User {name: 'Alice'})");
db.run("CREATE (:User {name: 'BOB'})");
let rows =
db.run("MATCH (u:User) WHERE string.lower(u.name) STARTS WITH 'a' RETURN u.name AS name");
assert_eq!(rows.len(), 1);
assert_eq!(rows[0]["name"], "Alice");
}
#[test]
fn string_concat_in_return() {
let db = TestDb::new();
db.run("CREATE (:Person {first: 'John', last: 'Doe'})");
let rows = db.run("MATCH (p:Person) RETURN p.first + ' ' + p.last AS fullName");
assert_eq!(rows[0]["fullName"], "John Doe");
}
#[test]
fn case_with_size_function() {
let db = TestDb::new();
db.run("CREATE (:Item {name: 'A', tags: ['x']})");
db.run("CREATE (:Item {name: 'B', tags: ['x', 'y', 'z']})");
let rows = db.run(
"MATCH (i:Item) \
RETURN i.name AS name, \
CASE WHEN value.size(i.tags) > 2 THEN 'many' ELSE 'few' END AS count \
ORDER BY i.name",
);
assert_eq!(rows[0]["count"], "few");
assert_eq!(rows[1]["count"], "many");
}
#[test]
fn with_computed_values_reused() {
let rows = TestDb::new().run(
"WITH 'hello world' AS text \
WITH text, value.size(text) AS len, string.upper(text) AS upper \
RETURN len, upper",
);
assert_eq!(rows[0]["len"], 11);
assert_eq!(rows[0]["upper"], "HELLO WORLD");
}