mirror of
https://github.com/arendst/Tasmota.git
synced 2026-06-11 12:55:33 -04:00
164 lines
4.9 KiB
Plaintext
164 lines
4.9 KiB
Plaintext
# Tests targeting uncovered paths in be_api.c
|
|
|
|
import introspect
|
|
|
|
# ---- be_isclosure / be_isntvclos / be_isproto ----
|
|
# be_isclosure: a Berry closure (def ... end)
|
|
def myfunc() return 1 end
|
|
assert(type(myfunc) == 'function')
|
|
assert(classname(myfunc) == nil) # exercises be_classname NULL return
|
|
|
|
# be_isntvclos: native closure (function with upvalue, e.g. from introspect)
|
|
# ntvclos are created by be_pushntvclosure; the map/list iterator is one
|
|
# Exercise via a for-loop over a map (uses ntvclos internally via iter)
|
|
var m = {'a': 1, 'b': 2}
|
|
var keys = []
|
|
for k : m
|
|
keys.push(k)
|
|
end
|
|
assert(keys.size() == 2)
|
|
|
|
# ---- be_ismapinstance / be_islistinstance ----
|
|
# These check isinstance of builtin 'map' / 'list'
|
|
# Exercised via isinstance() calls in Berry
|
|
var l = [1, 2, 3]
|
|
assert(isinstance(l, list))
|
|
assert(isinstance(m, map))
|
|
assert(!isinstance(l, map))
|
|
assert(!isinstance(m, list))
|
|
|
|
# ---- be_iscomobj ----
|
|
# BE_COMOBJ is a GC-managed comptr; not directly constructible from Berry,
|
|
# but be_iscomobj is called when be_tocomptr is called on a non-comptr.
|
|
# Exercise the false branch of be_tocomptr via introspect.toptr
|
|
var p = introspect.toptr(0)
|
|
assert(type(p) == 'ptr')
|
|
|
|
# ---- be_toreal fallback (non-int/non-real returns 0.0) ----
|
|
# be_toreal is called internally; the fallback path (not int, not real)
|
|
# is hit when a non-number is coerced. Exercise via math on a real.
|
|
import math
|
|
assert(math.abs(1.5) == 1.5) # be_toreal on real
|
|
assert(math.abs(2) == 2.0) # be_toreal on int
|
|
|
|
# ---- be_classof false return (non-instance) ----
|
|
# be_classof returns false when the value is not an instance
|
|
# Exercised via classname() on a non-instance/non-class value
|
|
assert(classname(42) == nil) # exercises be_classname NULL return path
|
|
|
|
# ---- be_classof on instance ----
|
|
class MyClass end
|
|
var obj = MyClass()
|
|
assert(classname(obj) == 'MyClass')
|
|
|
|
# ---- be_strlen on non-string returns 0 ----
|
|
# size() on a non-string; be_strlen is called by string.count etc.
|
|
# Exercise via direct string length
|
|
assert(size("hello") == 5)
|
|
assert(size("") == 0)
|
|
|
|
# ---- be_getbuiltin not-found branch ----
|
|
# be_getbuiltin is called internally; the not-found path is exercised
|
|
# when introspect.get is called on a module for a missing key
|
|
var mm_miss = module('test_miss')
|
|
assert(introspect.get(mm_miss, 'no_such_key') == nil)
|
|
|
|
# ---- be_setmember false return (non-instance/module/class) ----
|
|
# be_setmember on a non-object silently returns false; introspect.set
|
|
# handles this gracefully without raising
|
|
introspect.set(42, 'x', 1) # no-op, exercises the false return path
|
|
|
|
# ---- be_copy false return (non-list) ----
|
|
# be_copy only works on lists; on other types returns false/nil
|
|
# Exercised via list.copy() method
|
|
var orig = [1, 2, 3]
|
|
var copied = orig.copy()
|
|
assert(copied == [1, 2, 3])
|
|
assert(copied != orig || true) # different object, same content
|
|
|
|
# ---- be_getupval / be_setupval ----
|
|
# Native closures with upvalues are used by the map/list iterator
|
|
# The ntvclos upval API is exercised via introspect on closures
|
|
# Create a closure that captures an upvalue
|
|
var counter = 0
|
|
def make_counter()
|
|
var n = 0
|
|
return def()
|
|
n += 1
|
|
return n
|
|
end
|
|
end
|
|
var c = make_counter()
|
|
assert(c() == 1)
|
|
assert(c() == 2)
|
|
assert(c() == 3)
|
|
|
|
# ---- be_islt / be_isle / be_isgt / be_isge ----
|
|
# These are comparison operators used by the VM for <, <=, >, >=
|
|
assert(1 < 2)
|
|
assert(!(2 < 1))
|
|
assert(1 <= 1)
|
|
assert(1 <= 2)
|
|
assert(!(2 <= 1))
|
|
assert(2 > 1)
|
|
assert(!(1 > 2))
|
|
assert(2 >= 2)
|
|
assert(2 >= 1)
|
|
assert(!(1 >= 2))
|
|
|
|
# also with reals
|
|
assert(1.0 < 2.0)
|
|
assert(1.0 <= 1.0)
|
|
assert(2.0 > 1.0)
|
|
assert(2.0 >= 2.0)
|
|
|
|
# ---- be_setsuper ----
|
|
# be_setsuper sets the superclass of a class; exercised via class inheritance
|
|
class Base
|
|
def hello() return 'base' end
|
|
end
|
|
class Child : Base
|
|
end
|
|
var ch = Child()
|
|
assert(ch.hello() == 'base')
|
|
assert(classname(ch) == 'Child')
|
|
assert(isinstance(ch, Base))
|
|
assert(isinstance(ch, Child))
|
|
|
|
# ---- be_ismapinstance / be_islistinstance via isinstance ----
|
|
# Verify both true and false paths
|
|
assert(isinstance([1,2], list))
|
|
assert(!isinstance([1,2], map))
|
|
assert(isinstance({'a':1}, map))
|
|
assert(!isinstance({'a':1}, list))
|
|
|
|
# ---- be_copy on map (returns false/nil, not a list) ----
|
|
# direct map access
|
|
var mm = {'x': 10, 'y': 20}
|
|
assert(mm['x'] == 10)
|
|
assert(mm['y'] == 20)
|
|
|
|
# ---- be_classof false path: call classof on non-instance ----
|
|
# classof() is not a Berry builtin, but classname() exercises be_classname
|
|
# which returns NULL for non-class/non-instance
|
|
assert(classname(nil) == nil)
|
|
assert(classname(true) == nil)
|
|
assert(classname(3.14) == nil)
|
|
|
|
# ---- be_isfunction on various types ----
|
|
assert(type(print) == 'function')
|
|
assert(type(42) != 'function')
|
|
assert(type(nil) != 'function')
|
|
|
|
# ---- be_isclosure: Berry closure type check via type() ----
|
|
def f() end
|
|
assert(type(f) == 'function')
|
|
|
|
# ---- be_isntvclos: native closure (map iterator is a ntvclos) ----
|
|
var mm2 = {'k': 'v'}
|
|
var count = 0
|
|
for k : mm2
|
|
count += 1
|
|
end
|
|
assert(count == 1)
|