fix(selfop): allow controlled manual collection in test
This commit is contained in:
+12
@@ -25,6 +25,18 @@ class CollectionQueryServiceTest {
|
||||
CollectionQuery q(Integer page,LocalDateTime upper,Long id) {
|
||||
return new CollectionQuery("primary","A",null,null,null,null,null,null,page,null,upper==null?null:upper.toInstant(ZoneOffset.UTC),id);
|
||||
}
|
||||
@Test void controlledTestBusinessProjectsEnabledInventoryPublicationWithoutAutomaticSchedule() {
|
||||
config.setCollectionMode("BUSINESS");config.setEnvironment("test");config.setQuantityUnit("PCS");
|
||||
config.setExclusiveHandoffVerified(true);config.setPriorEgressClosed(true);config.setInflightDrained(true);config.setTransferredBudgetVerified(true);
|
||||
config.setExclusiveGrantExpiresAtUtc(now.plusHours(1));config.setDailyRequestBudget(100);
|
||||
var rows=service.overview(q(null,null,null)).warehouses();
|
||||
assertFalse(rows.isEmpty());for(var row:rows){assertTrue(row.executionEnabled());assertNull(row.disabledReason());assertNull(row.nextScheduledAt());
|
||||
assertEquals("INVENTORY".equals(row.dataFamily()),row.publicationEnabled());}
|
||||
config.setExclusiveGrantExpiresAtUtc(now.minusSeconds(1));
|
||||
for(var row:service.overview(q(null,null,null)).warehouses()){assertFalse(row.executionEnabled());assertEquals("EXCLUSIVE_GRANT_NOT_VALID",row.disabledReason());}
|
||||
config.setEnvironment("development");
|
||||
for(var row:service.overview(q(null,null,null)).warehouses()){assertFalse(row.executionEnabled());assertEquals("BUSINESS_ENVIRONMENT_REJECTED",row.disabledReason());}
|
||||
}
|
||||
Scope scope() {
|
||||
return new Scope(1L,"A","OUTBOUND","hash","Asia/Shanghai","0 0 8,20 * * *",93600,
|
||||
now.minusMonths(2),now,null,null,0,null,null,null,7,null,null);
|
||||
|
||||
+10
-2
@@ -29,11 +29,19 @@ class SelfopEgressServiceTest {
|
||||
private void success(EgressContext c,Operation op){service.authorize(new AuthorizationRequest(c,op,PROVIDER));service.complete(new CompletionRequest(c,op,PROVIDER,1,null,200,200,false,null));clock.advance(5);}
|
||||
private SelfopApiBudget budget(){return SelfopSupport.read(account.getApiBudgetJson(),SelfopApiBudget.class);}
|
||||
private SelfopValidationBudget rootBudget(){return SelfopSupport.read(task.getValidationBudgetJson(),SelfopValidationBudget.class);}
|
||||
@Test void offUnknownModeNonProductionBusinessAndUnverifiedHandoffFailBeforeAnyLock(){
|
||||
@Test void offUnknownModeUnknownEnvironmentBusinessAndUnverifiedHandoffFailBeforeAnyLock(){
|
||||
cfg.setCollectionMode("OFF");assertThatThrownBy(()->reserve(Operation.WAREHOUSES,1,null,null)).hasMessage("EGRESS_MODE_REJECTED");
|
||||
cfg.setCollectionMode("BUSINESS");assertThatThrownBy(()->reserve(Operation.WAREHOUSES,1,null,null)).hasMessage("BUSINESS_ENVIRONMENT_REJECTED");
|
||||
cfg.setCollectionMode("BUSINESS");cfg.setEnvironment("unknown");assertThatThrownBy(()->reserve(Operation.WAREHOUSES,1,null,null)).hasMessage("BUSINESS_ENVIRONMENT_REJECTED");
|
||||
cfg.setCollectionMode("VALIDATION");cfg.setPriorEgressClosed(false);assertThatThrownBy(()->reserve(Operation.WAREHOUSES,1,null,null)).hasMessage("EXCLUSIVE_HANDOFF_UNCONFIRMED");verifyNoInteractions(mapper);
|
||||
}
|
||||
@Test void testBusinessStillChargesPersistentAccountAndRequiresLiveExclusiveGrant(){
|
||||
business();cfg.setEnvironment("test");
|
||||
var c=reserve(Operation.WAREHOUSES,1,null,null);success(c,Operation.WAREHOUSES);
|
||||
assertThat(budget().reservedHttp).isEqualTo(1);assertThat(budget().confirmedHttp).isEqualTo(1);
|
||||
cfg.setExclusiveGrantExpiresAtUtc(now());
|
||||
assertThatThrownBy(()->reserve(Operation.WAREHOUSES,1,null,null)).hasMessage("EXCLUSIVE_HANDOFF_UNCONFIRMED");
|
||||
assertThat(budget().reservedHttp).isEqualTo(1);
|
||||
}
|
||||
@Test void frozenPageSizeCannotBeExpanded(){assertThatThrownBy(()->reserve(Operation.WAREHOUSES,11,null,null)).hasMessage("VALIDATION_PAGE_SIZE");assertThat(budget().reservedHttp).isZero();}
|
||||
@Test void allFamiliesAndFailuresConsumeOneRootAndAccountAcrossServiceRestart(){
|
||||
var c=reserve(Operation.WAREHOUSES,2,null,null);success(c,Operation.WAREHOUSES);
|
||||
|
||||
+28
-2
@@ -75,17 +75,43 @@ class SelfopCommandServiceTest {
|
||||
task.setWarehouseCode(warehouse); task.setTaskRole("WAREHOUSE_SYNC"); task.setStatus("DEAD");
|
||||
return task;
|
||||
}
|
||||
@Test void offModeAndNonProductionBusinessDoNotAcceptNewCollectionTask() {
|
||||
@Test void offModeAndUnknownEnvironmentDoNotAcceptNewCollectionTask() {
|
||||
configure();config.setCollectionMode("OFF");
|
||||
assertThat(config.isExecutionEnabled()).isFalse();
|
||||
var c=new SelfopCommandService.Command("disabled","WH-A","INVENTORY",null,null,null,null,null,"offline test");
|
||||
assertThatThrownBy(()->service.request(c,"42")).hasMessage("采集功能未启用,当前环境不允许执行采集或重试");
|
||||
assertThatThrownBy(()->service.request(retry(),"42")).hasMessage("采集功能未启用,当前环境不允许执行采集或重试");
|
||||
config.setCollectionMode("BUSINESS");config.setEnvironment("test");
|
||||
config.setCollectionMode("BUSINESS");config.setEnvironment("development");
|
||||
assertThat(config.isExecutionEnabled()).isFalse();
|
||||
assertThatThrownBy(()->service.request(c,"42")).hasMessage("采集功能未启用,当前环境不允许执行采集或重试");
|
||||
verifyNoInteractions(taskService,scopes,accounts,tasks);
|
||||
}
|
||||
@Test void testBusinessManualInventoryUsesWholeScopeAndBackfillKeepsOneDayBound() {
|
||||
configure();config.setEnvironment("test");config.setSourceQueryTimezone("Asia/Shanghai");
|
||||
var scope=new SelfopSyncScope();scope.setId(10L);scope.setScopeHash("scope");scope.setScopeJson("{\"qualities\":\"ALL\"}");
|
||||
var account=new SelfopOutboundDiscoveryScope();account.setId(20L);
|
||||
when(scopes.selectOne(any())).thenReturn(scope);when(accounts.selectOne(any())).thenReturn(account);
|
||||
when(taskService.create(any(SelfopSyncTask.class))).thenAnswer(call->call.getArgument(0));
|
||||
var inventory=service.request(new SelfopCommandService.Command("full-inventory","WH-A","INVENTORY",null,null,null,null,null,null),"42");
|
||||
assertThat(config.isExecutionEnabled()).isTrue();assertThat(config.getEnvironment()).isEqualTo("test");
|
||||
assertThat(inventory.getExecutionPurpose()).isEqualTo("BUSINESS");assertThat(inventory.getValidationRootTaskId()).isNull();
|
||||
assertThat(inventory.getTaskRole()).isEqualTo("WAREHOUSE_SYNC");assertThat(inventory.getScopeId()).isEqualTo(10L);
|
||||
assertThat(inventory.getQueryScopeJson()).isEqualTo(scope.getScopeJson());assertThat(inventory.getRequestKey()).isEqualTo("manual:full-inventory");
|
||||
var from=LocalDateTime.of(2026,10,12,0,0);
|
||||
var outbound=service.request(new SelfopCommandService.Command("one-day","WH-A","BACKFILL",null,from,from.plusDays(1),null,null,null),"42");
|
||||
assertThat(outbound.getExecutionPurpose()).isEqualTo("BUSINESS");assertThat(outbound.getTaskRole()).isEqualTo("ACCOUNT_DISCOVERY");
|
||||
assertThat(outbound.getQueryUntilUtc()).isEqualTo(outbound.getQueryFromUtc().plusDays(1));
|
||||
clearInvocations(taskService);
|
||||
assertThatThrownBy(()->service.request(new SelfopCommandService.Command("too-long","WH-A","BACKFILL",null,from,from.plusDays(1).plusSeconds(1),null,null,null),"42"))
|
||||
.hasMessage("单次采集时间范围不能超过一天");
|
||||
verify(taskService,never()).create(any(SelfopSyncTask.class));
|
||||
}
|
||||
@Test void testCannotUseRetryToReviveAutomaticScheduledWork() {
|
||||
configure();config.setEnvironment("test");var original=original("synthetic-account","WH-A");
|
||||
original.setTaskType("SCHEDULED");original.setRequestKey("slot:old");when(tasks.selectOne(any())).thenReturn(original);
|
||||
assertThatThrownBy(()->service.request(retry(),"42")).hasMessage("测试环境仅允许重试人工采集任务及其派生任务");
|
||||
verify(taskService,never()).retry(anyLong(),anyString(),anyString(),anyString());
|
||||
}
|
||||
@Test void validationModeRejectsFormalInventoryEntry() {
|
||||
configure();config.setCollectionMode("VALIDATION");
|
||||
var c=new SelfopCommandService.Command("wrong-purpose","WH-A","INVENTORY",null,null,null,null,null,"offline test");
|
||||
|
||||
+24
@@ -32,6 +32,30 @@ class SelfopSchedulePlannerTest {
|
||||
planner.tick();
|
||||
verifyNoInteractions(taskService, execution, scopes, accounts, tasks, orders, locks, tx);
|
||||
}
|
||||
@Test void testBusinessPollsManualRootAndRelatedChildrenWithoutAutomaticPlanningOrInitialization() {
|
||||
config.setCollectionMode("BUSINESS");config.setEnvironment("test");
|
||||
var root=controlled(101L,"ACCOUNT_DISCOVERY","BACKFILL","manual:one-day");root.setRequestedBy("42");
|
||||
var child=controlled(102L,"WAREHOUSE_SYNC","BACKFILL","route:101:WH-A");child.setWarehouseCode("WH-A");child.setUpstreamTaskId(101L);
|
||||
var refresh=controlled(103L,"ACCOUNT_DISCOVERY","RECHECK","refresh:101:object:4");refresh.setQueryScopeJson("{\"parentTaskId\":101}");
|
||||
var scheduled=controlled(104L,"WAREHOUSE_SYNC","SCHEDULED","slot:old");
|
||||
var orphan=controlled(105L,"WAREHOUSE_SYNC","BACKFILL","route:999:WH-A");orphan.setWarehouseCode("WH-A");orphan.setUpstreamTaskId(999L);
|
||||
var other=controlled(106L,"WAREHOUSE_SYNC","BACKFILL","route:101:WH-A");other.setSourceAccount("other");other.setWarehouseCode("WH-A");other.setUpstreamTaskId(101L);
|
||||
when(tasks.selectById(101L)).thenReturn(root);when(taskService.due(10)).thenReturn(List.of(root,child,refresh,scheduled,orphan,other));
|
||||
planner.tick();verify(execution).execute(101L);verify(execution).execute(102L);verify(execution).execute(103L);
|
||||
verify(execution,never()).execute(104L);verify(execution,never()).execute(105L);verify(execution,never()).execute(106L);
|
||||
verify(taskService,never()).initialize();verify(taskService,never()).initializeAccount();verify(taskService,never()).create(any(SelfopSyncTask.class));
|
||||
verifyNoInteractions(scopes,accounts,orders,locks,tx);
|
||||
}
|
||||
@Test void testRejectsDirectPlanAndReviewBeforeAnyStateOrTwoMonthWindowWrite() {
|
||||
config.setCollectionMode("BUSINESS");config.setEnvironment("test");var preview=scope(10L,"WH-A","OUTBOUND");
|
||||
assertThatThrownBy(()->planner.plan(preview,LocalDateTime.of(2026,10,12,4,0))).hasMessage("SELFOP_AUTOMATIC_PLANNING_ENVIRONMENT_REJECTED");
|
||||
assertThatThrownBy(()->planner.review(preview,LocalDateTime.of(2026,10,12,4,0))).hasMessage("SELFOP_AUTOMATIC_PLANNING_ENVIRONMENT_REJECTED");
|
||||
assertThat(preview.getInitialUntilUtc()).isNull();verifyNoInteractions(taskService,execution,scopes,accounts,tasks,orders,locks,tx);
|
||||
}
|
||||
private SelfopSyncTask controlled(long id,String role,String type,String key) {
|
||||
var task=new SelfopSyncTask();task.setId(id);task.setSourceAccount("synthetic");task.setExecutionPurpose("BUSINESS");
|
||||
task.setTaskRole(role);task.setTaskType(type);task.setRequestKey(key);return task;
|
||||
}
|
||||
@Test void validationWithoutConfiguredWarehouseOnlyInitializesAccountAndExecutesDurableCommand() {
|
||||
config.setCollectionMode("VALIDATION");
|
||||
var due=new SelfopSyncTask();due.setId(101L);due.setTaskType("VALIDATION");due.setExecutionPurpose("VALIDATION");
|
||||
|
||||
Reference in New Issue
Block a user