// 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_METHOD0(SetUpDBus, void());
};

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));
  }

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

    EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());

    collector_.Initialize(IsMetrics);

    ASSERT_TRUE(temp_dir_generator_.CreateUniqueTempDir());

    FilePath log_config_path =
        temp_dir_generator_.GetPath().Append(kLogConfigFileName);
    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();

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

  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));
  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");
  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.
