• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/traced/probes/filesystem/inode_file_data_source.h"
18 
19 #include "perfetto/trace/filesystem/inode_file_map.pbzero.h"
20 #include "src/base/test/test_task_runner.h"
21 #include "src/traced/probes/filesystem/lru_inode_cache.h"
22 #include "src/tracing/core/null_trace_writer.h"
23 
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 
27 namespace perfetto {
28 namespace {
29 
30 using ::testing::Eq;
31 using ::testing::InvokeWithoutArgs;
32 using ::testing::IsNull;
33 using ::testing::Pointee;
34 using ::testing::_;
35 
36 class TestInodeFileDataSource : public InodeFileDataSource {
37  public:
TestInodeFileDataSource(DataSourceConfig cfg,base::TaskRunner * task_runner,TracingSessionID tsid,std::map<BlockDeviceID,std::unordered_map<Inode,InodeMapValue>> * static_file_map,LRUInodeCache * cache,std::unique_ptr<TraceWriter> writer)38   TestInodeFileDataSource(
39       DataSourceConfig cfg,
40       base::TaskRunner* task_runner,
41       TracingSessionID tsid,
42       std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>*
43           static_file_map,
44       LRUInodeCache* cache,
45       std::unique_ptr<TraceWriter> writer)
46       : InodeFileDataSource(std::move(cfg),
47                             task_runner,
48                             tsid,
49                             static_file_map,
50                             cache,
51                             std::move(writer)) {
52     struct stat buf;
53     PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata", &buf) != -1);
54     mount_points_.emplace(buf.st_dev, "src/traced/probes/filesystem/testdata");
55   }
56 
57   MOCK_METHOD3(FillInodeEntry,
58                void(InodeFileMap* destination,
59                     Inode inode_number,
60                     const InodeMapValue& inode_map_value));
61 };
62 
63 class InodeFileDataSourceTest : public ::testing::Test {
64  protected:
InodeFileDataSourceTest()65   InodeFileDataSourceTest() {}
66 
GetInodeFileDataSource(DataSourceConfig cfg)67   std::unique_ptr<TestInodeFileDataSource> GetInodeFileDataSource(
68       DataSourceConfig cfg) {
69     return std::unique_ptr<TestInodeFileDataSource>(new TestInodeFileDataSource(
70         cfg, &task_runner_, 0, &static_file_map_, &cache_,
71         std::unique_ptr<NullTraceWriter>(new NullTraceWriter)));
72   }
73 
74   LRUInodeCache cache_{100};
75   std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>
76       static_file_map_;
77   base::TestTaskRunner task_runner_;
78 };
79 
TEST_F(InodeFileDataSourceTest,TestFileSystemScan)80 TEST_F(InodeFileDataSourceTest, TestFileSystemScan) {
81   DataSourceConfig config;
82   config.mutable_inode_file_config()->set_scan_interval_ms(1);
83   config.mutable_inode_file_config()->set_scan_delay_ms(1);
84   auto data_source = GetInodeFileDataSource(config);
85 
86   struct stat buf;
87   PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata/file2", &buf) !=
88                  -1);
89 
90   auto done = task_runner_.CreateCheckpoint("done");
91   InodeMapValue value(protos::pbzero::InodeFileMap_Entry_Type_FILE,
92                       {"src/traced/probes/filesystem/testdata/file2"});
93   EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)))
94       .WillOnce(InvokeWithoutArgs(done));
95 
96   data_source->OnInodes({{buf.st_ino, buf.st_dev}});
97   task_runner_.RunUntilCheckpoint("done");
98 
99   // Expect that the found inode is added the the LRU cache.
100   EXPECT_THAT(cache_.Get(std::make_pair(buf.st_dev, buf.st_ino)),
101               Pointee(Eq(value)));
102 }
103 
TEST_F(InodeFileDataSourceTest,TestStaticMap)104 TEST_F(InodeFileDataSourceTest, TestStaticMap) {
105   DataSourceConfig config;
106   auto data_source = GetInodeFileDataSource(config);
107   CreateStaticDeviceToInodeMap("src/traced/probes/filesystem/testdata",
108                                &static_file_map_);
109 
110   struct stat buf;
111   PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata/file2", &buf) !=
112                  -1);
113 
114   InodeMapValue value(protos::pbzero::InodeFileMap_Entry_Type_FILE,
115                       {"src/traced/probes/filesystem/testdata/file2"});
116   EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)));
117 
118   data_source->OnInodes({{buf.st_ino, buf.st_dev}});
119   // Expect that the found inode is not added the the LRU cache.
120   EXPECT_THAT(cache_.Get(std::make_pair(buf.st_dev, buf.st_ino)), IsNull());
121 }
122 
TEST_F(InodeFileDataSourceTest,TestCache)123 TEST_F(InodeFileDataSourceTest, TestCache) {
124   DataSourceConfig config;
125   auto data_source = GetInodeFileDataSource(config);
126   CreateStaticDeviceToInodeMap("src/traced/probes/filesystem/testdata",
127                                &static_file_map_);
128 
129   struct stat buf;
130   PERFETTO_CHECK(lstat("src/traced/probes/filesystem/testdata/file2", &buf) !=
131                  -1);
132 
133   InodeMapValue value(protos::pbzero::InodeFileMap_Entry_Type_FILE,
134                       {"src/traced/probes/filesystem/testdata/file2"});
135   cache_.Insert(std::make_pair(buf.st_dev, buf.st_ino), value);
136 
137   EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)));
138 
139   data_source->OnInodes({{buf.st_ino, buf.st_dev}});
140 }
141 
142 }  // namespace
143 }  // namespace perfetto
144