Skip to content

Minimal and backend-only Maven projects, default from 7.0.275 - #5937

Merged
shai-almog merged 6 commits into
masterfrom
maven-minimal-layouts
Oct 3, 2026
Merged

shai-almog merged 6 commits into
masterfrom
maven-minimal-layouts

Conversation

@shai-almog

Copy link
Copy Markdown
Collaborator

Gradle projects got two shapes in #5922 that Maven lacked: a minimal tree with no per-OS modules, and a backend-only project. This brings both to Maven and makes them the default for new projects. The archetype switches over immediately. The Initializr switches once its plugin is 7.0.275 or newer, which happens automatically when update-cn1-version.sh bumps it.

The layouts

Before Now (default) Opt-in
App root + common + javase android ios javascript win linux + backend root + common -DplatformModules=all / "Include all platform modules"
App with backend (same as above) root + common + backend -DprojectType=app-with-backend
Backend only not available for Maven one module at the root -DprojectType=backend-only

-DplatformModules=all -DprojectType=app-with-backend reproduces the old layout exactly.

How a project with no platform modules builds

One rule decides it: a platform has a module of its own exactly when <root>/<platform>/pom.xml exists.

  • Module present: it does the work as it always has. common's stand-ins skip themselves, so a project that adds a module later never builds a platform twice.
  • Module absent: common does the work. common/pom.xml carries one shared fragment, scripts/initializr/common/src/main/resources/common-hosted-platform-profiles.xml, which the archetype and the Initializr both inject. It contains:
    • cn1-host-<platform> profiles, active on -Dcodename1.platform=<p> and a missing ../<p>/pom.xml (Maven ANDs the two). They bind cn1:build from common.
    • cn1-javase-natives, which compiles javase/src/main/java (plus cn1lib nativese sources and the desktop stub) into common/target/cn1-javase/classes. That is never target/classes, which every device build uploads, and it is outside the bytecode-compliance check.
    • The run, test and package profiles the javase module used to own: simulator, idea-simulator, debug-simulator, debug-eclipse, run-desktop, executable-jar, test and run-android. Each of their goals carries <hostedPlatform>, and each third-party execution reads the cn1.hosted.<p>.skip property those goals set.
  • The root pom: each module profile also requires <module>/pom.xml to exist. activeByDefault is dropped when there is no javase module, because Maven applies it even when the profile's own conditions fail.
  • Native code still lives in <platform>/src/main/.... cn1:generate-native-interfaces creates those directories with no pom.xml, and a build from common uploads them exactly as a module would package them.

New in the plugin:

  • HostedPlatforms and AbstractCN1Mojo.hostedPlatform.
  • The goals hosted-platform, compile-javase-natives and javase-executable-jar.
  • Hosting support in cn1:build, prepare-simulator-classpath, generate-desktop-app-wrapper, cn1:test, cn1:run, cn1:debug and cn1:simulator.
    • The forked simulator gets its classpath from a JDK argument file, because exec:exec's <classpath/> cannot be extended. The file also keeps long classpaths under the Windows command-line limit.
  • ProjectLayout gains hasPlatformModule, nativeResourcesDir and platformUploadDirs; the Gradle plugin now uses the shared platformUploadDirs.
  • A backend-only Maven project at the root is detected as MAVEN/BACKEND.

The version gate:

  • Before 7.0.275 the Initializr's Maven output is byte-identical to today's (checked against origin/master for every Maven and Gradle download), apart from the JUnit fix below and the agent-skill text.
  • A pom that uses the new goals fails at once on an older plugin, on the unknown hosted-platform / compile-javase-natives goal, rather than building nothing.
  • cn1:update refuses to move such a project below 7.0.275.
  • update-cn1-version.sh now fails if it did not rewrite CN1_PLUGIN_VERSION.

A pre-existing bug this fixes: JUnit tests never ran

Generated Maven apps advertise mvn test for JUnit 5 tests, but the root pom gives Surefire Codename One's stub provider, which returns no tests. A deliberately failing @Test passed the build in the full layout on master. The javase module, common.zip and the new common profile now also declare surefire-junit-platform, so JUnit tests run, a failing one fails the build, and -DskipTests still skips. Existing downloads change in this one respect.

How this was verified

New integration test maven/integration-tests/cn1app-minimal-layout-test.sh, in archetype-smoke.yml and all.sh. It generates a minimal app and a backend-only project and checks:

  • a native interface's stubs land with no pom.xml;
  • cn1:test and JUnit both reach a JavaSE native that only a JDK compiles;
  • the simulator argument file carries the natives;
  • the -Pexecutable-jar desktop jar has the right Main-Class, stub, natives, icons and native theme;
  • all six device targets stage from common with exactly their own native files, and no JavaSE classes reach the Android upload;
  • adding android/pom.xml moves the Android build into the module;
  • the backend-only project builds its router and entry point, packages to a native binary, and that binary answers /healthz.

Run locally against a fresh full install of the reactor:

  • Integration tests: cn1app-minimal-layout-test.sh (with CN1_BACKEND_PACKAGE_REQUIRED=1), cn1app-archetype-test.sh (full layout, including the native backend), cn1app-staged-jar-test.sh, and these integration scripts, which now pass the full-layout flags: build-hint-annotations-test.sh, cn1app-desktop-build-test.sh, initializr-roundtrip-test.sh, gradle-maven-parity-test.sh, gradle-migrate-test.sh and native-interfaces.sh.
  • Simulator launches: exactly one launch, from the right module, for cn1:run, -pl common cn1:run, and verify -Psimulator with and without -Dcodename1.platform, on both layouts. This used a stand-in java on PATH, so no window opened.
  • Initializr output: its own minimal and backend-only downloads build against the snapshot plugin. GeneratorModelIntegrationBuildTest now does this when CN1_MAVEN_PLUGIN_VERSION is set (opt-in, like its Gradle half).
  • Unit tests: project-model 25, build-engine 2322, codenameone-maven-plugin 410 (HostedPlatformsTest is new, and includes a structural test that every goal in the shared fragment steps aside for a module), Gradle plugin 19, and the Initializr's 6 tests (including the version gate and the Maven layout matrix across templates and IDEs).
  • Fixtures and scaffolding: fixtures for every Maven layout and IDE, the scaffolding parity scripts and the launcher parity check.
  • Static checks: SpotBugs zero findings in all four changed modules, plus the copyright, ASCII and control-character checks.
  • Docs: Vale, LanguageTool, paragraph capitalization and the cross-reference check on the changed chapters.

