1//===- DependencyScanningFilesystemTest.cpp -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h"
10#include "llvm/ADT/SmallString.h"
11#include "llvm/Support/VirtualFileSystem.h"
12#include "gtest/gtest.h"
13
14using namespace clang::tooling::dependencies;
15
16TEST(DependencyScanningWorkerFilesystem, CacheStatusFailures) {
17 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
18
19 auto InstrumentingFS =
20 llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(A&: InMemoryFS);
21
22 DependencyScanningFilesystemSharedCache SharedCache;
23 DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
24 DependencyScanningWorkerFilesystem DepFS2(SharedCache, InstrumentingFS);
25
26 DepFS.status(Path: "/foo.c");
27 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
28
29 DepFS.status(Path: "/foo.c");
30 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u); // Cached, no increase.
31
32 DepFS.status(Path: "/bar.c");
33 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
34
35 DepFS2.status(Path: "/foo.c");
36 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u); // Shared cache.
37}
38
39TEST(DependencyScanningFilesystem, CacheGetRealPath) {
40 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
41 InMemoryFS->setCurrentWorkingDirectory("/");
42 InMemoryFS->addFile(Path: "/foo", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
43 InMemoryFS->addFile(Path: "/bar", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
44
45 auto InstrumentingFS =
46 llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(A&: InMemoryFS);
47
48 DependencyScanningFilesystemSharedCache SharedCache;
49 DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
50 DependencyScanningWorkerFilesystem DepFS2(SharedCache, InstrumentingFS);
51
52 {
53 llvm::SmallString<128> Result;
54 DepFS.getRealPath(Path: "/foo", Output&: Result);
55 EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u);
56 }
57
58 {
59 llvm::SmallString<128> Result;
60 DepFS.getRealPath(Path: "/foo", Output&: Result);
61 EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 1u); // Cached, no increase.
62 }
63
64 {
65 llvm::SmallString<128> Result;
66 DepFS.getRealPath(Path: "/bar", Output&: Result);
67 EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u);
68 }
69
70 {
71 llvm::SmallString<128> Result;
72 DepFS2.getRealPath(Path: "/foo", Output&: Result);
73 EXPECT_EQ(InstrumentingFS->NumGetRealPathCalls, 2u); // Shared cache.
74 }
75}
76
77TEST(DependencyScanningFilesystem, RealPathAndStatusInvariants) {
78 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
79 InMemoryFS->setCurrentWorkingDirectory("/");
80 InMemoryFS->addFile(Path: "/foo.c", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
81 InMemoryFS->addFile(Path: "/bar.c", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
82
83 DependencyScanningFilesystemSharedCache SharedCache;
84 DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);
85
86 // Success.
87 {
88 DepFS.status(Path: "/foo.c");
89
90 llvm::SmallString<128> Result;
91 DepFS.getRealPath(Path: "/foo.c", Output&: Result);
92 }
93 {
94 llvm::SmallString<128> Result;
95 DepFS.getRealPath(Path: "/bar.c", Output&: Result);
96
97 DepFS.status(Path: "/bar.c");
98 }
99
100 // Failure.
101 {
102 DepFS.status(Path: "/foo.m");
103
104 llvm::SmallString<128> Result;
105 DepFS.getRealPath(Path: "/foo.m", Output&: Result);
106 }
107 {
108 llvm::SmallString<128> Result;
109 DepFS.getRealPath(Path: "/bar.m", Output&: Result);
110
111 DepFS.status(Path: "/bar.m");
112 }
113
114 // Failure without caching.
115 {
116 DepFS.status(Path: "/foo");
117
118 llvm::SmallString<128> Result;
119 DepFS.getRealPath(Path: "/foo", Output&: Result);
120 }
121 {
122 llvm::SmallString<128> Result;
123 DepFS.getRealPath(Path: "/bar", Output&: Result);
124
125 DepFS.status(Path: "/bar");
126 }
127}
128
129TEST(DependencyScanningFilesystem, CacheStatOnExists) {
130 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
131 auto InstrumentingFS =
132 llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(A&: InMemoryFS);
133 InMemoryFS->setCurrentWorkingDirectory("/");
134 InMemoryFS->addFile(Path: "/foo", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
135 InMemoryFS->addFile(Path: "/bar", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
136 DependencyScanningFilesystemSharedCache SharedCache;
137 DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
138
139 DepFS.status(Path: "/foo");
140 DepFS.status(Path: "/foo");
141 DepFS.status(Path: "/bar");
142 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
143
144 DepFS.exists(Path: "/foo");
145 DepFS.exists(Path: "/bar");
146 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
147 EXPECT_EQ(InstrumentingFS->NumExistsCalls, 0u);
148}
149
150TEST(DependencyScanningFilesystem, CacheStatFailures) {
151 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
152 InMemoryFS->setCurrentWorkingDirectory("/");
153 InMemoryFS->addFile(Path: "/dir/vector", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
154 InMemoryFS->addFile(Path: "/cache/a.pcm", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
155
156 auto InstrumentingFS =
157 llvm::makeIntrusiveRefCnt<llvm::vfs::TracingFileSystem>(A&: InMemoryFS);
158
159 DependencyScanningFilesystemSharedCache SharedCache;
160 DependencyScanningWorkerFilesystem DepFS(SharedCache, InstrumentingFS);
161
162 DepFS.status(Path: "/dir");
163 DepFS.status(Path: "/dir");
164 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 1u);
165
166 DepFS.status(Path: "/dir/vector");
167 DepFS.status(Path: "/dir/vector");
168 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 2u);
169
170 DepFS.setBypassedPathPrefix("/cache");
171 DepFS.exists(Path: "/cache/a.pcm");
172 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 3u);
173 DepFS.exists(Path: "/cache/a.pcm");
174 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 4u);
175
176 DepFS.resetBypassedPathPrefix();
177 DepFS.exists(Path: "/cache/a.pcm");
178 DepFS.exists(Path: "/cache/a.pcm");
179 EXPECT_EQ(InstrumentingFS->NumStatusCalls, 5u);
180}
181
182TEST(DependencyScanningFilesystem, DiagnoseStaleStatFailures) {
183 auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
184 InMemoryFS->setCurrentWorkingDirectory("/");
185
186 DependencyScanningFilesystemSharedCache SharedCache;
187 DependencyScanningWorkerFilesystem DepFS(SharedCache, InMemoryFS);
188
189 bool Path1Exists = DepFS.exists(Path: "/path1.suffix");
190 EXPECT_EQ(Path1Exists, false);
191
192 // Adding a file that has been stat-ed,
193 InMemoryFS->addFile(Path: "/path1.suffix", ModificationTime: 0, Buffer: llvm::MemoryBuffer::getMemBuffer(InputData: ""));
194 Path1Exists = DepFS.exists(Path: "/path1.suffix");
195 // Due to caching in SharedCache, path1 should not exist in
196 // DepFS's eyes.
197 EXPECT_EQ(Path1Exists, false);
198
199 std::vector<llvm::StringRef> InvalidPaths =
200 SharedCache.getInvalidNegativeStatCachedPaths(UnderlyingFS&: *InMemoryFS);
201
202 EXPECT_EQ(InvalidPaths.size(), 1u);
203 ASSERT_STREQ("/path1.suffix", InvalidPaths[0].str().c_str());
204}
205

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/Tooling/DependencyScanning/DependencyScanningFilesystemTest.cpp