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