use super::*;
#[test]
fn rules_for_known_languages() {
assert!(rules_for("Rust").is_some());
assert!(rules_for("Python").is_some());
assert!(rules_for("JavaScript").is_some());
assert!(rules_for("Go").is_some());
assert!(rules_for("C").is_some());
assert!(rules_for("Ruby").is_some());
}
#[test]
fn rules_for_unknown_language() {
assert!(rules_for("COBOL").is_none());
assert!(rules_for("JSON").is_none());
}
#[test]
fn rust_simple_function() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["fn foo() {", " let x = 1;", " let y = x + 2;", "}"];
let counts = count_tokens(&lines, rules, &[]);
assert!(counts.total_operators > 0);
assert!(counts.total_operands > 0);
assert!(!counts.distinct_operators.contains("fn"));
assert!(!counts.distinct_operators.contains("let"));
assert!(counts.distinct_operands.contains("foo"));
assert!(counts.distinct_operands.contains("x"));
assert!(counts.distinct_operands.contains("1"));
}
#[test]
fn keywords_in_strings_not_counted() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["let s = \"if for while match\";"];
let counts = count_tokens(&lines, rules, &[]);
assert!(!counts.distinct_operators.contains("if"));
assert!(!counts.distinct_operators.contains("for"));
assert!(!counts.distinct_operators.contains("while"));
assert!(!counts.distinct_operators.contains("match"));
}
#[test]
fn function_names_are_operands() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["foo(x, y);"];
let counts = count_tokens(&lines, rules, &[]);
assert!(counts.distinct_operands.contains("foo"));
assert!(counts.distinct_operands.contains("x"));
assert!(counts.distinct_operands.contains("y"));
assert!(counts.distinct_operators.contains("("));
assert!(counts.distinct_operators.contains(","));
assert!(counts.distinct_operators.contains(";"));
}
#[test]
fn numeric_literals_are_operands() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["let x = 42;", "let y = 0xff;"];
let counts = count_tokens(&lines, rules, &[]);
assert!(counts.distinct_operands.contains("42"));
assert!(counts.distinct_operands.contains("0xff"));
}
#[test]
fn multi_char_symbols() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["if x && y || z == w {"];
let counts = count_tokens(&lines, rules, &[]);
assert!(counts.distinct_operators.contains("&&"));
assert!(counts.distinct_operators.contains("||"));
assert!(counts.distinct_operators.contains("=="));
}
#[test]
fn python_tokens() {
let rules = rules_for("Python").unwrap();
let lines = vec!["def foo(x):", " if x > 0:", " return x + 1"];
let counts = count_tokens(&lines, rules, &[]);
assert!(!counts.distinct_operators.contains("def"));
assert!(counts.distinct_operators.contains("if"));
assert!(counts.distinct_operators.contains("return"));
assert!(counts.distinct_operands.contains("foo"));
assert!(counts.distinct_operands.contains("x"));
assert!(counts.distinct_operands.contains("0"));
assert!(counts.distinct_operands.contains("1"));
}
#[test]
fn empty_input() {
let rules = rules_for("Rust").unwrap();
let lines: Vec<&str> = vec![];
let counts = count_tokens(&lines, rules, &[]);
assert_eq!(counts.total_operators, 0);
assert_eq!(counts.total_operands, 0);
assert!(counts.distinct_operators.is_empty());
assert!(counts.distinct_operands.is_empty());
}
#[test]
fn operator_symbols_sorted_longest_first() {
let languages = [
"Rust",
"Python",
"JavaScript",
"Go",
"C",
"Ruby",
"Kotlin",
"Swift",
"Bourne Shell",
];
for lang in &languages {
let rules = rules_for(lang).unwrap();
for (i, sym) in rules.operator_symbols.iter().enumerate() {
for later in &rules.operator_symbols[i + 1..] {
if later.starts_with(sym) && later.len() > sym.len() {
panic!(
"{lang}: \"{sym}\" appears before \"{later}\" — \
longer symbols must come first for correct longest-match"
);
}
}
}
}
}
#[test]
fn longest_match_for_symbols() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["x >>= y;"];
let counts = count_tokens(&lines, rules, &[]);
assert!(counts.distinct_operators.contains(">>="));
assert_eq!(counts.total_operators, 2);
}
#[test]
fn ignored_keywords_not_counted() {
let rules = rules_for("Rust").unwrap();
let lines = vec!["pub fn foo(x: i32) -> bool {"];
let counts = count_tokens(&lines, rules, &[]);
assert!(!counts.distinct_operators.contains("pub"));
assert!(!counts.distinct_operators.contains("fn"));
assert!(!counts.distinct_operands.contains("i32"));
assert!(!counts.distinct_operands.contains("bool"));
assert!(counts.distinct_operands.contains("foo"));
assert!(counts.distinct_operands.contains("x"));
}