Docs

The developer guide covers the layouts and the opt-in flags in the archetype appendix, which pom to edit when there are no platform modules, backend-only projects in the backend chapter, and the native interface paths. The generated project's README has a project layout section, and the agent skill now uses root-level mvn package -Dcodename1.platform=... commands that work in either layout.

🤖 Generated with Claude Code

Maven projects can now omit every platform module: the root pom and
common/ build all platforms, run the simulator and tests, and package the
desktop app. A platform has its own module exactly when <platform>/pom.xml
exists; adding one later moves that platform's build into it. A
backend-only project is a single module at the root.

The archetype generates the minimal layout by default
(-DplatformModules, -DprojectType); the Initializr does once its plugin
is 7.0.275 or newer, with the full layout as an opt-in.

Also fixes JUnit tests in generated apps, which never ran: Surefire only
had Codename One's stub provider.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 157 screenshots: 157 matched.

Native Android coverage

  • 📊 Line coverage: 9.37% (9331/99611 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.10% (47834/525841), branch 3.60% (1793/49819), complexity 3.57% (1898/53096), method 5.52% (1542/27918), class 11.04% (413/3742)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 9.37% (9331/99611 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 9.10% (47834/525841), branch 3.60% (1793/49819), complexity 3.57% (1898/53096), method 5.52% (1542/27918), class 11.04% (413/3742)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6367 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.ClassReader – 0.00% (0/1524 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1187 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.MethodWriter – 0.00% (0/922 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/736 lines covered)
      • com.google.common.cache.com.google.common.cache.LocalCache$Segment – 0.00% (0/726 lines covered)
      • okio.okio.Buffer – 0.00% (0/687 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/625 lines covered)
      • org.jacoco.agent.rt.internal_0e20598.asm.org.jacoco.agent.rt.internal_0e20598.asm.Frame – 0.00% (0/570 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 199ms / native 261ms = 0.7x speedup
SIMD float-mul (64K x300) java 191ms / native 87ms = 2.1x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path gated to scalar (CPU autovectorizes scalar; explicit SIMD not beneficial here)
Base64 CN1 encode 102.000 ms
Base64 CN1 decode 87.000 ms
Base64 native encode 440.000 ms
Base64 encode ratio (CN1/native) 0.232x (76.8% faster)
Base64 native decode 289.000 ms
Base64 decode ratio (CN1/native) 0.301x (69.9% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 193 screenshots: 193 matched.
✅ JavaScript-port screenshot tests passed.

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ✅ ByteCodeTranslator: 0 findings (no issues)
    • ✅ android: 0 findings (no issues)
    • ✅ backend: 0 findings (no issues)
    • ✅ build-engine: 0 findings (no issues)
    • ✅ build-hint-catalog: 0 findings (no issues)
    • ✅ build-hint-tools: 0 findings (no issues)
    • ✅ codenameone-gradle-plugin: 0 findings (no issues)
    • ✅ codenameone-maven-plugin: 0 findings (no issues)
    • ✅ core-unittests: 0 findings (no issues)
    • ✅ ios: 0 findings (no issues)
    • ✅ project-model: 0 findings (no issues)
  • ✅ PMD: 0 findings (no issues) [Report archive]
  • ✅ Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 154 screenshots: 154 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 424 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 69ms / native 3ms = 23.0x speedup
SIMD float-mul (64K x300) java 53ms / native 3ms = 17.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 79.000 ms
Base64 CN1 decode 59.000 ms
Base64 native encode 795.000 ms
Base64 encode ratio (CN1/native) 0.099x (90.1% faster)
Base64 native decode 300.000 ms
Base64 decode ratio (CN1/native) 0.197x (80.3% faster)
Base64 SIMD encode 70.000 ms
Base64 encode ratio (SIMD/CN1) 0.886x (11.4% faster)
Base64 SIMD decode 74.000 ms
Base64 decode ratio (SIMD/CN1) 1.254x (25.4% slower)
Base64 encode ratio (SIMD/native) 0.088x (91.2% faster)
Base64 decode ratio (SIMD/native) 0.247x (75.3% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 17.000 ms
Image createMask (SIMD on) 6.000 ms
Image createMask ratio (SIMD on/off) 0.353x (64.7% faster)
Image applyMask (SIMD off) 66.000 ms
Image applyMask (SIMD on) 74.000 ms
Image applyMask ratio (SIMD on/off) 1.121x (12.1% slower)
Image modifyAlpha (SIMD off) 73.000 ms
Image modifyAlpha (SIMD on) 78.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.068x (6.8% slower)
Image modifyAlpha removeColor (SIMD off) 100.000 ms
Image modifyAlpha removeColor (SIMD on) 79.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.790x (21.0% faster)

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

✅ ByteCodeTranslator Quality Report

Test & Coverage

  • ✅ Tests: 740 total, 0 failed, 57 skipped

Benchmark Results

  • Execution Time: 16055 ms

  • Hotspots (Top 20 sampled methods):

    • 5.26% com.codename1.tools.translator.BytecodeMethod.equals (75 samples)
    • 5.05% java.util.ArrayList.indexOf (72 samples)
    • 4.35% java.lang.StringBuilder.append (62 samples)
    • 4.28% com.codename1.tools.translator.IteratorEscape.ctorOnlyStoresParamsIntoThis (61 samples)
    • 3.02% com.codename1.tools.translator.ByteCodeClass.hasDeclaredMethod (43 samples)
    • 2.81% com.codename1.tools.translator.JavascriptReachability.enqueueResolved (40 samples)
    • 2.52% java.lang.String.equals (36 samples)
    • 2.38% com.codename1.tools.translator.IteratorEscape.mangle (34 samples)
    • 2.17% com.codename1.tools.translator.NativeSymbolIndex.extend (31 samples)
    • 2.17% java.lang.System.identityHashCode (31 samples)
    • 2.10% com.codename1.tools.translator.bytecodes.Invoke.findMethodUp (30 samples)
    • 1.89% java.util.HashMap.hash (27 samples)
    • 1.82% java.lang.Object.hashCode (26 samples)
    • 1.75% org.objectweb.asm.tree.analysis.SourceInterpreter.merge (25 samples)
    • 1.47% com.codename1.tools.translator.BytecodeMethod.updateInlinableFieldDependencies (21 samples)
    • 1.19% com.codename1.tools.translator.NativeSymbolIndex.<init> (17 samples)
    • 1.19% org.objectweb.asm.tree.analysis.Frame.merge (17 samples)
    • 1.12% com.codename1.tools.translator.IteratorEscape.walk (16 samples)
    • 1.05% com.codename1.tools.translator.bytecodes.Invoke.resolveDirectTarget (15 samples)
    • 1.05% com.codename1.tools.translator.BytecodeMethod.optimize (15 samples)
  • ⚠️ Coverage report not generated.

Static Analysis

  • ✅ SpotBugs: no findings (report was not generated by the build).
  • ⚠️ PMD report not generated.
  • ⚠️ Checkstyle report not generated.

Generated automatically by the PR CI workflow.

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 166 screenshots: 166 matched.
✅ Native Mac screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 230 seconds

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 67ms / native 4ms = 16.7x speedup
SIMD float-mul (64K x300) java 59ms / native 3ms = 19.6x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 native bridge unavailable (CN1 + SIMD + image benchmarks only)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 44.000 ms
Base64 CN1 decode 53.000 ms
Image encode benchmark iterations 100
Image createMask (SIMD off) 20.000 ms
Image createMask (SIMD on) 6.000 ms
Image createMask ratio (SIMD on/off) 0.300x (70.0% faster)
Image applyMask (SIMD off) 73.000 ms
Image applyMask (SIMD on) 65.000 ms
Image applyMask ratio (SIMD on/off) 0.890x (11.0% faster)
Image modifyAlpha (SIMD off) 62.000 ms
Image modifyAlpha (SIMD on) 48.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.774x (22.6% faster)
Image modifyAlpha removeColor (SIMD off) 43.000 ms
Image modifyAlpha removeColor (SIMD on) 56.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.302x (30.2% slower)

ParparVM vs HotSpot (JDK 25): macOS arm64

Runner CPU: Apple M1 (Virtual) (baseline macos-arm64)

Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in vm/selfhost/perf-baseline/ fails: above it is a regression, below it an improvement that has to be rebaselined (a row whose calibration runs were noisier carries a wider tolerance), and for RAM the change must also exceed 0.05x in absolute terms. Both run unpinned on all of the runner's CPUs, with their own default thread counts.

Benchmark Cores Time RAM Status
hello (HelloCodenameOne) 3 0.79x (base 0.96x, -17.5%) 1.14x (base 1.34x, -14.7%) ok
translator (self) 3 0.57x (base 0.54x, +5.0%) 0.77x (base 0.74x, +3.6%) ok
intArithmetic 3 1.03x (base 1.03x, -0.5%) 0.12x (base 0.12x, -0.9%) ok
longArithmetic 3 0.99x (base 1.03x, -3.9%) 0.11x (base 0.11x, +0.3%) ok
mathTranscendental 3 0.98x (base 1.01x, -2.5%) 0.12x (base 0.12x, -0.3%) ok
arraySequential 3 0.44x (base 0.42x, +4.4%) 0.53x (base 0.53x, -0.1%) ok
arrayRandom 3 0.95x (base 0.99x, -3.7%) 0.32x (base 0.32x, -0.2%) ok
objectAllocation 3 3.69x (base 3.70x, -0.2%) 0.40x (base 0.48x, -17.0%) ok
valueEscape 3 0.50x (base 0.51x, -2.2%) 0.08x (base 0.09x, -5.4%) ok
hashMapChurn 3 1.08x (base 1.18x, -8.2%) 0.07x (base 0.07x, +6.1%) ok
stringBuilding 3 0.89x (base 0.84x, +5.6%) 0.46x (base 0.46x, -0.6%) ok
recursion 3 1.18x (base 1.24x, -4.4%) 0.12x (base 0.12x, -0.6%) ok
quicksort 3 1.00x (base 1.01x, -0.8%) 0.11x (base 0.11x, +0.6%) ok

Result: no regression

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 155 screenshots: 155 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 1413 seconds

Build and Run Timing

Metric Duration
Simulator Boot 1000 ms
Simulator Boot (Run) 0 ms
App Install 15000 ms
App Launch 1000 ms
Test Execution 384000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 55ms / native 4ms = 13.7x speedup
SIMD float-mul (64K x300) java 55ms / native 3ms = 18.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 204.000 ms
Base64 CN1 decode 84.000 ms
Base64 native encode 3840.000 ms
Base64 encode ratio (CN1/native) 0.053x (94.7% faster)
Base64 native decode 1307.000 ms
Base64 decode ratio (CN1/native) 0.064x (93.6% faster)
Base64 SIMD encode 103.000 ms
Base64 encode ratio (SIMD/CN1) 0.505x (49.5% faster)
Base64 SIMD decode 89.000 ms
Base64 decode ratio (SIMD/CN1) 1.060x (6.0% slower)
Base64 encode ratio (SIMD/native) 0.027x (97.3% faster)
Base64 decode ratio (SIMD/native) 0.068x (93.2% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 6.000 ms
Image createMask (SIMD on) 24.000 ms
Image createMask ratio (SIMD on/off) 4.000x (300.0% slower)
Image applyMask (SIMD off) 35.000 ms
Image applyMask (SIMD on) 266.000 ms
Image applyMask ratio (SIMD on/off) 7.600x (660.0% slower)
Image modifyAlpha (SIMD off) 35.000 ms
Image modifyAlpha (SIMD on) 26.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.743x (25.7% faster)
Image modifyAlpha removeColor (SIMD off) 66.000 ms
Image modifyAlpha removeColor (SIMD on) 57.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.864x (13.6% faster)

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 150 screenshots: 150 matched.
✅ Native Apple TV (tvOS, Metal) screenshot tests passed.

@shai-almog

shai-almog commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 155 screenshots: 155 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 1757 seconds

Build and Run Timing

Metric Duration
Simulator Boot 89000 ms
Simulator Boot (Run) 0 ms
App Install 16000 ms
App Launch 4000 ms
Test Execution 487000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 81ms / native 6ms = 13.5x speedup
SIMD float-mul (64K x300) java 82ms / native 3ms = 27.3x speedup
SIMD kernel correctness PASS (native result == scalar reference)
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 SIMD byte path active (NEON-accelerated)
Base64 CN1 encode 181.000 ms
Base64 CN1 decode 97.000 ms
Base64 native encode 2416.000 ms
Base64 encode ratio (CN1/native) 0.075x (92.5% faster)
Base64 native decode 1105.000 ms
Base64 decode ratio (CN1/native) 0.088x (91.2% faster)
Base64 SIMD encode 68.000 ms
Base64 encode ratio (SIMD/CN1) 0.376x (62.4% faster)
Base64 SIMD decode 60.000 ms
Base64 decode ratio (SIMD/CN1) 0.619x (38.1% faster)
Base64 encode ratio (SIMD/native) 0.028x (97.2% faster)
Base64 decode ratio (SIMD/native) 0.054x (94.6% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 147.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.020x (98.0% faster)
Image applyMask (SIMD off) 58.000 ms
Image applyMask (SIMD on) 65.000 ms
Image applyMask ratio (SIMD on/off) 1.121x (12.1% slower)
Image modifyAlpha (SIMD off) 396.000 ms
Image modifyAlpha (SIMD on) 59.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.149x (85.1% faster)
Image modifyAlpha removeColor (SIMD off) 85.000 ms
Image modifyAlpha removeColor (SIMD on) 543.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 6.388x (538.8% slower)

@shai-almog

shai-almog commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator Author

Compared 223 screenshots: 223 matched.
✅ Native Apple Watch (watchOS, Core Graphics) screenshot tests passed.

@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-03T13:07:59.104061Z 1b7453c Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d1c060c49d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- The archetype build injected the hosted profiles with Ant's <replace>, which
  rewrites through an owner-only (0600) temp file. The staged common/pom.xml
  was then unreadable to the runner and hashFiles('**/pom.xml') failed the
  guibuilder job's cache step. Use a filtered <copy> of a deleted target.
- cn1-binaries-javase carries ${cn1.version}: the initializr's root pom does
  not manage it, so its simulator profiles had no version. A test now checks
  every fragment dependency against both root poms, and the initializr build
  hook resolves the simulator profile.
- compile-javase-natives re-extracts cn1lib natives from scratch and records
  resource names, so removed sources and deleted resources rebuild.
- cn1:update works for a backend-only project at the root.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9dbddc3a2f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

shai-almog and others added 3 commits October 3, 2026 12:11
- The hosted simulator refuses a JDK older than 11 up front, as cn1:run and
  cn1:debug do, instead of letting a Java 8 launcher read its argument file as
  a class name. The simulator needs JDK 11+ at runtime whatever the project's
  source level; the integration test prepares it on the newer JDK CI names.
- Desktop profiles that run JavaSE code from common, executable-jar and test
  included, ship cn1-binaries-javase like the javase module, so the packaged
  desktop app keeps the bundled FFmpeg binaries.
- compile-javase-natives keys its cache on each cn1lib archive's content hash.
- cn1:update fails with a clear message when a project lacks the cn1.version
  or cn1.plugin.version property, instead of an NPE.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Java CI leg runs integration-tests/all.sh on JDK 8 with no newer JDK
named, so preparing the simulator there now refuses (it needs JDK 11+).
Assert that refusal and its message on an older JDK; prepare and check the
classpath on a newer one.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a195783e67

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

- generate-desktop-app-wrapper deletes a stub it generated earlier once a
  custom javase/src/desktop/java stub appears, so the two are never compiled
  together.
- compile-javase-natives skips builds for a platform other than javase: a
  device build uploads none of it, and a desktop-only compile error must not
  stop it. Builds that name no platform (mvn test) still compile it.
- Its cache requires the output directory to exist, and the stamp goes with
  the output when there is nothing left to compile.
- The hosted desktop jar takes the javase natives, resources and desktop
  resources before common's classes, the order a full layout's classpath
  resolves them in.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shai-almog

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: 1b7453c3a8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@shai-almog
shai-almog merged commit b6e9bb8 into master Oct 3, 2026
@shai-almog
shai-almog deleted the maven-minimal-layouts branch October 3, 2026 16:58
shai-almog added a commit that referenced this pull request Oct 3, 2026
Merged master (#5937, minimal and backend-only Maven projects). The
backend-only Maven project now gets the @backendtest setup and the two
sample tests every other backend layout has; the generated project's
mvn test runs them (3 tests).

Review fixes:
- CORS same-origin detection compares the scheme too: the request's own
  (X-Forwarded-Proto behind a TLS terminating proxy, else whether the
  server speaks TLS). http://api.example calling https://api.example
  skipped the policy.
- Surefire %regex[...] includes, excludes and -Dtest entries select as
  Surefire does, over the class path.
- hasTests() counts Kotlin test sources, so a Kotlin-only suite reaches
  the explicit "Kotlin tests cannot be compiled" failure.
- assertEquals with a negative or NaN delta fails on the delta first,
  with JUnit 5.9's own failure (measured: AssertionFailedError, not
  IllegalArgumentException).
- TestRestTemplate targets the server's real scheme and listen address.
- A test or lifecycle method that returns a value is a build error for the
  compiled run, as JUnit does not run it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 3, 2026
…ilation

Brings in #5937 (minimal and backend-only Maven projects), whose
cn1app-minimal-layout-test.sh generates a project on JDK 8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 3, 2026
…s for 17

This branch had changed the default from "auto" to 17, so a project generated
on JDK 8 targeted Java 17 and did not compile there. Master's
cn1app-minimal-layout-test.sh (#5937) generates on JDK 8 and failed with
"invalid target release: 17" in archetype-smoke and build-linux-jdk8. "auto"
already resolves to 17 on any JDK >= 17, which is what a Flutter project
needs; the Flutter benchmark now passes -DjavaVersion=17 explicitly rather
than depending on the JDK it runs on. Verified: generated on JDK 8 the
project gets java.version=8 and common compiles.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 3, 2026
…layout

Since #5937 the archetype generates the minimal layout, which has no android/
or ios/ module: the builds write their Gradle and Xcode source projects under
common/target. build_apps.sh looked only in android/target and ios/target, so
the Android leg reported "no generated Gradle project" after a successful
build. Both lookups now search the project's target directories.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
shai-almog added a commit that referenced this pull request Oct 6, 2026
…I cleanup (#5932)

* Backend: Spring-style test framework, hellocodenameone e2e server, API cleanup

- Public backend API is now what an app writes against: the Spring aliases and
  settings annotations are gone (application.properties is compiled in instead)
  and the generated-code plumbing moved to com.codename1.impl.backend, which the
  backend javadoc excludes.
- codenameone-backend-test: @backendtest, MockMvc, TestRestTemplate,
  @TestConfiguration and @MockitoBean. The same JUnit 5 tests run on the JVM and,
  with -Dcn1.backend.compiledTests=true, translated into a native test binary.
- CORS, multipart/@RequestPart and gzip in the server.
- scripts/hellocodenameone/backend replaces demo/cn1ss and the legacy Java
  server as the single CI server: the screenshot websocket plus the REST surface
  new device tests in common drive.
- Archetype, initializr template, docs and CI wired to all of the above.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Record the vendored JZlib sources in the copyright-header exclusions

They are touched only to mark them @SharedWithBackend, which pulls them into the
diff-scoped header check; they keep JCraft's BSD notice.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Fix the CI failures and the review findings on the backend testing PR

CI:
- The packaged archetype server refused to start on the compiled-in
  ${DATABASE_URL}: an unset reference no longer counts as a configured database
  when nothing needs one (Config.resolves); code that needs one still fails loudly.
- The Gradle conversion kept the archetype's untouched backend once it carried the
  sample tests; the generated tests and their dependencies are part of the skeleton.
- oteltest used Builder.management(), now internal; BackendOtelTest counted a
  bridge method's parameter type as McpServer being linked.
- The device legs' backend tests: a failed request threw instead of failing (the
  suite timed out), and a step that hears nothing now fails by name; Android allows
  cleartext to the CI host; the CI JS, Linux and Windows launchers instantiate the
  generated bootstraps a real build does.
- Ports the tests found broken: the Linux and Windows ports ignored the HTTP method,
  the connect and read timeouts, and (Windows) followed redirects natively; watchOS
  and tvOS had no HTTP at all (an NSURLSession path); the JS port answered null for
  every response header and stored binary bytes, and String.getBytes, unsigned.
- LanguageTool terms.

Review:
- Compression and CORS no longer mutate a Response a handler shares.
- An explicit gzip entry in Accept-Encoding wins over *.
- The compiled runner: unannotated overrides hide inherited tests, package-private
  base-class methods are reached through a helper in their package, it runs the
  classes Surefire selects, and duplicate injected field names are a build error.
- MockMvc: a lower-case Host is kept, and Content-Type is visible as a header.
- Gradle: Kotlin tests get the test pass, and the properties files are task inputs.
- server.sh installs and digests the build engine.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Fix the remaining backend test failures and the second review round

CI:
- The timeout probe set setFailSilently(true), and NetworkManager hands a
  fail-silent request's exception to nobody, overridden handleException included:
  a timed-out request ended with no callback on every port without native
  timeouts. The JS port also ignored timeouts; its synchronous XHR now gets
  xhr.timeout and reports a TimeoutError as an IOException.
- The musl leg built the plugin's whole dependency tree inside its container to
  start the test server, past the suite's wait. prepare-suite now builds a server
  copy both Linux legs run (CN1SS_SERVER_DIST), and a server that does not start
  now fails with its own output.

Review:
- @backendtest holds a JUnit resource lock, so parallel execution never runs two
  classes that would stop each other's application.
- An @BeforeAll assumption that does not hold skips the class in a compiled run.
- application.properties and its profile files are compiled in as UTF-8, and a
  profile file is found without a base file.
- Multipart: the part header limit is for the whole block, and a multipart body
  with no valid boundary is refused.
- CORS answers carry Vary: Origin whenever the policy names origins.
- MockMvc: queryParam on a multipart builder stays in the URL.
- Generated test context and runner names that would collide are a build error.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the third backend review round

- SurefireSelection honours negative -Dtest entries (!SlowTest).
- The compiled test run refuses Kotlin test sources by name instead of running
  without them; the Gradle task passes the Kotlin test directory so it can tell.
- Linux and Windows ports: an explicit GET or POST overrides the post flag, and an
  explicit GET sends no body.
- Multipart: a part ends only at a complete delimiter, so data that contains the
  boundary followed by more is not cut there.
- The compiled runner reports a teardown failure over an earlier assumption abort.
- MockMvc drops the body of a HEAD, 1xx, 204, 205 or 304 answer, as the HTTP
  writers do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Let the backend timeout probe hear its own failure

Android and the browser dropped the timeout step: the request did time out,
but the app's Lifecycle.handleNetworkError consumes every network error (and
shows a modal "Connection Error" dialog), and NetworkManager calls a
request's own handleException only when no listener consumed it. The probe
now carries a ReportsOwnErrors marker that the app's handler leaves alone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the fourth backend review round and the browser timeout probe

The browser leg still dropped the timeout step: ConnectionRequest calls
handleException on the network thread, and the probe ran the next step and
finished the test from there. Error callbacks now go to the EDT, and the
backend client tests get a budget their 12s step watchdog fits inside.

Review fixes:
- Linux sends a buffered body for any method but GET and HEAD (a DELETE
  with a body went out empty).
- The compiled runner collects default @test and lifecycle methods from
  implemented interfaces, and an unannotated method suppresses an
  inherited test only when it really overrides it (package-private
  methods in another package do not).
- @backendtest is @inherited; an abstract base's concrete subclasses each
  get a generated context.
- -Dtest=Class#method narrows the compiled run to the same methods.
- Mockito is detected in code, not in comments or strings.
- A multipart @RequestParam that is not UTF-8 is a 400, not a 500.
- A 206 / Content-Range response is never compressed.
- A CORS origin with a path, query or fragment is refused at start.
- The shim compares nested primitive arrays by content.
- jsonPath exists()/doesNotExist() treat JSON null as absent, as Spring.
- getBody() is documented as Spring's string converter behaves: a binary
  body is decoded when it is valid UTF-8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the fifth backend review round and the remaining CI failures

CI:
- The browser timeout probe: a timed-out synchronous XHR can come back from
  send() without throwing, and reading on reached responseText, which an
  arraybuffer request throws for -- ending the network thread with no
  callback at all. send() now reports status 0 with no response as a
  failure, and responseText is never read on an arraybuffer request.
- Developer guide: a sentence Vale's write-good rule refused.

Review fixes:
- Request.param throws for a malformed multipart body instead of reading
  it as "no field"; the generated guard answers that, and a non-UTF-8
  field, with 400.
- A @RequestBody binding answers a binary body that is not UTF-8 with 400
  instead of a 500.
- An eligible response varies by Accept-Encoding even when it went out
  uncompressed.
- A gzip request body is decoded member by member; trailing bytes that
  are not another member are refused.
- andExpectAll reports a matcher that throws and runs the rest.
- Linux, Windows and JS advertise the read timeouts they now honour.
- WebEnvironment.NONE keeps its loopback listener, documented with why;
  AssertionError(Object) keeps "null", which is what the JDK does.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Keep exceptions that unwind through a finally on the JS port

The browser's backend timeout probe was not a networking bug. The JS
translator's dead-case pass kept a try/catch table entry's handler pc only
when ",t:" followed it, so every catch-all handler -- a finally, a
synchronized block's release -- lost its case label. An exception
unwinding through one was dispatched to a pc with no case, fell to
"default: return" and vanished: ConnectionRequest.performOperationComplete
returned normally from a timed-out request and nothing heard of it.
Reproduced against the CI bundle in headless Chromium, confirmed by
restoring the one label, and covered by a translation test that fails
without the fix (score 14, not 31).

Review fixes:
- bodyContent refuses a body over the cap (413), so MockMvc refuses what
  the listener does.
- An empty body declared multipart is malformed, not "no parts".
- Windows reports a failed body read (a stall past the read timeout) as
  an IOException instead of end of stream.
- jsonPath isEmpty() needs the path to exist.
- HttpStatusCode.isError() is 4xx or 5xx only.
- Only a directly nested @TestConfiguration applies to its test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Stop a catch handler's throw being caught by its own sibling handler

ParparVM: a try statement with several catch clauses registers one try
block per clause, and throwException popped only the block that matched.
When that handler threw -- a rethrow or a new exception -- its sibling
handler for the same try was still registered and caught it:
`catch (IOException e) { throw e; } catch (Exception e) {}` swallowed the
rethrow on every native target. Each handler entry now resets
tryBlockOffset to the depth at its label, as JUMP_TO does for a jump.
Found when the JUnit stand-in's assertAll, which rethrows an
OutOfMemoryError ahead of catch (Throwable), behaved differently compiled.
CatchRethrowIntegrationTest covers it on every compiler configuration
(RESULT 104 without the fix, 127 with), and SelfTest's long-skipped
nested-finally probe -- already working, as the same test shows -- now
runs as an ordinary check.

Review fixes:
- Vary given as a List is extended element by element, without duplicates.
- A close delimiter must end at padding, CRLF or the end of the body.
- The boundary search is linear (KMP).
- Form decoding keeps a supplementary character beside + and %.
- A strong ETag keeps its response uncompressed, as Tomcat does.
- assertThrows builds a supplier message only on failure; assertAll
  rethrows an OutOfMemoryError; assertIterableEquals recurses.
- Composed @test (and lifecycle) annotations are recognized.
- The compiled run names only the selected tests to javac, finding what
  they use through -sourcepath; a non-strict run with nothing to compile
  (all Mockito, or nothing selected) warns and skips.
- Gradle runs the test pass over the Java and Kotlin test outputs as one
  hierarchy, weaving each class where its file is.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the seventh backend review round

Merged master first: the PR check compared against an old merge base, so
the nightly fold of perf-baseline/base/ looked like this branch's change.

- CORS: a cross-origin request whose origin or method the policy does not
  admit is refused with 403 before any handler runs, as Spring's
  CorsProcessor refuses it. A simple request needs no preflight, so its
  handler used to run and only the headers were withheld; allowedMethods
  was never checked for it at all.
- A compiled-in cn1.profile applies when neither the process nor a file
  beside the binary names one; the profile file is read for it.
- The native CI server installs the ParparVM toolchain and digests the
  translator and JavaAPI sources, so a translator change is what it builds
  with.
- The compiled run selects a source by the classes it declares (read from
  the JVM build's test classes), not its file name, and clears earlier
  compiled reports before writing.
- A composed @disabled is honoured.
- MockMvc releases a file response it sends no body for (HEAD).
- The shim rethrows OutOfMemoryError from assertDoesNotThrow and from
  assertThrows/assertThrowsExactly when it is not the expected type.
- Gradle tracks src/main/resources/application*.properties as inputs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the eighth backend review round; tests for backend-only projects

Merged master (#5937, minimal and backend-only Maven projects). The
backend-only Maven project now gets the @backendtest setup and the two
sample tests every other backend layout has; the generated project's
mvn test runs them (3 tests).

Review fixes:
- CORS same-origin detection compares the scheme too: the request's own
  (X-Forwarded-Proto behind a TLS terminating proxy, else whether the
  server speaks TLS). http://api.example calling https://api.example
  skipped the policy.
- Surefire %regex[...] includes, excludes and -Dtest entries select as
  Surefire does, over the class path.
- hasTests() counts Kotlin test sources, so a Kotlin-only suite reaches
  the explicit "Kotlin tests cannot be compiled" failure.
- assertEquals with a negative or NaN delta fails on the delta first,
  with JUnit 5.9's own failure (measured: AssertionFailedError, not
  IllegalArgumentException).
- TestRestTemplate targets the server's real scheme and listen address.
- A test or lifecycle method that returns a value is a build error for the
  compiled run, as JUnit does not run it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the ninth backend review round

- The compiled test run compiles and translates with the module's
  test-scoped dependencies, as Surefire runs the tests with them; the
  JVM-only test libraries (JUnit, which the shim replaces, the backend
  test jar, Mockito and its byte-code helpers) and runtime-scoped
  dependencies stay out, and so does the backend runtime jar.
- A generated test runner rethrows an OutOfMemoryError from a test or a
  lifecycle method instead of recording it and carrying on.
- The opening multipart delimiter must start a line and be complete; a
  boundary-like string inside the preamble is skipped.
- A bracketed JSON path name must close with its own quote and then ];
  a name containing ] is no longer cut at it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the tenth backend review round

- A multipart/form-data part must carry Content-Disposition: form-data
  and name its field (RFC 7578 4.2); one that does not is a malformed
  form, not a nameless part an optional binding ignores.
- Windows: a failure to recreate the WinHTTP request for a custom method
  is recorded where the request is created, so httpFailure reports it and
  the caller gets an IOException, not response code -1.
- A static @test is a build error for the compiled run, as JUnit does not
  run it.
- Gradle, mixed Java and Kotlin backends: kept as is and documented.
  Annotated classes in both languages produce two entry point records and
  same-named generated classes, which the existing SplitOutputCheck after
  compileJava refuses; a test now covers the backend records.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the eleventh backend review round and the PMD findings

PMD: a literal-first comparison in Multipart.isFormData, and the test
server's loopback bind marked as the deliberate literal it is.

- An unterminated quoted multipart parameter (boundary="b, name="f) is
  malformed: the lookup answers absent, which both callers refuse.
- The compiled run reads Surefire's includes and excludes from the
  default-test execution's configuration too, over the plugin's.
- A test that uses a Mockito-only support class -- directly or through a
  chain -- is left out with it, rather than pulled into javac through
  -sourcepath without Mockito on the classpath.
- A credentialed preflight against allowedMethods=* echoes the requested
  method, as a browser reads * as a literal name with credentials.
- Interface lifecycle hooks run at the level that implements them: base
  class setup, then the subclass's interfaces' hooks, then its own, as
  JUnit orders them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the twelfth backend review round

- Override discovery follows Java across interfaces: a superclass's
  unannotated method hides an interface's default @test of the same
  signature, and an interface default never hides a class method; the
  lifecycle order keeps each class's interfaces at its level.
- The probe server's /api/big clamps its size before allocating, as the
  download probe does, so a huge or negative size cannot take the shared
  test server down.
- A urlencoded form value that is not UTF-8 once percent-decoded (%FF) is
  refused rather than decoded to a replacement character; a generated
  @RequestParam binding answers it with 400.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the thirteenth backend review round

- A test that injects the DataSource or EntityManager itself starts the
  database even when the application needs none, instead of being filled
  with null.
- MockMvc's multipart builder escapes quotes and backslashes in a part's
  name and filename, and refuses a line break, so a"b.txt arrives intact.
- TestRestTemplate recognises an absolute URL's scheme case-insensitively.
- Windows: a connect timeout bounds name resolution too, so an unanswered
  DNS lookup cannot block past the timeout the caller set.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the fourteenth backend review round

- -Dtest's classless method selector (#fast*+slowTest) selects those
  methods in every class instead of being dropped, which ran every method.
- Linux: the read timeout is a millisecond idle limit, checked by a
  progress callback when data arrives and while none does; libcurl's
  low-speed options measured average speed in whole seconds, so a
  response trickling a byte every 900ms beat a 500ms limit.
- A run with no test sources does nothing, for Gradle's backendTest as for
  the Maven goal, instead of failing with "No test source can be compiled".
- An explicit Builder.host() -- null or "" for every interface -- wins over
  cn1.server.address; a tokenless MCP endpoint refuses the explicit
  wildcard as it refuses any non-loopback address.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the fifteenth backend review round; document niche gaps

Fixed:
- Gradle conversion: the Surefire plugin counts as generated only when it
  is exactly the archetype's (reuseForks=false); a backend whose Surefire
  carries the developer's own settings is their work and is kept, not left
  behind.
- The JUnit shim's @test and lifecycle annotations allow annotation types,
  so a composed test annotation compiles in the native run as on the JVM
  (the hellocodenameone suite now uses one).

Documented as unsupported rather than implemented, as niche JUnit and
Surefire parity:
- repeating @tag on one element (vm/JavaAPI has no @repeatable);
- a -Dtest regex selector with a method part (%regex[...#...]).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the sixteenth backend review round

- Gradle backendTest passes the test source set's compile classpath, so a
  testImplementation helper compiles in the native run; JVM-only libraries
  are recognised in Gradle's cache layout too.
- CORS preflights that echo the requested method or headers say so in Vary.
- MockMvc and TestRestTemplate refuse a URI template with no variable for a
  placeholder instead of sending the literal braces.
- Windows sends no buffered body for an explicit HEAD, as Linux does.
- JS port: document that a synchronous XHR can only enforce the timeouts as
  a whole-request deadline.
- Reword the Backend-Testing line Vale flagged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the seventeenth backend review round

- The server's own 404 and 500 carry the CORS headers, through a
  package-private fallback hook Backend's chain implements, so a browser
  sees the real status instead of a CORS failure.
- Linux read timeout: progress since the last callback counts before the
  idle check, and the first callback after connecting starts the clock.
- Test contexts that differ only in injecting the database get distinct
  cache keys, so one started without it is not handed to the other.
- Mockito reach matches class names in code only, not comments or strings.
- JUnit shim: @disabled may be composed; an inert @nested lets a source
  declaring one compile. Nested classes inside @backendtest documented as
  unsupported.
- Reword the Backend-Testing line LanguageTool flagged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the eighteenth backend review round

- CORS: a wildcard policy answers "*" with or without Origin, so its
  un-varied responses are right from a cache; a preflight refused for its
  method varies by Access-Control-Request-Method.
- Test context keys include each mock's field name, which names the bean.
- Gradle backendTest compiles what test annotation processors generated.
- cn1:backend-test clears earlier compiled reports even when the compiled
  run is off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the nineteenth backend review round

- cn1ss.sh uses the prebuilt server a job is handed (CN1SS_SERVER_DIST)
  instead of building one, launching it with server.sh exec-dist.
- CORS allow-list origins are compared without their scheme's default port,
  as browsers serialize them.
- Document that MockMvc does not validate request targets like the wire
  parsers, and that compiled reports keep method names as Surefire's do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the twentieth backend review round; fix JS screenshot drop

- JS port: the cn1ss screenshot websocket reconnects after an open socket
  closes. It stayed "open", so every later screenshot went to a closed
  socket and the javascript-screenshots run lost the rest of its images.
- Linux read timeout starts after the TLS handshake for https, which is the
  connect timeout's business.
- cn1:backend-test clears earlier compiled reports on every path, the
  no-tests and Windows ones included.
- A test class with more than one constructor is skipped in the compiled
  run, as JUnit refuses it.
- CatchRethrowIntegrationTest runs one compiler configuration: the bug is
  in the translator, and the diagonal cost ten minutes of vm-tests.
- Document the Surefire include/exclude forms and Kotlin test directories
  the compiled run does not read.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Address the twenty-first backend review round

- MockMvc reports the response as the wire sends it: the content type
  through the writers' default and validation, extra headers without the
  server-owned and unsafe ones the writers drop.
- The build reads application-<profile>.properties even with no base
  application.properties, for every setting that needs generated linkage,
  cn1.otel.enabled included.
- A PER_CLASS @backendtest resets its mocks after each test; a test pins it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Rebaseline objectAllocation on the AMD EPYC 9V74 Linux runner

The runner's base baseline predates #5940's allocation path, and the fold
that followed #5940 did not cover this CPU, so the gate failed every run
on it as an improvement past the baseline (4.76x -> 1.17x).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Rebaseline objectAllocation on the Intel model 173 Windows x64 runner

Same as the EPYC 9V74 row: the base baseline predates #5940's allocation
path (4.10x -> 1.62x), so every run on this CPU failed as an improvement.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Skip build-engine's proxy-jar test copy when tests are skipped

The hellocodenameone test server installs the backend modules with
-DskipTests on every screenshot leg. build-engine's antrun copy of the
ParparVM JavaScript proxy jars ran anyway and failed where that bundle is
not built (the iOS legs), so server.sh fell back to -am and rebuilt every
dependency: about seven minutes per leg, which pushed build-ios-metal past
its 75-minute limit. The copy only feeds JavaScriptProxyPackagerTest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Drop the EPYC 9V74 rebaseline that #5938 already carries

Master's pr/5938.json rebaselines the same objectAllocation row from the
same value, and the gate refuses two overlays moving one row. The Intel
model 173 Windows row stays: no other overlay covers it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant