Skip to content

Commit 9ef4b5f

Browse files
author
Harlan Haskins
committed
[ParseableInterface] Add test for writing modules to a buffer
1 parent f4da34f commit 9ef4b5f

File tree

3 files changed

+157
-3
lines changed

3 files changed

+157
-3
lines changed

include/swift/Frontend/ParseableInterfaceModuleLoader.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,18 @@ namespace clang {
110110
class CompilerInstance;
111111
}
112112

113+
namespace unittest {
114+
class ParseableInterfaceModuleLoaderTest;
115+
}
116+
113117
namespace swift {
114118

115119
/// A ModuleLoader that runs a subordinate \c CompilerInvocation and
116120
/// \c CompilerInstance to convert .swiftinterface files to .swiftmodule
117121
/// files on the fly, caching the resulting .swiftmodules in the module cache
118122
/// directory, and loading the serialized .swiftmodules from there.
119123
class ParseableInterfaceModuleLoader : public SerializedModuleLoaderBase {
124+
friend class unittest::ParseableInterfaceModuleLoaderTest;
120125
explicit ParseableInterfaceModuleLoader(ASTContext &ctx, StringRef cacheDir,
121126
StringRef prebuiltCacheDir,
122127
DependencyTracker *tracker,
@@ -134,7 +139,6 @@ class ParseableInterfaceModuleLoader : public SerializedModuleLoaderBase {
134139
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
135140
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) override;
136141

137-
138142
public:
139143
static std::unique_ptr<ParseableInterfaceModuleLoader>
140144
create(ASTContext &ctx, StringRef cacheDir, StringRef prebuiltCacheDir,

unittests/FrontendTool/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
add_swift_unittest(SwiftFrontendTests
2-
FrontendToolTests.cpp)
3-
target_link_libraries(SwiftFrontendTests PRIVATE swiftFrontendTool)
2+
FrontendToolTests.cpp
3+
ModuleLoadingTests.cpp)
4+
5+
target_link_libraries(SwiftFrontendTests
6+
PRIVATE
7+
swiftFrontend
8+
swiftFrontendTool)
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//===--- ModuleLoadingTests.cpp -------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 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 "gtest/gtest.h"
14+
#include "swift/AST/ASTContext.h"
15+
#include "swift/Frontend/Frontend.h"
16+
#include "swift/Frontend/ParseableInterfaceModuleLoader.h"
17+
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
18+
#include "swift/Serialization/Validation.h"
19+
#include "llvm/ADT/SmallString.h"
20+
#include "llvm/Support/VirtualFileSystem.h"
21+
22+
using namespace swift;
23+
24+
static std::string createFilename(StringRef base, StringRef name) {
25+
SmallString<256> path = base;
26+
llvm::sys::path::append(path, name);
27+
return llvm::Twine(path).str();
28+
}
29+
30+
static bool emitFileWithContents(StringRef path, StringRef contents,
31+
std::string *pathOut = nullptr) {
32+
int fd;
33+
if (llvm::sys::fs::openFileForWrite(path, fd))
34+
return true;
35+
if (pathOut)
36+
*pathOut = path;
37+
llvm::raw_fd_ostream file(fd, /*shouldClose=*/true);
38+
file << contents;
39+
return false;
40+
}
41+
42+
static bool emitFileWithContents(StringRef base, StringRef name,
43+
StringRef contents,
44+
std::string *pathOut = nullptr) {
45+
return emitFileWithContents(createFilename(base, name), contents, pathOut);
46+
}
47+
48+
namespace unittest {
49+
50+
class OpenTrackingFileSystem : public llvm::vfs::ProxyFileSystem {
51+
llvm::StringMap<unsigned> numberOfOpensPerFile;
52+
public:
53+
OpenTrackingFileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs)
54+
: llvm::vfs::ProxyFileSystem(fs) {}
55+
56+
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
57+
openFileForRead(const Twine &Path) override {
58+
numberOfOpensPerFile[Path.str()] += 1;
59+
return ProxyFileSystem::openFileForRead(Path);
60+
}
61+
62+
unsigned numberOfOpens(StringRef path) {
63+
return numberOfOpensPerFile[path];
64+
}
65+
};
66+
67+
class ParseableInterfaceModuleLoaderTest : public testing::Test {
68+
protected:
69+
void setupAndLoadParseableModule() {
70+
SmallString<256> tempDir;
71+
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory(
72+
"ParseableModuleBufferTests.emitModuleInMemory", tempDir));
73+
SWIFT_DEFER { llvm::sys::fs::remove_directories(tempDir); };
74+
75+
auto cacheDir = createFilename(tempDir, "ModuleCache");
76+
ASSERT_FALSE(llvm::sys::fs::create_directory(cacheDir));
77+
78+
auto prebuiltCacheDir = createFilename(tempDir, "PrebuiltModuleCache");
79+
ASSERT_FALSE(llvm::sys::fs::create_directory(prebuiltCacheDir));
80+
81+
// Emit an interface file that we can attempt to compile.
82+
ASSERT_FALSE(emitFileWithContents(tempDir, "Library.swiftinterface",
83+
"// swift-interface-format-version: 1.0\n"
84+
"// swift-module-flags: -module-name TestModule -parse-stdlib\n"
85+
"public func foo()\n"));
86+
87+
SourceManager sourceMgr;
88+
89+
// Create a file system that tracks how many times a file has been opened.
90+
llvm::IntrusiveRefCntPtr<OpenTrackingFileSystem> fs(
91+
new OpenTrackingFileSystem(sourceMgr.getFileSystem()));
92+
93+
sourceMgr.setFileSystem(fs);
94+
PrintingDiagnosticConsumer printingConsumer;
95+
DiagnosticEngine diags(sourceMgr);
96+
diags.addConsumer(printingConsumer);
97+
LangOptions langOpts;
98+
langOpts.Target = llvm::Triple(llvm::sys::getDefaultTargetTriple());
99+
SearchPathOptions searchPathOpts;
100+
auto ctx = ASTContext::get(langOpts, searchPathOpts, sourceMgr, diags);
101+
102+
auto loader = ParseableInterfaceModuleLoader::create(
103+
*ctx, cacheDir, prebuiltCacheDir,
104+
/*dependencyTracker*/nullptr,
105+
ModuleLoadingMode::PreferSerialized);
106+
107+
Identifier moduleName = ctx->getIdentifier("TestModule");
108+
109+
std::unique_ptr<llvm::MemoryBuffer> moduleBuffer;
110+
std::unique_ptr<llvm::MemoryBuffer> moduleDocBuffer;
111+
112+
auto error =
113+
loader->findModuleFilesInDirectory({moduleName, SourceLoc()}, tempDir,
114+
"Library.swiftmodule", "Library.swiftdoc",
115+
&moduleBuffer, &moduleDocBuffer);
116+
ASSERT_FALSE(error);
117+
ASSERT_FALSE(diags.hadAnyError());
118+
119+
ASSERT_NE(nullptr, moduleBuffer);
120+
121+
// We should not have written a module doc file.
122+
ASSERT_EQ(nullptr, moduleDocBuffer);
123+
124+
// Make sure the buffer identifier points to the written module.
125+
StringRef cachedModulePath = moduleBuffer->getBufferIdentifier();
126+
ASSERT_TRUE(fs->exists(cachedModulePath));
127+
128+
// Assert that we've only opened this file once, to write it.
129+
ASSERT_EQ((unsigned)1, fs->numberOfOpens(cachedModulePath));
130+
131+
auto bufOrErr = fs->getBufferForFile(cachedModulePath);
132+
ASSERT_TRUE(bufOrErr);
133+
134+
auto bufData = (*bufOrErr)->getBuffer();
135+
auto validationInfo = serialization::validateSerializedAST(bufData);
136+
ASSERT_EQ(serialization::Status::Valid, validationInfo.status);
137+
ASSERT_EQ(bufData, moduleBuffer->getBuffer());
138+
}
139+
};
140+
141+
TEST_F(ParseableInterfaceModuleLoaderTest, LoadModuleFromBuffer) {
142+
setupAndLoadParseableModule();
143+
}
144+
145+
} // end namespace unittest

0 commit comments

Comments
 (0)