From 6b801217f1601afb89f3a5138ed62293a54309d8 Mon Sep 17 00:00:00 2001 From: Andrei Ovcharenko Date: Fri, 31 Jul 2026 17:45:19 +0300 Subject: [PATCH] Harden Solution2 stdin handling --- .../java/algorithms/sprint1/Solution2.java | 50 ++++++++++++++++--- .../java/algorithms/AlgorithmCliTest.java | 17 +++++++ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/main/java/algorithms/sprint1/Solution2.java b/src/main/java/algorithms/sprint1/Solution2.java index 66bb225..acab909 100644 --- a/src/main/java/algorithms/sprint1/Solution2.java +++ b/src/main/java/algorithms/sprint1/Solution2.java @@ -5,10 +5,13 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.StringTokenizer; public class Solution2 { + private static final int MAX_LINE_COUNT = 1_000_000; + public static void solution(Node head) { StringBuilder output = new StringBuilder(); Node current = head; @@ -35,16 +38,47 @@ static void test() { } public static void main(String[] args) throws IOException { - StringBuilder outputBuffer = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); - int lineCount = parseInt(reader.readLine()); + int lineCount = readLineCount(reader); + PrintWriter writer = new PrintWriter(System.out, false, StandardCharsets.UTF_8); for (int i = 0; i < lineCount; ++i) { - StringTokenizer tokenizer = new StringTokenizer(reader.readLine()); - int firstValue = parseInt(tokenizer.nextToken()); - int secondValue = parseInt(tokenizer.nextToken()); - int result = firstValue + secondValue; - outputBuffer.append(result).append("\n"); + StringTokenizer tokenizer = new StringTokenizer(readInputLine(reader, i + 1)); + int firstValue = parseInt(nextToken(tokenizer, i + 1)); + int secondValue = parseInt(nextToken(tokenizer, i + 1)); + if (tokenizer.hasMoreTokens()) { + throw new IllegalArgumentException("Line " + (i + 1) + " must contain exactly two integers"); + } + int result = Math.addExact(firstValue, secondValue); + writer.println(result); + } + writer.println(); + writer.flush(); + } + + private static int readLineCount(BufferedReader reader) throws IOException { + String countLine = reader.readLine(); + if (countLine == null) { + throw new IllegalArgumentException("Missing line count"); + } + int lineCount = parseInt(countLine); + if (lineCount < 0 || lineCount > MAX_LINE_COUNT) { + throw new IllegalArgumentException("Line count must be between 0 and " + MAX_LINE_COUNT); + } + return lineCount; + } + + private static String readInputLine(BufferedReader reader, int lineNumber) throws IOException { + String inputLine = reader.readLine(); + if (inputLine == null) { + throw new IllegalArgumentException("Missing input line " + lineNumber); + } + return inputLine; + } + + private static String nextToken(StringTokenizer tokenizer, int lineNumber) { + if (!tokenizer.hasMoreTokens()) { + throw new IllegalArgumentException("Line " + lineNumber + " must contain exactly two integers"); } - System.out.println(outputBuffer); + return tokenizer.nextToken(); } } diff --git a/src/test/java/algorithms/AlgorithmCliTest.java b/src/test/java/algorithms/AlgorithmCliTest.java index 0da7388..d46a235 100644 --- a/src/test/java/algorithms/AlgorithmCliTest.java +++ b/src/test/java/algorithms/AlgorithmCliTest.java @@ -1,6 +1,7 @@ package algorithms; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.params.provider.Arguments.arguments; import java.io.ByteArrayInputStream; @@ -33,6 +34,22 @@ void stdioEntryPointProducesExpectedOutput( assertEquals(normalizeLines(expectedOutput), normalizeLines(invokeWithStdio(className, methodName, input))); } + @Test + void solution2RejectsMissingInputLine() { + assertThrows(IllegalArgumentException.class, () -> invokeWithStdio( + "algorithms.sprint1.Solution2", + "main", + "2%n1 2%n".formatted())); + } + + @Test + void solution2RejectsOversizedLineCount() { + assertThrows(IllegalArgumentException.class, () -> invokeWithStdio( + "algorithms.sprint1.Solution2", + "main", + "1000001%n".formatted())); + } + @Test void distancesRunReadsAndWritesContestFiles() throws Exception { Path input = Path.of("input.txt");