已合并
fix: ASCEND_WORK_PATH指定trace日志产出文件的落盘路径,实际落盘到默认路径下 (#758) #3746
fix: ASCEND_WORK_PATH指定trace日志产出文件的落盘路径,实际落盘到默认路径下 (#758) #3746
已合并
GuoWenbo创建于 7月21日
2 个文件变更+275-20
@@ -91,8 +91,42 @@ STATIC TraStatus TraceMkdirRecur(const char *dirPath)
91 return err;91 return err;
92}92}
93 93 
94+STATIC TraStatus TraceNormalizeEnvPath(char *envDir, uint32_t len)
zhangjiezhangjie
zhangjiezhangjie7月21日

级别:一般 问题:TraceNormalizeEnvPath 直接访问 envDir[0],未对 envDir 为 NULL 或 len 为 0 的情况做防御性校验。 影响:若上游调用者传入 NULL(例如 getenv 失败回填的指针)或 len==0,将触发空指针解引用或越界读,导致进程崩溃。 修复建议:在函数入口增加 if (envDir == NULL || len == 0) { return TRACE_FAILURE; } 校验。

likedislike
zhangjiezhangjie7月21日

级别:一般 问题:未对空字符串场景做处理。当 envDir 为 "" 时,envDir[0] != '/',会进入归一化分支,生成 "/" 的路径,语义不明确且后续 TraceAccess/TraceMkdirRecur 行为可能不符合预期。 影响:环境变量被误设为空时,不会按预期失败,而是在 cwd 下创建意外目录,污染工作目录。 修复建议:在绝对路径判断前增加 strlen(envDir) == 0 的非法判断,直接返回 TRACE_FAILURE。

