cat("\n===== Starting AFL geneeration tests =====\n")
test_that(echo("expression_parser handles basic inputs"), {
expect_equal(scidb::expression_parser(1)$to_afl(), "1")
expect_equal(scidb::expression_parser(-1)$to_afl(), "-1")
expect_equal(scidb::expression_parser(a)$to_afl(), "a")
expect_equal(scidb::expression_parser(A)$to_afl(), "A")
expect_equal(scidb::expression_parser(1-1)$to_afl(), "0")
expect_equal(scidb::expression_parser(2+1)$to_afl(), "3")
})
test_that(echo("Generate afl filter expressions from R expressions"), {
expect_equal(scidb::filter_to_afl(a == TRUE), "a = true")
expect_equal(scidb::filter_to_afl(a == !!T), "a = true")
expect_equal(scidb::filter_to_afl(a == !!F), "a = false")
expect_equal(scidb::filter_to_afl(a == 42), "a = 42")
expect_equal(scidb::filter_to_afl(is.null(a)), "is_null(a)")
expect_equal(scidb::filter_to_afl(is.null(a), b != 0), "is_null(a) and (b != 0)")
expect_equal(scidb::filter_to_afl(a %in% c(1,2,3)), "((a = 1) or (a = 2)) or (a = 3)")
expect_equal(scidb::filter_to_afl((a + b + "c") == 'value'), "((a + b) + 'c') = 'value'")
})
test_that(echo("Regular expressions"), {
# Basic tests
expect_equal(scidb::filter_to_afl(field %like% '.+a.+'), "regex(field, '(?i).+a.+')")
expect_equal(scidb::filter_to_afl(field %contains% 'a'), "regex(field, '(?i).*a.*')")
expect_equal(scidb::filter_to_afl(field %starts_with% 'a'), "regex(field, '(?i)a.*')")
expect_equal(scidb::filter_to_afl(field %ends_with% 'a'), "regex(field, '(?i).*a')")
# Escape single-quote character in all regex operations
expect_equal(scidb::filter_to_afl(field %like% "a'a"), "regex(field, '(?i)a\\'a')")
expect_equal(scidb::filter_to_afl(field %contains% "a'a"), "regex(field, '(?i).*a\\'a.*')")
expect_equal(scidb::filter_to_afl(field %starts_with% "a'a"), "regex(field, '(?i)a\\'a.*')")
expect_equal(scidb::filter_to_afl(field %ends_with% "a'a"), "regex(field, '(?i).*a\\'a')")
# Escape double-quote character in all regex operations
expect_equal(scidb::filter_to_afl(field %like% 'a"'), "regex(field, '(?i)a\"')")
expect_equal(scidb::filter_to_afl(field %contains% 'a"'), "regex(field, '(?i).*a\".*')")
expect_equal(scidb::filter_to_afl(field %starts_with% 'a"'), "regex(field, '(?i)a\".*')")
expect_equal(scidb::filter_to_afl(field %ends_with% 'a"'), "regex(field, '(?i).*a\"')")
# Treat regex characters literally, requiring users to escape manually when
# needing to match a literal prefix or suffix containing regex special characters
# NOTE: this behavior differs from arrayop::aflutils$e_to_afl, which escapes some
# special characters like * and \, but does not handle regex characters (e.g. '.')
# TODO: add a literal(...) method to escape all regex characters, which users can
# chain together with the regex methods; this would require an R-value RHS
expect_equal(scidb::filter_to_afl(field %contains% ' a*b(par\\en)\\ '), "regex(field, '(?i).* a*b(par\\en)\\ .*')")
expect_equal(scidb::filter_to_afl(field %starts_with% ' ]"[ '), "regex(field, '(?i) ]\"[ .*')")
# Error regex_func mode
expect_error(scidb::filter_to_afl(field %like% c('a', 'b')), "ERROR: cannot apply character operation 'stringr::str_detect'; RHS is not a scalar character")
})
test_that(echo("Simple type checking for raw values"), {
# Numeric-only
expect_error(scidb::filter_to_afl(a >= "foo"), "ERROR: cannot apply numeric operation '>='; RHS is not a scalar numeric")
expect_error(scidb::filter_to_afl(a > "foo"), "ERROR: cannot apply numeric operation '>'; RHS is not a scalar numeric")
expect_error(scidb::filter_to_afl(a <= "foo"), "ERROR: cannot apply numeric operation '<='; RHS is not a scalar numeric")
expect_error(scidb::filter_to_afl(a < "foo"), "ERROR: cannot apply numeric operation '<'; RHS is not a scalar numeric")
expect_error(scidb::filter_to_afl(paste0(a,3)), "ERROR: cannot apply character operation 'paste0'; RHS is not a scalar character")
expect_error(scidb::filter_to_afl(str_detect(a,3)), "ERROR: cannot apply character operation 'stringr::str_detect'; RHS is not a scalar character")
})
test_that(echo("Generate complex filter expression with logical operators"), {
# Basic cases
expect_equal(scidb::filter_to_afl(a == 3, b == 'val'), "(a = 3) and (b = 'val')")
expect_equal(scidb::filter_to_afl(a == 3 && b == 'val'), "(a = 3) and (b = 'val')")
expect_equal(scidb::filter_to_afl(a == 3 & b == 'val'), "(a = 3) and (b = 'val')")
expect_equal(scidb::filter_to_afl(a == 3 || b == 'val'), "(a = 3) or (b = 'val')")
expect_equal(scidb::filter_to_afl(a == 3 | b == 'val'), "(a = 3) or (b = 'val')")
# Handle logical operator precedence
expect_equal(scidb::filter_to_afl(a == 3 && b == 4 && c == 5), "((a = 3) and (b = 4)) and (c = 5)")
expect_equal(scidb::filter_to_afl(a == 3 || b == 4 || c == 5), "((a = 3) or (b = 4)) or (c = 5)")
expect_equal(scidb::filter_to_afl(a == 3 && (b == 4 || c == 5)), "(a = 3) and ((b = 4) or (c = 5))")
# Push down ! with equalities and inequalities
expect_equal(scidb::filter_to_afl(!(a == 3)), "a != 3")
expect_equal(scidb::filter_to_afl(!(!(a == 3))), "a = 3")
expect_equal(scidb::filter_to_afl(!(a != 3)), "a = 3")
expect_equal(scidb::filter_to_afl(!(a >= 3)), "a < 3")
expect_equal(scidb::filter_to_afl(!(a > 3)), "a <= 3")
expect_equal(scidb::filter_to_afl(!(a <= 3)), "a > 3")
expect_equal(scidb::filter_to_afl(!(a < 3)), "a >= 3")
# Push down ! via De Morgan's Laws, preserving unary composite-ness
A <- scidb::expression_parser(!(a == 3 && b == 4 && c == 5))
B <- scidb::expression_parser(!(a == 3 || b == 4 || c == 5))
C <- scidb::expression_parser(!(a == 3 && (b == 4 || c == 5)))
expect_equal(A$to_afl(), "((a != 3) or (b != 4)) or (c != 5)")
expect_equal(B$to_afl(), "((a != 3) and (b != 4)) and (c != 5)")
expect_equal(C$to_afl(), "(a != 3) or ((b != 4) and (c != 5))")
expect_true(A$unary_composite())
expect_true(B$unary_composite())
expect_true(C$unary_composite())
expect_equal(A$left()$to_afl(), "(a != 3) or (b != 4)")
expect_equal(A$left()$left()$to_afl(), "a != 3")
expect_equal(A$left()$right()$to_afl(), "b != 4")
expect_equal(A$right()$to_afl(), "c != 5")
expect_equal(B$left()$to_afl(), "(a != 3) and (b != 4)")
expect_equal(B$left()$left()$to_afl(), "a != 3")
expect_equal(B$left()$right()$to_afl(), "b != 4")
expect_equal(B$right()$to_afl(), "c != 5")
expect_equal(C$left()$to_afl(), "a != 3")
expect_equal(C$right()$to_afl(), "(b != 4) and (c != 5)")
expect_equal(C$right()$left()$to_afl(), "b != 4")
expect_equal(C$right()$right()$to_afl(), "c != 5")
})
test_that(echo("Anonymous predicate filters"), {
expect_equal(scidb::filter_to_afl(a = EQUALS(3)), "a = 3")
expect_equal(scidb::filter_to_afl(a = IN(c(3,4,5))), "((a = 3) or (a = 4)) or (a = 5)")
expect_equal(scidb::filter_to_afl(a = NOT_IN(c(3,4,5))), "((a != 3) and (a != 4)) and (a != 5)")
expect_equal(scidb::filter_to_afl(a = IS_NULL()), "is_null(a)")
expect_equal(scidb::filter_to_afl(a = NOT_NULL()), "not(is_null(a))")
expect_equal(scidb::filter_to_afl(a = NEQ(3)), "a != 3")
expect_equal(scidb::filter_to_afl(a = GEQ(3)), "a >= 3")
expect_equal(scidb::filter_to_afl(a = GT(3)), "a > 3")
expect_equal(scidb::filter_to_afl(a = LEQ(3)), "a <= 3")
expect_equal(scidb::filter_to_afl(a = LT(3)), "a < 3")
expect_equal(scidb::filter_to_afl(a = IN_RANGE(3,5)), "(a >= 3) and (a <= 5)")
expect_equal(scidb::filter_to_afl(a = IN_RANGE_INCL(3,5)), "(a >= 3) and (a <= 5)")
expect_equal(scidb::filter_to_afl(a = IN_RANGE_EXCL(3,5)), "(a > 3) and (a < 5)")
})
test_that(echo("Value substitution and symbol interpolation"), {
# Value substitution
value <- 3
expect_equal(scidb::filter_to_afl(a == !!value), "a = 3")
value <- c(3,4,5)
expect_equal(scidb::filter_to_afl(a %in% !!value), "((a = 3) or (a = 4)) or (a = 5)")
value <- "3"
expect_equal(scidb::filter_to_afl(a == !!value), "a = '3'")
# Symbol interpolation
variable <- "a"
# Style 1: !!rlang::sym() in expression
expect_equal(scidb::filter_to_afl(!!rlang::sym(variable) %in% !!value), "a = '3'")
# Style 2: !!key :=
expect_equal(scidb::filter_to_afl(!!variable := !!value), "a = '3'")
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.