From 842720a8c0eae06fc73a637cbcf5626d540821c6 Mon Sep 17 00:00:00 2001 From: Aviral Date: Wed, 17 Jun 2026 21:28:18 +0530 Subject: [PATCH 1/3] chore: upgrade Java Maven stack to Java 25 --- .hackerrank/merge_surefire_to_unit_xml.py | 76 +++++++++++++++++++++++ .hackerrank/run-tests-with-unit-xml.sh | 15 +++++ hackerrank.yml | 5 +- pom.xml | 24 ++++--- 4 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 .hackerrank/merge_surefire_to_unit_xml.py create mode 100755 .hackerrank/run-tests-with-unit-xml.sh diff --git a/.hackerrank/merge_surefire_to_unit_xml.py b/.hackerrank/merge_surefire_to_unit_xml.py new file mode 100644 index 0000000..7ec5806 --- /dev/null +++ b/.hackerrank/merge_surefire_to_unit_xml.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import glob +import shutil +import sys +import xml.etree.ElementTree as ET +from pathlib import Path + + +def as_int(value: str | None) -> int: + try: + return int(value or "0") + except ValueError: + return 0 + + +def as_float(value: str | None) -> float: + try: + return float(value or "0") + except ValueError: + return 0.0 + + +def empty_report(message: str) -> ET.ElementTree: + suites = ET.Element("testsuites", {"name": "maven", "tests": "1", "failures": "0", "errors": "1", "skipped": "0"}) + suite = ET.SubElement(suites, "testsuite", {"name": "report-generation", "tests": "1", "failures": "0", "errors": "1", "skipped": "0"}) + case = ET.SubElement(suite, "testcase", {"classname": "report-generation", "name": "surefire-report"}) + ET.SubElement(case, "error", {"message": message}).text = message + return ET.ElementTree(suites) + + +def main() -> int: + output = Path("unit.xml") + reports = sorted(Path(".").glob("target/surefire-reports/TEST-*.xml")) + reports += sorted(Path(".").glob("target/failsafe-reports/TEST-*.xml")) + valid = [] + for report in reports: + try: + tree = ET.parse(report) + except ET.ParseError: + continue + root = tree.getroot() + if root.tag in {"testsuite", "testsuites"}: + valid.append((report, root)) + + if not valid: + tree = empty_report("No Maven Surefire/Failsafe XML reports were generated.") + tree.write(output, encoding="utf-8", xml_declaration=True) + return 1 + + if len(valid) == 1 and valid[0][1].tag == "testsuite": + shutil.copyfile(valid[0][0], output) + return 0 + + suites = ET.Element("testsuites", {"name": "maven"}) + totals = {"tests": 0, "failures": 0, "errors": 0, "skipped": 0} + total_time = 0.0 + for _, root in valid: + children = [root] if root.tag == "testsuite" else list(root.findall("testsuite")) + for suite in children: + totals["tests"] += as_int(suite.get("tests")) + totals["failures"] += as_int(suite.get("failures")) + totals["errors"] += as_int(suite.get("errors")) + totals["skipped"] += as_int(suite.get("skipped")) + total_time += as_float(suite.get("time")) + suites.append(suite) + for key, value in totals.items(): + suites.set(key, str(value)) + suites.set("time", f"{total_time:.3f}") + ET.ElementTree(suites).write(output, encoding="utf-8", xml_declaration=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.hackerrank/run-tests-with-unit-xml.sh b/.hackerrank/run-tests-with-unit-xml.sh new file mode 100755 index 0000000..a5a7e39 --- /dev/null +++ b/.hackerrank/run-tests-with-unit-xml.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set +e +if [ "$#" -eq 0 ]; then + echo "Usage: $0 ''" >&2 + exit 2 +fi +rm -f unit.xml +bash -lc "$*" +status=$? +python3 .hackerrank/merge_surefire_to_unit_xml.py +merge_status=$? +if [ "$status" -eq 0 ] && [ "$merge_status" -ne 0 ]; then + exit "$merge_status" +fi +exit "$status" diff --git a/hackerrank.yml b/hackerrank.yml index 99c1daa..8f05abb 100644 --- a/hackerrank.yml +++ b/hackerrank.yml @@ -6,8 +6,9 @@ configuration: - src/test/* - generate-data.sh scoring: - command: mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh + command: bash .hackerrank/run-tests-with-unit-xml.sh 'mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh' files: + - unit.xml - reports/test_result.xml hidden_files_paths: - src/test/java/com/hackerrank/risk/PerformanceTest.java @@ -21,4 +22,4 @@ configuration: project_menu: run: mvn clean package -DskipTests && java -jar target/risk-engine-1.0.jar < sample-transactions.csv install: mvn clean install -DskipTests - test: mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh + test: bash .hackerrank/run-tests-with-unit-xml.sh 'mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh' diff --git a/pom.xml b/pom.xml index b4c2e8f..3472070 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,5 @@ - - + + 4.0.0 com.hackerrank @@ -14,17 +12,17 @@ UTF-8 - 21 - 21 + 25 + 25 5.9.3 - + 2525 org.junit.jupiter junit-jupiter - ${junit.version} + 6.0.1 test @@ -35,31 +33,31 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.15.0 21 21 - + 25 org.apache.maven.plugins maven-surefire-plugin - 3.0.0 + 3.5.6 **/*Test.java xml - + ${project.build.directory}/surefire-reportsfalse org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.2 From cbd053a1bd43eb8cd7b9849dac5939a99387229b Mon Sep 17 00:00:00 2001 From: Aviral Date: Wed, 17 Jun 2026 22:18:50 +0530 Subject: [PATCH 2/3] docs: add Java 25 README contract --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..78b4fec --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Adyen Risk Engine + +This Java Maven challenge is upgraded for Java 25. + +## Validation + +- Build and tests run with Maven on Java 25. +- HackerRank scoring generates `unit.xml` from Maven Surefire/Failsafe XML output through `.hackerrank/run-tests-with-unit-xml.sh`. +- Candidate-facing source, tests, and scoring entry points remain in the existing project layout. From 66c540ce9a14527401abf74c222c1e31451bf443 Mon Sep 17 00:00:00 2001 From: Aviral Date: Thu, 18 Jun 2026 01:39:57 +0530 Subject: [PATCH 3/3] fix: use surefire reports directly for scoring --- .hackerrank/merge_surefire_to_unit_xml.py | 76 ----------------------- .hackerrank/run-tests-with-unit-xml.sh | 15 ----- README.md | 1 - hackerrank.yml | 5 +- 4 files changed, 2 insertions(+), 95 deletions(-) delete mode 100644 .hackerrank/merge_surefire_to_unit_xml.py delete mode 100755 .hackerrank/run-tests-with-unit-xml.sh diff --git a/.hackerrank/merge_surefire_to_unit_xml.py b/.hackerrank/merge_surefire_to_unit_xml.py deleted file mode 100644 index 7ec5806..0000000 --- a/.hackerrank/merge_surefire_to_unit_xml.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations - -import glob -import shutil -import sys -import xml.etree.ElementTree as ET -from pathlib import Path - - -def as_int(value: str | None) -> int: - try: - return int(value or "0") - except ValueError: - return 0 - - -def as_float(value: str | None) -> float: - try: - return float(value or "0") - except ValueError: - return 0.0 - - -def empty_report(message: str) -> ET.ElementTree: - suites = ET.Element("testsuites", {"name": "maven", "tests": "1", "failures": "0", "errors": "1", "skipped": "0"}) - suite = ET.SubElement(suites, "testsuite", {"name": "report-generation", "tests": "1", "failures": "0", "errors": "1", "skipped": "0"}) - case = ET.SubElement(suite, "testcase", {"classname": "report-generation", "name": "surefire-report"}) - ET.SubElement(case, "error", {"message": message}).text = message - return ET.ElementTree(suites) - - -def main() -> int: - output = Path("unit.xml") - reports = sorted(Path(".").glob("target/surefire-reports/TEST-*.xml")) - reports += sorted(Path(".").glob("target/failsafe-reports/TEST-*.xml")) - valid = [] - for report in reports: - try: - tree = ET.parse(report) - except ET.ParseError: - continue - root = tree.getroot() - if root.tag in {"testsuite", "testsuites"}: - valid.append((report, root)) - - if not valid: - tree = empty_report("No Maven Surefire/Failsafe XML reports were generated.") - tree.write(output, encoding="utf-8", xml_declaration=True) - return 1 - - if len(valid) == 1 and valid[0][1].tag == "testsuite": - shutil.copyfile(valid[0][0], output) - return 0 - - suites = ET.Element("testsuites", {"name": "maven"}) - totals = {"tests": 0, "failures": 0, "errors": 0, "skipped": 0} - total_time = 0.0 - for _, root in valid: - children = [root] if root.tag == "testsuite" else list(root.findall("testsuite")) - for suite in children: - totals["tests"] += as_int(suite.get("tests")) - totals["failures"] += as_int(suite.get("failures")) - totals["errors"] += as_int(suite.get("errors")) - totals["skipped"] += as_int(suite.get("skipped")) - total_time += as_float(suite.get("time")) - suites.append(suite) - for key, value in totals.items(): - suites.set(key, str(value)) - suites.set("time", f"{total_time:.3f}") - ET.ElementTree(suites).write(output, encoding="utf-8", xml_declaration=True) - return 0 - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/.hackerrank/run-tests-with-unit-xml.sh b/.hackerrank/run-tests-with-unit-xml.sh deleted file mode 100755 index a5a7e39..0000000 --- a/.hackerrank/run-tests-with-unit-xml.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -set +e -if [ "$#" -eq 0 ]; then - echo "Usage: $0 ''" >&2 - exit 2 -fi -rm -f unit.xml -bash -lc "$*" -status=$? -python3 .hackerrank/merge_surefire_to_unit_xml.py -merge_status=$? -if [ "$status" -eq 0 ] && [ "$merge_status" -ne 0 ]; then - exit "$merge_status" -fi -exit "$status" diff --git a/README.md b/README.md index 78b4fec..960df97 100644 --- a/README.md +++ b/README.md @@ -5,5 +5,4 @@ This Java Maven challenge is upgraded for Java 25. ## Validation - Build and tests run with Maven on Java 25. -- HackerRank scoring generates `unit.xml` from Maven Surefire/Failsafe XML output through `.hackerrank/run-tests-with-unit-xml.sh`. - Candidate-facing source, tests, and scoring entry points remain in the existing project layout. diff --git a/hackerrank.yml b/hackerrank.yml index 8f05abb..99c1daa 100644 --- a/hackerrank.yml +++ b/hackerrank.yml @@ -6,9 +6,8 @@ configuration: - src/test/* - generate-data.sh scoring: - command: bash .hackerrank/run-tests-with-unit-xml.sh 'mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh' + command: mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh files: - - unit.xml - reports/test_result.xml hidden_files_paths: - src/test/java/com/hackerrank/risk/PerformanceTest.java @@ -22,4 +21,4 @@ configuration: project_menu: run: mvn clean package -DskipTests && java -jar target/risk-engine-1.0.jar < sample-transactions.csv install: mvn clean install -DskipTests - test: bash .hackerrank/run-tests-with-unit-xml.sh 'mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh' + test: mvn clean test -Dsurefire.reportFormat=xml; bash merge_test_reports.sh