From 3d2bd895590c55beb0b9eb352b934328ed2d9692 Mon Sep 17 00:00:00 2001 From: David Dreschner Date: Tue, 27 Oct 2026 09:50:35 +0100 Subject: [PATCH] test(avatar): Check the guest avatar independent of the font renderer GuestAvatarTest::testGet() compared the generated PNG byte for byte with a stored image. The anti-aliasing of the letter depends on the GD and FreeType versions: the stored image matches Ubuntu 24.04 (libgd3 2.3.3-9ubuntu5, FreeType 2.13.2), while Ubuntu 26.04 (libgd3 2.3.3-13ubuntu2, FreeType 2.14.2) and the bundled GD of the official PHP images render a few edge pixels differently. The nodb jobs therefore fail whenever they run on a runner with the newer image. Check the PNG format, the image size and the guest background color in the light and the dark theme instead, and count the pixels in the letter color: the anti-aliased edges differ between renderers, the strokes of the letter don't. Also remove the SVG fixture, which has been unused since guest avatars switched to PNG. Assisted-by: ClaudeCode:claude-opus-5-5 Signed-off-by: David Dreschner --- tests/data/REUSE.toml | 2 +- tests/data/guest_avatar_einstein_32.png | Bin 272 -> 0 bytes tests/data/guest_avatar_einstein_32.svg | 5 --- tests/lib/Avatar/GuestAvatarTest.php | 43 +++++++++++++++++++----- 4 files changed, 35 insertions(+), 15 deletions(-) delete mode 100644 tests/data/guest_avatar_einstein_32.png delete mode 100644 tests/data/guest_avatar_einstein_32.svg diff --git a/tests/data/REUSE.toml b/tests/data/REUSE.toml index 3a19ce29f8384..b5456d1447111 100644 --- a/tests/data/REUSE.toml +++ b/tests/data/REUSE.toml @@ -94,7 +94,7 @@ SPDX-FileCopyrightText = "2018 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = ["integritycheck/mimetypeListModified/core/js/mimetypelist.js", "integritycheck/mimetypeListModified/core/signature.json", "guest_avatar_einstein_32.png", "guest_avatar_einstein_32.svg", "test.pdf"] +path = ["integritycheck/mimetypeListModified/core/js/mimetypelist.js", "integritycheck/mimetypeListModified/core/signature.json", "test.pdf"] precedence = "aggregate" SPDX-FileCopyrightText = "2019 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" diff --git a/tests/data/guest_avatar_einstein_32.png b/tests/data/guest_avatar_einstein_32.png deleted file mode 100644 index d03f0509bac3b028f15f29292a57ec8447c68966..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1SJ1Ryj={WI14-?iy0XBj({-ZRBb+Kpx_}- z7sn8f&g7b(KdqT{8HIg)<+mnWVOqr?rgXLT@7L!)pUY=7Dc#9olF7NU@xhVD+e?41 zTf~_*OY``P)4|7?I5J8vP85I8R@`dIX)!;AJLSg?5!RiYtDTve)g~!E_`bh>|Nno@ z#gQ{PclVoc2bs-re5S|0b%OANMax)Q!&U|DnNzS%g5TOvcS&S|g5nCLGtQHyO$-ik zIMAt{FJJeA>$w*9XAKU46Jkpu4gOw - - - E - diff --git a/tests/lib/Avatar/GuestAvatarTest.php b/tests/lib/Avatar/GuestAvatarTest.php index eed41e8221e82..cf91454eaaf4e 100644 --- a/tests/lib/Avatar/GuestAvatarTest.php +++ b/tests/lib/Avatar/GuestAvatarTest.php @@ -12,6 +12,7 @@ use OC\Avatar\GuestAvatar; use OCP\Files\SimpleFS\InMemoryFile; use OCP\IConfig; +use PHPUnit\Framework\Attributes\DataProvider; use Psr\Log\LoggerInterface; use Test\TestCase; @@ -37,19 +38,43 @@ public function setupGuestAvatar(): void { $this->guestAvatar = new GuestAvatar('einstein', $config, $logger); } + public static function themeProvider(): array { + return [ + 'light theme' => ['darkTheme' => false, 'backgroundColor' => 0xe9f3f7], + 'dark theme' => ['darkTheme' => true, 'backgroundColor' => 0x030e12], + ]; + } + /** - * Asserts that testGet() returns the expected avatar. + * Asserts that GuestAvatar::getFile() returns the expected avatar. * - * For the test a static name "einstein" is used and - * the generated image is compared with an expected one. + * For the test a static name "einstein" is used. */ - public function testGet(): void { - $avatar = $this->guestAvatar->getFile(32); + #[DataProvider('themeProvider')] + public function testGet(bool $darkTheme, int $backgroundColor): void { + $size = 32; + $avatar = $this->guestAvatar->getFile($size, $darkTheme); self::assertInstanceOf(InMemoryFile::class, $avatar); - $expectedFile = file_get_contents( - __DIR__ . '/../../data/guest_avatar_einstein_32.png' - ); - self::assertEquals(trim($expectedFile), trim($avatar->getContent())); + $content = $avatar->getContent(); + self::assertStringStartsWith("\x89PNG\r\n\x1a\n", $content, 'The avatar is not a PNG'); + + $image = imagecreatefromstring($content); + self::assertInstanceOf(\GdImage::class, $image); + self::assertSame($size, imagesx($image)); + self::assertSame($size, imagesy($image)); + self::assertSame($backgroundColor, imagecolorat($image, 0, 0), 'The background is not the guest color'); + + // The anti-aliased edges depend on the GD and FreeType versions, the strokes of the letter don't + $letterPixels = 0; + for ($y = 0; $y < $size; $y++) { + for ($x = 0; $x < $size; $x++) { + if (imagecolorat($image, $x, $y) === 0x248eb5) { + $letterPixels++; + } + } + } + // A Noto Sans "E" at 32 px has 27 fully covered pixels + self::assertSame(27, $letterPixels, 'The avatar does not show a Noto Sans "E" in the guest color'); } /**