Skip to content

Commit a99bfd1

Browse files
authored
Merge pull request #9232 from aschwaighofer/more_tests_for_assignWith_witnesses
2 parents f5c9ee3 + 3564733 commit a99bfd1

File tree

1 file changed

+243
-34
lines changed

1 file changed

+243
-34
lines changed

unittests/runtime/Metadata.cpp

Lines changed: 243 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "swift/Runtime/Metadata.h"
1413
#include "swift/Runtime/Concurrent.h"
14+
#include "swift/Runtime/HeapObject.h"
15+
#include "swift/Runtime/Metadata.h"
1516
#include "gtest/gtest.h"
1617
#include <iterator>
1718
#include <functional>
@@ -1120,13 +1121,7 @@ TEST(WitnessTableTest, getGenericWitnessTable) {
11201121
}
11211122
}
11221123

1123-
TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod) {
1124-
auto any =
1125-
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1126-
/*superclass=*/nullptr, 0, nullptr);
1127-
auto anyVWT = any->getValueWitnesses();
1128-
1129-
ValueWitnessTable testTable;
1124+
static void initialize_pod_witness_table(ValueWitnessTable &testTable) {
11301125
testTable.size = sizeof(ValueBuffer);
11311126
testTable.flags = ValueWitnessFlags()
11321127
.withAlignment(alignof(ValueBuffer))
@@ -1135,19 +1130,22 @@ TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod) {
11351130
.withInlineStorage(true);
11361131
testTable.stride = sizeof(ValueBuffer);
11371132
installCommonValueWitnesses(&testTable);
1133+
}
1134+
1135+
TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod) {
1136+
auto any =
1137+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1138+
/*superclass=*/nullptr, 0, nullptr);
1139+
auto anyVWT = any->getValueWitnesses();
1140+
1141+
ValueWitnessTable testTable;
1142+
initialize_pod_witness_table(testTable);
11381143
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
11391144
Metadata *metadata = &testMetadata.base;
11401145

11411146
ValueWitnessTable testTable2;
1142-
testTable2.size = sizeof(ValueBuffer);
1143-
testTable2.flags = ValueWitnessFlags()
1144-
.withAlignment(alignof(ValueBuffer))
1145-
.withPOD(true)
1146-
.withBitwiseTakable(true)
1147-
.withInlineStorage(true);
1148-
testTable2.stride = sizeof(ValueBuffer);
1149-
installCommonValueWitnesses(&testTable2);
1150-
FullOpaqueMetadata testMetadata2 = {{&testTable}, {{MetadataKind::Opaque}}};
1147+
initialize_pod_witness_table(testTable2);
1148+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
11511149
Metadata *metadata2 = &testMetadata2.base;
11521150

