use super::{FeatureCategory, FeatureTest};
pub const FEATURE_TESTS: &[FeatureTest] = &[
FeatureTest {
name: "number_literal",
covers: &["number", "integer", "literal"],
code: "function test() { return 42; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "string_literal",
covers: &["string", "literal"],
code: r#"function test() { return "hello"; }"#,
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "boolean_literal",
covers: &["boolean", "literal"],
code: "function test() { return true; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "null_literal",
covers: &["none_literal", "literal"],
code: "function test() { return null; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "array_literal",
covers: &["array_literal", "array_elements", "array_element"],
code: "function test() { return [1, 2, 3]; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "object_literal",
covers: &["object_literal", "object_fields", "object_field"],
code: "function test() { return { a: 1, b: 2 }; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "color_literal",
covers: &["color", "literal"],
code: "function test() { return 'red'; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "duration_literal",
covers: &["duration", "duration_unit", "simple_duration"],
code: "function test() { return 5m; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "datetime_literal",
covers: &["datetime_literal", "datetime_expr"],
code: r#"function test() { return @"2020-01-01"; }"#,
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "time_ref",
covers: &["time_ref", "named_time"],
code: "function test() { return @today; }",
function: "test",
category: FeatureCategory::Literal,
requires_data: false,
},
FeatureTest {
name: "arithmetic_add_sub",
covers: &["additive_expr", "expression"],
code: "function test() { return 1 + 2 - 1; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "arithmetic_mul_div_mod",
covers: &["multiplicative_expr"],
code: "function test() { return 2 * 3 / 2 % 2; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "arithmetic_pow",
covers: &["exponential_expr"],
code: "function test() { return 2 ^ 3; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "comparison_operators",
covers: &["comparison_expr", "comparison_op", "comparison_tail"],
code: "function test() { return (5 > 3) && (3 < 5) && (5 >= 5) && (3 <= 5); }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "equality_operators",
covers: &["comparison_op"],
code: "function test() { return (5 == 5) && (5 != 3); }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "fuzzy_equal_basic",
covers: &["fuzzy_comparison_tail", "fuzzy_op"],
code: "function test() { return 100 ~= 102; }", function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "fuzzy_equal_with_absolute_tolerance",
covers: &[
"fuzzy_comparison_tail",
"fuzzy_op",
"within_clause",
"tolerance_spec",
],
code: "function test() { return 100 ~= 105 within 10; }", function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "fuzzy_equal_with_percentage_tolerance",
covers: &[
"fuzzy_comparison_tail",
"fuzzy_op",
"within_clause",
"tolerance_spec",
],
code: "function test() { return 100 ~= 110 within 15%; }", function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "fuzzy_greater",
covers: &["fuzzy_comparison_tail", "fuzzy_op"],
code: "function test() { return 100 ~> 98; }", function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "fuzzy_less",
covers: &["fuzzy_comparison_tail", "fuzzy_op"],
code: "function test() { return 98 ~< 100; }", function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "fuzzy_equal_false",
covers: &["fuzzy_comparison_tail", "fuzzy_op", "within_clause"],
code: "function test() { return 100 ~= 200 within 5; }", function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "logical_and",
covers: &["and_expr"],
code: "function test() { return true && false; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "logical_or",
covers: &["or_expr"],
code: "function test() { return true || false; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "logical_not",
covers: &["unary_expr"],
code: "function test() { return !false; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "unary_negation",
covers: &["unary_expr"],
code: "function test() { return -5; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "ternary_op",
covers: &["ternary_expr", "ternary_branch"],
code: "function test() { return 1 > 0 ? 1 : 2; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "null_coalesce",
covers: &["null_coalesce_expr"],
code: "function test() { let x = null; return x ?? 5; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "range_expr",
covers: &["range_expr"],
code: "function test() { return 1:5; }",
function: "test",
category: FeatureCategory::Operator,
requires_data: false,
},
FeatureTest {
name: "if_expr",
covers: &["if_expr"],
code: "function test() { return if 1 > 0 then 1 else 2; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "if_stmt",
covers: &["if_stmt", "else_clause"],
code: "function test() { let x = 0; if (1 > 0) { x = 1; } else { x = 2; } return x; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "match_expr",
covers: &["match_expr", "match_arm", "pattern"],
code: "function test() { return match 2 { 1 => 10, 2 => 20, _ => 0 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "match_with_guard",
covers: &["match_expr", "match_arm"],
code: "function test() { return match 4 { x where x > 3 => x, _ => 0 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "match_array_pattern",
covers: &["pattern_array"],
code: "function test() { return match [1, 2] { [a, b] => a + b, _ => 0 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "match_object_pattern",
covers: &["pattern_object", "pattern_field"],
code: "function test() { return match { a: 1, b: 2 } { { a: x, b: y } => x + y, _ => 0 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "match_constructor",
covers: &["pattern_constructor"],
code: "function test() { return match { value: 3 } { Ok(x) => x, Err(e) => -1 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "for_loop",
covers: &["for_loop", "for_clause"],
code: "function test() { let sum = 0; for x in [1, 2, 3] { sum = sum + x; } return sum; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "for_expr",
covers: &["for_expr", "for_expr_clause"],
code: "function test() { return for x in [1, 2, 3] { x * 2 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "while_loop",
covers: &["while_loop"],
code: "function test() { let i = 0; while (i < 3) { i = i + 1; } return i; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "while_expr",
covers: &["while_expr"],
code: "function test() { let i = 0; return while i < 3 { i = i + 1; i }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "loop_expr",
covers: &["loop_expr", "block_expr"],
code: "function test() { let i = 0; return loop { i = i + 1; if i == 3 then break i; i }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "break_continue",
covers: &["break_stmt", "break_expr", "continue_stmt", "continue_expr"],
code: "function test() { let sum = 0; for x in [1, 2, 3, 4] { if x == 2 { continue; } if x == 4 { break; } sum = sum + x; } return sum; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "return_stmt",
covers: &["return_stmt", "return_expr"],
code: "function test() { return 42; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "variable_decl",
covers: &["variable_decl", "var_keyword"],
code: "function test() { let x = 5; return x; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "const_var_decl",
covers: &["variable_decl", "var_keyword"],
code: "function test() { const a = 1; var b = 2; return a + b; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "assignment",
covers: &["assignment", "assignment_expr"],
code: "function test() { let x = 1; x = 2; return x; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "destructure_array",
covers: &["destructure_pattern", "destructure_array_pattern"],
code: "function test() { let [a, b] = [1, 2]; return a + b; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "destructure_object",
covers: &[
"destructure_pattern",
"destructure_object_pattern",
"destructure_object_pattern_field",
],
code: "function test() { let { a, b } = { a: 1, b: 2 }; return a + b; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "destructure_rest",
covers: &["destructure_rest_pattern"],
code: "function test() { let { a, ...rest } = { a: 1, b: 2 }; return rest.b; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "let_expr",
covers: &["let_expr"],
code: "function test() { return let x = 5 in x + 3; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
FeatureTest {
name: "function_def",
covers: &[
"function_def",
"function_params",
"function_param",
"function_body",
],
code: "function add(a, b) { return a + b; } function test() { return add(1, 2); }",
function: "test",
category: FeatureCategory::Function,
requires_data: false,
},
FeatureTest {
name: "arrow_function",
covers: &["arrow_function"],
code: "function test() { let f = x => x + 1; return f(5); }",
function: "test",
category: FeatureCategory::Function,
requires_data: false,
},
FeatureTest {
name: "function_expr",
covers: &["function_expr"],
code: "function test() { let f = function(x) { return x + 1; }; return f(5); }",
function: "test",
category: FeatureCategory::Function,
requires_data: false,
},
FeatureTest {
name: "closure_capture",
covers: &["function_expr"],
code: "function test() { let base = 3; let f = function(x) { return x + base; }; return f(4); }",
function: "test",
category: FeatureCategory::Function,
requires_data: false,
},
FeatureTest {
name: "function_call",
covers: &["function_call", "arg_list"],
code: "function double(x) { return x * 2; } function test() { return double(5); }",
function: "test",
category: FeatureCategory::Function,
requires_data: false,
},
FeatureTest {
name: "return_type_annotation",
covers: &["return_type", "type_annotation"],
code: "function add(a, b) -> number { return a + b; } function test() { return add(1, 2); }",
function: "test",
category: FeatureCategory::Function,
requires_data: false,
},
FeatureTest {
name: "index_access",
covers: &["index_access", "index_expr", "postfix_expr"],
code: "function test() { return [1, 2, 3][1]; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "negative_index",
covers: &["index_access", "index_expr"],
code: "function test() { return [1, 2, 3][-1]; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "slice_access",
covers: &["index_access", "range_expr"],
code: "function test() { return [1, 2, 3, 4][1:3]; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "property_access",
covers: &["property_access", "postfix_expr"],
code: "function test() { return { a: 1 }.a; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "optional_property_access",
covers: &["optional_property_access"],
code: "function test() { let x = null; return x?.a; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "spread_element",
covers: &["spread_element", "array_element"],
code: "function test() { let xs = [1, 2]; return [0, ...xs, 3]; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "object_spread",
covers: &["object_spread", "object_field_item"],
code: "function test() { let a = { x: 1 }; return { ...a, y: 2 }; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "list_comprehension",
covers: &["list_comprehension", "comprehension_clause"],
code: "function test() { return [x * 2 for x in [1, 2, 3]]; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "list_comprehension_filter",
covers: &["list_comprehension", "comprehension_clause"],
code: "function test() { return [x for x in [1, 2, 3, 4] if x > 2]; }",
function: "test",
category: FeatureCategory::Collection,
requires_data: false,
},
FeatureTest {
name: "data_ref",
covers: &["data_ref", "primary_expr"],
code: "function test() { return data[0].close; }",
function: "test",
category: FeatureCategory::Domain,
requires_data: true,
},
FeatureTest {
name: "datetime_access",
covers: &["datetime_access", "datetime_range"],
code: r#"function test() { return data[@"2020-01-01"]; }"#,
function: "test",
category: FeatureCategory::Domain,
requires_data: false,
},
FeatureTest {
name: "timeframe_expr",
covers: &["timeframe_expr", "timeframe"],
code: "function test() { return on(1h) { 2 + 2 }; }",
function: "test",
category: FeatureCategory::Domain,
requires_data: false,
},
FeatureTest {
name: "temporal_nav",
covers: &["temporal_nav", "back_nav", "forward_nav", "nav_amount"],
code: "function test() { return back(5); }",
function: "test",
category: FeatureCategory::Domain,
requires_data: false,
},
FeatureTest {
name: "pattern_name",
covers: &["pattern_name"],
code: "function test() { return pattern::mypat; }",
function: "test",
category: FeatureCategory::Domain,
requires_data: false,
},
FeatureTest {
name: "builtin_function",
covers: &["builtin_function"],
code: "function test() { return abs(-5) + sqrt(9); }",
function: "test",
category: FeatureCategory::Domain,
requires_data: false,
},
FeatureTest {
name: "type_method_expr",
covers: &["postfix_expr"],
code: "function test() { return 123.type().to_string(); }",
function: "test",
category: FeatureCategory::TypeSystem,
requires_data: false,
},
FeatureTest {
name: "type_assertion",
covers: &["type_assertion_suffix", "postfix_expr"],
code: "function test() { let x = 5 as number; return x; }",
function: "test",
category: FeatureCategory::TypeSystem,
requires_data: false,
},
FeatureTest {
name: "type_annotation",
covers: &["type_annotation", "primary_type", "basic_type"],
code: "function test(x: number) -> number { return x; } function main() { return test(5); }",
function: "main",
category: FeatureCategory::TypeSystem,
requires_data: false,
},
FeatureTest {
name: "generic_type",
covers: &["generic_type", "type_param_list"],
code: "function test() { let arr: Vec<number> = [1, 2, 3]; return arr[0]; }",
function: "test",
category: FeatureCategory::TypeSystem,
requires_data: false,
},
FeatureTest {
name: "tuple_type",
covers: &["tuple_type"],
code: "function test() { let t: [number, string] = [1, \"a\"]; return t[0]; }",
function: "test",
category: FeatureCategory::TypeSystem,
requires_data: false,
},
FeatureTest {
name: "object_type",
covers: &["object_type", "object_type_member"],
code: "function test() { let obj: { a: number; b: string } = { a: 1, b: \"x\" }; return obj.a; }",
function: "test",
category: FeatureCategory::TypeSystem,
requires_data: false,
},
FeatureTest {
name: "ident_and_keyword",
covers: &["ident", "keyword"],
code: "function test() { let myVar = 5; return myVar; }",
function: "test",
category: FeatureCategory::Module,
requires_data: false,
},
FeatureTest {
name: "block_expr",
covers: &["block_expr", "block_items", "block_item"],
code: "function test() { return { let x = 1; x + 2 }; }",
function: "test",
category: FeatureCategory::ControlFlow,
requires_data: false,
},
FeatureTest {
name: "expression_stmt",
covers: &["expression_stmt", "statement"],
code: "function test() { let x = 0; x = x + 1; return x; }",
function: "test",
category: FeatureCategory::Variable,
requires_data: false,
},
];
#[cfg(test)]
mod tests {
use super::*;
use std::collections::BTreeSet;
#[test]
fn test_feature_tests_defined() {
assert!(!FEATURE_TESTS.is_empty());
let categories: BTreeSet<_> = FEATURE_TESTS.iter().map(|t| t.category).collect();
assert!(categories.len() >= 5);
}
}