Skip to content

Commit 3857270

Browse files
authored
Switch CI Device tests to DeviceRunner (#4092)
* Simplify DeviceRunner sample sources * Fix DeviceRunner integration for local builds * Replace DeviceRunner tests with Codename One compliant APIs * Avoid regex sanitization in DeviceRunner helper * Use CLDC-safe string helpers in DeviceRunner * Restore lambdas and CLDC-safe stack traces * Guard DeviceRunner EDT usage and locate iOS simulator app * Fix CN1SS chunk parsing and simulator destination handling * Fix CN1SS base64 emission and improve simulator selection * Improve browser test readiness and simulator selection * Fix BrowserComponent load listener for DeviceRunner * Harden iOS simulator launch and BrowserComponent test * Simplify iOS destination parsing without awk * Refine iOS simulator destination handling * Testing changes * Fixed truncated lines * Tried to fix Android/iOS comment editing logic * Fixed comment posting logic * Updated screenshot process to use native screenshots * Fixed iOS build pom generation * Fixed compile issue * Added device screenshots with known bug Missing browser component behavior in the new model.
1 parent b958063 commit 3857270

18 files changed

+1056
-444
lines changed

scripts/README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,26 @@ workflows to build and validate Codename One ports.
1212
- `build-android-app.sh` / `build-ios-app.sh` – generate a "Hello Codename One"
1313
sample application and build it against the freshly compiled port.
1414
- `run-android-instrumentation-tests.sh` – launches the Android emulator,
15-
executes instrumentation tests, and prepares screenshot reports for pull
16-
requests.
15+
drives the Codename One DeviceRunner suite, and prepares screenshot
16+
reports for pull requests.
17+
- `run-ios-ui-tests.sh` – runs the Codename One DeviceRunner suite on the iOS
18+
simulator and emits matching screenshot reports.
1719

1820
## Subdirectories
1921

20-
- `android/`Python helpers, baseline screenshots, and utilities that power
21-
the Android instrumentation test workflow.
22-
- `android/lib/`library-style Python modules shared across Android
23-
automation scripts.
22+
- `android/`Java helpers, baseline screenshots, and utilities that power the
23+
Android DeviceRunner test workflow.
24+
- `android/lib/`standalone Java sources invoked directly by the shell
25+
scripts for Gradle patching and similar tasks.
2426
- `android/tests/` – command-line tools used by CI for processing screenshots
2527
and posting feedback to pull requests.
2628
- `android/screenshots/` – reference images used when comparing emulator
2729
output.
28-
- `templates/` – code templates consumed by the sample app builders.
30+
- `ios/` – Helpers and screenshot baselines used by the iOS DeviceRunner
31+
workflow.
32+
- `device-runner-app/` – Java sources for the shared sample application and its
33+
DeviceRunner UI tests.
2934

3035
These scripts are designed so that shell logic focuses on orchestration, while
31-
Python modules encapsulate the heavier data processing steps. This separation
32-
keeps the entry points easy to follow and simplifies maintenance.
36+
small Java utilities encapsulate the heavier data processing steps. This
37+
separation keeps the entry points easy to follow and simplifies maintenance.
-9.56 KB
Loading
-103 Bytes
Loading

scripts/android/tests/Cn1ssChunkTools.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class Cn1ssChunkTools {
1414
private static final String DEFAULT_TEST_NAME = "default";
1515
private static final String DEFAULT_CHANNEL = "";
1616
private static final Pattern CHUNK_PATTERN = Pattern.compile(
17-
"CN1SS(?:(?<channel>[A-Z]+))?:(?:(?<test>[A-Za-z0-9_.-]+):)?(?<index>\\d{6}):(?<payload>.*)");
17+
"CN1SS(?:(?<channel>[A-Z]+))?:(?:(?<test>[A-Za-z0-9_.-]+):)?(?<index>\\d{6,}):(?<payload>.*)");
1818

1919
public static void main(String[] args) throws Exception {
2020
if (args.length == 0) {

scripts/android/tests/PostPrComment.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,28 @@ private static String readStream(java.io.InputStream stream) throws IOException
381381
}
382382

383383
private static AttachmentReplacement replaceAttachments(String body, Map<String, String> urls) {
384+
// Build a case-insensitive lookup alongside the original map
385+
Map<String, String> urlsCI = new HashMap<>();
386+
for (Map.Entry<String, String> e : urls.entrySet()) {
387+
if (e.getKey() != null && e.getValue() != null) {
388+
urlsCI.put(e.getKey().toLowerCase(), e.getValue());
389+
}
390+
}
391+
384392
Pattern pattern = Pattern.compile("\\(attachment:([^\\)]+)\\)");
385393
Matcher matcher = pattern.matcher(body);
386394
StringBuffer sb = new StringBuffer();
387395
List<String> missing = new ArrayList<>();
388396
while (matcher.find()) {
389397
String name = matcher.group(1);
398+
if (name != null) {
399+
name = name.trim();
400+
}
390401
String url = urls.get(name);
402+
if (url == null && name != null) {
403+
// try case-insensitive match
404+
url = urlsCI.get(name.toLowerCase());
405+
}
391406
if (url != null) {
392407
matcher.appendReplacement(sb, Matcher.quoteReplacement("(" + url + ")"));
393408
} else {

scripts/build-android-app.sh

Lines changed: 36 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ rm -rf "$WORK_DIR"; mkdir -p "$WORK_DIR"
8282

8383
GROUP_ID="com.codenameone.examples"
8484
ARTIFACT_ID="hello-codenameone"
85+
PACKAGE_NAME="com.codenameone.examples.hellocodenameone"
8586
MAIN_NAME="HelloCodenameOne"
8687

8788
SOURCE_PROJECT="$REPO_ROOT/Samples/SampleProjectTemplate"
@@ -204,48 +205,49 @@ SETTINGS_FILE="$APP_DIR/common/codenameone_settings.properties"
204205
echo "codename1.arg.android.useAndroidX=true" >> "$SETTINGS_FILE"
205206
[ -f "$SETTINGS_FILE" ] || { ba_log "codenameone_settings.properties not found at $SETTINGS_FILE" >&2; exit 1; }
206207

207-
# --- Read settings ---
208-
read_prop() { grep -E "^$1=" "$SETTINGS_FILE" | head -n1 | cut -d'=' -f2- | sed 's/^[[:space:]]*//'; }
209-
210-
PACKAGE_NAME="$(read_prop 'codename1.packageName' || true)"
211-
CURRENT_MAIN_NAME="$(read_prop 'codename1.mainName' || true)"
212-
213-
if [ -z "$PACKAGE_NAME" ]; then
214-
PACKAGE_NAME="$GROUP_ID"
215-
ba_log "Package name not found in settings. Falling back to groupId $PACKAGE_NAME"
216-
fi
217-
if [ -z "$CURRENT_MAIN_NAME" ]; then
218-
CURRENT_MAIN_NAME="$MAIN_NAME"
219-
ba_log "Main class name not found in settings. Falling back to target $CURRENT_MAIN_NAME"
220-
fi
208+
set_prop() {
209+
local key="$1" value="$2"
210+
if grep -q "^${key}=" "$SETTINGS_FILE"; then
211+
if sed --version >/dev/null 2>&1; then
212+
sed -i -E "s|^${key}=.*$|${key}=${value}|" "$SETTINGS_FILE"
213+
else
214+
sed -i '' -E "s|^${key}=.*$|${key}=${value}|" "$SETTINGS_FILE"
215+
fi
216+
else
217+
printf '\n%s=%s\n' "$key" "$value" >> "$SETTINGS_FILE"
218+
fi
219+
}
221220

222-
# --- Generate Java from external template ---
221+
# --- Install Codename One application sources ---
223222
PACKAGE_PATH="${PACKAGE_NAME//.//}"
224223
JAVA_DIR="$APP_DIR/common/src/main/java/${PACKAGE_PATH}"
225224
mkdir -p "$JAVA_DIR"
226-
MAIN_FILE="$JAVA_DIR/${MAIN_NAME}.java"
227-
228-
TEMPLATE="$SCRIPT_DIR/templates/HelloCodenameOne.java.tmpl"
229-
if [ ! -f "$TEMPLATE" ]; then
230-
ba_log "Template not found: $TEMPLATE" >&2
225+
MAIN_FILE_SOURCE="$SCRIPT_DIR/device-runner-app/main/${MAIN_NAME}.java"
226+
if [ ! -f "$MAIN_FILE_SOURCE" ]; then
227+
ba_log "Sample application source not found: $MAIN_FILE_SOURCE" >&2
231228
exit 1
232229
fi
230+
cp "$MAIN_FILE_SOURCE" "$JAVA_DIR/${MAIN_NAME}.java"
233231

234-
sed -e "s|@PACKAGE@|$PACKAGE_NAME|g" \
235-
-e "s|@MAIN_NAME@|$MAIN_NAME|g" \
236-
"$TEMPLATE" > "$MAIN_FILE"
237-
238-
# --- Ensure codename1.mainName is set ---
239-
ba_log "Setting codename1.mainName to $MAIN_NAME"
240-
if grep -q '^codename1.mainName=' "$SETTINGS_FILE"; then
241-
# GNU sed in CI: in-place edit without backup
242-
sed -E -i 's|^codename1\.mainName=.*$|codename1.mainName='"$MAIN_NAME"'|' "$SETTINGS_FILE"
243-
else
244-
printf '\ncodename1.mainName=%s\n' "$MAIN_NAME" >> "$SETTINGS_FILE"
245-
fi
232+
ba_log "Setting Codename One application metadata"
233+
set_prop "codename1.packageName" "$PACKAGE_NAME"
234+
set_prop "codename1.mainName" "$MAIN_NAME"
235+
# DeviceRunner integration is handled inside the copied sources, so unit test
236+
# build mode is not required (and is unsupported for local Android builds).
246237
# Ensure trailing newline
247238
tail -c1 "$SETTINGS_FILE" | read -r _ || echo >> "$SETTINGS_FILE"
248239

240+
# --- Install DeviceRunner UI tests ---
241+
TEST_SOURCE_DIR="$SCRIPT_DIR/device-runner-app/tests"
242+
TEST_JAVA_DIR="$APP_DIR/common/src/main/java/${PACKAGE_PATH}/tests"
243+
mkdir -p "$TEST_JAVA_DIR"
244+
if [ ! -d "$TEST_SOURCE_DIR" ]; then
245+
ba_log "DeviceRunner test sources not found: $TEST_SOURCE_DIR" >&2
246+
exit 1
247+
fi
248+
cp "$TEST_SOURCE_DIR"/*.java "$TEST_JAVA_DIR"/
249+
ba_log "Installed DeviceRunner UI tests in $TEST_JAVA_DIR"
250+
249251
# --- Normalize Codename One versions (use Maven Versions Plugin) ---
250252
ba_log "Normalizing Codename One Maven coordinates to $CN1_VERSION"
251253

@@ -266,7 +268,7 @@ if [ -z "$GRADLE_PROJECT_DIR" ]; then
266268
exit 1
267269
fi
268270

269-
ba_log "Configuring instrumentation test sources in $GRADLE_PROJECT_DIR"
271+
ba_log "Normalizing Android Gradle project in $GRADLE_PROJECT_DIR"
270272

271273
# Ensure AndroidX flags in gradle.properties
272274
# --- BEGIN: robust Gradle patch for AndroidX tests ---
@@ -301,30 +303,6 @@ echo "----- app/build.gradle tail -----"
301303
tail -n 80 "$APP_BUILD_GRADLE" | sed 's/^/| /'
302304
echo "---------------------------------"
303305

304-
TEST_SRC_DIR="$GRADLE_PROJECT_DIR/app/src/androidTest/java/${PACKAGE_PATH}"
305-
mkdir -p "$TEST_SRC_DIR"
306-
TEST_CLASS="$TEST_SRC_DIR/HelloCodenameOneInstrumentedTest.java"
307-
TEST_TEMPLATE="$SCRIPT_DIR/android/tests/HelloCodenameOneInstrumentedTest.java"
308-
309-
if [ ! -f "$TEST_TEMPLATE" ]; then
310-
ba_log "Missing instrumentation test template: $TEST_TEMPLATE" >&2
311-
exit 1
312-
fi
313-
314-
sed "s|@PACKAGE@|$PACKAGE_NAME|g" "$TEST_TEMPLATE" > "$TEST_CLASS"
315-
ba_log "Created instrumentation test at $TEST_CLASS"
316-
317-
DEFAULT_ANDROID_TEST="$GRADLE_PROJECT_DIR/app/src/androidTest/java/com/example/myapplication2/ExampleInstrumentedTest.java"
318-
if [ -f "$DEFAULT_ANDROID_TEST" ]; then
319-
rm -f "$DEFAULT_ANDROID_TEST"
320-
ba_log "Removed default instrumentation stub at $DEFAULT_ANDROID_TEST"
321-
DEFAULT_ANDROID_TEST_DIR="$(dirname "$DEFAULT_ANDROID_TEST")"
322-
DEFAULT_ANDROID_TEST_PARENT="$(dirname "$DEFAULT_ANDROID_TEST_DIR")"
323-
rmdir "$DEFAULT_ANDROID_TEST_DIR" 2>/dev/null || true
324-
rmdir "$DEFAULT_ANDROID_TEST_PARENT" 2>/dev/null || true
325-
rmdir "$(dirname "$DEFAULT_ANDROID_TEST_PARENT")" 2>/dev/null || true
326-
fi
327-
328306
ba_log "Invoking Gradle build in $GRADLE_PROJECT_DIR"
329307
chmod +x "$GRADLE_PROJECT_DIR/gradlew"
330308
ORIGINAL_JAVA_HOME="$JAVA_HOME"
@@ -348,7 +326,7 @@ if [ -n "${GITHUB_OUTPUT:-}" ]; then
348326
{
349327
echo "gradle_project_dir=$GRADLE_PROJECT_DIR"
350328
echo "apk_path=$APK_PATH"
351-
echo "instrumentation_test_class=$PACKAGE_NAME.HelloCodenameOneInstrumentedTest"
329+
echo "package_name=$PACKAGE_NAME"
352330
} >> "$GITHUB_OUTPUT"
353331
ba_log "Published GitHub Actions outputs for downstream steps"
354332
fi

0 commit comments

Comments
 (0)