/*
 * Copyright (C) 2018 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.
 */
#define LOG_TAG "Cts-NdkBinderTest"

#include <android/binder_ibinder_jni.h>
#include <gtest/gtest.h>
#include <test_package/BnEmpty.h>
#include <test_package/BpTest.h>
#include <test_package/RegularPolygon.h>

#include "itest_impl.h"
#include "utilities.h"

using ::aidl::test_package::BpTest;
using ::aidl::test_package::ITest;
using ::aidl::test_package::RegularPolygon;
using ::android::AutoAIBinder;
using ::android::AutoAStatus;

class NdkBinderTest_Aidl
    : public NdkBinderTest,
      public ::testing::WithParamInterface<std::shared_ptr<ITest>> {};

#define iface GetParam()

TEST_P(NdkBinderTest_Aidl, GotTest) { ASSERT_NE(nullptr, iface); }

TEST_P(NdkBinderTest_Aidl, UseBinder) {
  ASSERT_EQ(STATUS_OK, AIBinder_ping(iface->asBinder().get()));
}

TEST_P(NdkBinderTest_Aidl, Oneway) { ASSERT_OK(iface->TestOneway()); }

TEST_P(NdkBinderTest_Aidl, Constants) {
  ASSERT_EQ(0, ITest::kZero);
  ASSERT_EQ(1, ITest::kOne);
  ASSERT_EQ(0xffffffff, ITest::kOnes);
  ASSERT_EQ(std::string(""), ITest::kEmpty);
  ASSERT_EQ(std::string("foo"), ITest::kFoo);
}

TEST_P(NdkBinderTest_Aidl, RepeatPrimitives) {
  {
    int32_t out;
    ASSERT_OK(iface->RepeatInt(3, &out));
    EXPECT_EQ(3, out);
  }

  {
    int64_t out;
    ASSERT_OK(iface->RepeatLong(3, &out));
    EXPECT_EQ(3, out);
  }

  {
    float out;
    ASSERT_OK(iface->RepeatFloat(2.0f, &out));
    EXPECT_EQ(2.0f, out);
  }

  {
    double out;
    ASSERT_OK(iface->RepeatDouble(3.0, &out));
    EXPECT_EQ(3.0, out);
  }

  {
    bool out;
    ASSERT_OK(iface->RepeatBoolean(true, &out));
    EXPECT_EQ(true, out);
  }

  {
    char16_t out;
    ASSERT_OK(iface->RepeatChar(L'@', &out));
    EXPECT_EQ(L'@', out);
  }

  {
    int8_t out;
    ASSERT_OK(iface->RepeatByte(3, &out));
    EXPECT_EQ(3, out);
  }
}

TEST_P(NdkBinderTest_Aidl, RepeatBinder) {
  AutoAIBinder binder = iface->asBinder();
  AutoAIBinder ret;

  ASSERT_OK(iface->RepeatBinder(binder, &ret));
  EXPECT_EQ(binder.get(), ret.get());

  ASSERT_OK(iface->RepeatBinder(nullptr, &ret));
  EXPECT_EQ(nullptr, ret.get());
}

TEST_P(NdkBinderTest_Aidl, RepeatInterface) {
  class MyEmpty : public ::aidl::test_package::BnEmpty {};

  std::shared_ptr<IEmpty> empty = (new MyEmpty)->ref<IEmpty>();

  std::shared_ptr<IEmpty> ret;
  ASSERT_OK(iface->RepeatInterface(empty, &ret));
  EXPECT_EQ(empty.get(), ret.get());

  ASSERT_OK(iface->RepeatInterface(nullptr, &ret));
  EXPECT_EQ(nullptr, ret.get());
}

TEST_P(NdkBinderTest_Aidl, RepeatString) {
  std::string res;

  EXPECT_OK(iface->RepeatString("", &res));
  EXPECT_EQ("", res);

  EXPECT_OK(iface->RepeatString("a", &res));
  EXPECT_EQ("a", res);

  EXPECT_OK(iface->RepeatString("say what?", &res));
  EXPECT_EQ("say what?", res);
}

TEST_P(NdkBinderTest_Aidl, ParcelableDefaults) {
  RegularPolygon polygon;

  EXPECT_EQ("square", polygon.name);
  EXPECT_EQ(4, polygon.numSides);
  EXPECT_EQ(1.0f, polygon.sideLength);
}

TEST_P(NdkBinderTest_Aidl, RepeatPolygon) {
  RegularPolygon defaultPolygon = {"hexagon", 6, 2.0f};
  RegularPolygon outputPolygon;
  ASSERT_OK(iface->RepeatPolygon(defaultPolygon, &outputPolygon));
  EXPECT_EQ("hexagon", outputPolygon.name);
  EXPECT_EQ(defaultPolygon.numSides, outputPolygon.numSides);
  EXPECT_EQ(defaultPolygon.sideLength, outputPolygon.sideLength);
}

std::shared_ptr<ITest> getLocalService() {
  // BpTest -> AIBinder -> test
  std::shared_ptr<MyTest> test = (new MyTest)->ref<MyTest>();
  return BpTest::associate(test->asBinder());
}

std::shared_ptr<ITest> getNdkBinderTestJavaService(const std::string& method) {
  JNIEnv* env = GetEnv();
  if (env == nullptr) {
    std::cout << "No environment" << std::endl;
    return nullptr;
  }

  jclass cl = env->FindClass("android/binder/cts/NdkBinderTest");
  if (cl == nullptr) {
    std::cout << "No class" << std::endl;
    return nullptr;
  }

  jmethodID mid =
      env->GetStaticMethodID(cl, method.c_str(), "()Landroid/os/IBinder;");
  if (mid == nullptr) {
    std::cout << "No method id" << std::endl;
    return nullptr;
  }

  jobject object = env->CallStaticObjectMethod(cl, mid);
  if (object == nullptr) {
    std::cout << "Got null service from Java" << std::endl;
    return nullptr;
  }

  AutoAIBinder binder = AutoAIBinder(AIBinder_fromJavaBinder(env, object));

  return BpTest::associate(binder);
}

INSTANTIATE_TEST_CASE_P(Local, NdkBinderTest_Aidl,
                        ::testing::Values(getLocalService()));
INSTANTIATE_TEST_CASE_P(
    RemoteNative, NdkBinderTest_Aidl,
    ::testing::Values(getNdkBinderTestJavaService("getRemoteNativeService")));
INSTANTIATE_TEST_CASE_P(
    RemoteJava, NdkBinderTest_Aidl,
    ::testing::Values(getNdkBinderTestJavaService("getRemoteJavaService")));