11531151
void *zeroPtr = nullptr;
@@ -1175,27 +1173,13 @@ TEST(TestOpaqueExistentialBox, test_assignWithTake_pod) {
11751173
auto anyVWT = any->getValueWitnesses();
11761174

11771175
ValueWitnessTable testTable;
1178-
testTable.size = sizeof(ValueBuffer);
1179-
testTable.flags = ValueWitnessFlags()
1180-
.withAlignment(alignof(ValueBuffer))
1181-
.withPOD(true)
1182-
.withBitwiseTakable(true)
1183-
.withInlineStorage(true);
1184-
testTable.stride = sizeof(ValueBuffer);
1185-
installCommonValueWitnesses(&testTable);
1176+
initialize_pod_witness_table(testTable);
11861177
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
11871178
Metadata *metadata = &testMetadata.base;
11881179

11891180
ValueWitnessTable testTable2;
1190-
testTable2.size = sizeof(ValueBuffer);
1191-
testTable2.flags = ValueWitnessFlags()
1192-
.withAlignment(alignof(ValueBuffer))
1193-
.withPOD(true)
1194-
.withBitwiseTakable(true)
1195-
.withInlineStorage(true);
1196-
testTable2.stride = sizeof(ValueBuffer);
1197-
installCommonValueWitnesses(&testTable2);
1198-
FullOpaqueMetadata testMetadata2 = {{&testTable}, {{MetadataKind::Opaque}}};
1181+
initialize_pod_witness_table(testTable2);
1182+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
11991183
Metadata *metadata2 = &testMetadata2.base;
12001184

12011185
void *zeroPtr = nullptr;
@@ -1215,3 +1199,228 @@ TEST(TestOpaqueExistentialBox, test_assignWithTake_pod) {
12151199
EXPECT_EQ(existBox.buffer.PrivateData[1], otherPtr);
12161200
EXPECT_EQ(existBox.buffer.PrivateData[2], zeroPtr);
12171201
}
1202+
1203+
static void initialize_indirect_witness_table(ValueWitnessTable &testTable) {
1204+
testTable.size = sizeof(ValueBuffer) + 1;
1205+
testTable.flags = ValueWitnessFlags()
1206+
.withAlignment(alignof(ValueBuffer))
1207+
.withPOD(true)
1208+
.withBitwiseTakable(true)
1209+
.withInlineStorage(false);
1210+
testTable.stride = sizeof(ValueBuffer) + 1;
1211+
installCommonValueWitnesses(&testTable);
1212+
}
1213+
1214+
TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_indirect) {
1215+
auto any =
1216+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1217+
/*superclass=*/nullptr, 0, nullptr);
1218+
auto anyVWT = any->getValueWitnesses();
1219+
1220+
ValueWitnessTable testTable;
1221+
initialize_indirect_witness_table(testTable);
1222+
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
1223+
Metadata *metadata = &testMetadata.base;
1224+
1225+
ValueWitnessTable testTable2;
1226+
initialize_indirect_witness_table(testTable2);
1227+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
1228+
Metadata *metadata2 = &testMetadata2.base;
1229+
1230+
void *zeroPtr = nullptr;
1231+
auto refAndObjectAddr = BoxPair(swift_allocBox(metadata));
1232+
swift_retain(refAndObjectAddr.first);
1233+
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
1234+
struct {
1235+
ValueBuffer buffer;
1236+
Metadata *type;
1237+
uintptr_t canary;
1238+
} existBox{{{refAndObjectAddr.first, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
1239+
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
1240+
1241+
anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
1242+
reinterpret_cast<OpaqueValue *>(&existBox2), any);
1243+
1244+
EXPECT_EQ(existBox.type, metadata2);
1245+
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
1246+
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
1247+
EXPECT_EQ(swift_retainCount(refAndObjectAddr.first), 1);
1248+
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2);
1249+
}
1250+
1251+
TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_indirect) {
1252+
auto any =
1253+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1254+
/*superclass=*/nullptr, 0, nullptr);
1255+
auto anyVWT = any->getValueWitnesses();
1256+
1257+
ValueWitnessTable testTable;
1258+
initialize_indirect_witness_table(testTable);
1259+
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
1260+
Metadata *metadata = &testMetadata.base;
1261+
1262+
ValueWitnessTable testTable2;
1263+
initialize_indirect_witness_table(testTable2);
1264+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
1265+
Metadata *metadata2 = &testMetadata2.base;
1266+
1267+
void *zeroPtr = nullptr;
1268+
auto refAndObjectAddr = BoxPair(swift_allocBox(metadata));
1269+
swift_retain(refAndObjectAddr.first);
1270+
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
1271+
struct {
1272+
ValueBuffer buffer;
1273+
Metadata *type;
1274+
uintptr_t canary;
1275+
} existBox{{{refAndObjectAddr.first, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
1276+
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
1277+
1278+
anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
1279+
reinterpret_cast<OpaqueValue *>(&existBox2), any);
1280+
1281+
EXPECT_EQ(existBox.type, metadata2);
1282+
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
1283+
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
1284+
EXPECT_EQ(swift_retainCount(refAndObjectAddr.first), 1);
1285+
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1);
1286+
}
1287+
1288+
TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod_indirect) {
1289+
auto any =
1290+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1291+
/*superclass=*/nullptr, 0, nullptr);
1292+
auto anyVWT = any->getValueWitnesses();
1293+
1294+
ValueWitnessTable testTable;
1295+
initialize_pod_witness_table(testTable);
1296+
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
1297+
Metadata *metadata = &testMetadata.base;
1298+
1299+
ValueWitnessTable testTable2;
1300+
initialize_indirect_witness_table(testTable2);
1301+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
1302+
Metadata *metadata2 = &testMetadata2.base;
1303+
1304+
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
1305+
struct {
1306+
ValueBuffer buffer;
1307+
Metadata *type;
1308+
uintptr_t canary;
1309+
} existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
1310+
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
1311+
1312+
anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
1313+
reinterpret_cast<OpaqueValue *>(&existBox2), any);
1314+
1315+
EXPECT_EQ(existBox.type, metadata2);
1316+
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
1317+
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
1318+
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2);
1319+
}
1320+
1321+
TEST(TestOpaqueExistentialBox, test_assignWithTake_pod_indirect) {
1322+
auto any =
1323+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1324+
/*superclass=*/nullptr, 0, nullptr);
1325+
auto anyVWT = any->getValueWitnesses();
1326+
1327+
ValueWitnessTable testTable;
1328+
initialize_pod_witness_table(testTable);
1329+
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
1330+
Metadata *metadata = &testMetadata.base;
1331+
1332+
ValueWitnessTable testTable2;
1333+
initialize_indirect_witness_table(testTable2);
1334+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
1335+
Metadata *metadata2 = &testMetadata2.base;
1336+
1337+
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
1338+
struct {
1339+
ValueBuffer buffer;
1340+
Metadata *type;
1341+
uintptr_t canary;
1342+
} existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
1343+
existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
1344+
1345+
anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
1346+
reinterpret_cast<OpaqueValue *>(&existBox2), any);
1347+
1348+
EXPECT_EQ(existBox.type, metadata2);
1349+
EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
1350+
EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
1351+
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1);
1352+
}
1353+
1354+
TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_pod) {
1355+
auto any =
1356+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1357+
/*superclass=*/nullptr, 0, nullptr);
1358+
auto anyVWT = any->getValueWitnesses();
1359+
1360+
ValueWitnessTable testTable;
1361+
initialize_pod_witness_table(testTable);
1362+
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
1363+
Metadata *metadata = &testMetadata.base;
1364+
1365+
ValueWitnessTable testTable2;
1366+
initialize_indirect_witness_table(testTable2);
1367+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
1368+
Metadata *metadata2 = &testMetadata2.base;
1369+
1370+
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
1371+
void *someAddr = &anyVWT;
1372+
swift_retain(refAndObjectAddr2.first);
1373+
struct {
1374+
ValueBuffer buffer;
1375+
Metadata *type;
1376+
uintptr_t canary;
1377+
} existBox2{{{someAddr, nullptr, someAddr}}, metadata, 0x5A5A5A5AU},
1378+
existBox{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
1379+
1380+
anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
1381+
reinterpret_cast<OpaqueValue *>(&existBox2), any);
1382+
1383+
EXPECT_EQ(existBox.type, metadata);
1384+
EXPECT_EQ(existBox.canary, 0xB5A5A5A5U);
1385+
EXPECT_EQ(existBox.buffer.PrivateData[0], someAddr);
1386+
EXPECT_EQ(existBox.buffer.PrivateData[1], nullptr);
1387+
EXPECT_EQ(existBox.buffer.PrivateData[2], someAddr);
1388+
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1);
1389+
}
1390+
1391+
TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_pod) {
1392+
auto any =
1393+
swift_getExistentialTypeMetadata(ProtocolClassConstraint::Any,
1394+
/*superclass=*/nullptr, 0, nullptr);
1395+
auto anyVWT = any->getValueWitnesses();
1396+
1397+
ValueWitnessTable testTable;
1398+
initialize_pod_witness_table(testTable);
1399+
FullOpaqueMetadata testMetadata = {{&testTable}, {{MetadataKind::Opaque}}};
1400+
Metadata *metadata = &testMetadata.base;
1401+
1402+
ValueWitnessTable testTable2;
1403+
initialize_indirect_witness_table(testTable2);
1404+
FullOpaqueMetadata testMetadata2 = {{&testTable2}, {{MetadataKind::Opaque}}};
1405+
Metadata *metadata2 = &testMetadata2.base;
1406+
1407+
auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
1408+
void *someAddr = &anyVWT;
1409+
swift_retain(refAndObjectAddr2.first);
1410+
struct {
1411+
ValueBuffer buffer;
1412+
Metadata *type;
1413+
uintptr_t canary;
1414+
} existBox2{{{someAddr, nullptr, someAddr}}, metadata, 0x5A5A5A5AU},
1415+
existBox{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
1416+
1417+
anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
1418+
reinterpret_cast<OpaqueValue *>(&existBox2), any);
1419+
1420+
EXPECT_EQ(existBox.type, metadata);
1421+
EXPECT_EQ(existBox.canary, 0xB5A5A5A5U);
1422+
EXPECT_EQ(existBox.buffer.PrivateData[0], someAddr);
1423+
EXPECT_EQ(existBox.buffer.PrivateData[1], nullptr);
1424+
EXPECT_EQ(existBox.buffer.PrivateData[2], someAddr);
1425+
EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1);
1426+
}

0 commit comments

Comments
 (0)