* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <cstring>
#include <memory>
#include "acl/acl.h"
#include "acl/acl_prof.h"
#include "kernel_elf_parser.h"
#define ASCENDC_CPU_DEBUG
class TEST_ACL_STUB : public ::testing::Test {
protected:
void SetUp() {}
void TearDown() {}
};
TEST_F(TEST_ACL_STUB, AclProfInitSuccess)
{
EXPECT_EQ(aclprofInit(nullptr, 0), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclProfSetConfigSuccess)
{
EXPECT_EQ(aclprofSetConfig(ACL_PROF_STORAGE_LIMIT, nullptr, 0), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclProfStartStopFinalizeSuccess)
{
EXPECT_EQ(aclprofStart(nullptr), ACL_SUCCESS);
EXPECT_EQ(aclprofStop(nullptr), ACL_SUCCESS);
EXPECT_EQ(aclprofFinalize(), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclInitFinalizeTest)
{
EXPECT_EQ(aclInit(nullptr), ACL_SUCCESS);
EXPECT_EQ(aclFinalize(), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclrtGetVersionSuccess)
{
EXPECT_EQ(aclrtGetVersion(nullptr, nullptr, nullptr), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclDataTypeSizeCorrect)
{
EXPECT_EQ(aclDataTypeSize(ACL_FLOAT), 4);
EXPECT_EQ(aclDataTypeSize(ACL_FLOAT16), 2);
EXPECT_EQ(aclDataTypeSize(ACL_INT8), 1);
EXPECT_EQ(aclDataTypeSize(ACL_INT16), 2);
EXPECT_EQ(aclDataTypeSize(ACL_INT32), 4);
EXPECT_EQ(aclDataTypeSize(ACL_INT64), 8);
EXPECT_EQ(aclDataTypeSize(ACL_UINT8), 1);
EXPECT_EQ(aclDataTypeSize(ACL_UINT16), 2);
EXPECT_EQ(aclDataTypeSize(ACL_UINT32), 4);
EXPECT_EQ(aclDataTypeSize(ACL_UINT64), 8);
EXPECT_EQ(aclDataTypeSize(ACL_DOUBLE), 8);
EXPECT_EQ(aclDataTypeSize(ACL_BOOL), 1);
EXPECT_EQ(aclDataTypeSize(static_cast<aclDataType>(999)), 0);
}
TEST_F(TEST_ACL_STUB, AclFloat16AndFloatConvert)
{
float f_val = 123.0f;
aclFloat16 f16_val = aclFloatToFloat16(f_val);
float f_convert = aclFloat16ToFloat(f16_val);
EXPECT_NEAR(f_convert, f_val, 0.1f);
EXPECT_EQ(aclFloat16ToFloat(aclFloatToFloat16(0.0f)), 0.0f);
EXPECT_NEAR(aclFloat16ToFloat(aclFloatToFloat16(100.0f)), 100.0f, 0.1f);
}
TEST_F(TEST_ACL_STUB, AclrtDeviceStreamContextSuccess)
{
EXPECT_EQ(aclrtSetDevice(0), ACL_SUCCESS);
EXPECT_EQ(aclrtSetDevice(-1), ACL_SUCCESS);
EXPECT_EQ(aclrtResetDevice(0), ACL_SUCCESS);
aclrtStream stream = nullptr;
EXPECT_EQ(aclrtCreateStream(&stream), ACL_SUCCESS);
EXPECT_EQ(aclrtCreateStreamWithConfig(&stream, 10, 1), ACL_SUCCESS);
EXPECT_EQ(aclrtDestroyStream(stream), ACL_SUCCESS);
EXPECT_EQ(aclrtDestroyStreamForce(stream), ACL_SUCCESS);
EXPECT_EQ(aclrtSynchronizeStream(stream), ACL_SUCCESS);
aclrtContext ctx = nullptr;
EXPECT_EQ(aclrtCreateContext(&ctx, 0), ACL_SUCCESS);
EXPECT_EQ(aclrtDestroyContext(ctx), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclrtSynchronizeDeviceSuccess)
{
EXPECT_EQ(aclrtSynchronizeDevice(), ACL_SUCCESS);
}
TEST_F(TEST_ACL_STUB, AclrtMallocFreeSuccess)
{
void* dev_ptr = nullptr;
EXPECT_EQ(aclrtMalloc(&dev_ptr, 1024, ACL_MEM_MALLOC_HUGE_FIRST), ACL_SUCCESS);
EXPECT_NE(dev_ptr, nullptr);
EXPECT_EQ(aclrtFree(dev_ptr), ACL_SUCCESS);
EXPECT_EQ(aclrtMalloc(nullptr, 1024, ACL_MEM_MALLOC_HUGE_FIRST), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtMalloc(&dev_ptr, 0, ACL_MEM_MALLOC_HUGE_FIRST), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtFree(nullptr), ACL_ERROR_INVALID_PARAM);
}
TEST_F(TEST_ACL_STUB, AclrtMallocHostFreeHostSuccess)
{
void* host_ptr = nullptr;
EXPECT_EQ(aclrtMallocHost(&host_ptr, 2048), ACL_SUCCESS);
EXPECT_NE(host_ptr, nullptr);
EXPECT_EQ(aclrtFreeHost(host_ptr), ACL_SUCCESS);
EXPECT_EQ(aclrtMallocHost(nullptr, 2048), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtMallocHost(&host_ptr, 0), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtFreeHost(nullptr), ACL_ERROR_INVALID_PARAM);
}
TEST_F(TEST_ACL_STUB, AclrtMemsetSuccess)
{
char buf[1024] = {0};
EXPECT_EQ(aclrtMemset(buf, sizeof(buf), 0x55, sizeof(buf) / 2), ACL_SUCCESS);
for (int i = 0; i < static_cast<int>(sizeof(buf) / 2); ++i) {
EXPECT_EQ(buf[i], 0x55);
}
EXPECT_EQ(aclrtMemset(nullptr, 1024, 0, 512), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtMemset(buf, 1024, 0, 2048), ACL_ERROR_BAD_ALLOC);
}
TEST_F(TEST_ACL_STUB, AclrtMemsetAsyncSuccess)
{
char buf[1024] = {0};
aclrtStream stream = nullptr;
EXPECT_EQ(aclrtMemsetAsync(buf, sizeof(buf), 0x66, sizeof(buf), stream), ACL_SUCCESS);
for (int i = 0; i < static_cast<int>(sizeof(buf)); ++i) {
EXPECT_EQ(buf[i], 0x66);
}
EXPECT_EQ(aclrtMemsetAsync(nullptr, 1024, 0, 512, stream), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtMemsetAsync(buf, 1024, 0, 2048, stream), ACL_ERROR_BAD_ALLOC);
}
TEST_F(TEST_ACL_STUB, AclrtMemcpySuccess)
{
char src[1024] = "test_memcpy";
char dst[1024] = {0};
EXPECT_EQ(aclrtMemcpy(dst, sizeof(dst), src, strlen(src) + 1, ACL_MEMCPY_HOST_TO_HOST), ACL_SUCCESS);
EXPECT_STREQ(dst, src);
EXPECT_EQ(aclrtMemcpy(dst, 5, src, 10, ACL_MEMCPY_HOST_TO_HOST), ACL_ERROR_BAD_ALLOC);
}
TEST_F(TEST_ACL_STUB, AclrtMemcpyAsyncSuccess)
{
char src[1024] = "test_memcpy_async";
char dst[1024] = {0};
aclrtStream stream = nullptr;
EXPECT_EQ(aclrtMemcpyAsync(dst, sizeof(dst), src, strlen(src) + 1, ACL_MEMCPY_HOST_TO_HOST, stream), ACL_SUCCESS);
EXPECT_STREQ(dst, src);
EXPECT_EQ(aclrtMemcpyAsync(dst, 5, src, 10, ACL_MEMCPY_HOST_TO_HOST, stream), ACL_ERROR_BAD_ALLOC);
}
TEST_F(TEST_ACL_STUB, AclrtMemcpy2dSuccess)
{
char src[1024] = "test_memcpy2d";
char dst[1024] = {0};
EXPECT_EQ(aclrtMemcpy2d(dst, sizeof(dst), src, sizeof(src), strlen(src) + 1, 1, ACL_MEMCPY_HOST_TO_HOST), ACL_SUCCESS);
EXPECT_STREQ(dst, src);
EXPECT_EQ(aclrtMemcpy2d(dst, sizeof(dst), nullptr, sizeof(src), 10, 1, ACL_MEMCPY_HOST_TO_HOST), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtMemcpy2d(dst, 5, src, sizeof(src), 10, 1, ACL_MEMCPY_HOST_TO_HOST), ACL_ERROR_BAD_ALLOC);
}
TEST_F(TEST_ACL_STUB, AclrtMemcpy2dAsyncSuccess)
{
char src[1024] = "test_memcpy2d_async";
char dst[1024] = {0};
aclrtStream stream = nullptr;
EXPECT_EQ(aclrtMemcpy2dAsync(dst, sizeof(dst), src, sizeof(src), strlen(src) + 1, 1, ACL_MEMCPY_HOST_TO_HOST, stream), ACL_SUCCESS);
EXPECT_STREQ(dst, src);
EXPECT_EQ(aclrtMemcpy2dAsync(dst, sizeof(dst), nullptr, sizeof(src), 10, 1, ACL_MEMCPY_HOST_TO_HOST, stream), ACL_ERROR_INVALID_PARAM);
EXPECT_EQ(aclrtMemcpy2dAsync(dst, 5, src, sizeof(src), 10, 1, ACL_MEMCPY_HOST_TO_HOST, stream), ACL_ERROR_BAD_ALLOC);
}
TEST_F(TEST_ACL_STUB, AclrtMemcpy2dMultiRowPacked)
{
constexpr size_t rowBytes = 4 * sizeof(float);
constexpr size_t height = 3;
float src[height * 4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
float dst[height * 4] = {0};
EXPECT_EQ(aclrtMemcpy2d(dst, rowBytes, src, rowBytes, rowBytes, height, ACL_MEMCPY_HOST_TO_HOST), ACL_SUCCESS);
for (size_t i = 0; i < height * 4; ++i) {
EXPECT_EQ(dst[i], src[i]);
}
}
TEST_F(TEST_ACL_STUB, AclrtMemcpy2dStridedRows)
{
constexpr size_t width = 3 * sizeof(float);
constexpr size_t spitch = 5 * sizeof(float);
constexpr size_t dpitch = 4 * sizeof(float);
constexpr size_t height = 3;
float src[5 * height] = {1, 2, 3, 0, 0, 4, 5, 6, 0, 0, 7, 8, 9, 0, 0};
float dst[4 * height] = {0};
EXPECT_EQ(aclrtMemcpy2d(dst, dpitch, src, spitch, width, height, ACL_MEMCPY_HOST_TO_HOST), ACL_SUCCESS);
for (size_t row = 0; row < height; ++row) {
EXPECT_EQ(dst[row * 4 + 0], src[row * 5 + 0]);
EXPECT_EQ(dst[row * 4 + 1], src[row * 5 + 1]);
EXPECT_EQ(dst[row * 4 + 2], src[row * 5 + 2]);
}
}
TEST_F(TEST_ACL_STUB, AclrtMemcpy2dAsyncMultiRow)
{
constexpr size_t rowBytes = 4 * sizeof(float);
constexpr size_t height = 3;
float src[height * 4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
float dst[height * 4] = {0};
aclrtStream stream = nullptr;
EXPECT_EQ(aclrtMemcpy2dAsync(dst, rowBytes, src, rowBytes, rowBytes, height, ACL_MEMCPY_HOST_TO_HOST, stream),
ACL_SUCCESS);
for (size_t i = 0; i < height * 4; ++i) {
EXPECT_EQ(dst[i], src[i]);
}
}
TEST_F(TEST_ACL_STUB, AclrtBinaryLoadFromDataSuccess)
{
uint8_t elfData[512] = {0};
elfData[EI_MAG0] = 0x7f;
elfData[EI_MAG1] = 'E';
elfData[EI_MAG2] = 'L';
elfData[EI_MAG3] = 'F';
elfData[EI_CLASS] = ELFCLASS64;
elfData[EI_DATA] = ELFDATA2LSB;
elfData[40] = 64;
elfData[58] = 64;
elfData[60] = 2;
elfData[62] = 1;
Elf64_Shdr* shdr0 = reinterpret_cast<Elf64_Shdr*>(elfData + 64);
shdr0->sh_name = 0;
shdr0->sh_type = 0;
shdr0->sh_offset = 192;
shdr0->sh_size = 64;
Elf64_Shdr* shdr1 = reinterpret_cast<Elf64_Shdr*>(elfData + 128);
shdr1->sh_name = 1;
shdr1->sh_type = 0;
shdr1->sh_offset = 256;
shdr1->sh_size = 64;
const char* strTab = ".ascend.meta._Z11test_kernelv\0.shstrtab\n";
memcpy(elfData + 256, strTab, strlen(strTab) + 1);
uint8_t* metaSection = elfData + 192;
AscendC::ElfTlvHead* head = reinterpret_cast<AscendC::ElfTlvHead*>(metaSection);
head->type = AscendC::FUNC_META_TYPE_KERNEL_TYPE;
head->length = 4;
uint32_t kernelType = AscendC::K_TYPE_AIC;
memcpy(metaSection + sizeof(AscendC::ElfTlvHead), &kernelType, sizeof(uint32_t));
shdr0->sh_size = sizeof(AscendC::ElfTlvHead) + 4;
AscendC::KernelModeRegister& reg = AscendC::KernelModeRegister::GetInstance();
reg.Clear();
EXPECT_EQ(aclrtBinaryLoadFromData(elfData, sizeof(elfData), nullptr, nullptr), ACL_SUCCESS);
KernelMode mode = reg.GetKenelMode("_Z11test_kernelv");
EXPECT_EQ(mode, KernelMode::AIC_MODE);
}
TEST_F(TEST_ACL_STUB, AclrtBinaryLoadFromDataInvalidElf)
{
uint8_t elfData[32] = {0};
elfData[EI_MAG0] = 0x7f;
elfData[EI_MAG1] = 'E';
elfData[EI_MAG2] = 'L';
elfData[EI_MAG3] = 'X';
aclrtBinHandle binHandle = nullptr;
EXPECT_EQ(aclrtBinaryLoadFromData(elfData, sizeof(elfData), nullptr, &binHandle), ACL_ERROR_INVALID_PARAM);
}
TEST_F(TEST_ACL_STUB, AclrtBinaryLoadFromDataNullPointer)
{
aclrtBinHandle binHandle = nullptr;
EXPECT_EQ(aclrtBinaryLoadFromData(nullptr, 512, nullptr, &binHandle), ACL_ERROR_INVALID_PARAM);
}