package jnpf.dmsService;
|
|
import feign.Request;
|
import feign.Response;
|
import jnpf.base.ActionResult;
|
import jnpf.dmsEntity.permission.enums.DmsResourceType;
|
import jnpf.dmsEntity.preview.form.DmsFilePreviewTicketRequest;
|
import jnpf.dmsEntity.preview.vo.DmsFilePageCountVO;
|
import jnpf.dmsEntity.preview.vo.DmsFilePreviewTicketVO;
|
import jnpf.dmsService.file.DmsFileContentApi;
|
import jnpf.onlyoffice.DmsPageCountApi;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.ArgumentCaptor;
|
|
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.util.Collections;
|
import java.util.UUID;
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verifyNoInteractions;
|
import static org.mockito.Mockito.when;
|
|
class DmsFilePageCountServiceTest {
|
private final DmsFilePreviewService previewService = mock(DmsFilePreviewService.class);
|
private final DmsFileContentApi fileContentApi = mock(DmsFileContentApi.class);
|
private final DmsDocumentPageCountService documentPageCountService =
|
mock(DmsDocumentPageCountService.class);
|
private final DmsPageCountApi onlyOfficePageCountApi = mock(DmsPageCountApi.class);
|
private final DmsFilePageCountService service = new DmsFilePageCountService(
|
previewService, fileContentApi, documentPageCountService, onlyOfficePageCountApi);
|
private final UUID fileVersionId =
|
UUID.fromString("018f0000-0000-7000-8000-000000000702");
|
|
@BeforeEach
|
void setUp() {
|
DmsFilePreviewTicketVO ticket = new DmsFilePreviewTicketVO();
|
ticket.setFileVersionId(fileVersionId);
|
ticket.setFileName("quality-manual.pdf");
|
ticket.setAccessTicket("page-count-ticket");
|
when(previewService.createTicket(any())).thenReturn(ticket);
|
}
|
|
@Test
|
void readsProtectedFileAndDeletesTemporaryCopy() throws Exception {
|
byte[] fileBytes = new byte[]{1, 2, 3, 4};
|
when(fileContentApi.stream(fileVersionId, "page-count-ticket"))
|
.thenReturn(response(200, fileBytes));
|
AtomicReference<Path> temporaryFile = new AtomicReference<>();
|
when(documentPageCountService.getPageCount(any(Path.class), eq("quality-manual.pdf")))
|
.thenAnswer(invocation -> {
|
Path path = invocation.getArgument(0);
|
temporaryFile.set(path);
|
assertArrayEquals(fileBytes, Files.readAllBytes(path));
|
return 12;
|
});
|
|
DmsFilePageCountVO result = service.getPageCount(fileVersionId);
|
|
assertEquals(fileVersionId, result.getFileVersionId());
|
assertEquals("quality-manual.pdf", result.getFileName());
|
assertEquals(12, result.getPageCount());
|
assertNotNull(temporaryFile.get());
|
assertFalse(Files.exists(temporaryFile.get()));
|
verifyNoInteractions(onlyOfficePageCountApi);
|
|
ArgumentCaptor<DmsFilePreviewTicketRequest> requestCaptor =
|
ArgumentCaptor.forClass(DmsFilePreviewTicketRequest.class);
|
verify(previewService).createTicket(requestCaptor.capture());
|
DmsFilePreviewTicketRequest request = requestCaptor.getValue();
|
assertEquals(DmsResourceType.FILE_VERSION, request.getResourceType());
|
assertEquals(fileVersionId, request.getResourceId());
|
assertNotNull(request.getOperationId());
|
}
|
|
@Test
|
void countsBothWordFormatsUsingOnlyOfficePreview() throws Exception {
|
for (String fileName : new String[]{"玻思韬DMS调研报告.docx", "legacy.DOC"}) {
|
wordTicket(fileName);
|
when(onlyOfficePageCountApi.getPageCount(fileVersionId, "page-count-ticket"))
|
.thenReturn(pageCountResponse(200, 19));
|
|
DmsFilePageCountVO result = service.getPageCount(fileVersionId);
|
|
assertEquals(19, result.getPageCount());
|
assertEquals(fileVersionId, result.getFileVersionId());
|
assertEquals(fileName, result.getFileName());
|
}
|
verifyNoInteractions(fileContentApi, documentPageCountService);
|
}
|
|
@Test
|
void neverFallsBackToWordMetadataWhenConversionFails() {
|
wordTicket("manual.docx");
|
when(onlyOfficePageCountApi.getPageCount(fileVersionId, "page-count-ticket"))
|
.thenReturn(null, pageCountResponse(500, 20), pageCountResponse(200, 0),
|
pageCountResponse(200, -1), pageCountResponse(200, null));
|
for (int attempt = 0; attempt < 5; attempt++) {
|
assertThrows(IOException.class, () -> service.getPageCount(fileVersionId));
|
}
|
when(onlyOfficePageCountApi.getPageCount(fileVersionId, "page-count-ticket"))
|
.thenThrow(new IllegalStateException("conversion timed out"));
|
assertThrows(IllegalStateException.class, () -> service.getPageCount(fileVersionId));
|
verifyNoInteractions(fileContentApi, documentPageCountService);
|
}
|
|
private void wordTicket(String fileName) {
|
DmsFilePreviewTicketVO ticket = new DmsFilePreviewTicketVO();
|
ticket.setFileVersionId(fileVersionId);
|
ticket.setFileName(fileName);
|
ticket.setAccessTicket("page-count-ticket");
|
when(previewService.createTicket(any())).thenReturn(ticket);
|
}
|
|
private ActionResult<Integer> pageCountResponse(int code, Integer pages) {
|
ActionResult<Integer> response = new ActionResult<>();
|
response.setCode(code);
|
response.setData(pages);
|
return response;
|
}
|
|
@Test
|
void rejectsFileServiceErrorBeforeParsing() throws Exception {
|
when(fileContentApi.stream(fileVersionId, "page-count-ticket"))
|
.thenReturn(response(503, null));
|
|
IOException exception = assertThrows(IOException.class,
|
() -> service.getPageCount(fileVersionId));
|
|
assertEquals("文件服务读取失败", exception.getMessage());
|
verify(documentPageCountService, never()).getPageCount(any(), any());
|
}
|
|
private Response response(int status, byte[] body) {
|
Request request = Request.create(Request.HttpMethod.GET, "http://file-service/content",
|
Collections.emptyMap(), null, StandardCharsets.UTF_8);
|
Response.Builder builder = Response.builder()
|
.request(request)
|
.status(status)
|
.reason(status == 200 ? "OK" : "Service Unavailable")
|
.headers(Collections.emptyMap());
|
return body == null ? builder.build() : builder.body(body).build();
|
}
|
}
|