summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-stdlib/spec/std_spec.yaml
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-stdlib/spec/std_spec.yaml')
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/spec/std_spec.yaml444
1 files changed, 444 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/spec/std_spec.yaml b/Data/BuiltIn/Libraries/lua-stdlib/spec/std_spec.yaml
new file mode 100644
index 0000000..b747abf
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/spec/std_spec.yaml
@@ -0,0 +1,444 @@
+# General Lua Libraries for Lua 5.1, 5.2 & 5.3
+# Copyright (C) 2011-2018 stdlib authors
+
+before: |
+ this_module = 'std'
+ global_table = '_G'
+
+ exported_apis = {'assert', 'elems', 'eval', 'getmetamethod',
+ 'ielems', 'ipairs', 'npairs', 'pairs',
+ 'require', 'ripairs', 'rnpairs'}
+
+ -- Tables with iterator metamethods used by various examples.
+ __pairs = setmetatable({content='a string'}, {
+ __pairs = function(t)
+ return function(x, n)
+ if n < #x.content then
+ return n+1, string.sub(x.content, n+1, n+1)
+ end
+ end, t, 0
+ end,
+ })
+ __index = setmetatable({content='a string'}, {
+ __index = function(t, n)
+ if n <= #t.content then
+ return t.content:sub(n, n)
+ end
+ end,
+ __len = function(t)
+ return #t.content
+ end,
+ })
+
+ M = require(this_module)
+ M.version = nil -- previous specs may have autoloaded it
+
+
+specify std:
+- context when required:
+ - it does not touch the global table:
+ expect(show_apis {added_to=global_table, by=this_module}).
+ to_equal {}
+ - it exports the documented apis:
+ t = {}
+ for k in pairs(M) do
+ t[#t + 1] = k
+ end
+ expect(t).to_contain.a_permutation_of(exported_apis)
+
+- context when lazy loading:
+ - it has no submodules on initial load:
+ for _, v in pairs(M) do
+ expect(type(v)).not_to_be 'table'
+ end
+ - it loads submodules on demand:
+ lazy = M.math
+ expect(lazy).to_be(require 'std.math')
+ - it loads submodule functions on demand:
+ expect(M.math.round(3.141592)).to_be(3)
+
+- describe assert:
+ - before:
+ f = M.assert
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.assert(?any, ?string, ?any*)')
+
+ - context when it does not trigger:
+ - it has a truthy initial argument:
+ expect(f(1)).not_to_raise 'any error'
+ expect(f(true)).not_to_raise 'any error'
+ expect(f 'yes').not_to_raise 'any error'
+ expect(f(false == false)).not_to_raise 'any error'
+ - it returns the initial argument:
+ expect(f(1)).to_be(1)
+ expect(f(true)).to_be(true)
+ expect(f 'yes').to_be 'yes'
+ expect(f(false == false)).to_be(true)
+ - context when it triggers:
+ - it has a falsey initial argument:
+ expect(f()).to_raise()
+ expect(f(false)).to_raise()
+ expect(f(1 == 0)).to_raise()
+ - it throws an optional error string:
+ expect(f(false, 'ah boo')).to_raise 'ah boo'
+ - it plugs specifiers with string.format: |
+ expect(f(nil, '%s %d: %q', 'here', 42, 'a string')).
+ to_raise(string.format('%s %d: %q', 'here', 42, 'a string'))
+
+
+- describe elems:
+ - before:
+ f = M.elems
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.elems(table)')
+
+ - it is an iterator over table values:
+ t = {}
+ for e in f {'foo', bar='baz', 42} do
+ t[#t + 1] = e
+ end
+ expect(t).to_contain.a_permutation_of {'foo', 'baz', 42}
+ - it respects __pairs metamethod: |
+ t = {}
+ for v in f(__pairs) do
+ t[#t + 1] = v
+ end
+ expect(t).
+ to_contain.a_permutation_of {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'}
+ - it works for an empty list:
+ t = {}
+ for e in f {} do
+ t[#t + 1] = e
+ end
+ expect(t).to_equal {}
+
+
+- describe eval:
+ - before:
+ f = M.eval
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.eval(string)')
+
+ - it diagnoses invalid lua:
+ # Some internal error when eval tries to call uncompilable '=' code.
+ expect(f '=').to_raise()
+ - it evaluates a string of lua code:
+ expect(f 'math.min(2, 10)').to_be(math.min(2, 10))
+
+
+- describe getmetamethod:
+ - before:
+ f = M.getmetamethod
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.getmetamethod(?any, string)')
+
+ - context with a table:
+ - before:
+ method = function()
+ return 'called'
+ end
+ functor = setmetatable({}, {__call=method})
+ t = setmetatable({}, {
+ _type='table', _method=method, _functor=functor,
+ })
+ - it returns nil for missing metamethods:
+ expect(f(t, 'not a metamethod on t')).to_be(nil)
+ - it returns nil for non-callable metatable entries:
+ expect(f(t, '_type')).to_be(nil)
+ - it returns a method from the metatable:
+ expect(f(t, '_method')).to_be(method)
+ expect(f(t, '_method')()).to_be 'called'
+ - it returns a functor from the metatable:
+ expect(f(t, '_functor')).to_be(functor)
+ expect(f(t, '_functor')()).to_be 'called'
+
+
+- describe ielems:
+ - before:
+ f = M.ielems
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.ielems(table)')
+
+ - it is an iterator over integer-keyed table values:
+ t = {}
+ for e in f {'foo', 42} do
+ t[#t + 1] = e
+ end
+ expect(t).to_equal {'foo', 42}
+ - it ignores the dictionary part of a table:
+ t = {}
+ for e in f {'foo', 42; bar='baz', qux='quux'} do
+ t[#t + 1] = e
+ end
+ expect(t).to_equal {'foo', 42}
+ - it respects __len metamethod:
+ t = {}
+ for v in f(__index) do
+ t[#t + 1] = v
+ end
+ expect(t).to_equal {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'}
+ - it works for an empty list:
+ t = {}
+ for e in f {} do
+ t[#t + 1] = e
+ end
+ expect(t).to_equal {}
+
+
+- describe ipairs:
+ - before:
+ f = M.ipairs
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.ipairs(table)')
+
+ - it is an iterator over integer-keyed table values:
+ t = {}
+ for i, v in f {'foo', 42} do
+ t[i] = v
+ end
+ expect(t).to_equal {'foo', 42}
+ - it ignores the dictionary part of a table:
+ t = {}
+ for i, v in f {'foo', 42; bar='baz', qux='quux'} do
+ t[i] = v
+ end
+ expect(t).to_equal {'foo', 42}
+ - it respects __len metamethod:
+ t = {}
+ for k, v in f(__index) do
+ t[k] = v
+ end
+ expect(t).to_equal {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'}
+ - it works for an empty list:
+ t = {}
+ for i, v in f {} do
+ t[i] = v
+ end
+ expect(t).to_equal {}
+
+
+- describe npairs:
+ - before:
+ f = M.npairs
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.npairs(table)')
+
+ - it is an iterator over integer-keyed table values:
+ t = {}
+ for i, v in f {'foo', 42, nil, nil, 'five'} do
+ t[i] = v
+ end
+ expect(t).to_equal {'foo', 42, nil, nil, 'five'}
+ - it ignores the dictionary part of a table:
+ t = {}
+ for i, v in f {'foo', 42, nil, nil, 'five'; bar='baz', qux='quux'} do
+ t[i] = v
+ end
+ expect(t).to_equal {'foo', 42, nil, nil, 'five'}
+ - it respects __len metamethod:
+ t = {}
+ for _, v in f(setmetatable({[2]=false}, {__len=function(self) return 4 end})) do
+ t[#t + 1] = tostring(v)
+ end
+ expect(table.concat(t, ',')).to_be 'nil,false,nil,nil'
+ - it works for an empty list:
+ t = {}
+ for i, v in f {} do
+ t[i] = v
+ end
+ expect(t).to_equal {}
+
+
+- describe pairs:
+ - before:
+ f = M.pairs
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.pairs(table)')
+
+ - it is an iterator over all table values:
+ t = {}
+ for k, v in f {'foo', bar='baz', 42} do
+ t[k] = v
+ end
+ expect(t).to_equal {'foo', bar='baz', 42}
+ - it respects __pairs metamethod: |
+ t = {}
+ for k, v in f(__pairs) do
+ t[k] = v
+ end
+ expect(t).
+ to_contain.a_permutation_of {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'}
+ - it works for an empty list:
+ t = {}
+ for k, v in f {} do
+ t[k] = v
+ end
+ expect(t).to_equal {}
+
+
+- describe require:
+ - before:
+ f = M.require
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.require(string, ?string, ?string, ?string)')
+
+ - it diagnoses non-existent module:
+ expect(f('module-not-exists', '', '')).to_raise 'module-not-exists'
+ - it diagnoses module too old:
+ expect(f('std', '9999', '9999')).
+ to_raise "require 'std' with at least version 9999,"
+ - it diagnoses module too new:
+ expect(f('std', '0', '0')).
+ to_raise "require 'std' with version less than 0,"
+ - context when the module version is compatible:
+ - it returns the module table:
+ expect(f('std', '0', '9999')).to_be(require 'std')
+ - it places no upper bound by default:
+ expect(f('std', '0')).to_be(require 'std')
+ - it places no lower bound by default:
+ expect(f 'std').to_be(require 'std')
+ - it uses _VERSION when version field is nil:
+ expect(luaproc [[
+ package.loaded['poop'] = {_VERSION='41.1'}
+ f = require 'std'.require
+ print(f('poop', '41', '9999')._VERSION)
+ ]]).to_succeed_with '41.1\n'
+ - context with semantic versioning:
+ - before:
+ std = require 'std'
+ ver = std.version
+ std.version = '1.2.3'
+ - after:
+ std.version = ver
+ - it diagnoses module too old:
+ expect(f('std', '1.2.4')).
+ to_raise "require 'std' with at least version 1.2.4,"
+ expect(f('std', '1.3')).
+ to_raise "require 'std' with at least version 1.3,"
+ expect(f('std', '2.1.2')).
+ to_raise "require 'std' with at least version 2.1.2,"
+ expect(f('std', '2')).
+ to_raise "require 'std' with at least version 2,"
+ expect(f('std', '1.2.10')).
+ to_raise "require 'std' with at least version 1.2.10,"
+ - it diagnoses module too new:
+ expect(f('std', nil, '1.2.2')).
+ to_raise "require 'std' with version less than 1.2.2,"
+ expect(f('std', nil, '1.1')).
+ to_raise "require 'std' with version less than 1.1,"
+ expect(f('std', nil, '1.1.2')).
+ to_raise "require 'std' with version less than 1.1.2,"
+ expect(f('std', nil, '1')).
+ to_raise "require 'std' with version less than 1,"
+ - it returns modules with version in range:
+ expect(f('std')).to_be(std)
+ expect(f('std', '1')).to_be(std)
+ expect(f('std', '1.2.3')).to_be(std)
+ expect(f('std', nil, '2')).to_be(std)
+ expect(f('std', nil, '1.3')).to_be(std)
+ expect(f('std', nil, '1.2.10')).to_be(std)
+ expect(f('std', '1.2.3', '1.2.4')).to_be(std)
+ - context with several numbers in version string:
+ - before:
+ std = require 'std'
+ ver = std.version
+ std.version = 'standard library for Lua 5.3 / 41.0.0'
+ - after:
+ std.version = ver
+ - it diagnoses module too old:
+ expect(f('std', '42')).to_raise()
+ - it diagnoses module too new:
+ expect(f('std', nil, '40')).to_raise()
+ - it returns modules with version in range:
+ expect(f('std')).to_be(std)
+ expect(f('std', '1')).to_be(std)
+ expect(f('std', '41')).to_be(std)
+ expect(f('std', nil, '42')).to_be(std)
+ expect(f('std', '41', '42')).to_be(std)
+
+
+- describe ripairs:
+ - before:
+ f = M.ripairs
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.ripairs(table)')
+
+ - it returns a function, the table and a number:
+ fn, t, i = f {1, 2, 3}
+ expect({type(fn), t, type(i)}).to_equal {'function', {1, 2, 3}, 'number'}
+ - it iterates over the array part of a table:
+ t, u = {1, 2, 3; a=4, b=5, c=6}, {}
+ for i, v in f(t) do
+ u[i] = v
+ end
+ expect(u).to_equal {1, 2, 3}
+ - it returns elements in reverse order:
+ t, u = {'one', 'two', 'five'}, {}
+ for _, v in f(t) do
+ u[#u + 1] = v
+ end
+ expect(u).to_equal {'five', 'two', 'one'}
+ - it respects __len metamethod:
+ t = {}
+ for i, v in f(__index) do
+ t[i] = v
+ end
+ expect(t).to_equal {'a', ' ', 's', 't', 'r', 'i', 'n', 'g'}
+ t = {}
+ for _, v in f(__index) do
+ t[#t + 1] = v
+ end
+ expect(t).to_equal {'g', 'n', 'i', 'r', 't', 's', ' ', 'a'}
+ - it works with the empty list:
+ t = {}
+ for k, v in f {} do
+ t[k] = v
+ end
+ expect(t).to_equal {}
+
+
+- describe rnpairs:
+ - before:
+ f = M.rnpairs
+
+ - context with bad arguments:
+ badargs.diagnose(f, 'std.rnpairs(table)')
+
+ - it returns a function, the table and a number:
+ fn, t, i = f {1, 2, nil, nil, 3}
+ expect({type(fn), t, type(i)}).
+ to_equal {'function', {1, 2, nil, nil, 3}, 'number'}
+ - it iterates over the array part of a table:
+ t, u = {1, 2, nil, nil, 3; a=4, b=5, c=6}, {}
+ for i, v in f(t) do
+ u[i] = v
+ end
+ expect(u).to_equal {1, 2, nil, nil, 3}
+ - it returns elements in reverse order:
+ t, u, i = {'one', 'two', nil, nil, 'five'}, {}, 1
+ for _, v in f(t) do
+ u[i], i = v, i + 1
+ end
+ expect(u).to_equal {'five', nil, nil, 'two', 'one'}
+ - it respects __len metamethod:
+ t = {}
+ for _, v in f(setmetatable({[2]=false}, {__len=function(self) return 4 end})) do
+ t[#t + 1] = tostring(v)
+ end
+ expect(table.concat(t, ',')).to_be 'nil,nil,false,nil'
+ - it works with the empty list:
+ t = {}
+ for k, v in f {} do
+ t[k] = v
+ end
+ expect(t).to_equal {}