diff --git a/CHANGELOG.md b/CHANGELOG.md index efc5892..956c0b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Add alias `--no-capture` for the option `-c` (gh-391). - Fix reporting of an assertion failure in `Server:exec()` in case verbose error serialization is enabled in Tarantool (gh-376). +- Added `assert_items_exclude`. ## 1.0.1 diff --git a/README.rst b/README.rst index c99a245..183b2db 100644 --- a/README.rst +++ b/README.rst @@ -239,6 +239,9 @@ List of luatest functions +--------------------------------------------------------------------+-----------------------------------------------+ | ``assert_eval_to_true (value[, message])`` | Alias for assert. | +--------------------------------------------------------------------+-----------------------------------------------+ +| ``assert_items_exclude (actual, expected[, message])`` | Checks that one table does not include any | +| | items of another, irrespective of their keys. | ++--------------------------------------------------------------------+-----------------------------------------------+ | ``assert_items_include (actual, expected[, message])`` | Checks that one table includes all items of | | | another, irrespective of their keys. | +--------------------------------------------------------------------+-----------------------------------------------+ diff --git a/luatest/assertions.lua b/luatest/assertions.lua index 842e705..693eafa 100644 --- a/luatest/assertions.lua +++ b/luatest/assertions.lua @@ -411,6 +411,21 @@ function M.assert_items_include(actual, expected, message) end end +--- Checks that one table does not include any items of another, irrespective of their keys. +-- +-- @param actual +-- @param expected +-- @string[opt] message +function M.assert_items_exclude(actual, expected, message) + if type(actual) ~= 'table' or type(expected) ~= 'table' then + failure('Argument 1 and 2 must be tables', nil, 2) + end + if not comparator.are_disjoint(expected, actual) then + expected, actual = prettystr_pairs(expected, actual) + fail_fmt(2, message, 'Expected no item values from: %s\nTo be present in: %s', expected, actual) + end +end + local function table_slice(actual, expected) if type(expected) ~= 'table' or type(actual) ~= 'table' then return actual diff --git a/luatest/comparator.lua b/luatest/comparator.lua index 3377b45..699eee3 100644 --- a/luatest/comparator.lua +++ b/luatest/comparator.lua @@ -70,6 +70,23 @@ function comparator.is_subset(actual, expected) return #expected_array - found_count end +-- Returns false if 'actual' or 'expected' are not tables or their value sets +-- intersect. Returns true otherwise. +function comparator.are_disjoint(actual, expected) + if (type(actual) ~= 'table') or (type(expected) ~= 'table') then + return false + end + + for _, a in pairs(actual) do + for _, b in pairs(expected) do + if comparator.equals(a, b) then + return false + end + end + end + return true +end + -- This is a specialized metatable to help with the bookkeeping of recursions -- in table_equals(). It provides an __index table that implements utility -- functions for easier management of the table. The "cached" method queries diff --git a/test/luaunit/assertions_test.lua b/test/luaunit/assertions_test.lua index bdc1705..c82acb1 100644 --- a/test/luaunit/assertions_test.lua +++ b/test/luaunit/assertions_test.lua @@ -333,6 +333,39 @@ function g.test_assert_items_include() assert_failure(subject, {1,2,3}, {1,1,2,3}) end +function g.test_assert_items_exclude() + local subject = t.assert_items_exclude + assert_failure(subject, {1,2,3}, {3,1,2}) + assert_failure(subject, {one=1,two=2,three=3}, {two=2,one=1,three=3}) + assert_failure(subject, {one=1,two=2,three=3}, {a=1,b=2,c=3}) + assert_failure(subject, {1,2,three=3}, {3,1,two=2}) + + assert_failure(subject, {1,2,3,4}, {3,1,2}) + assert_failure(subject, {1,1,2,3}, {3,1,2}) + assert_failure(subject, {1,2,3}, {1,2,3,4}) + assert_failure(subject, {1,2,3}, {1,1,2,3}) + + assert_failure(subject, nil, {1}) + assert_failure(subject, {}, nil) + assert_failure(subject, 1, {1}) + assert_failure(subject, {}, 1) + assert_failure(subject, 'asd', {one = 'asd', two = 'dsa', three = 1}) + assert_failure(subject, {one = 'asd', two = 'dsa', three = 1}, 'dsa') + assert_failure(subject, 1, 1) + assert_failure(subject, nil, 1) + assert_failure(subject, 1, nil) + + subject({}, {1}) + subject({},{}) + subject({nil},{nil}) + subject({1},{}) + subject({one=1},{}) + subject({},{one=1}) + subject({1, 2, 3},{4, 5, 6, 7}) + subject({one=1, two=2, three=3},{four=4, five=5}) + subject({one=1, 2, 3},{four=4, 5}) +end + function g.test_assert_nan() assert_failure(t.assert_nan, "hi there!") assert_failure(t.assert_nan, nil)