From 8a9a536d18864443905e1e573c720bf39b79ddaf Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Mon, 6 Oct 2025 02:12:06 -0400 Subject: [PATCH 1/4] Add transposition tests --- QRCoderTests/QRCoderTests.csproj | 11 +- ...ationTests.artqrcode_renderer.approved.gif | Bin 0 -> 2955 bytes ...Tests.ascii_renderer.FullSize.approved.txt | 29 +++ ...ionTests.ascii_renderer.Small.approved.txt | 15 ++ ...nTests.black_module_reference.approved.gif | Bin 0 -> 487 bytes QRCoderTests/TransposeVerificationTests.cs | 170 ++++++++++++++++++ ...ficationTests.image_renderers.approved.gif | Bin 0 -> 2592 bytes ...erificationTests.pdf_renderer.approved.pdf | Bin 0 -> 3346 bytes ...ationTests.postscript_renderer.approved.ps | Bin 0 -> 2663 bytes 9 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 QRCoderTests/TransposeVerificationTests.artqrcode_renderer.approved.gif create mode 100644 QRCoderTests/TransposeVerificationTests.ascii_renderer.FullSize.approved.txt create mode 100644 QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt create mode 100644 QRCoderTests/TransposeVerificationTests.black_module_reference.approved.gif create mode 100644 QRCoderTests/TransposeVerificationTests.cs create mode 100644 QRCoderTests/TransposeVerificationTests.image_renderers.approved.gif create mode 100644 QRCoderTests/TransposeVerificationTests.pdf_renderer.approved.pdf create mode 100644 QRCoderTests/TransposeVerificationTests.postscript_renderer.approved.ps diff --git a/QRCoderTests/QRCoderTests.csproj b/QRCoderTests/QRCoderTests.csproj index bc4aed9a..79fa6a0e 100644 --- a/QRCoderTests/QRCoderTests.csproj +++ b/QRCoderTests/QRCoderTests.csproj @@ -13,6 +13,7 @@ + @@ -58,11 +59,11 @@ - - - - - + + + + + diff --git a/QRCoderTests/TransposeVerificationTests.artqrcode_renderer.approved.gif b/QRCoderTests/TransposeVerificationTests.artqrcode_renderer.approved.gif new file mode 100644 index 0000000000000000000000000000000000000000..b8b516595622f469231a0906c16362a9d7a5714a GIT binary patch literal 2955 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 B_niO$ literal 0 HcmV?d00001 diff --git a/QRCoderTests/TransposeVerificationTests.ascii_renderer.FullSize.approved.txt b/QRCoderTests/TransposeVerificationTests.ascii_renderer.FullSize.approved.txt new file mode 100644 index 00000000..ec53d7cc --- /dev/null +++ b/QRCoderTests/TransposeVerificationTests.ascii_renderer.FullSize.approved.txt @@ -0,0 +1,29 @@ + + + + + ██████████████ ██ ████ ██████████████ + ██ ██ ████ ██ ██ ██ + ██ ██████ ██ ████ ██ ██ ██████ ██ + ██ ██████ ██ ██ ██ ██ ██████ ██ + ██ ██████ ██ ██ ██ ██ ██████ ██ + ██ ██ ██ ████ ██ ██ + ██████████████ ██ ██ ██ ██████████████ + ██████████ + ████ ██ ████ ████ ██████ ████ + ██ ████████ ████ ██ + ██ ██ ██ ██████ ████ ██ + ██ ██████ ████ ██ ██ ████ + ██████ ██ ██████████ ██ ██ ████████ + ████ ██ ██████ ██ + ██████████████ ████ ██ ██ ██ + ██ ██ ██████████ ██████ ████ + ██ ██████ ██ ██ ██ ██████ ██████ + ██ ██████ ██ ████ ██ ████████ + ██ ██████ ██ ██ ██ ██ ██ + ██ ██ ████ ████ ██ ██ ██ + ██████████████ ██ ██████ ██████ + + + + \ No newline at end of file diff --git a/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt b/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt new file mode 100644 index 00000000..af18134e --- /dev/null +++ b/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt @@ -0,0 +1,15 @@ +█████████████████████████████ +█████████████████████████████ +████ ▄▄▄▄▄ █ ▄▄▀ █ ▄▄▄▄▄ ████ +████ █ █ █▀ ▀▀▄█ █ █ ████ +████ █▄▄▄█ ██ █ ▄█ █▄▄▄█ ████ +████▄▄▄▄▄▄▄█ █▄█ █▄▄▄▄▄▄▄████ +████▀ ▀▄▄▄ ▀ ▀▀ ▀ ▄████ +████▀▀█▀█▀▄ ▄█▄▀▄▀█ ▀▀██ ████ +████▄█▄█▄▄▄▄██ █▄█▀ ██▄▀▄████ +████ ▄▄▄▄▄ █ ▄██▄▀▀▀ ██▄█████ +████ █ █ █▄██▀ ▀ ▄▀▄▄ ████ +████ █▄▄▄█ █ █▄▀ ▀█▀ █▄▄████ +████▄▄▄▄▄▄▄████▄███▄▄▄▄▄█████ +█████████████████████████████ +▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ \ No newline at end of file diff --git a/QRCoderTests/TransposeVerificationTests.black_module_reference.approved.gif b/QRCoderTests/TransposeVerificationTests.black_module_reference.approved.gif new file mode 100644 index 0000000000000000000000000000000000000000..60f763b71c8e893682bbbd2f8d133a77a9aa874c GIT binary patch literal 487 zcmV-YS= z{|^`_I7nD%c!-#&xX9S(_y`#(IZ0V*d5M{+xyjk-`3V{-I!an`U)E> zJ4;(@dyAW^yUW|_`wJW_JWO0{e2ko|yv*F}{0to}JxyJ0eT|*1z0KY2{S6*2K2Bb4 zevY25zRuq6{th26KTlt8e~+K9zt7+A{|_*rz<~q{8a#+Fp~8g>8#;UlF`~qY6f0W1 zh%uwajjkL!di)47q{xvZOPV~1GNsCuEL*yK2{We5nKWzKyoocX&Ye7aZUg`{s8EhV zivl2OG$_)fM}IPHs_`k*j8c~-wQ3Y=QJ-A9di@GEtk|(+%bGolHm%yVY}>kh3pcLZ zxpeE=y^A-m-o1SL`uz(yu;9Uj3mZO+II-fzj2k +/// Tests to verify that QR codes are not transposed along the main diagonal. +/// All tests use the same QR code data with default renderer settings. +/// Human verification of approval files is required to ensure correct orientation. +/// +public class TransposeVerificationTests +{ + private readonly QRCodeData _sharedQrCodeData; + + public TransposeVerificationTests() + { + // Create a single QR code sample that will be used across all tests + // Using a distinctive pattern that makes transpose errors obvious + var gen = new QRCodeGenerator(); + _sharedQrCodeData = gen.CreateQrCode("ABCD", QRCodeGenerator.ECCLevel.L); + } + +#if SYSTEM_DRAWING + [Theory] + [InlineData("QRCode")] + [InlineData("BitmapByteQRCode")] + [InlineData("Base64QRCode")] + [InlineData("PngByteQRCode")] + public void image_renderers(string rendererType) + { + byte[] imageBytes = rendererType switch + { + "QRCode" => GetQRCodeBytes(), + "BitmapByteQRCode" => GetBitmapByteQRCodeBytes(), + "Base64QRCode" => GetBase64QRCodeBytes(), + "PngByteQRCode" => GetPngByteQRCodeBytes(), + "SvgQRCode" => GetSvgQRCodeBytes(), + _ => throw new ArgumentException($"Unknown renderer type: {rendererType}") + }; + + imageBytes.ShouldMatchApprovedImage(asMonochrome: true); + } + + [Fact] + public void artqrcode_renderer() + { + var qrCode = new ArtQRCode(_sharedQrCodeData); + var bitmap = qrCode.GetGraphic(10, Color.Black, Color.White, Color.White, null, 1, true, ArtQRCode.QuietZoneStyle.Flat, ArtQRCode.BackgroundImageStyle.Fill, null); + bitmap.ShouldMatchApproved(); + } + + private byte[] GetQRCodeBytes() + { + var qrCode = new QRCode(_sharedQrCodeData); + var bitmap = qrCode.GetGraphic(10); + using var ms = new MemoryStream(); + bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + return ms.ToArray(); + } + + private byte[] GetBitmapByteQRCodeBytes() + { + var qrCode = new BitmapByteQRCode(_sharedQrCodeData); + return qrCode.GetGraphic(10); + } + + private byte[] GetBase64QRCodeBytes() + { + var qrCode = new Base64QRCode(_sharedQrCodeData); + var base64String = qrCode.GetGraphic(10); + return Convert.FromBase64String(base64String); + } + + private byte[] GetPngByteQRCodeBytes() + { + var qrCode = new PngByteQRCode(_sharedQrCodeData); + return qrCode.GetGraphic(10); + } + + private byte[] GetSvgQRCodeBytes() + { + var qrCode = new SvgQRCode(_sharedQrCodeData); + var svgString = qrCode.GetGraphic(10); + var bitmapSize = _sharedQrCodeData.ModuleMatrix.Count * 10; + // use Svg.Net to render SVG to bitmap for comparison + var svgDoc = Svg.SvgDocument.FromSvg(svgString); + var bitmap = svgDoc.Draw(bitmapSize, bitmapSize); + using var ms = new MemoryStream(); + bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); + return ms.ToArray(); + } +#endif + + [Theory] + [InlineData("FullSize")] + [InlineData("Small")] + public void ascii_renderer(string sizeType) + { + var qrCode = new AsciiQRCode(_sharedQrCodeData); + var asciiArt = sizeType switch + { + "FullSize" => qrCode.GetGraphic(1), + "Small" => qrCode.GetGraphicSmall(), + _ => throw new ArgumentException($"Unknown size type: {sizeType}") + }; + asciiArt.ShouldMatchApproved(x => x.NoDiff().WithDiscriminator(sizeType)); + } + + [Fact] + public void pdf_renderer() + { + var qrCode = new PdfByteQRCode(_sharedQrCodeData); + var pdfBytes = qrCode.GetGraphic(10); + pdfBytes.ShouldMatchApproved("pdf"); + } + + [Fact] + public void postscript_renderer() + { + var qrCode = new PostscriptQRCode(_sharedQrCodeData); + var postscript = qrCode.GetGraphic(10); + postscript.ShouldMatchApproved(x => x.NoDiff().WithFileExtension("ps")); + } + + [Fact] + public void black_module_position() + { + // The black module in a QR code is always at position (4*version + 9, 8) + (4,4) due to the quiet zone + // For our test QR code (version 1), it should be at (13, 8) + // If transposed, it would be at (8, 13) + var version = _sharedQrCodeData.Version; + var expectedRow = 4 * version + 9 + 4; + var expectedCol = 8 + 4; + var transposedRow = expectedCol; + var transposedCol = expectedRow; + + // Verify the black module is at the expected position + _sharedQrCodeData.ModuleMatrix[expectedRow][expectedCol].ShouldBeTrue( + $"Black module should be at position ({expectedRow}, {expectedCol})"); + + // Verify it's NOT at the transposed position (unless they happen to be the same) + if (expectedRow != transposedCol || expectedCol != transposedRow) + { + _sharedQrCodeData.ModuleMatrix[transposedRow][transposedCol].ShouldBeFalse( + $"Black module should NOT be at transposed position ({transposedRow}, {transposedCol})"); + } + } + +#if SYSTEM_DRAWING + [Fact] + public void black_module_reference() + { + // Create a QR code data with the same size as our test matrix + // but with only a single black module at the expected black module position + var version = _sharedQrCodeData.Version; + var blackModuleRow = 4 * version + 9 + 4; + var blackModuleCol = 8 + 4; + + // Create a minimal QRCodeData with just the black module + var referenceData = new QRCodeData(version, addPadding: true); + + // Set only the black module position to true + referenceData.ModuleMatrix[blackModuleRow][blackModuleCol] = true; + + // Render this reference image for human verification + var qrCode = new QRCode(referenceData); + var bitmap = qrCode.GetGraphic(10); + bitmap.ShouldMatchApproved(); + } +#endif +} diff --git a/QRCoderTests/TransposeVerificationTests.image_renderers.approved.gif b/QRCoderTests/TransposeVerificationTests.image_renderers.approved.gif new file mode 100644 index 0000000000000000000000000000000000000000..5db6923e32dc21d1dba60547478884375a2ecf45 GIT binary patch literal 2592 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 literal 0 HcmV?d00001 From c8d802807d261112c39ffe9a55ac502369a60239 Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Mon, 6 Oct 2025 03:06:03 -0400 Subject: [PATCH 2/4] Include SVG renderer --- QRCoderTests/TransposeVerificationTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/QRCoderTests/TransposeVerificationTests.cs b/QRCoderTests/TransposeVerificationTests.cs index 9e57df51..f165048d 100644 --- a/QRCoderTests/TransposeVerificationTests.cs +++ b/QRCoderTests/TransposeVerificationTests.cs @@ -25,6 +25,7 @@ public TransposeVerificationTests() [InlineData("BitmapByteQRCode")] [InlineData("Base64QRCode")] [InlineData("PngByteQRCode")] + [InlineData("SvgQRCode")] public void image_renderers(string rendererType) { byte[] imageBytes = rendererType switch From d85e408b6828611cf7d65a4a605ff2a43e33d024 Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Mon, 6 Oct 2025 03:08:24 -0400 Subject: [PATCH 3/4] Update --- QRCoderTests/TransposeVerificationTests.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/QRCoderTests/TransposeVerificationTests.cs b/QRCoderTests/TransposeVerificationTests.cs index f165048d..e288b95c 100644 --- a/QRCoderTests/TransposeVerificationTests.cs +++ b/QRCoderTests/TransposeVerificationTests.cs @@ -41,18 +41,10 @@ public void image_renderers(string rendererType) imageBytes.ShouldMatchApprovedImage(asMonochrome: true); } - [Fact] - public void artqrcode_renderer() - { - var qrCode = new ArtQRCode(_sharedQrCodeData); - var bitmap = qrCode.GetGraphic(10, Color.Black, Color.White, Color.White, null, 1, true, ArtQRCode.QuietZoneStyle.Flat, ArtQRCode.BackgroundImageStyle.Fill, null); - bitmap.ShouldMatchApproved(); - } - private byte[] GetQRCodeBytes() { var qrCode = new QRCode(_sharedQrCodeData); - var bitmap = qrCode.GetGraphic(10); + using var bitmap = qrCode.GetGraphic(10); using var ms = new MemoryStream(); bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); return ms.ToArray(); @@ -84,11 +76,19 @@ private byte[] GetSvgQRCodeBytes() var bitmapSize = _sharedQrCodeData.ModuleMatrix.Count * 10; // use Svg.Net to render SVG to bitmap for comparison var svgDoc = Svg.SvgDocument.FromSvg(svgString); - var bitmap = svgDoc.Draw(bitmapSize, bitmapSize); + using var bitmap = svgDoc.Draw(bitmapSize, bitmapSize); using var ms = new MemoryStream(); bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); return ms.ToArray(); } + + [Fact] + public void artqrcode_renderer() + { + var qrCode = new ArtQRCode(_sharedQrCodeData); + using var bitmap = qrCode.GetGraphic(10, Color.Black, Color.White, Color.White, null, 1, true, ArtQRCode.QuietZoneStyle.Flat, ArtQRCode.BackgroundImageStyle.Fill, null); + bitmap.ShouldMatchApproved(); + } #endif [Theory] @@ -164,7 +164,7 @@ public void black_module_reference() // Render this reference image for human verification var qrCode = new QRCode(referenceData); - var bitmap = qrCode.GetGraphic(10); + using var bitmap = qrCode.GetGraphic(10); bitmap.ShouldMatchApproved(); } #endif From 5491e47d751ba35162f6eb2504094e47176b6ad8 Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Mon, 6 Oct 2025 11:48:09 -0400 Subject: [PATCH 4/4] Update transposition tests --- ...ionTests.ascii_renderer.Small.approved.txt | 30 +++++++++--------- QRCoderTests/TransposeVerificationTests.cs | 2 +- ...ationTests.postscript_renderer.approved.ps | Bin 2663 -> 2627 bytes 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt b/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt index af18134e..fd8ff2b3 100644 --- a/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt +++ b/QRCoderTests/TransposeVerificationTests.ascii_renderer.Small.approved.txt @@ -1,15 +1,15 @@ -█████████████████████████████ -█████████████████████████████ -████ ▄▄▄▄▄ █ ▄▄▀ █ ▄▄▄▄▄ ████ -████ █ █ █▀ ▀▀▄█ █ █ ████ -████ █▄▄▄█ ██ █ ▄█ █▄▄▄█ ████ -████▄▄▄▄▄▄▄█ █▄█ █▄▄▄▄▄▄▄████ -████▀ ▀▄▄▄ ▀ ▀▀ ▀ ▄████ -████▀▀█▀█▀▄ ▄█▄▀▄▀█ ▀▀██ ████ -████▄█▄█▄▄▄▄██ █▄█▀ ██▄▀▄████ -████ ▄▄▄▄▄ █ ▄██▄▀▀▀ ██▄█████ -████ █ █ █▄██▀ ▀ ▄▀▄▄ ████ -████ █▄▄▄█ █ █▄▀ ▀█▀ █▄▄████ -████▄▄▄▄▄▄▄████▄███▄▄▄▄▄█████ -█████████████████████████████ -▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ \ No newline at end of file + + + █▀▀▀▀▀█ ▄█ █▀ █▀▀▀▀▀█ + █ ███ █ ▀█ ▄▀ █ ███ █ + █ ▀▀▀ █ █ ▄█ █ ▀▀▀ █ + ▀▀▀▀▀▀▀ █▄█▄█ ▀▀▀▀▀▀▀ + █▀▄█▄▄▀▀▄█▀ █▀▀ ▀▀ + ▀▄ █▄▄▀ ██▀▄▀▀ ▄▀▄▄ + ▀▀▀ ▀ ▀▀██▀▄▀ ▀▄██▀█ + █▀▀▀▀▀█ ▀█▄▄▄█ █▄█ ▄▄ + █ ███ █ ▄█ █ ▀▀▀▄███ + █ ▀▀▀ █ ▄█ ▀▄▄ █ ▄ █ + ▀▀▀▀▀▀▀ ▀ ▀▀▀ ▀▀▀ + + \ No newline at end of file diff --git a/QRCoderTests/TransposeVerificationTests.cs b/QRCoderTests/TransposeVerificationTests.cs index e288b95c..fd8e0d4f 100644 --- a/QRCoderTests/TransposeVerificationTests.cs +++ b/QRCoderTests/TransposeVerificationTests.cs @@ -100,7 +100,7 @@ public void ascii_renderer(string sizeType) var asciiArt = sizeType switch { "FullSize" => qrCode.GetGraphic(1), - "Small" => qrCode.GetGraphicSmall(), + "Small" => qrCode.GetGraphicSmall(invert: true), _ => throw new ArgumentException($"Unknown size type: {sizeType}") }; asciiArt.ShouldMatchApproved(x => x.NoDiff().WithDiscriminator(sizeType)); diff --git a/QRCoderTests/TransposeVerificationTests.postscript_renderer.approved.ps b/QRCoderTests/TransposeVerificationTests.postscript_renderer.approved.ps index 433198d24dc74c98ef55a906ab49975cff3f9d73..0aef3dfac7427557c25a2ba4203fd63f8dc015bc 100644 GIT binary patch delta 10 RcmaDZa#&=7<;GYpE&v$b1HJ$N delta 44 zcmX>s@?2zsrJ{3DYGO%dex6HWNvf5Ck%5t^uAzahfmw)wp_Qq*m66FtGhQwLN5l-R