Skip to content

Add caching regression tests for FontRegistry - #4249

Open
HeikoKlare wants to merge 1 commit into
eclipse-platform:masterfrom
HeikoKlare:fontregistry-tests
Open

Add caching regression tests for FontRegistry#4249
HeikoKlare wants to merge 1 commit into
eclipse-platform:masterfrom
HeikoKlare:fontregistry-tests

Conversation

@HeikoKlare

Copy link
Copy Markdown
Contributor

Guard the font-caching invariants that FontRegistry relies on: get(), getBold() and getItalic() return the identical Font instance across repeated lookups, a symbolic name that was never registered stably falls back to the default font, and the default font stays stable when other names are looked up (including from a non-UI thread).

Also cover the surrounding put() contract: hasValueFor()/getKeySet() only reflect explicitly registered names, getFontData()/getDescriptor() fall back to the default like get() does, put() only fires a property change when the data actually changes, put() with new data invalidates previously cached base/bold/italic fonts, and a font replaced by put() stays usable until its Display is disposed rather than being disposed immediately.

Note

We are currently invesigating issues with FontRegistry in multi-display usage scenarios on Windows. In order to prevent regression (during according fixes and other changes to FontRegistry), this adds a bunch of tests for essential contracts of the class as the FontRegistry is badly tested right now.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Test Results

   858 files  ± 0     858 suites  ±0   51m 14s ⏱️ - 16m 13s
 8 171 tests +11   7 928 ✅ +11  243 💤 ±0  0 ❌ ±0 
20 415 runs  +33  19 759 ✅ +31  656 💤 +2  0 ❌ ±0 

Results for commit 93b0e24. ± Comparison against base commit 420efae.

♻️ This comment has been updated with latest results.

@HeikoKlare
HeikoKlare marked this pull request as ready for review August 13, 2026 17:47
Guard the font-caching invariants that FontRegistry relies on: get(),
getBold() and getItalic() return the identical Font instance across
repeated lookups, a symbolic name that was never registered stably
falls back to the default font, and the default font stays stable
when other names are looked up (including from a non-UI thread).

Also cover the surrounding put() contract: hasValueFor()/getKeySet()
only reflect explicitly registered names, getFontData()/getDescriptor()
fall back to the default like get() does, put() only fires a property
change when the data actually changes, put() with new data invalidates
previously cached base/bold/italic fonts, and a font replaced by put()
stays usable until its Display is disposed rather than being disposed
immediately.

Copilot AI 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.

Pull request overview

Adds regression tests to FontRegistry (JFace resources) to guard key caching and fallback invariants, especially around repeated lookups, default-font stability, and update/replace semantics (including multi-Display behavior on Windows).

Changes:

  • Add tests asserting stable/identical Font instances across repeated get() / getBold() / getItalic() calls.
  • Add tests for fallback behavior of unknown symbolic names and for hasValueFor() / getKeySet() only reflecting explicitly registered entries.
  • Add tests for put() semantics (property-change emission only on actual data changes, cache invalidation on updates, and delayed disposal until Display disposal).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +208 to +223
FontRegistry fontRegistry = new FontRegistry();
Display secondDisplay = initializeDisplayInSeparateThread();

Font original = secondDisplay.syncCall(() -> {
fontRegistry.put("myfont", new FontData[] { new FontData("Arial", 12, SWT.NORMAL) });
return fontRegistry.get("myfont");
});

secondDisplay
.syncExec(() -> fontRegistry.put("myfont", new FontData[] { new FontData("Arial", 18, SWT.BOLD) }));
// the font may still be in use elsewhere, so it must not be disposed right away
assertFalse(original.isDisposed(), "previous font must stay usable until its display is disposed");

secondDisplay.syncExec(secondDisplay::dispose);
assertTrue(original.isDisposed(), "stale font must be disposed once its display is disposed");
}
Comment on lines +173 to +174
assertEquals(fontRegistry.get(JFaceResources.DEFAULT_FONT), first);
assertEquals(first, second);
}

@Test
public void put_withNewDataInvalidatesPreviouslyCachedFont() {
Comment on lines +147 to +153
AtomicReference<Font> fontFromNonUIThread = new AtomicReference<>();
Font defaultFont = fontRegistry.get(JFaceResources.DEFAULT_FONT);
Thread nonUiThread = new Thread(() -> fontFromNonUIThread.set(fontRegistry.get("myfont")));
nonUiThread.start();
nonUiThread.join();
assertEquals(defaultFont, fontRegistry.get(JFaceResources.DEFAULT_FONT));
}
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.

2 participants