Skip to content

Commit fadf6b3

Browse files
committed
[unittest] Add some basic tests for TypeBase::canOverride.
Also, move the version lattice tests under a general "AST" test bundle.
1 parent 831f086 commit fadf6b3

File tree

5 files changed

+299
-8
lines changed

5 files changed

+299
-8
lines changed

unittests/AST/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_swift_unittest(SwiftASTTests
2+
OverrideTests.cpp
3+
VersionRangeLattice.cpp
4+
)
5+
6+
target_link_libraries(SwiftASTTests
7+
swiftAST
8+
# FIXME: Circular dependencies.
9+
swiftParse
10+
)

unittests/AST/OverrideTests.cpp

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
//===--- OverrideTests.cpp - Tests for overriding logic -------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/AST/ASTContext.h"
14+
#include "swift/AST/DiagnosticEngine.h"
15+
#include "swift/AST/Module.h"
16+
#include "swift/AST/SearchPathOptions.h"
17+
#include "swift/AST/Types.h"
18+
#include "swift/Basic/LangOptions.h"
19+
#include "swift/Basic/SourceManager.h"
20+
#include "swift/Strings.h"
21+
#include "swift/Subsystems.h"
22+
#include "llvm/ADT/Triple.h"
23+
#include "llvm/Support/Host.h"
24+
#include "gtest/gtest.h"
25+
26+
using namespace swift;
27+
28+
namespace {
29+
/// Helper class used to set the LangOpts target before initializing the
30+
/// ASTContext.
31+
///
32+
/// \see TestContext
33+
class TestContextBase {
34+
public:
35+
LangOptions LangOpts;
36+
SearchPathOptions SearchPathOpts;
37+
SourceManager SourceMgr;
38+
DiagnosticEngine Diags;
39+
40+
TestContextBase() : Diags(SourceMgr) {
41+
LangOpts.Target = llvm::Triple(llvm::sys::getProcessTriple());
42+
}
43+
};
44+
45+
enum ShouldDeclareOptionalTypes : bool {
46+
DoNotDeclareOptionalTypes,
47+
DeclareOptionalTypes
48+
};
49+
50+
/// Owns an ASTContext and the associated types.
51+
class TestContext : public TestContextBase {
52+
SourceFile *FileForLookups;
53+
54+
void declareOptionalType(Identifier name) {
55+
auto wrapped = new (Ctx) GenericTypeParamDecl(File,
56+
Ctx.getIdentifier("Wrapped"),
57+
SourceLoc(), /*depth*/0,
58+
/*index*/0);
59+
auto params = GenericParamList::create(Ctx, SourceLoc(), wrapped,
60+
SourceLoc());
61+
auto decl = new (Ctx) EnumDecl(SourceLoc(), name, SourceLoc(),
62+
/*inherited*/{}, params, File);
63+
wrapped->setDeclContext(decl);
64+
FileForLookups->Decls.push_back(decl);
65+
}
66+
67+
public:
68+
ASTContext Ctx;
69+
DerivedFileUnit *File;
70+
71+
TestContext(ShouldDeclareOptionalTypes optionals = DoNotDeclareOptionalTypes)
72+
: Ctx(LangOpts, SearchPathOpts, SourceMgr, Diags) {
73+
auto stdlibID = Ctx.getIdentifier(STDLIB_NAME);
74+
auto *module = ModuleDecl::create(stdlibID, Ctx);
75+
Ctx.LoadedModules[stdlibID] = module;
76+
File = new (Ctx) DerivedFileUnit(*module);
77+
78+
if (optionals == DeclareOptionalTypes) {
79+
using ImplicitModuleImportKind = SourceFile::ImplicitModuleImportKind;
80+
FileForLookups = new (Ctx) SourceFile(*module, SourceFileKind::Library,
81+
/*buffer*/None,
82+
ImplicitModuleImportKind::None);
83+
module->addFile(*FileForLookups);
84+
85+
declareOptionalType(Ctx.getIdentifier("Optional"));
86+
declareOptionalType(Ctx.getIdentifier("ImplicitlyUnwrappedOptional"));
87+
}
88+
}
89+
90+
template <typename Nominal>
91+
Nominal *makeNominal(StringRef name,
92+
GenericParamList *genericParams = nullptr) {
93+
auto result = new (Ctx) Nominal(SourceLoc(), Ctx.getIdentifier(name),
94+
SourceLoc(), /*inherited*/{},
95+
genericParams, File);
96+
result->setAccessibility(Accessibility::Internal);
97+
return result;
98+
}
99+
};
100+
} // end anonymous namespace
101+
102+
TEST(Override, IdenticalTypes) {
103+
TestContext C;
104+
105+
auto check = [&C](Type ty) {
106+
return ty->canOverride(ty, OverrideMatchMode::Strict, /*resolver*/nullptr);
107+
};
108+
109+
EXPECT_TRUE(check(C.Ctx.TheEmptyTupleType));
110+
EXPECT_TRUE(check(C.Ctx.TheRawPointerType));
111+
112+
Type voidToVoidFn = FunctionType::get(C.Ctx.TheEmptyTupleType,
113+
C.Ctx.TheEmptyTupleType);
114+
EXPECT_TRUE(check(voidToVoidFn));
115+
116+
Type ptrToPtrFn = FunctionType::get(C.Ctx.TheRawPointerType,
117+
C.Ctx.TheRawPointerType);
118+
EXPECT_TRUE(check(ptrToPtrFn));
119+
120+
auto *someStruct = C.makeNominal<StructDecl>("MyStruct");
121+
Type structTy = someStruct->getDeclaredInterfaceType();
122+
EXPECT_TRUE(check(structTy));
123+
124+
Type structToStructFn = FunctionType::get(structTy, structTy);
125+
EXPECT_TRUE(check(structToStructFn));
126+
}
127+
128+
TEST(Override, UnrelatedTypes) {
129+
TestContext C;
130+
131+
auto check = [&C](Type base, Type derived) {
132+
return derived->canOverride(base, OverrideMatchMode::Strict,
133+
/*resolver*/nullptr);
134+
};
135+
136+
EXPECT_FALSE(check(C.Ctx.TheEmptyTupleType, C.Ctx.TheRawPointerType));
137+
EXPECT_FALSE(check(C.Ctx.TheRawPointerType, C.Ctx.TheEmptyTupleType));
138+
139+
Type voidToVoidFn = FunctionType::get(C.Ctx.TheEmptyTupleType,
140+
C.Ctx.TheEmptyTupleType);
141+
EXPECT_FALSE(check(voidToVoidFn, C.Ctx.TheEmptyTupleType));
142+
EXPECT_FALSE(check(C.Ctx.TheEmptyTupleType, voidToVoidFn));
143+
144+
Type ptrToPtrFn = FunctionType::get(C.Ctx.TheRawPointerType,
145+
C.Ctx.TheRawPointerType);
146+
EXPECT_FALSE(check(ptrToPtrFn, voidToVoidFn));
147+
EXPECT_FALSE(check(voidToVoidFn, ptrToPtrFn));
148+
149+
auto *someStruct = C.makeNominal<StructDecl>("MyStruct");
150+
Type structTy = someStruct->getDeclaredInterfaceType();
151+
EXPECT_FALSE(check(structTy, C.Ctx.TheEmptyTupleType));
152+
EXPECT_FALSE(check(C.Ctx.TheEmptyTupleType, structTy));
153+
EXPECT_FALSE(check(structTy, voidToVoidFn));
154+
EXPECT_FALSE(check(voidToVoidFn, structTy));
155+
156+
Type structToStructFn = FunctionType::get(structTy, structTy);
157+
EXPECT_FALSE(check(structToStructFn, structTy));
158+
EXPECT_FALSE(check(structTy, structToStructFn));
159+
EXPECT_FALSE(check(structToStructFn, voidToVoidFn));
160+
EXPECT_FALSE(check(voidToVoidFn, structToStructFn));
161+
162+
auto *anotherStruct = C.makeNominal<StructDecl>("AnotherStruct");
163+
Type anotherStructTy = anotherStruct->getDeclaredInterfaceType();
164+
EXPECT_FALSE(check(structTy, anotherStructTy));
165+
EXPECT_FALSE(check(anotherStructTy, structTy));
166+
167+
Type anothorStructToAnotherStructFn = FunctionType::get(anotherStructTy,
168+
anotherStructTy);
169+
EXPECT_FALSE(check(anothorStructToAnotherStructFn, structToStructFn));
170+
EXPECT_FALSE(check(structToStructFn, anothorStructToAnotherStructFn));
171+
172+
Type S2ASFn = FunctionType::get(structTy, anotherStructTy);
173+
EXPECT_FALSE(check(S2ASFn, structToStructFn));
174+
EXPECT_FALSE(check(structToStructFn, S2ASFn));
175+
EXPECT_FALSE(check(S2ASFn, anothorStructToAnotherStructFn));
176+
EXPECT_FALSE(check(anothorStructToAnotherStructFn, S2ASFn));
177+
}
178+
179+
TEST(Override, Classes) {
180+
TestContext C;
181+
182+
auto check = [&C](Type base, Type derived) {
183+
return derived->canOverride(base, OverrideMatchMode::Strict,
184+
/*resolver*/nullptr);
185+
};
186+
187+
auto *baseClass = C.makeNominal<ClassDecl>("Base");
188+
Type baseTy = baseClass->getDeclaredInterfaceType();
189+
190+
auto *subClass = C.makeNominal<ClassDecl>("Sub");
191+
subClass->setSuperclass(baseTy);
192+
Type subTy = subClass->getDeclaredInterfaceType();
193+
194+
EXPECT_TRUE(check(baseTy, subTy));
195+
EXPECT_FALSE(check(subTy, baseTy));
196+
197+
auto *otherClass = C.makeNominal<ClassDecl>("Other");
198+
Type otherTy = otherClass->getDeclaredInterfaceType();
199+
EXPECT_FALSE(check(otherTy, baseTy));
200+
EXPECT_FALSE(check(baseTy, otherTy));
201+
EXPECT_FALSE(check(otherTy, subTy));
202+
EXPECT_FALSE(check(subTy, otherTy));
203+
204+
Type baseToVoid = FunctionType::get(baseTy, C.Ctx.TheEmptyTupleType);
205+
Type subToVoid = FunctionType::get(subTy, C.Ctx.TheEmptyTupleType);
206+
EXPECT_FALSE(check(baseToVoid, subToVoid));
207+
EXPECT_TRUE(check(subToVoid, baseToVoid));
208+
209+
Type voidToBase = FunctionType::get(C.Ctx.TheEmptyTupleType, baseTy);
210+
Type voidToSub = FunctionType::get(C.Ctx.TheEmptyTupleType, subTy);
211+
EXPECT_FALSE(check(voidToSub, voidToBase));
212+
EXPECT_TRUE(check(voidToBase, voidToSub));
213+
214+
Type baseToBase = FunctionType::get(baseTy, baseTy);
215+
Type subToSub = FunctionType::get(subTy, subTy);
216+
EXPECT_FALSE(check(baseToBase, subToSub));
217+
EXPECT_FALSE(check(subToSub, baseToBase));
218+
}
219+
220+
TEST(Override, Optionals) {
221+
TestContext C{DeclareOptionalTypes};
222+
223+
auto check = [&C](Type base, Type derived) {
224+
return derived->canOverride(base, OverrideMatchMode::Strict,
225+
/*resolver*/nullptr);
226+
};
227+
228+
auto *baseClass = C.makeNominal<ClassDecl>("Base");
229+
Type baseTy = baseClass->getDeclaredInterfaceType();
230+
Type optTy = OptionalType::get(baseTy);
231+
232+
EXPECT_FALSE(check(baseTy, optTy));
233+
EXPECT_TRUE(check(optTy, baseTy));
234+
235+
Type baseToVoid = FunctionType::get(baseTy, C.Ctx.TheEmptyTupleType);
236+
Type optToVoid = FunctionType::get(optTy, C.Ctx.TheEmptyTupleType);
237+
EXPECT_TRUE(check(baseToVoid, optToVoid));
238+
EXPECT_FALSE(check(optToVoid, baseToVoid));
239+
240+
Type voidToBase = FunctionType::get(C.Ctx.TheEmptyTupleType, baseTy);
241+
Type voidToOpt = FunctionType::get(C.Ctx.TheEmptyTupleType, optTy);
242+
EXPECT_FALSE(check(voidToBase, voidToOpt));
243+
EXPECT_TRUE(check(voidToOpt, voidToBase));
244+
245+
Type baseToBase = FunctionType::get(baseTy, baseTy);
246+
Type optToOpt = FunctionType::get(optTy, optTy);
247+
EXPECT_FALSE(check(baseToBase, optToOpt));
248+
EXPECT_FALSE(check(optToOpt, baseToBase));
249+
}
250+
251+
TEST(Override, IUONearMatch) {
252+
TestContext C{DeclareOptionalTypes};
253+
254+
auto check = [&C](Type base, Type derived) {
255+
return derived->canOverride(base, OverrideMatchMode::Strict,
256+
/*resolver*/nullptr);
257+
};
258+
auto checkIUO = [&C](Type base, Type derived) {
259+
return derived->canOverride(base,
260+
OverrideMatchMode::AllowNonOptionalForIUOParam,
261+
/*resolver*/nullptr);
262+
};
263+
264+
auto *baseClass = C.makeNominal<ClassDecl>("Base");
265+
Type baseTy = baseClass->getDeclaredInterfaceType();
266+
Type optTy = ImplicitlyUnwrappedOptionalType::get(baseTy);
267+
268+
Type baseToVoid = FunctionType::get(baseTy, C.Ctx.TheEmptyTupleType);
269+
Type optToVoid = FunctionType::get(optTy, C.Ctx.TheEmptyTupleType);
270+
EXPECT_TRUE(check(baseToVoid, optToVoid));
271+
EXPECT_TRUE(checkIUO(baseToVoid, optToVoid));
272+
EXPECT_FALSE(check(optToVoid, baseToVoid));
273+
EXPECT_TRUE(checkIUO(optToVoid, baseToVoid));
274+
275+
Type voidToBase = FunctionType::get(C.Ctx.TheEmptyTupleType, baseTy);
276+
Type voidToOpt = FunctionType::get(C.Ctx.TheEmptyTupleType, optTy);
277+
EXPECT_FALSE(check(voidToBase, voidToOpt));
278+
EXPECT_FALSE(checkIUO(voidToBase, voidToOpt));
279+
EXPECT_TRUE(check(voidToOpt, voidToBase));
280+
EXPECT_TRUE(checkIUO(voidToOpt, voidToBase));
281+
282+
Type baseToBase = FunctionType::get(baseTy, baseTy);
283+
Type optToOpt = FunctionType::get(optTy, optTy);
284+
EXPECT_FALSE(check(baseToBase, optToOpt));
285+
EXPECT_FALSE(checkIUO(baseToBase, optToOpt));
286+
EXPECT_FALSE(check(optToOpt, baseToBase));
287+
EXPECT_TRUE(checkIUO(optToOpt, baseToBase));
288+
}

unittests/Availability/CMakeLists.txt

Lines changed: 0 additions & 7 deletions
This file was deleted.

unittests/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ endfunction()
4040
if(SWIFT_BUILD_TOOLS)
4141
# We can't link C++ unit tests unless we build the tools.
4242

43-
add_subdirectory(Availability)
43+
add_subdirectory(AST)
4444
add_subdirectory(Basic)
4545
add_subdirectory(Driver)
4646
add_subdirectory(IDE)

0 commit comments

Comments
 (0)