From c410e859783438e40a6ec6c1bc386c25c4d6d9b1 Mon Sep 17 00:00:00 2001 From: youge325 Date: Sun, 14 Jun 2026 15:40:02 +0800 Subject: [PATCH 01/10] docs(skill): update branch creation workflow --- .claude/skills/add-compat-api/SKILL.md | 4 ++-- .../skills/add-compat-api/references/Step7.md | 18 +++++++++++------- .claude/skills/fix-compat-api/SKILL.md | 2 +- .github/skills/add-compat-api/SKILL.md | 4 ++-- .../skills/add-compat-api/references/Step7.md | 18 +++++++++++------- .github/skills/fix-compat-api/SKILL.md | 2 +- 6 files changed, 28 insertions(+), 20 deletions(-) diff --git a/.claude/skills/add-compat-api/SKILL.md b/.claude/skills/add-compat-api/SKILL.md index 1bc79e5..b784e5e 100644 --- a/.claude/skills/add-compat-api/SKILL.md +++ b/.claude/skills/add-compat-api/SKILL.md @@ -202,12 +202,12 @@ bash test/result_cmp.sh ./build/ 闭环验证通过且文档已回填后,按以下流程提交。完整命令模板见 [`references/Step7.md`](references/Step7.md)。 -1. **从 fork 主分支 checkout 新分支**(`git fetch upstream && git checkout -B add/- upstream/develop`) +1. **从本地跟踪 origin 的 develop 创建新分支**(`git checkout develop && git pull --ff-only origin develop && git checkout -b add/-`) 2. **commit 改动**(commit message 首行使用 `[Cpp API Compatibility] <对齐迭代记录标题>`) 3. **push 到 fork**(`git push origin `) 4. **`gh pr create` 到 upstream**(`--repo PaddlePaddle/Paddle --base develop`) 5. **同步 PCAT 测试改动** - 1. **从 fork 主分支 checkout 新分支**(`cd "$PCAT_ROOT" && git fetch upstream && git checkout -B test/- upstream/master`) + 1. **从本地跟踪 origin 的 master 创建新分支**(`cd "$PCAT_ROOT" && git checkout master && git pull --ff-only origin master && git checkout -b test/-`) 2. **commit 改动**(commit message 首行使用 `test(): align with Paddle compat 行为`) 3. **push 到 fork**(`git push origin `) 4. **`gh pr create` 到 upstream**(`--repo PFCCLab/PaddleCppAPITest --base master`,PR body 中加 `Related: PaddlePaddle/Paddle#`) diff --git a/.claude/skills/add-compat-api/references/Step7.md b/.claude/skills/add-compat-api/references/Step7.md index 892239d..ec2f5d4 100644 --- a/.claude/skills/add-compat-api/references/Step7.md +++ b/.claude/skills/add-compat-api/references/Step7.md @@ -13,24 +13,27 @@ 任一未通过 → **不要**进入本流程。 -## 1) 从 fork 主分支 checkout 新分支 +## 1) 从本地跟踪 origin 的基分支创建新分支 ### Paddle 侧 ```bash cd "$PADDLE_ROOT" -git fetch upstream +git checkout develop +git pull --ff-only origin develop # add 流程 -git checkout -B "add/-$(date +%Y%m%d)" upstream/develop +git checkout -b "add/-$(date +%Y%m%d)" # fix 流程 -git checkout -B "fix/-$(date +%Y%m%d)" upstream/develop +git checkout -b "fix/-$(date +%Y%m%d)" ``` 分支命名规则: - add:`add/-`(例:`add/abs-20260519`) - fix:`fix/-`(例:`fix/78652-20260519`) -> 前提:Paddle 仓库已配置 `origin = /Paddle` 与 `upstream = PaddlePaddle/Paddle`。若 remote 缺失,**提示用户配置后再继续**,不要主动改用户仓库的 remote。 +> 实际执行时只选 add 或 fix 对应的一条 `git checkout -b`。若分支已存在,`git checkout -b` 会失败;换新分支名或让用户手动处理,**不要**改用 `-B` 覆盖已有分支。 +> +> 前提:Paddle 仓库已配置 `origin = /Paddle` 与 `upstream = PaddlePaddle/Paddle`,且本地 `develop` 跟踪 `origin/develop`。若 remote 或本地基分支缺失,**提示用户配置后再继续**,不要主动改用户仓库的 remote。 ## 2) commit 改动 @@ -100,8 +103,9 @@ EOF ```bash cd "$PCAT_ROOT" -git fetch upstream -git checkout -B "test/-$(date +%Y%m%d)" upstream/master +git checkout master +git pull --ff-only origin master +git checkout -b "test/-$(date +%Y%m%d)" git add test/<改动文件> git commit -m "test(): align with Paddle compat 行为" git push origin diff --git a/.claude/skills/fix-compat-api/SKILL.md b/.claude/skills/fix-compat-api/SKILL.md index 9245cf8..d366845 100644 --- a/.claude/skills/fix-compat-api/SKILL.md +++ b/.claude/skills/fix-compat-api/SKILL.md @@ -218,7 +218,7 @@ bash test/result_cmp.sh ./build/ 闭环验证通过且文档已回填后,按以下流程提交。完整命令模板见 [`../add-compat-api/references/Step7.md`](../add-compat-api/references/Step7.md)(与 `add-compat-api` 共享同一份 references)。 -1. **从 fork 主分支 checkout 新分支**(`git fetch upstream && git checkout -B fix/- upstream/develop`) +1. **从本地跟踪 origin 的 develop 创建新分支**(`git checkout develop && git pull --ff-only origin develop && git checkout -b fix/-`) 2. **commit 改动**(commit message 首行使用 `[Cpp API Compatibility] `) 3. **征求用户同意后 push 到 fork**(`git push origin `——这是发出去的动作,**push 前必须明确询问用户**) 4. **征求用户同意后 `gh pr create` 到 upstream**(`--repo PaddlePaddle/Paddle --base develop`——同样需要用户确认;若本轮修复源自外部 PR/Actions/comment 链接,PR 描述里应**引用原链接**便于追溯) diff --git a/.github/skills/add-compat-api/SKILL.md b/.github/skills/add-compat-api/SKILL.md index 1bc79e5..b784e5e 100644 --- a/.github/skills/add-compat-api/SKILL.md +++ b/.github/skills/add-compat-api/SKILL.md @@ -202,12 +202,12 @@ bash test/result_cmp.sh ./build/ 闭环验证通过且文档已回填后,按以下流程提交。完整命令模板见 [`references/Step7.md`](references/Step7.md)。 -1. **从 fork 主分支 checkout 新分支**(`git fetch upstream && git checkout -B add/- upstream/develop`) +1. **从本地跟踪 origin 的 develop 创建新分支**(`git checkout develop && git pull --ff-only origin develop && git checkout -b add/-`) 2. **commit 改动**(commit message 首行使用 `[Cpp API Compatibility] <对齐迭代记录标题>`) 3. **push 到 fork**(`git push origin `) 4. **`gh pr create` 到 upstream**(`--repo PaddlePaddle/Paddle --base develop`) 5. **同步 PCAT 测试改动** - 1. **从 fork 主分支 checkout 新分支**(`cd "$PCAT_ROOT" && git fetch upstream && git checkout -B test/- upstream/master`) + 1. **从本地跟踪 origin 的 master 创建新分支**(`cd "$PCAT_ROOT" && git checkout master && git pull --ff-only origin master && git checkout -b test/-`) 2. **commit 改动**(commit message 首行使用 `test(): align with Paddle compat 行为`) 3. **push 到 fork**(`git push origin `) 4. **`gh pr create` 到 upstream**(`--repo PFCCLab/PaddleCppAPITest --base master`,PR body 中加 `Related: PaddlePaddle/Paddle#`) diff --git a/.github/skills/add-compat-api/references/Step7.md b/.github/skills/add-compat-api/references/Step7.md index 892239d..ec2f5d4 100644 --- a/.github/skills/add-compat-api/references/Step7.md +++ b/.github/skills/add-compat-api/references/Step7.md @@ -13,24 +13,27 @@ 任一未通过 → **不要**进入本流程。 -## 1) 从 fork 主分支 checkout 新分支 +## 1) 从本地跟踪 origin 的基分支创建新分支 ### Paddle 侧 ```bash cd "$PADDLE_ROOT" -git fetch upstream +git checkout develop +git pull --ff-only origin develop # add 流程 -git checkout -B "add/-$(date +%Y%m%d)" upstream/develop +git checkout -b "add/-$(date +%Y%m%d)" # fix 流程 -git checkout -B "fix/-$(date +%Y%m%d)" upstream/develop +git checkout -b "fix/-$(date +%Y%m%d)" ``` 分支命名规则: - add:`add/-`(例:`add/abs-20260519`) - fix:`fix/-`(例:`fix/78652-20260519`) -> 前提:Paddle 仓库已配置 `origin = /Paddle` 与 `upstream = PaddlePaddle/Paddle`。若 remote 缺失,**提示用户配置后再继续**,不要主动改用户仓库的 remote。 +> 实际执行时只选 add 或 fix 对应的一条 `git checkout -b`。若分支已存在,`git checkout -b` 会失败;换新分支名或让用户手动处理,**不要**改用 `-B` 覆盖已有分支。 +> +> 前提:Paddle 仓库已配置 `origin = /Paddle` 与 `upstream = PaddlePaddle/Paddle`,且本地 `develop` 跟踪 `origin/develop`。若 remote 或本地基分支缺失,**提示用户配置后再继续**,不要主动改用户仓库的 remote。 ## 2) commit 改动 @@ -100,8 +103,9 @@ EOF ```bash cd "$PCAT_ROOT" -git fetch upstream -git checkout -B "test/-$(date +%Y%m%d)" upstream/master +git checkout master +git pull --ff-only origin master +git checkout -b "test/-$(date +%Y%m%d)" git add test/<改动文件> git commit -m "test(): align with Paddle compat 行为" git push origin diff --git a/.github/skills/fix-compat-api/SKILL.md b/.github/skills/fix-compat-api/SKILL.md index 9245cf8..d366845 100644 --- a/.github/skills/fix-compat-api/SKILL.md +++ b/.github/skills/fix-compat-api/SKILL.md @@ -218,7 +218,7 @@ bash test/result_cmp.sh ./build/ 闭环验证通过且文档已回填后,按以下流程提交。完整命令模板见 [`../add-compat-api/references/Step7.md`](../add-compat-api/references/Step7.md)(与 `add-compat-api` 共享同一份 references)。 -1. **从 fork 主分支 checkout 新分支**(`git fetch upstream && git checkout -B fix/- upstream/develop`) +1. **从本地跟踪 origin 的 develop 创建新分支**(`git checkout develop && git pull --ff-only origin develop && git checkout -b fix/-`) 2. **commit 改动**(commit message 首行使用 `[Cpp API Compatibility] `) 3. **征求用户同意后 push 到 fork**(`git push origin `——这是发出去的动作,**push 前必须明确询问用户**) 4. **征求用户同意后 `gh pr create` 到 upstream**(`--repo PaddlePaddle/Paddle --base develop`——同样需要用户确认;若本轮修复源自外部 PR/Actions/comment 链接,PR 描述里应**引用原链接**便于追溯) From 0d071c14c1895c213e9dde40abf068b89356d78f Mon Sep 17 00:00:00 2001 From: youge325 Date: Sat, 20 Jun 2026 18:02:13 +0800 Subject: [PATCH 02/10] Fix PCAT result file handling --- test/ATen/ops/AsStridedTest.cpp | 17 +++------------- test/ATen/ops/BitwiseTest.cpp | 13 +----------- test/ATen/ops/ClampTest.cpp | 35 +++++++++++---------------------- test/ATen/ops/VarTest.cpp | 19 ++++-------------- test/result_cmp.sh | 26 ++++++++++++++++++++++-- 5 files changed, 44 insertions(+), 66 deletions(-) diff --git a/test/ATen/ops/AsStridedTest.cpp b/test/ATen/ops/AsStridedTest.cpp index 4410024..d1f46b4 100644 --- a/test/ATen/ops/AsStridedTest.cpp +++ b/test/ATen/ops/AsStridedTest.cpp @@ -19,19 +19,8 @@ class AsStridedTest : public ::testing::Test { void SetUp() override {} }; -// 返回当前用例的结果文件名 -std::string GetTestCaseResultFileName() { - std::string base = g_custom_param.get(); - std::string test_name = - ::testing::UnitTest::GetInstance()->current_test_info()->name(); - if (base.size() >= 4 && base.substr(base.size() - 4) == ".txt") { - base.resize(base.size() - 4); - } - return base + "_" + test_name + ".txt"; -} - TEST_F(AsStridedTest, AsStrided) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.createFile(); file << "AsStrided "; at::Tensor tensor = at::ones({2, 3, 4}, at::kFloat); @@ -44,7 +33,7 @@ TEST_F(AsStridedTest, AsStrided) { } TEST_F(AsStridedTest, AsStridedInplace) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "AsStridedInplace "; at::Tensor tensor = at::ones({2, 3, 4}, at::kFloat); @@ -57,7 +46,7 @@ TEST_F(AsStridedTest, AsStridedInplace) { } TEST_F(AsStridedTest, AsStridedScatter) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "AsStridedScatter "; at::Tensor tensor = at::ones({2, 3, 4}, at::kFloat); diff --git a/test/ATen/ops/BitwiseTest.cpp b/test/ATen/ops/BitwiseTest.cpp index 90d2a55..77f2a85 100644 --- a/test/ATen/ops/BitwiseTest.cpp +++ b/test/ATen/ops/BitwiseTest.cpp @@ -19,19 +19,8 @@ class BitwiseTest : public ::testing::Test { void SetUp() override {} }; -// 返回当前用例的结果文件名 -std::string GetTestCaseResultFileName() { - std::string base = g_custom_param.get(); - std::string test_name = - ::testing::UnitTest::GetInstance()->current_test_info()->name(); - if (base.size() >= 4 && base.substr(base.size() - 4) == ".txt") { - base.resize(base.size() - 4); - } - return base + "_" + test_name + ".txt"; -} - TEST_F(BitwiseTest, BitwiseRightShift) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.createFile(); file << "BitwiseRightShift "; at::Tensor input = at::ones({2, 3}, at::kInt).fill_(8); diff --git a/test/ATen/ops/ClampTest.cpp b/test/ATen/ops/ClampTest.cpp index 26ed74d..28d54a3 100644 --- a/test/ATen/ops/ClampTest.cpp +++ b/test/ATen/ops/ClampTest.cpp @@ -19,19 +19,8 @@ class ClampTest : public ::testing::Test { void SetUp() override {} }; -// 返回当前用例的结果文件名 -std::string GetTestCaseResultFileName() { - std::string base = g_custom_param.get(); - std::string test_name = - ::testing::UnitTest::GetInstance()->current_test_info()->name(); - if (base.size() >= 4 && base.substr(base.size() - 4) == ".txt") { - base.resize(base.size() - 4); - } - return base + "_" + test_name + ".txt"; -} - TEST_F(ClampTest, ClampScalarMinMax) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.createFile(); file << "ClampScalarMinMax "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -44,7 +33,7 @@ TEST_F(ClampTest, ClampScalarMinMax) { } TEST_F(ClampTest, ClampTensorMinMax) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampTensorMinMax "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -57,7 +46,7 @@ TEST_F(ClampTest, ClampTensorMinMax) { } TEST_F(ClampTest, ClampInplaceScalar) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampInplaceScalar "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -69,7 +58,7 @@ TEST_F(ClampTest, ClampInplaceScalar) { } TEST_F(ClampTest, ClampInplaceTensor) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampInplaceTensor "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -82,7 +71,7 @@ TEST_F(ClampTest, ClampInplaceTensor) { } TEST_F(ClampTest, ClampMaxScalar) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMaxScalar "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -94,7 +83,7 @@ TEST_F(ClampTest, ClampMaxScalar) { } TEST_F(ClampTest, ClampMaxTensor) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMaxTensor "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -106,7 +95,7 @@ TEST_F(ClampTest, ClampMaxTensor) { } TEST_F(ClampTest, ClampMaxInplace) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMaxInplace "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -118,7 +107,7 @@ TEST_F(ClampTest, ClampMaxInplace) { } TEST_F(ClampTest, ClampMaxInplaceTensor) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMaxInplaceTensor "; at::Tensor input = at::ones({2, 3}, at::kFloat).fill_(5.0f); @@ -130,7 +119,7 @@ TEST_F(ClampTest, ClampMaxInplaceTensor) { } TEST_F(ClampTest, ClampMinScalar) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMinScalar "; at::Tensor input = at::ones({2, 3}, at::kFloat); @@ -142,7 +131,7 @@ TEST_F(ClampTest, ClampMinScalar) { } TEST_F(ClampTest, ClampMinTensor) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMinTensor "; at::Tensor input = at::ones({2, 3}, at::kFloat); @@ -154,7 +143,7 @@ TEST_F(ClampTest, ClampMinTensor) { } TEST_F(ClampTest, ClampMinInplace) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMinInplace "; at::Tensor input = at::ones({2, 3}, at::kFloat); @@ -166,7 +155,7 @@ TEST_F(ClampTest, ClampMinInplace) { } TEST_F(ClampTest, ClampMinInplaceTensor) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "ClampMinInplaceTensor "; at::Tensor input = at::ones({2, 3}, at::kFloat); diff --git a/test/ATen/ops/VarTest.cpp b/test/ATen/ops/VarTest.cpp index feac64c..82b80b0 100644 --- a/test/ATen/ops/VarTest.cpp +++ b/test/ATen/ops/VarTest.cpp @@ -19,19 +19,8 @@ class VarTest : public ::testing::Test { void SetUp() override {} }; -// 返回当前用例的结果文件名 -std::string GetTestCaseResultFileName() { - std::string base = g_custom_param.get(); - std::string test_name = - ::testing::UnitTest::GetInstance()->current_test_info()->name(); - if (base.size() >= 4 && base.substr(base.size() - 4) == ".txt") { - base.resize(base.size() - 4); - } - return base + "_" + test_name + ".txt"; -} - TEST_F(VarTest, VarDim) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.createFile(); file << "VarDim "; at::Tensor input = at::ones({2, 3}, at::kFloat); @@ -44,7 +33,7 @@ TEST_F(VarTest, VarDim) { } TEST_F(VarTest, VarAll) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "VarAll "; at::Tensor input = at::ones({2, 3}, at::kFloat); @@ -57,7 +46,7 @@ TEST_F(VarTest, VarAll) { } TEST_F(VarTest, VarDims) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "VarDims "; at::Tensor input = at::ones({2, 3}, at::kFloat); @@ -71,7 +60,7 @@ TEST_F(VarTest, VarDims) { } TEST_F(VarTest, VarCorrection) { - FileManerger file(GetTestCaseResultFileName()); + FileManerger file(g_custom_param.get()); file.openAppend(); file << "VarCorrection "; at::Tensor input = at::ones({2, 3}, at::kFloat); diff --git a/test/result_cmp.sh b/test/result_cmp.sh index e5fa3c0..4311325 100755 --- a/test/result_cmp.sh +++ b/test/result_cmp.sh @@ -8,6 +8,22 @@ PADDLE_PATH=${BUILD_PATH}/paddle/ TORCH_PATH=${BUILD_PATH}/torch/ RESULT_FILE_PATH="/tmp/paddle_cpp_api_test/" +cleanup_coverage_data() { + local build_path="$1" + local gcda_count + + if [[ ! -d "$build_path" ]]; then + return + fi + + gcda_count=$(find "$build_path" -type f -name "*.gcda" | wc -l) + gcda_count=${gcda_count//[[:space:]]/} + if [[ "$gcda_count" -gt 0 ]]; then + echo "Cleaning ${gcda_count} stale .gcda coverage files under ${build_path}..." + find "$build_path" -type f -name "*.gcda" -delete + fi +} + # 保存原始终端输出,并在退出时稳定打印日志路径 LOG_FILE="${RESULT_FILE_PATH}result_cmp_$(date +%Y%m%d_%H%M%S).log" mkdir -p "${RESULT_FILE_PATH}" @@ -16,6 +32,8 @@ trap 'status=$?; printf "\nDone. Full output saved to: %s\n" "$LOG_FILE" | tee - exec > >(tee -a "$LOG_FILE") 2>&1 echo "Log file: $LOG_FILE" +cleanup_coverage_data "$BUILD_PATH" + collect_and_run_executables() { local exec_path="$1" local prefix="$2" @@ -59,8 +77,12 @@ for key in "${!TORCH_EXECUTABLES[@]}"; do done while IFS= read -r key; do - paddle_exec="${PADDLE_EXECUTABLES[$key]}" - torch_exec="${TORCH_EXECUTABLES[$key]}" + if [[ -z "$key" ]]; then + continue + fi + + paddle_exec="${PADDLE_EXECUTABLES[$key]:-}" + torch_exec="${TORCH_EXECUTABLES[$key]:-}" if [[ -z "$paddle_exec" || -z "$torch_exec" ]]; then has_mismatch=1 From 223b3c6639b6ddb0e2bec77d0c5a7b79c6cd71f5 Mon Sep 17 00:00:00 2001 From: youge325 Date: Sat, 20 Jun 2026 22:27:47 +0800 Subject: [PATCH 03/10] Add transpose large-dim alignment tests --- test/ATen/ops/TransposeTest.cpp | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/test/ATen/ops/TransposeTest.cpp b/test/ATen/ops/TransposeTest.cpp index 8731aa8..2d24da7 100644 --- a/test/ATen/ops/TransposeTest.cpp +++ b/test/ATen/ops/TransposeTest.cpp @@ -284,5 +284,55 @@ TEST_F(TransposeTest, TransposeSpecialValues) { file.saveFile(); } +TEST_F(TransposeTest, LargePositiveDimThrows) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "LargePositiveDimThrows "; + + try { + (void)at::transpose(tensor, 1LL << 32, 1); + file << "ok "; + } catch (const std::exception&) { + file << "exception "; + } + + at::Tensor in_place = at::zeros({2, 3, 4}, at::kFloat); + try { + (void)in_place.transpose_(1LL << 32, 1); + file << "inplace_ok "; + } catch (const std::exception&) { + file << "inplace_exception "; + } + for (int64_t i = 0; i < in_place.dim(); ++i) { + file << std::to_string(in_place.sizes()[i]) << " "; + } + file << "\n"; + file.saveFile(); +} + +TEST_F(TransposeTest, LargeNegativeDimThrows) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "LargeNegativeDimThrows "; + + try { + (void)tensor.transpose(0, -(1LL << 32)); + file << "member_ok "; + } catch (const std::exception&) { + file << "member_exception "; + } + + try { + (void)at::transpose(tensor, 0, -(1LL << 32)); + file << "free_ok "; + } catch (const std::exception&) { + file << "free_exception "; + } + file << "\n"; + file.saveFile(); +} + } // namespace test } // namespace at From b6d337b9d32f0f08b223487963a63b37fd097a21 Mon Sep 17 00:00:00 2001 From: youge325 Date: Fri, 26 Jun 2026 18:09:31 +0800 Subject: [PATCH 04/10] Add Tensor const_data_ptr alignment coverage --- test/ATen/ops/TensorPtrTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/ATen/ops/TensorPtrTest.cpp b/test/ATen/ops/TensorPtrTest.cpp index 8f46f8b..8c116c6 100644 --- a/test/ATen/ops/TensorPtrTest.cpp +++ b/test/ATen/ops/TensorPtrTest.cpp @@ -12,6 +12,9 @@ TEST(TensorBodyTest, PtrTest) { const float* const_ptr = t.const_data_ptr(); EXPECT_NE(const_ptr, nullptr); + const float* const_type_ptr = t.const_data_ptr(); + EXPECT_NE(const_type_ptr, nullptr); + const void* void_const_ptr = t.const_data_ptr(); EXPECT_NE(void_const_ptr, nullptr); @@ -27,6 +30,7 @@ TEST(TensorBodyTest, PtrTest) { file.createFile(); file << "PtrTest "; file << "const_ptr[0]: " + std::to_string(const_ptr[0]) + "\n"; + file << "const_type_ptr[0]: " + std::to_string(const_type_ptr[0]) + "\n"; mut_ptr[0] = 5.0f; file << "mut_ptr[0]: " + std::to_string(mut_ptr[0]) + "\n"; From 2be4399b90ce8ef95e209bad9d9ad104c71d91cb Mon Sep 17 00:00:00 2001 From: youge325 Date: Sat, 27 Jun 2026 11:18:19 +0800 Subject: [PATCH 05/10] Add TensorBase noexcept alignment coverage --- test/ATen/core/TensorUtilTest.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/ATen/core/TensorUtilTest.cpp b/test/ATen/core/TensorUtilTest.cpp index f0c17c7..947b4bc 100644 --- a/test/ATen/core/TensorUtilTest.cpp +++ b/test/ATen/core/TensorUtilTest.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include "src/file_manager.h" @@ -17,6 +18,11 @@ namespace test { using paddle_api_test::FileManerger; using paddle_api_test::ThreadSafeParam; +static_assert(noexcept(std::declval().is_same( + std::declval()))); +static_assert(noexcept(std::declval().use_count())); +static_assert(noexcept(std::declval().weak_use_count())); + class TensorUtilTest : public ::testing::Test { protected: void SetUp() override { From 622e2ba2b781b89e6bc01440f365bfe4004adbae Mon Sep 17 00:00:00 2001 From: youge325 Date: Sat, 27 Jun 2026 12:35:29 +0800 Subject: [PATCH 06/10] Extend Tensor pointer alignment coverage --- test/ATen/ops/TensorPtrTest.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/ATen/ops/TensorPtrTest.cpp b/test/ATen/ops/TensorPtrTest.cpp index 8c116c6..813bb4a 100644 --- a/test/ATen/ops/TensorPtrTest.cpp +++ b/test/ATen/ops/TensorPtrTest.cpp @@ -18,6 +18,12 @@ TEST(TensorBodyTest, PtrTest) { const void* void_const_ptr = t.const_data_ptr(); EXPECT_NE(void_const_ptr, nullptr); + float* data_ptr = t.data_ptr(); + EXPECT_NE(data_ptr, nullptr); + + void* void_data_ptr = t.data_ptr(); + EXPECT_NE(void_data_ptr, nullptr); + float* mut_ptr = t.mutable_data_ptr(); EXPECT_NE(mut_ptr, nullptr); @@ -31,6 +37,15 @@ TEST(TensorBodyTest, PtrTest) { file << "PtrTest "; file << "const_ptr[0]: " + std::to_string(const_ptr[0]) + "\n"; file << "const_type_ptr[0]: " + std::to_string(const_type_ptr[0]) + "\n"; + file << "void_const_ptr_equal: " + << std::to_string(void_const_ptr == static_cast(const_ptr)) + << "\n"; + file << "data_ptr_equal: " + << std::to_string(static_cast(data_ptr) == void_data_ptr) << "\n"; + file << "const_type_ptr_equal: " + << std::to_string(static_cast(const_type_ptr) == + static_cast(const_ptr)) + << "\n"; mut_ptr[0] = 5.0f; file << "mut_ptr[0]: " + std::to_string(mut_ptr[0]) + "\n"; From bc33301f27ed7711ae945bca892d23dd144f0a24 Mon Sep 17 00:00:00 2001 From: youge325 Date: Sat, 27 Jun 2026 21:14:14 +0800 Subject: [PATCH 07/10] Add as_strided_scatter alignment coverage --- test/ATen/ops/AsStridedTest.cpp | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/ATen/ops/AsStridedTest.cpp b/test/ATen/ops/AsStridedTest.cpp index d1f46b4..90d650e 100644 --- a/test/ATen/ops/AsStridedTest.cpp +++ b/test/ATen/ops/AsStridedTest.cpp @@ -58,5 +58,40 @@ TEST_F(AsStridedTest, AsStridedScatter) { file.saveFile(); } +TEST_F(AsStridedTest, AsStridedScatterPreservesInputShape) { + FileManerger file(g_custom_param.get()); + file.openAppend(); + file << "AsStridedScatterPreservesInputShape "; + at::Tensor tensor = at::arange(12, at::kFloat); + at::Tensor src = at::full({2, 3}, 99.0f, at::kFloat); + at::Tensor result = tensor.as_strided_scatter(src, {2, 3}, {3, 1}); + file << std::to_string(result.dim()) << " "; + file << std::to_string(result.sizes()[0]) << " "; + float* data = result.data_ptr(); + for (int i = 0; i < 6; ++i) { + file << std::to_string(data[i]) << " "; + } + file << "\n"; + file.saveFile(); +} + +TEST_F(AsStridedTest, AsStridedScatterWithOffset) { + FileManerger file(g_custom_param.get()); + file.openAppend(); + file << "AsStridedScatterWithOffset "; + at::Tensor tensor = at::arange(12, at::kFloat); + at::Tensor src = at::full({2, 2}, 88.0f, at::kFloat); + at::Tensor result = tensor.as_strided_scatter(src, {2, 2}, {2, 1}, 2); + file << std::to_string(result.dim()) << " "; + file << std::to_string(result.sizes()[0]) << " "; + float* data = result.data_ptr(); + file << std::to_string(data[0]) << " "; + file << std::to_string(data[2]) << " "; + file << std::to_string(data[3]) << " "; + file << std::to_string(data[5]) << " "; + file << "\n"; + file.saveFile(); +} + } // namespace test } // namespace at From c29c30bfcb749567208508c504bdeac3c11007a2 Mon Sep 17 00:00:00 2001 From: youge325 Date: Sat, 27 Jun 2026 22:50:13 +0800 Subject: [PATCH 08/10] Add index_put None alignment coverage --- test/ATen/ops/IndexPutTest.cpp | 58 ++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/ATen/ops/IndexPutTest.cpp b/test/ATen/ops/IndexPutTest.cpp index 3b1b258..ba36b1d 100644 --- a/test/ATen/ops/IndexPutTest.cpp +++ b/test/ATen/ops/IndexPutTest.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -190,5 +191,62 @@ TEST(TensorBodyTest, IndexPutAccumulateTrue) { file.saveFile(); } +TEST(TensorBodyTest, IndexPutTensorIndexNoneValue) { + auto options = at::TensorOptions().dtype(at::kFloat).device(at::kCPU); + at::Tensor base = at::zeros({2, 3}, options); + at::Tensor values = at::full({1, 2, 3}, 6.0f, options); + + base.index_put_({at::indexing::None}, values); + + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "IndexPutTensorIndexNoneValue "; + write_index_result_to_file(&file, base); + file << "\n"; + file.saveFile(); +} + +TEST(TensorBodyTest, IndexPutTensorIndexTensorNoneAndSlice) { + auto options = at::TensorOptions().dtype(at::kFloat).device(at::kCPU); + at::Tensor base = at::zeros({3, 4}, options); + at::Tensor idx = tensor_from_vector_i64({2, 0}); + at::Tensor values = at::full({2, 1, 4}, 8.0f, options); + + base.index_put_({idx, at::indexing::None, at::indexing::Slice()}, values); + + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "IndexPutTensorIndexTensorNoneAndSlice "; + file << std::to_string(base.dim()) << " "; + file << std::to_string(base.numel()) << " "; + file << std::to_string(base.sizes()[0]) << " "; + file << std::to_string(base.sizes()[1]) << " "; + at::Tensor cont = base.contiguous(); + float* data = cont.data_ptr(); + file << std::to_string(data[0]) << " "; + file << std::to_string(data[4]) << " "; + file << std::to_string(data[8]) << " "; + file << std::to_string(cont.sum().item()) << " "; + file << "\n"; + file.saveFile(); +} + +TEST(TensorBodyTest, IndexPutTensorIndexNoneScalar) { + auto options = at::TensorOptions().dtype(at::kFloat).device(at::kCPU); + at::Tensor base = at::zeros({2, 3}, options); + + base.index_put_({at::indexing::None}, at::Scalar(4.0)); + + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "IndexPutTensorIndexNoneScalar "; + write_index_result_to_file(&file, base); + file << "\n"; + file.saveFile(); +} + } // namespace test } // namespace at From 2e4a58d2d4569e01a2003b3155f7fc8c515dc6b5 Mon Sep 17 00:00:00 2001 From: youge325 Date: Thu, 28 May 2026 20:22:58 +0800 Subject: [PATCH 09/10] test(vstack): align with Paddle compat vstack behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add VStackTest.cpp covering shape/dtype/exception cases: - Scalar (0D), small shape (1D/2D), large shape, zero-dim, all-ones, mixed dims - Dtype: kFloat, kDouble, kInt, kLong - Empty list exception handling - Update cpp_api_mapping_cn.md: at::vstack from 功能缺失 to API完全一致 Co-Authored-By: Claude Opus 4.7 (1M context) --- test/ATen/ops/VStackTest.cpp | 225 +++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 test/ATen/ops/VStackTest.cpp diff --git a/test/ATen/ops/VStackTest.cpp b/test/ATen/ops/VStackTest.cpp new file mode 100644 index 0000000..6ca670a --- /dev/null +++ b/test/ATen/ops/VStackTest.cpp @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "src/file_manager.h" + +extern paddle_api_test::ThreadSafeParam g_custom_param; + +namespace at { +namespace test { + +using paddle_api_test::FileManerger; +using paddle_api_test::ThreadSafeParam; + +class VStackTest : public ::testing::Test { + protected: + void SetUp() override {} +}; + +static void write_vstack_result_to_file(FileManerger* file, + const at::Tensor& result) { + *file << std::to_string(result.dim()) << " "; + *file << std::to_string(result.numel()) << " "; + for (int64_t i = 0; i < result.dim(); ++i) { + *file << std::to_string(result.sizes()[i]) << " "; + } +} + +// ========== Shape 覆盖 ========== + +// 标量 (0-d tensor) -> vstack 后变成 2D +TEST_F(VStackTest, Scalar0D) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.createFile(); + file << "Scalar0D "; + auto t1 = at::full({}, 1.0f, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::full({}, 2.0f, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// 小 shape +TEST_F(VStackTest, SmallShape2D) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "SmallShape2D "; + auto t1 = at::ones({2, 3}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({2, 3}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// 1D tensor -> vstack 后变成 2D +TEST_F(VStackTest, SmallShape1D) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "SmallShape1D "; + auto t1 = at::ones({3}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({3}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// 大 shape +TEST_F(VStackTest, LargeShape) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "LargeShape "; + auto t1 = at::ones({50, 100}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({50, 100}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// 边界 shape: 含零维度 +TEST_F(VStackTest, ZeroDimShape) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "ZeroDimShape "; + auto t1 = at::ones({0, 3}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({2, 3}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// 边界 shape: 全一维度 +TEST_F(VStackTest, AllOnesShape) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "AllOnesShape "; + auto t1 = at::ones({1, 1}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({1, 1}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// 混合维度 +TEST_F(VStackTest, MixedDims) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "MixedDims "; + auto t1 = at::ones({3}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({1, 3}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// ========== Dtype 覆盖 ========== + +TEST_F(VStackTest, DtypeFloat) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "DtypeFloat "; + auto t1 = at::ones({2, 3}, at::TensorOptions().dtype(at::kFloat)); + auto t2 = at::zeros({2, 3}, at::TensorOptions().dtype(at::kFloat)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + file << std::to_string(static_cast(result.scalar_type())) << " "; + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +TEST_F(VStackTest, DtypeDouble) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "DtypeDouble "; + auto t1 = at::ones({2, 3}, at::TensorOptions().dtype(at::kDouble)); + auto t2 = at::zeros({2, 3}, at::TensorOptions().dtype(at::kDouble)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + file << std::to_string(static_cast(result.scalar_type())) << " "; + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +TEST_F(VStackTest, DtypeInt32) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "DtypeInt32 "; + auto t1 = at::ones({2, 3}, at::TensorOptions().dtype(at::kInt)); + auto t2 = at::zeros({2, 3}, at::TensorOptions().dtype(at::kInt)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + file << std::to_string(static_cast(result.scalar_type())) << " "; + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +TEST_F(VStackTest, DtypeInt64) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "DtypeInt64 "; + auto t1 = at::ones({2, 3}, at::TensorOptions().dtype(at::kLong)); + auto t2 = at::zeros({2, 3}, at::TensorOptions().dtype(at::kLong)); + std::vector tensors = {t1, t2}; + at::Tensor result = at::vstack(tensors); + file << std::to_string(static_cast(result.scalar_type())) << " "; + write_vstack_result_to_file(&file, result); + file << "\n"; + file.saveFile(); +} + +// ========== 异常行为 ========== + +TEST_F(VStackTest, EmptyListThrows) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "EmptyListThrows "; + std::vector tensors = {}; + try { + at::Tensor result = at::vstack(tensors); + file << "no_exception "; + write_vstack_result_to_file(&file, result); + } catch (const std::exception&) { + file << "exception "; + } + file << "\n"; + file.saveFile(); +} + +} // namespace test +} // namespace at From 50b314d16115293f5941f8a7f97197bdb60ebddd Mon Sep 17 00:00:00 2001 From: youge325 Date: Sun, 14 Jun 2026 16:53:03 +0800 Subject: [PATCH 10/10] test(vstack): cover values and mismatch alignment --- test/ATen/ops/VStackTest.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/ATen/ops/VStackTest.cpp b/test/ATen/ops/VStackTest.cpp index 6ca670a..78dec1e 100644 --- a/test/ATen/ops/VStackTest.cpp +++ b/test/ATen/ops/VStackTest.cpp @@ -33,6 +33,15 @@ static void write_vstack_result_to_file(FileManerger* file, } } +static void write_float_values_to_file(FileManerger* file, + const at::Tensor& result) { + auto contiguous = result.contiguous(); + const float* data = contiguous.data_ptr(); + for (int64_t i = 0; i < contiguous.numel(); ++i) { + *file << std::to_string(data[i]) << " "; + } +} + // ========== Shape 覆盖 ========== // 标量 (0-d tensor) -> vstack 后变成 2D @@ -46,6 +55,7 @@ TEST_F(VStackTest, Scalar0D) { std::vector tensors = {t1, t2}; at::Tensor result = at::vstack(tensors); write_vstack_result_to_file(&file, result); + write_float_values_to_file(&file, result); file << "\n"; file.saveFile(); } @@ -61,6 +71,7 @@ TEST_F(VStackTest, SmallShape2D) { std::vector tensors = {t1, t2}; at::Tensor result = at::vstack(tensors); write_vstack_result_to_file(&file, result); + write_float_values_to_file(&file, result); file << "\n"; file.saveFile(); } @@ -76,6 +87,7 @@ TEST_F(VStackTest, SmallShape1D) { std::vector tensors = {t1, t2}; at::Tensor result = at::vstack(tensors); write_vstack_result_to_file(&file, result); + write_float_values_to_file(&file, result); file << "\n"; file.saveFile(); } @@ -221,5 +233,25 @@ TEST_F(VStackTest, EmptyListThrows) { file.saveFile(); } +TEST_F(VStackTest, MismatchedShapeThrows) { + auto file_name = g_custom_param.get(); + FileManerger file(file_name); + file.openAppend(); + file << "MismatchedShapeThrows "; + std::vector tensors = { + at::ones({2, 3}, at::TensorOptions().dtype(at::kFloat)), + at::zeros({2, 4}, at::TensorOptions().dtype(at::kFloat))}; + try { + at::Tensor result = at::vstack(tensors); + file << "no_exception "; + write_vstack_result_to_file(&file, result); + write_float_values_to_file(&file, result); + } catch (const std::exception&) { + file << "exception "; + } + file << "\n"; + file.saveFile(); +} + } // namespace test } // namespace at