Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions QRCoderTests/QRCoderTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<PackageReference Include="KGySoft.Drawing" Version="9.2.0" />
<PackageReference Include="KGySoft.Drawing.Core" Version="9.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.3" />
<PackageReference Include="Svg" Version="3.4.7" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="shouldly" Version="4.3.0" />
Expand Down Expand Up @@ -59,11 +60,11 @@
</ItemGroup>

<ItemGroup>
<Using Include="QRCoder"/>
<Using Include="QRCoderTests.Helpers"/>
<Using Include="Shouldly"/>
<Using Include="System.Drawing"/>
<Using Include="Xunit"/>
<Using Include="QRCoder" />
<Using Include="QRCoderTests.Helpers" />
<Using Include="Shouldly" />
<Using Include="System.Drawing" />
<Using Include="Xunit" />
</ItemGroup>

</Project>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@




██████████████ ██ ████ ██████████████
██ ██ ████ ██ ██ ██
██ ██████ ██ ████ ██ ██ ██████ ██
██ ██████ ██ ██ ██ ██ ██████ ██
██ ██████ ██ ██ ██ ██ ██████ ██
██ ██ ██ ████ ██ ██
██████████████ ██ ██ ██ ██████████████
██████████
████ ██ ████ ████ ██████ ████
██ ████████ ████ ██
██ ██ ██ ██████ ████ ██
██ ██████ ████ ██ ██ ████
██████ ██ ██████████ ██ ██ ████████
████ ██ ██████ ██
██████████████ ████ ██ ██ ██
██ ██ ██████████ ██████ ████
██ ██████ ██ ██ ██ ██████ ██████
██ ██████ ██ ████ ██ ████████
██ ██████ ██ ██ ██ ██ ██
██ ██ ████ ████ ██ ██ ██
██████████████ ██ ██████ ██████




Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@


█▀▀▀▀▀█ ▄█ █▀ █▀▀▀▀▀█
█ ███ █ ▀█ ▄▀ █ ███ █
█ ▀▀▀ █ █ ▄█ █ ▀▀▀ █
▀▀▀▀▀▀▀ █▄█▄█ ▀▀▀▀▀▀▀
█▀▄█▄▄▀▀▄█▀ █▀▀ ▀▀
▀▄ █▄▄▀ ██▀▄▀▀ ▄▀▄▄
▀▀▀ ▀ ▀▀██▀▄▀ ▀▄██▀█
█▀▀▀▀▀█ ▀█▄▄▄█ █▄█ ▄▄
█ ███ █ ▄█ █ ▀▀▀▄███
█ ▀▀▀ █ ▄█ ▀▄▄ █ ▄ █
▀▀▀▀▀▀▀ ▀ ▀▀▀ ▀▀▀


Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
171 changes: 171 additions & 0 deletions QRCoderTests/TransposeVerificationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System.IO;

namespace QRCoderTests;

/// <summary>
/// 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.
/// </summary>
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")]
[InlineData("SvgQRCode")]
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);
}

private byte[] GetQRCodeBytes()
{
var qrCode = new QRCode(_sharedQrCodeData);
using 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<Svg.SvgDocument>(svgString);
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]
[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(invert: true),
_ => 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);
using var bitmap = qrCode.GetGraphic(10);
bitmap.ShouldMatchApproved();
}
#endif
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.