#include <gtest/gtest.h>

extern "C" {
  #include "task_parser.h"
  #include "config.h"
  #include "kernel_access.h"
}

KernelAddress g_virt_addr = 0x0;
static PaConfig g_pa_config = {0};
static TaskInfo g_init_task = {(KernelAddress)&g_init_task, 0, 0,
                               0x0, 0x0, 0x0, 0, NULL, 0, 42};

/*
 * Mocked functions
 */
extern "C" uint32_t IsKernelVirtualAddress(KernelAddress kernel_virt) {
  return 1;
}

extern "C" const PaConfig *GetConfig(void) {
    return &g_pa_config;
}

extern "C" PaTzResult KernelAccessInit(KernelAccessInfo *context) {
  return PA_TZ_SUCCESS;
}

extern "C" PaTzResult KernelAccessGetBytes(KernelAccessInfo *context, KernelAddress address, 
                                           size_t size, void *out) {
  return PA_TZ_SUCCESS;
}

extern "C" PaTzResult KernelAccessGetUint8(KernelAccessInfo *context,
                                           KernelAddress address, 
                                           uint8_t *out) {
  return PA_TZ_SUCCESS;
}

extern "C" PaTzResult KernelAccessGetUint32(KernelAccessInfo *context,
                                            KernelAddress address, 
                                            uint32_t *out) {
  return PA_TZ_SUCCESS;
}

extern "C" PaTzResult KernelAccessGetUint64(KernelAccessInfo *context, 
                                            KernelAddress address, 
                                            uint64_t *out) {
  return PA_TZ_SUCCESS;
}

extern "C" PaTzResult KernelAccessGetPointer(KernelAccessInfo *context, 
                                             KernelAddress address, 
                                             KernelAddress *out) {
  return PA_TZ_SUCCESS;
}

extern "C" PaTzResult KernelAccessDeinit(KernelAccessInfo *context) {
 return PA_TZ_SUCCESS;
}

extern "C" int PaTzDecoderCertificate(const void *memory, 
                                      const uint32_t size_buffer,
                                      PaCertificate_t **command) {
 return 0;
}

extern "C" int PaTzEncoderCertificate(const PaCertificate_t *certificate,
                                      void *memory, uint32_t *size) {
 return 0;
}

extern "C" PaTzResult TaskAccessPutBytes(const TaskInfo *task, const void *in, 
                                         size_t size, ProcessAddress address) {
  return PA_TZ_SUCCESS;
}

extern "C" size_t CryptoGetHashSize(HashType type) {
  return 0;
}

class TaskParseTest : public ::testing::Test {
protected:
  virtual void SetUp() {
  }

  virtual void TearDown() {
  }
};


TEST_F(TaskParseTest, OutTaskNUll) {
  PaTzResult result;
  TaskInfo *out_task_null = NULL;

  result = TaskParseBasicInfo(g_virt_addr, out_task_null);

  EXPECT_TRUE(PA_TZ_GENERAL_ERROR == result);
}

TEST_F(TaskParseTest, TaskParseHeadPaTaskDescriptor_DescrIsNull_Error) {
  PaTzResult res = TaskParsePaTaskDescriptorStruct(g_virt_addr, NULL);
  ASSERT_EQ(PA_TZ_GENERAL_ERROR, res);
}
