From c8a58b9d7f7da4331611ee16ccd91e7ad88e09bd Mon Sep 17 00:00:00 2001 From: Devi Pathak Date: Mon, 16 Mar 2026 10:48:03 +0530 Subject: [PATCH 1/2] FINERACT-2537: Add unit tests for StreamResponseUtil Add comprehensive unit tests for the StreamResponseUtil utility class. Tests cover: - ok(StreamResponseData) response creation - ok(AsyncResponse, StreamResponseData) asynchronous response handling - Content-Disposition header generation - StreamingOutput functionality - Async response execution These tests improve test coverage and help ensure correct behavior of response streaming utilities. --- .../fineract/util/StreamResponseUtilTest.java | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 fineract-core/src/test/java/org/apache/fineract/util/StreamResponseUtilTest.java diff --git a/fineract-core/src/test/java/org/apache/fineract/util/StreamResponseUtilTest.java b/fineract-core/src/test/java/org/apache/fineract/util/StreamResponseUtilTest.java new file mode 100644 index 00000000000..b1a95af567f --- /dev/null +++ b/fineract-core/src/test/java/org/apache/fineract/util/StreamResponseUtilTest.java @@ -0,0 +1,137 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.util; + +import jakarta.ws.rs.container.AsyncResponse; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.core.StreamingOutput; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.concurrent.Future; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +class StreamResponseUtilTest { + + @Test + void okReturnsResponseWithoutContentDispositionWhenDispositionTypeEmpty() { + + InputStream stream = new ByteArrayInputStream("test".getBytes()); + + StreamResponseUtil.StreamResponseData data = StreamResponseUtil.StreamResponseData.builder().stream(stream).type("text/plain") + .fileName("file.txt").build(); + + Response response = StreamResponseUtil.ok(data); + + Assertions.assertEquals("text/plain", response.getMediaType().toString()); + Assertions.assertNull(response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION)); + } + + @Test + void okReturnsResponseWithContentDispositionWhenDispositionTypePresent() { + + InputStream stream = new ByteArrayInputStream("test".getBytes()); + + StreamResponseUtil.StreamResponseData data = StreamResponseUtil.StreamResponseData.builder().stream(stream).type("text/plain") + .fileName("file.txt").dispositionType(StreamResponseUtil.DISPOSITION_TYPE_ATTACHMENT).build(); + + Response response = StreamResponseUtil.ok(data); + + Assertions.assertEquals("text/plain", response.getMediaType().toString()); + + String header = response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION); + + Assertions.assertNotNull(header); + Assertions.assertTrue(header.contains(StreamResponseUtil.DISPOSITION_TYPE_ATTACHMENT)); + Assertions.assertTrue(header.contains("file.txt")); + } + + @Test + void okAsyncResponseWithoutDisposition() throws Exception { + + AsyncResponse asyncResponse = Mockito.mock(AsyncResponse.class); + + InputStream stream = new ByteArrayInputStream("test".getBytes()); + + StreamResponseUtil.StreamResponseData data = StreamResponseUtil.StreamResponseData.builder().stream(stream).type("text/plain") + .build(); + + Future future = StreamResponseUtil.ok(asyncResponse, data); + + future.get(); + + Mockito.verify(asyncResponse).resume(Mockito.any(Response.class)); + } + + @Test + void okAsyncResponseWithDisposition() throws Exception { + + AsyncResponse asyncResponse = Mockito.mock(AsyncResponse.class); + + InputStream stream = new ByteArrayInputStream("test".getBytes()); + + StreamResponseUtil.StreamResponseData data = StreamResponseUtil.StreamResponseData.builder().stream(stream).type("text/plain") + .fileName("file.txt").dispositionType(StreamResponseUtil.DISPOSITION_TYPE_INLINE).build(); + + Future future = StreamResponseUtil.ok(asyncResponse, data); + + future.get(); + + Mockito.verify(asyncResponse).resume(Mockito.any(Response.class)); + } + + @Test + void okHeaderContainsCorrectFilename() { + + InputStream stream = new ByteArrayInputStream("hello".getBytes()); + + StreamResponseUtil.StreamResponseData data = StreamResponseUtil.StreamResponseData.builder().stream(stream).type("text/plain") + .fileName("example.txt").dispositionType(StreamResponseUtil.DISPOSITION_TYPE_ATTACHMENT).build(); + + Response response = StreamResponseUtil.ok(data); + + String header = response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION); + + Assertions.assertTrue(header.contains("attachment")); + Assertions.assertTrue(header.contains("example.txt")); + } + + @Test + void okStreamingOutputWritesStreamData() throws Exception { + + byte[] content = "stream-content".getBytes(); + InputStream stream = new ByteArrayInputStream(content); + + StreamResponseUtil.StreamResponseData data = StreamResponseUtil.StreamResponseData.builder().stream(stream).type("text/plain") + .build(); + + Response response = StreamResponseUtil.ok(data); + + StreamingOutput streamingOutput = (StreamingOutput) response.getEntity(); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + streamingOutput.write(out); + + Assertions.assertArrayEquals(content, out.toByteArray()); + } +} From 95254b2b84f87594f386b7a0f46f833a7481746c Mon Sep 17 00:00:00 2001 From: Devi Pathak Date: Mon, 16 Mar 2026 16:26:05 +0530 Subject: [PATCH 2/2] FINERACT-2539: Add unit tests for MathUtil utility class Add comprehensive unit tests for MathUtil covering core behaviors including null handling, arithmetic operations, comparison helpers, BigDecimal operations, percentage calculations, and formatting helpers. The tests verify correct handling of: - null and default value behavior - negative and zero values - arithmetic operations (add, subtract, abs) - BigDecimal utilities - percentage calculations - trailing zero normalization These tests improve reliability and increase test coverage for shared mathematical utilities used across the platform. --- .../core/service/MathUtilTest.java | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 fineract-core/src/test/java/org/apache/fineract/infrastructure/core/service/MathUtilTest.java diff --git a/fineract-core/src/test/java/org/apache/fineract/infrastructure/core/service/MathUtilTest.java b/fineract-core/src/test/java/org/apache/fineract/infrastructure/core/service/MathUtilTest.java new file mode 100644 index 00000000000..9e2ed4f88ff --- /dev/null +++ b/fineract-core/src/test/java/org/apache/fineract/infrastructure/core/service/MathUtilTest.java @@ -0,0 +1,145 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.infrastructure.core.service; + +import java.math.BigDecimal; +import java.math.MathContext; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNull; +import org.junit.jupiter.api.Test; + +class MathUtilTest { + + @Test + void nullToDefaultReturnsDefaultWhenValueNull() { + Long result = MathUtil.nullToDefault(null, 5L); + assertEquals(5L, result); + } + + @Test + void nullToDefaultReturnsValueWhenNotNull() { + Long result = MathUtil.nullToDefault(10L, 5L); + assertEquals(10L, result); + } + + @Test + void nullToZeroLongReturnsZeroWhenNull() { + Long result = MathUtil.nullToZero((Long) null); + assertEquals(0L, result); + } + + @Test + void zeroToNullReturnsNullWhenZero() { + Long result = MathUtil.zeroToNull(0L); + assertNull(result); + } + + @Test + void negativeToZeroReturnsZeroForNegativeValue() { + Long result = MathUtil.negativeToZero(-10L); + assertEquals(0L, result); + } + + @Test + void negativeToZeroReturnsSameValueForPositive() { + Long result = MathUtil.negativeToZero(20L); + assertEquals(20L, result); + } + + @Test + void isGreaterThanZeroReturnsTrueForPositive() { + assertTrue(MathUtil.isGreaterThanZero(5L)); + } + + @Test + void isLessThanZeroReturnsTrueForNegative() { + assertTrue(MathUtil.isLessThanZero(-5L)); + } + + @Test + void addHandlesNullValues() { + Long result = MathUtil.add(null, 10L); + assertEquals(10L, result); + } + + @Test + void addReturnsSumOfValues() { + Long result = MathUtil.add(10L, 20L); + assertEquals(30L, result); + } + + @Test + void subtractReturnsCorrectDifference() { + Long result = MathUtil.subtract(20L, 5L); + assertEquals(15L, result); + } + + @Test + void absReturnsPositiveValue() { + Long result = MathUtil.abs(-25L); + assertEquals(25L, result); + } + + @Test + void bigDecimalAddReturnsCorrectSum() { + BigDecimal result = MathUtil.add(new BigDecimal("10.5"), new BigDecimal("5.5"), new MathContext(10)); + + assertEquals(new BigDecimal("16.0"), result); + } + + @Test + void bigDecimalSubtractReturnsCorrectDifference() { + BigDecimal result = MathUtil.subtract(new BigDecimal("20"), new BigDecimal("5"), new MathContext(10)); + + assertEquals(new BigDecimal("15"), result); + } + + @Test + void percentageOfCalculatesCorrectValue() { + BigDecimal value = new BigDecimal("200"); + BigDecimal percentage = new BigDecimal("10"); + + BigDecimal result = MathUtil.percentageOf(value, percentage, new MathContext(10)); + + assertEquals(0, result.compareTo(new BigDecimal("20"))); + } + + @Test + void percentageOfReturnsZeroWhenValueZero() { + BigDecimal result = MathUtil.percentageOf(BigDecimal.ZERO, new BigDecimal("10"), new MathContext(10)); + assertEquals(BigDecimal.ZERO, result); + } + + @Test + void stripTrailingZerosRemovesExtraZeros() { + BigDecimal value = new BigDecimal("10.5000"); + + BigDecimal result = MathUtil.stripTrailingZeros(value); + + assertEquals(new BigDecimal("10.5"), result); + } + + @Test + void stripTrailingZerosReturnsNullWhenInputNull() { + assertNull(MathUtil.stripTrailingZeros(null)); + } + +}