// Copyright 2022 The Pigweed Authors
//
// 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
//
//     https://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 "pw_thread/thread_snapshot_service.h"

#include "gtest/gtest.h"
#include "pw_protobuf/decoder.h"
#include "pw_rpc/raw/server_reader_writer.h"
#include "pw_span/span.h"
#include "pw_thread/thread_info.h"
#include "pw_thread/thread_iteration.h"
#include "pw_thread_private/thread_snapshot_service.h"
#include "pw_thread_protos/thread.pwpb.h"
#include "pw_thread_protos/thread_snapshot_service.pwpb.h"

namespace pw::thread::proto {
namespace {

// Iterates through each proto encoded thread in the buffer.
bool EncodedThreadExists(ConstByteSpan serialized_thread_buffer,
                         ConstByteSpan thread_name) {
  protobuf::Decoder decoder(serialized_thread_buffer);
  while (decoder.Next().ok()) {
    switch (decoder.FieldNumber()) {
      case static_cast<uint32_t>(proto::SnapshotThreadInfo::Fields::kThreads): {
        ConstByteSpan thread_buffer;
        EXPECT_EQ(OkStatus(), decoder.ReadBytes(&thread_buffer));
        ConstByteSpan encoded_name;
        EXPECT_EQ(OkStatus(), DecodeThreadName(thread_buffer, encoded_name));
        if (encoded_name.size() == thread_name.size()) {
          if (std::equal(thread_name.begin(),
                         thread_name.end(),
                         encoded_name.begin())) {
            return true;
          }
        }
      }
    }
  }
  return false;
}

ThreadInfo CreateThreadInfoObject(std::optional<ConstByteSpan> name,
                                  std::optional<uintptr_t> low_addr,
                                  std::optional<uintptr_t> high_addr,
                                  std::optional<uintptr_t> peak_addr) {
  ThreadInfo thread_info;

  if (name.has_value()) {
    thread_info.set_thread_name(name.value());
  }
  if (low_addr.has_value()) {
    thread_info.set_stack_low_addr(low_addr.value());
  }
  if (high_addr.has_value()) {
    thread_info.set_stack_high_addr(high_addr.value());
  }
  if (peak_addr.has_value()) {
    thread_info.set_stack_peak_addr(peak_addr.value());
  }

  return thread_info;
}

// Test creates a custom thread info object and proto encodes. Checks that the
// custom object is encoded properly.
TEST(ThreadSnapshotService, DecodeSingleThreadInfoObject) {
  std::array<std::byte, RequiredServiceBufferSize(1)> encode_buffer;

  proto::SnapshotThreadInfo::MemoryEncoder encoder(encode_buffer);

  ConstByteSpan name = bytes::String("MyThread\0");
  ThreadInfo thread_info = CreateThreadInfoObject(
      std::make_optional(name), /* thread name */
      std::make_optional(
          static_cast<uintptr_t>(12345678u)) /* stack low address */,
      std::make_optional(static_cast<uintptr_t>(0u)) /* stack high address */,
      std::make_optional(
          static_cast<uintptr_t>(987654321u)) /* stack peak address */);

  EXPECT_EQ(OkStatus(), ProtoEncodeThreadInfo(encoder, thread_info));

  ConstByteSpan response_span(encoder);
  EXPECT_TRUE(
      EncodedThreadExists(response_span, thread_info.thread_name().value()));
}

TEST(ThreadSnapshotService, DecodeMultipleThreadInfoObjects) {
  std::array<std::byte, RequiredServiceBufferSize(3)> encode_buffer;

  proto::SnapshotThreadInfo::MemoryEncoder encoder(encode_buffer);

  ConstByteSpan name = bytes::String("MyThread1\0");
  ThreadInfo thread_info_1 =
      CreateThreadInfoObject(std::make_optional(name),
                             std::make_optional(static_cast<uintptr_t>(123u)),
                             std::make_optional(static_cast<uintptr_t>(1023u)),
                             std::make_optional(static_cast<uintptr_t>(321u)));

  name = bytes::String("MyThread2\0");
  ThreadInfo thread_info_2 = CreateThreadInfoObject(
      std::make_optional(name),
      std::make_optional(static_cast<uintptr_t>(1000u)),
      std::make_optional(static_cast<uintptr_t>(999999u)),
      std::make_optional(static_cast<uintptr_t>(0u)));

  name = bytes::String("MyThread3\0");
  ThreadInfo thread_info_3 =
      CreateThreadInfoObject(std::make_optional(name),
                             std::make_optional(static_cast<uintptr_t>(123u)),
                             std::make_optional(static_cast<uintptr_t>(1023u)),
                             std::make_optional(static_cast<uintptr_t>(321u)));

  // Encode out of order.
  EXPECT_EQ(OkStatus(), ProtoEncodeThreadInfo(encoder, thread_info_3));
  EXPECT_EQ(OkStatus(), ProtoEncodeThreadInfo(encoder, thread_info_1));
  EXPECT_EQ(OkStatus(), ProtoEncodeThreadInfo(encoder, thread_info_2));

  ConstByteSpan response_span(encoder);
  EXPECT_TRUE(
      EncodedThreadExists(response_span, thread_info_1.thread_name().value()));
  EXPECT_TRUE(
      EncodedThreadExists(response_span, thread_info_2.thread_name().value()));
  EXPECT_TRUE(
      EncodedThreadExists(response_span, thread_info_3.thread_name().value()));
}

TEST(ThreadSnapshotService, DefaultBufferSize) {
  static std::array<std::byte, RequiredServiceBufferSize()> encode_buffer;

  proto::SnapshotThreadInfo::MemoryEncoder encoder(encode_buffer);

  ConstByteSpan name = bytes::String("MyThread\0");
  std::optional<uintptr_t> example_addr =
      std::make_optional(std::numeric_limits<uintptr_t>::max());

  ThreadInfo thread_info = CreateThreadInfoObject(
      std::make_optional(name), example_addr, example_addr, example_addr);

  for (int i = 0; i < PW_THREAD_MAXIMUM_THREADS; i++) {
    EXPECT_EQ(OkStatus(), ProtoEncodeThreadInfo(encoder, thread_info));
  }

  ConstByteSpan response_span(encoder);
  EXPECT_TRUE(
      EncodedThreadExists(response_span, thread_info.thread_name().value()));
}

TEST(ThreadSnapshotService, FailedPrecondition) {
  static std::array<std::byte, RequiredServiceBufferSize(1)> encode_buffer;

  proto::SnapshotThreadInfo::MemoryEncoder encoder(encode_buffer);

  ThreadInfo thread_info_no_name = CreateThreadInfoObject(
      std::nullopt,
      std::make_optional(static_cast<uintptr_t>(1111111111u)),
      std::make_optional(static_cast<uintptr_t>(2222222222u)),
      std::make_optional(static_cast<uintptr_t>(3333333333u)));
  Status status = ProtoEncodeThreadInfo(encoder, thread_info_no_name);
  EXPECT_EQ(status, Status::FailedPrecondition());
  // Expected log: "Thread missing information needed by service."
  ErrorLog(status);

  // Same error log as above.
  ConstByteSpan name = bytes::String("MyThread\0");
  ThreadInfo thread_info_no_high_addr = CreateThreadInfoObject(
      std::make_optional(name),
      std::make_optional(static_cast<uintptr_t>(1111111111u)),
      std::nullopt,
      std::make_optional(static_cast<uintptr_t>(3333333333u)));
  EXPECT_EQ(ProtoEncodeThreadInfo(encoder, thread_info_no_high_addr),
            Status::FailedPrecondition());
}

TEST(ThreadSnapshotService, Unimplemented) {
  static std::array<std::byte, RequiredServiceBufferSize(1)> encode_buffer;

  proto::SnapshotThreadInfo::MemoryEncoder encoder(encode_buffer);

  ConstByteSpan name = bytes::String("MyThread\0");
  ThreadInfo thread_info_no_peak_addr =
      CreateThreadInfoObject(std::make_optional(name),
                             std::make_optional(static_cast<uintptr_t>(0u)),
                             std::make_optional(static_cast<uintptr_t>(0u)),
                             std::nullopt);

  Status status = ProtoEncodeThreadInfo(encoder, thread_info_no_peak_addr);
  EXPECT_EQ(status, Status::Unimplemented());
  // Expected log: "Peak stack usage reporting not supported by your current OS
  // or configuration."
  ErrorLog(status);
}

}  // namespace
}  // namespace pw::thread::proto
