Skip to content

Commit bef96ba

Browse files
authored
Java hackathon 1 (#7448)
* PHP Updates for Dockerfile and formatted output according to the new schema * Changes the testing flag in the Dockerfile * Removes output.txt from the repo * Added Kotlin Dockerfile changes and run_tests.py script * Adds Java Dockerfile changes and java run_tests.py script
1 parent f264d37 commit bef96ba

File tree

2 files changed

+239
-14
lines changed

2 files changed

+239
-14
lines changed

javav2/Dockerfile

+17-14
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
# syntax=docker/dockerfile:1
2-
FROM maven:latest
1+
# Use Python with Java and Git preinstalled
2+
FROM maven:3.9.4-eclipse-temurin-21 AS build
33

4-
# Update image
5-
RUN apt-get update && \
6-
apt-get upgrade -y && \
7-
apt-get clean && \
8-
rm -rf /var/lib/apt/lists/*
4+
# Silence all apt-get output and install Python, pip, git, etc.
5+
RUN apt-get update -qq && \
6+
DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \
7+
python3 python3-pip git curl vim less ca-certificates \
8+
> /dev/null 2>&1 && \
9+
apt-get clean && rm -rf /var/lib/apt/lists/*
910

10-
# Copy source code
11-
COPY . /javav2
11+
# Install boto3 quietly using pip
12+
RUN pip3 install --quiet --no-cache-dir boto3 > /dev/null 2>&1
1213

13-
# Set non-root user
14-
RUN useradd -m automation && \
15-
chown -R automation:automation /javav2
16-
USER automation:automation
14+
# Set workdir
15+
WORKDIR /app
1716

18-
CMD ["/javav2/run_tests.sh"]
17+
# Copy Python script into container
18+
COPY run_tests.py .
19+
20+
# Run Python script on container start
21+
CMD ["python3", "run_tests.py"]

javav2/run_tests.py

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
import subprocess
2+
import os
3+
import sys
4+
import re
5+
import time
6+
import uuid
7+
from datetime import datetime
8+
9+
import boto3
10+
from botocore.exceptions import ClientError
11+
12+
# Configuration
13+
GIT_REPO = "https://github.com/awsdocs/aws-doc-sdk-examples.git"
14+
CLONE_DIR = "/app/aws-doc-sdk-examples"
15+
ROOT_TEST_DIR = "javav2/example_code"
16+
17+
# Initialize DynamoDB client
18+
# dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
19+
FAILURE_TABLE = "TestFailures"
20+
SUMMARY_TABLE = "TestRunSummaries"
21+
22+
def run_command(cmd, cwd=None):
23+
# print(f"Running: {' '.join(cmd)}")
24+
result = subprocess.run(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
25+
# print(result.stdout)
26+
return result.returncode, result.stdout
27+
28+
def clone_repo():
29+
if os.path.exists(CLONE_DIR):
30+
# print("Repo already cloned.")
31+
return
32+
result = run_command(["git", "clone", GIT_REPO, CLONE_DIR])
33+
if result[0] != 0:
34+
sys.exit("❌ Failed to clone repo.")
35+
36+
def parse_test_results(output):
37+
passed = failed = skipped = 0
38+
match = re.search(r"Tests run: (\d+), Failures: (\d+), Errors: (\d+), Skipped: (\d+)", output)
39+
if match:
40+
tests_run = int(match.group(1))
41+
failures = int(match.group(2))
42+
errors = int(match.group(3))
43+
skipped = int(match.group(4))
44+
passed = tests_run - (failures + errors + skipped)
45+
return passed, failures + errors, skipped
46+
47+
def has_integration_tests(path):
48+
for root, _, files in os.walk(path):
49+
for file in files:
50+
if file.endswith(".java"):
51+
with open(os.path.join(root, file), encoding="utf-8") as f:
52+
content = f.read()
53+
if "@Test" in content and '@Tag("IntegrationTest")' in content:
54+
return True
55+
return False
56+
57+
def log_failure_to_dynamodb(service_name, test_path, output, run_id):
58+
# table = dynamodb.Table(FAILURE_TABLE)
59+
timestamp = datetime.utcnow().isoformat()
60+
61+
# Extract failure/error details
62+
error_summary = "Unknown error"
63+
match = re.search(r"(Tests run: .*?)(\n.*?at .*?Exception.*?)\n", output, re.DOTALL)
64+
if match:
65+
error_summary = match.group(2).strip()
66+
else:
67+
error_lines = [line for line in output.splitlines() if "Exception" in line or "FAILURE" in line]
68+
if error_lines:
69+
error_summary = error_lines[-1].strip()
70+
71+
try:
72+
pass
73+
# table.put_item(
74+
# Item={
75+
# "RunId": run_id,
76+
# "ServiceName": service_name,
77+
# "Timestamp": timestamp,
78+
# "TestPath": test_path,
79+
# "ErrorSummary": error_summary
80+
# }
81+
# )
82+
# print(f"🗃️ Logged failure for {service_name} to DynamoDB with RunId: {run_id}.")
83+
except ClientError as e:
84+
print(f"❗ Failed to log test failure: {e}")
85+
86+
def run_maven_tests(service_path, run_id):
87+
# print(f"\n🔧 Testing: {service_path}")
88+
returncode, output = run_command(["mvn", "clean", "test", "-Dgroups=IntegrationTest"], cwd=service_path)
89+
passed, failed, skipped = parse_test_results(output)
90+
status = "✅ Passed" if failed == 0 else "❌ Failed"
91+
# print(f"📊 Result: {status} — Passed: {passed}, Failed: {failed}, Skipped: {skipped}")
92+
93+
if failed > 0:
94+
service_name = os.path.basename(service_path)
95+
log_failure_to_dynamodb(service_name, service_path, output, run_id)
96+
97+
return passed, failed, skipped
98+
99+
def log_test_run_summary(run_id, tested_services, total_passed, total_failed, total_skipped, elapsed_seconds):
100+
# summary_table = dynamodb.Table(SUMMARY_TABLE)
101+
timestamp = datetime.utcnow().isoformat()
102+
103+
try:
104+
pass
105+
# summary_table.put_item(
106+
# Item={
107+
# "RunId": run_id,
108+
# "Timestamp": timestamp,
109+
# "ServicesTested": tested_services,
110+
# "TotalPassed": total_passed,
111+
# "TotalFailed": total_failed,
112+
# "TotalSkipped": total_skipped,
113+
# "TotalTimeSeconds": int(elapsed_seconds),
114+
# "Language": "Java"
115+
# }
116+
# )
117+
# print(f"🗃️ Test run summary logged to DynamoDB with RunId: {run_id}")
118+
except ClientError as e:
119+
pass
120+
# print(f"❗ Failed to log test summary: {e}")
121+
122+
def write_language_test_stats(language: str, total_tests: int, passed_tests: int):
123+
"""
124+
Write test statistics to the LanguageTestStats DynamoDB table.
125+
126+
Parameters:
127+
language (str): Programming language name (e.g., "Kotlin").
128+
total_tests (int): Total number of tests run.
129+
passed_tests (int): Number of tests that passed.
130+
"""
131+
pass_rate = (passed_tests / total_tests) * 100 if total_tests > 0 else 0
132+
133+
# dynamodb = boto3.client("dynamodb")
134+
135+
item = {
136+
'Language': {'S': language},
137+
'TotalTests': {'N': str(total_tests)},
138+
'PassedTests': {'N': str(passed_tests)},
139+
'PassRate': {'N': str(round(pass_rate, 2))}
140+
}
141+
142+
# try:
143+
# dynamodb.put_item(
144+
# TableName="LanguageTestStats",
145+
# Item=item
146+
# )
147+
# print(f"✅ Wrote stats for {language}: {passed_tests}/{total_tests} passed ({pass_rate:.2f}%)")
148+
# except ClientError as e:
149+
# print(f"❌ Failed to write stats for {language} to DynamoDB: {e}")
150+
151+
152+
def main():
153+
print("start of main")
154+
clone_repo()
155+
print("after clone")
156+
157+
total_passed = total_failed = total_skipped = 0
158+
tested_services = 0
159+
start_time = time.time()
160+
run_id = str(uuid.uuid4()) # Generate RunId at the beginning
161+
162+
root_test_path = os.path.join(CLONE_DIR, ROOT_TEST_DIR)
163+
service_dirs = sorted(
164+
[os.path.join(root_test_path, d) for d in os.listdir(root_test_path) if os.path.isdir(os.path.join(root_test_path, d))],
165+
key=lambda path: os.path.basename(path).lower()
166+
)
167+
168+
print("starting service loop")
169+
current = 0
170+
max = 1
171+
for service_path in service_dirs:
172+
if os.path.exists(os.path.join(service_path, "pom.xml")) and has_integration_tests(service_path):
173+
if current >= max:
174+
break
175+
current += 1
176+
passed, failed, skipped = run_maven_tests(service_path, run_id)
177+
total_passed += passed
178+
total_failed += failed
179+
total_skipped += skipped
180+
tested_services += 1
181+
print("end of service loop")
182+
elapsed = time.time() - start_time
183+
# print("\n===== ✅ Final Test Summary =====")
184+
# print(f"Services Tested: {tested_services}")
185+
# print(f"Total Tests Passed: {total_passed}")
186+
# print(f"Total Tests Failed: {total_failed}")
187+
# print(f"Total Tests Skipped: {total_skipped}")
188+
# print(f"Total Time: {int(elapsed // 60)} min {int(elapsed % 60)} sec")
189+
190+
print(
191+
{
192+
"schema-version": "0.0.1",
193+
"results": {
194+
"tool": "gradle",
195+
"summary": {
196+
"tests": tested_services,
197+
"passed": total_passed,
198+
"failed": total_failed,
199+
"skipped": total_skipped,
200+
"start_time": 0,
201+
"stop_time": int(elapsed)
202+
},
203+
"tests": [
204+
{
205+
"name": "test 1",
206+
"status": "failed",
207+
"duration": int(elapsed),
208+
"message": "apigateway",
209+
"log": "probably something to do with credentials"
210+
}
211+
]
212+
}
213+
})
214+
215+
# 🪪 Log to DynamoDB at the END of all testing
216+
log_test_run_summary(run_id, tested_services, total_passed, total_failed, total_skipped, elapsed)
217+
218+
total = total_passed + total_failed
219+
write_language_test_stats("Java", total, total_passed)
220+
221+
if __name__ == "__main__":
222+
main()

0 commit comments

Comments
 (0)