package jnpf.flowable.service;
|
|
import jnpf.flowable.mapper.FilePermissionSnapshotMapper;
|
import jnpf.flowable.model.filepermission.FilePermissionTaskState;
|
import jnpf.flowable.util.ServiceUtil;
|
import jnpf.base.UserInfo;
|
import jnpf.util.UserProvider;
|
import org.junit.Test;
|
import org.mockito.MockedStatic;
|
import java.util.*;
|
import java.util.concurrent.atomic.AtomicReference;
|
import static org.junit.Assert.*;
|
import static org.mockito.Mockito.*;
|
|
public class FilePermissionSnapshotServiceTest {
|
@Test public void distinguishesAbsentDeletedAndLegacyTasks() {
|
FilePermissionSnapshotMapper mapper = mock(FilePermissionSnapshotMapper.class);
|
FilePermissionSnapshotService service = new FilePermissionSnapshotService(mapper, mock(ServiceUtil.class));
|
try { service.find("task"); fail("absence must be explicit"); }
|
catch (FilePermissionSnapshotService.TaskNotFoundException expected) { }
|
FilePermissionTaskState row = new FilePermissionTaskState(); row.setTaskId("task"); row.setDeleteMark(1);
|
when(mapper.find("task")).thenReturn(row);
|
try { service.find("task"); fail("deleted task must fail closed"); }
|
catch (IllegalArgumentException expected) { assertFalse(expected instanceof FilePermissionSnapshotService.TaskNotFoundException); }
|
row.setDeleteMark(null);
|
jnpf.util.context.SpringContext.setApplicationContext(mock(org.springframework.context.ApplicationContext.class));
|
try (MockedStatic<UserProvider> users = mockStatic(UserProvider.class)) {
|
users.when(UserProvider::getUser).thenReturn(new UserInfo());
|
assertNull(service.find("task"));
|
}
|
}
|
|
@Test public void databaseFailureIsNeverReportedAsAbsent() {
|
FilePermissionSnapshotMapper mapper = mock(FilePermissionSnapshotMapper.class);
|
FilePermissionSnapshotService service = new FilePermissionSnapshotService(mapper, mock(ServiceUtil.class));
|
IllegalStateException outage = new IllegalStateException("database unavailable");
|
when(mapper.find("task")).thenThrow(outage);
|
try { service.find("task"); fail("must propagate outage"); }
|
catch (RuntimeException expected) { assertSame(outage, expected); }
|
}
|
|
@Test public void casPersistsReleaseRuleActivationReleaseAndReactivation() throws Exception {
|
FilePermissionSnapshotMapper mapper = mock(FilePermissionSnapshotMapper.class);
|
FilePermissionSnapshotService service = new FilePermissionSnapshotService(mapper, mock(ServiceUtil.class));
|
Map<String, Object> rule = new LinkedHashMap<>();
|
rule.put("id", "creator-readonly");
|
rule.put("formId", "form");
|
rule.put("field", "files");
|
rule.put("subject", "CREATOR");
|
rule.put("trigger", "ENTERED");
|
rule.put("triggerNodeId", "department-review");
|
rule.put("onReturn", "RELEASE");
|
rule.put("actions", Collections.singletonMap("EDIT", "DENY"));
|
AtomicReference<String> stored = new AtomicReference<>(jnpf.flowable.util.filepermission.FilePermissionSnapshot.create(
|
"tenant", "task", "flow", Map.of("version", 1, "rules", Collections.singletonList(rule))));
|
when(mapper.find("task")).thenAnswer(invocation -> {
|
FilePermissionTaskState state = new FilePermissionTaskState();
|
state.setTaskId("task");
|
state.setSnapshot(stored.get());
|
return state;
|
});
|
when(mapper.compareAndSetSnapshot(eq("task"), anyString(), anyString())).thenAnswer(invocation -> {
|
String expected = invocation.getArgument(1);
|
String updated = invocation.getArgument(2);
|
return stored.compareAndSet(expected, updated) ? 1 : 0;
|
});
|
jnpf.util.context.SpringContext.setApplicationContext(mock(org.springframework.context.ApplicationContext.class));
|
UserInfo user = new UserInfo();
|
user.setTenantId("tenant");
|
try (MockedStatic<UserProvider> users = mockStatic(UserProvider.class)) {
|
users.when(UserProvider::getUser).thenReturn(user);
|
service.markEntered("task", Collections.singleton("department-review"));
|
assertTrue(service.find("task").getActiveReleaseRules().contains("creator-readonly"));
|
|
service.markReturnedPast("task", Collections.singleton("qa"));
|
assertTrue(service.find("task").getActiveReleaseRules().contains("creator-readonly"));
|
|
service.markReturnedPast("task", Collections.singleton("department-review"));
|
assertFalse(service.find("task").getActiveReleaseRules().contains("creator-readonly"));
|
|
service.markEntered("task", Collections.singleton("department-review"));
|
assertTrue(service.find("task").getActiveReleaseRules().contains("creator-readonly"));
|
}
|
verify(mapper, times(3)).compareAndSetSnapshot(eq("task"), anyString(), anyString());
|
}
|
}
|