// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crash-reporter/udev_collector.h"

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/strings/stringprintf.h>
#include <brillo/syslog_logging.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "crash-reporter/test_util.h"

using base::FilePath;

namespace {

// Dummy log config file name.
const char kLogConfigFileName[] = "log_config_file";

// Dummy directory for storing device coredumps.
const char kDevCoredumpDirectory[] = "devcoredump";

// A bunch of random rules to put into the dummy log config file.
const char kLogConfigFileContents[] =
    "crash_reporter-udev-collection-change-card0-drm=echo change card0 drm\n"
    "crash_reporter-udev-collection-add-state0-cpu=echo change state0 cpu\n"
    "crash_reporter-udev-collection-devcoredump-iwlwifi=echo devcoredump\n"
    "cros_installer=echo not for udev";

const char kCrashLogFilePattern[] = "*.log.gz";
const char kDevCoredumpFilePattern[] = "*.devcore";

// Dummy content for device coredump data file.
const char kDevCoredumpDataContents[] = "coredump";

// Content for failing device's uevent file.
const char kFailingDeviceUeventContents[] = "DRIVER=iwlwifi\n";

bool s_consent_given = true;

bool IsMetrics() {
  return s_consent_given;
}

// Returns the number of files found in the given path that matches the
// specified file name pattern.
int GetNumFiles(const FilePath& path, const std::string& file_pattern) {
  base::FileEnumerator enumerator(path, false, base::FileEnumerator::FILES,
                                  file_pattern);
  int num_files = 0;
  for (FilePath file_path = enumerator.Next(); !file_path.value().empty();
       file_path = enumerator.Next()) {
    num_files++;
  }
  return num_files;
}

}  // namespace

class UdevCollectorMock : public UdevCollector {
 public:
  MOCK_METHOD(void, SetUpDBus, (), (override));
};

class UdevCollectorTest : public ::testing::Test {
 protected:
  base::ScopedTempDir temp_dir_generator_;

  void HandleCrash(const std::string& udev_event) {
    collector_.HandleCrash(udev_event);
  }

  void GenerateDevCoredump(const std::string& device_name) {
    // Generate coredump data file.
    ASSERT_TRUE(CreateDirectory(FilePath(
        base::StringPrintf("%s/%s", collector_.dev_coredump_directory_.c_str(),
                           device_name.c_str()))));
    FilePath data_path = FilePath(base::StringPrintf(
        "%s/%s/data", collector_.dev_coredump_directory_.c_str(),
        device_name.c_str()));
    ASSERT_TRUE(test_util::CreateFile(data_path, kDevCoredumpDataContents));
    // Generate uevent file for failing device.
    ASSERT_TRUE(CreateDirectory(FilePath(base::StringPrintf(
        "%s/%s/failing_device", collector_.dev_coredump_directory_.c_str(),
        device_name.c_str()))));
    FilePath uevent_path = FilePath(base::StringPrintf(
        "%s/%s/failing_device/uevent",
        collector_.dev_coredump_directory_.c_str(), device_name.c_str()));
    ASSERT_TRUE(
        test_util::CreateFile(uevent_path, kFailingDeviceUeventContents));
  }

  void SetUpCollector(UdevCollectorMock* collector) {
    EXPECT_CALL(*collector, SetUpDBus()).WillRepeatedly(testing::Return());
    collector->Initialize(IsMetrics, false);

    collector->log_config_path_ = log_config_path_;
    collector->set_crash_directory_for_test(temp_dir_generator_.GetPath());

    FilePath dev_coredump_path =
        temp_dir_generator_.GetPath().Append(kDevCoredumpDirectory);
    collector->dev_coredump_directory_ = dev_coredump_path.value();
  }

 private:
  void SetUp() override {
    s_consent_given = true;

    ASSERT_TRUE(temp_dir_generator_.CreateUniqueTempDir());
    log_config_path_ = temp_dir_generator_.GetPath().Append(kLogConfigFileName);

    SetUpCollector(&collector_);
    // Write to a dummy log config file.
    ASSERT_TRUE(
        test_util::CreateFile(log_config_path_, kLogConfigFileContents));
    brillo::ClearLog();
  }

  FilePath log_config_path_;
  UdevCollectorMock collector_;
};

TEST_F(UdevCollectorTest, TestNoConsent) {
  s_consent_given = false;
  HandleCrash("ACTION=change:KERNEL=card0:SUBSYSTEM=drm");
  EXPECT_EQ(0,
            GetNumFiles(temp_dir_generator_.GetPath(), kCrashLogFilePattern));
}

TEST_F(UdevCollectorTest, TestNoMatch) {
  // No rule should match this.
  HandleCrash("ACTION=change:KERNEL=foo:SUBSYSTEM=bar");
  EXPECT_EQ(0,
            GetNumFiles(temp_dir_generator_.GetPath(), kCrashLogFilePattern));
}

TEST_F(UdevCollectorTest, TestMatches) {
  // Try multiple udev events in sequence.  The number of log files generated
  // should increase.
  HandleCrash("ACTION=change:KERNEL=card0:SUBSYSTEM=drm");
  EXPECT_EQ(1,
            GetNumFiles(temp_dir_generator_.GetPath(), kCrashLogFilePattern));

  // Each collector is only allowed to handle one crash, so create a second
  // collector for the second crash.
  UdevCollectorMock second_collector;
  SetUpCollector(&second_collector);
  second_collector.HandleCrash("ACTION=add:KERNEL=state0:SUBSYSTEM=cpu");
  EXPECT_EQ(2,
            GetNumFiles(temp_dir_generator_.GetPath(), kCrashLogFilePattern));
}

TEST_F(UdevCollectorTest, TestDevCoredump) {
  GenerateDevCoredump("devcd0");
  HandleCrash("ACTION=add:KERNEL_NUMBER=0:SUBSYSTEM=devcoredump");
  EXPECT_EQ(
      1, GetNumFiles(temp_dir_generator_.GetPath(), kDevCoredumpFilePattern));
  GenerateDevCoredump("devcd1");
  // Each collector is only allowed to handle one crash, so create a second
  // collector for the second crash.
  UdevCollectorMock second_collector;
  SetUpCollector(&second_collector);
  second_collector.HandleCrash(
      "ACTION=add:KERNEL_NUMBER=1:SUBSYSTEM=devcoredump");
  EXPECT_EQ(
      2, GetNumFiles(temp_dir_generator_.GetPath(), kDevCoredumpFilePattern));
}

// TODO(sque, crosbug.com/32238) - test wildcard cases, multiple identical udev
// events.
