From 9ece49c245da141c88537d8d5bc586732f15f9f1 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 19 Jun 2021 01:47:15 -0400 Subject: [PATCH 1/5] Add tests for enum attrs tables ipairs() currently fails due to dfhack/dfhack#1860 --- test/structures/enum_attrs.lua | 78 ++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 test/structures/enum_attrs.lua diff --git a/test/structures/enum_attrs.lua b/test/structures/enum_attrs.lua new file mode 100644 index 0000000000..c86461d58d --- /dev/null +++ b/test/structures/enum_attrs.lua @@ -0,0 +1,78 @@ +function test.getmetatable() + expect.eq(getmetatable(df.item_type.attrs), 'item_type.attrs') +end + +local function check_valid_attr_entry(enum_type, index) + local entry = enum_type.attrs[index] + local suffix = ('%s entry at index %s'):format(enum_type._attr_entry_type, index) + expect.ne(entry, nil, 'nil ' .. suffix) + expect.true_(enum_type._attr_entry_type:is_instance(entry), 'invalid ' .. suffix) +end + +function test.valid_items() + for i in ipairs(df.item_type) do + check_valid_attr_entry(df.item_type, i) + -- expect.true_(df.item_type.attrs[i]) + -- expect.true_(df.item_type._attr_entry_type:is_instance(df.item_type.attrs[i])) + end +end + +function test.valid_items_name() + for i, name in ipairs(df.item_type) do + expect.eq(df.item_type.attrs[i], df.item_type.attrs[name]) + end +end + +function test.valid_items_unique() + -- check that every enum item has its own attrs entry + local addr_to_name = {} + for _, name in ipairs(df.item_type) do + local _, addr = df.sizeof(df.item_type.attrs[name]) + if addr_to_name[addr] then + expect.fail(('attrs shared between "%s" and "%s"'):format(name, addr_to_name[name])) + else + addr_to_name[addr] = name + end + end +end + +function test.invalid_items() + check_valid_attr_entry(df.item_type, df.item_type._first_item - 1) + check_valid_attr_entry(df.item_type, df.item_type._last_item + 1) +end + +function test.invalid_items_shared() + expect.eq(df.item_type.attrs[df.item_type._first_item - 1], df.item_type.attrs[df.item_type._last_item + 1]) +end + +function test.length() + expect.eq(#df.item_type.attrs, 0) +end + +local function max_attrs_length(enum_type) + return enum_type._last_item - enum_type._first_item + 1 +end + +function test.pairs() + local i = 0 + for _ in pairs(df.item_type.attrs) do + i = i + 1 + if i > max_attrs_length(df.item_type) then + expect.fail('pairs() returned too many items: ' .. tostring(i)) + break + end + end + expect.eq(i, 0) +end + +function test.ipairs() + local i = 0 + for _ in ipairs(df.item_type.attrs) do + i = i + 1 + if i > max_attrs_length(df.item_type) then + expect.fail('ipairs() returned too many items: ' .. tostring(i)) + break + end + end + expect.eq(i, max_attrs_length(df.item_type)) +end From 7bb1cdce9c832bff34f1af7435286b8f38aa501a Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 19 Jun 2021 01:53:32 -0400 Subject: [PATCH 2/5] Also check start index of ipairs() --- test/structures/enum_attrs.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/structures/enum_attrs.lua b/test/structures/enum_attrs.lua index c86461d58d..9b67145529 100644 --- a/test/structures/enum_attrs.lua +++ b/test/structures/enum_attrs.lua @@ -67,7 +67,10 @@ end function test.ipairs() local i = 0 - for _ in ipairs(df.item_type.attrs) do + for index in ipairs(df.item_type.attrs) do + if i == 0 then + expect.eq(index, df.item_type._first_item, 'ipairs() returned wrong start index') + end i = i + 1 if i > max_attrs_length(df.item_type) then expect.fail('ipairs() returned too many items: ' .. tostring(i)) From dde88dd6c809534bfa216a8675b73041c1c148a1 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 19 Jun 2021 02:12:06 -0400 Subject: [PATCH 3/5] Implement an enum.attrs.__ipairs that returns the right number of elements All values are currently nil --- library/LuaWrapper.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/library/LuaWrapper.cpp b/library/LuaWrapper.cpp index 59bd967328..4ded768a75 100644 --- a/library/LuaWrapper.cpp +++ b/library/LuaWrapper.cpp @@ -1534,6 +1534,25 @@ static void FillEnumKeys(lua_State *state, int ix_meta, int ftable, enum_identit lua_pushcclosure(state, meta_enum_attr_index, 3); freeze_table(state, false, (eid->getFullName()+".attrs").c_str()); + int ix_attrs = lua_gettop(state); + + // add metamethods to metatable of .attrs + if (lua_getmetatable(state, ix_attrs)) + { + int ix_attrs_meta = lua_gettop(state); + + if (eid->getFirstItem() <= eid->getLastItem()) + { + lua_pushvalue(state, ix_attrs); + lua_pushinteger(state, eid->getFirstItem() - 1); + lua_pushinteger(state, eid->getLastItem()); + lua_pushcclosure(state, wtype_ipairs, 3); + lua_setfield(state, ix_attrs_meta, "__ipairs"); + } + + lua_pop(state, 1); // pop metatable + } + lua_setfield(state, ftable, "attrs"); } From d60ca796a3cd79a786d679e646d41aae24203bf0 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 19 Jun 2021 02:15:48 -0400 Subject: [PATCH 4/5] Catch incorrect attrs returned by ipairs() --- test/structures/enum_attrs.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/structures/enum_attrs.lua b/test/structures/enum_attrs.lua index 9b67145529..967d33c3b2 100644 --- a/test/structures/enum_attrs.lua +++ b/test/structures/enum_attrs.lua @@ -67,7 +67,7 @@ end function test.ipairs() local i = 0 - for index in ipairs(df.item_type.attrs) do + for index, value in ipairs(df.item_type.attrs) do if i == 0 then expect.eq(index, df.item_type._first_item, 'ipairs() returned wrong start index') end @@ -76,6 +76,8 @@ function test.ipairs() expect.fail('ipairs() returned too many items: ' .. tostring(i)) break end + expect.eq(value, df.item_type.attrs[i + df.item_type._first_item], + 'ipairs() returned incorrect attrs for item at index: ' .. tostring(index)) end expect.eq(i, max_attrs_length(df.item_type)) end From 6fc85a60e5a6d70f25fe5f29f008b5a8c94a3ac8 Mon Sep 17 00:00:00 2001 From: lethosor Date: Sat, 19 Jun 2021 02:24:47 -0400 Subject: [PATCH 5/5] Clean up, check first/last items explicitly --- test/structures/enum_attrs.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/structures/enum_attrs.lua b/test/structures/enum_attrs.lua index 967d33c3b2..ff1e28aee1 100644 --- a/test/structures/enum_attrs.lua +++ b/test/structures/enum_attrs.lua @@ -12,9 +12,9 @@ end function test.valid_items() for i in ipairs(df.item_type) do check_valid_attr_entry(df.item_type, i) - -- expect.true_(df.item_type.attrs[i]) - -- expect.true_(df.item_type._attr_entry_type:is_instance(df.item_type.attrs[i])) end + check_valid_attr_entry(df.item_type, df.item_type._first_item) + check_valid_attr_entry(df.item_type, df.item_type._last_item) end function test.valid_items_name() @@ -62,7 +62,7 @@ function test.pairs() break end end - expect.eq(i, 0) + expect.eq(i, 0, 'pairs() returned wrong number of items') end function test.ipairs() @@ -79,5 +79,5 @@ function test.ipairs() expect.eq(value, df.item_type.attrs[i + df.item_type._first_item], 'ipairs() returned incorrect attrs for item at index: ' .. tostring(index)) end - expect.eq(i, max_attrs_length(df.item_type)) + expect.eq(i, max_attrs_length(df.item_type), 'ipairs() returned wrong number of items') end