Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is MathUtil needed? There are already functions on BigInteger/BigDecimal for add/subtract/mulitply/divide...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR only adds unit tests for the existing MathUtil utility class. The implementation of MathUtil was already present in the codebase and is currently used in several parts of the project.

The goal of this PR is to improve test coverage and ensure the correctness of the helper methods already provided by MathUtil, especially around null handling, comparison helpers, and convenience wrappers used across the platform.

No changes were made to the implementation itself.

* 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));
}

}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Loading