Skip to content

Commit ef83539

Browse files
committed
Add unittests for the remangler, particularly to cover error handling.
We currently don't have any tests for remangler error handling, because in asserts builds it asserts. This patch adds a flag that only exists in !NDEBUG builds to turn off assertions when inside the unit tests.
1 parent cdfb181 commit ef83539

File tree

5 files changed

+154
-6
lines changed

5 files changed

+154
-6
lines changed

include/swift/Demangling/Demangler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ class NodeFactory {
8080
#endif
8181

8282
public:
83+
#ifndef NDEBUG
84+
/// Enabled only by the unit tests to test the failure paths.
85+
bool disableAssertionsForUnitTest = false;
86+
#endif
8387

8488
NodeFactory() {
8589
#ifdef NODE_FACTORY_DEBUGGING

lib/Demangling/DemanglerAssert.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
#include "swift/Demangling/Demangle.h"
2323
#include "swift/Demangling/NamespaceMacros.h"
2424

25-
#if SWIFT_RUNTIME || defined(NDEBUG)
25+
#if defined(NDEBUG) || defined (SWIFT_RUNTIME)
2626

27-
// In the runtime and non-asserts builds, DEMANGLER_ASSERT() returns an error
27+
// In the runtime and non-asserts builds, DEMANGLER_ASSERT() returns an error.
2828
#define DEMANGLER_ASSERT(expr, node) \
2929
do { \
3030
if (!(expr)) \
@@ -33,14 +33,19 @@
3333

3434
#else
3535

36-
// Except in the runtime, assert builds cause DEMANGLER_ASSERT() to assert()
36+
// Except in unittests, assert builds cause DEMANGLER_ASSERT() to assert()
3737
#define DEMANGLER_ASSERT(expr, node) \
3838
do { \
39-
if (!(expr)) \
40-
swift::Demangle::failAssert(__FILE__, __LINE__, node, #expr); \
39+
if (!(expr)) { \
40+
if (Factory.disableAssertionsForUnitTest) \
41+
return ManglingError(ManglingError::AssertionFailed, (node), \
42+
__LINE__); \
43+
else \
44+
swift::Demangle::failAssert(__FILE__, __LINE__, node, #expr); \
45+
} \
4146
} while (0)
4247

43-
#endif // SWIFT_RUNTIME || defined(NDEBUG)
48+
#endif
4449

4550
// DEMANGLER_ALWAYS_ASSERT() *always* fails the program, even in the runtime
4651
#define DEMANGLER_ALWAYS_ASSERT(expr, node) \

unittests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ if(SWIFT_INCLUDE_TOOLS)
1313
add_subdirectory(Localization)
1414
add_subdirectory(IDE)
1515
add_subdirectory(Parse)
16+
add_subdirectory(Remangler)
1617
add_subdirectory(Sema)
1718
add_subdirectory(SIL)
1819
add_subdirectory(SwiftDemangle)
1920
add_subdirectory(Syntax)
21+
2022
if(SWIFT_BUILD_SYNTAXPARSERLIB)
2123
add_subdirectory(SyntaxParser)
2224
endif()

unittests/Remangler/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_swift_unittest(SwiftRemangleTests
2+
RemangleTest.cpp
3+
)
4+
5+
target_link_libraries(SwiftRemangleTests
6+
PRIVATE
7+
swiftBasic
8+
swiftDemangling
9+
LLVMTestingSupport
10+
)

unittests/Remangler/RemangleTest.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/Demangling/Demangle.h"
14+
#include "swift/Demangling/Demangler.h"
15+
#include "swift/Strings.h"
16+
#include "llvm/ADT/StringRef.h"
17+
18+
#include "gtest/gtest.h"
19+
20+
/// Helper class to conveniently construct demangle tree hierarchies.
21+
class NodeBuilder {
22+
using NodePointer = swift::Demangle::NodePointer;
23+
using Kind = swift::Demangle::Node::Kind;
24+
25+
swift::Demangle::Demangler &m_dem;
26+
27+
public:
28+
NodeBuilder(swift::Demangle::Demangler &dem) : m_dem(dem) {
29+
#ifndef NDEBUG
30+
m_dem.disableAssertionsForUnitTest = true;
31+
#endif
32+
}
33+
NodePointer Node(Kind kind, StringRef text) {
34+
return m_dem.createNode(kind, text);
35+
}
36+
NodePointer NodeWithIndex(Kind kind, swift::Demangle::Node::IndexType index) {
37+
return m_dem.createNode(kind, index);
38+
}
39+
NodePointer Node(Kind kind, NodePointer child0 = nullptr,
40+
NodePointer child1 = nullptr,
41+
NodePointer child2 = nullptr,
42+
NodePointer child3 = nullptr) {
43+
NodePointer node = m_dem.createNode(kind);
44+
45+
if (child0)
46+
node->addChild(child0, m_dem);
47+
if (child1)
48+
node->addChild(child1, m_dem);
49+
if (child2)
50+
node->addChild(child2, m_dem);
51+
if (child3)
52+
node->addChild(child3, m_dem);
53+
return node;
54+
}
55+
NodePointer IntType() {
56+
return Node(Node::Kind::Type,
57+
Node(Node::Kind::Structure,
58+
Node(Node::Kind::Module, swift::STDLIB_NAME),
59+
Node(Node::Kind::Identifier, "Int")));
60+
}
61+
NodePointer GlobalTypeMangling(NodePointer type) {
62+
assert(type && type->getKind() == Node::Kind::Type);
63+
return Node(Node::Kind::Global, Node(Node::Kind::TypeMangling, type));
64+
}
65+
NodePointer GlobalType(NodePointer type) {
66+
assert(type && type->getKind() != Node::Kind::Type &&
67+
type->getKind() != Node::Kind::TypeMangling &&
68+
type->getKind() != Node::Kind::Global);
69+
return GlobalTypeMangling(Node(Node::Kind::Type, type));
70+
}
71+
72+
ManglingErrorOr<StringRef> remangle(NodePointer node) {
73+
return mangleNode(
74+
node,
75+
[](SymbolicReferenceKind, const void *) -> NodePointer {
76+
return nullptr;
77+
},
78+
m_dem);
79+
}
80+
std::string remangleResult(NodePointer node) {
81+
return remangle(node).result().str();
82+
}
83+
bool remangleSuccess(NodePointer node) {
84+
return remangle(node).isSuccess();
85+
}
86+
};
87+
88+
TEST(TestSwiftRemangler, DependentGenericConformanceRequirement) {
89+
using namespace swift::Demangle;
90+
using Kind = swift::Demangle::Node::Kind;
91+
Demangler dem;
92+
NodeBuilder b(dem);
93+
{
94+
// Well-formed.
95+
NodePointer n = b.GlobalType(b.Node(
96+
Kind::DependentGenericType,
97+
b.Node(Kind::DependentGenericType,
98+
b.Node(Kind::DependentGenericSignature,
99+
b.NodeWithIndex(Kind::DependentGenericParamCount, 1),
100+
b.Node(Kind::DependentGenericConformanceRequirement,
101+
b.Node(Kind::Type,
102+
b.Node(Kind::DependentGenericParamType,
103+
b.NodeWithIndex(Kind::Index, 0),
104+
b.NodeWithIndex(Kind::Index, 0))),
105+
b.Node(Kind::Type,
106+
b.Node(Kind::Protocol,
107+
b.Node(Kind::Module, "M"),
108+
b.Node(Kind::Identifier, "B"))))),
109+
b.IntType())));
110+
ASSERT_EQ(b.remangleResult(n), "$sSi1M1BRzluuD");
111+
}
112+
{
113+
// Malformed.
114+
NodePointer n = b.GlobalType(b.Node(
115+
Kind::DependentGenericType,
116+
b.Node(Kind::DependentGenericType,
117+
b.Node(Kind::DependentGenericSignature,
118+
b.NodeWithIndex(Kind::DependentGenericParamCount, 1),
119+
b.Node(Kind::DependentGenericConformanceRequirement,
120+
b.Node(Kind::Type,
121+
b.Node(Kind::DependentGenericParamType,
122+
b.NodeWithIndex(Kind::Index, 0),
123+
b.NodeWithIndex(Kind::Index, 0))))),
124+
b.IntType())));
125+
ASSERT_FALSE(b.remangleSuccess(n));
126+
}
127+
}

0 commit comments

Comments
 (0)