001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (license2)
004: * Initial Developer: H2 Group
005: */
006: package org.h2.test.unit;
007:
008: import java.math.BigInteger;
009: import java.sql.SQLException;
010: import java.util.ArrayList;
011: import java.util.Random;
012:
013: import org.h2.constant.SysProperties;
014: import org.h2.test.TestBase;
015: import org.h2.value.Value;
016: import org.h2.value.ValueString;
017:
018: /**
019: * Tests numeric overflow on various data types.
020: * Other than in Java, overflow is detected and an exception is thrown.
021: */
022: public class TestOverflow extends TestBase {
023:
024: public void test() throws Exception {
025: test(Value.BYTE, Byte.MIN_VALUE, Byte.MAX_VALUE);
026: test(Value.INT, Integer.MIN_VALUE, Integer.MAX_VALUE);
027: test(Value.LONG, Long.MIN_VALUE, Long.MAX_VALUE);
028: test(Value.SHORT, Short.MIN_VALUE, Short.MAX_VALUE);
029: }
030:
031: private ArrayList values;
032: private int type;
033: private BigInteger min, max;
034: private boolean successExpected;
035:
036: private void test(int type, long min, long max) throws Exception {
037: values = new ArrayList();
038: this .type = type;
039: this .min = new BigInteger("" + min);
040: this .max = new BigInteger("" + max);
041: add(0);
042: add(min);
043: add(max);
044: add(max - 1);
045: add(min + 1);
046: add(1);
047: add(-1);
048: Random random = new Random(1);
049: for (int i = 0; i < 40; i++) {
050: if (max > Integer.MAX_VALUE) {
051: add(random.nextLong());
052: } else {
053: add((random.nextBoolean() ? 1 : -1)
054: * random.nextInt((int) max));
055: }
056: }
057: for (int a = 0; a < values.size(); a++) {
058: for (int b = 0; b < values.size(); b++) {
059: Value va = (Value) values.get(a);
060: Value vb = (Value) values.get(b);
061: testValues(va, vb);
062: }
063: }
064: }
065:
066: void checkIfExpected(String a, String b) throws Exception {
067: if (successExpected) {
068: check(a, b);
069: }
070: }
071:
072: void onSuccess() throws Exception {
073: if (!successExpected && SysProperties.OVERFLOW_EXCEPTIONS) {
074: error();
075: }
076: }
077:
078: void onError() throws Exception {
079: if (successExpected) {
080: error();
081: }
082: }
083:
084: private void testValues(Value va, Value vb) throws Exception {
085: BigInteger a = new BigInteger(va.getString());
086: BigInteger b = new BigInteger(vb.getString());
087: successExpected = inRange(a.negate());
088: try {
089: checkIfExpected(va.negate().getString(), a.negate()
090: .toString());
091: onSuccess();
092: } catch (SQLException e) {
093: onError();
094: }
095: successExpected = inRange(a.add(b));
096: try {
097: checkIfExpected(va.add(vb).getString(), a.add(b).toString());
098: onSuccess();
099: } catch (SQLException e) {
100: onError();
101: }
102: successExpected = inRange(a.subtract(b));
103: try {
104: checkIfExpected(va.subtract(vb).getString(), a.subtract(b)
105: .toString());
106: onSuccess();
107: } catch (SQLException e) {
108: onError();
109: }
110: successExpected = inRange(a.multiply(b));
111: try {
112: checkIfExpected(va.multiply(vb).getString(), a.multiply(b)
113: .toString());
114: onSuccess();
115: } catch (SQLException e) {
116: onError();
117: }
118: }
119:
120: private boolean inRange(BigInteger v) {
121: return v.compareTo(min) >= 0 && v.compareTo(max) <= 0;
122: }
123:
124: private void add(long l) throws SQLException {
125: values.add(ValueString.get("" + l).convertTo(type));
126: }
127:
128: }
|