/*
 * Copyright (C) 2020 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/system_info/system_info_data_source.h"
#include "src/traced/probes/common/cpu_freq_info_for_testing.h"
#include "src/tracing/core/trace_writer_for_testing.h"
#include "test/gtest_and_gmock.h"

#include "protos/perfetto/trace/system_info/cpu_info.gen.h"

using ::testing::AnyOf;
using ::testing::ElementsAre;
using ::testing::Return;

namespace perfetto {
namespace {

const char kMockCpuInfoAndroid[] = R"(
Processor	: AArch64 Processor rev 13 (aarch64)
processor	: 0
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x7
CPU part	: 0x803
CPU revision	: 12

processor	: 1
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x7
CPU part	: 0x803
CPU revision	: 12

processor	: 2
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x7
CPU part	: 0x803
CPU revision	: 12

processor	: 3
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x7
CPU part	: 0x803
CPU revision	: 12

processor	: 4
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x7
CPU part	: 0x803
CPU revision	: 12

processor	: 5
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x7
CPU part	: 0x803
CPU revision	: 12

processor	: 6
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x6
CPU part	: 0x802
CPU revision	: 13

processor	: 7
BogoMIPS	: 38.00
Features	: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp
CPU implementer	: 0x51
CPU architecture: 8
CPU variant	: 0x6
CPU part	: 0x802
CPU revision	: 13

Hardware	: Qualcomm Technologies, Inc SDM670

)";

class TestSystemInfoDataSource : public SystemInfoDataSource {
 public:
  TestSystemInfoDataSource(std::unique_ptr<TraceWriter> writer,
                           std::unique_ptr<CpuFreqInfo> cpu_freq_info)
      : SystemInfoDataSource(
            /* session_id */ 0,
            std::move(writer),
            std::move(cpu_freq_info)) {}

  MOCK_METHOD(std::string, ReadFile, (std::string), (override));
};

class SystemInfoDataSourceTest : public ::testing::Test {
 protected:
  std::unique_ptr<TestSystemInfoDataSource> GetSystemInfoDataSource() {
    auto writer =
        std::unique_ptr<TraceWriterForTesting>(new TraceWriterForTesting());
    writer_raw_ = writer.get();
    auto instance =
        std::unique_ptr<TestSystemInfoDataSource>(new TestSystemInfoDataSource(
            std::move(writer), cpu_freq_info_for_testing.GetInstance()));
    return instance;
  }

  TraceWriterForTesting* writer_raw_ = nullptr;
  CpuFreqInfoForTesting cpu_freq_info_for_testing;
};

TEST_F(SystemInfoDataSourceTest, CpuInfoAndroid) {
  auto data_source = GetSystemInfoDataSource();
  EXPECT_CALL(*data_source, ReadFile("/proc/cpuinfo"))
      .WillOnce(Return(kMockCpuInfoAndroid));
  data_source->Start();

  protos::gen::TracePacket packet = writer_raw_->GetOnlyTracePacket();
  ASSERT_TRUE(packet.has_cpu_info());
  auto cpu_info = packet.cpu_info();
  ASSERT_EQ(cpu_info.cpus_size(), 8);
  auto cpu = cpu_info.cpus()[0];
  ASSERT_EQ(cpu.processor(), "AArch64 Processor rev 13 (aarch64)");
  ASSERT_THAT(cpu.frequencies(),
              ElementsAre(300000, 576000, 748800, 998400, 1209600, 1324800,
                          1516800, 1612800, 1708800));
  cpu = cpu_info.cpus()[1];
  ASSERT_EQ(cpu.processor(), "AArch64 Processor rev 13 (aarch64)");
  ASSERT_THAT(cpu.frequencies(),
              ElementsAre(300000, 652800, 825600, 979200, 1132800, 1363200,
                          1536000, 1747200, 1843200, 1996800, 2803200));
}

}  // namespace
}  // namespace perfetto
