Report the real port status, and fix the desktop-port defects it was hiding - #5501
Report the real port status, and fix the desktop-port defects it was hiding#5501shai-almog wants to merge 93 commits into
Conversation
…hiding The Port Status table showed almost every column as partial, skipped or stale. Most of that was the reporting pipeline, not the ports. Reporting - scripts/website/sync_port_status_reports.sh re-implemented the publish rule as a jq expression that demanded a measured duration for all ten performance workloads. iOS, tvOS and watchOS legitimately skip the three GC-footprint workloads on the simulator, so every fresh Apple report was rejected, the site served the checked-in fallback, and after fourteen days those four columns rendered as stale. The rule now lives once in port_status.py (publishable_report_problems + the "accept" subcommand) next to the normalizer whose own tests already covered skipped workloads. Contract drift keeps the fallback with a warning; a malformed report fails the website build instead of quietly degrading. - port-status-publish.yml only publishes when a workflow_run event reaches it, and those events never arrive for the Linux and Windows suites: the data branch has never held a linux or windows-x64 report. The nightly now runs backfill_port_status.sh, which publishes from the newest master run of every producing workflow and fails when a port has no report inside the contract's staleness window. - Only the Android pipeline failed on a failing compliance test. iOS, macOS and JavaScript now do too; all three are at zero failures, so this is a ratchet rather than a new red. - A skip the errata account for by name renders as a pass with a marked note instead of a partial, and the page validator refuses a noted cell whose test the errata do not cover. A run that stopped early no longer withdraws the result of a feature whose every mapped test reported back. - The checked-in reports are refreshed, including the real (failing) Linux and Windows results, so the fallback states what those ports actually do. Desktop ports - java.time asked the host for the rules of a fixed offset by handing "GMT-05:00" to the platform time zone database. POSIX inverts the sign of a TZ offset and the Windows CRT cannot parse the form at all, so every OffsetDateTime formatted through a pattern came out shifted by twice its offset. Custom GMT/UTC IDs are now resolved in Java, and a ZoneOffset never reaches the host database. - Offsets now come from TimeZone.getOffset rather than from Calendar, which reconstructs local time from a raw offset plus a flat one-hour daylight guess. - Character.getType threw UnsupportedOperationException, which meant isLetter, isLetterOrDigit and isJavaIdentifierStart/Part threw for every input on these ports. ASCII now has a category table and the rest answers from the primitives this runtime implements. - openInputStream returned a stream wrapping a null file handle for a missing path, so callers could not tell a missing file from an empty one (issue #1502 on both desktop ports); openOutputStream and the storage streams silently discarded writes the same way. - The Linux port carried the Windows port's backslash path join, so its staged-resource fallback never resolved. - CameraApiTest treated the native Linux port as having a headless camera. It drives real V4L2 devices through GStreamer, which a hosted runner does not have, so it now skips with a stated reason like the other native ports. - The Linux capture harness accepts CN1_REQUIRE_SUITE, so it can demand the suite's own completion marker rather than stopping when screenshots go quiet while trailing tests are still queued. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aad27d0718
ℹ️ 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".
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 149 screenshots: 149 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 151 screenshots: 151 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
|
Compared 149 screenshots: 149 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 148 screenshots: 148 matched. |
|
Compared 148 screenshots: 148 matched. |
|
Compared 144 screenshots: 144 matched. |
|
Compared 217 screenshots: 217 matched. |
|
Compared 149 screenshots: 149 matched. Benchmark ResultsDetailed Performance Metrics
|
|
Compared 143 screenshots: 143 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 181 screenshots: 181 matched. |
|
Compared 149 screenshots: 149 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
…native semantics - backfill_port_status.sh published whatever the newest run produced. A report built against an older contract passes the freshness check but is rejected by the website sync, so the column would stay on its stale fallback while the sweep reported success. Each artifact now goes through "port_status.py accept" before publication, and the closing assertion re-checks the published file instead of only its timestamp -- which is how windows-arm64's drifted report now surfaces. - CN1_REQUIRE_SUITE is now set by both Linux legs. Left unset, the new branch in the capture harness was unreachable and both jobs kept the screenshot stabilization exit that kills the suite while DesktopMode, the VideoIO grid, the VR scene and the 360 panorama are still queued. - The shared offset lookup passes UTC fields. The POSIX native resolves them with timegm and the JavaScript runtime with Date.UTC, but the iOS native built its NSDate from [NSCalendar currentCalendar], reading them in the device's zone; near a transition that lands on the wrong side of it. It now builds the date in UTC, and no longer drops the hour and second components. - Character.getType collapsed every non-ASCII whitespace code point to SPACE_SEPARATOR. U+2028 and U+2029 are LINE_SEPARATOR and PARAGRAPH_SEPARATOR and U+180E is FORMAT, all of which isWhitespace already treats individually. - The page validator matched the note marker with quoted attributes, which the production build minifies away, so the check failed on CI and passed locally. - java.time/DateTimeSupport.java carries the project header; java.util.TimeZone keeps its Apache Harmony notice and is recorded in the exclusions list. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c58dcc345
ℹ️ 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".
Cloudflare Preview
|
The first CI run on this branch confirmed the time zone, Character.getType and openInputStream fixes -- TimeApiTest, SurfacesPublishTest and FileSystemStorageOpenInputStreamMissingTest all pass on Linux now -- and the new exceptions turned two silent write failures into named ones. - getAppHomePath() returned a bare path on both desktop ports. Android and iOS return it with the file:// scheme, and com.codename1.io.File prepends the app home to any path that lacks the scheme, so new File(fs.getAppHomePath() + "x") resolved to the home directory joined to itself: AudioMixerApiTest was asking to write ".../codenameone//home/runner/.local/share/codenameone/audio-mixer-api-test.wav". Both ports now return the scheme and implement toNativePath. - The Windows port never overrode getAppHomePath at all, so it inherited listFilesystemRoots()[0] + AppName, which is a drive root plus the literal string "null" when no app name is set. It now anchors on the same per-user storage directory the Linux port uses. - cn1StorageDir() created only the leaf directory. A home without an existing ~/.local/share -- a fresh CI runner, or a new account -- left the storage directory absent, so every write into it failed at fopen(); that is why ClipboardRoundTripTest could not create its file. The path is now created component by component. - Both ports record why the last open failed and include it in the exception, so a missing directory is distinguishable from a permission or sharing problem without another CI round trip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a2cb05fce5
ℹ️ 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".
|
Compared 148 screenshots: 148 matched. Benchmark Results
Detailed Performance Metrics
|
…misuse
Crypto
- The Linux port answers the whole com.codename1.security surface through
OpenSSL's EVP layer: secure random, AES in GCM/CBC/ECB, RSA with OAEP or
PKCS#1, SHA-2 signatures and RSA key generation. Keys cross the boundary in
the encodings the portable API documents -- X.509 SubjectPublicKeyInfo and
PKCS#8 PrivateKeyInfo -- so d2i_PUBKEY and d2i_PKCS8_PRIV_KEY_INFO do the
ASN.1 and nothing parses DER by hand. libcrypto comes with the libcurl the
port already links.
- The Windows port answers the same surface through CNG, with crypt32 doing
the ASN.1 between those DER encodings and BCRYPT_RSAKEY_BLOB.
- A failed operation raises rather than returning an empty array: an
authentication failure that answered "no bytes" would read as a successful
decryption of nothing. GCM keeps the tag appended to the ciphertext, which
is the convention the portable API documents.
- The OpenSSL implementation was exercised against libcrypto off-device
before landing: GCM round trip, tamper and wrong-AAD rejection, CBC with
padding, OAEP round trip, and sign/verify including tampered-data and
wrong-key rejection.
stringToUTF8 aliasing
stringToUTF8 returns one buffer per thread and overwrites it on every call,
so a native that converted a second String silently repointed the first
result at the second string. Five natives in the Linux port did exactly
that:
- fileRename renamed a file onto itself, which is why WAVWriter's rename
step left AudioMixerApiTest without its output;
- httpSetHeader sent every request header as "value: value";
- printDocument, showNotification and shareText each collapsed their
arguments onto the last one.
They now copy through cn1LinuxJStrDup, which the header documents as
mandatory for any native converting more than one String. The Windows port
was already safe -- its wide-string helper allocates.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8dd4c6a954
ℹ️ 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".
…ietly A test that blocks the event dispatch thread outright can never be timed out by the runner, because the per-test deadline is itself enforced by an EDT callback. The suite simply stopped: the log ended mid-line, every later test was published as "never run", and nothing said which test was responsible -- that is how Media360PanoramaScreenshotTest on Linux and CalendarApiTest on Windows have been going unattributed. A watchdog thread now tracks the running test and, thirty seconds past its deadline, reports it by name, emits a CN1SS:SUITE:WEDGED marker and exits. The normalized report then records that test as failed and the rest as unreached, which is what actually happened, and the harness stops burning its forty-minute cap on a thread that is not coming back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The shared POSIX implementation sets TZ and reads tm_gmtoff back. Neither half exists on Windows: the Microsoft C runtime only parses the "EST5EDT" form of TZ, not an IANA identifier, and its struct tm carries no GMT offset at all. Every named zone therefore resolved to an offset of zero, which is why TimeApiTest read America/New_York as UTC. Windows has shipped ICU since Windows 10 1703, and its calendar speaks IANA identifiers and knows the daylight rules for the instant being asked about. The three time zone natives now go through it and fall back to the previous behaviour if it is unavailable. The POSIX path is untouched and still passes the same probe through the ParparVM clean target. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c6c9701c8
ℹ️ 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 watchdog reached for Runtime.exit, which the bytecode compliance gate rejects along with System.exit -- both are outside the API the ports support, and exitApplication would have to run on the very thread that is stuck. That broke the suite build, and with it every job that compiles the suite. The watchdog now only reports: it names the test and emits CN1SS:SUITE:WEDGED. Both capture harnesses watch for that marker, stop waiting as soon as it appears and fail with the test name, which is ordinary JUnit code under no such restriction. It also starts through Display.startThread rather than configuring a raw Thread, and stops itself once the suite finishes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19255ebe82
ℹ️ 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".
Crypto - The RNG now fails closed. RAND_bytes and BCryptGenRandom report failure to Java, which throws, instead of leaving a zeroed buffer that KeyGenerator would hand out as a key. - OAEP masks with SHA-1 even when the digest is SHA-256, matching the JCE providers behind the JavaSE and Android ports. Naming the digest for both halves made anything sealed on a desktop port undecryptable elsewhere. - Initialization vectors are checked before they reach the platform library: a missing GCM nonce silently repeated across messages under one key, and a short CBC IV was read as a whole block past the Java array. - Windows imports private keys through NCrypt, which takes PKCS#8 for both RSA and EC, so the ECDSA signature APIs work instead of decoding every key as RSA. Sign and verify pick their padding from the key's own algorithm. Time zones - Custom IDs split their last two digits as minutes for the three-digit form too, so GMT+012 is UTC+00:12 rather than UTC+12. - The Windows raw offset samples the current year and prefers the later standard-time reading. A zone whose base offset changed mid-year with neither sample flagged as daylight saving -- Asia/Almaty in 2024 -- would otherwise report its retired offset forever. - The UWP native reads its fields as UTC like the POSIX, JavaScript and iOS implementations, rather than as host-local time. Port status - A report whose generated_at cannot be parsed is unusable rather than publishable; it would otherwise poison the sweep and the page's own rendering. - The sweep merges artifacts across candidate runs until every port a workflow owns is covered, so one failed matrix leg no longer hides the others, and compares exact elapsed seconds rather than whole days. - A feature whose tests all passed or were documented skips keeps its noted pass even when the suite run stopped early; the completion fallback now runs after that case rather than before it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 902b535c80
ℹ️ 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".
There was a problem hiding this comment.
🔵 Human review recommended
It touches core runtime behavior, multiple native ports, and CI/reporting pipelines across platforms, so it warrants careful human validation despite only minor review nits found.
Review details
Suppressed comments (1)
vm/JavaAPI/src/java/util/TimeZone.java:297
- The JavaDoc lists
UTC+01:30as a supported custom fixed-offset ID, but the implementation explicitly rejects non-"GMT" offset suffixes (see theindex != 3 || !ID.startsWith("GMT")check). This makes the comment inaccurate.
- Files reviewed: 73/75 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dedc1fc708
ℹ️ 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".
…cessor AudioMixerApiTest is fixed -- Windows went from pass=166 fail=4 to pass=167 fail=3 and the rename failure is gone. VideoIORoundTripTest still fails with SetStreamSelection in the build, so that was not the cause. Rather than guess a second time at a stack I cannot run here, readAudio now reports what MF actually did: read count, null-sample count, bytes collected, the last HRESULT and stream flags, and the negotiated rate/channels. It also bounds the null-sample path, which could otherwise spin forever on a stream that only ever ticks. For the NPE, the probes have it at addContent on a container holding an ON switch. The only state the ON path reaches that the OFF path does not is getSelectedStyle -- getThumbOnImage uses it where getThumbOffImage uses the unselected style -- and calcPreferredSize is what asks for the thumb. Both are public, so the test now touches unselectedStyle, selectedStyle and preferredSize in turn and the breadcrumbs will name which one throws. No probes in Switch itself. Cross-compiles into a real Windows PE. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Human review recommended
It changes core reporting gates and multiple native runtime/port implementations across platforms, so it needs careful human validation across the CI matrix and target environments.
Review details
- Files reviewed: 73/75 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c8644d55f5
ℹ️ 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".
Two Windows defects, both now diagnosed from CI rather than guessed at. Audio: the instrumentation answered plainly -- reads=1 nullSamples=0 bytes=0 lastFlags=0x2. That flag is MF_SOURCE_READERF_ENDOFSTREAM on the very first read after the rewind, so SetCurrentPosition was not bringing the audio stream back once the video pass had driven the file to end-of-stream, and its HRESULT was never checked. My earlier SetStreamSelection change did not fix this and was not the cause. readAudio now opens a source reader of its own from the stored URL: a fresh reader starts at the beginning by construction, so the audio track no longer depends on seek semantics or on what the video pass did to the shared position. The old rewind remains as a fallback. Images: createMutableImage returned 0 for any non-positive extent, and a 0 peer is worse than a tiny image -- Image.getGraphics() answers null for it and the caller dies with a NullPointerException far from the cause. That is the shape of the Switch failure: the probes put it in getPreferredSize(), whose track image is sized from the font height, and createRoundRectTrackImage calls img.getGraphics().setAntiAliased(true) with no null check. Clamped to 1x1 so the object is always usable, and the test reports the font height so the next run says whether a zero height is what got us there. Cross-compiles into a real Windows PE. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8175b20cc4
ℹ️ 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".
There was a problem hiding this comment.
🔵 Human review recommended
It introduces large cross-cutting changes across CI workflows, reporting gates, core Java APIs, and native desktop implementations, which warrants careful human validation on all affected platforms.
Review details
- Files reviewed: 74/76 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
You are right that clamping to 1x1 was the wrong answer: something asking for a zero-sized image has a real bug -- a metric that came out zero -- and quietly handing back a 1x1 surface leaves that unfixed and renders wrongly instead of crashing. createMutableImage refuses a degenerate extent again, but says so in the log rather than returning a bare 0 with no explanation. I do not yet know why the metric is zero, and I am not going to guess a fourth time. DirectWrite is not failing -- cn1dwCreateFormat logs when CreateTextFormat fails and nothing appears in the Windows log -- so the format is being created and the cached font->height should be real. The font-height probe added last commit reports the actual number on the next run. Permanent diagnostics instead of one-off probes, as asked: every reported throwable now carries the platform state that turns NullPointerException with no stack into a lead -- display extent, density, EDT flag, default font height and system font height. A zero font height or a zero display extent is exactly how a component ends up asking for a zero-sized image whose graphics come back null. Printed only on failure, on every port, and it stays in. Runner lambda count unchanged at 7 code lines. Cross-compiles into a real Windows PE. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 378c948385
ℹ️ 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".
There was a problem hiding this comment.
🔵 Human review recommended
It spans critical CI/reporting infrastructure plus multiple platform native/runtime changes (timezone, IO, crypto), so it needs careful human validation across ports beyond the targeted fixes.
Review details
Suppressed comments (1)
vm/JavaAPI/src/java/util/TimeZone.java:350
customTimeZone()rejects lowercase/mixed-case "GMT" offset IDs (e.g. "gmt+5") because it usesID.startsWith("GMT")(case-sensitive). SincegetTimeZone()is documented/implemented as case-insensitive on other ports/JDK, this causes such IDs to fall through to the malformed-offset fallback and resolve to plain GMT instead of the intended fixed offset.
- Files reviewed: 74/76 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
The cross-compile job went red because of me: I added #include <string> to cn1_windows_video.cpp, which drags in the MSVC STL, and that hard-asserts STL1000 unless clang is exactly 19. That job does not pin LLVM 19 the way the build+run job does. The file already carried a comment saying no std::wstring precisely to avoid this, and I ignored it. The URL is a malloc'd wchar_t copy now, freed in the destructor, and the file has no STL again. My local check passed only because Homebrew clang here is 22.1.6 -- so a green xwin run locally is NOT evidence the CI toolchain accepts it. On the NPE: the font-height theory is dead. Windows reports fontHeight=20, systemFontHeight=20, display 784x561, density 20, and both styles resolve. So no metric is zero and no image is degenerate -- which also means the clamp I removed would have fixed nothing. What remains inside calcPreferredSize is the thumb image, and Switch builds it by creating an image, blurring it for the drop shadow, and drawing on the result. Rather than read further, the test now walks that same sequence through the public API and reports each step: create, graphics, antialias, blur support, the blur call, and graphics on the blurred image. Whichever comes back null or throws is the defect. Left in permanently -- a platform whose blur returns something undrawable cannot render a Switch at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 214286accc
ℹ️ 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".
There was a problem hiding this comment.
🟡 Changes recommended
There are a few concrete correctness/diagnostic issues in the new JavaAPI TimeZone custom-ID logic and in two new tests’ failure messages that should be fixed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Suppressed comments (1)
vm/JavaAPI/src/java/util/TimeZone.java:350
- customTimeZone() uses a case-insensitive prefix match (regionMatches(true, ...)) but then requires ID.startsWith("GMT") case-sensitively. This inconsistent check will reject valid case variations like "gmt+05:00" (which the earlier logic already accepted as a GMT-prefix ID) and fall back to plain GMT instead of a fixed offset.
- Files reviewed: 74/76 changed files
- Comments generated: 0 new
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
The primitive probes came back entirely clean on Windows: create, graphics, antialias, blur supported, the blur call, graphics on the blurred image -- every one non-null. So the gaussian-blur theory is dead alongside the font-height one, and getPreferredSize still throws. The difference I had missed is that my probe called Image.createImage directly while Switch goes through ImageFactory.createImage(context, ...) with the component as context, which walks the parent chain looking for a per-component factory -- and at sizes derived from the font rather than my arbitrary 32x24. That exact call is now probed, at the size the switch computes. Also probing an OFF switch's preferred size. The ON/OFF split may be an artifact: the earlier OFF probe only ever called addContent, never getPreferredSize, so it may throw identically and the state is a red herring. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4aab910910
ℹ️ 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".
Two facts this round, both new. An OFF switch's getPreferredSize WORKS on Windows -- probe-off-preferredsize-ok -- and the ON switch's throws. So the ON/OFF split is real, not an artifact of which probe happened to compute a size. And the ImageFactory path is clean: create through the factory at the size the switch computes, take graphics, antialias, all fine. That leaves exactly one thing the ON path does that the OFF path does not. calcPreferredSize calls getCurrentThumbImage, then both track images; the tracks are shared, so the difference is getThumbOnImage vs getThumbOffImage. The ON thumb hard-codes shadowSpread=2 while the OFF thumb reads switchThumbShadowSpreadInt, which Material 3 sets to 0 for a flat thumb -- and a spread of 0 skips the drop-shadow branch entirely. The ON thumb is therefore the only one that ever reaches the blur. My earlier blur probe passed because it blurred a BLANK image. The real branch draws the shadow rings first, so the blur reads back a Direct2D target with an open draw batch. The probe now does that: create, draw, blur, take graphics -- and reports switchThumbShadowSpreadInt so the premise is checked rather than assumed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 89590b3dcf
ℹ️ 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".
switchThumbShadowSpreadInt is 0 on Windows, confirming the premise: the OFF thumb skips the drop-shadow branch and the ON thumb always enters it, which is the whole of the ON/OFF split. But create -> draw -> blur -> graphics all pass, so the blur itself is not it. The one call calcPreferredSize makes on the blur result that no probe has made is getWidth(). It matters here: the Windows blur returns Image.createImage(argb, w, h) rather than the mutable surface it was handed, so the result's dimensions come from a different native than the one every passing probe exercised. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27121ff241
ℹ️ 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".
External reproduction is exhausted: every step of the thumb branch passes when driven from the test at the exact size Switch uses -- create through ImageFactory, draw, blur, graphics, antialias, and getWidth on the blur result (34x34). Yet getPreferredSize still throws on an ON switch while an OFF switch answers fine, and switchThumbShadowSpreadInt=0 confirms the ON thumb is the only one that reaches the drop-shadow branch. So instrument the real path rather than a copy of it. createRoundThumbImage now fails with a named IllegalStateException when the factory, the blur, or either graphics comes back null, and calcPreferredSize names which of thumb/trackOn/ trackOff is null instead of letting the arithmetic throw. This does not paper over anything -- every one of these still fails the test -- it replaces a NullPointerException that carries no stack on ParparVM with a sentence saying what was null, which is the difference between one more round and an answer. Audio: the fresh reader did not change the symptom, and that is itself informative. A newly opened reader cannot be at EOF, so ENDOFSTREAM on its first read means the file has an audio stream header and no samples -- the writer, not the reader. videoWriterClose now reports how many audio samples and bytes were actually handed to the sink writer, plus the Finalize HRESULT. Note: the local xwin cross-link currently fails on bcrypt symbols in code this commit does not touch, with bcrypt.lib present in the sysroot. That looks like local toolchain state rather than these changes -- CI does its own cross-build and will say. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…cepts Three defects and one diagnostic, all found by reading the last run's evidence rather than by guessing. gaussianBlurImage on the Windows port returned Image.createImage(int[], w, h), which builds an ARGB-backed image with no Direct2D render target. Callers composite ON TOP of a blur result -- Switch blurs its thumb's drop shadow and then draws the knob onto it -- and getImageGraphics answers 0 for such an image, so Graphics wraps a null peer and every later draw either vanishes or dereferences it. The Linux port creates a target on demand for any image and JavaSE hands back a BufferedImage's graphics, so Windows was the outlier. Blit the blurred pixels into a mutable image before returning. The video writer reported hasAudio=0 at close for a clip the caller asked to have audio: Media Foundation's AAC encoder publishes input types at 44100 and 48000 Hz only, so AddStream failed for the suite's 8 kHz tone and the failure was swallowed by clearing hasAudio. The file then carried video alone while the writer reported success -- which is why a freshly opened reader, which cannot be at EOF, still hit ENDOFSTREAM on its first audio read. Configure the encoder at a rate it accepts, resample the incoming PCM to it, round the byte rate to a published value, and give the PCM input type the block alignment and byte rate it was missing. The AddStream/SetInputMediaType HRESULT is now reported at close instead of being discarded. ParparVM's Throwable.getStackTrace() is a stub that always answers an empty array, but the VM does record frames: the native fillInStack walks threadStateData->callStack when the throwable is constructed, and printStackTrace is the only accessor for the result. Asking getStackTrace and stopping there is why a NullPointerException on Windows arrived with no location at all. The runner now falls back to printStackTrace, which costs nothing on the JVM ports where the frames are non-empty. Review feedback, all six open threads: - The report sweep no longer treats a browser-evidence dispatch as the newest JavaScript producer. port-status-environment.json is excluded from the port report scan, and a successful run that uploaded it while naming none of the ports its workflow owns is skipped so newest_candidate advances. Gated on success so a producer that died before normalization still trips the strict checks. - The nightly site rebuild gets always(), so a browser-evidence failure no longer strands the reports the sweep just published. - ECB rejects any non-null IV on both desktop ports, not just a non-empty one: JavaSE branches on iv != null and ECB refuses the resulting IvParameterSpec. - An unfinished report that declares missing workloads must be labelled partial; port-status.html renders any benchmark whose status is complete. - Per-test "reasons" is validated as an array of strings, so a malformed one is a single unusable report rather than a failed Hugo build for the site. New tests: test_publishable_rejects_a_complete_label_on_partial_benchmark_data, test_publishable_rejects_a_malformed_reason_list and a positive counterpart. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…t it The bisect instrumentation has served its purpose -- the Windows NPE is understood and fixed in the previous commit -- so it comes out. What replaces it is the one check none of it started as: draw on the result of a blur. That gap is why this took so many rounds. Every probe passed while the real code faulted, because the probes stopped at Graphics.setAntiAliased, which the Windows port does not override and CodenameOneImplementation implements as an empty method: it never touches the native peer. concatenateAlpha is the first call that reads through it, and that is exactly the next statement in Switch.createRoundThumbImage after the blur. The full chain, for the record: gaussianBlurImage returned an ARGB-backed image whose mutableGraphics is NULL, getImageGraphics answered 0, core's getGraphics wrapped that in a Graphics (it never returns null, which is why the null guard added earlier could not fire), and getAlpha dereferenced g->alpha at a null address. cn1WinFaultToException maps a fault below 0x10000 to a synthesized NullPointerException -- hence no message, no frames, and nothing to locate it by. Only the ON thumb reaches it: the OFF thumb takes its shadow spread from switchThumbShadowSpreadInt, which the Material 3 theme sets to 0, so it never blurs. The replacement covers both shapes -- the blur-then-draw sequence in the order Switch performs it, and an ON switch's preferred size -- and stays on a throwaway Accordion so the kotlin golden is untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
kotlin, SwitchTheme_light and SwitchTheme_dark have never had a Windows reference image, because the port could not render a Switch: the ON thumb faulted in the blur path and both tests died before capture. With that fixed all three render, so the reports moved from "failed=NullPointerException" to "screenshot-missing_expected" -- the last step being the absent baseline. Taken from the CI artifact of run 31158011821, never from a local build, and checked before being committed rather than trusted for merely existing: all three match the Linux references pane for pane -- off thumb grey on a light track, ON thumb white on the purple pill with its drop shadow, disabled thumb flat -- differing only in canvas size (784x561 against 800x600) and font rasterisation. The kotlin capture shows Details / Preferences / Summary and nothing else, confirming the diagnostic accordion stays off the captured form. Windows is now pass=168 fail=2 skip=1, with both remaining failures being these missing baselines. VideoIORoundTripTest passes: the writer reports audioSamples=6 audioBytes=95976 hasAudio=1 encRate=48000 and the reader gets 48 reads / 96256 bytes back at 48 kHz. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
When Windows code calls Object.wait() with a timeout of at least 4,294,967,296 ms (about 49.7 days), wait_ms exceeds the 32-bit DWORD accepted by SleepConditionVariableSRW and this cast wraps it to a much shorter delay; a timeout congruent to 0xffffffff is even converted to Win32's INFINITE sentinel and may never expire. Long-duration waits, including the common wait(Long.MAX_VALUE) parking pattern, therefore return early or hang indefinitely on the new Windows compatibility path. Split the remaining duration into bounded chunks rather than narrowing it directly.
ℹ️ 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".
I had been reading review threads one page at a time and never paginating, so
"6 unresolved" was wrong: there are 113 threads and 13 were open. All of them
are addressed here.
Sweep and publication:
- Strictness is now scoped to scheduled and push runs. A workflow_dispatch
carries arbitrary inputs and routinely runs a subset on purpose --
scripts-ios.yml with watch_only skips the GL, Metal and tv legs, and
scripts-javascript.yml with port_status_browser_evidence skips its screenshot
job entirely -- so treating whichever run happened to be newest as the
authoritative producer failed the sweep for ports nobody asked to run. Their
reports are still merged and still win on recency; only the "must cover every
port" demand moves to the runs that are supposed to. This replaces the
narrower browser-evidence heuristic from the previous commit, which the
watch_only report showed was the same bug seen through one keyhole.
- port-status-publish.yml no longer requires conclusion == 'success'. The strict
gate fails a producer precisely when a test failed or never ran, so demanding
success published only the good news; the Linux producer can also finish after
the nightly snapshot, leaving the previous green report public for a further
day. A failed run with no artifacts is no longer a second red X.
- publish_port_status.sh propagates the acceptance status instead of always
exiting zero, so an unusable report fails its publishing workflow. Contract
drift stays quiet, which is what it is for.
Report validation -- each of these reached Hugo and could take the site build
down, which is worse than rejecting one report:
- suite_finished must be an actual boolean. bool() accepted "false" and 1.
- A test status is checked with isinstance before set membership; an unhashable
one raised TypeError past main()'s ContractError handler.
- Summary counts must be non-boolean non-negative integers. Python's True == 1
meant a count of exactly one serialized as a boolean compared equal.
- performance.status is validated for unfinished reports too; `eq .status
"complete"` against a map aborts the whole build.
Presentation:
- The errata list applies the same reason-code and port predicate the feature
cell uses. Listing every skip by test name alone filed a Linux encoder failure
under an erratum explaining an Apple simulator limitation, contradicting the
cell beside it.
- A port card accounts for not-run. Reading only summary.fail rendered a green
"Suite completed" card for a report from a red run.
Native and port:
- fileRename resolves the absent separator before comparing. One of wcsrchr's
results is NULL for any ordinary path, and relational comparison against a
null pointer is undefined behaviour -- an optimizing build picking NULL drops
the parent directory and puts the rename back where this join was meant to
stop it going.
- readAudio configures the fresh reader completely or discards it. Every call
was unchecked, so a reader that could not select its stream or negotiate PCM
was used anyway, returning compressed bytes labelled as 16-bit PCM.
- timegm no longer delegates to _mkgmtime, which is documented to start at the
epoch and returns -1 below it -- so every pre-1970 zone lookup collapsed to
-1 and was evaluated at 1969-12-31T23:59:59Z, answering a 1900 Europe/Paris
query with 1969's rules. Verified against Python for 1583, 1600, 1900, 1930,
1969, 1970, 2020 and 2100: exact on all eight, including the four the host's
own timegm cannot represent.
- checkKeyFamily requires the key label to be exactly RSA or EC. startsWith("EC")
called "ECfoo" an EC key and every other string an RSA one, while JavaSE hands
the label to KeyFactory.getInstance and throws.
Verification: 34 port-status tests pass (4 new), both desktop ports build, both
Windows natives cross-compile, the site builds under Hugo and
validate_port_status.mjs passes against the generated page.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two findings that were filed in review BODIES rather than as threads, which is
why the thread query never surfaced them.
pthread_cond_timedwait narrowed a 64-bit millisecond deadline straight to a
32-bit DWORD. Object.wait(Long.MAX_VALUE) -- the ordinary park-until-notified
idiom -- yields a wait of roughly 292 million years, so the truncation produced
an arbitrary short timeout, and a value whose low word happened to be
0xFFFFFFFF became Win32's INFINITE and would never expire. It now waits in
bounded ~24.8 day chunks and reports ETIMEDOUT only once the absolute deadline
has actually passed. A spurious wake still returns success, which is correct:
every caller re-tests its predicate.
The other finding -- that customTimeZone() is inconsistent for mixing a
case-INSENSITIVE regionMatches prefix test with a case-SENSITIVE
startsWith("GMT") acceptance test -- is not a defect, and I checked before
concluding that rather than after. Run against a real JDK 25:
GMT+05:00 -> id=GMT+05:00 raw=18000000
gmt+05:00 -> id=GMT raw=0
Gmt+05:00 -> id=GMT raw=0
gmt+5 -> id=GMT raw=0
utc+05:00 -> id=GMT raw=0
gmt-08:00 -> id=GMT raw=0
The JDK's parseCustomTimeZone tests `id.indexOf("GMT") != 0`, which is
case-sensitive, and the zone-name lookup ahead of it is case-sensitive too, so
every lowercase spelling answers plain GMT with a zero offset. The port already
matches that exactly. The two prefix tests answer different questions on
purpose: the insensitive one decides whether an id is an offset ATTEMPT (so it
falls back to GMT instead of to the platform database, where POSIX would invert
the sign), the sensitive one decides whether to HONOUR it.
Rather than leave that resting on an argument in a review thread, the seven
spellings are added to CustomTimeZoneApp, which compares ids and offsets
against the host JDK through the ParparVM clean target.
CustomTimeZoneIdTest passes with tests=1 failures=0 skipped=0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6559b6c9e1
ℹ️ 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".
| */ | ||
| @Override | ||
| public String getAppHomePath() { | ||
| String dir = WindowsNative.storageDir(); |
There was a problem hiding this comment.
Keep each Windows app home in its own directory
When two Windows Codename One applications run under the same user account, this new override returns the same %LOCALAPPDATA%\CodenameOne\ app home for both because WindowsNative.storageDir() contains no application identifier. Files created through FileSystemStorage.getAppHomePath() can therefore be read or overwritten by another CN1 application; preserve the writable base directory but append a stable package/application-specific component as the inherited implementation did.
Useful? React with 👍 / 👎.
| ERR_clear_error(); | ||
| cursor = der; | ||
| key = d2i_AutoPrivateKey(0, &cursor, (long) length); |
There was a problem hiding this comment.
Reject non-PKCS#8 private-key encodings
When a caller passes bare PKCS#1 RSA or SEC1 EC bytes to PrivateKey.fromPkcs8(), this fallback accepts them and signing/decryption succeeds on Linux. The public factory requires PKCS#8, while JavaSE and Android use PKCS8EncodedKeySpec and Windows imports NCRYPT_PKCS8_PRIVATE_KEY_BLOB, so the identical key is rejected on every other desktop/mobile implementation; remove the auto-private-key fallback or expose a separately documented factory for these encodings.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 86cfcb5d14
ℹ️ 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".
| return retriedTestIndex != index | ||
| && !"HTML5".equals(Display.getInstance().getPlatformName()) | ||
| && !testClass.isFailed() | ||
| && !testClass.isCaptureStarted() | ||
| && testClass.shouldTakeScreenshot(); | ||
| && !testClass.isCaptureStarted(); |
There was a problem hiding this comment.
Avoid retrying asynchronous non-screenshot tests
When an asynchronous native test exceeds the deadline without setting failed—for example, VideoIORoundTripTest.runTest() starts a detached worker and immediately returns—this predicate now retries the same BaseTest instance while the original worker is still running. resetForRetry() clears the shared completion state, so a late done() from the first worker can complete the second attempt and advance the suite before that attempt finishes, masking its timeout or failure and allowing background work to bleed into later tests; retain the non-screenshot/idempotence gate or isolate attempts with cancellation or generation tokens.
Useful? React with 👍 / 👎.
build-test (17) failed with "failed to resolve source metadata for docker.io/library/alpine:latest" after three retries. That is a Docker Hub outage, but the job had no business talking to Docker Hub at all: the only thing that needed it was the "Copying Files to Server" step, which is gated on `github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.java-version == 8` and therefore could never run on a pull request, let alone on the Java 17 leg. A Docker-based action is BUILT during job setup, before any step's `if` is evaluated. So every leg of every PR run was pulling alpine:latest to build an action none of them would execute, and any Docker Hub wobble failed the build for a deploy that was not happening. Retrying the job would have papered over an entirely avoidable dependency. The deploy moves to its own job with the condition at JOB level, which skips setup outright, so a pull request never fetches the image. build-test hands the bundle over as an artifact, uploaded only on the master pushes that actually deploy, so PR runs do not pay for that either. Verified actions/download-artifact@v7 exists and pairs with the actions/upload-artifact@v7 already used here, and that this was the only non-actions/ action in the workflow. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Why
The Port Status page reported almost every port as partial, skipped or stale. Most of that was the reporting pipeline lying about healthy ports; the rest was real defects in the desktop ports that nothing was failing on.
Before / after, from a local build of the page:
Every port now publishes a current report, so no column falls back to a
checked-in copy and none renders stale. Nine are green on this branch. The two
Windows cards are the remaining gap and are being worked in this PR, not
deferred:
windows-x64reports pass=166 fail=4, against master's pass=160fail=7 — and master ships those seven under a green workflow, because
Windows was the only producer that never set
CN1SS_FAIL_ON_TEST_PROBLEMS.The four that remain are
AudioMixerApiTest,VideoIORoundTripTest,KotlinUiTestandSwitchThemeScreenshotTest.Reporting pipeline
Every fresh Apple report was being thrown away.
sync_port_status_reports.shre-implemented the publish rule as a jq expression demanding a measured duration for all ten performance workloads. iOS, tvOS and watchOS legitimately skip the three GC-footprint workloads on the simulator (performance.skipped, which the normalizer supports and has a unit test for), so each night's report was rejected, the site fell back to the checked-in copy, and after fourteen days those four columns went stale.The rule now lives once, in
port_status.py(publishable_report_problems+ anacceptsubcommand the shell calls), beside the normalizer whose tests already covered skipped workloads. Contract drift — a report produced before a newly registered test — keeps the fallback with a warning; a malformed report now fails the website build instead of degrading quietly. Six new tests cover it, including one asserting every checked-in report is itself publishable.Linux and Windows have never published a report.
port-status-publish.ymlreacts toworkflow_run, and those events are not delivered for those two producers — Android/iOS/macOS/JavaScript get a publish run about three seconds after their run completes, Linux and Windows get none, and the data branch has nolinux-*orwindows-x64file in its entire history. Rather than keep guessing at that, the nightly now runsbackfill_port_status.sh: it publishes from the newest completed master run of every producing workflow and then fails if any port lacks a report inside the contract's staleness window, so a silent producer is a red workflow instead of a grey column.Nothing failed when a compliance test failed. Only the Android pipeline set
CN1SS_FAIL_ON_TEST_PROBLEMS. iOS (4 legs), macOS and JavaScript now set it too — all three are at zero failures and zero never-run tests today, so it is a ratchet, not a new red.Presentation. A skip the errata account for by name now renders as a pass with a marked note (
✓*) and its own legend entry, and the page validator refuses a noted cell whose test the errata do not cover. A run that stopped early no longer withdraws the result of a feature whose every mapped test reported back — the unreached tests still show as not-run and the port card still says the run was incomplete.Desktop port defects
Each of these was reproduced against the ParparVM clean target before and after the fix.
java.timeconverted aZoneOffsetto"GMT-05:00"and handed it to the platform. POSIX inverts the sign of aTZoffset, and the Windows CRT cannot parse the form at all, so everyOffsetDateTimeformatted through a pattern came out shifted by twice its offset —2020-03-08T01:30-05:00printed as11:30-05:00. CustomGMT/UTC/UTIDs are now resolved in Java, and aZoneOffsetnever reaches the host database. All ofTimeApiTest's zone assertions pass locally now, including both DST transitions.Calendar, which rebuilds local time from a raw offset plus a flat one-hour daylight guess. They now come fromTimeZone.getOffset, which consults the platform's real rules.Character.getTypethrewUnsupportedOperationException, soisLetter,isLetterOrDigit,isJavaIdentifierStartandisJavaIdentifierPartthrew for every input on these ports. ASCII now has a category table; above it the answer comes from the primitives this runtime actually implements.openInputStreamreturned a stream over a null file handle for a missing path, so a caller could not distinguish a missing file from an empty one — issue on iOS openInputStream for non-existent file do not throw FileNotFoundException #1502's exact defect, on both desktop ports.openOutputStreamand the storage streams discarded writes the same way.CameraApiTestassumed the native Linux port had a headless camera. It drives real V4L2 devices through GStreamer, which a hosted runner does not have, so it now skips with a stated reason like the other native ports; the existing camera erratum covers it.CN1_REQUIRE_SUITE, so it can demand the suite's own completion marker instead of stopping once screenshots go quiet — which it did while DesktopMode, the VideoIO grid, the VR scene and the 360 panorama were still queued, leaving every trailing test reported as never run.Crypto (added after the first review round)
Both desktop ports now answer the whole
com.codename1.securitysurface, whichCryptoApiTestwas failing at its first call:libcryptocomes with thelibcurlthe port already links. The implementation was exercised against reallibcryptooff-device before landing: GCM round trip, tamper and wrong-AAD rejection, CBC with padding, OAEP round trip, and sign/verify including tampered-data and wrong-key rejection.BCRYPT_RSAKEY_BLOB.The shared UTF-8 buffer
stringToUTF8returns one buffer per thread and overwrites it on every call, so a native that converted a second String silently repointed the first result at the second string. Five natives in the Linux port did exactly that:fileRenamerenamed a file onto itself — which is whyWAVWriter's rename step leftAudioMixerApiTestwith no output;httpSetHeadersent every request header as"value: value";printDocument,showNotificationandshareTexteach collapsed their arguments onto the last one.They now copy through
cn1LinuxJStrDup, documented in the header as mandatory for any native converting more than one String. The Windows port was already safe — its wide-string helper allocates.Still red after this change
Stated plainly rather than hidden:
Media360PanoramaScreenshotTeston Linux andCalendarApiTeston Windows. The runner's per-test deadline is enforced by an EDT callback, so a test that blocks the thread outright could never be timed out: the suite just stopped, mid-log-line, and every later test was published as "never run" with nothing naming the cause. A watchdog thread now reports the responsible test and exits, so the report attributes the failure instead of silently truncating. Fixing the two tests themselves needs profiling on those platforms — the Linux one is most likely the software Mesa rasterizer taking minutes over a stereo 360 sphere.java.util.Calendarstill mishandles daylight saving on these ports.java.timeno longer depends on it; the legacy class is a separate fix.Verification
port_status.py validateand the 16 normalizer tests pass.validate_port_status.mjspasses against the generated page.backfill_port_status.shwas dry-run against the live GitHub API: it selects the newest master run for all seven producing workflows and would publish the seven stale or missing reports.java.time,TimeZoneandCharacterfixes were each verified by building and running a probe through the ParparVM clean target.🤖 Generated with Claude Code