Skip to content

Commit 062a410

Browse files
committed
test: expand LuaRef/TableItem coverage — symmetry, hash contract, move semantics, moveTo variants
1 parent 380e063 commit 062a410

1 file changed

Lines changed: 208 additions & 1 deletion

File tree

‎Tests/Source/LuaRefTests.cpp‎

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1697,8 +1697,215 @@ TEST_F(LuaRefTests, TableItemIsValid)
16971697
auto item2 = result()[dynKey];
16981698
EXPECT_TRUE(item2.isValid());
16991699

1700-
// Moved-from TableItem is invalid
1700+
// After move: target is valid, source is invalid
17011701
auto moved = std::move(item2);
17021702
EXPECT_TRUE(moved.isValid());
17031703
EXPECT_FALSE(item2.isValid());
1704+
1705+
// Copy-constructed and copy-assigned TableItems are valid
1706+
auto copied = item;
1707+
EXPECT_TRUE(item.isValid());
1708+
EXPECT_TRUE(copied.isValid());
1709+
}
1710+
1711+
// --- NonMemberComparison additional coverage ---
1712+
1713+
TEST_F(LuaRefTests, NonMemberComparisonStrings)
1714+
{
1715+
luabridge::LuaRef hello(L, "hello");
1716+
luabridge::LuaRef world(L, "world");
1717+
1718+
// "hello" < "world" lexicographically
1719+
EXPECT_TRUE(std::string("hello") < world);
1720+
EXPECT_TRUE(std::string("hello") <= world);
1721+
EXPECT_FALSE(std::string("hello") > world);
1722+
EXPECT_FALSE(std::string("hello") >= world);
1723+
1724+
// Equal string values
1725+
EXPECT_FALSE(std::string("hello") < hello);
1726+
EXPECT_TRUE(std::string("hello") <= hello);
1727+
EXPECT_FALSE(std::string("hello") > hello);
1728+
EXPECT_TRUE(std::string("hello") >= hello);
1729+
1730+
EXPECT_FALSE(std::string("world") < world);
1731+
EXPECT_TRUE(std::string("world") <= world);
1732+
EXPECT_FALSE(std::string("world") > world);
1733+
EXPECT_TRUE(std::string("world") >= world);
1734+
}
1735+
1736+
TEST_F(LuaRefTests, NonMemberComparisonSymmetry)
1737+
{
1738+
luabridge::LuaRef seven(L, 7);
1739+
luabridge::LuaRef eight(L, 8);
1740+
1741+
// (T op LuaRef) must produce the same answer as (LuaRef reverse-op T)
1742+
EXPECT_EQ((7 < eight), static_cast<bool>(eight > 7));
1743+
EXPECT_EQ((7 <= eight), static_cast<bool>(eight >= 7));
1744+
EXPECT_EQ((8 > seven), static_cast<bool>(seven < 8));
1745+
EXPECT_EQ((8 >= seven), static_cast<bool>(seven <= 8));
1746+
1747+
// Equal values
1748+
EXPECT_EQ((7 < seven), static_cast<bool>(seven > 7));
1749+
EXPECT_EQ((7 <= seven), static_cast<bool>(seven >= 7));
1750+
EXPECT_EQ((7 > seven), static_cast<bool>(seven < 7));
1751+
EXPECT_EQ((7 >= seven), static_cast<bool>(seven <= 7));
1752+
}
1753+
1754+
TEST_F(LuaRefTests, NonMemberEqualityAndInequality)
1755+
{
1756+
luabridge::LuaRef seven(L, 7);
1757+
luabridge::LuaRef eight(L, 8);
1758+
1759+
EXPECT_TRUE(7 == seven);
1760+
EXPECT_FALSE(7 == eight);
1761+
EXPECT_FALSE(8 == seven);
1762+
EXPECT_TRUE(8 == eight);
1763+
1764+
EXPECT_FALSE(7 != seven);
1765+
EXPECT_TRUE(7 != eight);
1766+
}
1767+
1768+
// --- Hash additional coverage ---
1769+
1770+
TEST_F(LuaRefTests, HashBooleans)
1771+
{
1772+
luabridge::LuaRef t1(L, true);
1773+
luabridge::LuaRef t2(L, true);
1774+
luabridge::LuaRef f1(L, false);
1775+
1776+
EXPECT_EQ(t1.hash(), t2.hash());
1777+
EXPECT_NE(t1.hash(), f1.hash());
1778+
}
1779+
1780+
TEST_F(LuaRefTests, HashNumbers)
1781+
{
1782+
luabridge::LuaRef a(L, 42);
1783+
luabridge::LuaRef b(L, 42);
1784+
luabridge::LuaRef c(L, 43);
1785+
1786+
EXPECT_EQ(a.hash(), b.hash());
1787+
EXPECT_NE(a.hash(), c.hash());
1788+
}
1789+
1790+
TEST_F(LuaRefTests, HashDistinctTablesDistinct)
1791+
{
1792+
runLua("hashT1 = {}; hashT2 = {}");
1793+
auto t1 = luabridge::getGlobal(L, "hashT1");
1794+
auto t2 = luabridge::getGlobal(L, "hashT2");
1795+
1796+
EXPECT_FALSE(t1 == t2);
1797+
EXPECT_NE(t1.hash(), t2.hash());
1798+
}
1799+
1800+
TEST_F(LuaRefTests, HashUsableInUnorderedMap)
1801+
{
1802+
std::unordered_map<luabridge::LuaRef, int> map;
1803+
1804+
luabridge::LuaRef key1(L, "mapkey1");
1805+
luabridge::LuaRef key2(L, "mapkey2");
1806+
1807+
map[key1] = 100;
1808+
map[key2] = 200;
1809+
1810+
luabridge::LuaRef key1Copy(L, "mapkey1");
1811+
EXPECT_EQ(100, map.at(key1Copy));
1812+
EXPECT_EQ(200, map.at(key2));
1813+
}
1814+
1815+
// --- TableItem copy/move additional coverage ---
1816+
1817+
TEST_F(LuaRefTests, TableItemCopyAssignmentSelfAssign)
1818+
{
1819+
runLua("result = { a = 42 }");
1820+
auto item = result()["a"];
1821+
EXPECT_TRUE(item.isValid());
1822+
1823+
#if __clang__
1824+
#pragma clang diagnostic push
1825+
#pragma clang diagnostic ignored "-Wself-assign-overloaded"
1826+
#endif
1827+
item = item;
1828+
#if __clang__
1829+
#pragma clang diagnostic pop
1830+
#endif
1831+
1832+
EXPECT_TRUE(item.isValid());
1833+
EXPECT_EQ(42, item.unsafe_cast<int>());
1834+
}
1835+
1836+
TEST_F(LuaRefTests, TableItemCopyAssignmentSharesSlot)
1837+
{
1838+
// After b = a, b proxies the same table slot as a.
1839+
// Writing through b must also be visible when reading through a.
1840+
runLua("result = { a = 1, b = 2 }");
1841+
auto table = result();
1842+
1843+
auto a = table["a"];
1844+
auto b = table["b"];
1845+
1846+
b = a;
1847+
EXPECT_EQ(1, luabridge::LuaRef(b).unsafe_cast<int>());
1848+
1849+
b = 99;
1850+
EXPECT_EQ(99, table["a"].unsafe_cast<int>());
1851+
EXPECT_EQ(99, luabridge::LuaRef(a).unsafe_cast<int>());
1852+
}
1853+
1854+
TEST_F(LuaRefTests, TableItemMovedFromDestructible)
1855+
{
1856+
runLua("result = { key = 1 }");
1857+
auto item = result()["key"];
1858+
1859+
auto moved = std::move(item);
1860+
1861+
EXPECT_FALSE(item.isValid());
1862+
EXPECT_TRUE(moved.isValid());
1863+
// item goes out of scope here — must not double-unref or crash
1864+
}
1865+
1866+
TEST_F(LuaRefTests, TableItemMoveAssignReleasesOldRefs)
1867+
{
1868+
runLua("result = { a = 10, b = 20 }");
1869+
auto a = result()["a"];
1870+
auto b = result()["b"];
1871+
1872+
b = std::move(a);
1873+
1874+
EXPECT_FALSE(a.isValid());
1875+
EXPECT_TRUE(b.isValid());
1876+
EXPECT_EQ(10, luabridge::LuaRef(b).unsafe_cast<int>());
1877+
}
1878+
1879+
// --- moveTo() additional coverage ---
1880+
1881+
TEST_F(LuaRefTests, MoveToTransfersString)
1882+
{
1883+
runLua("result = 'hello'");
1884+
luabridge::LuaRef ref = result();
1885+
EXPECT_TRUE(ref.isString());
1886+
1887+
lua_State* thread = lua_newthread(L);
1888+
const int threadTop = lua_gettop(thread);
1889+
1890+
ref.moveTo(thread);
1891+
1892+
EXPECT_EQ(threadTop, lua_gettop(thread));
1893+
EXPECT_TRUE(ref.isString());
1894+
EXPECT_EQ("hello", ref.cast<std::string>().valueOr(""));
1895+
}
1896+
1897+
TEST_F(LuaRefTests, MoveToNilRef)
1898+
{
1899+
luabridge::LuaRef nilRef(L, luabridge::LuaNil());
1900+
EXPECT_TRUE(nilRef.isNil());
1901+
1902+
lua_State* thread = lua_newthread(L);
1903+
const int mainTop = lua_gettop(L);
1904+
const int threadTop = lua_gettop(thread);
1905+
1906+
nilRef.moveTo(thread);
1907+
1908+
EXPECT_EQ(mainTop, lua_gettop(L));
1909+
EXPECT_EQ(threadTop, lua_gettop(thread));
1910+
EXPECT_TRUE(nilRef.isNil());
17041911
}

0 commit comments

Comments
 (0)