-
Notifications
You must be signed in to change notification settings - Fork 0
/
ExceptionsTest.java
145 lines (132 loc) · 5.84 KB
/
ExceptionsTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package expression.exceptions;
import expression.parser.Either;
import expression.TripleExpression;
import expression.Variable;
import expression.parser.ParserTest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.LongBinaryOperator;
/**
* @author Niyaz Nigmatullin
* @author Georgiy Korneev ([email protected])
*/
public class ExceptionsTest extends ParserTest {
private final static int D = 5;
private final static List<Integer> OVERFLOW_VALUES = new ArrayList<>();
private final char[] CHARS = "AZ+-*%()[]<>".toCharArray();
public static final Variable VX = new Variable("x");
public static final Variable VY = new Variable("y");
public static final Reason OVERFLOW = new Reason("Overflow");
static {
addRange(OVERFLOW_VALUES, D, Integer.MIN_VALUE + D);
addRange(OVERFLOW_VALUES, D, Integer.MIN_VALUE / 2);
addRange(OVERFLOW_VALUES, D, (int) -Math.sqrt(Integer.MAX_VALUE));
addRange(OVERFLOW_VALUES, D, 0);
addRange(OVERFLOW_VALUES, D, (int) Math.sqrt(Integer.MAX_VALUE));
addRange(OVERFLOW_VALUES, D, Integer.MAX_VALUE / 2);
addRange(OVERFLOW_VALUES, D, Integer.MAX_VALUE - D);
}
protected final List<Op<String>> parsingTest = new ArrayList<>(Arrays.asList(
op("No first argument", "* y * z"),
op("No middle argument", "x * * z"),
op("No last argument", "x * y * "),
op("No first argument'", "1 + (* y * z) + 2"),
op("No middle argument'", "1 + (x * / 9) + 3"),
op("No last argument'", "1 + (x * y - ) + 3"),
op("No opening parenthesis", "x * y)"),
op("No closing parenthesis", "(x * y"),
op("Start symbol", "@x * y"),
op("Middle symbol", "x @ * y"),
op("End symbol", "x * y@"),
op("Constant overflow 1", Integer.MIN_VALUE - 1L + ""),
op("Constant overflow 2", Integer.MAX_VALUE + 1L + "")
));
public static void main(final String[] args) {
new ExceptionsTest().run();
}
private void testParsingErrors() {
for (final Op<String> op : parsingTest) {
try {
new ExpressionParser().parse(op.f);
assert false : "Successfully parsed " + op.f;
} catch (final Exception e) {
System.out.format("%-30s %s%n", op.name, e.getClass().getSimpleName() + ": " + e.getMessage());
}
}
}
protected void testOverflow() {
testOverflow((a, b) -> a + b, "+", new CheckedAdd(VX, VY));
testOverflow((a, b) -> a - b, "-", new CheckedSubtract(VX, VY));
testOverflow((a, b) -> a * b, "*", new CheckedMultiply(VX, VY));
testOverflow((a, b) -> b == 0 ? Long.MAX_VALUE : a / b, "/", new CheckedDivide(VX, VY));
testOverflow((a, b) -> -b, "<- ignore first argument, unary -", new CheckedNegate(VY));
}
protected void testOverflow(final LongBinaryOperator f, final String op, final TripleExpression expression) {
for (final int a : OVERFLOW_VALUES) {
for (final int b : OVERFLOW_VALUES) {
final long expected = f.applyAsLong(a, b);
try {
final int actual = expression.evaluate(a, b, 0);
assert actual == expected : a + " " + op + " " + b + " == " + actual;
} catch (final Exception e) {
if (Integer.MIN_VALUE <= expected && expected <= Integer.MAX_VALUE) {
throw new AssertionError("Unexpected error in " + a + " " + op + " " + b, e);
}
}
}
}
}
@Override
protected void test() {
testOverflow();
super.test();
testParsingErrors();
}
protected TripleExpression parse(final String expression, final boolean reparse) {
final Parser parser = new ExpressionParser();
if (expression.length() > 10) {
loop: for (final char ch : CHARS) {
for (int i = 0; i < 10; i++) {
final int index = 1 + randomInt(expression.length() - 2);
int pi = index - 1;
while (Character.isWhitespace(expression.charAt(pi))) {
pi--;
}
int ni = index;
while (Character.isWhitespace(expression.charAt(ni))) {
ni++;
}
final char pc = expression.charAt(pi);
final char nc = expression.charAt(ni);
if ("-(*".indexOf(nc) < 0 && nc != ch && pc != ch && !Character.isLetterOrDigit(nc)) {
final String input = expression.substring(0, index) + ch + expression.substring(index);
try {
counter.nextTest();
parser.parse(input);
throw new AssertionError("Parsing error expected for " + expression.substring(0, index) + "<ERROR_INSERTED -->" + ch + "<-- ERROR_INSERTED>" + expression.substring(index));
} catch (final Exception e) {
// Ok
counter.passed();
}
continue loop;
}
}
}
}
counter.nextTest();
try {
final TripleExpression parse = parser.parse(expression);
counter.passed();
return parse;
} catch (final Exception e) {
throw new AssertionError("Parser failed", e);
}
}
@Override
protected Either<Reason, Integer> lift(final long value) {
return value < Integer.MIN_VALUE || Integer.MAX_VALUE < value
? Either.left(OVERFLOW)
: super.lift(value);
}
}