From 9fa10f178b3d88c3a1e94d6ca3c6ac988ede8337 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Tue, 10 Mar 2026 18:14:50 +0800 Subject: [PATCH 01/17] Add tests for ContentRange functionality in Content Understanding SDK - Enhance ContentRangeTest with additional unit tests for various scenarios including: - Handling same start and end times. - Rejecting negative start times. - Validating time ranges and content range combinations. - Update Sample01_AnalyzeBinaryAsyncTest and Sample01_AnalyzeBinaryTest to include tests for analyzing binary documents with page content ranges. - Introduce new tests in Sample02_AnalyzeUrlAsyncTest and Sample02_AnalyzeUrlTest for analyzing URLs with page and time content ranges, ensuring proper functionality for both document and audio/video analyses. --- .../samples/Sample01_AnalyzeBinary.java | 76 ++++ .../samples/Sample01_AnalyzeBinaryAsync.java | 144 +++++++ .../samples/Sample02_AnalyzeUrl.java | 160 ++++++++ .../samples/Sample02_AnalyzeUrlAsync.java | 368 ++++++++++++++++++ .../tests/ContentRangeTest.java | 109 ++++++ .../Sample01_AnalyzeBinaryAsyncTest.java | 125 ++++++ .../samples/Sample01_AnalyzeBinaryTest.java | 104 +++++ .../samples/Sample02_AnalyzeUrlAsyncTest.java | 282 ++++++++++++++ .../samples/Sample02_AnalyzeUrlTest.java | 217 +++++++++++ 9 files changed, 1585 insertions(+) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java index efcdebca52f0..eac7dec5a1d8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java @@ -8,6 +8,7 @@ import com.azure.ai.contentunderstanding.ContentUnderstandingClientBuilder; import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -29,6 +30,7 @@ * 2. Analyzing the document * 3. Extracting markdown content * 4. Accessing document properties (pages, tables, etc.) + * 5. Using ContentRange to analyze specific pages */ public class Sample01_AnalyzeBinary { @@ -126,5 +128,79 @@ public static void main(String[] args) throws IOException { // END:ContentUnderstandingAccessDocumentProperties System.out.println("\nBinary document analysis completed successfully"); + + // Demonstrate ContentRange usage with a multi-page document + System.out.println("\n--- ContentRange Examples ---"); + analyzeBinaryWithContentRange(client); + } + + /** + * Sample demonstrating how to use ContentRange to analyze specific pages of a binary document. + * ContentRange allows you to specify which pages to analyze instead of the entire document. + */ + public static void analyzeBinaryWithContentRange(ContentUnderstandingClient client) { + try { + // Load a multi-page document (4 pages) + String multiPageFilePath = "src/samples/resources/mixed_financial_docs.pdf"; + Path multiPagePath = Paths.get(multiPageFilePath); + byte[] multiPageBytes = Files.readAllBytes(multiPagePath); + BinaryData multiPageData = BinaryData.fromBytes(multiPageBytes); + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithContentRange + // Analyze only pages 3 to end using ContentRange.pagesFrom() + SyncPoller rangeOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.pagesFrom(3), "application/octet-stream", null); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" + + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); + + // Analyze a single page using ContentRange.page() + SyncPoller pageOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.page(2), "application/octet-stream", null); + DocumentContent pageDoc = (DocumentContent) pageOperation.getFinalResult().getContents().get(0); + System.out.println("Page(2): returned " + pageDoc.getPages().size() + " page" + + " (page " + pageDoc.getStartPageNumber() + ")"); + + // Analyze a page range using ContentRange.pages() + SyncPoller pagesOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.pages(1, 3), "application/octet-stream", null); + DocumentContent pagesDoc = (DocumentContent) pagesOperation.getFinalResult().getContents().get(0); + System.out.println("Pages(1,3): returned " + pagesDoc.getPages().size() + " pages" + + " (pages " + pagesDoc.getStartPageNumber() + "-" + pagesDoc.getEndPageNumber() + ")"); + + // Combine multiple ranges using ContentRange.combine() + SyncPoller combineOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.combine( + ContentRange.page(1), + ContentRange.pages(3, 4)), + "application/octet-stream", null); + DocumentContent combineDoc = (DocumentContent) combineOperation.getFinalResult().getContents().get(0); + System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" + + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); + + // Combine with out-of-range pages (clamped by the service) + SyncPoller bigCombineOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.combine( + ContentRange.pages(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9)), + "application/octet-stream", null); + DocumentContent bigCombineDoc + = (DocumentContent) bigCombineOperation.getFinalResult().getContents().get(0); + System.out.println( + "Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + bigCombineDoc.getPages().size() + " pages"); + // END:ContentUnderstandingAnalyzeBinaryWithContentRange + + System.out.println("ContentRange binary analysis completed successfully"); + } catch (IOException e) { + System.err.println("Error reading multi-page file: " + e.getMessage()); + } } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java index e9ca0edb8e55..abfd2cf3782a 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java @@ -8,6 +8,7 @@ import com.azure.ai.contentunderstanding.ContentUnderstandingClientBuilder; import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -32,6 +33,7 @@ * 2. Analyzing the document * 3. Extracting markdown content * 4. Accessing document properties (pages, tables, etc.) + * 5. Using ContentRange to analyze specific pages */ public class Sample01_AnalyzeBinaryAsync { @@ -162,5 +164,147 @@ public static void main(String[] args) throws IOException, InterruptedException if (!latch.await(2, TimeUnit.MINUTES)) { System.err.println("Timed out waiting for async operations to complete."); } + + // Demonstrate ContentRange usage with a multi-page document + System.out.println("\n--- ContentRange Examples ---"); + analyzeBinaryWithContentRange(client); + } + + /** + * Sample demonstrating how to use ContentRange to analyze specific pages of a binary document asynchronously. + * ContentRange allows you to specify which pages to analyze instead of the entire document. + */ + public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient client) + throws IOException, InterruptedException { + // Load a multi-page document (4 pages) + String multiPageFilePath = "src/samples/resources/mixed_financial_docs.pdf"; + Path multiPagePath = Paths.get(multiPageFilePath); + byte[] multiPageBytes = Files.readAllBytes(multiPagePath); + BinaryData multiPageData = BinaryData.fromBytes(multiPageBytes); + + CountDownLatch rangeLatch = new CountDownLatch(1); + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithContentRangeAsync + // Analyze only pages 3 to end using ContentRange.pagesFrom() + Mono pagesFromMono = client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.pagesFrom(3), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent rangeDoc = (DocumentContent) result.getContents().get(0); + System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" + + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); + }); + + // Analyze a single page using ContentRange.page() + Mono pageMono = client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.page(2), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent pageDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Page(2): returned " + pageDoc.getPages().size() + " page" + + " (page " + pageDoc.getStartPageNumber() + ")"); + }); + + // Analyze a page range using ContentRange.pages() + Mono pagesMono = client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.pages(1, 3), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent pagesDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Pages(1,3): returned " + pagesDoc.getPages().size() + " pages" + + " (pages " + pagesDoc.getStartPageNumber() + "-" + pagesDoc.getEndPageNumber() + ")"); + }); + + // Combine multiple ranges using ContentRange.combine() + Mono combineMono = client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.combine( + ContentRange.page(1), + ContentRange.pages(3, 4)), + "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent combineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" + + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); + }); + + // Combine with out-of-range pages (clamped by the service) + Mono bigCombineMono = client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.combine( + ContentRange.pages(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9)), + "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent bigCombineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + + bigCombineDoc.getPages().size() + " pages"); + }); + + // Chain all operations sequentially using then() + pagesFromMono + .then(pageMono) + .then(pagesMono) + .then(combineMono) + .then(bigCombineMono) + .doOnError(error -> System.err.println("Error: " + error.getMessage())) + .subscribe( + result -> { + System.out.println("ContentRange async analysis completed successfully"); + rangeLatch.countDown(); + }, + error -> rangeLatch.countDown() + ); + // END:ContentUnderstandingAnalyzeBinaryWithContentRangeAsync + + if (!rangeLatch.await(5, TimeUnit.MINUTES)) { + System.err.println("Timed out waiting for ContentRange async operations."); + } } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java index 3006c2abd851..cdb3c9c3c3cd 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java @@ -10,6 +10,7 @@ import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.AudioVisualContent; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -19,6 +20,7 @@ import com.azure.core.util.polling.SyncPoller; import com.azure.identity.DefaultAzureCredentialBuilder; +import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -67,6 +69,15 @@ public static void main(String[] args) { System.out.println("\n--- Image Analysis Example ---"); analyzeImageUrl(client); + + System.out.println("\n--- Document ContentRange Example ---"); + analyzeDocumentUrlWithContentRange(client); + + System.out.println("\n--- Video ContentRange Example ---"); + analyzeVideoUrlWithContentRange(client); + + System.out.println("\n--- Audio ContentRange Example ---"); + analyzeAudioUrlWithContentRange(client); } /** @@ -281,4 +292,153 @@ public static void analyzeImageUrl(ContentUnderstandingClient client) { System.out.println("Summary: " + summary); // END:ContentUnderstandingAnalyzeImageUrl } + + /** + * Sample demonstrating how to analyze a document URL with ContentRange to extract specific pages. + */ + public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingClient client) { + // BEGIN:ContentUnderstandingAnalyzeUrlWithContentRange + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + + // Extract only page 1 using ContentRange + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.page(1)); + + SyncPoller rangeOperation + = client.beginAnalyze("prebuilt-documentSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + System.out.println("Page(1): returned " + rangeDoc.getPages().size() + " page" + + " (page " + rangeDoc.getStartPageNumber() + ")"); + System.out.println("Markdown length: " + rangeDoc.getMarkdown().length() + " characters"); + // END:ContentUnderstandingAnalyzeUrlWithContentRange + } + + /** + * Sample demonstrating how to analyze a video URL with ContentRange to extract specific time ranges. + */ + public static void analyzeVideoUrlWithContentRange(ContentUnderstandingClient client) { + // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithContentRange + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/videos/sdk_samples/FlightSimulator.mp4"; + + // Analyze only the first 5 seconds using ContentRange.timeRange() + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(5))); + + SyncPoller rangeOperation + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + + for (AnalysisContent media : rangeResult.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("TimeRange(0, 5s): Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + } + + // Analyze from 10 seconds onward using ContentRange.timeRangeFrom() + AnalysisInput rangeFromInput = new AnalysisInput(); + rangeFromInput.setUrl(uriSource); + rangeFromInput.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(10))); + + SyncPoller rangeFromOperation + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rangeFromInput)); + AnalysisResult rangeFromResult = rangeFromOperation.getFinalResult(); + + for (AnalysisContent media : rangeFromResult.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("TimeRangeFrom(10s): Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + } + + // Analyze with sub-second precision using milliseconds + AnalysisInput subSecondInput = new AnalysisInput(); + subSecondInput.setUrl(uriSource); + subSecondInput.setContentRange( + ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + SyncPoller subSecondOperation + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(subSecondInput)); + AnalysisResult subSecondResult = subSecondOperation.getFinalResult(); + + for (AnalysisContent media : subSecondResult.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("TimeRange(1200ms, 3651ms): Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + } + + // Combine multiple time ranges + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + SyncPoller combineOperation + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.getFinalResult(); + + int segmentIndex = 1; + for (AnalysisContent media : combineResult.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("Combined segment " + segmentIndex + ": Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + segmentIndex++; + } + // END:ContentUnderstandingAnalyzeVideoUrlWithContentRange + } + + /** + * Sample demonstrating how to analyze an audio URL with ContentRange to extract specific time ranges. + */ + public static void analyzeAudioUrlWithContentRange(ContentUnderstandingClient client) { + // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithContentRange + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/audio/callCenterRecording.mp3"; + + // Analyze from 5 seconds to end using ContentRange.timeRangeFrom() + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(5))); + + SyncPoller rangeOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + + AudioVisualContent audioContent = (AudioVisualContent) rangeResult.getContents().get(0); + System.out.println("TimeRangeFrom(5s): Start=" + audioContent.getStartTime().toMillis() + + " ms, End=" + audioContent.getEndTime().toMillis() + " ms"); + + // Analyze a specific time window + AnalysisInput windowInput = new AnalysisInput(); + windowInput.setUrl(uriSource); + windowInput.setContentRange(ContentRange.timeRange(Duration.ofSeconds(2), Duration.ofSeconds(8))); + + SyncPoller windowOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(windowInput)); + AnalysisResult windowResult = windowOperation.getFinalResult(); + + AudioVisualContent windowContent = (AudioVisualContent) windowResult.getContents().get(0); + System.out.println("TimeRange(2s, 8s): Start=" + windowContent.getStartTime().toMillis() + + " ms, End=" + windowContent.getEndTime().toMillis() + " ms"); + + // Analyze with sub-second precision using milliseconds + AnalysisInput subSecondInput = new AnalysisInput(); + subSecondInput.setUrl(uriSource); + subSecondInput.setContentRange( + ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + SyncPoller subSecondOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(subSecondInput)); + AnalysisResult subSecondResult = subSecondOperation.getFinalResult(); + + AudioVisualContent subSecondContent = (AudioVisualContent) subSecondResult.getContents().get(0); + System.out.println("TimeRange(1200ms, 3651ms): Start=" + subSecondContent.getStartTime().toMillis() + + " ms, End=" + subSecondContent.getEndTime().toMillis() + " ms"); + // END:ContentUnderstandingAnalyzeAudioUrlWithContentRange + } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 758ecfb223ba..69f94376487d 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -10,6 +10,7 @@ import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.AudioVisualContent; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -20,6 +21,7 @@ import com.azure.identity.DefaultAzureCredentialBuilder; import reactor.core.publisher.Mono; +import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -63,6 +65,15 @@ public static void main(String[] args) { System.out.println("\n--- Image Analysis Example ---"); analyzeImageUrl(client); + + System.out.println("\n--- Document URL with ContentRange Example ---"); + analyzeDocumentUrlWithContentRange(client); + + System.out.println("\n--- Video URL with ContentRange Example ---"); + analyzeVideoUrlWithContentRange(client); + + System.out.println("\n--- Audio URL with ContentRange Example ---"); + analyzeAudioUrlWithContentRange(client); } /** @@ -416,4 +427,361 @@ public static void analyzeImageUrl(ContentUnderstandingAsyncClient client) { } // END:ContentUnderstandingAnalyzeImageUrlAsyncAsync } + + /** + * Sample demonstrating how to analyze a document URL with page-based ContentRange. + */ + public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncClient client) { + // BEGIN:ContentUnderstandingAnalyzeDocumentUrlWithContentRangeAsync + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + + // Analyze only page 1 using ContentRange + AnalysisInput input = new AnalysisInput(); + input.setUrl(uriSource); + input.setContentRange(ContentRange.page(1)); + + PollerFlux operation + = client.beginAnalyze("prebuilt-documentSearch", Arrays.asList(input)); + + CountDownLatch latch = new CountDownLatch(1); + + operation.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent document = (DocumentContent) result.getContents().get(0); + System.out.println("Page(1): returned " + document.getPages().size() + " page" + + " (page " + document.getStartPageNumber() + ")"); + System.out.println("Markdown length: " + document.getMarkdown().length() + " characters"); + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch.countDown(), + error -> latch.countDown() + ); + + try { + latch.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for document analysis", e); + } + // END:ContentUnderstandingAnalyzeDocumentUrlWithContentRangeAsync + } + + /** + * Sample demonstrating how to analyze a video URL with time-based ContentRange. + */ + public static void analyzeVideoUrlWithContentRange(ContentUnderstandingAsyncClient client) { + // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithContentRangeAsync + String videoUrl + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/videos/sdk_samples/FlightSimulator.mp4"; + + // Analyze the first 5 seconds of the video + AnalysisInput input1 = new AnalysisInput(); + input1.setUrl(videoUrl); + input1.setContentRange(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(5))); + + PollerFlux operation1 + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(input1)); + + CountDownLatch latch1 = new CountDownLatch(1); + + operation1.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + for (AnalysisContent media : result.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("TimeRange(0, 5s): Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + } + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch1.countDown(), + error -> latch1.countDown() + ); + + try { + latch1.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for video analysis", e); + } + + // Analyze from 10 seconds onward using ContentRange.timeRangeFrom() + AnalysisInput input2 = new AnalysisInput(); + input2.setUrl(videoUrl); + input2.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(10))); + + PollerFlux operation2 + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(input2)); + + CountDownLatch latch2 = new CountDownLatch(1); + + operation2.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + for (AnalysisContent media : result.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("TimeRangeFrom(10s): Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + } + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch2.countDown(), + error -> latch2.countDown() + ); + + try { + latch2.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for video analysis", e); + } + + // Analyze with sub-second precision using milliseconds + AnalysisInput input3 = new AnalysisInput(); + input3.setUrl(videoUrl); + input3.setContentRange( + ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + PollerFlux operation3 + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(input3)); + + CountDownLatch latch3 = new CountDownLatch(1); + + operation3.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + for (AnalysisContent media : result.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("TimeRange(1200ms, 3651ms): Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + } + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch3.countDown(), + error -> latch3.countDown() + ); + + try { + latch3.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for video analysis", e); + } + + // Analyze with combined time ranges + AnalysisInput input4 = new AnalysisInput(); + input4.setUrl(videoUrl); + input4.setContentRange(ContentRange.combine( + ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + PollerFlux operation4 + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(input4)); + + CountDownLatch latch4 = new CountDownLatch(1); + + operation4.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + int segmentIndex = 1; + for (AnalysisContent media : result.getContents()) { + AudioVisualContent videoContent = (AudioVisualContent) media; + System.out.println("Combined segment " + segmentIndex + ": Start=" + videoContent.getStartTime().toMillis() + + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + segmentIndex++; + } + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch4.countDown(), + error -> latch4.countDown() + ); + + try { + latch4.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for video analysis", e); + } + // END:ContentUnderstandingAnalyzeVideoUrlWithContentRangeAsync + } + + /** + * Sample demonstrating how to analyze an audio URL with time-based ContentRange. + */ + public static void analyzeAudioUrlWithContentRange(ContentUnderstandingAsyncClient client) { + // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithContentRangeAsync + String audioUrl + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/audio/callCenterRecording.mp3"; + + // Analyze from 5 seconds onward + AnalysisInput input1 = new AnalysisInput(); + input1.setUrl(audioUrl); + input1.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(5))); + + PollerFlux operation1 + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(input1)); + + CountDownLatch latch1 = new CountDownLatch(1); + + operation1.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + AudioVisualContent audioContent = (AudioVisualContent) result.getContents().get(0); + System.out.println("TimeRangeFrom(5s): Start=" + audioContent.getStartTime().toMillis() + + " ms, End=" + audioContent.getEndTime().toMillis() + " ms"); + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch1.countDown(), + error -> latch1.countDown() + ); + + try { + latch1.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for audio analysis", e); + } + + // Analyze a specific time range (2s to 8s) + AnalysisInput input2 = new AnalysisInput(); + input2.setUrl(audioUrl); + input2.setContentRange(ContentRange.timeRange(Duration.ofSeconds(2), Duration.ofSeconds(8))); + + PollerFlux operation2 + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(input2)); + + CountDownLatch latch2 = new CountDownLatch(1); + + operation2.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + AudioVisualContent windowContent = (AudioVisualContent) result.getContents().get(0); + System.out.println("TimeRange(2s, 8s): Start=" + windowContent.getStartTime().toMillis() + + " ms, End=" + windowContent.getEndTime().toMillis() + " ms"); + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch2.countDown(), + error -> latch2.countDown() + ); + + try { + latch2.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for audio analysis", e); + } + + // Analyze with sub-second precision using milliseconds + AnalysisInput input3 = new AnalysisInput(); + input3.setUrl(audioUrl); + input3.setContentRange( + ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + PollerFlux operation3 + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(input3)); + + CountDownLatch latch3 = new CountDownLatch(1); + + operation3.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + AudioVisualContent subSecondContent = (AudioVisualContent) result.getContents().get(0); + System.out.println("TimeRange(1200ms, 3651ms): Start=" + subSecondContent.getStartTime().toMillis() + + " ms, End=" + subSecondContent.getEndTime().toMillis() + " ms"); + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> latch3.countDown(), + error -> latch3.countDown() + ); + + try { + latch3.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for audio analysis", e); + } + // END:ContentUnderstandingAnalyzeAudioUrlWithContentRangeAsync + } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/ContentRangeTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/ContentRangeTest.java index bbaa94b264fa..29572f98a155 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/ContentRangeTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/ContentRangeTest.java @@ -3,6 +3,7 @@ package com.azure.ai.contentunderstanding.tests; +import com.azure.ai.contentunderstanding.models.AnalysisInput; import com.azure.ai.contentunderstanding.models.ContentRange; import org.junit.jupiter.api.Test; @@ -10,6 +11,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; /** @@ -77,6 +79,11 @@ public void timeRangeMilliseconds() { assertEquals("1000-2000", ContentRange.timeRange(Duration.ofMillis(1000), Duration.ofMillis(2000)).toString()); } + @Test + public void timeRangeSameStartAndEnd() { + assertEquals("1000-1000", ContentRange.timeRange(Duration.ofMillis(1000), Duration.ofMillis(1000)).toString()); + } + @Test public void timeRangeRejectsNegativeStart() { assertThrows(IllegalArgumentException.class, @@ -95,6 +102,12 @@ public void timeRangeFromOpenEnded() { assertEquals("0-", ContentRange.timeRangeFrom(Duration.ZERO).toString()); } + @Test + public void timeRangeFromZeroStartTime() { + ContentRange range = ContentRange.timeRangeFrom(Duration.ZERO); + assertEquals("0-", range.toString()); + } + @Test public void timeRangeFromRejectsNegative() { assertThrows(IllegalArgumentException.class, () -> ContentRange.timeRangeFrom(Duration.ofMillis(-1))); @@ -184,4 +197,100 @@ public void timeRangeDurationRejectsNullEnd() { public void timeRangeFromDurationRejectsNull() { assertThrows(NullPointerException.class, () -> ContentRange.timeRangeFrom((Duration) null)); } + + @Test + public void timeRangeDurationRejectsNegativeStart() { + assertThrows(IllegalArgumentException.class, + () -> ContentRange.timeRange(Duration.ofMillis(-1), Duration.ofSeconds(5))); + } + + @Test + public void timeRangeDurationEndBeforeStart() { + assertThrows(IllegalArgumentException.class, + () -> ContentRange.timeRange(Duration.ofSeconds(5), Duration.ofSeconds(1))); + } + + @Test + public void timeRangeFromDurationRejectsNegative() { + assertThrows(IllegalArgumentException.class, () -> ContentRange.timeRangeFrom(Duration.ofMillis(-1))); + } + + @Test + public void constructorRawStringCustomFormats() { + ContentRange range = new ContentRange("custom-format"); + assertEquals("custom-format", range.toString()); + } + + // =================== AnalysisInput.setContentRange integration =================== + + @Test + public void analysisInputSetContentRangeAcceptsContentRange() { + AnalysisInput input = new AnalysisInput(); + input.setContentRange(ContentRange.pages(1, 3)); + // Verify via JSON round-trip that the range was stored + assertEquals("1-3", extractContentRangeFromJson(input)); + } + + @Test + public void analysisInputContentRangeNullByDefault() { + AnalysisInput input = new AnalysisInput(); + assertNull(extractContentRangeFromJson(input)); + } + + @Test + public void analysisInputContentRangeRoundTrips() { + AnalysisInput input = new AnalysisInput(); + ContentRange range = ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5)); + input.setContentRange(range); + assertEquals("1-3,5", extractContentRangeFromJson(input)); + } + + @Test + public void analysisInputSetContentRangeNull() { + AnalysisInput input = new AnalysisInput(); + input.setContentRange(ContentRange.page(1)); + input.setContentRange((ContentRange) null); + assertNull(extractContentRangeFromJson(input)); + } + + /** + * Helper: serialize AnalysisInput to JSON and extract the "range" field value. + * This avoids depending on package-private getContentRange(). + */ + private static String extractContentRangeFromJson(AnalysisInput input) { + try { + java.io.StringWriter sw = new java.io.StringWriter(); + com.azure.json.JsonWriter writer = com.azure.json.JsonProviders.createWriter(sw); + input.toJson(writer); + writer.flush(); + com.azure.json.JsonReader reader = com.azure.json.JsonProviders.createReader(sw.toString()); + AnalysisInput deserialized = AnalysisInput.fromJson(reader); + // Use toJson again to inspect; or parse the JSON directly + java.io.StringWriter sw2 = new java.io.StringWriter(); + com.azure.json.JsonWriter writer2 = com.azure.json.JsonProviders.createWriter(sw2); + deserialized.toJson(writer2); + writer2.flush(); + String json = sw2.toString(); + // Parse "range" field from JSON + int idx = json.indexOf("\"range\""); + if (idx < 0) { + return null; + } + int colon = json.indexOf(':', idx); + int valueStart = colon + 1; + // skip whitespace + while (valueStart < json.length() && json.charAt(valueStart) == ' ') { + valueStart++; + } + if (valueStart >= json.length() || json.charAt(valueStart) == 'n') { + return null; // null value + } + // It's a quoted string + int quoteStart = json.indexOf('"', valueStart); + int quoteEnd = json.indexOf('"', quoteStart + 1); + return json.substring(quoteStart + 1, quoteEnd); + } catch (java.io.IOException e) { + throw new RuntimeException(e); + } + } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java index 957b84325594..0a6710712fa7 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java @@ -6,6 +6,7 @@ import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -268,4 +269,128 @@ public void testAnalyzeBinaryAsync() throws IOException { } // END:Assertion_ContentUnderstandingAccessDocumentProperties } + + @Test + public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { + + // Load the multi-page sample file (4 pages) + String filePath = "src/samples/resources/mixed_financial_docs.pdf"; + Path path = Paths.get(filePath); + byte[] fileBytes = Files.readAllBytes(path); + BinaryData binaryData = BinaryData.fromBytes(fileBytes); + + // Full analysis for comparison + PollerFlux fullOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData); + AnalysisResult fullResult = fullOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); + assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + + // ---- PagesFrom(3) — extract pages 3 to end ---- + PollerFlux rangeOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.pagesFrom(3), "application/octet-stream", null); + AnalysisResult rangeResult = rangeOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + assertEquals(2, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 2 pages"); + assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); + assertEquals(4, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 4"); + assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); + assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); + + // ---- Page(2) — single page ---- + PollerFlux page2Operation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.page(2), "application/octet-stream", null); + AnalysisResult page2Result = page2Operation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent page2Doc = (DocumentContent) page2Result.getContents().get(0); + + assertEquals(1, page2Doc.getPages().size(), "Page(2) should return exactly 1 page"); + assertEquals(2, page2Doc.getStartPageNumber(), "Page(2) should start at page 2"); + assertEquals(2, page2Doc.getEndPageNumber(), "Page(2) should end at page 2"); + assertTrue(fullDoc.getMarkdown().length() > page2Doc.getMarkdown().length()); + + // ---- Pages(1, 3) — page range ---- + PollerFlux pages13Operation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.pages(1, 3), "application/octet-stream", null); + AnalysisResult pages13Result = pages13Operation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent pages13Doc = (DocumentContent) pages13Result.getContents().get(0); + + assertEquals(3, pages13Doc.getPages().size(), "Pages(1,3) should return exactly 3 pages"); + assertEquals(1, pages13Doc.getStartPageNumber()); + assertEquals(3, pages13Doc.getEndPageNumber()); + assertTrue(fullDoc.getMarkdown().length() > pages13Doc.getMarkdown().length()); + + // ---- Combine(Page(1), Pages(3, 4)) — combined single page and page range ---- + PollerFlux combineOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.combine(ContentRange.page(1), ContentRange.pages(3, 4)), "application/octet-stream", null); + AnalysisResult combineResult = combineOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); + + assertTrue(combineDoc.getPages().size() >= 2); + assertEquals(1, combineDoc.getStartPageNumber()); + assertTrue(combineDoc.getEndPageNumber() >= 4); + assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); + + // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges with out-of-range pages ---- + // Note: The document has only 4 pages, so Page(5) and PagesFrom(9) will be clamped + PollerFlux bigCombineOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), + "application/octet-stream", null); + AnalysisResult bigCombineResult = bigCombineOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent bigCombineDoc = (DocumentContent) bigCombineResult.getContents().get(0); + + assertNotNull(bigCombineResult); + assertNotNull(bigCombineResult.getContents()); + assertTrue(bigCombineDoc.getPages().size() > 0); + assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); + } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java index cfcff1e2ccc1..5265578dc4e0 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java @@ -6,6 +6,7 @@ import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -259,4 +260,107 @@ public void testAnalyzeBinary() throws IOException { } // END:Assertion_ContentUnderstandingAccessDocumentProperties } + + @Test + public void testAnalyzeBinaryWithPageContentRanges() throws IOException { + + // Load the multi-page sample file (4 pages) + String filePath = "src/samples/resources/mixed_financial_docs.pdf"; + Path path = Paths.get(filePath); + byte[] fileBytes = Files.readAllBytes(path); + BinaryData binaryData = BinaryData.fromBytes(fileBytes); + + // Full analysis for comparison + SyncPoller fullOperation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData); + AnalysisResult fullResult = fullOperation.getFinalResult(); + DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); + assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithPagesFrom + // ---- PagesFrom(3) — extract pages 3 to end ---- + SyncPoller rangeOperation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.pagesFrom(3), "application/octet-stream", null); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeBinaryWithPagesFrom + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom + assertNotNull(rangeOperation); + assertTrue(rangeOperation.waitForCompletion().getStatus().isComplete()); + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + assertEquals(2, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 2 pages"); + assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); + assertEquals(4, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 4"); + assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); + assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPages + // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- + // Note: The document has only 4 pages, so Page(5) and PagesFrom(9) will be clamped + SyncPoller combineRangeOperation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), + "application/octet-stream", null); + AnalysisResult combineRangeResult = combineRangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeBinaryWithCombinedPages + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages + assertNotNull(combineRangeOperation); + assertTrue(combineRangeOperation.waitForCompletion().getStatus().isComplete()); + assertNotNull(combineRangeResult); + assertNotNull(combineRangeResult.getContents()); + DocumentContent combineRangeDoc = (DocumentContent) combineRangeResult.getContents().get(0); + assertTrue(combineRangeDoc.getPages().size() > 0); + assertTrue(fullDoc.getMarkdown().length() >= combineRangeDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithSinglePage + // ---- Page(2) — single page ---- + SyncPoller page2Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, ContentRange.page(2), + "application/octet-stream", null); + DocumentContent page2Doc = (DocumentContent) page2Operation.getFinalResult().getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithSinglePage + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithSinglePage + assertEquals(1, page2Doc.getPages().size(), "Page(2) should return exactly 1 page"); + assertEquals(2, page2Doc.getStartPageNumber(), "Page(2) should start at page 2"); + assertEquals(2, page2Doc.getEndPageNumber(), "Page(2) should end at page 2"); + assertTrue(fullDoc.getMarkdown().length() > page2Doc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithSinglePage + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithPageRange + // ---- Pages(1, 3) — page range ---- + SyncPoller pages13Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.pages(1, 3), "application/octet-stream", null); + DocumentContent pages13Doc = (DocumentContent) pages13Operation.getFinalResult().getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithPageRange + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPageRange + assertEquals(3, pages13Doc.getPages().size(), "Pages(1,3) should return exactly 3 pages"); + assertEquals(1, pages13Doc.getStartPageNumber()); + assertEquals(3, pages13Doc.getEndPageNumber()); + assertTrue(fullDoc.getMarkdown().length() > pages13Doc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPageRange + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange + // ---- Combine(Page(1), Pages(3, 4)) — combined single page and page range ---- + SyncPoller combineOperation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.combine(ContentRange.page(1), ContentRange.pages(3, 4)), "application/octet-stream", null); + DocumentContent combineDoc = (DocumentContent) combineOperation.getFinalResult().getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange + assertTrue(combineDoc.getPages().size() >= 2); + assertEquals(1, combineDoc.getStartPageNumber()); + assertTrue(combineDoc.getEndPageNumber() >= 4); + assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange + } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index 5b146e03d78d..3d84c3a4cce0 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -8,6 +8,7 @@ import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.AudioVisualContent; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -23,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.time.Duration; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -439,4 +441,284 @@ public void testAnalyzeImageUrlAsync() { System.out.println("Image analysis validation completed successfully"); // END:Assertion_ContentUnderstandingAnalyzeImageUrlAsyncAsync } + + @Test + public void testAnalyzeUrlWithPageContentRangesAsync() { + + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + + // Full 4-page analysis for comparison + AnalysisInput fullInput = new AnalysisInput(); + fullInput.setUrl(uriSource); + + PollerFlux fullOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(fullInput)); + AnalysisResult fullResult = fullOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); + + // Extract only page 1 via AnalysisInput.setContentRange() + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.page(1)); + + PollerFlux rangeOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + DocumentContent rangeDocContent = (DocumentContent) rangeResult.getContents().get(0); + assertEquals(1, rangeDocContent.getPages().size(), "With ContentRange.page(1), should return only 1 page"); + assertEquals(1, rangeDocContent.getStartPageNumber()); + assertEquals(1, rangeDocContent.getEndPageNumber()); + assertTrue(fullDoc.getPages().size() > rangeDocContent.getPages().size()); + assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); + } + + @Test + public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { + + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/videos/sdk_samples/FlightSimulator.mp4"; + + // Full analysis for comparison + AnalysisInput fullInput = new AnalysisInput(); + fullInput.setUrl(uriSource); + + PollerFlux fullOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(fullInput)); + AnalysisResult fullResult = fullOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(fullResult); + assertNotNull(fullResult.getContents()); + assertTrue(fullResult.getContents().size() > 0); + + // ---- TimeRange(0, 5s) — first 5 seconds ---- + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(5))); + + PollerFlux rangeOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + assertTrue(rangeResult.getContents().size() > 0); + for (AnalysisContent content : rangeResult.getContents()) { + assertTrue(content instanceof AudioVisualContent, "Video analysis should return AudioVisualContent"); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + } + + // ---- TimeRangeFrom(10s) — from 10 seconds to end ---- + AnalysisInput rangeFromInput = new AnalysisInput(); + rangeFromInput.setUrl(uriSource); + rangeFromInput.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(10))); + + PollerFlux rangeFromOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rangeFromInput)); + AnalysisResult rangeFromResult = rangeFromOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(rangeFromResult); + assertNotNull(rangeFromResult.getContents()); + assertTrue(rangeFromResult.getContents().size() > 0); + for (AnalysisContent content : rangeFromResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertNotNull(avContent.getMarkdown()); + assertFalse(avContent.getMarkdown().isEmpty()); + } + + // ---- TimeRange sub-second precision (1200ms-3651ms) ---- + AnalysisInput subSecondInput = new AnalysisInput(); + subSecondInput.setUrl(uriSource); + subSecondInput.setContentRange(ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + PollerFlux subSecondOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(subSecondInput)); + AnalysisResult subSecondResult = subSecondOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(subSecondResult); + assertNotNull(subSecondResult.getContents()); + assertTrue(subSecondResult.getContents().size() > 0); + for (AnalysisContent content : subSecondResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + } + + // ---- Combine multiple time ranges (0-3s, 30s-) ---- + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + PollerFlux combineOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(combineResult); + assertNotNull(combineResult.getContents()); + assertTrue(combineResult.getContents().size() > 0); + for (AnalysisContent content : combineResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertNotNull(avContent.getMarkdown()); + assertFalse(avContent.getMarkdown().isEmpty()); + } + } + + @Test + public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { + + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/audio/callCenterRecording.mp3"; + + // Full analysis for comparison + AnalysisInput fullInput = new AnalysisInput(); + fullInput.setUrl(uriSource); + + PollerFlux fullOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(fullInput)); + AnalysisResult fullResult = fullOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + AudioVisualContent fullAudioContent = (AudioVisualContent) fullResult.getContents().get(0); + long fullDurationMs = fullAudioContent.getEndTime().toMillis() - fullAudioContent.getStartTime().toMillis(); + + // ---- TimeRangeFrom(5s) — from 5 seconds to end ---- + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(5))); + + PollerFlux rangeOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + assertTrue(rangeResult.getContents().size() > 0); + AudioVisualContent rangeAudioContent = (AudioVisualContent) rangeResult.getContents().get(0); + assertTrue(rangeAudioContent instanceof AudioVisualContent); + assertTrue(fullAudioContent.getMarkdown().length() >= rangeAudioContent.getMarkdown().length()); + int fullPhraseCount + = fullAudioContent.getTranscriptPhrases() != null ? fullAudioContent.getTranscriptPhrases().size() : 0; + int rangePhraseCount + = rangeAudioContent.getTranscriptPhrases() != null ? rangeAudioContent.getTranscriptPhrases().size() : 0; + assertTrue(fullPhraseCount >= rangePhraseCount); + long rangeDurationMs = rangeAudioContent.getEndTime().toMillis() - rangeAudioContent.getStartTime().toMillis(); + assertTrue(fullDurationMs >= rangeDurationMs); + + // ---- TimeRange(2s, 8s) — specific time window ---- + AnalysisInput windowInput = new AnalysisInput(); + windowInput.setUrl(uriSource); + windowInput.setContentRange(ContentRange.timeRange(Duration.ofSeconds(2), Duration.ofSeconds(8))); + + PollerFlux windowOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(windowInput)); + AnalysisResult windowResult = windowOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + AudioVisualContent audioWindowContent = (AudioVisualContent) windowResult.getContents().get(0); + + assertTrue(audioWindowContent.getEndTime().toMillis() > audioWindowContent.getStartTime().toMillis()); + assertTrue(audioWindowContent.getMarkdown().length() > 0); + long windowDurationMs + = audioWindowContent.getEndTime().toMillis() - audioWindowContent.getStartTime().toMillis(); + assertTrue(fullDurationMs >= windowDurationMs); + + // ---- TimeRange sub-second precision (1200ms-3651ms) ---- + AnalysisInput subSecondInput = new AnalysisInput(); + subSecondInput.setUrl(uriSource); + subSecondInput.setContentRange(ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + PollerFlux subSecondOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(subSecondInput)); + AnalysisResult subSecondResult = subSecondOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + AudioVisualContent audioSubSecondContent = (AudioVisualContent) subSecondResult.getContents().get(0); + + assertTrue(audioSubSecondContent.getEndTime().toMillis() > audioSubSecondContent.getStartTime().toMillis()); + assertTrue(audioSubSecondContent.getMarkdown().length() > 0); + long subSecondDurationMs + = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); + assertTrue(fullDurationMs >= subSecondDurationMs); + } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index f0d0df4f9426..f283cd958df8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -8,6 +8,7 @@ import com.azure.ai.contentunderstanding.models.AnalysisResult; import com.azure.ai.contentunderstanding.models.AudioVisualContent; import com.azure.ai.contentunderstanding.models.ContentAnalyzerAnalyzeOperationStatus; +import com.azure.ai.contentunderstanding.models.ContentRange; import com.azure.ai.contentunderstanding.models.DocumentContent; import com.azure.ai.contentunderstanding.models.DocumentPage; import com.azure.ai.contentunderstanding.models.DocumentTable; @@ -26,6 +27,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.time.Duration; /** * Sample demonstrating how to analyze documents from URL using Content Understanding service. @@ -363,6 +365,221 @@ public void testAnalyzeAudioUrl() { // END:Assertion_ContentUnderstandingAnalyzeAudioUrl } + @Test + public void testAnalyzeUrlWithPageContentRanges() { + + // BEGIN:ContentUnderstandingAnalyzeUrlWithPageContentRanges + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + + // Full 4-page analysis for comparison + AnalysisInput fullInput = new AnalysisInput(); + fullInput.setUrl(uriSource); + + SyncPoller fullOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(fullInput)); + AnalysisResult fullResult = fullOperation.getFinalResult(); + DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); + + // Extract only page 1 via AnalysisInput.setContentRange() + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.page(1)); + + SyncPoller rangeOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeUrlWithPageContentRanges + + // BEGIN:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRanges + assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + assertNotNull(rangeOperation); + assertTrue(rangeOperation.waitForCompletion().getStatus().isComplete()); + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + DocumentContent rangeDocContent = (DocumentContent) rangeResult.getContents().get(0); + assertEquals(1, rangeDocContent.getPages().size(), "With ContentRange.page(1), should return only 1 page"); + assertEquals(1, rangeDocContent.getStartPageNumber()); + assertEquals(1, rangeDocContent.getEndPageNumber()); + assertTrue(fullDoc.getPages().size() > rangeDocContent.getPages().size()); + assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRanges + } + + @Test + public void testAnalyzeVideoUrlWithTimeContentRanges() { + // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithTimeContentRanges + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/videos/sdk_samples/FlightSimulator.mp4"; + + // Full analysis for comparison + AnalysisInput fullInput = new AnalysisInput(); + fullInput.setUrl(uriSource); + + SyncPoller fullOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(fullInput)); + AnalysisResult fullResult = fullOperation.getFinalResult(); + + // ---- TimeRange(0, 5s) — first 5 seconds ---- + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(5))); + + SyncPoller rangeOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeVideoUrlWithTimeContentRanges + + // BEGIN:Assertion_ContentUnderstandingAnalyzeVideoUrlWithTimeContentRanges + assertNotNull(fullResult); + assertNotNull(fullResult.getContents()); + assertTrue(fullResult.getContents().size() > 0); + + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + assertTrue(rangeResult.getContents().size() > 0); + for (AnalysisContent content : rangeResult.getContents()) { + assertTrue(content instanceof AudioVisualContent, "Video analysis should return AudioVisualContent"); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + } + // END:Assertion_ContentUnderstandingAnalyzeVideoUrlWithTimeContentRanges + + // ---- TimeRangeFrom(10s) — from 10 seconds to end ---- + AnalysisInput rangeFromInput = new AnalysisInput(); + rangeFromInput.setUrl(uriSource); + rangeFromInput.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(10))); + + SyncPoller rangeFromOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rangeFromInput)); + AnalysisResult rangeFromResult = rangeFromOperation.getFinalResult(); + + assertNotNull(rangeFromResult); + assertNotNull(rangeFromResult.getContents()); + assertTrue(rangeFromResult.getContents().size() > 0); + for (AnalysisContent content : rangeFromResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertNotNull(avContent.getMarkdown()); + assertFalse(avContent.getMarkdown().isEmpty()); + } + + // ---- TimeRange sub-second precision (1200ms-3651ms) ---- + AnalysisInput subSecondInput = new AnalysisInput(); + subSecondInput.setUrl(uriSource); + subSecondInput.setContentRange(ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + SyncPoller subSecondOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(subSecondInput)); + AnalysisResult subSecondResult = subSecondOperation.getFinalResult(); + + assertNotNull(subSecondResult); + assertNotNull(subSecondResult.getContents()); + assertTrue(subSecondResult.getContents().size() > 0); + for (AnalysisContent content : subSecondResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + } + + // ---- Combine multiple time ranges (0-3s, 30s-) ---- + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + SyncPoller combineOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.getFinalResult(); + + assertNotNull(combineResult); + assertNotNull(combineResult.getContents()); + assertTrue(combineResult.getContents().size() > 0); + for (AnalysisContent content : combineResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertNotNull(avContent.getMarkdown()); + assertFalse(avContent.getMarkdown().isEmpty()); + } + } + + @Test + public void testAnalyzeAudioUrlWithTimeContentRanges() { + // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithTimeContentRanges + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/audio/callCenterRecording.mp3"; + + // Full analysis for comparison + AnalysisInput fullInput = new AnalysisInput(); + fullInput.setUrl(uriSource); + + SyncPoller fullOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(fullInput)); + AnalysisResult fullResult = fullOperation.getFinalResult(); + AudioVisualContent fullAudioContent = (AudioVisualContent) fullResult.getContents().get(0); + long fullDurationMs = fullAudioContent.getEndTime().toMillis() - fullAudioContent.getStartTime().toMillis(); + + // ---- TimeRangeFrom(5s) — from 5 seconds to end ---- + AnalysisInput rangeInput = new AnalysisInput(); + rangeInput.setUrl(uriSource); + rangeInput.setContentRange(ContentRange.timeRangeFrom(Duration.ofSeconds(5))); + + SyncPoller rangeOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rangeInput)); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeAudioUrlWithTimeContentRanges + + // BEGIN:Assertion_ContentUnderstandingAnalyzeAudioUrlWithTimeContentRanges + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + assertTrue(rangeResult.getContents().size() > 0); + AudioVisualContent rangeAudioContent = (AudioVisualContent) rangeResult.getContents().get(0); + assertTrue(rangeAudioContent instanceof AudioVisualContent); + assertTrue(fullAudioContent.getMarkdown().length() >= rangeAudioContent.getMarkdown().length()); + int fullPhraseCount + = fullAudioContent.getTranscriptPhrases() != null ? fullAudioContent.getTranscriptPhrases().size() : 0; + int rangePhraseCount + = rangeAudioContent.getTranscriptPhrases() != null ? rangeAudioContent.getTranscriptPhrases().size() : 0; + assertTrue(fullPhraseCount >= rangePhraseCount); + long rangeDurationMs = rangeAudioContent.getEndTime().toMillis() - rangeAudioContent.getStartTime().toMillis(); + assertTrue(fullDurationMs >= rangeDurationMs); + // END:Assertion_ContentUnderstandingAnalyzeAudioUrlWithTimeContentRanges + + // ---- TimeRange(2s, 8s) — specific time window ---- + AnalysisInput windowInput = new AnalysisInput(); + windowInput.setUrl(uriSource); + windowInput.setContentRange(ContentRange.timeRange(Duration.ofSeconds(2), Duration.ofSeconds(8))); + + SyncPoller windowOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(windowInput)); + AnalysisResult windowResult = windowOperation.getFinalResult(); + AudioVisualContent audioWindowContent = (AudioVisualContent) windowResult.getContents().get(0); + + assertTrue(audioWindowContent.getEndTime().toMillis() > audioWindowContent.getStartTime().toMillis()); + assertTrue(audioWindowContent.getMarkdown().length() > 0); + long windowDurationMs + = audioWindowContent.getEndTime().toMillis() - audioWindowContent.getStartTime().toMillis(); + assertTrue(fullDurationMs >= windowDurationMs); + + // ---- TimeRange sub-second precision (1200ms-3651ms) ---- + AnalysisInput subSecondInput = new AnalysisInput(); + subSecondInput.setUrl(uriSource); + subSecondInput.setContentRange(ContentRange.timeRange(Duration.ofMillis(1200), Duration.ofMillis(3651))); + + SyncPoller subSecondOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(subSecondInput)); + AnalysisResult subSecondResult = subSecondOperation.getFinalResult(); + AudioVisualContent audioSubSecondContent = (AudioVisualContent) subSecondResult.getContents().get(0); + + assertTrue(audioSubSecondContent.getEndTime().toMillis() > audioSubSecondContent.getStartTime().toMillis()); + assertTrue(audioSubSecondContent.getMarkdown().length() > 0); + long subSecondDurationMs + = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); + assertTrue(fullDurationMs >= subSecondDurationMs); + } + @Test public void testAnalyzeImageUrl() { // BEGIN:ContentUnderstandingAnalyzeImageUrl From b70d35b6da5303d50e7d0aac4d946b8da25601a0 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Wed, 11 Mar 2026 13:05:52 +0800 Subject: [PATCH 02/17] Fix document URL in ContentRange sample and tests --- .../ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java | 2 +- .../contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java | 2 +- .../tests/samples/Sample02_AnalyzeUrlAsyncTest.java | 2 +- .../tests/samples/Sample02_AnalyzeUrlTest.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java index cdb3c9c3c3cd..2790937a7637 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java @@ -299,7 +299,7 @@ public static void analyzeImageUrl(ContentUnderstandingClient client) { public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingClient client) { // BEGIN:ContentUnderstandingAnalyzeUrlWithContentRange String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; // Extract only page 1 using ContentRange AnalysisInput rangeInput = new AnalysisInput(); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 69f94376487d..41787da968d8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -434,7 +434,7 @@ public static void analyzeImageUrl(ContentUnderstandingAsyncClient client) { public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncClient client) { // BEGIN:ContentUnderstandingAnalyzeDocumentUrlWithContentRangeAsync String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; // Analyze only page 1 using ContentRange AnalysisInput input = new AnalysisInput(); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index 3d84c3a4cce0..05ab9bef190c 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -446,7 +446,7 @@ public void testAnalyzeImageUrlAsync() { public void testAnalyzeUrlWithPageContentRangesAsync() { String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; // Full 4-page analysis for comparison AnalysisInput fullInput = new AnalysisInput(); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index f283cd958df8..9cc382e14741 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -370,7 +370,7 @@ public void testAnalyzeUrlWithPageContentRanges() { // BEGIN:ContentUnderstandingAnalyzeUrlWithPageContentRanges String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/documents/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; // Full 4-page analysis for comparison AnalysisInput fullInput = new AnalysisInput(); From 422eeaadc04a394f743c6a456cf9010d816da2ee Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Wed, 11 Mar 2026 13:21:32 +0800 Subject: [PATCH 03/17] Update test recordings for ContentRange samples --- .../azure-ai-contentunderstanding/assets.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json b/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json index 83ce14e6ee66..3b72fa4403b4 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/contentunderstanding/azure-ai-contentunderstanding", - "Tag": "java/contentunderstanding/azure-ai-contentunderstanding_6d6c9cbfc1" + "Tag": "java/contentunderstanding/azure-ai-contentunderstanding_a546deb443" } From 76a0ec7ad03d8b87d9828e0878638c50b6dcd2d5 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Fri, 13 Mar 2026 16:37:26 +0800 Subject: [PATCH 04/17] Add raw ContentRange examples and tests for binary and URL analysis --- .../samples/Sample01_AnalyzeBinary.java | 39 ++++++++++ .../samples/Sample01_AnalyzeBinaryAsync.java | 20 +++++ .../samples/Sample02_AnalyzeUrl.java | 34 ++++++++ .../samples/Sample02_AnalyzeUrlAsync.java | 31 ++++++++ .../Sample01_AnalyzeBinaryAsyncTest.java | 78 +++++++++++++++++++ .../samples/Sample01_AnalyzeBinaryTest.java | 48 ++++++++++++ .../samples/Sample02_AnalyzeUrlAsyncTest.java | 55 +++++++++++++ .../samples/Sample02_AnalyzeUrlTest.java | 42 ++++++++++ 8 files changed, 347 insertions(+) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java index eac7dec5a1d8..f7a348125d7e 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java @@ -196,6 +196,45 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie = (DocumentContent) bigCombineOperation.getFinalResult().getContents().get(0); System.out.println( "Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + bigCombineDoc.getPages().size() + " pages"); + + // Raw string "2" — single page, equivalent to ContentRange.page(2) + SyncPoller rawPage2Operation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("2"), "application/octet-stream", null); + DocumentContent rawPage2Doc + = (DocumentContent) rawPage2Operation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + " page, " + + rawPage2Doc.getMarkdown().length() + " chars"); + + // Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) + SyncPoller rawPages13Operation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("1-3"), "application/octet-stream", null); + DocumentContent rawPages13Doc + = (DocumentContent) rawPages13Operation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " + + rawPages13Doc.getMarkdown().length() + " chars"); + + // Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) + SyncPoller rawPagesFrom3Operation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("3-"), "application/octet-stream", null); + DocumentContent rawPagesFrom3Doc + = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " + + rawPagesFrom3Doc.getMarkdown().length() + " chars"); + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithRawContentRange + // Analyze pages 1-3, page 5, and pages 9 onward using a raw range string. + // This is equivalent to: ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)) + SyncPoller rawRangeOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("1-3,5,9-"), "application/octet-stream", null); + DocumentContent rawRangeDoc + = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " + + rawRangeDoc.getMarkdown().length() + " chars"); + // END:ContentUnderstandingAnalyzeBinaryWithRawContentRange // END:ContentUnderstandingAnalyzeBinaryWithContentRange System.out.println("ContentRange binary analysis completed successfully"); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java index abfd2cf3782a..6eccfcdc05a5 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java @@ -293,6 +293,26 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient .then(pagesMono) .then(combineMono) .then(bigCombineMono) + .then(Mono.defer(() -> { + // Raw string "1-3,5,9-" — equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) + return client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("1-3,5,9-"), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent rawRangeDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + + " pages, " + rawRangeDoc.getMarkdown().length() + " chars"); + }); + })) .doOnError(error -> System.err.println("Error: " + error.getMessage())) .subscribe( result -> { diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java index 2790937a7637..41b021796817 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java @@ -389,6 +389,24 @@ public static void analyzeVideoUrlWithContentRange(ContentUnderstandingClient cl + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); segmentIndex++; } + + // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithRawContentRange + // Analyze the first 5 seconds using a raw range string (milliseconds). + // This is equivalent to: ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(5)) + AnalysisInput rawRangeInput = new AnalysisInput(); + rawRangeInput.setUrl(uriSource); + rawRangeInput.setContentRange(new ContentRange("0-5000")); + + SyncPoller rawRangeOperation + = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rawRangeInput)); + AnalysisResult rawRangeResult = rawRangeOperation.getFinalResult(); + + for (AnalysisContent rawMedia : rawRangeResult.getContents()) { + AudioVisualContent rawVideoContent = (AudioVisualContent) rawMedia; + System.out.println("Raw ContentRange segment: " + rawVideoContent.getStartTime().toMillis() + + " ms - " + rawVideoContent.getEndTime().toMillis() + " ms"); + } + // END:ContentUnderstandingAnalyzeVideoUrlWithRawContentRange // END:ContentUnderstandingAnalyzeVideoUrlWithContentRange } @@ -439,6 +457,22 @@ public static void analyzeAudioUrlWithContentRange(ContentUnderstandingClient cl AudioVisualContent subSecondContent = (AudioVisualContent) subSecondResult.getContents().get(0); System.out.println("TimeRange(1200ms, 3651ms): Start=" + subSecondContent.getStartTime().toMillis() + " ms, End=" + subSecondContent.getEndTime().toMillis() + " ms"); + + // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithRawContentRange + // Analyze audio from 5 seconds onward using a raw range string (milliseconds). + // This is equivalent to: ContentRange.timeRangeFrom(Duration.ofSeconds(5)) + AnalysisInput rawRangeInput = new AnalysisInput(); + rawRangeInput.setUrl(uriSource); + rawRangeInput.setContentRange(new ContentRange("5000-")); + + SyncPoller rawRangeOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawRangeInput)); + AnalysisResult rawRangeResult = rawRangeOperation.getFinalResult(); + + AudioVisualContent rawAudioContent = (AudioVisualContent) rawRangeResult.getContents().get(0); + System.out.println("Raw ContentRange audio analysis: " + rawAudioContent.getStartTime().toMillis() + + " ms onward"); + // END:ContentUnderstandingAnalyzeAudioUrlWithRawContentRange // END:ContentUnderstandingAnalyzeAudioUrlWithContentRange } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 41787da968d8..193d6abb52fb 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -782,6 +782,37 @@ public static void analyzeAudioUrlWithContentRange(ContentUnderstandingAsyncClie Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for audio analysis", e); } + // Raw string "5000-" — equivalent to TimeRangeFrom(5s) + AnalysisInput rawInput = new AnalysisInput(); + rawInput.setUrl(audioUrl); + rawInput.setContentRange(new ContentRange("5000-")); + + PollerFlux rawOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawInput)); + + CountDownLatch latch4 = new CountDownLatch(1); + + rawOperation.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + AudioVisualContent rawAudioContent = (AudioVisualContent) result.getContents().get(0); + System.out.println("Raw ContentRange audio analysis: " + + rawAudioContent.getStartTime().toMillis() + " ms onward"); + }) + .doOnError(error -> System.err.println("Error occurred: " + error.getMessage())) + .subscribe(result -> latch4.countDown(), error -> latch4.countDown()); + + try { latch4.await(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for audio analysis", e); + } // END:ContentUnderstandingAnalyzeAudioUrlWithContentRangeAsync } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java index 0a6710712fa7..f09e654657ff 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java @@ -392,5 +392,83 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertNotNull(bigCombineResult.getContents()); assertTrue(bigCombineDoc.getPages().size() > 0); assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); + + // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- + PollerFlux rawPage2Operation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("2"), "application/octet-stream", null); + AnalysisResult rawPage2Result = rawPage2Operation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent rawPage2Doc = (DocumentContent) rawPage2Result.getContents().get(0); + assertEquals(1, rawPage2Doc.getPages().size(), "Raw ContentRange('2') should return exactly 1 page"); + assertEquals(2, rawPage2Doc.getStartPageNumber(), "Raw ContentRange('2') should start at page 2"); + assertEquals(2, rawPage2Doc.getEndPageNumber(), "Raw ContentRange('2') should end at page 2"); + assertEquals(page2Doc.getMarkdown().length(), rawPage2Doc.getMarkdown().length(), + "Raw ContentRange('2') should return same markdown length as Page(2)"); + + // ---- Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) ---- + PollerFlux rawPages13Operation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1-3"), "application/octet-stream", null); + AnalysisResult rawPages13Result = rawPages13Operation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent rawPages13Doc = (DocumentContent) rawPages13Result.getContents().get(0); + assertEquals(3, rawPages13Doc.getPages().size(), "Raw ContentRange('1-3') should return exactly 3 pages"); + assertEquals(1, rawPages13Doc.getStartPageNumber(), "Raw ContentRange('1-3') should start at page 1"); + assertEquals(3, rawPages13Doc.getEndPageNumber(), "Raw ContentRange('1-3') should end at page 3"); + assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), + "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); + + // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- + PollerFlux rawPagesFrom3Operation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("3-"), "application/octet-stream", null); + AnalysisResult rawPagesFrom3Result = rawPagesFrom3Operation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent rawPagesFrom3Doc = (DocumentContent) rawPagesFrom3Result.getContents().get(0); + assertEquals(2, rawPagesFrom3Doc.getPages().size(), "Raw ContentRange('3-') should return 2 pages (pages 3-4)"); + assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); + assertEquals(4, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 4"); + assertEquals(rangeDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), + "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); + + // ---- Raw string "1-3,5,9-" — combine, equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) ---- + PollerFlux rawRangeOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1-3,5,9-"), "application/octet-stream", null); + AnalysisResult rawRangeResult = rawRangeOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent rawRangeDoc = (DocumentContent) rawRangeResult.getContents().get(0); + assertTrue(rawRangeDoc.getPages().size() > 0, "Raw ContentRange should return at least one page"); + assertEquals(bigCombineDoc.getPages().size(), rawRangeDoc.getPages().size(), + "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); + assertEquals(bigCombineDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), + "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); + System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " + + rawRangeDoc.getMarkdown().length() + " chars"); } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java index 5265578dc4e0..9547a1831f0d 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java @@ -362,5 +362,53 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { assertTrue(combineDoc.getEndPageNumber() >= 4); assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange + + // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- + SyncPoller rawPage2Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("2"), "application/octet-stream", null); + DocumentContent rawPage2Doc = (DocumentContent) rawPage2Operation.getFinalResult().getContents().get(0); + assertEquals(1, rawPage2Doc.getPages().size(), "Raw ContentRange('2') should return exactly 1 page"); + assertEquals(2, rawPage2Doc.getStartPageNumber(), "Raw ContentRange('2') should start at page 2"); + assertEquals(2, rawPage2Doc.getEndPageNumber(), "Raw ContentRange('2') should end at page 2"); + assertEquals(page2Doc.getMarkdown().length(), rawPage2Doc.getMarkdown().length(), + "Raw ContentRange('2') should return same markdown length as Page(2)"); + + // ---- Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) ---- + SyncPoller rawPages13Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1-3"), "application/octet-stream", null); + DocumentContent rawPages13Doc = (DocumentContent) rawPages13Operation.getFinalResult().getContents().get(0); + assertEquals(3, rawPages13Doc.getPages().size(), "Raw ContentRange('1-3') should return exactly 3 pages"); + assertEquals(1, rawPages13Doc.getStartPageNumber(), "Raw ContentRange('1-3') should start at page 1"); + assertEquals(3, rawPages13Doc.getEndPageNumber(), "Raw ContentRange('1-3') should end at page 3"); + assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), + "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); + + // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- + SyncPoller rawPagesFrom3Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("3-"), "application/octet-stream", null); + DocumentContent rawPagesFrom3Doc + = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); + assertEquals(2, rawPagesFrom3Doc.getPages().size(), "Raw ContentRange('3-') should return 2 pages (pages 3-4)"); + assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); + assertEquals(4, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 4"); + DocumentContent rangeFromDoc = (DocumentContent) rangeOperation.getFinalResult().getContents().get(0); + assertEquals(rangeFromDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), + "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); + + // ---- Raw string "1-3,5,9-" — combine, equivalent to ContentRange.combine(Pages(1,3), Page(5), PagesFrom(9)) ---- + SyncPoller rawRangeOperation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1-3,5,9-"), "application/octet-stream", null); + DocumentContent rawRangeDoc = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); + assertTrue(rawRangeDoc.getPages().size() > 0, "Raw ContentRange should return at least one page"); + assertEquals(combineRangeDoc.getPages().size(), rawRangeDoc.getPages().size(), + "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); + assertEquals(combineRangeDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), + "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); + System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " + + rawRangeDoc.getMarkdown().length() + " chars"); } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index 05ab9bef190c..d9c70d09fad4 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -620,6 +620,34 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertNotNull(avContent.getMarkdown()); assertFalse(avContent.getMarkdown().isEmpty()); } + + // ---- Raw string "0-5000" — equivalent to TimeRange(0, 5s) ---- + AnalysisInput rawVideoInput = new AnalysisInput(); + rawVideoInput.setUrl(uriSource); + rawVideoInput.setContentRange(new ContentRange("0-5000")); + + PollerFlux rawVideoOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rawVideoInput)); + AnalysisResult rawVideoResult = rawVideoOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(rawVideoResult); + assertNotNull(rawVideoResult.getContents()); + assertTrue(rawVideoResult.getContents().size() > 0, "Raw range video should return segments"); + for (AnalysisContent content : rawVideoResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + } + assertEquals(rangeResult.getContents().size(), rawVideoResult.getContents().size(), + "Raw ContentRange('0-5000') should return same segment count as TimeRange equivalent"); + System.out.println("Raw ContentRange('0-5000'): " + rawVideoResult.getContents().size() + " segment(s)"); } @Test @@ -720,5 +748,32 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { long subSecondDurationMs = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= subSecondDurationMs); + + // ---- Raw string "5000-" — equivalent to TimeRangeFrom(5s) ---- + AnalysisInput rawAudioInput = new AnalysisInput(); + rawAudioInput.setUrl(uriSource); + rawAudioInput.setContentRange(new ContentRange("5000-")); + + PollerFlux rawAudioOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawAudioInput)); + AnalysisResult rawAudioResult = rawAudioOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(rawAudioResult); + assertNotNull(rawAudioResult.getContents()); + assertTrue(rawAudioResult.getContents().size() > 0, "Raw range audio should return content"); + AudioVisualContent rawAudioContent = (AudioVisualContent) rawAudioResult.getContents().get(0); + assertTrue(rawAudioContent.getStartTime().toMillis() >= 5000, + "Raw ContentRange('5000-') audio StartTime should be >= 5000 ms"); + assertEquals(rangeAudioContent.getMarkdown().length(), rawAudioContent.getMarkdown().length(), + "Raw ContentRange('5000-') should return same markdown length as TimeRangeFrom equivalent"); + System.out.println("Raw ContentRange('5000-'): " + rawAudioContent.getMarkdown().length() + " chars, starts at " + + rawAudioContent.getStartTime().toMillis() + " ms"); } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index 9cc382e14741..f4425f943a99 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -503,6 +503,28 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertNotNull(avContent.getMarkdown()); assertFalse(avContent.getMarkdown().isEmpty()); } + + // ---- Raw string "0-5000" — equivalent to TimeRange(0, 5s) ---- + AnalysisInput rawVideoInput = new AnalysisInput(); + rawVideoInput.setUrl(uriSource); + rawVideoInput.setContentRange(new ContentRange("0-5000")); + + SyncPoller rawVideoOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rawVideoInput)); + AnalysisResult rawVideoResult = rawVideoOperation.getFinalResult(); + + assertNotNull(rawVideoResult); + assertNotNull(rawVideoResult.getContents()); + assertTrue(rawVideoResult.getContents().size() > 0, "Raw range video should return segments"); + for (AnalysisContent content : rawVideoResult.getContents()) { + assertTrue(content instanceof AudioVisualContent); + AudioVisualContent avContent = (AudioVisualContent) content; + assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + } + // The raw string "0-5000" should produce identical results to TimeRange(0, 5s) + assertEquals(rangeResult.getContents().size(), rawVideoResult.getContents().size(), + "Raw ContentRange('0-5000') should return same segment count as TimeRange equivalent"); + System.out.println("Raw ContentRange('0-5000'): " + rawVideoResult.getContents().size() + " segment(s)"); } @Test @@ -578,6 +600,26 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { long subSecondDurationMs = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= subSecondDurationMs); + + // ---- Raw string "5000-" — equivalent to TimeRangeFrom(5s) ---- + AnalysisInput rawAudioInput = new AnalysisInput(); + rawAudioInput.setUrl(uriSource); + rawAudioInput.setContentRange(new ContentRange("5000-")); + + SyncPoller rawAudioOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawAudioInput)); + AnalysisResult rawAudioResult = rawAudioOperation.getFinalResult(); + + assertNotNull(rawAudioResult); + assertNotNull(rawAudioResult.getContents()); + assertTrue(rawAudioResult.getContents().size() > 0, "Raw range audio should return content"); + AudioVisualContent rawAudioContent = (AudioVisualContent) rawAudioResult.getContents().get(0); + assertTrue(rawAudioContent.getStartTime().toMillis() >= 5000, + "Raw ContentRange('5000-') audio StartTime should be >= 5000 ms"); + assertEquals(rangeAudioContent.getMarkdown().length(), rawAudioContent.getMarkdown().length(), + "Raw ContentRange('5000-') should return same markdown length as TimeRangeFrom equivalent"); + System.out.println("Raw ContentRange('5000-'): " + rawAudioContent.getMarkdown().length() + " chars, starts at " + + rawAudioContent.getStartTime().toMillis() + " ms"); } @Test From 2dc0db8de622401b115ee45c8b68ee7ad93c0c8c Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Mon, 16 Mar 2026 13:54:47 +0800 Subject: [PATCH 05/17] Update assets.json tag and modify sample file paths --- .../azure-ai-contentunderstanding/assets.json | 2 +- .../samples/Sample01_AnalyzeBinary.java | 6 +-- .../samples/Sample01_AnalyzeBinaryAsync.java | 6 +-- .../resources/mixed_financial_invoices.pdf | Bin 0 -> 15324 bytes .../Sample01_AnalyzeBinaryAsyncTest.java | 38 +++++++++++++----- .../samples/Sample01_AnalyzeBinaryTest.java | 37 ++++++++++++----- 6 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/resources/mixed_financial_invoices.pdf diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json b/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json index 3b72fa4403b4..d770358ba5ed 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/contentunderstanding/azure-ai-contentunderstanding", - "Tag": "java/contentunderstanding/azure-ai-contentunderstanding_a546deb443" + "Tag": "java/contentunderstanding/azure-ai-contentunderstanding_acf3c730ff" } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java index f7a348125d7e..92e63d08c6e8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java @@ -140,8 +140,8 @@ public static void main(String[] args) throws IOException { */ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient client) { try { - // Load a multi-page document (4 pages) - String multiPageFilePath = "src/samples/resources/mixed_financial_docs.pdf"; + // Load a multi-page document (10 pages) + String multiPageFilePath = "src/samples/resources/mixed_financial_invoices.pdf"; Path multiPagePath = Paths.get(multiPageFilePath); byte[] multiPageBytes = Files.readAllBytes(multiPagePath); BinaryData multiPageData = BinaryData.fromBytes(multiPageBytes); @@ -184,7 +184,7 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); - // Combine with out-of-range pages (clamped by the service) + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward SyncPoller bigCombineOperation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, ContentRange.combine( diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java index 6eccfcdc05a5..8d831ebcc1ce 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java @@ -176,8 +176,8 @@ public static void main(String[] args) throws IOException, InterruptedException */ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient client) throws IOException, InterruptedException { - // Load a multi-page document (4 pages) - String multiPageFilePath = "src/samples/resources/mixed_financial_docs.pdf"; + // Load a multi-page document (10 pages) + String multiPageFilePath = "src/samples/resources/mixed_financial_invoices.pdf"; Path multiPagePath = Paths.get(multiPageFilePath); byte[] multiPageBytes = Files.readAllBytes(multiPagePath); BinaryData multiPageData = BinaryData.fromBytes(multiPageBytes); @@ -264,7 +264,7 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); }); - // Combine with out-of-range pages (clamped by the service) + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward Mono bigCombineMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, ContentRange.combine( diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/resources/mixed_financial_invoices.pdf b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/resources/mixed_financial_invoices.pdf new file mode 100644 index 0000000000000000000000000000000000000000..793c3d4e24b224a54b3080866a997d7df1dee832 GIT binary patch literal 15324 zcmch8byyYLvbS`1NVAbfVh6G5M!FjWiA_m&HzJLMbhjW#OGt;LARrRb-64(ofp1)W z^_+8`=ezgrKQ`ka6 zHrRGqD)%VQ*QYd)D=J9cgH_+Qh$IVM!JVg>66bKgP9TsI(Y!<7(M~-cb4g{udVGaX zqHgFvniT6Jj@Zm^LW%X5x2wnSVFYkmm6Am;`@F&kW|vDC=-!wb8i9Gh?<*k#y+WNF z<&0Pg5k~OC6RCOIA&HA@PsteDGdcA#D;PKU*!`JV*nDL0DvM5!WwKavvJc&Y9rr=? zERhCQlegZUp{N0&OT&Cti*4!h-iY@U(HAmB$l81Q_wc<&U6ojB<=BP;WZ~Db;s!|v z^xyO=_K(DMa9@&8B!AM%D?y?iM0%ht(T{v>OvX_KjiPzTmQ>9o&o4r5i&bA7vxdFc z998ZbYGv4-2IlakIKEW=a0Qn`K5zXvEy|%QBgppHumT`hjzf*|&8FNm+(dn5a?MX%<3oj14%6orheFYXIaHEZD)?_) z(v8Lqr>QKB1{b?bbZ3LrY?ZFj3gn@83u4OkH_=51mAXed0Uj{PGMGQzq5#ROt03S&U1Y;x7yTn)E7i+ z9r5w=(z^VD0s40Cx_nj^ppJt5z7GK#hqfm9>5R*#C7P>RzP*XWTG21>txb`)*NQK^ z1=!e&v6eXuXBJQw*(-q`Iv7(sh)Jln-0!&g*#Saq?|ilO3WD36AM$T`ola1nVZZgR z!l08or48u*}GoOGj8tW;l6Le>Z5y4sGzTLwmp9?*VbSsdyb@>iJ@S zqV*S4dj6uKF{4-?8Dsc}iE9>l-&R+y8Ddr~{Jw-8**f3g)K8tr5=>LeVatxES1zR~ zbsG#UyI7FYluNv==S?r~`mC|auU%3Kzb##xS`uYP)i`?Lafv5uuvjDe+2igiTv;z9 z41aPByO{dq&0@*d!(#5odj@GdN~ef0N2EvVPA<9y7OC_YGf1PSZvJel2_a6&J?$6K zg0-4drz$&x#!#nrXA**Rpk5J@5uZXXY-}0JLtnPzoYcZY0gaQY9u}{*{ANIiCB0gz zbzOVhau_G7Iu!>*tSROmQ`_NFoB1f;f}ItsTK>{(MFRh0;6QJP%nXpGoz#IcBjJLY z5ZhJzx^ii_?_NewxwiiL`LTQL+Zx*s;1nYd8>fksfFa?>AA@M$ISMQ_2rO~c6o!EYZVUl7EVi$)Mkw`vl(0Cizv$+R<`?ix$$v$8tKrH}H=$<^GPFhv)2IeRttN!%0qhAAb|qAyRX z*mS_Oi=+S|R*)REfzE9f9NzAg-!P~kTT`Y&&q>@8;x(Qx5kaOQCXTkFsIFOrSdSW? zC;KQK0vNi!a0Fu@1QD=VjiW^oA>$@op(L-)?7N4ach@g}jrE&LU;yb}7n88eafRLR z-*v-3sIe+4?1q061l!Xao;`DN?6>o6j{f+Ub@nCAwy^yY<-{#|{)s4m;^-|f|Aj|? z1Kghg_AdeM4;cRenSTJd+rEDh{I>uH&O}00m6x8>InWkiBr2M>Nw-wmCA004d3++xGYSN03&6~#f&ghzL!k2w4g_TmQ_)kURw50O^rzlNgPhqhQ6EN(Zuzw{UX0w0+v z{uKf3yv`gU=ma6x-fn|H%8M%-3?D9>k!Yv@CV3}SKSnnMXSi%uC2dQ!;0W$#tmbS9 zfKqnS4aGaBM=m>@!%=^3&Fc8H+{0|I78{TJxoq$xn-&8o>*l>deiCyayUQKU3FdZ)@l<#?p#|VsvtVxlc9#fDj4vLQ-^`g0h)rk4CQU4tLv(yp2Q6m zV%L{$lFNaZV@|SIm6&9ox>zJ+JGwbwhA$J+$^j5+aU_Zk-oIDtFN#ziBJ)J;`gW4- zeXmP2)qtb<3PTQCaAi<5X|I)IW~+of6~9pOSd)uf-%dDuz5bI=q;TfU*2a9dPUu(m z$eAsBkT@kDq_u7Wg!xV*bU0m-F5KGTa~uR)+&BUFm_l$hvNPXX*5Xl^_-USf7Y!la zS5dNuv+k4ev#Jj`c(;MYOO_f&B#*soJbL+Q^f~nOa0PcT#X=Kbq9lPoXWu`aFiuV? zMake@hQ}EtmQdmi0y25mpuJ{$n(2sar21OVUJf@9f0aLIVYJdY(ZhkS>hp;BFqJd& z%cQh^a-!{Zt6Ke5_&NE01(-r^eTK|N-7ES<)hBe$-I-lLkQP3l6R~T(jUK+>s(eTG zfzwbTTUe$egOO?uxQqs^S%!H}KF|f^BUH*-IH&Fhq)6SMHzz>W_}Uh_X^y1xkiJ3Yn&h5oF@5y~1CdM+0YE#~qQs`l~Xm zG%=mU*RShxJ8Y7lnR#8jBU#f)OyceEtd=2oxWx0sMQ8P~4e^(cUBxdjeA4a;%gI-N zWF-od^)h#i-&q!COR^_djMpN6OzV%ARJ%;LD4MvO5_P1Yq0Ld+%(o_d;#xstt!O=( zhqi?qaptgo9ms=m3bNxEUJS0Lb!c+XO3%ltDUjSknipo6VtHvoDb99m{^iRUa|v5h z;InQ^|-u3*yadt&H#GywBfn_Tsd|JUgJH);J}o@QCtqdTNQmx()7&eC7w;`G(Lf z+ji$yVZFWo|0P?03oGdM^8fFo^$)MX@2!sSo&O^F@5GfG`m@#HqORaH!;SmqN~>8M zdp9yFa3RTCo%V%F&ohd!l*kz1jXqLE#PWB%-mgv|A1ItzG;(|1HuLF>s^s88ES$5K zHdLn2u^G$O?a(|-cnz;SB!Q`(sXqe6o-N9l1|px2?+{qEMlLfPQs2INF!OQ_5C0?E zy$k;SR#JFFzxFlSkI=iMT8x!XS0GmGV~?eMk;{(8jDx1Omg_mXs}R>Ih_{#4u#dZY z9V>Me?SK!5Uui$@cGMgM8osR585-Cha|zHngw@U_Y;W4**Ux{bFIA{)xAJge1lo{M zl)QW?UW&8Ak+VJh?5ybXqbqJq8NDnws6yHMFlmz&54xirVW~PJCG1*kvT3}!%efR; zlo#DkF_8+StR+~?fu@#pE0DfNU6SN)Ya82NR%`5Uh}g6lz9}gIv0dO<4>Fm2M|WdV)kuAtV4~k{ zPA^3iPu&UpYUXggH8nE0*Z9HCH!W7NP5VLd7_T) zGwB9L@^iMG%k~9@2xmBoIP0S)<<&d9pe+inwFL%VOUx zUl4$o@^lG5Kdy(vD;sq;q=yL1Kmx1yZ-=B*KA;fI7s!PR;8_GlwFavt(`7A562}meNq=T2UA2#~ zpL5ufZ&}wPsld@_Xz?rga77sz{!k-fTCi?;n|c4}0MwHLnr+?+u|#eNQ1bpJV9~-+ zibZ@#W^W81qh?06igs`IxY#}fqV^`C+tJWhSfp9+%{cQq`SBxCT;g;Txk1R>?rFuv zA@a6-1r3|#j88@nIJm7S?u@aMhj?_A{jiIa>fK(PJK@O#wPTBL*YnGbm^WxUSmsoW zaF9r9`~FYu_97*pgA5hKmyTCGJjsCA)jTV?qQ&PTtD$^phQl2$N-^?SB=ar22t*7)5q6;swFW{5!JsmNoM4IWVjxO}YvlpckuUh>V##=0q{` zvGF}mdxPvrap;6F-*6I+HYf!n_K`jlvJNm(>c|}Roo`!mhI841I_cu=svTW@ZgxAS9F=uPz+pWtc!4WsszZwbs@`hsw`YVrWf(WBb z?6DhvU~mJU4F#K&r9eeJTao}fz0oxyA)Et3M(;z9$daS4Z(CT>rS6eGP*#`TN}t)J zmwH5>zMy|U{lRFbbdjwbnOP=_9Mdr09?R-QPyS=+x1tE%N{q0@EOZn%_-lO!!tOjl z>{Oc9!)Qf)yR6mwrMi%2lO*1hfGZu%YL4mbWzViwi*8G9d+#7(tc|h|F?4&Bjg5TC z5b}~{{q`lxFW1d;f*r+OQS{d*bBBJ=&lU6X<(w*tPGyLT?`Z?Z^Q5g*yPsG#Mm-4= zi)XPp)YTYYS}YY21hK4zJBgL_B_g{xN{aHTQx(aIPe>LpJR}>Jxl0s6pm4?HI^r65ta=9!)o1*%+Xs zAIs3$C-UO5-jR&ko7~15|RATl`+DmZ#D0u<>L9o7LB#x(co8&IZqa(c&w8@ zU=f+P=CNfAVG%inJQjJRnn$BEF(QqLg3Q20mY{(}Nwlzng3NV(IBadTK=pCoKqAzL z`*jM*poNGgMEyNhi;3L_93sr)7cBi*z;~@aJZPh_FU5*YZI9ZeEPa%j*AnwzCJmtw zIni%Tf!XP?2CRa69PQsn%E<&(k>%tF8jSvMYMG+8{u5}GGXu#o1a z=Nt!fL==4)fUD@E4&P#&B??8K>0Uosu=N4fM=(4c!e&EFVi2@Wmcqd@`H;t!DT#yS z)J@^zHZnb$ZSA_j6x~Xe6o(9}7Jq<7%|rF1K;luu*KX`Af-ILW#z*wzrde06HFTwv zEG%9u{cL+ITS6-PVxei?XK#uzRcowE30cxoKH%OjOcd)TDS%E4GK7RT#FaO|YM4q1 z$=c(#)D%@f+sP!|hFvEz# zaxrosSQA{7rRi!*EoFkj`?cY_je%C*@G_6HW{kBcef=zA&QZE!ysw&>-+G><+I_fx zPHlQVODz=W8+qjSHh&T6HxT{X;1TFQM2{dpMWk+HS3fw{zIXl$_5U42LwP_y-AY~5 z`yBJ6Z_M2LM;|E{%Z*Sj3O|7JZXB)l&d^*Adg(ASgpi01tD#9H;<_@JvOUwioVfw- z3ozxmgE>ezSdda>A=uud_|vB|lCLB)BPP$04vD1>KiyXztbb^RgsX$?B=}UVaWRDO zwZJ%b3+n|o&7B6MnM?FTVMMr?2Okg6KVa#IjJ}1{okWxA`r@#9VrpJbnqqZ!FIaM? z_KNH~%WLLsLLwQ1+^dq$ibk?q8oWAY z)u0{o;Z?Fy7U}0>in&+v1%YvQwdWC()IwZ7wGdY^*LpCIsbSglL{o$2Lx43pB+mJ) zE>F-^%X#fXUagYT1eKKeX4>7@djq&1v2oN0N=jKU&s~fu8oD+ zEU6*;IVPei8X{K}J0AMxL5cuRwN0}er&VOHbFQ@J&7PfH-1i?6s)6+Qe3oDQI!c`| zs`;V=C?1e{spA&ZI7eUHx!@JQr;PB$3 zxuKkV7$^#37hFjw&wklVY@reK9|b&@yLfIIn(5+p&(a{S3Q5l?SfY2 zB?i|`@Ts52m%GLE6JmL%*tft(l4K?dw5Syd{QP?K7$YfSoZ=kvdgl)0<7}OD+z;;( z4T0Znlgrn=6Wb5mTsIe&7H5mU3#rh9oe!+s$(1KOO2xN?FclX@HWt!bchw6n$@y*+ z9^ISf9`2ix+0GB^S$Z;Pu#jPBp#jCtv`y=GI^;;DtnzRx?vQ1{N<$d5SO8})H9iw` z%=ZcKrZ9k4%vU$PyZlaeMO8fGO%wU48GYmsxA!8F{Ho%3D)J_B*yFk_q&`amT!jqN zWNuz6MowNGca90UjJ_@8su>Jzd$MBQuOE85FAr2MzMakaJ;_3>_>Btqt$Q8xAN=c( zKdt!RTj~F82Rj7xvy~o_Ea#L5#r5C6Ao4k&QA@OVCW0CrP2DsnV_l(O#iG%G%j)$J z_W*uaer?juWHGY9f-_Nl@o4#Rqi{(`*TOzVj6K}^0e*j?M|hp7^G2?~Jl1pLmQsT6Nh!#B;H()#D&Ok%X(LnpNjY*o?3)2Yj-&n&RwD z;+V*>Zo0d=W{%y1k=1QG6Y9er>SLrTV(gbUzj-yxkw!jEgA; z?5!=X^Nhe3PL-a}&%1-h6_K0PcLo@t)dA>?)H z)rs64e1s*2-$ndDaC1eP7731a5F&$9HCm+xK4|f!4Z^q=%p9a+%9Nn@1iLA*sm34H z*e-Phh{(NkMXIl|f!Q2qpDW_<`KIi-yzdLVzd0AENVZ_H&W#biQj;COLky*_wAV## zR*Mj>UeIG@N|*`6Zt5GrVkgMEH_yYg#QoA?)Vnz!v+9EotvY5AnqU{Fjjm3AW95`R z{rt>`B?85yCixAiocJB?YyYmCG2~-5ZukhS5XYGjqr4a8un%h*XlT)fg!mm13V~w$ z^c$uR^c-Qc_eXRPq>LZysnQj}XK+@qA|Hf;+{g~ZC=d$aY(d$|wg`OItZD0Y)190g zbgWwsb=QPPy8yvY-O;H zqji|f-V3rNGkmm7=XKE;+tpHiovznUt3Qe_KOSplMIa6c9&|n zaK>%*jXbE$hN%8_HRQ`&s3N&DzeO63q~qm?OkH;X3Mec^EtDFsU7oU1GE}U=W#g5t zL))%hK+{Q$6!oAwa@A%<`eA<{V2Jz-PbkY&{qkw^L7Y2dMC2@uz<3N zT$mdsxjcU?r4HBbNm+>Hv%N;rcAC;~S?WecjPSjhM{RzU3{bT_`VBg7=~`P-&$zJw z#rG7SA22^VVWNNPq1BUB#0AYwT`oc6j@(1spl8FG;e3o!TUL?QY0DTxJyE4_41cW4T?01D+Vfn??b>T>uk~Q@3H!A$MkplIgwB z5`pR~JT5yG+PpL@WCg_GWNpFNwWu+|*tb@bK{z^}Rm6t$M#{W+pV^y}ShXkVKT;FM z{z69ko7w-?RSW(Pu3E^SHtuf$?0e_`jtvXqgmV2f|HNdu__RL(ELptHYD60T@FTfN zaySn+)E^?F!M>ABw{!li`!xS_-p=GzWw31DIK?&7=CzwjEf%7nqmI1+7 z!&E!FJ&f00k8p8ibI#En4%ZCZ_7SVmT-uA$KVlQ!Prvaog$o+_FtL>Oa4EKc}tjE^8dpf&BX zL_qz1F5!)fY2ptTQyQv+7y^7e=lwZBMTf+A=N4%KR?+h8ol(~lx;?yMl=tPl-rscW zv~Vj*i^QvEJ}7xT-AeK_+^_5B^Ac;?6=&y`B4tuhYgM1Nv|S*WZRB<(*O^}`k7C19&L&3UoK%T z7&^7nJ9X!4pc_9^U<^;!;E;EO z+MX^!1h}6oVx)-Xfb>{^3+rje5>W#auGKuqbJFa1M(6e3MWrR&=+Ok}+dC|K76*-( z=?i2)oi$0m7>IPo#pCy}%toK_s0U!g!i7^;6f-KpAFauTefjUF5hz7gr%F}4l`)d1 zz3-i_3s3z-g)DAkma*~39@t63|uE4kk<{D4#(V~ z@jhcw)j<>9))ed$c5O|k>VwxTM&CeiAOV&a{ZTaUn;Rd14*g2}+ymLUY@O}3Tu;X<;-y(jwfWi<}7!vsB>f>|D)2gJVW4k-X_Z ztpZ60p}xY1(<8^BWii~IcOv`%+w7y)_Z2~~xzMHRu1z|ygLODMT4Hs&p^0@_FoC{R z$dyG5u)~r(K2XQ>JxzF1w40oRPO?208n1=_eo6klYdVJm_BIZp2Py)5OWCB{TD*$_ z4;ex(Y$wtdGcE_GFqF&f*7B<%_}=Ej=|;FxeUj? z^?n+Ww(|8^9z3ZJcfLuMo2Ho4;xmzA>k<&=lVs?_conEaF(ki2$L^^<bu)MrJcFno=-UJ zrXczAJoPUr50)*zt>R=*J|xVebR;aV@9f&#jpdCv;B!^CgU86Ro}|o5S|iP3gmKKD_LFH|$NUQ;iZuN%__yRBZaCmIgu$S9H}Q&BXiL zIVCSnvqaLOh9lVnM=^N=-&1>m`oH(f2#ke;V zd9v{}%3y@B*L>*+zIjIlyd2A~NEO9EatiV)5LDoc>qAfMLPVp;AfoIy4GCWwXBZ~h z_Uok|_4pNOzP|?k3l{zkXn_B`3jIr*{o`Tr?{W5f=f6n)J8uaH0{%HF7?q@FH^WWn zKYw)}`_&_hfK*y$)g*zT%EWFx|A`ulOT=Lve@I+fO1*r?dgQqZkL1!FUBkpgDYic0QXL2i{Lh#;eaTCWZqMS7bz>y4_=#Nd zJo{QT>~-+e=SxVyq9>N&m;kfv+hv7D9~_6cgiTkyecSMd1|=B+yaM7k?~#O_Vc(+7 zW3-0i%rX49*WonmYVMKL{nkWUmST~n_K#)zb~oHy(1(q56DE%9S(P5CTN{K6boYk( zJ*t_}>}Keu#v~Zjti3-LBY6SCh!<$D=w~&^5_s-vxJU3Hu$SZ+p?*zo2pq;!jyv&A zDxvi1LZ8|gTm0NNn3@AdttqI?h1=AtpLgqvB0`Mh?K|}2xv`V-x=qVDp=%DzXv=IP zXiv$L1@>fJl!DG^F3TL?b5y5$9hkz|6^3_*Kt1j9PqPPz6rt;gw2!$k2fYJ)DdG_o z)usfKo!Q{fhM(@Imnq7dAh%E_ z8*|`vGzzsm#2#C;Y8KgDFEZfFAI88Uf=ZwhaIqW-Jk&Txel5FtJqv)!FcqSSm?T16^t+P!46gwYKKC#! z!@c>bm5=jzTG(Hx2DhZB3mrO9PdL)Z74|M?M?h8*L2V4ZR1^0@!D4S3}V zGhMs;`a6nYmN@~Qlh(@E`rF!G%^xC-UVD2``ZjpA83~nJ8bp=ykX#wyMllr2y*61I z{&;oA1VkLj2i-(@akLxwIJ$Phbm7JOV!ia`{SE!+6(5@D6acC9(Pi8ZM$^Y;f&O=UTVhB#>#_WA=jj z%%fRS{8XiR988FYVx(GmKP>m~FJrWo)#T}LHrGkc-kW*qLN_ec3rdlNOR_?*5yg1y z!_F+IX+ibvDzBr0^k1q|KS{EE|II?ByyAiDb1UtJkdpykq%>f)*mbRj{PL_WapmV6X7(0K@`MAA4fc{DVxux`jCmj4^BE|1U60@^5 z{T~?SM+e?-hWQ^D;U|CI?Q#hSa7cjw;6HDWQeeRMx!y$er62(Ccf7mF3*k_9v@=nI zIRo@KZjyBX9O^Lln}wFKxrrBu{rOk?&%ZJce_Xd8ue0BG=YMy&pRT(9`?LG;y86FA zyYJ5_{x&fF*Jt-VH1vNs+^y~Pe>mKay5pC<`~Nud-@Ot4hx7PRW&ARa8!7&u6==wh z`a{&k*}~2d!1MrS3v;|lDl-L`-TV~wba8|ML}dVfn$-XeTT_^$le3ZScMYs2AqQ|W zvaz>@IWgZP_}%22-KNq>+;j&pN$`PzU~VAfCLQg@NCt7~-n3A+bhf^!lCu1sa%W@> z(7eqha0JNMy4qRZCcv=))I=4O(Q!YQ-Av-wG7#`aIsM!Y0_M62 zzy6~PavP8Nxr`IU`)e7P=LVC0ZpZbTak)UZj}?Dz$IT1~_~4L~3W^q)L~K%Bqq2M7%1`sWxRFz>JJAi!Vt z4RmwH{>k&rk>mO28h{`W=s))y1mWcUWn2jNFZ&CE@Z9E}{dk$4QJ7>U6quZx?GPY)RfbT+l`$Gbt zC%_Apfbj5ef+WRwxgZi;T%uA?Fc%aoA;k^k;)IHE3;pL7-x2>tz#W~xOB;xj6U>WF LPcNw?h5r8lGu)Xy literal 0 HcmV?d00001 diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java index f09e654657ff..4c346a5b0dc1 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java @@ -273,8 +273,8 @@ public void testAnalyzeBinaryAsync() throws IOException { @Test public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { - // Load the multi-page sample file (4 pages) - String filePath = "src/samples/resources/mixed_financial_docs.pdf"; + // Load the multi-page sample file (10 pages) + String filePath = "src/samples/resources/mixed_financial_invoices.pdf"; Path path = Paths.get(filePath); byte[] fileBytes = Files.readAllBytes(path); BinaryData binaryData = BinaryData.fromBytes(fileBytes); @@ -291,7 +291,7 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { } }).block(); DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); - assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); // ---- PagesFrom(3) — extract pages 3 to end ---- PollerFlux rangeOperation @@ -309,9 +309,9 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); - assertEquals(2, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 2 pages"); + assertEquals(8, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 8 pages"); assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); - assertEquals(4, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 4"); + assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); @@ -368,12 +368,19 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); assertTrue(combineDoc.getPages().size() >= 2); + assertEquals(3, combineDoc.getPages().size(), "Combine(Page(1), Pages(3,4)) should return exactly 3 pages"); + java.util.List combinePageNumbers = combineDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 3, 4), combinePageNumbers, + "Combine(Page(1), Pages(3,4)) should extract pages 1, 3, 4"); assertEquals(1, combineDoc.getStartPageNumber()); - assertTrue(combineDoc.getEndPageNumber() >= 4); + assertEquals(4, combineDoc.getEndPageNumber(), "Combine should end at page 4"); assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); - // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges with out-of-range pages ---- - // Note: The document has only 4 pages, so Page(5) and PagesFrom(9) will be clamped + // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- PollerFlux bigCombineOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), @@ -390,7 +397,15 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertNotNull(bigCombineResult); assertNotNull(bigCombineResult.getContents()); - assertTrue(bigCombineDoc.getPages().size() > 0); + assertEquals(6, bigCombineDoc.getPages().size(), + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); + java.util.List combineRangePageNumbers = bigCombineDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- @@ -444,9 +459,10 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { } }).block(); DocumentContent rawPagesFrom3Doc = (DocumentContent) rawPagesFrom3Result.getContents().get(0); - assertEquals(2, rawPagesFrom3Doc.getPages().size(), "Raw ContentRange('3-') should return 2 pages (pages 3-4)"); + assertEquals(8, rawPagesFrom3Doc.getPages().size(), + "Raw ContentRange('3-') should return 8 pages (pages 3-10)"); assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); - assertEquals(4, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 4"); + assertEquals(10, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 10"); assertEquals(rangeDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java index 9547a1831f0d..fe18467d11c7 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java @@ -264,8 +264,8 @@ public void testAnalyzeBinary() throws IOException { @Test public void testAnalyzeBinaryWithPageContentRanges() throws IOException { - // Load the multi-page sample file (4 pages) - String filePath = "src/samples/resources/mixed_financial_docs.pdf"; + // Load the multi-page sample file (10 pages) + String filePath = "src/samples/resources/mixed_financial_invoices.pdf"; Path path = Paths.get(filePath); byte[] fileBytes = Files.readAllBytes(path); BinaryData binaryData = BinaryData.fromBytes(fileBytes); @@ -275,7 +275,7 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData); AnalysisResult fullResult = fullOperation.getFinalResult(); DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); - assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); // BEGIN:ContentUnderstandingAnalyzeBinaryWithPagesFrom // ---- PagesFrom(3) — extract pages 3 to end ---- @@ -291,16 +291,15 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); - assertEquals(2, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 2 pages"); + assertEquals(8, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 8 pages"); assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); - assertEquals(4, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 4"); + assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPages // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- - // Note: The document has only 4 pages, so Page(5) and PagesFrom(9) will be clamped SyncPoller combineRangeOperation = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), @@ -314,7 +313,15 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { assertNotNull(combineRangeResult); assertNotNull(combineRangeResult.getContents()); DocumentContent combineRangeDoc = (DocumentContent) combineRangeResult.getContents().get(0); - assertTrue(combineRangeDoc.getPages().size() > 0); + assertEquals(6, combineRangeDoc.getPages().size(), + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); + java.util.List combineRangePageNumbers = combineRangeDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); assertTrue(fullDoc.getMarkdown().length() >= combineRangeDoc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages @@ -357,9 +364,16 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { // END:ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange - assertTrue(combineDoc.getPages().size() >= 2); + assertEquals(3, combineDoc.getPages().size(), "Combine(Page(1), Pages(3,4)) should return exactly 3 pages"); + java.util.List combinePageNumbers = combineDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 3, 4), combinePageNumbers, + "Combine(Page(1), Pages(3,4)) should extract pages 1, 3, 4"); assertEquals(1, combineDoc.getStartPageNumber()); - assertTrue(combineDoc.getEndPageNumber() >= 4); + assertEquals(4, combineDoc.getEndPageNumber(), "Combine should end at page 4"); assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange @@ -391,9 +405,10 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { new ContentRange("3-"), "application/octet-stream", null); DocumentContent rawPagesFrom3Doc = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); - assertEquals(2, rawPagesFrom3Doc.getPages().size(), "Raw ContentRange('3-') should return 2 pages (pages 3-4)"); + assertEquals(8, rawPagesFrom3Doc.getPages().size(), + "Raw ContentRange('3-') should return 8 pages (pages 3-10)"); assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); - assertEquals(4, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 4"); + assertEquals(10, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 10"); DocumentContent rangeFromDoc = (DocumentContent) rangeOperation.getFinalResult().getContents().get(0); assertEquals(rangeFromDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); From 490216e2ea0dd147789040750fbc47f716334ae9 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Mon, 16 Mar 2026 18:48:08 +0800 Subject: [PATCH 06/17] Add assertions for start and end time ranges in audio/video analysis tests --- .../samples/Sample02_AnalyzeUrlAsyncTest.java | 27 +++++++++++++++++++ .../samples/Sample02_AnalyzeUrlTest.java | 27 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index d9c70d09fad4..d86364d44054 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -539,6 +539,10 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertTrue(content instanceof AudioVisualContent, "Video analysis should return AudioVisualContent"); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 0, + "Range(0-5s) segment StartTime (" + avContent.getStartTime().toMillis() + " ms) should be >= 0 ms"); + assertTrue(avContent.getEndTime().toMillis() <= 5000, + "Range(0-5s) segment EndTime (" + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); } // ---- TimeRangeFrom(10s) — from 10 seconds to end ---- @@ -564,6 +568,8 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 10000, "TimeRangeFrom(10s) segment StartTime (" + + avContent.getStartTime().toMillis() + " ms) should be >= 10000 ms"); assertNotNull(avContent.getMarkdown()); assertFalse(avContent.getMarkdown().isEmpty()); } @@ -591,6 +597,10 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 1200, "Range(1200ms-3651ms) segment StartTime (" + + avContent.getStartTime().toMillis() + " ms) should be >= 1200 ms"); + assertTrue(avContent.getEndTime().toMillis() <= 3651, "Range(1200ms-3651ms) segment EndTime (" + + avContent.getEndTime().toMillis() + " ms) should be <= 3651 ms"); } // ---- Combine multiple time ranges (0-3s, 30s-) ---- @@ -617,6 +627,9 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getEndTime().toMillis() <= 3000 || avContent.getStartTime().toMillis() >= 30000, + "Combine(0-3s, 30s-) segment should be in [0,3s] or [30s,∞), but was " + + avContent.getStartTime().toMillis() + "-" + avContent.getEndTime().toMillis() + " ms"); assertNotNull(avContent.getMarkdown()); assertFalse(avContent.getMarkdown().isEmpty()); } @@ -644,6 +657,10 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 0, "Raw range(0-5000) segment StartTime (" + + avContent.getStartTime().toMillis() + " ms) should be >= 0 ms"); + assertTrue(avContent.getEndTime().toMillis() <= 5000, "Raw range(0-5000) segment EndTime (" + + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); } assertEquals(rangeResult.getContents().size(), rawVideoResult.getContents().size(), "Raw ContentRange('0-5000') should return same segment count as TimeRange equivalent"); @@ -702,6 +719,8 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { assertTrue(fullPhraseCount >= rangePhraseCount); long rangeDurationMs = rangeAudioContent.getEndTime().toMillis() - rangeAudioContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= rangeDurationMs); + assertTrue(rangeAudioContent.getStartTime().toMillis() >= 5000, "TimeRangeFrom(5s) audio StartTime (" + + rangeAudioContent.getStartTime().toMillis() + " ms) should be >= 5000 ms"); // ---- TimeRange(2s, 8s) — specific time window ---- AnalysisInput windowInput = new AnalysisInput(); @@ -722,6 +741,10 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { assertTrue(audioWindowContent.getEndTime().toMillis() > audioWindowContent.getStartTime().toMillis()); assertTrue(audioWindowContent.getMarkdown().length() > 0); + assertTrue(audioWindowContent.getStartTime().toMillis() >= 2000, "Range(2s-8s) audio StartTime (" + + audioWindowContent.getStartTime().toMillis() + " ms) should be >= 2000 ms"); + assertTrue(audioWindowContent.getEndTime().toMillis() <= 8000, + "Range(2s-8s) audio EndTime (" + audioWindowContent.getEndTime().toMillis() + " ms) should be <= 8000 ms"); long windowDurationMs = audioWindowContent.getEndTime().toMillis() - audioWindowContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= windowDurationMs); @@ -745,6 +768,10 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { assertTrue(audioSubSecondContent.getEndTime().toMillis() > audioSubSecondContent.getStartTime().toMillis()); assertTrue(audioSubSecondContent.getMarkdown().length() > 0); + assertTrue(audioSubSecondContent.getStartTime().toMillis() >= 1200, "Range(1200ms-3651ms) audio StartTime (" + + audioSubSecondContent.getStartTime().toMillis() + " ms) should be >= 1200 ms"); + assertTrue(audioSubSecondContent.getEndTime().toMillis() <= 3651, "Range(1200ms-3651ms) audio EndTime (" + + audioSubSecondContent.getEndTime().toMillis() + " ms) should be <= 3651 ms"); long subSecondDurationMs = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= subSecondDurationMs); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index f4425f943a99..673aee696e85 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -442,6 +442,10 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertTrue(content instanceof AudioVisualContent, "Video analysis should return AudioVisualContent"); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 0, + "Range(0-5s) segment StartTime (" + avContent.getStartTime().toMillis() + " ms) should be >= 0 ms"); + assertTrue(avContent.getEndTime().toMillis() <= 5000, + "Range(0-5s) segment EndTime (" + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); } // END:Assertion_ContentUnderstandingAnalyzeVideoUrlWithTimeContentRanges @@ -461,6 +465,8 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 10000, "TimeRangeFrom(10s) segment StartTime (" + + avContent.getStartTime().toMillis() + " ms) should be >= 10000 ms"); assertNotNull(avContent.getMarkdown()); assertFalse(avContent.getMarkdown().isEmpty()); } @@ -481,6 +487,10 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 1200, "Range(1200ms-3651ms) segment StartTime (" + + avContent.getStartTime().toMillis() + " ms) should be >= 1200 ms"); + assertTrue(avContent.getEndTime().toMillis() <= 3651, "Range(1200ms-3651ms) segment EndTime (" + + avContent.getEndTime().toMillis() + " ms) should be <= 3651 ms"); } // ---- Combine multiple time ranges (0-3s, 30s-) ---- @@ -500,6 +510,9 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getEndTime().toMillis() <= 3000 || avContent.getStartTime().toMillis() >= 30000, + "Combine(0-3s, 30s-) segment should be in [0,3s] or [30s,∞), but was " + + avContent.getStartTime().toMillis() + "-" + avContent.getEndTime().toMillis() + " ms"); assertNotNull(avContent.getMarkdown()); assertFalse(avContent.getMarkdown().isEmpty()); } @@ -520,6 +533,10 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertTrue(content instanceof AudioVisualContent); AudioVisualContent avContent = (AudioVisualContent) content; assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); + assertTrue(avContent.getStartTime().toMillis() >= 0, "Raw range(0-5000) segment StartTime (" + + avContent.getStartTime().toMillis() + " ms) should be >= 0 ms"); + assertTrue(avContent.getEndTime().toMillis() <= 5000, "Raw range(0-5000) segment EndTime (" + + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); } // The raw string "0-5000" should produce identical results to TimeRange(0, 5s) assertEquals(rangeResult.getContents().size(), rawVideoResult.getContents().size(), @@ -567,6 +584,8 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { assertTrue(fullPhraseCount >= rangePhraseCount); long rangeDurationMs = rangeAudioContent.getEndTime().toMillis() - rangeAudioContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= rangeDurationMs); + assertTrue(rangeAudioContent.getStartTime().toMillis() >= 5000, "TimeRangeFrom(5s) audio StartTime (" + + rangeAudioContent.getStartTime().toMillis() + " ms) should be >= 5000 ms"); // END:Assertion_ContentUnderstandingAnalyzeAudioUrlWithTimeContentRanges // ---- TimeRange(2s, 8s) — specific time window ---- @@ -581,6 +600,10 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { assertTrue(audioWindowContent.getEndTime().toMillis() > audioWindowContent.getStartTime().toMillis()); assertTrue(audioWindowContent.getMarkdown().length() > 0); + assertTrue(audioWindowContent.getStartTime().toMillis() >= 2000, "Range(2s-8s) audio StartTime (" + + audioWindowContent.getStartTime().toMillis() + " ms) should be >= 2000 ms"); + assertTrue(audioWindowContent.getEndTime().toMillis() <= 8000, + "Range(2s-8s) audio EndTime (" + audioWindowContent.getEndTime().toMillis() + " ms) should be <= 8000 ms"); long windowDurationMs = audioWindowContent.getEndTime().toMillis() - audioWindowContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= windowDurationMs); @@ -597,6 +620,10 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { assertTrue(audioSubSecondContent.getEndTime().toMillis() > audioSubSecondContent.getStartTime().toMillis()); assertTrue(audioSubSecondContent.getMarkdown().length() > 0); + assertTrue(audioSubSecondContent.getStartTime().toMillis() >= 1200, "Range(1200ms-3651ms) audio StartTime (" + + audioSubSecondContent.getStartTime().toMillis() + " ms) should be >= 1200 ms"); + assertTrue(audioSubSecondContent.getEndTime().toMillis() <= 3651, "Range(1200ms-3651ms) audio EndTime (" + + audioSubSecondContent.getEndTime().toMillis() + " ms) should be <= 3651 ms"); long subSecondDurationMs = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= subSecondDurationMs); From 47702f583db2d605d11acda0e8f5a31e1830f265 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Thu, 19 Mar 2026 15:40:33 +0800 Subject: [PATCH 07/17] Add raw ContentRange examples and tests for combined page ranges in binary analysis --- .../samples/Sample01_AnalyzeBinary.java | 69 +++++---- .../samples/Sample01_AnalyzeBinaryAsync.java | 128 +++++++++++++---- .../Sample01_AnalyzeBinaryAsyncTest.java | 131 +++++++++++------- .../samples/Sample01_AnalyzeBinaryTest.java | 73 +++++++--- 4 files changed, 276 insertions(+), 125 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java index 92e63d08c6e8..79151eeab19b 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java @@ -157,6 +157,19 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward + SyncPoller bigCombineOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.combine( + ContentRange.pages(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9)), + "application/octet-stream", null); + DocumentContent bigCombineDoc + = (DocumentContent) bigCombineOperation.getFinalResult().getContents().get(0); + System.out.println( + "Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + bigCombineDoc.getPages().size() + " pages"); + // Analyze a single page using ContentRange.page() SyncPoller pageOperation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, @@ -184,18 +197,26 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); - // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward - SyncPoller bigCombineOperation + // Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) + SyncPoller rawPagesFrom3Operation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.combine( - ContentRange.pages(1, 3), - ContentRange.page(5), - ContentRange.pagesFrom(9)), - "application/octet-stream", null); - DocumentContent bigCombineDoc - = (DocumentContent) bigCombineOperation.getFinalResult().getContents().get(0); - System.out.println( - "Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + bigCombineDoc.getPages().size() + " pages"); + new ContentRange("3-"), "application/octet-stream", null); + DocumentContent rawPagesFrom3Doc + = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " + + rawPagesFrom3Doc.getMarkdown().length() + " chars"); + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithRawContentRange + // Analyze pages 1-3, page 5, and pages 9 onward using a raw range string. + // This is equivalent to: ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)) + SyncPoller rawRangeOperation + = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("1-3,5,9-"), "application/octet-stream", null); + DocumentContent rawRangeDoc + = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " + + rawRangeDoc.getMarkdown().length() + " chars"); + // END:ContentUnderstandingAnalyzeBinaryWithRawContentRange // Raw string "2" — single page, equivalent to ContentRange.page(2) SyncPoller rawPage2Operation @@ -215,26 +236,14 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " + rawPages13Doc.getMarkdown().length() + " chars"); - // Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) - SyncPoller rawPagesFrom3Operation + // Raw string "1,3-4" — combined page ranges, equivalent to ContentRange.combine(page(1), pages(3, 4)) + SyncPoller rawCombineOperation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("3-"), "application/octet-stream", null); - DocumentContent rawPagesFrom3Doc - = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " - + rawPagesFrom3Doc.getMarkdown().length() + " chars"); - - // BEGIN:ContentUnderstandingAnalyzeBinaryWithRawContentRange - // Analyze pages 1-3, page 5, and pages 9 onward using a raw range string. - // This is equivalent to: ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)) - SyncPoller rawRangeOperation - = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1-3,5,9-"), "application/octet-stream", null); - DocumentContent rawRangeDoc - = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " - + rawRangeDoc.getMarkdown().length() + " chars"); - // END:ContentUnderstandingAnalyzeBinaryWithRawContentRange + new ContentRange("1,3-4"), "application/octet-stream", null); + DocumentContent rawCombineDoc + = (DocumentContent) rawCombineOperation.getFinalResult().getContents().get(0); + System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + " pages, " + + rawCombineDoc.getMarkdown().length() + " chars"); // END:ContentUnderstandingAnalyzeBinaryWithContentRange System.out.println("ContentRange binary analysis completed successfully"); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java index 8d831ebcc1ce..7346685c49fc 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java @@ -204,6 +204,29 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); }); + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward + Mono bigCombineMono = client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + ContentRange.combine( + ContentRange.pages(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9)), + "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent bigCombineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + + bigCombineDoc.getPages().size() + " pages"); + }); + // Analyze a single page using ContentRange.page() Mono pageMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, @@ -264,35 +287,32 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); }); - // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward - Mono bigCombineMono = client - .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.combine( - ContentRange.pages(1, 3), - ContentRange.page(5), - ContentRange.pagesFrom(9)), - "application/octet-stream", null) - .last() - .flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error(new RuntimeException( - "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }) - .doOnNext(result -> { - DocumentContent bigCombineDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " - + bigCombineDoc.getPages().size() + " pages"); - }); - // Chain all operations sequentially using then() pagesFromMono + .then(bigCombineMono) .then(pageMono) .then(pagesMono) .then(combineMono) - .then(bigCombineMono) + .then(Mono.defer(() -> { + // Raw string "3-" — equivalent to ContentRange.pagesFrom(3) + return client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("3-"), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent rawPagesFrom3Doc = (DocumentContent) result.getContents().get(0); + System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + + " pages, " + rawPagesFrom3Doc.getMarkdown().length() + " chars"); + }); + })) .then(Mono.defer(() -> { // Raw string "1-3,5,9-" — equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) return client @@ -313,6 +333,66 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient + " pages, " + rawRangeDoc.getMarkdown().length() + " chars"); }); })) + .then(Mono.defer(() -> { + // Raw string "2" — equivalent to ContentRange.page(2) + return client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("2"), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent rawPage2Doc = (DocumentContent) result.getContents().get(0); + System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + + " page, " + rawPage2Doc.getMarkdown().length() + " chars"); + }); + })) + .then(Mono.defer(() -> { + // Raw string "1-3" — equivalent to ContentRange.pages(1, 3) + return client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("1-3"), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent rawPages13Doc = (DocumentContent) result.getContents().get(0); + System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + + " pages, " + rawPages13Doc.getMarkdown().length() + " chars"); + }); + })) + .then(Mono.defer(() -> { + // Raw string "1,3-4" — equivalent to ContentRange.combine(page(1), pages(3, 4)) + return client + .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, + new ContentRange("1,3-4"), "application/octet-stream", null) + .last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent rawCombineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + + " pages, " + rawCombineDoc.getMarkdown().length() + " chars"); + }); + })) .doOnError(error -> System.err.println("Error: " + error.getMessage())) .subscribe( result -> { diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java index 4c346a5b0dc1..bcd820763559 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java @@ -315,6 +315,34 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); + // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- + PollerFlux bigCombineOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), + "application/octet-stream", null); + AnalysisResult bigCombineResult = bigCombineOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent bigCombineDoc = (DocumentContent) bigCombineResult.getContents().get(0); + + assertNotNull(bigCombineResult); + assertNotNull(bigCombineResult.getContents()); + assertEquals(6, bigCombineDoc.getPages().size(), + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); + java.util.List combineRangePageNumbers = bigCombineDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); + assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); + // ---- Page(2) — single page ---- PollerFlux page2Operation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -380,12 +408,11 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertEquals(4, combineDoc.getEndPageNumber(), "Combine should end at page 4"); assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); - // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- - PollerFlux bigCombineOperation + // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- + PollerFlux rawPagesFrom3Operation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), - "application/octet-stream", null); - AnalysisResult bigCombineResult = bigCombineOperation.last().flatMap(pollResponse -> { + new ContentRange("3-"), "application/octet-stream", null); + AnalysisResult rawPagesFrom3Result = rawPagesFrom3Operation.last().flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { return pollResponse.getFinalResult(); } else { @@ -393,20 +420,32 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); - DocumentContent bigCombineDoc = (DocumentContent) bigCombineResult.getContents().get(0); + DocumentContent rawPagesFrom3Doc = (DocumentContent) rawPagesFrom3Result.getContents().get(0); + assertEquals(8, rawPagesFrom3Doc.getPages().size(), + "Raw ContentRange('3-') should return 8 pages (pages 3-10)"); + assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); + assertEquals(10, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 10"); + assertEquals(rangeDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), + "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); - assertNotNull(bigCombineResult); - assertNotNull(bigCombineResult.getContents()); - assertEquals(6, bigCombineDoc.getPages().size(), - "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); - java.util.List combineRangePageNumbers = bigCombineDoc.getPages() - .stream() - .map(p -> p.getPageNumber()) - .sorted() - .collect(java.util.stream.Collectors.toList()); - assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, - "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); - assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); + // ---- Raw string "1-3,5,9-" — combine, equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) ---- + PollerFlux rawRangeOperation + = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1-3,5,9-"), "application/octet-stream", null); + AnalysisResult rawRangeResult = rawRangeOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + DocumentContent rawRangeDoc = (DocumentContent) rawRangeResult.getContents().get(0); + assertEquals(6, rawRangeDoc.getPages().size(), "Raw ContentRange('1-3,5,9-') should return exactly 6 pages"); + assertEquals(bigCombineDoc.getPages().size(), rawRangeDoc.getPages().size(), + "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); + assertEquals(bigCombineDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), + "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- PollerFlux rawPage2Operation @@ -446,11 +485,11 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); - // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- - PollerFlux rawPagesFrom3Operation + // ---- Raw string "1,3-4" — combined page ranges, equivalent to ContentRange.combine(page(1), pages(3, 4)) ---- + PollerFlux rawCombineOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("3-"), "application/octet-stream", null); - AnalysisResult rawPagesFrom3Result = rawPagesFrom3Operation.last().flatMap(pollResponse -> { + new ContentRange("1,3-4"), "application/octet-stream", null); + AnalysisResult rawCombineResult = rawCombineOperation.last().flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { return pollResponse.getFinalResult(); } else { @@ -458,33 +497,29 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); - DocumentContent rawPagesFrom3Doc = (DocumentContent) rawPagesFrom3Result.getContents().get(0); - assertEquals(8, rawPagesFrom3Doc.getPages().size(), - "Raw ContentRange('3-') should return 8 pages (pages 3-10)"); - assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); - assertEquals(10, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 10"); - assertEquals(rangeDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), - "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); - - // ---- Raw string "1-3,5,9-" — combine, equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) ---- - PollerFlux rawRangeOperation - = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1-3,5,9-"), "application/octet-stream", null); - AnalysisResult rawRangeResult = rawRangeOperation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - DocumentContent rawRangeDoc = (DocumentContent) rawRangeResult.getContents().get(0); - assertTrue(rawRangeDoc.getPages().size() > 0, "Raw ContentRange should return at least one page"); - assertEquals(bigCombineDoc.getPages().size(), rawRangeDoc.getPages().size(), - "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); - assertEquals(bigCombineDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), - "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); + DocumentContent rawCombineDoc = (DocumentContent) rawCombineResult.getContents().get(0); + assertEquals(3, rawCombineDoc.getPages().size(), "Raw ContentRange('1,3-4') should return exactly 3 pages"); + java.util.List rawCombinePageNumbers = rawCombineDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 3, 4), rawCombinePageNumbers, + "Raw ContentRange('1,3-4') should extract pages 1, 3, 4"); + assertEquals(combineDoc.getPages().size(), rawCombineDoc.getPages().size(), + "Raw ContentRange('1,3-4') should return same page count as Combine equivalent"); + assertEquals(combineDoc.getMarkdown().length(), rawCombineDoc.getMarkdown().length(), + "Raw ContentRange('1,3-4') should return same markdown length as Combine equivalent"); + + System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " + + rawPagesFrom3Doc.getMarkdown().length() + " chars"); System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " + rawRangeDoc.getMarkdown().length() + " chars"); + System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + " page, " + + rawPage2Doc.getMarkdown().length() + " chars"); + System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " + + rawPages13Doc.getMarkdown().length() + " chars"); + System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + " pages, " + + rawCombineDoc.getMarkdown().length() + " chars"); } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java index fe18467d11c7..42435cf9d90f 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java @@ -377,28 +377,6 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange - // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- - SyncPoller rawPage2Operation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("2"), "application/octet-stream", null); - DocumentContent rawPage2Doc = (DocumentContent) rawPage2Operation.getFinalResult().getContents().get(0); - assertEquals(1, rawPage2Doc.getPages().size(), "Raw ContentRange('2') should return exactly 1 page"); - assertEquals(2, rawPage2Doc.getStartPageNumber(), "Raw ContentRange('2') should start at page 2"); - assertEquals(2, rawPage2Doc.getEndPageNumber(), "Raw ContentRange('2') should end at page 2"); - assertEquals(page2Doc.getMarkdown().length(), rawPage2Doc.getMarkdown().length(), - "Raw ContentRange('2') should return same markdown length as Page(2)"); - - // ---- Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) ---- - SyncPoller rawPages13Operation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1-3"), "application/octet-stream", null); - DocumentContent rawPages13Doc = (DocumentContent) rawPages13Operation.getFinalResult().getContents().get(0); - assertEquals(3, rawPages13Doc.getPages().size(), "Raw ContentRange('1-3') should return exactly 3 pages"); - assertEquals(1, rawPages13Doc.getStartPageNumber(), "Raw ContentRange('1-3') should start at page 1"); - assertEquals(3, rawPages13Doc.getEndPageNumber(), "Raw ContentRange('1-3') should end at page 3"); - assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), - "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); - // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- SyncPoller rawPagesFrom3Operation = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -418,12 +396,61 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, new ContentRange("1-3,5,9-"), "application/octet-stream", null); DocumentContent rawRangeDoc = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); - assertTrue(rawRangeDoc.getPages().size() > 0, "Raw ContentRange should return at least one page"); + assertEquals(6, rawRangeDoc.getPages().size(), "Raw ContentRange('1-3,5,9-') should return exactly 6 pages"); assertEquals(combineRangeDoc.getPages().size(), rawRangeDoc.getPages().size(), "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); assertEquals(combineRangeDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); + + // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- + SyncPoller rawPage2Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("2"), "application/octet-stream", null); + DocumentContent rawPage2Doc = (DocumentContent) rawPage2Operation.getFinalResult().getContents().get(0); + assertEquals(1, rawPage2Doc.getPages().size(), "Raw ContentRange('2') should return exactly 1 page"); + assertEquals(2, rawPage2Doc.getStartPageNumber(), "Raw ContentRange('2') should start at page 2"); + assertEquals(2, rawPage2Doc.getEndPageNumber(), "Raw ContentRange('2') should end at page 2"); + assertEquals(page2Doc.getMarkdown().length(), rawPage2Doc.getMarkdown().length(), + "Raw ContentRange('2') should return same markdown length as Page(2)"); + + // ---- Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) ---- + SyncPoller rawPages13Operation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1-3"), "application/octet-stream", null); + DocumentContent rawPages13Doc = (DocumentContent) rawPages13Operation.getFinalResult().getContents().get(0); + assertEquals(3, rawPages13Doc.getPages().size(), "Raw ContentRange('1-3') should return exactly 3 pages"); + assertEquals(1, rawPages13Doc.getStartPageNumber(), "Raw ContentRange('1-3') should start at page 1"); + assertEquals(3, rawPages13Doc.getEndPageNumber(), "Raw ContentRange('1-3') should end at page 3"); + assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), + "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); + + // ---- Raw string "1,3-4" — combined page ranges, equivalent to ContentRange.combine(page(1), pages(3, 4)) ---- + SyncPoller rawCombineOperation + = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, + new ContentRange("1,3-4"), "application/octet-stream", null); + DocumentContent rawCombineDoc = (DocumentContent) rawCombineOperation.getFinalResult().getContents().get(0); + assertEquals(3, rawCombineDoc.getPages().size(), "Raw ContentRange('1,3-4') should return exactly 3 pages"); + java.util.List rawCombinePageNumbers = rawCombineDoc.getPages() + .stream() + .map(p -> p.getPageNumber()) + .sorted() + .collect(java.util.stream.Collectors.toList()); + assertEquals(java.util.Arrays.asList(1, 3, 4), rawCombinePageNumbers, + "Raw ContentRange('1,3-4') should extract pages 1, 3, 4"); + assertEquals(combineDoc.getPages().size(), rawCombineDoc.getPages().size(), + "Raw ContentRange('1,3-4') should return same page count as Combine equivalent"); + assertEquals(combineDoc.getMarkdown().length(), rawCombineDoc.getMarkdown().length(), + "Raw ContentRange('1,3-4') should return same markdown length as Combine equivalent"); + + System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " + + rawPagesFrom3Doc.getMarkdown().length() + " chars"); System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " + rawRangeDoc.getMarkdown().length() + " chars"); + System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + " page, " + + rawPage2Doc.getMarkdown().length() + " chars"); + System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " + + rawPages13Doc.getMarkdown().length() + " chars"); + System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + " pages, " + + rawCombineDoc.getMarkdown().length() + " chars"); } } From ae27c820044aafd69c7eb9d4758eaa4ee6a07549 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Tue, 24 Mar 2026 14:21:20 +0800 Subject: [PATCH 08/17] Refactor Content Understanding Samples and Tests for Binary Analysis - Updated Sample01_AnalyzeBinary and Sample01_AnalyzeBinaryAsync to streamline the analysis of binary documents using ContentRange. - Removed redundant operations and consolidated logic for analyzing specific page ranges. - Enhanced test cases in Sample01_AnalyzeBinaryTest and Sample01_AnalyzeBinaryAsyncTest to reflect changes in the sample implementations. - Ensured that assertions accurately validate the expected outcomes for page analyses and combined ranges. --- .../samples/Sample01_AnalyzeBinary.java | 88 ++------- .../samples/Sample01_AnalyzeBinaryAsync.java | 176 ++++-------------- .../Sample01_AnalyzeBinaryAsyncTest.java | 172 +++-------------- .../samples/Sample01_AnalyzeBinaryTest.java | 158 ++++------------ 4 files changed, 128 insertions(+), 466 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java index 79151eeab19b..6eb859da1856 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinary.java @@ -147,29 +147,6 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie BinaryData multiPageData = BinaryData.fromBytes(multiPageBytes); // BEGIN:ContentUnderstandingAnalyzeBinaryWithContentRange - // Analyze only pages 3 to end using ContentRange.pagesFrom() - SyncPoller rangeOperation - = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.pagesFrom(3), "application/octet-stream", null); - AnalysisResult rangeResult = rangeOperation.getFinalResult(); - - DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); - System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" - + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); - - // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward - SyncPoller bigCombineOperation - = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.combine( - ContentRange.pages(1, 3), - ContentRange.page(5), - ContentRange.pagesFrom(9)), - "application/octet-stream", null); - DocumentContent bigCombineDoc - = (DocumentContent) bigCombineOperation.getFinalResult().getContents().get(0); - System.out.println( - "Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + bigCombineDoc.getPages().size() + " pages"); - // Analyze a single page using ContentRange.page() SyncPoller pageOperation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, @@ -197,53 +174,28 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingClient clie System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); - // Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) - SyncPoller rawPagesFrom3Operation - = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("3-"), "application/octet-stream", null); - DocumentContent rawPagesFrom3Doc - = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " - + rawPagesFrom3Doc.getMarkdown().length() + " chars"); - - // BEGIN:ContentUnderstandingAnalyzeBinaryWithRawContentRange - // Analyze pages 1-3, page 5, and pages 9 onward using a raw range string. - // This is equivalent to: ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)) - SyncPoller rawRangeOperation - = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1-3,5,9-"), "application/octet-stream", null); - DocumentContent rawRangeDoc - = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " - + rawRangeDoc.getMarkdown().length() + " chars"); - // END:ContentUnderstandingAnalyzeBinaryWithRawContentRange - - // Raw string "2" — single page, equivalent to ContentRange.page(2) - SyncPoller rawPage2Operation - = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("2"), "application/octet-stream", null); - DocumentContent rawPage2Doc - = (DocumentContent) rawPage2Operation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + " page, " - + rawPage2Doc.getMarkdown().length() + " chars"); - - // Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) - SyncPoller rawPages13Operation + // Analyze only pages 3 to end using ContentRange.pagesFrom() + SyncPoller rangeOperation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1-3"), "application/octet-stream", null); - DocumentContent rawPages13Doc - = (DocumentContent) rawPages13Operation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " - + rawPages13Doc.getMarkdown().length() + " chars"); - - // Raw string "1,3-4" — combined page ranges, equivalent to ContentRange.combine(page(1), pages(3, 4)) - SyncPoller rawCombineOperation + ContentRange.pagesFrom(3), "application/octet-stream", null); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" + + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); + + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward + SyncPoller bigCombineOperation = client.beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1,3-4"), "application/octet-stream", null); - DocumentContent rawCombineDoc - = (DocumentContent) rawCombineOperation.getFinalResult().getContents().get(0); - System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + " pages, " - + rawCombineDoc.getMarkdown().length() + " chars"); + ContentRange.combine( + ContentRange.pages(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9)), + "application/octet-stream", null); + DocumentContent bigCombineDoc + = (DocumentContent) bigCombineOperation.getFinalResult().getContents().get(0); + System.out.println( + "Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + bigCombineDoc.getPages().size() + " pages"); // END:ContentUnderstandingAnalyzeBinaryWithContentRange System.out.println("ContentRange binary analysis completed successfully"); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java index 7346685c49fc..71b3d47122bd 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample01_AnalyzeBinaryAsync.java @@ -185,10 +185,10 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient CountDownLatch rangeLatch = new CountDownLatch(1); // BEGIN:ContentUnderstandingAnalyzeBinaryWithContentRangeAsync - // Analyze only pages 3 to end using ContentRange.pagesFrom() - Mono pagesFromMono = client + // Analyze a single page using ContentRange.page() + Mono pageMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.pagesFrom(3), "application/octet-stream", null) + ContentRange.page(2), "application/octet-stream", null) .last() .flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { @@ -199,19 +199,15 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient } }) .doOnNext(result -> { - DocumentContent rangeDoc = (DocumentContent) result.getContents().get(0); - System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" - + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); + DocumentContent pageDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Page(2): returned " + pageDoc.getPages().size() + " page" + + " (page " + pageDoc.getStartPageNumber() + ")"); }); - // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward - Mono bigCombineMono = client + // Analyze a page range using ContentRange.pages() + Mono pagesMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.combine( - ContentRange.pages(1, 3), - ContentRange.page(5), - ContentRange.pagesFrom(9)), - "application/octet-stream", null) + ContentRange.pages(1, 3), "application/octet-stream", null) .last() .flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { @@ -222,15 +218,18 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient } }) .doOnNext(result -> { - DocumentContent bigCombineDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " - + bigCombineDoc.getPages().size() + " pages"); + DocumentContent pagesDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Pages(1,3): returned " + pagesDoc.getPages().size() + " pages" + + " (pages " + pagesDoc.getStartPageNumber() + "-" + pagesDoc.getEndPageNumber() + ")"); }); - // Analyze a single page using ContentRange.page() - Mono pageMono = client + // Combine multiple ranges using ContentRange.combine() + Mono combineMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.page(2), "application/octet-stream", null) + ContentRange.combine( + ContentRange.page(1), + ContentRange.pages(3, 4)), + "application/octet-stream", null) .last() .flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { @@ -241,15 +240,15 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient } }) .doOnNext(result -> { - DocumentContent pageDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Page(2): returned " + pageDoc.getPages().size() + " page" - + " (page " + pageDoc.getStartPageNumber() + ")"); + DocumentContent combineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" + + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); }); - // Analyze a page range using ContentRange.pages() - Mono pagesMono = client + // Analyze only pages 3 to end using ContentRange.pagesFrom() + Mono pagesFromMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - ContentRange.pages(1, 3), "application/octet-stream", null) + ContentRange.pagesFrom(3), "application/octet-stream", null) .last() .flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { @@ -260,17 +259,18 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient } }) .doOnNext(result -> { - DocumentContent pagesDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Pages(1,3): returned " + pagesDoc.getPages().size() + " pages" - + " (pages " + pagesDoc.getStartPageNumber() + "-" + pagesDoc.getEndPageNumber() + ")"); + DocumentContent rangeDoc = (DocumentContent) result.getContents().get(0); + System.out.println("PagesFrom(3): returned " + rangeDoc.getPages().size() + " pages" + + " (pages " + rangeDoc.getStartPageNumber() + "-" + rangeDoc.getEndPageNumber() + ")"); }); - // Combine multiple ranges using ContentRange.combine() - Mono combineMono = client + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward + Mono bigCombineMono = client .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, ContentRange.combine( - ContentRange.page(1), - ContentRange.pages(3, 4)), + ContentRange.pages(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9)), "application/octet-stream", null) .last() .flatMap(pollResponse -> { @@ -282,117 +282,17 @@ public static void analyzeBinaryWithContentRange(ContentUnderstandingAsyncClient } }) .doOnNext(result -> { - DocumentContent combineDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Combine(Page(1), Pages(3,4)): returned " + combineDoc.getPages().size() + " pages" - + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); + DocumentContent bigCombineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Combine(Pages(1,3), Page(5), PagesFrom(9)): returned " + + bigCombineDoc.getPages().size() + " pages"); }); // Chain all operations sequentially using then() - pagesFromMono - .then(bigCombineMono) - .then(pageMono) + pageMono .then(pagesMono) .then(combineMono) - .then(Mono.defer(() -> { - // Raw string "3-" — equivalent to ContentRange.pagesFrom(3) - return client - .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("3-"), "application/octet-stream", null) - .last() - .flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error(new RuntimeException( - "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }) - .doOnNext(result -> { - DocumentContent rawPagesFrom3Doc = (DocumentContent) result.getContents().get(0); - System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() - + " pages, " + rawPagesFrom3Doc.getMarkdown().length() + " chars"); - }); - })) - .then(Mono.defer(() -> { - // Raw string "1-3,5,9-" — equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) - return client - .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1-3,5,9-"), "application/octet-stream", null) - .last() - .flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error(new RuntimeException( - "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }) - .doOnNext(result -> { - DocumentContent rawRangeDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() - + " pages, " + rawRangeDoc.getMarkdown().length() + " chars"); - }); - })) - .then(Mono.defer(() -> { - // Raw string "2" — equivalent to ContentRange.page(2) - return client - .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("2"), "application/octet-stream", null) - .last() - .flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error(new RuntimeException( - "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }) - .doOnNext(result -> { - DocumentContent rawPage2Doc = (DocumentContent) result.getContents().get(0); - System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() - + " page, " + rawPage2Doc.getMarkdown().length() + " chars"); - }); - })) - .then(Mono.defer(() -> { - // Raw string "1-3" — equivalent to ContentRange.pages(1, 3) - return client - .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1-3"), "application/octet-stream", null) - .last() - .flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error(new RuntimeException( - "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }) - .doOnNext(result -> { - DocumentContent rawPages13Doc = (DocumentContent) result.getContents().get(0); - System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() - + " pages, " + rawPages13Doc.getMarkdown().length() + " chars"); - }); - })) - .then(Mono.defer(() -> { - // Raw string "1,3-4" — equivalent to ContentRange.combine(page(1), pages(3, 4)) - return client - .beginAnalyzeBinary("prebuilt-documentSearch", multiPageData, - new ContentRange("1,3-4"), "application/octet-stream", null) - .last() - .flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error(new RuntimeException( - "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }) - .doOnNext(result -> { - DocumentContent rawCombineDoc = (DocumentContent) result.getContents().get(0); - System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() - + " pages, " + rawCombineDoc.getMarkdown().length() + " chars"); - }); - })) + .then(pagesFromMono) + .then(bigCombineMono) .doOnError(error -> System.err.println("Error: " + error.getMessage())) .subscribe( result -> { diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java index bcd820763559..b58c4b673e3b 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java @@ -293,56 +293,6 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); - // ---- PagesFrom(3) — extract pages 3 to end ---- - PollerFlux rangeOperation - = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - ContentRange.pagesFrom(3), "application/octet-stream", null); - AnalysisResult rangeResult = rangeOperation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - - assertNotNull(rangeResult); - assertNotNull(rangeResult.getContents()); - DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); - assertEquals(8, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 8 pages"); - assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); - assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); - assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); - assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); - - // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- - PollerFlux bigCombineOperation - = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), - "application/octet-stream", null); - AnalysisResult bigCombineResult = bigCombineOperation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - DocumentContent bigCombineDoc = (DocumentContent) bigCombineResult.getContents().get(0); - - assertNotNull(bigCombineResult); - assertNotNull(bigCombineResult.getContents()); - assertEquals(6, bigCombineDoc.getPages().size(), - "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); - java.util.List combineRangePageNumbers = bigCombineDoc.getPages() - .stream() - .map(p -> p.getPageNumber()) - .sorted() - .collect(java.util.stream.Collectors.toList()); - assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, - "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); - assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); - // ---- Page(2) — single page ---- PollerFlux page2Operation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -408,69 +358,11 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertEquals(4, combineDoc.getEndPageNumber(), "Combine should end at page 4"); assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); - // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- - PollerFlux rawPagesFrom3Operation - = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("3-"), "application/octet-stream", null); - AnalysisResult rawPagesFrom3Result = rawPagesFrom3Operation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - DocumentContent rawPagesFrom3Doc = (DocumentContent) rawPagesFrom3Result.getContents().get(0); - assertEquals(8, rawPagesFrom3Doc.getPages().size(), - "Raw ContentRange('3-') should return 8 pages (pages 3-10)"); - assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); - assertEquals(10, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 10"); - assertEquals(rangeDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), - "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); - - // ---- Raw string "1-3,5,9-" — combine, equivalent to Combine(Pages(1,3), Page(5), PagesFrom(9)) ---- - PollerFlux rawRangeOperation - = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1-3,5,9-"), "application/octet-stream", null); - AnalysisResult rawRangeResult = rawRangeOperation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - DocumentContent rawRangeDoc = (DocumentContent) rawRangeResult.getContents().get(0); - assertEquals(6, rawRangeDoc.getPages().size(), "Raw ContentRange('1-3,5,9-') should return exactly 6 pages"); - assertEquals(bigCombineDoc.getPages().size(), rawRangeDoc.getPages().size(), - "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); - assertEquals(bigCombineDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), - "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); - - // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- - PollerFlux rawPage2Operation - = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("2"), "application/octet-stream", null); - AnalysisResult rawPage2Result = rawPage2Operation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - DocumentContent rawPage2Doc = (DocumentContent) rawPage2Result.getContents().get(0); - assertEquals(1, rawPage2Doc.getPages().size(), "Raw ContentRange('2') should return exactly 1 page"); - assertEquals(2, rawPage2Doc.getStartPageNumber(), "Raw ContentRange('2') should start at page 2"); - assertEquals(2, rawPage2Doc.getEndPageNumber(), "Raw ContentRange('2') should end at page 2"); - assertEquals(page2Doc.getMarkdown().length(), rawPage2Doc.getMarkdown().length(), - "Raw ContentRange('2') should return same markdown length as Page(2)"); - - // ---- Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) ---- - PollerFlux rawPages13Operation + // ---- PagesFrom(3) — extract pages 3 to end ---- + PollerFlux rangeOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1-3"), "application/octet-stream", null); - AnalysisResult rawPages13Result = rawPages13Operation.last().flatMap(pollResponse -> { + ContentRange.pagesFrom(3), "application/octet-stream", null); + AnalysisResult rangeResult = rangeOperation.last().flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { return pollResponse.getFinalResult(); } else { @@ -478,18 +370,22 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); - DocumentContent rawPages13Doc = (DocumentContent) rawPages13Result.getContents().get(0); - assertEquals(3, rawPages13Doc.getPages().size(), "Raw ContentRange('1-3') should return exactly 3 pages"); - assertEquals(1, rawPages13Doc.getStartPageNumber(), "Raw ContentRange('1-3') should start at page 1"); - assertEquals(3, rawPages13Doc.getEndPageNumber(), "Raw ContentRange('1-3') should end at page 3"); - assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), - "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); - - // ---- Raw string "1,3-4" — combined page ranges, equivalent to ContentRange.combine(page(1), pages(3, 4)) ---- - PollerFlux rawCombineOperation + + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + assertEquals(8, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 8 pages"); + assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); + assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); + assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); + assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); + + // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- + PollerFlux bigCombineOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1,3-4"), "application/octet-stream", null); - AnalysisResult rawCombineResult = rawCombineOperation.last().flatMap(pollResponse -> { + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), + "application/octet-stream", null); + AnalysisResult bigCombineResult = bigCombineOperation.last().flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { return pollResponse.getFinalResult(); } else { @@ -497,29 +393,19 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); - DocumentContent rawCombineDoc = (DocumentContent) rawCombineResult.getContents().get(0); - assertEquals(3, rawCombineDoc.getPages().size(), "Raw ContentRange('1,3-4') should return exactly 3 pages"); - java.util.List rawCombinePageNumbers = rawCombineDoc.getPages() + DocumentContent bigCombineDoc = (DocumentContent) bigCombineResult.getContents().get(0); + + assertNotNull(bigCombineResult); + assertNotNull(bigCombineResult.getContents()); + assertEquals(6, bigCombineDoc.getPages().size(), + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); + java.util.List combineRangePageNumbers = bigCombineDoc.getPages() .stream() .map(p -> p.getPageNumber()) .sorted() .collect(java.util.stream.Collectors.toList()); - assertEquals(java.util.Arrays.asList(1, 3, 4), rawCombinePageNumbers, - "Raw ContentRange('1,3-4') should extract pages 1, 3, 4"); - assertEquals(combineDoc.getPages().size(), rawCombineDoc.getPages().size(), - "Raw ContentRange('1,3-4') should return same page count as Combine equivalent"); - assertEquals(combineDoc.getMarkdown().length(), rawCombineDoc.getMarkdown().length(), - "Raw ContentRange('1,3-4') should return same markdown length as Combine equivalent"); - - System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " - + rawPagesFrom3Doc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " - + rawRangeDoc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + " page, " - + rawPage2Doc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " - + rawPages13Doc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + " pages, " - + rawCombineDoc.getMarkdown().length() + " chars"); + assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); + assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java index 42435cf9d90f..d4a0a176e3d1 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java @@ -277,54 +277,6 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); - // BEGIN:ContentUnderstandingAnalyzeBinaryWithPagesFrom - // ---- PagesFrom(3) — extract pages 3 to end ---- - SyncPoller rangeOperation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - ContentRange.pagesFrom(3), "application/octet-stream", null); - AnalysisResult rangeResult = rangeOperation.getFinalResult(); - // END:ContentUnderstandingAnalyzeBinaryWithPagesFrom - - // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom - assertNotNull(rangeOperation); - assertTrue(rangeOperation.waitForCompletion().getStatus().isComplete()); - assertNotNull(rangeResult); - assertNotNull(rangeResult.getContents()); - DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); - assertEquals(8, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 8 pages"); - assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); - assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); - assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); - assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); - // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom - - // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPages - // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- - SyncPoller combineRangeOperation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), - "application/octet-stream", null); - AnalysisResult combineRangeResult = combineRangeOperation.getFinalResult(); - // END:ContentUnderstandingAnalyzeBinaryWithCombinedPages - - // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages - assertNotNull(combineRangeOperation); - assertTrue(combineRangeOperation.waitForCompletion().getStatus().isComplete()); - assertNotNull(combineRangeResult); - assertNotNull(combineRangeResult.getContents()); - DocumentContent combineRangeDoc = (DocumentContent) combineRangeResult.getContents().get(0); - assertEquals(6, combineRangeDoc.getPages().size(), - "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); - java.util.List combineRangePageNumbers = combineRangeDoc.getPages() - .stream() - .map(p -> p.getPageNumber()) - .sorted() - .collect(java.util.stream.Collectors.toList()); - assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, - "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); - assertTrue(fullDoc.getMarkdown().length() >= combineRangeDoc.getMarkdown().length()); - // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages - // BEGIN:ContentUnderstandingAnalyzeBinaryWithSinglePage // ---- Page(2) — single page ---- SyncPoller page2Operation @@ -377,80 +329,52 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange - // ---- Raw string "3-" — pages from, equivalent to ContentRange.pagesFrom(3) ---- - SyncPoller rawPagesFrom3Operation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("3-"), "application/octet-stream", null); - DocumentContent rawPagesFrom3Doc - = (DocumentContent) rawPagesFrom3Operation.getFinalResult().getContents().get(0); - assertEquals(8, rawPagesFrom3Doc.getPages().size(), - "Raw ContentRange('3-') should return 8 pages (pages 3-10)"); - assertEquals(3, rawPagesFrom3Doc.getStartPageNumber(), "Raw ContentRange('3-') should start at page 3"); - assertEquals(10, rawPagesFrom3Doc.getEndPageNumber(), "Raw ContentRange('3-') should end at page 10"); - DocumentContent rangeFromDoc = (DocumentContent) rangeOperation.getFinalResult().getContents().get(0); - assertEquals(rangeFromDoc.getMarkdown().length(), rawPagesFrom3Doc.getMarkdown().length(), - "Raw ContentRange('3-') should return same markdown length as PagesFrom(3)"); - - // ---- Raw string "1-3,5,9-" — combine, equivalent to ContentRange.combine(Pages(1,3), Page(5), PagesFrom(9)) ---- - SyncPoller rawRangeOperation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1-3,5,9-"), "application/octet-stream", null); - DocumentContent rawRangeDoc = (DocumentContent) rawRangeOperation.getFinalResult().getContents().get(0); - assertEquals(6, rawRangeDoc.getPages().size(), "Raw ContentRange('1-3,5,9-') should return exactly 6 pages"); - assertEquals(combineRangeDoc.getPages().size(), rawRangeDoc.getPages().size(), - "Raw ContentRange('1-3,5,9-') should return same page count as Combine equivalent"); - assertEquals(combineRangeDoc.getMarkdown().length(), rawRangeDoc.getMarkdown().length(), - "Raw ContentRange('1-3,5,9-') should return same markdown length as Combine equivalent"); - - // ---- Raw string "2" — single page, equivalent to ContentRange.page(2) ---- - SyncPoller rawPage2Operation - = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("2"), "application/octet-stream", null); - DocumentContent rawPage2Doc = (DocumentContent) rawPage2Operation.getFinalResult().getContents().get(0); - assertEquals(1, rawPage2Doc.getPages().size(), "Raw ContentRange('2') should return exactly 1 page"); - assertEquals(2, rawPage2Doc.getStartPageNumber(), "Raw ContentRange('2') should start at page 2"); - assertEquals(2, rawPage2Doc.getEndPageNumber(), "Raw ContentRange('2') should end at page 2"); - assertEquals(page2Doc.getMarkdown().length(), rawPage2Doc.getMarkdown().length(), - "Raw ContentRange('2') should return same markdown length as Page(2)"); - - // ---- Raw string "1-3" — page range, equivalent to ContentRange.pages(1, 3) ---- - SyncPoller rawPages13Operation + // BEGIN:ContentUnderstandingAnalyzeBinaryWithPagesFrom + // ---- PagesFrom(3) — extract pages 3 to end ---- + SyncPoller rangeOperation = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1-3"), "application/octet-stream", null); - DocumentContent rawPages13Doc = (DocumentContent) rawPages13Operation.getFinalResult().getContents().get(0); - assertEquals(3, rawPages13Doc.getPages().size(), "Raw ContentRange('1-3') should return exactly 3 pages"); - assertEquals(1, rawPages13Doc.getStartPageNumber(), "Raw ContentRange('1-3') should start at page 1"); - assertEquals(3, rawPages13Doc.getEndPageNumber(), "Raw ContentRange('1-3') should end at page 3"); - assertEquals(pages13Doc.getMarkdown().length(), rawPages13Doc.getMarkdown().length(), - "Raw ContentRange('1-3') should return same markdown length as Pages(1,3)"); - - // ---- Raw string "1,3-4" — combined page ranges, equivalent to ContentRange.combine(page(1), pages(3, 4)) ---- - SyncPoller rawCombineOperation + ContentRange.pagesFrom(3), "application/octet-stream", null); + AnalysisResult rangeResult = rangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeBinaryWithPagesFrom + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom + assertNotNull(rangeOperation); + assertTrue(rangeOperation.waitForCompletion().getStatus().isComplete()); + assertNotNull(rangeResult); + assertNotNull(rangeResult.getContents()); + DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); + assertEquals(8, rangeDoc.getPages().size(), "With ContentRange.pagesFrom(3), should return only 8 pages"); + assertEquals(3, rangeDoc.getStartPageNumber(), "pagesFrom(3) should start at page 3"); + assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); + assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); + assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFrom + + // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPages + // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- + SyncPoller combineRangeOperation = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, - new ContentRange("1,3-4"), "application/octet-stream", null); - DocumentContent rawCombineDoc = (DocumentContent) rawCombineOperation.getFinalResult().getContents().get(0); - assertEquals(3, rawCombineDoc.getPages().size(), "Raw ContentRange('1,3-4') should return exactly 3 pages"); - java.util.List rawCombinePageNumbers = rawCombineDoc.getPages() + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9)), + "application/octet-stream", null); + AnalysisResult combineRangeResult = combineRangeOperation.getFinalResult(); + // END:ContentUnderstandingAnalyzeBinaryWithCombinedPages + + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages + assertNotNull(combineRangeOperation); + assertTrue(combineRangeOperation.waitForCompletion().getStatus().isComplete()); + assertNotNull(combineRangeResult); + assertNotNull(combineRangeResult.getContents()); + DocumentContent combineRangeDoc = (DocumentContent) combineRangeResult.getContents().get(0); + assertEquals(6, combineRangeDoc.getPages().size(), + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should return exactly 6 pages"); + java.util.List combineRangePageNumbers = combineRangeDoc.getPages() .stream() .map(p -> p.getPageNumber()) .sorted() .collect(java.util.stream.Collectors.toList()); - assertEquals(java.util.Arrays.asList(1, 3, 4), rawCombinePageNumbers, - "Raw ContentRange('1,3-4') should extract pages 1, 3, 4"); - assertEquals(combineDoc.getPages().size(), rawCombineDoc.getPages().size(), - "Raw ContentRange('1,3-4') should return same page count as Combine equivalent"); - assertEquals(combineDoc.getMarkdown().length(), rawCombineDoc.getMarkdown().length(), - "Raw ContentRange('1,3-4') should return same markdown length as Combine equivalent"); - - System.out.println("Raw ContentRange('3-'): " + rawPagesFrom3Doc.getPages().size() + " pages, " - + rawPagesFrom3Doc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('1-3,5,9-'): " + rawRangeDoc.getPages().size() + " pages, " - + rawRangeDoc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('2'): " + rawPage2Doc.getPages().size() + " page, " - + rawPage2Doc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('1-3'): " + rawPages13Doc.getPages().size() + " pages, " - + rawPages13Doc.getMarkdown().length() + " chars"); - System.out.println("Raw ContentRange('1,3-4'): " + rawCombineDoc.getPages().size() + " pages, " - + rawCombineDoc.getMarkdown().length() + " chars"); + assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, + "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); + assertTrue(fullDoc.getMarkdown().length() >= combineRangeDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPages } } From f78318450fc3ccde7718c3d44378d18b0748efcf Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Tue, 24 Mar 2026 14:36:28 +0800 Subject: [PATCH 09/17] Add @LiveOnly annotation to audio/video URL analysis tests --- .../tests/samples/Sample02_AnalyzeUrlAsyncTest.java | 3 +++ .../tests/samples/Sample02_AnalyzeUrlTest.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index d86364d44054..c02e86a37132 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -15,6 +15,7 @@ import com.azure.ai.contentunderstanding.models.DocumentTableCell; import com.azure.ai.contentunderstanding.models.AnalysisContent; import com.azure.ai.contentunderstanding.models.TranscriptPhrase; +import com.azure.core.test.annotation.LiveOnly; import com.azure.core.util.polling.PollerFlux; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; @@ -491,6 +492,7 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); } + @LiveOnly @Test public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { @@ -667,6 +669,7 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { System.out.println("Raw ContentRange('0-5000'): " + rawVideoResult.getContents().size() + " segment(s)"); } + @LiveOnly @Test public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index 673aee696e85..e7d2228fad17 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -15,6 +15,7 @@ import com.azure.ai.contentunderstanding.models.DocumentTableCell; import com.azure.ai.contentunderstanding.models.AnalysisContent; import com.azure.ai.contentunderstanding.models.TranscriptPhrase; +import com.azure.core.test.annotation.LiveOnly; import com.azure.core.util.polling.SyncPoller; import org.junit.jupiter.api.Test; @@ -406,6 +407,7 @@ public void testAnalyzeUrlWithPageContentRanges() { // END:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRanges } + @LiveOnly @Test public void testAnalyzeVideoUrlWithTimeContentRanges() { // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithTimeContentRanges @@ -544,6 +546,7 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { System.out.println("Raw ContentRange('0-5000'): " + rawVideoResult.getContents().size() + " segment(s)"); } + @LiveOnly @Test public void testAnalyzeAudioUrlWithTimeContentRanges() { // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithTimeContentRanges From 1eb5247d653905342e7e4c3bd59f62381606ddc1 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Tue, 24 Mar 2026 16:21:36 +0800 Subject: [PATCH 10/17] Add ContentRange examples and tests for combined page ranges in document analysis --- .../samples/Sample02_AnalyzeUrl.java | 19 +++++++- .../samples/Sample02_AnalyzeUrlAsync.java | 47 ++++++++++++++++++- .../samples/Sample02_AnalyzeUrlAsyncTest.java | 37 ++++++++++++++- .../samples/Sample02_AnalyzeUrlTest.java | 30 +++++++++++- 4 files changed, 128 insertions(+), 5 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java index 41b021796817..babbf6cf2858 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java @@ -299,7 +299,7 @@ public static void analyzeImageUrl(ContentUnderstandingClient client) { public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingClient client) { // BEGIN:ContentUnderstandingAnalyzeUrlWithContentRange String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; // Extract only page 1 using ContentRange AnalysisInput rangeInput = new AnalysisInput(); @@ -314,6 +314,23 @@ public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingClient System.out.println("Page(1): returned " + rangeDoc.getPages().size() + " page" + " (page " + rangeDoc.getStartPageNumber() + ")"); System.out.println("Markdown length: " + rangeDoc.getMarkdown().length() + " characters"); + + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.pageRange(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9))); + + SyncPoller combineOperation + = client.beginAnalyze("prebuilt-documentSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.getFinalResult(); + + DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); + System.out.println("Combine(1-3, 5, 9-): returned " + combineDoc.getPages().size() + " pages" + + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); + System.out.println("Markdown length: " + combineDoc.getMarkdown().length() + " characters"); // END:ContentUnderstandingAnalyzeUrlWithContentRange } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 193d6abb52fb..73b27db5fad8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -434,7 +434,7 @@ public static void analyzeImageUrl(ContentUnderstandingAsyncClient client) { public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncClient client) { // BEGIN:ContentUnderstandingAnalyzeDocumentUrlWithContentRangeAsync String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; // Analyze only page 1 using ContentRange AnalysisInput input = new AnalysisInput(); @@ -465,7 +465,7 @@ public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncC System.err.println("Error occurred: " + error.getMessage()); }) .subscribe( - result -> latch.countDown(), + result -> { }, error -> latch.countDown() ); @@ -475,6 +475,49 @@ public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncC Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for document analysis", e); } + + // Combine multiple page ranges: pages 1-3, page 5, and pages 9 onward + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.pageRange(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9))); + + CountDownLatch combineLatch = new CountDownLatch(1); + + PollerFlux combineOperation + = client.beginAnalyze("prebuilt-documentSearch", Arrays.asList(combineInput)); + + combineOperation.last() + .flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error(new RuntimeException( + "Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }) + .doOnNext(result -> { + DocumentContent combineDoc = (DocumentContent) result.getContents().get(0); + System.out.println("Combine(1-3, 5, 9-): returned " + combineDoc.getPages().size() + " pages" + + " (pages " + combineDoc.getStartPageNumber() + "-" + combineDoc.getEndPageNumber() + ")"); + System.out.println("Markdown length: " + combineDoc.getMarkdown().length() + " characters"); + }) + .doOnError(error -> { + System.err.println("Error occurred: " + error.getMessage()); + }) + .subscribe( + result -> combineLatch.countDown(), + error -> combineLatch.countDown() + ); + + try { + combineLatch.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for combined range analysis", e); + } // END:ContentUnderstandingAnalyzeDocumentUrlWithContentRangeAsync } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index c02e86a37132..312657fa9552 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -447,7 +447,7 @@ public void testAnalyzeImageUrlAsync() { public void testAnalyzeUrlWithPageContentRangesAsync() { String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; // Full 4-page analysis for comparison AnalysisInput fullInput = new AnalysisInput(); @@ -490,6 +490,41 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { assertEquals(1, rangeDocContent.getEndPageNumber()); assertTrue(fullDoc.getPages().size() > rangeDocContent.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); + + // Combined disjoint page ranges: pages 1-3, page 5, and pages 9 onward + // Document has 4 pages, so only pages 1-3 match (no page 5 or 9+) + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.pageRange(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9))); + + PollerFlux combineOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.last().flatMap(pollResponse -> { + if (pollResponse.getStatus().isComplete()) { + return pollResponse.getFinalResult(); + } else { + return Mono.error( + new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); + } + }).block(); + + assertNotNull(combineResult); + assertNotNull(combineResult.getContents()); + DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); + assertEquals(3, combineDoc.getPages().size(), + "Combine(1-3, 5, 9-) should return 3 pages (1-3), got " + combineDoc.getPages().size()); + assertEquals(1, combineDoc.getStartPageNumber()); + assertEquals(3, combineDoc.getEndPageNumber()); + List combinePageNumbers = new java.util.ArrayList<>(); + for (DocumentPage page : combineDoc.getPages()) { + combinePageNumbers.add(page.getPageNumber()); + } + java.util.Collections.sort(combinePageNumbers); + assertEquals(Arrays.asList(1, 2, 3), combinePageNumbers, + "Combine(1-3, 5, 9-) page numbers should be [1, 2, 3]"); } @LiveOnly diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index e7d2228fad17..c3c54eb570ea 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -371,7 +371,7 @@ public void testAnalyzeUrlWithPageContentRanges() { // BEGIN:ContentUnderstandingAnalyzeUrlWithPageContentRanges String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_docs.pdf"; + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; // Full 4-page analysis for comparison AnalysisInput fullInput = new AnalysisInput(); @@ -405,6 +405,34 @@ public void testAnalyzeUrlWithPageContentRanges() { assertTrue(fullDoc.getPages().size() > rangeDocContent.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRanges + + // Combined disjoint page ranges: pages 1-3, page 5, and pages 9 onward + // Document has 4 pages, so only pages 1-3 match (no page 5 or 9+) + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.pageRange(1, 3), + ContentRange.page(5), + ContentRange.pagesFrom(9))); + + SyncPoller combineOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.getFinalResult(); + + assertNotNull(combineResult); + assertNotNull(combineResult.getContents()); + DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); + assertEquals(3, combineDoc.getPages().size(), + "Combine(1-3, 5, 9-) should return 3 pages (1-3), got " + combineDoc.getPages().size()); + assertEquals(1, combineDoc.getStartPageNumber()); + assertEquals(3, combineDoc.getEndPageNumber()); + List combinePageNumbers = new java.util.ArrayList<>(); + for (DocumentPage page : combineDoc.getPages()) { + combinePageNumbers.add(page.getPageNumber()); + } + java.util.Collections.sort(combinePageNumbers); + assertEquals(Arrays.asList(1, 2, 3), combinePageNumbers, + "Combine(1-3, 5, 9-) page numbers should be [1, 2, 3]"); } @LiveOnly From 5712626c11bafe1037eb05898e8b7198e3933db5 Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Tue, 24 Mar 2026 16:31:43 +0800 Subject: [PATCH 11/17] Update assertions in AnalyzeUrl tests to reflect correct page counts and ranges for documents with 10 pages --- .../samples/Sample02_AnalyzeUrlAsyncTest.java | 14 +++++++------- .../tests/samples/Sample02_AnalyzeUrlTest.java | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index 312657fa9552..a292af018e85 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -481,7 +481,7 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { } }).block(); - assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); DocumentContent rangeDocContent = (DocumentContent) rangeResult.getContents().get(0); @@ -492,7 +492,7 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); // Combined disjoint page ranges: pages 1-3, page 5, and pages 9 onward - // Document has 4 pages, so only pages 1-3 match (no page 5 or 9+) + // Document has 10 pages, so pages 1-3, 5, 9-10 match (6 pages total) AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); combineInput.setContentRange(ContentRange.combine( @@ -514,17 +514,17 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { assertNotNull(combineResult); assertNotNull(combineResult.getContents()); DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); - assertEquals(3, combineDoc.getPages().size(), - "Combine(1-3, 5, 9-) should return 3 pages (1-3), got " + combineDoc.getPages().size()); + assertEquals(6, combineDoc.getPages().size(), + "Combine(1-3, 5, 9-) should return 6 pages (1-3, 5, 9-10), got " + combineDoc.getPages().size()); assertEquals(1, combineDoc.getStartPageNumber()); - assertEquals(3, combineDoc.getEndPageNumber()); + assertEquals(10, combineDoc.getEndPageNumber()); List combinePageNumbers = new java.util.ArrayList<>(); for (DocumentPage page : combineDoc.getPages()) { combinePageNumbers.add(page.getPageNumber()); } java.util.Collections.sort(combinePageNumbers); - assertEquals(Arrays.asList(1, 2, 3), combinePageNumbers, - "Combine(1-3, 5, 9-) page numbers should be [1, 2, 3]"); + assertEquals(Arrays.asList(1, 2, 3, 5, 9, 10), combinePageNumbers, + "Combine(1-3, 5, 9-) page numbers should be [1, 2, 3, 5, 9, 10]"); } @LiveOnly diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index c3c54eb570ea..aea5bc30798c 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -393,7 +393,7 @@ public void testAnalyzeUrlWithPageContentRanges() { // END:ContentUnderstandingAnalyzeUrlWithPageContentRanges // BEGIN:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRanges - assertEquals(4, fullDoc.getPages().size(), "Full document should return all 4 pages"); + assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); assertNotNull(rangeOperation); assertTrue(rangeOperation.waitForCompletion().getStatus().isComplete()); assertNotNull(rangeResult); @@ -407,7 +407,7 @@ public void testAnalyzeUrlWithPageContentRanges() { // END:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRanges // Combined disjoint page ranges: pages 1-3, page 5, and pages 9 onward - // Document has 4 pages, so only pages 1-3 match (no page 5 or 9+) + // Document has 10 pages, so pages 1-3, 5, 9-10 match (6 pages total) AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); combineInput.setContentRange(ContentRange.combine( @@ -422,17 +422,17 @@ public void testAnalyzeUrlWithPageContentRanges() { assertNotNull(combineResult); assertNotNull(combineResult.getContents()); DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); - assertEquals(3, combineDoc.getPages().size(), - "Combine(1-3, 5, 9-) should return 3 pages (1-3), got " + combineDoc.getPages().size()); + assertEquals(6, combineDoc.getPages().size(), + "Combine(1-3, 5, 9-) should return 6 pages (1-3, 5, 9-10), got " + combineDoc.getPages().size()); assertEquals(1, combineDoc.getStartPageNumber()); - assertEquals(3, combineDoc.getEndPageNumber()); + assertEquals(10, combineDoc.getEndPageNumber()); List combinePageNumbers = new java.util.ArrayList<>(); for (DocumentPage page : combineDoc.getPages()) { combinePageNumbers.add(page.getPageNumber()); } java.util.Collections.sort(combinePageNumbers); - assertEquals(Arrays.asList(1, 2, 3), combinePageNumbers, - "Combine(1-3, 5, 9-) page numbers should be [1, 2, 3]"); + assertEquals(Arrays.asList(1, 2, 3, 5, 9, 10), combinePageNumbers, + "Combine(1-3, 5, 9-) page numbers should be [1, 2, 3, 5, 9, 10]"); } @LiveOnly From 2e7bb2112cd1b24bc4ef7cf388fe214523d7ad39 Mon Sep 17 00:00:00 2001 From: aluneth Date: Tue, 24 Mar 2026 18:02:31 +0800 Subject: [PATCH 12/17] Refactor ContentRange examples to combine multiple time ranges in audio/video analysis samples and tests --- .../samples/Sample02_AnalyzeUrl.java | 47 ++++---------- .../samples/Sample02_AnalyzeUrlAsync.java | 27 ++++---- .../samples/Sample02_AnalyzeUrlAsyncTest.java | 64 +++++-------------- .../samples/Sample02_AnalyzeUrlTest.java | 62 ++++++------------ 4 files changed, 64 insertions(+), 136 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java index babbf6cf2858..3148632e5842 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java @@ -406,24 +406,6 @@ public static void analyzeVideoUrlWithContentRange(ContentUnderstandingClient cl + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); segmentIndex++; } - - // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithRawContentRange - // Analyze the first 5 seconds using a raw range string (milliseconds). - // This is equivalent to: ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(5)) - AnalysisInput rawRangeInput = new AnalysisInput(); - rawRangeInput.setUrl(uriSource); - rawRangeInput.setContentRange(new ContentRange("0-5000")); - - SyncPoller rawRangeOperation - = client.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rawRangeInput)); - AnalysisResult rawRangeResult = rawRangeOperation.getFinalResult(); - - for (AnalysisContent rawMedia : rawRangeResult.getContents()) { - AudioVisualContent rawVideoContent = (AudioVisualContent) rawMedia; - System.out.println("Raw ContentRange segment: " + rawVideoContent.getStartTime().toMillis() - + " ms - " + rawVideoContent.getEndTime().toMillis() + " ms"); - } - // END:ContentUnderstandingAnalyzeVideoUrlWithRawContentRange // END:ContentUnderstandingAnalyzeVideoUrlWithContentRange } @@ -475,21 +457,20 @@ public static void analyzeAudioUrlWithContentRange(ContentUnderstandingClient cl System.out.println("TimeRange(1200ms, 3651ms): Start=" + subSecondContent.getStartTime().toMillis() + " ms, End=" + subSecondContent.getEndTime().toMillis() + " ms"); - // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithRawContentRange - // Analyze audio from 5 seconds onward using a raw range string (milliseconds). - // This is equivalent to: ContentRange.timeRangeFrom(Duration.ofSeconds(5)) - AnalysisInput rawRangeInput = new AnalysisInput(); - rawRangeInput.setUrl(uriSource); - rawRangeInput.setContentRange(new ContentRange("5000-")); - - SyncPoller rawRangeOperation - = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawRangeInput)); - AnalysisResult rawRangeResult = rawRangeOperation.getFinalResult(); - - AudioVisualContent rawAudioContent = (AudioVisualContent) rawRangeResult.getContents().get(0); - System.out.println("Raw ContentRange audio analysis: " + rawAudioContent.getStartTime().toMillis() - + " ms onward"); - // END:ContentUnderstandingAnalyzeAudioUrlWithRawContentRange + // Combine multiple time ranges + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + SyncPoller combineOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.getFinalResult(); + + AudioVisualContent combineContent = (AudioVisualContent) combineResult.getContents().get(0); + System.out.println("Combined time ranges: Start=" + combineContent.getStartTime().toMillis() + + " ms, End=" + combineContent.getEndTime().toMillis() + " ms"); // END:ContentUnderstandingAnalyzeAudioUrlWithContentRange } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 73b27db5fad8..d6872b7e2771 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -825,17 +825,20 @@ public static void analyzeAudioUrlWithContentRange(ContentUnderstandingAsyncClie Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for audio analysis", e); } - // Raw string "5000-" — equivalent to TimeRangeFrom(5s) - AnalysisInput rawInput = new AnalysisInput(); - rawInput.setUrl(audioUrl); - rawInput.setContentRange(new ContentRange("5000-")); - PollerFlux rawOperation - = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawInput)); + // Combine multiple time ranges + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(audioUrl); + combineInput.setContentRange(ContentRange.combine( + ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + PollerFlux combineOperation + = client.beginAnalyze("prebuilt-audioSearch", Arrays.asList(combineInput)); CountDownLatch latch4 = new CountDownLatch(1); - rawOperation.last() + combineOperation.last() .flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { return pollResponse.getFinalResult(); @@ -845,14 +848,16 @@ public static void analyzeAudioUrlWithContentRange(ContentUnderstandingAsyncClie } }) .doOnNext(result -> { - AudioVisualContent rawAudioContent = (AudioVisualContent) result.getContents().get(0); - System.out.println("Raw ContentRange audio analysis: " - + rawAudioContent.getStartTime().toMillis() + " ms onward"); + AudioVisualContent combineContent = (AudioVisualContent) result.getContents().get(0); + System.out.println("Combined time ranges: Start=" + combineContent.getStartTime().toMillis() + + " ms, End=" + combineContent.getEndTime().toMillis() + " ms"); }) .doOnError(error -> System.err.println("Error occurred: " + error.getMessage())) .subscribe(result -> latch4.countDown(), error -> latch4.countDown()); - try { latch4.await(); } catch (InterruptedException e) { + try { + latch4.await(); + } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for audio analysis", e); } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index a292af018e85..4af371a2ca19 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -671,37 +671,6 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertFalse(avContent.getMarkdown().isEmpty()); } - // ---- Raw string "0-5000" — equivalent to TimeRange(0, 5s) ---- - AnalysisInput rawVideoInput = new AnalysisInput(); - rawVideoInput.setUrl(uriSource); - rawVideoInput.setContentRange(new ContentRange("0-5000")); - - PollerFlux rawVideoOperation - = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rawVideoInput)); - AnalysisResult rawVideoResult = rawVideoOperation.last().flatMap(pollResponse -> { - if (pollResponse.getStatus().isComplete()) { - return pollResponse.getFinalResult(); - } else { - return Mono.error( - new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); - } - }).block(); - - assertNotNull(rawVideoResult); - assertNotNull(rawVideoResult.getContents()); - assertTrue(rawVideoResult.getContents().size() > 0, "Raw range video should return segments"); - for (AnalysisContent content : rawVideoResult.getContents()) { - assertTrue(content instanceof AudioVisualContent); - AudioVisualContent avContent = (AudioVisualContent) content; - assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); - assertTrue(avContent.getStartTime().toMillis() >= 0, "Raw range(0-5000) segment StartTime (" - + avContent.getStartTime().toMillis() + " ms) should be >= 0 ms"); - assertTrue(avContent.getEndTime().toMillis() <= 5000, "Raw range(0-5000) segment EndTime (" - + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); - } - assertEquals(rangeResult.getContents().size(), rawVideoResult.getContents().size(), - "Raw ContentRange('0-5000') should return same segment count as TimeRange equivalent"); - System.out.println("Raw ContentRange('0-5000'): " + rawVideoResult.getContents().size() + " segment(s)"); } @LiveOnly @@ -814,14 +783,16 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= subSecondDurationMs); - // ---- Raw string "5000-" — equivalent to TimeRangeFrom(5s) ---- - AnalysisInput rawAudioInput = new AnalysisInput(); - rawAudioInput.setUrl(uriSource); - rawAudioInput.setContentRange(new ContentRange("5000-")); + // ---- Combine multiple time ranges (0-3s, 30s-) ---- + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); - PollerFlux rawAudioOperation - = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawAudioInput)); - AnalysisResult rawAudioResult = rawAudioOperation.last().flatMap(pollResponse -> { + PollerFlux combineOperation + = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.last().flatMap(pollResponse -> { if (pollResponse.getStatus().isComplete()) { return pollResponse.getFinalResult(); } else { @@ -830,15 +801,12 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { } }).block(); - assertNotNull(rawAudioResult); - assertNotNull(rawAudioResult.getContents()); - assertTrue(rawAudioResult.getContents().size() > 0, "Raw range audio should return content"); - AudioVisualContent rawAudioContent = (AudioVisualContent) rawAudioResult.getContents().get(0); - assertTrue(rawAudioContent.getStartTime().toMillis() >= 5000, - "Raw ContentRange('5000-') audio StartTime should be >= 5000 ms"); - assertEquals(rangeAudioContent.getMarkdown().length(), rawAudioContent.getMarkdown().length(), - "Raw ContentRange('5000-') should return same markdown length as TimeRangeFrom equivalent"); - System.out.println("Raw ContentRange('5000-'): " + rawAudioContent.getMarkdown().length() + " chars, starts at " - + rawAudioContent.getStartTime().toMillis() + " ms"); + assertNotNull(combineResult); + assertNotNull(combineResult.getContents()); + assertTrue(combineResult.getContents().size() > 0); + AudioVisualContent combineContent = (AudioVisualContent) combineResult.getContents().get(0); + assertTrue(combineContent.getEndTime().toMillis() > combineContent.getStartTime().toMillis()); + assertNotNull(combineContent.getMarkdown()); + assertFalse(combineContent.getMarkdown().isEmpty()); } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index aea5bc30798c..3789bf339c7c 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -547,31 +547,6 @@ public void testAnalyzeVideoUrlWithTimeContentRanges() { assertFalse(avContent.getMarkdown().isEmpty()); } - // ---- Raw string "0-5000" — equivalent to TimeRange(0, 5s) ---- - AnalysisInput rawVideoInput = new AnalysisInput(); - rawVideoInput.setUrl(uriSource); - rawVideoInput.setContentRange(new ContentRange("0-5000")); - - SyncPoller rawVideoOperation - = contentUnderstandingClient.beginAnalyze("prebuilt-videoSearch", Arrays.asList(rawVideoInput)); - AnalysisResult rawVideoResult = rawVideoOperation.getFinalResult(); - - assertNotNull(rawVideoResult); - assertNotNull(rawVideoResult.getContents()); - assertTrue(rawVideoResult.getContents().size() > 0, "Raw range video should return segments"); - for (AnalysisContent content : rawVideoResult.getContents()) { - assertTrue(content instanceof AudioVisualContent); - AudioVisualContent avContent = (AudioVisualContent) content; - assertTrue(avContent.getEndTime().toMillis() > avContent.getStartTime().toMillis()); - assertTrue(avContent.getStartTime().toMillis() >= 0, "Raw range(0-5000) segment StartTime (" - + avContent.getStartTime().toMillis() + " ms) should be >= 0 ms"); - assertTrue(avContent.getEndTime().toMillis() <= 5000, "Raw range(0-5000) segment EndTime (" - + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); - } - // The raw string "0-5000" should produce identical results to TimeRange(0, 5s) - assertEquals(rangeResult.getContents().size(), rawVideoResult.getContents().size(), - "Raw ContentRange('0-5000') should return same segment count as TimeRange equivalent"); - System.out.println("Raw ContentRange('0-5000'): " + rawVideoResult.getContents().size() + " segment(s)"); } @LiveOnly @@ -659,25 +634,24 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { = audioSubSecondContent.getEndTime().toMillis() - audioSubSecondContent.getStartTime().toMillis(); assertTrue(fullDurationMs >= subSecondDurationMs); - // ---- Raw string "5000-" — equivalent to TimeRangeFrom(5s) ---- - AnalysisInput rawAudioInput = new AnalysisInput(); - rawAudioInput.setUrl(uriSource); - rawAudioInput.setContentRange(new ContentRange("5000-")); - - SyncPoller rawAudioOperation - = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(rawAudioInput)); - AnalysisResult rawAudioResult = rawAudioOperation.getFinalResult(); - - assertNotNull(rawAudioResult); - assertNotNull(rawAudioResult.getContents()); - assertTrue(rawAudioResult.getContents().size() > 0, "Raw range audio should return content"); - AudioVisualContent rawAudioContent = (AudioVisualContent) rawAudioResult.getContents().get(0); - assertTrue(rawAudioContent.getStartTime().toMillis() >= 5000, - "Raw ContentRange('5000-') audio StartTime should be >= 5000 ms"); - assertEquals(rangeAudioContent.getMarkdown().length(), rawAudioContent.getMarkdown().length(), - "Raw ContentRange('5000-') should return same markdown length as TimeRangeFrom equivalent"); - System.out.println("Raw ContentRange('5000-'): " + rawAudioContent.getMarkdown().length() + " chars, starts at " - + rawAudioContent.getStartTime().toMillis() + " ms"); + // ---- Combine multiple time ranges (0-3s, 30s-) ---- + AnalysisInput combineInput = new AnalysisInput(); + combineInput.setUrl(uriSource); + combineInput.setContentRange(ContentRange.combine( + ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); + + SyncPoller combineOperation + = contentUnderstandingClient.beginAnalyze("prebuilt-audioSearch", Arrays.asList(combineInput)); + AnalysisResult combineResult = combineOperation.getFinalResult(); + + assertNotNull(combineResult); + assertNotNull(combineResult.getContents()); + assertTrue(combineResult.getContents().size() > 0); + AudioVisualContent combineContent = (AudioVisualContent) combineResult.getContents().get(0); + assertTrue(combineContent.getEndTime().toMillis() > combineContent.getStartTime().toMillis()); + assertNotNull(combineContent.getMarkdown()); + assertFalse(combineContent.getMarkdown().isEmpty()); } @Test From 4fd8e0546e4d578051190c75246b8725ac0ad678 Mon Sep 17 00:00:00 2001 From: aluneth Date: Tue, 24 Mar 2026 18:25:51 +0800 Subject: [PATCH 13/17] Refactor ContentRange usage in analysis samples and tests; add image analysis test --- .../samples/Sample02_AnalyzeUrl.java | 2 +- .../samples/Sample02_AnalyzeUrlAsync.java | 2 +- .../Sample01_AnalyzeBinaryAsyncTest.java | 21 +++- .../samples/Sample01_AnalyzeBinaryTest.java | 8 +- .../samples/Sample02_AnalyzeUrlAsyncTest.java | 61 ++++++----- .../samples/Sample02_AnalyzeUrlTest.java | 100 +++++++++--------- 6 files changed, 110 insertions(+), 84 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java index 3148632e5842..a6e165ccc27d 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrl.java @@ -319,7 +319,7 @@ public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingClient AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); combineInput.setContentRange(ContentRange.combine( - ContentRange.pageRange(1, 3), + ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9))); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index d6872b7e2771..68fceba7c679 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -480,7 +480,7 @@ public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncC AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); combineInput.setContentRange(ContentRange.combine( - ContentRange.pageRange(1, 3), + ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9))); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java index b58c4b673e3b..ba472cc293cb 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryAsyncTest.java @@ -293,6 +293,7 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { DocumentContent fullDoc = (DocumentContent) fullResult.getContents().get(0); assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); + // BEGIN:ContentUnderstandingAnalyzeBinaryWithSinglePageAsync // ---- Page(2) — single page ---- PollerFlux page2Operation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -306,12 +307,16 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { } }).block(); DocumentContent page2Doc = (DocumentContent) page2Result.getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithSinglePageAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithSinglePageAsync assertEquals(1, page2Doc.getPages().size(), "Page(2) should return exactly 1 page"); assertEquals(2, page2Doc.getStartPageNumber(), "Page(2) should start at page 2"); assertEquals(2, page2Doc.getEndPageNumber(), "Page(2) should end at page 2"); assertTrue(fullDoc.getMarkdown().length() > page2Doc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithSinglePageAsync + // BEGIN:ContentUnderstandingAnalyzeBinaryWithPagesAsync // ---- Pages(1, 3) — page range ---- PollerFlux pages13Operation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -325,12 +330,16 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { } }).block(); DocumentContent pages13Doc = (DocumentContent) pages13Result.getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithPagesAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesAsync assertEquals(3, pages13Doc.getPages().size(), "Pages(1,3) should return exactly 3 pages"); assertEquals(1, pages13Doc.getStartPageNumber()); assertEquals(3, pages13Doc.getEndPageNumber()); assertTrue(fullDoc.getMarkdown().length() > pages13Doc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesAsync + // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRangeAsync // ---- Combine(Page(1), Pages(3, 4)) — combined single page and page range ---- PollerFlux combineOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -344,8 +353,9 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { } }).block(); DocumentContent combineDoc = (DocumentContent) combineResult.getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRangeAsync - assertTrue(combineDoc.getPages().size() >= 2); + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRangeAsync assertEquals(3, combineDoc.getPages().size(), "Combine(Page(1), Pages(3,4)) should return exactly 3 pages"); java.util.List combinePageNumbers = combineDoc.getPages() .stream() @@ -357,7 +367,9 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertEquals(1, combineDoc.getStartPageNumber()); assertEquals(4, combineDoc.getEndPageNumber(), "Combine should end at page 4"); assertTrue(fullDoc.getMarkdown().length() >= combineDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRangeAsync + // BEGIN:ContentUnderstandingAnalyzeBinaryWithPagesFromAsync // ---- PagesFrom(3) — extract pages 3 to end ---- PollerFlux rangeOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -370,7 +382,9 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); + // END:ContentUnderstandingAnalyzeBinaryWithPagesFromAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFromAsync assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); DocumentContent rangeDoc = (DocumentContent) rangeResult.getContents().get(0); @@ -379,7 +393,9 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertEquals(10, rangeDoc.getEndPageNumber(), "pagesFrom(3) should end at page 10"); assertTrue(fullDoc.getPages().size() > rangeDoc.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPagesFromAsync + // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPagesAsync // ---- Combine(Pages(1,3), Page(5), PagesFrom(9)) — combined page ranges ---- PollerFlux bigCombineOperation = contentUnderstandingAsyncClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, @@ -394,7 +410,9 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { } }).block(); DocumentContent bigCombineDoc = (DocumentContent) bigCombineResult.getContents().get(0); + // END:ContentUnderstandingAnalyzeBinaryWithCombinedPagesAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPagesAsync assertNotNull(bigCombineResult); assertNotNull(bigCombineResult.getContents()); assertEquals(6, bigCombineDoc.getPages().size(), @@ -407,5 +425,6 @@ public void testAnalyzeBinaryWithPageContentRangesAsync() throws IOException { assertEquals(java.util.Arrays.asList(1, 2, 3, 5, 9, 10), combineRangePageNumbers, "Combine(Pages(1,3), Page(5), PagesFrom(9)) should extract pages 1, 2, 3, 5, 9, 10"); assertTrue(fullDoc.getMarkdown().length() >= bigCombineDoc.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithCombinedPagesAsync } } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java index d4a0a176e3d1..9eecf856f757 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample01_AnalyzeBinaryTest.java @@ -292,20 +292,20 @@ public void testAnalyzeBinaryWithPageContentRanges() throws IOException { assertTrue(fullDoc.getMarkdown().length() > page2Doc.getMarkdown().length()); // END:Assertion_ContentUnderstandingAnalyzeBinaryWithSinglePage - // BEGIN:ContentUnderstandingAnalyzeBinaryWithPageRange + // BEGIN:ContentUnderstandingAnalyzeBinaryWithPages // ---- Pages(1, 3) — page range ---- SyncPoller pages13Operation = contentUnderstandingClient.beginAnalyzeBinary("prebuilt-documentSearch", binaryData, ContentRange.pages(1, 3), "application/octet-stream", null); DocumentContent pages13Doc = (DocumentContent) pages13Operation.getFinalResult().getContents().get(0); - // END:ContentUnderstandingAnalyzeBinaryWithPageRange + // END:ContentUnderstandingAnalyzeBinaryWithPages - // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPageRange + // BEGIN:Assertion_ContentUnderstandingAnalyzeBinaryWithPages assertEquals(3, pages13Doc.getPages().size(), "Pages(1,3) should return exactly 3 pages"); assertEquals(1, pages13Doc.getStartPageNumber()); assertEquals(3, pages13Doc.getEndPageNumber()); assertTrue(fullDoc.getMarkdown().length() > pages13Doc.getMarkdown().length()); - // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPageRange + // END:Assertion_ContentUnderstandingAnalyzeBinaryWithPages // BEGIN:ContentUnderstandingAnalyzeBinaryWithCombinedPageAndRange // ---- Combine(Page(1), Pages(3, 4)) — combined single page and page range ---- diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index 4af371a2ca19..2c56b7753b40 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -44,7 +44,7 @@ public class Sample02_AnalyzeUrlAsyncTest extends ContentUnderstandingClientTest @Test public void testAnalyzeUrlAsync() { - // BEGIN:ContentUnderstandingAnalyzeUrlAsyncAsync + // BEGIN:ContentUnderstandingAnalyzeUrlAsync // Using a publicly accessible sample file from Azure-Samples GitHub repository String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-dotnet/main/ContentUnderstanding.Common/data/invoice.pdf"; @@ -65,9 +65,9 @@ public void testAnalyzeUrlAsync() { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); // block() is used here for testing; in production, use subscribe() - // END:ContentUnderstandingAnalyzeUrlAsyncAsync + // END:ContentUnderstandingAnalyzeUrlAsync - // BEGIN:Assertion_ContentUnderstandingAnalyzeUrlAsyncAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeUrlAsync assertNotNull(uriSource, "URI source should not be null"); assertNotNull(operation, "Analysis operation should not be null"); assertNotNull(result, "Analysis result should not be null"); @@ -75,7 +75,7 @@ public void testAnalyzeUrlAsync() { System.out.println("Analysis operation properties verified"); System.out.println("Analysis result contains " + (result.getContents() != null ? result.getContents().size() : 0) + " content(s)"); - // END:Assertion_ContentUnderstandingAnalyzeUrlAsyncAsync + // END:Assertion_ContentUnderstandingAnalyzeUrlAsync // A PDF file has only one content element even if it contains multiple pages AnalysisContent content = null; @@ -246,7 +246,7 @@ public void testAnalyzeUrlAsync() { @Test public void testAnalyzeVideoUrlAsync() { - // BEGIN:ContentUnderstandingAnalyzeVideoUrlAsyncAsync + // BEGIN:ContentUnderstandingAnalyzeVideoUrlAsync String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/videos/sdk_samples/FlightSimulator.mp4"; @@ -292,9 +292,9 @@ public void testAnalyzeVideoUrlAsync() { System.out.println("---------------------"); segmentIndex++; } - // END:ContentUnderstandingAnalyzeVideoUrlAsyncAsync + // END:ContentUnderstandingAnalyzeVideoUrlAsync - // BEGIN:Assertion_ContentUnderstandingAnalyzeVideoUrlAsyncAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeVideoUrlAsync assertNotNull(operation, "Analysis operation should not be null"); assertNotNull(result, "Analysis result should not be null"); assertNotNull(result.getContents(), "Result contents should not be null"); @@ -311,12 +311,12 @@ public void testAnalyzeVideoUrlAsync() { assertFalse(summaryStr.trim().isEmpty(), "Summary should not be empty"); } System.out.println("Video analysis validation completed successfully"); - // END:Assertion_ContentUnderstandingAnalyzeVideoUrlAsyncAsync + // END:Assertion_ContentUnderstandingAnalyzeVideoUrlAsync } @Test public void testAnalyzeAudioUrlAsync() { - // BEGIN:ContentUnderstandingAnalyzeAudioUrlAsyncAsync + // BEGIN:ContentUnderstandingAnalyzeAudioUrlAsync String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/audio/callCenterRecording.mp3"; @@ -365,9 +365,9 @@ public void testAnalyzeAudioUrlAsync() { count++; } } - // END:ContentUnderstandingAnalyzeAudioUrlAsyncAsync + // END:ContentUnderstandingAnalyzeAudioUrlAsync - // BEGIN:Assertion_ContentUnderstandingAnalyzeAudioUrlAsyncAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeAudioUrlAsync assertNotNull(operation, "Analysis operation should not be null"); assertNotNull(result, "Analysis result should not be null"); assertNotNull(result.getContents(), "Result contents should not be null"); @@ -387,12 +387,12 @@ public void testAnalyzeAudioUrlAsync() { assertFalse(summaryStr.trim().isEmpty(), "Summary should not be empty"); } System.out.println("Audio analysis validation completed successfully"); - // END:Assertion_ContentUnderstandingAnalyzeAudioUrlAsyncAsync + // END:Assertion_ContentUnderstandingAnalyzeAudioUrlAsync } @Test public void testAnalyzeImageUrlAsync() { - // BEGIN:ContentUnderstandingAnalyzeImageUrlAsyncAsync + // BEGIN:ContentUnderstandingAnalyzeImageUrlAsync String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/image/pieChart.jpg"; @@ -423,9 +423,9 @@ public void testAnalyzeImageUrlAsync() { : "") : ""; System.out.println("Summary: " + summary); - // END:ContentUnderstandingAnalyzeImageUrlAsyncAsync + // END:ContentUnderstandingAnalyzeImageUrlAsync - // BEGIN:Assertion_ContentUnderstandingAnalyzeImageUrlAsyncAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeImageUrlAsync assertNotNull(operation, "Analysis operation should not be null"); assertNotNull(result, "Analysis result should not be null"); assertNotNull(result.getContents(), "Result contents should not be null"); @@ -440,12 +440,13 @@ public void testAnalyzeImageUrlAsync() { assertFalse(summaryStr.trim().isEmpty(), "Summary should not be empty"); } System.out.println("Image analysis validation completed successfully"); - // END:Assertion_ContentUnderstandingAnalyzeImageUrlAsyncAsync + // END:Assertion_ContentUnderstandingAnalyzeImageUrlAsync } @Test public void testAnalyzeUrlWithPageContentRangesAsync() { + // BEGIN:ContentUnderstandingAnalyzeUrlWithPageContentRangesAsync String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; @@ -480,7 +481,9 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); + // END:ContentUnderstandingAnalyzeUrlWithPageContentRangesAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRangesAsync assertEquals(10, fullDoc.getPages().size(), "Full document should return all 10 pages"); assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); @@ -490,15 +493,14 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { assertEquals(1, rangeDocContent.getEndPageNumber()); assertTrue(fullDoc.getPages().size() > rangeDocContent.getPages().size()); assertTrue(fullDoc.getMarkdown().length() > rangeDocContent.getMarkdown().length()); + // END:Assertion_ContentUnderstandingAnalyzeUrlWithPageContentRangesAsync // Combined disjoint page ranges: pages 1-3, page 5, and pages 9 onward // Document has 10 pages, so pages 1-3, 5, 9-10 match (6 pages total) AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); - combineInput.setContentRange(ContentRange.combine( - ContentRange.pageRange(1, 3), - ContentRange.page(5), - ContentRange.pagesFrom(9))); + combineInput.setContentRange( + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9))); PollerFlux combineOperation = contentUnderstandingAsyncClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(combineInput)); @@ -531,6 +533,7 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { @Test public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { + // BEGIN:ContentUnderstandingAnalyzeVideoUrlWithTimeContentRangesAsync String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/videos/sdk_samples/FlightSimulator.mp4"; @@ -549,10 +552,6 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { } }).block(); - assertNotNull(fullResult); - assertNotNull(fullResult.getContents()); - assertTrue(fullResult.getContents().size() > 0); - // ---- TimeRange(0, 5s) — first 5 seconds ---- AnalysisInput rangeInput = new AnalysisInput(); rangeInput.setUrl(uriSource); @@ -568,6 +567,12 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); + // END:ContentUnderstandingAnalyzeVideoUrlWithTimeContentRangesAsync + + // BEGIN:Assertion_ContentUnderstandingAnalyzeVideoUrlWithTimeContentRangesAsync + assertNotNull(fullResult); + assertNotNull(fullResult.getContents()); + assertTrue(fullResult.getContents().size() > 0); assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); @@ -581,6 +586,7 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { assertTrue(avContent.getEndTime().toMillis() <= 5000, "Range(0-5s) segment EndTime (" + avContent.getEndTime().toMillis() + " ms) should be <= 5000 ms"); } + // END:Assertion_ContentUnderstandingAnalyzeVideoUrlWithTimeContentRangesAsync // ---- TimeRangeFrom(10s) — from 10 seconds to end ---- AnalysisInput rangeFromInput = new AnalysisInput(); @@ -677,6 +683,7 @@ public void testAnalyzeVideoUrlWithTimeContentRangesAsync() { @Test public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { + // BEGIN:ContentUnderstandingAnalyzeAudioUrlWithTimeContentRangesAsync String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/audio/callCenterRecording.mp3"; @@ -712,7 +719,9 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { new RuntimeException("Polling completed unsuccessfully with status: " + pollResponse.getStatus())); } }).block(); + // END:ContentUnderstandingAnalyzeAudioUrlWithTimeContentRangesAsync + // BEGIN:Assertion_ContentUnderstandingAnalyzeAudioUrlWithTimeContentRangesAsync assertNotNull(rangeResult); assertNotNull(rangeResult.getContents()); assertTrue(rangeResult.getContents().size() > 0); @@ -728,6 +737,7 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { assertTrue(fullDurationMs >= rangeDurationMs); assertTrue(rangeAudioContent.getStartTime().toMillis() >= 5000, "TimeRangeFrom(5s) audio StartTime (" + rangeAudioContent.getStartTime().toMillis() + " ms) should be >= 5000 ms"); + // END:Assertion_ContentUnderstandingAnalyzeAudioUrlWithTimeContentRangesAsync // ---- TimeRange(2s, 8s) — specific time window ---- AnalysisInput windowInput = new AnalysisInput(); @@ -786,8 +796,7 @@ public void testAnalyzeAudioUrlWithTimeContentRangesAsync() { // ---- Combine multiple time ranges (0-3s, 30s-) ---- AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); - combineInput.setContentRange(ContentRange.combine( - ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + combineInput.setContentRange(ContentRange.combine(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); PollerFlux combineOperation diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index 3789bf339c7c..2b9092c5e186 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -366,6 +366,52 @@ public void testAnalyzeAudioUrl() { // END:Assertion_ContentUnderstandingAnalyzeAudioUrl } + + @Test + public void testAnalyzeImageUrl() { + // BEGIN:ContentUnderstandingAnalyzeImageUrl + String uriSource + = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/image/pieChart.jpg"; + + AnalysisInput input = new AnalysisInput(); + input.setUrl(uriSource); + + SyncPoller operation + = contentUnderstandingClient.beginAnalyze("prebuilt-imageSearch", Arrays.asList(input)); + + AnalysisResult result = operation.getFinalResult(); + + AnalysisContent content = result.getContents().get(0); + System.out.println("Markdown:"); + System.out.println(content.getMarkdown()); + + String summary = content.getFields() != null && content.getFields().containsKey("Summary") + ? (content.getFields().get("Summary").getValue() != null + ? content.getFields().get("Summary").getValue().toString() + : "") + : ""; + System.out.println("Summary: " + summary); + // END:ContentUnderstandingAnalyzeImageUrl + + // BEGIN:Assertion_ContentUnderstandingAnalyzeImageUrl + assertNotNull(operation, "Analysis operation should not be null"); + assertTrue(operation.waitForCompletion().getStatus().isComplete(), "Operation should be completed"); + assertNotNull(result, "Analysis result should not be null"); + assertNotNull(result.getContents(), "Result contents should not be null"); + assertTrue(result.getContents().size() > 0, "Result should have at least one content"); + + // Verify content has Summary field + for (AnalysisContent mediaContent : result.getContents()) { + assertNotNull(mediaContent.getFields(), "Content should have fields"); + assertTrue(mediaContent.getFields().containsKey("Summary"), "Image content should have Summary field"); + assertNotNull(mediaContent.getFields().get("Summary").getValue(), "Summary value should not be null"); + String summaryStr = mediaContent.getFields().get("Summary").getValue().toString(); + assertFalse(summaryStr.trim().isEmpty(), "Summary should not be empty"); + } + System.out.println("Image analysis validation completed successfully"); + // END:Assertion_ContentUnderstandingAnalyzeImageUrl + } + @Test public void testAnalyzeUrlWithPageContentRanges() { @@ -410,10 +456,8 @@ public void testAnalyzeUrlWithPageContentRanges() { // Document has 10 pages, so pages 1-3, 5, 9-10 match (6 pages total) AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); - combineInput.setContentRange(ContentRange.combine( - ContentRange.pageRange(1, 3), - ContentRange.page(5), - ContentRange.pagesFrom(9))); + combineInput.setContentRange( + ContentRange.combine(ContentRange.pages(1, 3), ContentRange.page(5), ContentRange.pagesFrom(9))); SyncPoller combineOperation = contentUnderstandingClient.beginAnalyze("prebuilt-documentSearch", Arrays.asList(combineInput)); @@ -637,8 +681,7 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { // ---- Combine multiple time ranges (0-3s, 30s-) ---- AnalysisInput combineInput = new AnalysisInput(); combineInput.setUrl(uriSource); - combineInput.setContentRange(ContentRange.combine( - ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), + combineInput.setContentRange(ContentRange.combine(ContentRange.timeRange(Duration.ZERO, Duration.ofSeconds(3)), ContentRange.timeRangeFrom(Duration.ofSeconds(30)))); SyncPoller combineOperation @@ -653,49 +696,4 @@ public void testAnalyzeAudioUrlWithTimeContentRanges() { assertNotNull(combineContent.getMarkdown()); assertFalse(combineContent.getMarkdown().isEmpty()); } - - @Test - public void testAnalyzeImageUrl() { - // BEGIN:ContentUnderstandingAnalyzeImageUrl - String uriSource - = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/image/pieChart.jpg"; - - AnalysisInput input = new AnalysisInput(); - input.setUrl(uriSource); - - SyncPoller operation - = contentUnderstandingClient.beginAnalyze("prebuilt-imageSearch", Arrays.asList(input)); - - AnalysisResult result = operation.getFinalResult(); - - AnalysisContent content = result.getContents().get(0); - System.out.println("Markdown:"); - System.out.println(content.getMarkdown()); - - String summary = content.getFields() != null && content.getFields().containsKey("Summary") - ? (content.getFields().get("Summary").getValue() != null - ? content.getFields().get("Summary").getValue().toString() - : "") - : ""; - System.out.println("Summary: " + summary); - // END:ContentUnderstandingAnalyzeImageUrl - - // BEGIN:Assertion_ContentUnderstandingAnalyzeImageUrl - assertNotNull(operation, "Analysis operation should not be null"); - assertTrue(operation.waitForCompletion().getStatus().isComplete(), "Operation should be completed"); - assertNotNull(result, "Analysis result should not be null"); - assertNotNull(result.getContents(), "Result contents should not be null"); - assertTrue(result.getContents().size() > 0, "Result should have at least one content"); - - // Verify content has Summary field - for (AnalysisContent mediaContent : result.getContents()) { - assertNotNull(mediaContent.getFields(), "Content should have fields"); - assertTrue(mediaContent.getFields().containsKey("Summary"), "Image content should have Summary field"); - assertNotNull(mediaContent.getFields().get("Summary").getValue(), "Summary value should not be null"); - String summaryStr = mediaContent.getFields().get("Summary").getValue().toString(); - assertFalse(summaryStr.trim().isEmpty(), "Summary should not be empty"); - } - System.out.println("Image analysis validation completed successfully"); - // END:Assertion_ContentUnderstandingAnalyzeImageUrl - } } From 93417367d7e48dfc0ccf81555c88c4cd463ac7bb Mon Sep 17 00:00:00 2001 From: aluneth Date: Tue, 24 Mar 2026 21:30:39 +0800 Subject: [PATCH 14/17] Update asset tag in assets.json and remove unnecessary blank line in Sample02_AnalyzeUrlTest --- .../azure-ai-contentunderstanding/assets.json | 2 +- .../tests/samples/Sample02_AnalyzeUrlTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json b/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json index d770358ba5ed..58186b3555c8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/contentunderstanding/azure-ai-contentunderstanding", - "Tag": "java/contentunderstanding/azure-ai-contentunderstanding_acf3c730ff" + "Tag": "java/contentunderstanding/azure-ai-contentunderstanding_670ad2966f" } diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index 2b9092c5e186..bc19b973bed9 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -366,7 +366,6 @@ public void testAnalyzeAudioUrl() { // END:Assertion_ContentUnderstandingAnalyzeAudioUrl } - @Test public void testAnalyzeImageUrl() { // BEGIN:ContentUnderstandingAnalyzeImageUrl From 42ef1e1597cd8601987e666c50b522cd87716fdc Mon Sep 17 00:00:00 2001 From: aluneth Date: Tue, 24 Mar 2026 22:19:13 +0800 Subject: [PATCH 15/17] Update comments in analysis sample tests for clarity --- .../tests/samples/Sample02_AnalyzeUrlAsyncTest.java | 2 +- .../tests/samples/Sample02_AnalyzeUrlTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java index 2c56b7753b40..9a632d4e1d5c 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlAsyncTest.java @@ -450,7 +450,7 @@ public void testAnalyzeUrlWithPageContentRangesAsync() { String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; - // Full 4-page analysis for comparison + // Full document analysis for comparison AnalysisInput fullInput = new AnalysisInput(); fullInput.setUrl(uriSource); diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java index bc19b973bed9..7c538bb4a2b5 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/test/java/com/azure/ai/contentunderstanding/tests/samples/Sample02_AnalyzeUrlTest.java @@ -418,7 +418,7 @@ public void testAnalyzeUrlWithPageContentRanges() { String uriSource = "https://raw.githubusercontent.com/Azure-Samples/azure-ai-content-understanding-assets/main/document/mixed_financial_invoices.pdf"; - // Full 4-page analysis for comparison + // Full document analysis for comparison AnalysisInput fullInput = new AnalysisInput(); fullInput.setUrl(uriSource); From e80753f4ab6725570c5610d5807bca45303b13aa Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Tue, 24 Mar 2026 22:58:06 +0800 Subject: [PATCH 16/17] Update sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 68fceba7c679..39147e6c1942 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -464,9 +464,10 @@ public static void analyzeDocumentUrlWithContentRange(ContentUnderstandingAsyncC .doOnError(error -> { System.err.println("Error occurred: " + error.getMessage()); }) + .doFinally(signalType -> latch.countDown()) .subscribe( result -> { }, - error -> latch.countDown() + error -> { } ); try { From 0533456318a407a2a1320e6e703792c4ad74c5be Mon Sep 17 00:00:00 2001 From: Changjian Wang Date: Wed, 25 Mar 2026 08:23:29 +0800 Subject: [PATCH 17/17] Update sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../samples/Sample02_AnalyzeUrlAsync.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java index 39147e6c1942..2c4812505d4b 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/src/samples/java/com/azure/ai/contentunderstanding/samples/Sample02_AnalyzeUrlAsync.java @@ -679,8 +679,12 @@ public static void analyzeVideoUrlWithContentRange(ContentUnderstandingAsyncClie int segmentIndex = 1; for (AnalysisContent media : result.getContents()) { AudioVisualContent videoContent = (AudioVisualContent) media; - System.out.println("Combined segment " + segmentIndex + ": Start=" + videoContent.getStartTime().toMillis() - + " ms, End=" + videoContent.getEndTime().toMillis() + " ms"); + System.out.println( + "Combined segment " + segmentIndex + ": Start=" + + videoContent.getStartTime().toMillis() + + " ms, End=" + + videoContent.getEndTime().toMillis() + + " ms"); segmentIndex++; } })