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:
TestCache()28 TestCache() : FileCache(testPath("foo.cc")) {}
29
setContents(const char * C)30 void setContents(const char *C) {
31 if (C)
32 FS.Files[testPath("foo.cc")] = C;
33 else
34 FS.Files.erase(testPath("foo.cc"));
35 }
36
37 std::pair<std::string, /*Parsed=*/bool>
get(std::chrono::steady_clock::time_point FreshTime) const38 get(std::chrono::steady_clock::time_point FreshTime) const {
39 bool GotParse = false;
40 bool GotRead = false;
41 std::string Result;
42 read(
43 FS, FreshTime,
44 [&](std::optional<llvm::StringRef> Data) {
45 GotParse = true;
46 Value = Data.value_or("").str();
47 },
48 [&]() {
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
TEST(FileCacheTest,Invalidation)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