1 | //===-- FileCacheTests.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 "support/FileCache.h" |
10 | |
11 | #include "TestFS.h" |
12 | #include "gmock/gmock.h" |
13 | #include "gtest/gtest.h" |
14 | #include <chrono> |
15 | #include <optional> |
16 | #include <utility> |
17 | |
18 | namespace clang { |
19 | namespace clangd { |
20 | namespace config { |
21 | namespace { |
22 | |
23 | class TestCache : public FileCache { |
24 | MockFS FS; |
25 | mutable std::string Value; |
26 | |
27 | public: |
28 | TestCache() : FileCache(testPath(File: "foo.cc" )) {} |
29 | |
30 | void setContents(const char *C) { |
31 | if (C) |
32 | FS.Files[testPath(File: "foo.cc" )] = C; |
33 | else |
34 | FS.Files.erase(Key: testPath(File: "foo.cc" )); |
35 | } |
36 | |
37 | std::pair<std::string, /*Parsed=*/bool> |
38 | get(std::chrono::steady_clock::time_point FreshTime) const { |
39 | bool GotParse = false; |
40 | bool GotRead = false; |
41 | std::string Result; |
42 | read( |
43 | TFS: FS, FreshTime, |
44 | Parse: [&](std::optional<llvm::StringRef> Data) { |
45 | GotParse = true; |
46 | Value = Data.value_or(u: "" ).str(); |
47 | }, |
48 | Read: [&]() { |
49 | GotRead = true; |
50 | Result = Value; |
51 | }); |
52 | EXPECT_TRUE(GotRead); |
53 | return {Result, GotParse}; |
54 | } |
55 | }; |
56 | |
57 | MATCHER_P(Parsed, Value, "" ) { return arg.second && arg.first == Value; } |
58 | MATCHER_P(Cached, Value, "" ) { return !arg.second && arg.first == Value; } |
59 | |
60 | TEST(FileCacheTest, Invalidation) { |
61 | TestCache C; |
62 | |
63 | auto StaleOK = std::chrono::steady_clock::now(); |
64 | auto MustBeFresh = StaleOK + std::chrono::hours(1); |
65 | |
66 | C.setContents("a" ); |
67 | EXPECT_THAT(C.get(StaleOK), Parsed("a" )) << "Parsed first time" ; |
68 | EXPECT_THAT(C.get(StaleOK), Cached("a" )) << "Cached (time)" ; |
69 | EXPECT_THAT(C.get(MustBeFresh), Cached("a" )) << "Cached (stat)" ; |
70 | C.setContents("bb" ); |
71 | EXPECT_THAT(C.get(StaleOK), Cached("a" )) << "Cached (time)" ; |
72 | EXPECT_THAT(C.get(MustBeFresh), Parsed("bb" )) << "Size changed" ; |
73 | EXPECT_THAT(C.get(MustBeFresh), Cached("bb" )) << "Cached (stat)" ; |
74 | C.setContents(nullptr); |
75 | EXPECT_THAT(C.get(StaleOK), Cached("bb" )) << "Cached (time)" ; |
76 | EXPECT_THAT(C.get(MustBeFresh), Parsed("" )) << "stat failed" ; |
77 | EXPECT_THAT(C.get(MustBeFresh), Cached("" )) << "Cached (404)" ; |
78 | C.setContents("bb" ); // Match the previous stat values! |
79 | EXPECT_THAT(C.get(StaleOK), Cached("" )) << "Cached (time)" ; |
80 | EXPECT_THAT(C.get(MustBeFresh), Parsed("bb" )) << "Size changed" ; |
81 | } |
82 | |
83 | } // namespace |
84 | } // namespace config |
85 | } // namespace clangd |
86 | } // namespace clang |
87 | |