package testcases.bigDecimal; import java.math.BigDecimal; import org.testng.annotations.Test; import de.jpaw.bonaparte.core.BonaPortable; import de.jpaw.bonaparte.core.ByteArrayComposer; import de.jpaw.bonaparte.core.ByteArrayParser; import de.jpaw.bonaparte.core.CompactByteArrayComposer; import de.jpaw.bonaparte.core.CompactByteArrayParser; import de.jpaw.bonaparte.core.MessageParser; import de.jpaw.bonaparte.core.MessageParserException; import de.jpaw.bonaparte.core.ObjectValidationException; import de.jpaw.bonaparte.core.StringBuilderComposer; import de.jpaw.bonaparte.core.StringBuilderParser; import de.jpaw.bonaparte.pojos.bigdecimal.BDTest; import de.jpaw.bonaparte.pojos.bigdecimal.BDTestUnsigned; import de.jpaw.bonaparte.pojos.bigdecimal.BDTestWithAutoRounding; import de.jpaw.bonaparte.pojos.bigdecimal.BDTestWithAutoRounding2; import de.jpaw.bonaparte.pojos.bigdecimal.BDTestWithAutoRoundingAndScaling; import de.jpaw.util.ByteBuilder; /** test cases to see if overflow exception are done in the right cases. * Each test is done on 4 different BonaPortable classes (using Decimal with different flags, but same precision) and with 3 different parser / composers. * In total, 12 tests are done per external test case. */ public class TestBigDecimalOverflows { private void checkParsingException(MessageParser<MessageParserException> p, BigDecimal num, BonaPortable testClass, int parseException) throws Exception { // first, do the validation test try { BonaPortable o = p.readRecord(); if (parseException != 0) { // we should have had an exception throw new Exception("Expected a parsing exception for class " + testClass.ret$PQON() + " and value " + num.toPlainString() + " using " + p.getClass().getSimpleName()); } // now the result should be the same as the input if (!testClass.equals(o)) throw new Exception("Record successfully parsed, but contents is not the same for class " + testClass.ret$PQON() + " and value " + num.toPlainString()); } catch (MessageParserException mpe) { if (mpe.getErrorCode() != parseException) if (parseException == 0) throw new Exception("Parsing exception " + mpe.getErrorCode() + " thrown" + " for class " + testClass.ret$PQON() + " and value " + num.toPlainString() + " using " + p.getClass().getSimpleName()); else throw new Exception("Expected a parsing exception " + parseException + " for class " + testClass.ret$PQON() + " and value " + num.toPlainString() + ", but got " + mpe.getErrorCode() + " using " + p.getClass().getSimpleName()); } } private void checkOverflow(BigDecimal num, BonaPortable testClass, int parseException, int validationException) throws Exception { // first, do the validation test try { testClass.validate(); if (validationException != 0) { // we should have had an exception throw new Exception("Expected a validation exception for class " + testClass.ret$PQON() + " and value " + num.toPlainString()); } } catch (ObjectValidationException ve) { if (ve.getErrorCode() != validationException) if (validationException == 0) throw new Exception("Validation exception " + ve.getErrorCode() + " thrown" + " for class " + testClass.ret$PQON() + " and value " + num.toPlainString()); else throw new Exception("Expected a validation exception " + validationException + " for class " + testClass.ret$PQON() + " and value " + num.toPlainString() + ", but got " + ve.getErrorCode()); } // run serialization test for ByteArrayComposer ByteArrayComposer bac = new ByteArrayComposer(); bac.writeRecord(testClass); ByteArrayParser bap = new ByteArrayParser(bac.getBytes(), 0, -1); checkParsingException(bap, num, testClass, parseException); // run serialization test for CompactComposer CompactByteArrayComposer cbac = new CompactByteArrayComposer(new ByteBuilder(), false); cbac.writeRecord(testClass); CompactByteArrayParser cbap = new CompactByteArrayParser(cbac.getBuilder().getBytes(), 0, -1); checkParsingException(cbap, num, testClass, parseException); // run serialization test for StringBuilderComposer StringBuilder sb = new StringBuilder(); StringBuilderComposer sbc = new StringBuilderComposer(sb); sbc.writeRecord(testClass); StringBuilderParser sbp = new StringBuilderParser(sb, 0, -1); checkParsingException(sbp, num, testClass, parseException); } // test function. inputNumber is the string to test, // parseException is 0 if the parsing should be successful, else the expected error code, // validationException is 0 if the validation should be successful, else the expected error code // The test is run with all 3 test classes private void checkOverflow(String inputNumber, int parseException, int validationException) throws Exception { BigDecimal ref = new BigDecimal(inputNumber); checkOverflow(ref, new BDTest(ref), parseException, validationException); checkOverflow(ref, new BDTestWithAutoRounding(ref), parseException, validationException); checkOverflow(ref, new BDTestWithAutoRounding2(ref), parseException, validationException); checkOverflow(ref, new BDTestWithAutoRoundingAndScaling(ref), parseException, validationException); } @Test public void testOKNumber() throws Exception { checkOverflow("138712633456.6262", 0, 0); } @Test public void testNegativeNumber() throws Exception { checkOverflow("-138712633456.6262", 0, 0); } @Test public void testOKFractionalNumber() throws Exception { checkOverflow("138712633456.62620000000", 0, 0); } @Test public void testTooManyFractionalNumber() throws Exception { BigDecimal ref = new BigDecimal("138712633456.6262123213"); checkOverflow(ref, new BDTest(ref), MessageParserException.TOO_MANY_DECIMALS, ObjectValidationException.TOO_MANY_FRACTIONAL_DIGITS); } @Test public void testTooManyDigitsNumber() throws Exception { checkOverflow("1387132633456.626", MessageParserException.TOO_MANY_DIGITS, ObjectValidationException.TOO_MANY_DIGITS); } @Test public void testNegNOKNumber() throws Exception { BigDecimal ref = new BigDecimal("-13856.626"); checkOverflow(ref, new BDTestUnsigned(ref), MessageParserException.SUPERFLUOUS_SIGN, ObjectValidationException.NO_NEGATIVE_ALLOWED); } }