1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
# frozen_string_literal: true
require "test_helper"
class ExpressionTest < Minitest::Test
def test_constant_literals
assert_equal(true, Liquid::C::Expression.strict_parse("true"))
assert_equal(false, Liquid::C::Expression.strict_parse("false"))
assert_nil(Liquid::C::Expression.strict_parse("nil"))
assert_nil(Liquid::C::Expression.strict_parse("null"))
empty = Liquid::C::Expression.strict_parse("empty")
assert_equal("", empty)
assert_same(empty, Liquid::C::Expression.strict_parse("blank"))
end
def test_push_literals
assert_nil(compile_and_eval("nil"))
assert_equal(true, compile_and_eval("true"))
assert_equal(false, compile_and_eval("false"))
end
def test_constant_integer
assert_equal(42, Liquid::C::Expression.strict_parse("42"))
end
def test_push_int8
assert_equal(127, compile_and_eval("127"))
assert_equal(-128, compile_and_eval("-128"))
end
def test_push_int16
assert_equal(128, compile_and_eval("128"))
assert_equal(-129, compile_and_eval("-129"))
assert_equal(32767, compile_and_eval("32767"))
assert_equal(-32768, compile_and_eval("-32768"))
end
def test_push_large_fixnum
assert_equal(32768, compile_and_eval("32768"))
assert_equal(-2147483648, compile_and_eval("-2147483648"))
assert_equal(2147483648, compile_and_eval("2147483648"))
assert_equal(4611686018427387903, compile_and_eval("4611686018427387903"))
end
def test_push_big_int
num = 1 << 128
assert_equal(num, compile_and_eval(num.to_s))
end
def test_float
assert_equal(123.4, Liquid::C::Expression.strict_parse("123.4"))
assert_equal(-1.5, compile_and_eval("-1.5"))
end
def test_string
assert_equal("hello", Liquid::C::Expression.strict_parse('"hello"'))
assert_equal("world", compile_and_eval("'world'"))
end
def test_find_static_variable
context = Liquid::Context.new({ "x" => 123 })
expr = Liquid::C::Expression.strict_parse("x")
assert_instance_of(Liquid::C::Expression, expr)
assert_equal(123, context.evaluate(expr))
end
def test_find_dynamic_variable
context = Liquid::Context.new({ "x" => "y", "y" => 42 })
expr = Liquid::C::Expression.strict_parse("[x]")
assert_equal(42, context.evaluate(expr))
end
def test_find_missing_variable
context = Liquid::Context.new({})
expr = Liquid::C::Expression.strict_parse("missing")
assert_nil(context.evaluate(expr))
context.strict_variables = true
assert_raises(Liquid::UndefinedVariable) do
context.evaluate(expr)
end
end
def test_lookup_const_key
context = Liquid::Context.new({ "obj" => { "prop" => "some value" } })
expr = Liquid::C::Expression.strict_parse("obj.prop")
assert_equal("some value", context.evaluate(expr))
expr = Liquid::C::Expression.strict_parse('obj["prop"]')
assert_equal("some value", context.evaluate(expr))
end
def test_lookup_variable_key
context = Liquid::Context.new({ "field_name" => "prop", "obj" => { "prop" => "another value" } })
expr = Liquid::C::Expression.strict_parse("obj[field_name]")
assert_equal("another value", context.evaluate(expr))
end
def test_lookup_command
context = Liquid::Context.new({ "ary" => ["a", "b", "c"] })
assert_equal(3, context.evaluate(Liquid::C::Expression.strict_parse("ary.size")))
assert_equal("a", context.evaluate(Liquid::C::Expression.strict_parse("ary.first")))
assert_equal("c", context.evaluate(Liquid::C::Expression.strict_parse("ary.last")))
end
def test_lookup_missing_key
context = Liquid::Context.new({ "obj" => {} })
expr = Liquid::C::Expression.strict_parse("obj.missing")
assert_nil(context.evaluate(expr))
context.strict_variables = true
assert_raises(Liquid::UndefinedVariable) do
context.evaluate(expr)
end
end
def test_lookup_on_var_with_literal_name
context = Liquid::Context.new({ "blank" => { "x" => "result" } })
assert_equal("result", context.evaluate(Liquid::C::Expression.strict_parse("blank.x")))
assert_equal("result", context.evaluate(Liquid::C::Expression.strict_parse('blank["x"]')))
end
def test_const_range
assert_equal((1..2), Liquid::C::Expression.strict_parse("(1..2)"))
end
def test_dynamic_range
context = Liquid::Context.new({ "var" => 42 })
expr = Liquid::C::Expression.strict_parse("(1..var)")
assert_instance_of(Liquid::C::Expression, expr)
assert_equal((1..42), context.evaluate(expr))
end
def test_disassemble
expression = Liquid::C::Expression.strict_parse("foo.bar[123]")
assert_equal(<<~ASM, expression.disassemble)
0x0000: find_static_var("foo")
0x0003: lookup_const_key("bar")
0x0006: push_int8(123)
0x0008: lookup_key
0x0009: leave
ASM
end
def test_disassemble_int16
assert_equal(<<~ASM, Liquid::C::Expression.strict_parse("[12345]").disassemble)
0x0000: push_int16(12345)
0x0003: find_var
0x0004: leave
ASM
end
def test_disable_c_nodes
context = Liquid::Context.new({ "x" => 123, "y" => { 123 => 42 } })
expr = Liquid::ParseContext.new.parse_expression("x")
assert_instance_of(Liquid::C::Expression, expr)
assert_equal(123, context.evaluate(expr))
expr = Liquid::ParseContext.new(disable_liquid_c_nodes: true).parse_expression("x")
assert_instance_of(Liquid::VariableLookup, expr)
assert_equal(123, context.evaluate(expr))
expr = Liquid::ParseContext.new(disable_liquid_c_nodes: true).parse_expression("y[x]")
assert_instance_of(Liquid::VariableLookup, expr)
assert_instance_of(Liquid::VariableLookup, expr.lookups.first)
assert_equal(42, context.evaluate(expr))
end
private
class ReturnKeyDrop < Liquid::Drop
def liquid_method_missing(key)
key
end
end
def compile_and_eval(source)
context = Liquid::Context.new({ "ret_key" => ReturnKeyDrop.new })
expr = Liquid::C::Expression.strict_parse("ret_key[#{source}]")
context.evaluate(expr)
end
end
|