diff --git a/src/main/java/algorithms/sprint2/Calculator.java b/src/main/java/algorithms/sprint2/Calculator.java index 5f1da48..0a5ad1c 100644 --- a/src/main/java/algorithms/sprint2/Calculator.java +++ b/src/main/java/algorithms/sprint2/Calculator.java @@ -45,9 +45,16 @@ private static int eval(FastIn in) throws IOException { if (t.length() == 1) { char op = t.charAt(0); if (op == '+' || op == '-' || op == '*' || op == '/') { + if (st.size() < 2) { + throw new IllegalArgumentException("Operator requires two operands: " + op); + } int b = st.pop(); int a = st.pop(); + if (op == '/' && b == 0) { + throw new IllegalArgumentException("Division by zero"); + } + int r; if (op == '+') { r = a + b; @@ -64,9 +71,16 @@ private static int eval(FastIn in) throws IOException { } } - st.push(parseInt(t)); + try { + st.push(parseInt(t)); + } catch (NumberFormatException exception) { + throw new IllegalArgumentException("Invalid token: " + t, exception); + } } + if (st.size() != 1) { + throw new IllegalArgumentException("Expression must produce exactly one result"); + } return st.peek(); } @@ -74,7 +88,13 @@ private static void run() throws Exception { FastIn in = new FastIn(System.in); FastOut out = new FastOut(System.out); - int ans = eval(in); + final int ans; + try { + ans = eval(in); + } catch (IllegalArgumentException exception) { + System.err.println("Invalid expression: " + exception.getMessage()); + return; + } out.writeInt(ans); out.writeByte('\n'); diff --git a/src/test/java/algorithms/AlgorithmCliTest.java b/src/test/java/algorithms/AlgorithmCliTest.java index 0da7388..4dc06af 100644 --- a/src/test/java/algorithms/AlgorithmCliTest.java +++ b/src/test/java/algorithms/AlgorithmCliTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; @Tag("integration") class AlgorithmCliTest { @@ -50,6 +51,12 @@ void distancesRunReadsAndWritesContestFiles() throws Exception { } } + @ParameterizedTest + @ValueSource(strings = {"+", "", "1 0 /", "abc", "1 2"}) + void calculatorRejectsMalformedExpressionsWithoutThrowing(String input) throws Exception { + assertEquals("", invokeWithStdio("algorithms.sprint2.Calculator", "run", input)); + } + private static Stream stdioCases() { return Stream.of( arguments("algorithms.sprint0.SlidingAverage", "main",