mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
test(wiki): cross-feature end-to-end domain scenario
This commit is contained in:
parent
8b4e1a12f9
commit
3a781ef0d9
@ -0,0 +1,153 @@
|
||||
package vip.mate.wiki;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import vip.mate.wiki.model.WikiAgentPageTypePermissionEntity;
|
||||
import vip.mate.wiki.model.WikiPageEntity;
|
||||
import vip.mate.wiki.model.WikiPipelineDefinitionEntity;
|
||||
import vip.mate.wiki.pipeline.WikiPipelineService;
|
||||
import vip.mate.wiki.pipeline.WikiPipelineTriggerService;
|
||||
import vip.mate.wiki.pipeline.WikiStepContext;
|
||||
import vip.mate.wiki.pipeline.WikiStepExecutor;
|
||||
import vip.mate.wiki.profile.WikiPageTypeProfile;
|
||||
import vip.mate.wiki.profile.WikiPageTypeProfileService;
|
||||
import vip.mate.wiki.repository.WikiAgentPageTypePermissionMapper;
|
||||
import vip.mate.wiki.repository.WikiPageMapper;
|
||||
import vip.mate.wiki.repository.WikiPipelineDefinitionMapper;
|
||||
import vip.mate.wiki.repository.WikiPipelineRunMapper;
|
||||
import vip.mate.wiki.repository.WikiPipelineStepRunMapper;
|
||||
import vip.mate.wiki.service.WikiDependencyService;
|
||||
import vip.mate.wiki.service.WikiPageService;
|
||||
import vip.mate.wiki.service.WikiPageTypePermissionService;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Cross-RFC end-to-end scenario exercised against H2 with no external model:
|
||||
* a KB defines a custom pageType profile (layered fact/experience), pages are
|
||||
* created, an agent's pageType read permission filters them, an experience
|
||||
* page depends on a fact page and goes stale when the fact changes, and a
|
||||
* count-threshold pipeline fires once the fact pages accumulate.
|
||||
*/
|
||||
@SpringBootTest(
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE,
|
||||
properties = {
|
||||
"spring.flyway.enabled=true",
|
||||
"spring.flyway.locations=classpath:db/migration/h2",
|
||||
"mateclaw.feature-flag.refresh-ms=999999"
|
||||
}
|
||||
)
|
||||
class WikiDomainIntegrationE2ETest {
|
||||
|
||||
private static final WikiStepExecutor NOOP = new WikiStepExecutor() {
|
||||
public String type() { return "noop"; }
|
||||
public String execute(WikiStepContext c) { return "ok"; }
|
||||
};
|
||||
|
||||
@Autowired private WikiPageTypeProfileService profileService;
|
||||
@Autowired private WikiPageService pageService;
|
||||
@Autowired private WikiPageTypePermissionService permissionService;
|
||||
@Autowired private WikiAgentPageTypePermissionMapper permissionMapper;
|
||||
@Autowired private WikiDependencyService dependencyService;
|
||||
@Autowired private WikiPipelineDefinitionMapper definitionMapper;
|
||||
@Autowired private WikiPipelineRunMapper runMapper;
|
||||
@Autowired private WikiPipelineStepRunMapper stepRunMapper;
|
||||
@Autowired private WikiPageMapper pageMapper;
|
||||
@Autowired private ObjectMapper objectMapper;
|
||||
|
||||
private static final java.util.concurrent.atomic.AtomicLong SEQ =
|
||||
new java.util.concurrent.atomic.AtomicLong(System.nanoTime());
|
||||
|
||||
@Test
|
||||
void fullDomainFlow() {
|
||||
long kb = SEQ.incrementAndGet();
|
||||
long agent = SEQ.incrementAndGet();
|
||||
|
||||
// --- RFC-56: a custom KB profile with layered page types ---
|
||||
profileService.saveProfile(kb, "liquidity",
|
||||
"{\"version\":1,\"pageTypes\":{"
|
||||
+ "\"episode\":{\"label\":\"Episode\",\"layer\":\"fact\"},"
|
||||
+ "\"pattern\":{\"label\":\"Pattern\",\"layer\":\"experience\"}}}");
|
||||
WikiPageTypeProfile profile = profileService.resolveProfile(kb);
|
||||
assertTrue(profile.hasPageType("episode"));
|
||||
assertTrue(profile.hasPageType("pattern"));
|
||||
|
||||
// --- create pages: two fact episodes + one experience pattern ---
|
||||
WikiPageEntity ep1 = createPage(kb, "ep1-" + kb, "episode", "fact");
|
||||
WikiPageEntity ep2 = createPage(kb, "ep2-" + kb, "episode", "fact");
|
||||
WikiPageEntity pat = createPage(kb, "pat-" + kb, "pattern", "experience");
|
||||
|
||||
// --- RFC-58: agent may read episode (fact) but not pattern ---
|
||||
permissionMapper.insert(perm(agent, kb, "episode", 1));
|
||||
permissionMapper.insert(perm(agent, kb, "pattern", 0));
|
||||
WikiPageTypePermissionService.Access access = permissionService.resolve(agent, kb);
|
||||
assertTrue(access.canRead("episode"));
|
||||
assertFalse(access.canRead("pattern"));
|
||||
|
||||
// --- RFC-57: pattern depends on the episodes; updating one marks it stale ---
|
||||
List<String> rejected = dependencyService.setDependencies(kb, pat.getId(),
|
||||
List.of(ep1.getId(), ep2.getId()));
|
||||
assertTrue(rejected.isEmpty(), () -> "unexpected rejections: " + rejected);
|
||||
int marked = dependencyService.markDependentsStale(kb, ep1.getId(), "episode revised");
|
||||
assertEquals(1, marked);
|
||||
assertEquals(1, pageService.getBySlug(kb, "pat-" + kb).getStale());
|
||||
|
||||
// --- RFC-60: a pipeline fires once 2 episodes exist (threshold 2) ---
|
||||
long defId = seedPipeline(kb);
|
||||
WikiPipelineService pipelineService = new WikiPipelineService(
|
||||
runMapper, stepRunMapper, objectMapper, List.of(NOOP));
|
||||
WikiPipelineTriggerService trigger = new WikiPipelineTriggerService(
|
||||
definitionMapper, pipelineService, pageMapper, objectMapper);
|
||||
|
||||
int started = trigger.onPageTypeCount(kb, "episode");
|
||||
assertEquals(1, started, "pipeline should fire once the episode count reaches the threshold");
|
||||
long runs = runMapper.selectCount(com.baomidou.mybatisplus.core.toolkit.Wrappers
|
||||
.<vip.mate.wiki.model.WikiPipelineRunEntity>lambdaQuery()
|
||||
.eq(vip.mate.wiki.model.WikiPipelineRunEntity::getDefinitionId, defId));
|
||||
assertEquals(1, runs);
|
||||
|
||||
// Re-evaluating in the same bucket does not double-fire (idempotent).
|
||||
assertEquals(0, trigger.onPageTypeCount(kb, "episode"));
|
||||
}
|
||||
|
||||
private WikiPageEntity createPage(long kb, String slug, String pageType, String layer) {
|
||||
WikiPageEntity p = pageService.createPage(kb, slug, slug, "body", "s", "[1]", pageType);
|
||||
pageService.setLayerAndDependencies(p.getId(), layer, null);
|
||||
return pageService.getBySlug(kb, slug);
|
||||
}
|
||||
|
||||
private WikiAgentPageTypePermissionEntity perm(long agent, long kb, String type, int canRead) {
|
||||
WikiAgentPageTypePermissionEntity e = new WikiAgentPageTypePermissionEntity();
|
||||
e.setAgentId(agent);
|
||||
e.setKbId(kb);
|
||||
e.setPageType(type);
|
||||
e.setCanRead(canRead);
|
||||
e.setCanCreate(0);
|
||||
e.setCanUpdate(0);
|
||||
e.setCanDelete(0);
|
||||
e.setWritePolicy("deny");
|
||||
return e;
|
||||
}
|
||||
|
||||
private long seedPipeline(long kb) {
|
||||
WikiPipelineDefinitionEntity d = new WikiPipelineDefinitionEntity();
|
||||
d.setKbId(kb);
|
||||
d.setName("episode-to-pattern-" + SEQ.incrementAndGet());
|
||||
d.setOwnerAgentId(99L);
|
||||
d.setTriggerType("page_type_count");
|
||||
d.setTriggerConfigJson("{\"page_type\":\"episode\",\"threshold\":2}");
|
||||
d.setStepsJson("[{\"id\":\"s\",\"executor\":\"noop\"}]");
|
||||
d.setEnabled(1);
|
||||
d.setCreateTime(LocalDateTime.now());
|
||||
d.setUpdateTime(LocalDateTime.now());
|
||||
definitionMapper.insert(d);
|
||||
return d.getId();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user