/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/traced/probes/filesystem/inode_file_data_source.h"

#include "perfetto/protozero/scattered_heap_buffer.h"
#include "src/base/test/test_task_runner.h"
#include "src/base/test/utils.h"
#include "src/traced/probes/filesystem/lru_inode_cache.h"
#include "src/tracing/core/null_trace_writer.h"

#include "test/gtest_and_gmock.h"

#include "protos/perfetto/config/inode_file/inode_file_config.pbzero.h"
#include "protos/perfetto/trace/filesystem/inode_file_map.pbzero.h"

namespace perfetto {
namespace {

using ::testing::_;
using ::testing::Eq;
using ::testing::InvokeWithoutArgs;
using ::testing::IsNull;
using ::testing::Pointee;

class TestInodeFileDataSource : public InodeFileDataSource {
 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)
      : InodeFileDataSource(std::move(cfg),
                            task_runner,
                            tsid,
                            static_file_map,
                            cache,
                            std::move(writer)) {
    struct stat buf;
    PERFETTO_CHECK(
        lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata")
                  .c_str(),
              &buf) != -1);
    mount_points_.emplace(
        buf.st_dev,
        base::GetTestDataPath("src/traced/probes/filesystem/testdata"));
  }

  MOCK_METHOD(void,
              FillInodeEntry,
              (InodeFileMap * destination,
               Inode inode_number,
               const InodeMapValue& inode_map_value),
              (override));
};

class InodeFileDataSourceTest : public ::testing::Test {
 protected:
  InodeFileDataSourceTest() {}

  std::unique_ptr<TestInodeFileDataSource> GetInodeFileDataSource(
      DataSourceConfig cfg) {
    return std::unique_ptr<TestInodeFileDataSource>(new TestInodeFileDataSource(
        cfg, &task_runner_, 0, &static_file_map_, &cache_,
        std::unique_ptr<NullTraceWriter>(new NullTraceWriter)));
  }

  LRUInodeCache cache_{100};
  std::map<BlockDeviceID, std::unordered_map<Inode, InodeMapValue>>
      static_file_map_;
  base::TestTaskRunner task_runner_;
};

TEST_F(InodeFileDataSourceTest, TestFileSystemScan) {
  DataSourceConfig ds_config;
  protozero::HeapBuffered<protos::pbzero::InodeFileConfig> inode_cfg;
  inode_cfg->set_scan_interval_ms(1);
  inode_cfg->set_scan_delay_ms(1);
  ds_config.set_inode_file_config_raw(inode_cfg.SerializeAsString());
  auto data_source = GetInodeFileDataSource(ds_config);

  struct stat buf;
  PERFETTO_CHECK(
      lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")
                .c_str(),
            &buf) != -1);

  auto done = task_runner_.CreateCheckpoint("done");
  InodeMapValue value(
      protos::pbzero::InodeFileMap::Entry::Type::FILE,
      {base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")});
  EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)))
      .WillOnce(InvokeWithoutArgs(done));

  data_source->OnInodes({{buf.st_ino, buf.st_dev}});
  task_runner_.RunUntilCheckpoint("done");

  // Expect that the found inode is added in the LRU cache.
  EXPECT_THAT(cache_.Get(std::make_pair(buf.st_dev, buf.st_ino)),
              Pointee(Eq(value)));
}

TEST_F(InodeFileDataSourceTest, TestStaticMap) {
  DataSourceConfig config;
  auto data_source = GetInodeFileDataSource(config);
  CreateStaticDeviceToInodeMap(
      base::GetTestDataPath("src/traced/probes/filesystem/testdata"),
      &static_file_map_);

  struct stat buf;
  PERFETTO_CHECK(
      lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")
                .c_str(),
            &buf) != -1);

  InodeMapValue value(
      protos::pbzero::InodeFileMap::Entry::Type::FILE,
      {base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")});
  EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)));

  data_source->OnInodes({{buf.st_ino, buf.st_dev}});
  // Expect that the found inode is not added the LRU cache.
  EXPECT_THAT(cache_.Get(std::make_pair(buf.st_dev, buf.st_ino)), IsNull());
}

TEST_F(InodeFileDataSourceTest, TestCache) {
  DataSourceConfig config;
  auto data_source = GetInodeFileDataSource(config);
  CreateStaticDeviceToInodeMap(
      base::GetTestDataPath("src/traced/probes/filesystem/testdata"),
      &static_file_map_);

  struct stat buf;
  PERFETTO_CHECK(
      lstat(base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")
                .c_str(),
            &buf) != -1);

  InodeMapValue value(
      protos::pbzero::InodeFileMap::Entry::Type::FILE,
      {base::GetTestDataPath("src/traced/probes/filesystem/testdata/file2")});
  cache_.Insert(std::make_pair(buf.st_dev, buf.st_ino), value);

  EXPECT_CALL(*data_source, FillInodeEntry(_, buf.st_ino, Eq(value)));

  data_source->OnInodes({{buf.st_ino, buf.st_dev}});
}

}  // namespace
}  // namespace perfetto
