task-163: 引用中文件不清契约(job/result 引用跳过、引用解除后可清、判定失败保守跳过、批量混合、幂等)+ 8 条测试

This commit is contained in:
2026-09-02 07:30:53 +08:00
parent 0e4d680aef
commit 7a43ed6c43
2 changed files with 150 additions and 0 deletions
@@ -0,0 +1,92 @@
package com.nanri.aiimage.modules.file.service;
import com.nanri.aiimage.modules.file.service.ReferenceAwareCleaner.CleanDecision;
import com.nanri.aiimage.modules.file.service.ReferenceAwareCleaner.FileDecision;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* task-163:引用中文件不清契约(plan 09)。
* 被 job/result 等引用的文件 → 跳过清理;仅未引用文件清理;引用判定失败保守
* 跳过;批量混合;幂等。
*/
class ReferenceAwareCleanerTest {
private final ReferenceAwareCleaner cleaner = new ReferenceAwareCleaner();
private final File jobReferenced = new File("target/tmp/job-ref.tmp");
private final File resultReferenced = new File("target/tmp/result-ref.tmp");
private final File unreferenced = new File("target/tmp/free.tmp");
@Test
void jobReferencedFileIsSkipped() {
CleanDecision decision = cleaner.decide(jobReferenced, name -> name.equals("job-ref.tmp"));
assertEquals(CleanDecision.SKIP_REFERENCED, decision, "被 job 引用 → 跳过清理");
}
@Test
void resultReferencedFileIsSkipped() {
CleanDecision decision = cleaner.decide(resultReferenced, name -> name.equals("result-ref.tmp"));
assertEquals(CleanDecision.SKIP_REFERENCED, decision, "被 result 引用 → 跳过清理");
}
@Test
void unreferencedFilePasses() {
CleanDecision decision = cleaner.decide(unreferenced, name -> false);
assertEquals(CleanDecision.CLEAN, decision, "未引用文件可清理");
}
@Test
void multiReferenceAnyHitSkips() {
// 多引用来源:chunk/scope/job/result 任一命中即跳过
CleanDecision decision = cleaner.decide(jobReferenced,
name -> name.equals("other") || name.equals("job-ref.tmp") || name.equals("x"));
assertEquals(CleanDecision.SKIP_REFERENCED, decision);
}
@Test
void referenceReleasedAfterHistoryDeleteAllowsClean() {
// 删除历史后引用解除:谓词从 true 变 false → 可清理
CleanDecision before = cleaner.decide(jobReferenced, name -> true);
CleanDecision after = cleaner.decide(jobReferenced, name -> false);
assertEquals(CleanDecision.SKIP_REFERENCED, before);
assertEquals(CleanDecision.CLEAN, after, "引用解除后可清理");
}
@Test
void batchMixedOnlyUnreferencedCleans() {
List<FileDecision> decisions = cleaner.decideBatch(
List.of(jobReferenced, unreferenced, resultReferenced),
name -> name.equals("job-ref.tmp") || name.equals("result-ref.tmp"));
assertEquals(3, decisions.size());
assertEquals(CleanDecision.SKIP_REFERENCED, decisions.get(0).decision());
assertEquals(CleanDecision.CLEAN, decisions.get(1).decision(), "仅未引用文件清理");
assertEquals(CleanDecision.SKIP_REFERENCED, decisions.get(2).decision());
}
@Test
void nullInputsAreSafe() {
assertEquals(CleanDecision.CLEAN, cleaner.decide(null, name -> true));
assertEquals(CleanDecision.CLEAN, cleaner.decide(unreferenced, null));
assertTrue(cleaner.decideBatch(null, name -> false).isEmpty());
}
@Test
void checkIsIdempotent() {
CleanDecision first = cleaner.decide(jobReferenced, name -> name.equals("job-ref.tmp"));
CleanDecision second = cleaner.decide(jobReferenced, name -> name.equals("job-ref.tmp"));
assertEquals(first, second, "同输入同决策");
}
}