* 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.
*/
* \file test_output_dir.cpp
* \brief Unit tests for OutputBaseDir() and GetEmitPath() in config_manager
*/
#include <cstdlib>
#include <string>
#include <sys/stat.h>
#include "gtest/gtest.h"
#include "tilefwk/tilefwk.h"
#include "interface/configs/config_manager.h"
#include "tilefwk/pypto_fwk_log.h"
using namespace npu::tile_fwk;
class TestOutputDir : public testing::Test {
public:
static void SetUpTestCase() {}
static void TearDownTestCase() {}
void SetUp() override
{
savedTileFwkDir_ = GetEnvOrEmpty("TILE_FWK_OUTPUT_DIR");
savedAscendWorkPath_ = GetEnvOrEmpty("ASCEND_WORK_PATH");
savedDeviceId_ = GetEnvOrEmpty("TILE_FWK_DEVICE_ID");
}
void TearDown() override
{
RestoreEnv("TILE_FWK_OUTPUT_DIR", savedTileFwkDir_);
RestoreEnv("ASCEND_WORK_PATH", savedAscendWorkPath_);
RestoreEnv("TILE_FWK_DEVICE_ID", savedDeviceId_);
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, false);
}
static std::string GetEnvOrEmpty(const char* name)
{
const char* val = std::getenv(name);
return (val != nullptr) ? std::string(val) : std::string();
}
static void SetEnv(const char* name, const char* value) { setenv(name, value, 1); }
static void UnsetEnv(const char* name) { unsetenv(name); }
static void RestoreEnv(const char* name, const std::string& value)
{
if (value.empty()) {
unsetenv(name);
} else {
setenv(name, value.c_str(), 1);
}
}
protected:
std::string savedTileFwkDir_;
std::string savedAscendWorkPath_;
std::string savedDeviceId_;
};
TEST_F(TestOutputDir, GetEmitPath_UsesLogTopFolderByDefault)
{
UnsetEnv("TILE_FWK_OUTPUT_DIR");
UnsetEnv("ASCEND_WORK_PATH");
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, false);
std::string path = config::GetEmitPath("kernel_aicore");
EXPECT_FALSE(path.empty());
EXPECT_NE(path.find("kernel_aicore"), std::string::npos);
EXPECT_NE(path.find("output"), std::string::npos);
}
TEST_F(TestOutputDir, GetEmitPath_FixedPathWithAscendWork)
{
const char* workPath = "/tmp/test_ut_ascend_work";
SetEnv("ASCEND_WORK_PATH", workPath);
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string path = config::GetEmitPath("kernel_aicore");
EXPECT_NE(path.find(workPath), std::string::npos);
EXPECT_NE(path.find("pypto"), std::string::npos);
EXPECT_NE(path.find("kernel_aicore"), std::string::npos);
}
TEST_F(TestOutputDir, GetEmitPath_FixedPathWithoutAscendWork)
{
UnsetEnv("ASCEND_WORK_PATH");
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string path = config::GetEmitPath("kernel_aicore");
EXPECT_EQ(path, "kernel_aicore");
}
TEST_F(TestOutputDir, GetEmitPath_FixedPathWithDeviceId)
{
const char* workPath = "/tmp/test_ut_ascend_work2";
SetEnv("ASCEND_WORK_PATH", workPath);
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string path = config::GetEmitPath("kernel_aicpu");
EXPECT_NE(path.find(workPath), std::string::npos);
EXPECT_NE(path.find("pypto"), std::string::npos);
EXPECT_NE(path.find("kernel_aicpu"), std::string::npos);
}
TEST_F(TestOutputDir, GetEmitPath_DifferentNames)
{
UnsetEnv("ASCEND_WORK_PATH");
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string pathCore = config::GetEmitPath("kernel_aicore");
std::string pathCpu = config::GetEmitPath("kernel_aicpu");
EXPECT_EQ(pathCore, "kernel_aicore");
EXPECT_EQ(pathCpu, "kernel_aicpu");
EXPECT_NE(pathCore, pathCpu);
}
TEST_F(TestOutputDir, GetEmitPath_TileFwkOutputDirTakesPriority)
{
SetEnv("TILE_FWK_OUTPUT_DIR", "/tmp/tile_fwk_override_test");
SetEnv("ASCEND_WORK_PATH", "/tmp/ascend_work_test");
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string path = config::GetEmitPath("kernel_aicore");
EXPECT_NE(path.find("ascend_work_test"), std::string::npos);
EXPECT_EQ(path.find("tile_fwk_override_test"), std::string::npos);
}
TEST_F(TestOutputDir, GetEmitPath_EmptyName)
{
UnsetEnv("ASCEND_WORK_PATH");
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string path = config::GetEmitPath("");
EXPECT_TRUE(path.empty());
}
TEST_F(TestOutputDir, GetEmitPath_RepeatedCallsConsistent)
{
const char* workPath = "/tmp/test_ut_consistency";
mkdir(workPath, 0755);
SetEnv("ASCEND_WORK_PATH", workPath);
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, true);
std::string path1 = config::GetEmitPath("kernel_aicore");
std::string path2 = config::GetEmitPath("kernel_aicore");
EXPECT_EQ(path1, path2);
ConfigManager::Instance().SetCodeGenConfig(KEY_FIXED_OUTPUT_PATH, false);
std::string path3 = config::GetEmitPath("kernel_aicore");
std::string path4 = config::GetEmitPath("kernel_aicore");
EXPECT_EQ(path3, path4);
EXPECT_NE(path1, path3);
}
TEST_F(TestOutputDir, OutputBaseDir_ReturnsNonEmpty)
{
const std::string& dir = config::OutputBaseDir();
EXPECT_FALSE(dir.empty());
}