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
(local l (require :test.luaunit))
(local fennel (require :fennel))
(local view (require :fennel.view))
(fn test-traceback []
(let [tracer (fennel.dofile "test/mod/tracer.fnl")
traceback (tracer)]
(l.assertStrContains traceback "tracer.fnl:4:")
(l.assertStrContains traceback "tracer.fnl:9:")))
(fn test-leak []
(l.assertFalse (pcall fennel.eval "(->1 1 (+ 4))" {:allowedGlobals false})
"Expected require-macros not leak into next evaluation."))
(fn test-runtime-quote []
(l.assertFalse (pcall fennel.eval "`(hey)" {:allowedGlobals false})
"Expected quoting lists to fail at runtime.")
(l.assertFalse (pcall fennel.eval "`[hey]" {:allowedGlobals false})
"Expected quoting syms to fail at runtime."))
(fn test-global-mangling []
(l.assertTrue (pcall fennel.eval "(.. hello-world :w)" {:env {:hello-world "hi"}})
"Expected global mangling to work."))
(fn test-include []
(let [expected "foo:FOO-1bar:BAR-2-BAZ-3"
(ok out) (pcall fennel.dofile "test/mod/foo.fnl")
(ok2 out2) (pcall fennel.dofile "test/mod/foo2.fnl"
{:requireAsIncluede true})]
(l.assertTrue ok "Expected foo to run")
(l.assertTrue ok2 "Expected foo2 to run")
(l.assertEquals (and (= :table (type out)) out.result) expected
(.. "Expected include to have result: " expected))
(l.assertFalse out.quux
"Expected include not to leak upvalues into included modules")
(l.assertEquals (view out) (view out2)
"Expected requireAsInclude to behave the same as include")
(l.assertNil _G.quux "Expected include to actually be local")
(let [spliceOk (pcall fennel.dofile "test/mod/splice.fnl")]
(l.assertTrue spliceOk "Expected splice to run")
(l.assertNil _G.q "Expected include to actually be local"))))
(fn test-env-iteration []
(local tbl [])
(local g {:hello-world "hi"
:pairs (fn [t] (local mt (getmetatable t))
(if (and mt mt.__pairs)
(mt.__pairs t)
(pairs t)))
:tbl tbl})
(set g._G g)
(fennel.eval "(each [k (pairs _G)] (tset tbl k true))" {:env g})
(l.assertTrue (. tbl "hello-world")
"Expected wrapped _G to support env iteration.")
(var (e k) [])
(fennel.eval "(global x-x 42)" {:env e})
(fennel.eval "x-x" {:env e})
(each [mangled (pairs e)]
(set k mangled))
(l.assertEquals (. e k) 42
"Expected mangled globals to be kept across eval invocations."))
(fn test-empty-values []
(l.assertTrue (fennel.eval
"(let [a (values)
b (values (values))
(c d) (values)
e (if (values) (values))
f (while (values) (values))
[g] [(values)]
{: h} {:h (values)}]
(not (or a b c d e f g h)))")
"empty (values) should resolve to nil")
(let [broken-code (fennel.compile "(local [x] (values)) (local {: y} (values))")]
(l.assertNotNil broken-code "code should compile")
(l.assertError broken-code "code should fail at runtime")))
(fn test-short-circuit []
(let [method-code "(var shorted? false)
(fn set-shorted! [] (set shorted? true) {:f! (fn [])})
(and false (: (set-shorted!) :f!))
shorted?"
comparator-code "(and false (< 1 (error :nein!) 3))"]
(l.assertFalse (fennel.eval method-code))
(l.assertFalse (fennel.eval comparator-code))))
{: test-empty-values
: test-env-iteration
: test-global-mangling
: test-include
: test-leak
: test-runtime-quote
: test-traceback
: test-short-circuit}