/*
 * Copyright (C) 2021 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 <android/binder_auto_utils.h>
#include <android/binder_manager.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <aidl/android/aidl/tests/ITestService.h>

using aidl::android::aidl::tests::BackendType;
using aidl::android::aidl::tests::ITestService;
using testing::Eq;

struct AidlTest : testing::Test {
  template <typename T>
  std::shared_ptr<T> getService() {
    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
    return T::fromBinder(binder);
  }
  void SetUp() override {
    service = getService<ITestService>();
    auto status = service->getBackendType(&backend);
    ASSERT_TRUE(status.isOk()) << status.getDescription();
  }
  std::shared_ptr<ITestService> service;
  BackendType backend;
};

TEST_F(AidlTest, repeatUtf8String) {
  const std::vector<std::string> utf8_inputs = {
      std::string("Deliver us from evil."),
      std::string(),
      std::string("\0\0", 2),
      // Similarly, the utf8 encodings of the small letter yee and euro sign.
      std::string("\xF0\x90\x90\xB7\xE2\x82\xAC"),
      ITestService::STRING_TEST_CONSTANT_UTF8,
  };

  for (const auto& input : utf8_inputs) {
    std::string reply;
    auto status = service->RepeatUtf8CppString(input, &reply);
    ASSERT_TRUE(status.isOk());
    ASSERT_THAT(reply, Eq(input));
  }

  std::optional<std::string> reply;
  auto status = service->RepeatNullableUtf8CppString(std::nullopt, &reply);
  ASSERT_TRUE(status.isOk());
  ASSERT_FALSE(reply.has_value());

  for (const auto& input : utf8_inputs) {
    std::optional<std::string> reply;
    auto status = service->RepeatNullableUtf8CppString(input, &reply);
    ASSERT_TRUE(status.isOk());
    ASSERT_TRUE(reply.has_value());
    ASSERT_THAT(*reply, Eq(input));
  }
}

TEST_F(AidlTest, reverseUtf8StringArray) {
  std::vector<std::string> input = {"a", "", "\xc3\xb8"};
  decltype(input) repeated;
  if (backend == BackendType::JAVA) {
    repeated = decltype(input)(input.size());
  }
  decltype(input) reversed;

  auto status = service->ReverseUtf8CppString(input, &repeated, &reversed);
  ASSERT_TRUE(status.isOk()) << status.getDescription();
  ASSERT_THAT(repeated, Eq(input));

  decltype(input) reversed_input(input);
  std::reverse(reversed_input.begin(), reversed_input.end());
  ASSERT_THAT(reversed, Eq(reversed_input));
}

struct AidlStringArrayTest : public AidlTest {
  void DoTest(::ndk::ScopedAStatus (ITestService::*func)(
      const std::optional<std::vector<std::optional<std::string>>>&,
      std::optional<std::vector<std::optional<std::string>>>*,
      std::optional<std::vector<std::optional<std::string>>>*)) {
    std::optional<std::vector<std::optional<std::string>>> input;
    decltype(input) repeated;
    decltype(input) reversed;

    auto status = (*service.*func)(input, &repeated, &reversed);
    ASSERT_TRUE(status.isOk()) << status.getDescription();

    if (func == &ITestService::ReverseUtf8CppStringList && backend == BackendType::JAVA) {
      // Java cannot clear the input variable to return a null value. It can
      // only ever fill out a list.
      ASSERT_TRUE(repeated.has_value());
    } else {
      ASSERT_FALSE(repeated.has_value());
    }

    ASSERT_FALSE(reversed.has_value());

    input = std::vector<std::optional<std::string>>();
    input->push_back("Deliver us from evil.");
    input->push_back(std::nullopt);
    input->push_back("\xF0\x90\x90\xB7\xE2\x82\xAC");

    // usable size needs to be initialized for Java
    repeated = std::vector<std::optional<std::string>>(input->size());

    status = (*service.*func)(input, &repeated, &reversed);
    ASSERT_TRUE(status.isOk()) << status.getDescription();
    ASSERT_TRUE(reversed.has_value());
    ASSERT_TRUE(repeated.has_value());
    ASSERT_THAT(reversed->size(), Eq(input->size()));
    ASSERT_THAT(repeated->size(), Eq(input->size()));

    for (size_t i = 0; i < input->size(); i++) {
      auto input_str = (*input)[i];
      auto repeated_str = (*repeated)[i];
      auto reversed_str = (*reversed)[(reversed->size() - 1) - i];
      if (!input_str) {
        ASSERT_FALSE(repeated_str.has_value());
        ASSERT_FALSE(reversed_str.has_value());
        // 3 nullptrs to strings.  No need to compare values.
        continue;
      }
      ASSERT_TRUE(repeated_str.has_value());
      ASSERT_TRUE(reversed_str.has_value());

      ASSERT_THAT(*repeated_str, Eq(*input_str));
      ASSERT_THAT(*reversed_str, Eq(*input_str));
    }
  }
};

TEST_F(AidlStringArrayTest, nullableList) {
  DoTest(&ITestService::ReverseUtf8CppStringList);
}

TEST_F(AidlStringArrayTest, nullableArray) {
  DoTest(&ITestService::ReverseNullableUtf8CppString);
}
