diff --git a/CHANGELOG.md b/CHANGELOG.md index 62f6a2a..6048d28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Introduce preloaded hooks (gh-380). - Add `treegen` helper as a tree generator (gh-364). - Add support for declarative configuration to `server.lua` (gh-367). +- Make `assert_covers` recursive (gh-379). ## 1.0.1 diff --git a/luatest/assertions.lua b/luatest/assertions.lua index c61e1a6..842e705 100644 --- a/luatest/assertions.lua +++ b/luatest/assertions.lua @@ -411,15 +411,22 @@ function M.assert_items_include(actual, expected, message) end end -local function table_covers(actual, expected) - if type(actual) ~= 'table' or type(expected) ~= 'table' then - failure('Argument 1 and 2 must be tables', nil, 3) +local function table_slice(actual, expected) + if type(expected) ~= 'table' or type(actual) ~= 'table' then + return actual end local sliced = {} for k, _ in pairs(expected) do - sliced[k] = actual[k] + sliced[k] = table_slice(actual[k], expected[k]) end - return comparator.equals(sliced, expected) + return sliced +end + +local function table_covers(actual, expected) + if type(actual) ~= 'table' or type(expected) ~= 'table' then + failure('Argument 1 and 2 must be tables', nil, 3) + end + return comparator.equals(table_slice(actual, expected), expected) end --- Checks that actual map includes expected one. @@ -663,20 +670,6 @@ local function error_unpack(err) return unpacked end --- Return table with keys from expected but values from actual. Apply --- same changes recursively for key 'prev'. -local function error_slice(actual, expected) - if type(expected) ~= 'table' or type(actual) ~= 'table' then - return actual - end - local sliced = {} - for k, _ in pairs(expected) do - sliced[k] = actual[k] - end - sliced.prev = error_slice(sliced.prev, expected.prev) - return sliced -end - --- Checks that error raised by function is table that includes expected one. --- box.error is unpacked to convert to table. Stacked errors are supported. --- That is if there is prev field in expected then it should cover prev field @@ -693,7 +686,7 @@ function M.assert_error_covers(expected, fn, ...) prettystr(actual), prettystr(expected)) end local unpacked = error_unpack(actual) - if not comparator.equals(error_slice(unpacked, expected), expected) then + if not comparator.equals(table_slice(unpacked, expected), expected) then actual, expected = prettystr_pairs(unpacked, expected) fail_fmt(2, nil, 'Error expected: %s\nError received: %s', expected, actual) diff --git a/test/luatest_test.lua b/test/luatest_test.lua index 87a85f1..7db1ec8 100644 --- a/test/luatest_test.lua +++ b/test/luatest_test.lua @@ -114,6 +114,8 @@ g.test_assert_covers = function() subject({a = 1, b = 2, c = 3}, {a = 1}) subject({a = 1, b = 2, c = 3}, {a = 1, c = 3}) subject({a = 1, b = 2, c = 3}, {a = 1, b = 2, c = 3}) + subject({a = {b = 1, c = 2}}, {a = {b = 1}}) + subject({a = 1, b = {c = 2, d = {e = 3, f = 4}}}, {b = {d = {f = 4}}}) subject({a = box.NULL}, {a = box.NULL}) subject({a = box.tuple.new({1})}, {a = box.tuple.new({1})}) @@ -121,6 +123,8 @@ g.test_assert_covers = function() helper.assert_failure(subject, {a = 1, b = 2, c = 3}, {a = 1, b = 1}) helper.assert_failure(subject, {a = 1, b = 2, c = 3}, {a = 1, b = 2, c = 3, d = 4}) helper.assert_failure(subject, {a = 1, b = 2, c = 3}, {d = 1}) + helper.assert_failure(subject, {a = {b = 1, c = 2}}, {a = {b = 2, c = 2}}) + helper.assert_failure(subject, {a = {b = 1, c = 2}}, {a = {b = 1, c = 2, d = 3}}) helper.assert_failure(subject, {a = nil}, {a = box.NULL}) helper.assert_failure(subject, {a = box.tuple.new({1})}, {a = box.tuple.new({2})}) helper.assert_failure_contains('Argument 1 and 2 must be tables', subject, {a = 1, b = 2, c = 3}, nil)