Skip to content

Fix 2 bugs (NdefRecord URI, OpenAiClient error swallowing) + add 250 unit tests across 16 previously-0%-coverage classes#5233

Merged
shai-almog merged 5 commits into
masterfrom
nfc-uri-fix-and-coverage
Jun 12, 2026
Merged

Fix 2 bugs (NdefRecord URI, OpenAiClient error swallowing) + add 250 unit tests across 16 previously-0%-coverage classes#5233
shai-almog merged 5 commits into
masterfrom
nfc-uri-fix-and-coverage

Conversation

@shai-almog

@shai-almog shai-almog commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two correctness fixes plus 250 unit tests covering 16 classes that were at 0% line coverage, spanning pure-logic, network/HTTP, and UI. Everything drives the real public APIs against the in-tree mock platform (UITestBase + TestCodenameOneImplementation). No Mockito, no reflection, no visibility widening.

Bug fixes (each with a test that fails without the fix)

  1. NdefRecord.getUriPayload() returned null for TNF_ABSOLUTE_URI records with an empty payload (the URI lives in the type field; the payload.length < 1 guard short-circuited first). Moved the absolute-URI branch ahead of the guard.

  2. OpenAiClient.chat/embed swallowed HTTP errors. With readResponseForErrors=true and handleErrorResponseCode suppressed, the framework routes 4xx/5xx through postResponse(), which parsed the {"error":...} envelope as an empty successful ChatResponse — so the typed mapErrorStatic classification never fired. postResponse now inspects the status code (and a 200 carrying an error envelope) and surfaces the typed LlmException. Tests assert AUTH / RATE_LIMIT / INVALID_REQUEST / SERVER / MODEL_OVERLOADED / CONTEXT_LENGTH mapping + the 200-with-error and embeddings paths.

New coverage

Class Tests Kind
nfc.NdefRecord 25 pure logic
nfc.NdefMessage 17 pure logic
io.grpc.ProtoWriter 17 pure logic
io.grpc.ProtoReader 24 pure logic
io.grpc.GrpcWeb 20 network + framing
io.JSONWriter 14 pure logic
binding.Binders 14 logic
gpu.GltfLoader 11 glTF/GLB parser
util.Base64 7 pure logic
io.oidc.OidcClient 21 network
ai.OpenAiClient 19 network
io.graphql.GraphQLSubscription 7 network
social.Auth0Connect 15 network (OIDC + passkey)
social.AppleSignIn 18 native/web sign-in
components.OtpField 21 UI component

Paths that genuinely require a live browser, WebSocket, or native sheet are driven up to the deterministic boundary (guards, builders, request/response parsing, error mapping) with the unreachable remainder noted, rather than faked brittlely. Source changes are limited to the two fixes above.

Testing

All 250 tests pass on JBR-17:

Tests run: 250, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

🤖 Generated with Claude Code

… add NFC/grpc unit tests

NdefRecord.getUriPayload() returned null for any TNF_ABSOLUTE_URI record
with an empty payload, because the leading `payload.length < 1` guard
short-circuited before the absolute-URI branch ran. An absolute-URI
record carries its URI in the type field and commonly has no payload, so
this was always broken for that record type. Move the TNF_ABSOLUTE_URI
branch ahead of the payload-length guard (the guard is only needed by the
well-known URI form, whose prefix code lives in payload[0]).

Also adds unit-test coverage for four previously-uncovered pure-logic
classes (all were at 0% line coverage):
- com.codename1.nfc.NdefRecord (25 tests)
- com.codename1.nfc.NdefMessage (17 tests)
- com.codename1.io.grpc.ProtoWriter (17 tests)
- com.codename1.io.grpc.ProtoReader (24 tests)

Tests drive the real public APIs only -- no mocks, reflection, or
internal-state exposure -- and exercise round-trips, canonical protobuf
byte sequences, defensive-copy guarantees, proto3 default omission, and
malformed-input handling. Includes a regression test for the URI fix.

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

