xref: /llvm-project/clang-tools-extra/clangd/unittests/support/FileCacheTests.cpp (revision e26dad0a661e055076002d0de4ceb713b8ca6917)
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