#include <gtest/gtest.h>
#include <stdint.h>

extern "C" {
  #include "access_control.h"
}

static const TEE_UUID g_test_uuid = { 0xFFFFFFFF, 0x0000, 0x0000, {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}};
static const TEE_UUID g_secure_storage_uuid = { 0x00000000, 0x0000, 0x0000, {
    0x00, 0x00, 0x53, 0x45, 0x43, 0x53, 0x54, 0x52}};

static const TEE_UUID g_null_uuid = { 0x00000000, 0x0000, 0x0000, {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};

static const TEE_UUID *g_allowed_uuid_for_task_api[] = {
  &g_test_uuid,
  &g_secure_storage_uuid,
  NULL // Last element should be NULL
};

static TEE_Result g_platform_get_caller_uuid_return = TEE_SUCCESS;
static TEE_UUID *g_platform_get_caller_uuid =
                      (TEE_UUID *)g_allowed_uuid_for_task_api[1];
static TEE_UUID *g_access_control_get_allowlist_return =
                      (TEE_UUID *)g_allowed_uuid_for_task_api;

extern "C" TEE_Result PlatformGetCallerUuid(TEE_UUID *uuid) {
  *uuid = *g_platform_get_caller_uuid;
  return g_platform_get_caller_uuid_return;
}

extern "C" const TEE_UUID** AccessControlGetAllowlist(void) {
  return (const TEE_UUID **)g_access_control_get_allowlist_return;
}

class AccessControlIsAllowedOperationTest : public ::testing::Test {
protected:
  virtual void SetUp() {
    g_platform_get_caller_uuid_return = TEE_SUCCESS;
    g_platform_get_caller_uuid = (TEE_UUID *)g_allowed_uuid_for_task_api[0];
    g_access_control_get_allowlist_return = (TEE_UUID *)g_allowed_uuid_for_task_api;
  }

  virtual void TearDown() {
  }
};


TEST_F(AccessControlIsAllowedOperationTest, AllowAuthentication) {
  uint32_t result;
  
  result = AccessControlIsAllowedOperation(kAuthentication);

  EXPECT_TRUE(1 == result);
}

TEST_F(AccessControlIsAllowedOperationTest, FailedPlatformGetCallerUuid) {
  uint32_t result;

  g_platform_get_caller_uuid_return = TEE_ERROR_GENERIC;
  
  result = AccessControlIsAllowedOperation(kAuthentication);

  EXPECT_TRUE(0 == result);
}

TEST_F(AccessControlIsAllowedOperationTest, AllowReadWriteToTrustlet) {
  uint32_t result;

  result = AccessControlIsAllowedOperation(kReadToTrustlet);

  EXPECT_TRUE(1 == result);
}

TEST_F(AccessControlIsAllowedOperationTest, ForbidReadWriteToTrustlet) {
  uint32_t result;
  g_platform_get_caller_uuid = (TEE_UUID *)&g_null_uuid;
  
  result = AccessControlIsAllowedOperation(kReadToTrustlet);

  EXPECT_TRUE(0 == result);
}