likedislike
95+{
96+ if ((envDir == NULL) || (len == 0U) || (envDir[0] == '\0')) {
97+ ADIAG_WAR("ASCEND_WORK_PATH is invalid.");
98+ return TRACE_FAILURE;
99+ }
100+ if (envDir[0] == '/') {
101+ return TRACE_SUCCESS;
102+ }
103+ 
104+ char cwd[MAX_FILEDIR_LEN + 1U] = { 0 };
105+ if (getcwd(cwd, sizeof(cwd)) == NULL) {
106+ ADIAG_WAR("get current directory failed, strerr=%s.", strerror(AdiagGetErrorCode()));
107+ return TRACE_FAILURE;
zhangjie
zhangjiezhangjie7月21日

级别:提示 问题:absPath 与 cwd 缓冲固定为 MAX_FILEDIR_LEN+1,但 envDir 的容量由参数 len 决定。当 cwd 与 envDir 拼接后长度超过 MAX_FILEDIR_LEN 时,snprintf_s 截断后返回 -1,函数返回失败,行为可接受但缺少对路径过长的明确日志区分。 影响:路径过长导致的失败与环境/系统调用失败混在一起,排障困难。 修复建议:可在 snprintf_s 失败时进一步使用 strerror(errno) 或单独日志标注是路径过长,便于定位。

likedislike
108+ }
109+ 
110+ char absPath[MAX_FILEDIR_LEN + 1U] = { 0 };
111+ int32_t ret = snprintf_s(absPath, sizeof(absPath), sizeof(absPath) - 1U, "%s/%s", cwd, envDir);
112+ if (ret == -1) {
113+ ADIAG_WAR("build ASCEND_WORK_PATH absolute path failed, path may exceed %u bytes, cwd=%s, env=%s.",
114+ MAX_FILEDIR_LEN, cwd, envDir);
115+ return TRACE_FAILURE;
zhangjie
zhangjiezhangjie7月21日

级别:一般 问题:若 envDir 由 getenv() 返回的指针直接传入,TraceNormalizeEnvPath 使用 strcpy_s 原地改写 envDir 内容,属于修改 getenv 返回值,POSIX 标准中该行为未定义。 影响:若上游确实传入 getenv() 返回的内存,可能破坏进程环境块、引发 UB 或在多线程读取环境变量时出现数据竞争。 修复建议:确认调用链中 envDir 是否为 getenv 直接返回值;若是,应改为拷贝到本地缓冲后再归一化,避免修改 getenv 返回值。

likedislike
116+ }
117+ ret = strcpy_s(envDir, len, absPath);
atomgit-bot
atomgit-botatomgit-bot7月21日

🟡 Medium Priority

TraceNormalizeEnvPath 函数(第 112 行)中,strcpy_s(envDir, len, absPath) 的调用存在缓冲区大小不匹配问题:

触发条件:strlen(cwd) + 1 + strlen(envDir) == 255,即当前工作目录长度加上原环境变量路径长度恰好等于 MAX_FILEDIR_LEN-1。此时 snprintf_s 不会报错(正好写满 255 字符),但后续 strcpy_s 会失败。

失败后果:TraceNormalizeEnvPath 返回 TRACE_FAILURE,进而导致 TraceGetEnvPath 失败,TraceInitRootPath 回退到使用 home 目录的默认路径,与 Issue #758 描述的 bug 行为一致——用户指定的相对路径被忽略,回退到默认路径。

建议:将 strcpy_s(envDir, len, absPath) 改为 strcpy_s(envDir, (size_t)len + 1U, absPath)。但这要求调用方确保 envDir 的实际缓冲区大小至少为 len + 1。更好的方案是:将 TraceInitRootPathAdiagMalloc(MAX_FILEDIR_LEN) 改为 AdiagMalloc(MAX_FILEDIR_LEN + 1U),确保缓冲区始终多 1 字节以容纳 null 终止符。或者改用 snprintf_s 直接写入 envDir,跳过中间的 absPathstrcpy_s

改动建议
117
- ret = strcpy_s(envDir, len, absPath);
117
+ ret = strcpy_s(envDir, (size_t)len + 1U, absPath);
118
+ if (ret != EOK) {
119
+ ADIAG_WAR("copy ASCEND_WORK_PATH absolute path failed, ret=%d.", ret);
120
+ return TRACE_FAILURE;
121
+ }
应用建议
likedislike
不准确?
118+ if (ret != EOK) {
119+ ADIAG_WAR("copy ASCEND_WORK_PATH absolute path failed, ret=%d.", ret);
120+ return TRACE_FAILURE;
121+ }
122+ return TRACE_SUCCESS;
123+}
124+ 
94STATIC TraStatus TraceGetValidPath(char *envDir, uint32_t len)125STATIC TraStatus TraceGetValidPath(char *envDir, uint32_t len)
95{126{
127+ if (TraceNormalizeEnvPath(envDir, len) != TRACE_SUCCESS) {
128+ return TRACE_FAILURE;
129+ }
96 if ((TraceAccess(envDir, F_OK) != EN_OK) && (TraceMkdirRecur(envDir) != EN_OK)) {130 if ((TraceAccess(envDir, F_OK) != EN_OK) && (TraceMkdirRecur(envDir) != EN_OK)) {
97 ADIAG_WAR("path %s doesn't exist.", envDir);131 ADIAG_WAR("path %s doesn't exist.", envDir);
98 return TRACE_FAILURE;132 return TRACE_FAILURE;
@@ -182,16 +216,16 @@ STATIC TraStatus TraceInitRootPath(TraceRecorderMgr *mgr)
182 return TRACE_FAILURE;216 return TRACE_FAILURE;
183 }217 }
184#else218#else
185- char *path = (char *)AdiagMalloc(MAX_FILEDIR_LEN);219+ char *path = (char *)AdiagMalloc(MAX_FILEDIR_LEN + 1U);
186 ADIAG_CHK_EXPR_ACTION(path == NULL, return TRACE_FAILURE,220 ADIAG_CHK_EXPR_ACTION(path == NULL, return TRACE_FAILURE,
187 "malloc root path failed, strerr=%s", strerror(AdiagGetErrorCode()));221 "malloc root path failed, strerr=%s", strerror(AdiagGetErrorCode()));
188 222 
189- TraStatus ret = TraceGetEnvPath(path, MAX_FILEDIR_LEN);223+ TraStatus ret = TraceGetEnvPath(path, MAX_FILEDIR_LEN + 1U);
190 if (ret == TRACE_SUCCESS) {224 if (ret == TRACE_SUCCESS) {
191 res = snprintf_truncated_s(mgr->rootPath, MAX_FILEDIR_LEN + 1U, "%s", path);225 res = snprintf_truncated_s(mgr->rootPath, MAX_FILEDIR_LEN + 1U, "%s", path);
192 } else {226 } else {
193 // get process user home path227 // get process user home path
194- ret = TraceGetHomeDir(path, MAX_FILEDIR_LEN);228+ ret = TraceGetHomeDir(path, MAX_FILEDIR_LEN + 1U);
195 if (ret != TRACE_SUCCESS) {229 if (ret != TRACE_SUCCESS) {
196 ADIAG_SAFE_FREE(path);230 ADIAG_SAFE_FREE(path);
197 ADIAG_ERR("get home directory failed, ret=%d.", ret);231 ADIAG_ERR("get home directory failed, ret=%d.", ret);
@@ -20,7 +20,9 @@
20#include <atomic>20#include <atomic>
21#include <cerrno>21#include <cerrno>
22#include <fcntl.h>22#include <fcntl.h>
23+#include <string>
23#include <sys/stat.h>24#include <sys/stat.h>
25+#include <vector>
24 26 
25#define TIMESTAMP_MAX_LENGTH 29U27#define TIMESTAMP_MAX_LENGTH 29U
26 28 
@@ -28,6 +30,7 @@ static std::atomic<uint32_t> g_traceOpenCallIndex(0);
28static std::atomic<bool> g_firstTraceOpenEntered(false);30static std::atomic<bool> g_firstTraceOpenEntered(false);
29static std::atomic<bool> g_allowFirstTraceOpen(false);31static std::atomic<bool> g_allowFirstTraceOpen(false);
30static std::atomic<bool> g_agingThreadDone(false);32static std::atomic<bool> g_agingThreadDone(false);
33+static std::atomic<uint32_t> g_strcpyCallIndex(0);
31 34 
32typedef struct {35typedef struct {
33 TraceDirInfo dirInfo;36 TraceDirInfo dirInfo;
@@ -59,6 +62,39 @@ int32_t TraceOpenBlockFirstThenOpen(const char *filePath, int32_t flag, uint32_t
59 return fd;62 return fd;
60}63}
61 64 
65+TraStatus TraceHandleEmptyEnvStringStub(const char *env, char *buf, uint32_t len)
66+{
67+ (void)env;
68+ if ((buf == nullptr) || (len == 0U)) {
69+ return TRACE_FAILURE;
70+ }
71+ buf[0] = '\0';
72+ return TRACE_SUCCESS;
73+}
74+ 
75+TraStatus TraceHandleRelativeEnvStringStub(const char *env, char *buf, uint32_t len)
76+{
77+ (void)env;
78+ const char relativePath[] = "trace_recorder_copy_failed_path";
79+ if ((buf == nullptr) || (len <= strlen(relativePath))) {
80+ return TRACE_FAILURE;
81+ }
82+ errno_t ret = memcpy_s(buf, len, relativePath, strlen(relativePath) + 1U);
83+ return (ret == EOK) ? TRACE_SUCCESS : TRACE_FAILURE;
84+}
85+ 
86+errno_t StrcpyFailOnceThenCopy(char *strDest, size_t destMax, const char *strSrc)
87+{
88+ if (g_strcpyCallIndex.fetch_add(1U) == 0U) {
89+ return EINVAL;
90+ }
91+ if ((strDest == nullptr) || (strSrc == nullptr) || (destMax == 0U) || (strlen(strSrc) >= destMax)) {
92+ return EINVAL;
93+ }
94+ errno_t ret = memcpy_s(strDest, destMax, strSrc, strlen(strSrc) + 1U);
95+ return (ret == EOK) ? EOK : EINVAL;
96+}
97+ 
62void *TraceRecorderGetFdThread(void *arg)98void *TraceRecorderGetFdThread(void *arg)
63{99{
64 TraceGetFdThreadArg *threadArg = static_cast<TraceGetFdThreadArg *>(arg);100 TraceGetFdThreadArg *threadArg = static_cast<TraceGetFdThreadArg *>(arg);
@@ -113,9 +149,52 @@ bool BuildRecorderFilePath(char *path, size_t len, const char *eventName, const
113 int32_t ret = snprintf_s(path, len, len - 1U, "%s/%s_tracer_%s%s", dirPath, tracerName, objName, suffix);149 int32_t ret = snprintf_s(path, len, len - 1U, "%s/%s_tracer_%s%s", dirPath, tracerName, objName, suffix);
114 return ret != -1;150 return ret != -1;
115}151}
116- 152+ 
zhangjiezhangjie
zhangjiezhangjie7月21日

级别:一般 问题:ScopedCwdAndEnv 通过 chdir 修改进程级 cwd,属于进程全局状态。若 gtest 启用并行执行(--jobs 或自定义 runner),或与 TestRecord_Concurrent 等用例并发运行,会相互污染工作目录。 影响:并行测试场景下用例间 cwd 相互干扰,出现间歇性失败、不稳定用例。 修复建议:在用例内禁用并行(或显式标注为串行用例);如必须改 cwd,考虑使用子进程隔离或在用例文档中明确依赖串行执行。

likedislike
zhangjiezhangjie7月21日

级别:提示 问题:测试新增了相对路径场景,但缺少以下覆盖:1) envDir 为 NULL/空字符串的边界;2) 相对路径以 "./" 或 "../" 开头;3) cwd + envDir 拼接超过 MAX_FILEDIR_LEN 的截断/失败路径。 影响:新增逻辑的边界与异常分支未被覆盖,回归保护不足。 修复建议:补充对应 UT 用例,验证空字符串、"../"、超长路径等场景返回 TRACE_FAILURE。

likedislike
117-class TraceRecorderUtest: public testing::Test {153+bool BuildRecorderFilePathWithRoot(char *path, size_t len, const char *rootPath, const char *eventName,
118-protected:154+ const char *dirTime, const char *tracerName, const char *objName, const char *suffix)
155+{
156+ int32_t ret = snprintf_s(path, len, len - 1U, "%s/atrace/trace_%d_%d_%s/%s_event_%d_%s/%s_tracer_%s%s",
157+ rootPath, TraceAttrGetPgid(), TraceAttrGetPid(), TraceAttrGetTime(), eventName, getpid(), dirTime,
158+ tracerName, objName, suffix);
159+ return ret != -1;
160+}
161+ 
162+void RemoveTestPath(const std::string &path)
163+{
164+ if (path.empty()) {
165+ return;
166+ }
167+ std::string cmd = "rm -rf " + path;
168+ (void)system(cmd.c_str());
169+}
170+ 
171+class ScopedEnvAndPathCleanup {
172+public:
173+ explicit ScopedEnvAndPathCleanup(const char *envName) : envName_(envName)
174+ {
175+ }
176+ 
177+ ~ScopedEnvAndPathCleanup()
178+ {
179+ unsetenv(envName_);
180+ for (auto iter = cleanupPaths_.rbegin(); iter != cleanupPaths_.rend(); ++iter) {
181+ RemoveTestPath(*iter);
182+ }
183+ }
184+ 
185+ void AddPath(const std::string &path)
186+ {
187+ cleanupPaths_.push_back(path);
188+ RemoveTestPath(path);
189+ }
190+ 
191+private:
192+ const char *envName_;
193+ std::vector<std::string> cleanupPaths_;
194+};
195+ 
196+class TraceRecorderUtest: public testing::Test {
197+protected:
119 static void SetUpTestCase()198 static void SetUpTestCase()
120 {199 {
121 }200 }
@@ -196,22 +275,164 @@ TEST_F(TraceRecorderUtest, TestRecord_Concurrent)
196 unsetenv("ASCEND_WORK_PATH");275 unsetenv("ASCEND_WORK_PATH");
197}276}
198 277 
199-TEST_F(TraceRecorderUtest, TestRecordEnvPath)278+TEST_F(TraceRecorderUtest, TestRecordEnvPath)
200-{279+{
201- TraceRecorderExit();280+ TraceRecorderExit();
202- setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1);281+ setenv("ASCEND_WORK_PATH", LLT_TEST_DIR, 1);
203- EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit());282+ EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit());
204 283 
205 TestRecorderWrite(1, 1, 2, TRACE_FILE_TXT_SUFFIX);284 TestRecorderWrite(1, 1, 2, TRACE_FILE_TXT_SUFFIX);
206- 285+ 
207- unsetenv("ASCEND_WORK_PATH");286+ unsetenv("ASCEND_WORK_PATH");
208-}287+}
209- 288+ 
210-TEST_F(TraceRecorderUtest, TestRecordEnvInvalidPath)289+TEST_F(TraceRecorderUtest, TestRecordEnvRelativePath)
211-{290+{
212- printf("path doesn't exist, then create it successfully.\n");291+ TraceRecorderExit();
213- TraceRecorderExit();292+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
214- setenv("ASCEND_WORK_PATH", LLT_TEST_DIR "/env/", 1);293+ const std::string relativeDir = "trace_recorder_relative_path_ut";
294+ envGuard.AddPath(relativeDir);
295+ setenv("ASCEND_WORK_PATH", ("./" + relativeDir).c_str(), 1);
296+ ASSERT_EQ(TRACE_SUCCESS, TraceRecorderInit());
297+ 
298+ const char *dirTime = "19700101080004000001";
299+ TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTime, true };
300+ TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "relative", TRACE_FILE_TXT_SUFFIX };
301+ int32_t fd = -1;
302+ auto ret = TraceRecorderGetFd(&dirInfo, &fileInfo, &fd);
303+ ASSERT_EQ(TRACE_SUCCESS, ret);
304+ EXPECT_EQ(TRACE_SUCCESS, TraceRecorderWrite(fd, "relative", 8U));
305+ if (fd >= 0) {
306+ close(fd);
307+ }
308+ 
309+ char cwd[MAX_FILEDIR_LEN + 1U] = {0};
310+ ASSERT_NE(nullptr, getcwd(cwd, sizeof(cwd)));
311+ std::string expectedRoot = std::string(cwd) + "/" + relativeDir;
312+ char filePath[MAX_FULLPATH_LEN + 1U] = {0};
313+ ASSERT_TRUE(BuildRecorderFilePathWithRoot(filePath, MAX_FULLPATH_LEN + 1U, expectedRoot.c_str(),
314+ TRACER_SCHEDULE_NAME, dirTime, TRACER_SCHEDULE_NAME, "relative", TRACE_FILE_TXT_SUFFIX));
315+ EXPECT_EQ(0, access(filePath, F_OK));
316+}
317+ 
318+TEST_F(TraceRecorderUtest, TestRecordEnvRelativePathWithParentDir)
319+{
320+ TraceRecorderExit();
321+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
322+ const std::string parentDir = "trace_recorder_relative_dotdot_parent";
323+ const std::string targetDir = "trace_recorder_relative_dotdot_target";
324+ envGuard.AddPath(parentDir);
325+ envGuard.AddPath(targetDir);
326+ setenv("ASCEND_WORK_PATH", (parentDir + "/../" + targetDir).c_str(), 1);
327+ ASSERT_EQ(TRACE_SUCCESS, TraceRecorderInit());
328+ 
329+ const char *dirTime = "19700101080004000002";
330+ TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTime, true };
331+ TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "dotdot", TRACE_FILE_TXT_SUFFIX };
332+ int32_t fd = -1;
333+ auto ret = TraceRecorderGetFd(&dirInfo, &fileInfo, &fd);
334+ ASSERT_EQ(TRACE_SUCCESS, ret);
335+ if (fd >= 0) {
336+ close(fd);
337+ }
338+ 
339+ char cwd[MAX_FILEDIR_LEN + 1U] = {0};
340+ ASSERT_NE(nullptr, getcwd(cwd, sizeof(cwd)));
341+ std::string expectedRoot = std::string(cwd) + "/" + targetDir;
342+ char filePath[MAX_FULLPATH_LEN + 1U] = {0};
343+ ASSERT_TRUE(BuildRecorderFilePathWithRoot(filePath, MAX_FULLPATH_LEN + 1U, expectedRoot.c_str(),
344+ TRACER_SCHEDULE_NAME, dirTime, TRACER_SCHEDULE_NAME, "dotdot", TRACE_FILE_TXT_SUFFIX));
345+ EXPECT_EQ(0, access(filePath, F_OK));
346+}
347+ 
348+TEST_F(TraceRecorderUtest, TestRecordEnvEmptyPathFallbackToHome)
349+{
350+ TraceRecorderExit();
351+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
352+ setenv("ASCEND_WORK_PATH", "", 1);
353+ ASSERT_EQ(TRACE_SUCCESS, TraceRecorderInit());
354+ 
355+ const char *dirTime = "19700101080004000003";
356+ TraceDirInfo dirInfo = { TRACER_SCHEDULE_NAME, getpid(), dirTime, true };
357+ TraceFileInfo fileInfo = { TRACER_SCHEDULE_NAME, "empty", TRACE_FILE_TXT_SUFFIX };
358+ int32_t fd = -1;
359+ auto ret = TraceRecorderGetFd(&dirInfo, &fileInfo, &fd);
360+ ASSERT_EQ(TRACE_SUCCESS, ret);
361+ if (fd >= 0) {
362+ close(fd);
363+ }
364+ 
365+ char filePath[MAX_FULLPATH_LEN + 1U] = {0};
366+ ASSERT_TRUE(BuildRecorderFilePathWithRoot(filePath, MAX_FULLPATH_LEN + 1U, LLT_TEST_DIR "/ascend",
367+ TRACER_SCHEDULE_NAME, dirTime, TRACER_SCHEDULE_NAME, "empty", TRACE_FILE_TXT_SUFFIX));
368+ EXPECT_EQ(0, access(filePath, F_OK));
369+}
370+ 
371+TEST_F(TraceRecorderUtest, TestRecordEnvNormalizeEmptyBufferFallbackToHome)
372+{
373+ TraceRecorderExit();
374+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
375+ MOCKER(TraceHandleEnvString).stubs().will(invoke(TraceHandleEmptyEnvStringStub));
376+ ASSERT_EQ(TRACE_SUCCESS, TraceRecorderInit());
377+ GlobalMockObject::verify();
378+}
379+ 
380+TEST_F(TraceRecorderUtest, TestRecordEnvRelativePathGetcwdFailedFallbackToHome)
381+{
382+ TraceRecorderExit();
383+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
384+ setenv("ASCEND_WORK_PATH", "trace_recorder_getcwd_failed_path", 1);
385+ MOCKER(getcwd).stubs().will(returnValue((char *)nullptr));
386+ ASSERT_EQ(TRACE_SUCCESS, TraceRecorderInit());
387+ GlobalMockObject::verify();
388+}
389+ 
390+TEST_F(TraceRecorderUtest, TestRecordEnvRelativePathCopyFailedFallbackToHome)
391+{
392+ TraceRecorderExit();
393+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
394+ g_strcpyCallIndex.store(0U);
395+ MOCKER(TraceHandleEnvString).stubs().will(invoke(TraceHandleRelativeEnvStringStub));
396+ MOCKER(strcpy_s).stubs().will(invoke(StrcpyFailOnceThenCopy));
397+ ASSERT_EQ(TRACE_SUCCESS, TraceRecorderInit());
398+ GlobalMockObject::verify();
399+}
400+ 
401+TEST_F(TraceRecorderUtest, TestRecordEnvRelativePathMaxLengthInitSucceeds)
402+{
403+ TraceRecorderExit();
404+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
405+ char cwd[MAX_FILEDIR_LEN + 1U] = {0};
406+ ASSERT_NE(nullptr, getcwd(cwd, sizeof(cwd)));
407+ ASSERT_LT(strlen(cwd) + 1U, static_cast<size_t>(MAX_FILEDIR_LEN));
408+ size_t relativeLen = static_cast<size_t>(MAX_FILEDIR_LEN) - strlen(cwd) - 1U;
409+ std::string relativeDir(relativeLen, 'a');
410+ envGuard.AddPath(relativeDir);
411+ setenv("ASCEND_WORK_PATH", relativeDir.c_str(), 1);
412+ EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit());
413+ EXPECT_EQ(0, access(relativeDir.c_str(), F_OK));
414+}
415+ 
416+TEST_F(TraceRecorderUtest, TestRecordEnvRelativePathTooLongFallbackToHome)
417+{
418+ TraceRecorderExit();
419+ ScopedEnvAndPathCleanup envGuard("ASCEND_WORK_PATH");
420+ char cwd[MAX_FILEDIR_LEN + 1U] = {0};
421+ ASSERT_NE(nullptr, getcwd(cwd, sizeof(cwd)));
422+ ASSERT_LT(strlen(cwd), static_cast<size_t>(MAX_FILEDIR_LEN));
423+ size_t relativeLen = static_cast<size_t>(MAX_FILEDIR_LEN) - strlen(cwd) + 1U;
424+ std::string relativeDir(relativeLen, 'b');
425+ envGuard.AddPath(relativeDir);
426+ setenv("ASCEND_WORK_PATH", relativeDir.c_str(), 1);
427+ EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit());
428+ EXPECT_NE(0, access(relativeDir.c_str(), F_OK));
429+}
430+ 
431+TEST_F(TraceRecorderUtest, TestRecordEnvInvalidPath)
432+{
433+ printf("path doesn't exist, then create it successfully.\n");
434+ TraceRecorderExit();
435+ setenv("ASCEND_WORK_PATH", LLT_TEST_DIR "/env/", 1);
215 EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit());436 EXPECT_EQ(TRACE_SUCCESS, TraceRecorderInit());
216 437 
217 printf("path doesn't exist, then create it failed.\n");438 printf("path doesn't exist, then create it failed.\n");