shai-almog commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 128 screenshots: 128 matched.

Native Android coverage

  • 📊 Line coverage: 14.22% (8647/60799 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 11.51% (42610/370069), branch 5.06% (1762/34801), complexity 6.05% (2017/33356), method 10.47% (1633/15593), class 17.14% (377/2200)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 14.22% (8647/60799 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 11.51% (42610/370069), branch 5.06% (1762/34801), complexity 6.05% (2017/33356), method 10.47% (1633/15593), class 17.14% (377/2200)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
SIMD kernel backend scalar fallback (no native SIMD)
SIMD int-add (64K x300) java 162ms / native 75ms = 2.1x speedup
SIMD float-mul (64K x300) java 173ms / native 80ms = 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 271.000 ms
Base64 CN1 decode 326.000 ms
Base64 native encode 930.000 ms
Base64 encode ratio (CN1/native) 0.291x (70.9% faster)
Base64 native decode 1088.000 ms
Base64 decode ratio (CN1/native) 0.300x (70.0% faster)
Image encode benchmark status skipped (SIMD unsupported)

@github-actions

Copy link
Copy Markdown
Contributor

Cloudflare Preview

@github-actions

github-actions Bot commented Jun 12, 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)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 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.

Broadens coverage beyond pure-logic classes: OidcClient was 1050 missed
instructions at 0% coverage because its main paths (discovery, the
token-endpoint POST, revocation) are network-bound. These are now driven
against the real mock platform -- UITestBase for an initialized Display
and TestCodenameOneImplementation.addNetworkMockResponse for HTTP -- with
no Mockito and no reflection.

21 tests covering:
- discover(): success, trailing-slash tolerance, empty-document failure,
  null-issuer guard
- refresh()/token-endpoint POST: token exchange + persistence,
  refresh-token fallback, OAuth error-field surfacing, guards
- revoke(): null token, no-endpoint, and success responses
- refreshIfExpired()/loadStoredTokens() with an in-memory TokenStore
- configuration guards and chainable setters

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shai-almog shai-almog changed the title Fix NdefRecord.getUriPayload for empty-payload absolute-URI records + add NFC/grpc unit tests Fix NdefRecord.getUriPayload + add NFC, grpc-proto, and OidcClient unit tests Jun 12, 2026
@shai-almog

shai-almog commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 56ms / native 4ms = 14.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 278.000 ms
Base64 CN1 decode 199.000 ms
Base64 native encode 668.000 ms
Base64 encode ratio (CN1/native) 0.416x (58.4% faster)
Base64 native decode 314.000 ms
Base64 decode ratio (CN1/native) 0.634x (36.6% faster)
Base64 SIMD encode 56.000 ms
Base64 encode ratio (SIMD/CN1) 0.201x (79.9% faster)
Base64 SIMD decode 57.000 ms
Base64 decode ratio (SIMD/CN1) 0.286x (71.4% faster)
Base64 encode ratio (SIMD/native) 0.084x (91.6% faster)
Base64 decode ratio (SIMD/native) 0.182x (81.8% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 17.000 ms
Image createMask (SIMD on) 7.000 ms
Image createMask ratio (SIMD on/off) 0.412x (58.8% faster)
Image applyMask (SIMD off) 82.000 ms
Image applyMask (SIMD on) 58.000 ms
Image applyMask ratio (SIMD on/off) 0.707x (29.3% faster)
Image modifyAlpha (SIMD off) 71.000 ms
Image modifyAlpha (SIMD on) 44.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.620x (38.0% faster)
Image modifyAlpha removeColor (SIMD off) 69.000 ms
Image modifyAlpha removeColor (SIMD on) 41.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.594x (40.6% faster)

@shai-almog

shai-almog commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

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

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 94000 ms
Simulator Boot (Run) 1000 ms
App Install 16000 ms
App Launch 12000 ms
Test Execution 283000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 287ms / native 3ms = 95.6x speedup
SIMD float-mul (64K x300) java 147ms / native 4ms = 36.7x 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 401.000 ms
Base64 CN1 decode 537.000 ms
Base64 native encode 1275.000 ms
Base64 encode ratio (CN1/native) 0.315x (68.5% faster)
Base64 native decode 580.000 ms
Base64 decode ratio (CN1/native) 0.926x (7.4% faster)
Base64 SIMD encode 127.000 ms
Base64 encode ratio (SIMD/CN1) 0.317x (68.3% faster)
Base64 SIMD decode 110.000 ms
Base64 decode ratio (SIMD/CN1) 0.205x (79.5% faster)
Base64 encode ratio (SIMD/native) 0.100x (90.0% faster)
Base64 decode ratio (SIMD/native) 0.190x (81.0% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 26.000 ms
Image createMask (SIMD on) 3.000 ms
Image createMask ratio (SIMD on/off) 0.115x (88.5% faster)
Image applyMask (SIMD off) 107.000 ms
Image applyMask (SIMD on) 71.000 ms
Image applyMask ratio (SIMD on/off) 0.664x (33.6% faster)
Image modifyAlpha (SIMD off) 347.000 ms
Image modifyAlpha (SIMD on) 375.000 ms
Image modifyAlpha ratio (SIMD on/off) 1.081x (8.1% slower)
Image modifyAlpha removeColor (SIMD off) 287.000 ms
Image modifyAlpha removeColor (SIMD on) 360.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 1.254x (25.4% slower)

… UI)

Extends the coverage push to a broad set of previously-untested classes,
132 new tests total, all driving the real public APIs against the in-tree
mock platform (UITestBase + TestCodenameOneImplementation). No Mockito,
no reflection, no visibility widening.

Pure logic:
- com.codename1.io.JSONWriter            (14) serializer, escaping, builders
- com.codename1.binding.Binders          (14) registry, bind, update regions
- com.codename1.gpu.GltfLoader           (11) glTF/GLB parse, normals, errors

Network / HTTP (mocked via addNetworkMockResponse):
- com.codename1.io.grpc.GrpcWeb          (20) framing, decode, unary call
- com.codename1.ai.OpenAiClient          (12) chat/embeddings parse, config
- com.codename1.io.graphql.GraphQLSubscription (7) guards, payload, endpoint

Social / UI:
- com.codename1.social.Auth0Connect      (15) passkey challenge/register flows
- com.codename1.social.AppleSignIn       (18) native packed-result parse, web
- com.codename1.components.OtpField       (21) value, auto-advance, paste

Paths requiring a live browser/WebSocket/native sheet are driven up to the
deterministic boundary (guards, builders, request/response parsing, error
mapping) and the unreachable remainder noted, rather than faked brittlely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shai-almog shai-almog changed the title Fix NdefRecord.getUriPayload + add NFC, grpc-proto, and OidcClient unit tests Fix NdefRecord.getUriPayload + add 236 unit tests across 14 previously-0%-coverage classes Jun 12, 2026
…ting tests

Two fixes surfaced by the coverage work, each with tests that fail without
the fix and pass with it.

OpenAiClient.chat/embed: because configureRequest sets
readResponseForErrors=true and the client suppresses handleErrorResponseCode,
the framework routes HTTP 4xx/5xx through postResponse() (never
handleException). The old postResponse parsed the error body with the lenient
non-streaming parser, turning an {"error":...} envelope into an empty,
successful ChatResponse -- so the rich OpenAiSseDecoder.mapErrorStatic
status->ErrorType classification never fired. postResponse now inspects the
status code (and a 200 carrying an {"error":...} body) and surfaces the typed
LlmException via mapErrorStatic. New tests assert AUTH/RATE_LIMIT/
INVALID_REQUEST/SERVER/MODEL_OVERLOADED/CONTEXT_LENGTH mapping plus the
200-with-error-envelope and embeddings error paths.

Base64.allocByteMaybeSimd: called Simd.get() ->
Display.getInstance().getSimd() unguarded, raising a raw NullPointerException
when Base64 is used before Display is initialized (early boot, background
threads, tests) for any output >= 16 bytes. Now wrapped in try/catch(Throwable)
with a plain-array fallback, mirroring VertexBuffer.allocAligned. New
Base64Test (plain, no Display) covers encode/decode/url-safe round-trips over
the >=16-byte SIMD-allocation path; reverting the guard makes 6 of its 7
tests NPE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shai-almog shai-almog changed the title Fix NdefRecord.getUriPayload + add 236 unit tests across 14 previously-0%-coverage classes Fix 3 bugs (NdefRecord URI, OpenAiClient error swallowing, Base64 pre-init NPE) + add 250 unit tests across 16 previously-0%-coverage classes Jun 12, 2026
Pre-init usage of Base64 (before Display is initialized) is not a supported
scenario, so the allocByteMaybeSimd try/catch guard was solving a non-problem
(a test-harness artifact, not a real-world code path). Reverts that source
change -- Base64.java is now byte-identical to master.

Base64Test is retained for the genuine coverage value but now extends
UITestBase so Display is initialized exactly as in real usage; the pre-init
framing and reverting-the-guard commentary are removed. Still covers
encode/encodeNoNewline/encodeUrlSafe/decode round-trips across all
length-mod-3 cases and the >= 16-byte SIMD-allocation path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@shai-almog shai-almog changed the title Fix 3 bugs (NdefRecord URI, OpenAiClient error swallowing, Base64 pre-init NPE) + add 250 unit tests across 16 previously-0%-coverage classes Fix 2 bugs (NdefRecord URI, OpenAiClient error swallowing) + add 250 unit tests across 16 previously-0%-coverage classes Jun 12, 2026
@shai-almog

shai-almog commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator Author

Compared 124 screenshots: 124 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

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

Build and Run Timing

Metric Duration
Simulator Boot 139000 ms
Simulator Boot (Run) 1000 ms
App Install 20000 ms
App Launch 37000 ms
Test Execution 366000 ms

Detailed Performance Metrics

Metric Duration
SIMD kernel backend SSE2 (x64) / NEON (arm64) native kernels
SIMD int-add (64K x300) java 164ms / native 3ms = 54.6x speedup
SIMD float-mul (64K x300) java 62ms / native 3ms = 20.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 510.000 ms
Base64 CN1 decode 464.000 ms
Base64 native encode 1645.000 ms
Base64 encode ratio (CN1/native) 0.310x (69.0% faster)
Base64 native decode 544.000 ms
Base64 decode ratio (CN1/native) 0.853x (14.7% faster)
Base64 SIMD encode 196.000 ms
Base64 encode ratio (SIMD/CN1) 0.384x (61.6% faster)
Base64 SIMD decode 206.000 ms
Base64 decode ratio (SIMD/CN1) 0.444x (55.6% faster)
Base64 encode ratio (SIMD/native) 0.119x (88.1% faster)
Base64 decode ratio (SIMD/native) 0.379x (62.1% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 68.000 ms
Image createMask (SIMD on) 8.000 ms
Image createMask ratio (SIMD on/off) 0.118x (88.2% faster)
Image applyMask (SIMD off) 114.000 ms
Image applyMask (SIMD on) 119.000 ms
Image applyMask ratio (SIMD on/off) 1.044x (4.4% slower)
Image modifyAlpha (SIMD off) 622.000 ms
Image modifyAlpha (SIMD on) 90.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.145x (85.5% faster)
Image modifyAlpha removeColor (SIMD off) 146.000 ms
Image modifyAlpha removeColor (SIMD on) 588.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 4.027x (302.7% slower)

@shai-almog shai-almog merged commit b8fbe71 into master Jun 12, 2026
32 of 34 checks passed
@shai-almog shai-almog deleted the nfc-uri-fix-and-coverage branch June 12, 2026 16:19
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