blob: 3a0af6cfc28d086672cc4a3420150ed86170ccf9 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/containers/span.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "chrome/test/base/platform_browser_test.h"
#include "components/qr_code_generator/bitmap_generator.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "ui/base/test/skia_gold_pixel_diff.h"
namespace qrcode_generator {
namespace {
class QrCodeGeneratorServicePixelTest : public PlatformBrowserTest {
public:
QrCodeGeneratorServicePixelTest() = default;
void TestGolden(const std::string& data,
const qr_code_generator::CenterImage& center_image,
const qr_code_generator::ModuleStyle& module_style,
const qr_code_generator::LocatorStyle& locator_style) {
auto response = qr_code_generator::GenerateBitmap(
base::as_byte_span(data), module_style, locator_style, center_image,
qr_code_generator::QuietZone::kIncluded);
// Verify that we got a successful response.
ASSERT_TRUE(response.has_value());
// Version 1 of QR codes has 21x21 modules/tiles/pixels. Verify that the
// returned QR image has a size that is at least 21x21.
ASSERT_GE(response->height(), 21);
ASSERT_GE(response->width(), 21);
// The QR code should be a square.
ASSERT_EQ(response->width(), response->height());
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
// Verify image contents through go/chrome-engprod-skia-gold.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kVerifyPixels)) {
const ::testing::TestInfo* test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ui::test::SkiaGoldPixelDiff* pixel_diff =
ui::test::SkiaGoldPixelDiff::GetSession();
ASSERT_TRUE(pixel_diff);
ASSERT_TRUE(pixel_diff->CompareScreenshot(
ui::test::SkiaGoldPixelDiff::GetGoldenImageName(
test_info, ui::test::SkiaGoldPixelDiff::GetPlatform()),
response.value()));
}
#endif
}
};
IN_PROC_BROWSER_TEST_F(QrCodeGeneratorServicePixelTest,
DinoWithRoundQrPixelsAndLocators) {
TestGolden("https://example.com", qr_code_generator::CenterImage::kDino,
qr_code_generator::ModuleStyle::kCircles,
qr_code_generator::LocatorStyle::kRounded);
}
IN_PROC_BROWSER_TEST_F(QrCodeGeneratorServicePixelTest,
PassKeyWithSquareQrPixelsAndLocators) {
TestGolden("https://example.com", qr_code_generator::CenterImage::kPasskey,
qr_code_generator::ModuleStyle::kSquares,
qr_code_generator::LocatorStyle::kSquare);
}
IN_PROC_BROWSER_TEST_F(QrCodeGeneratorServicePixelTest,
ProductLogoWithSquareQrPixelsAndLocators) {
TestGolden("https://example.com",
qr_code_generator::CenterImage::kProductLogo,
qr_code_generator::ModuleStyle::kSquares,
qr_code_generator::LocatorStyle::kSquare);
}
// This is a regression test for https://crbug.com/1334066. It tests that the
// QR code generator can handle fairly big inputs (the URL below is more than
// 800 bytes long).
//
// The pixel test verifies that the output of the QR code generator doesn't
// change. The real verification is checking if the generated QR code can be
// used by a variety of QR code readers (e.g. by Chrome, Safari, etc.) to
// navigate to the https://md5calc.com/hash/crc32/... URL - the result of such
// navigation should show a HTML page that says: CRC32 hash is "9f329afa".
//
// Note that https://www.qrcode.com/en/howto/code.html points out that there
// should be light/white space of 4 or more modules/pixels around the QR code
// but currently that margin is added by higher layers of code. And therefore
// the verification should be done after embedding or printing the generated
// image onto a light background.
//
// Limits for input sizes at version 40 of QR codes can be found at
// https://www.qrcode.com/en/about/version.html - 2331 is the limit for
// an input containing arbitrary bytes. In practice though QR codes that are
// so big may not be recognized by QR code readers and therefore the test uses
// a slightly smaller input.
IN_PROC_BROWSER_TEST_F(QrCodeGeneratorServicePixelTest, BigUrl) {
const char kInput[] =
"https://md5calc.com/hash/crc32/"
"Lorem+ipsum+dolor+sit+amet,+consectetur+adipiscing+elit.+Donec+sit+amet+"
"odio+sit+amet+arcu+lacinia+imperdiet+eget+vitae+ante.+Integer+a+urna+ac+"
"ipsum+vehicula+consequat.+Quisque+vel+maximus+dolor.+Donec+ullamcorper+"
"lectus+at+augue+imperdiet,+vel+lacinia+lacus+euismod.+Proin+vestibulum+"
"eget+ipsum+eu+laoreet.+Vivamus+commodo+malesuada+ipsum+sit+amet+mollis.+"
"Praesent+et+facilisis+sem.++Nulla+sit+amet+dolor+id+lectus+mattis+"
"laoreet.+Sed+arcu+dolor,+sodales+vel+nisl+in,+convallis+elementum+"
"sapien.+Pellentesque+vestibulum+neque+et+nisl+ultrices,+vel+congue+"
"sapien+bibendum.+Aliquam+ornare+in+ante+ac+dignissim.+Interdum+et+"
"malesuada+fames+ac+ante+ipsum+primis+in+faucibus.+Sed+magna+tortor,+"
"ornare+ac+bibendum+ac,+ultricies+nec+nisl.+Maecenas+consequat+interdum+"
"ipsum+a+ultrices.";
TestGolden(kInput, qr_code_generator::CenterImage::kDino,
qr_code_generator::ModuleStyle::kCircles,
qr_code_generator::LocatorStyle::kRounded);
}
// This is a regression test for https://crbug.com/1334066. It tests that the
// QR code generator can handle fairly big inputs (the URL below is 2331 bytes
// long).
//
// The pixel test verifies that the output of the QR code generator doesn't
// change. The real verification is checking if the generated QR code can be
// used by a variety of QR code readers (e.g. by Chrome, Safari, etc.) to
// navigate to the https://md5calc.com/hash/crc32/... URL - the result of such
// navigation should show a HTML page that says: CRC32 hash is "b6e1c7ad".
// OTOH, a QR code this bug may not be recognized by all QR code readers, so
// it's okay if the "real verification" is skipped for *this* particular test
// (`BigUrl` should still work).
//
// Note that https://www.qrcode.com/en/howto/code.html points out that there
// should be light/white space of 4 or more modules/pixels around the QR code
// but currently that margin is added by higher layers of code. And therefore
// the verification should be done after embedding or printing the generated
// image onto a light background.
//
// Limits for input sizes at version 40 of QR codes can be found at
// https://www.qrcode.com/en/about/version.html - 2331 is indeed the limit for
// an input containing arbitrary bytes. In theory, a smart segmentation
// algorithm could support longer URLs, but only if the input consistent of less
// arbitrary bytes, and contained more digits and/or UPPER case alphabetic
// characters.
IN_PROC_BROWSER_TEST_F(QrCodeGeneratorServicePixelTest, HugeUrl) {
const char kInput[] =
"https://md5calc.com/hash/crc32/"
"Lorem+ipsum+dolor+sit+amet,+consectetur+adipiscing+elit.+Donec+sit+amet+"
"odio+sit+amet+arcu+lacinia+imperdiet+eget+vitae+ante.+Integer+a+urna+ac+"
"ipsum+vehicula+consequat.+Quisque+vel+maximus+dolor.+Donec+ullamcorper+"
"lectus+at+augue+imperdiet,+vel+lacinia+lacus+euismod.+Proin+vestibulum+"
"eget+ipsum+eu+laoreet.+Vivamus+commodo+malesuada+ipsum+sit+amet+mollis.+"
"Praesent+et+facilisis+sem.++Nulla+sit+amet+dolor+id+lectus+mattis+"
"laoreet.+Sed+arcu+dolor,+sodales+vel+nisl+in,+convallis+elementum+"
"sapien.+Pellentesque+vestibulum+neque+et+nisl+ultrices,+vel+congue+"
"sapien+bibendum.+Aliquam+ornare+in+ante+ac+dignissim.+Interdum+et+"
"malesuada+fames+ac+ante+ipsum+primis+in+faucibus.+Sed+magna+tortor,+"
"ornare+ac+bibendum+ac,+ultricies+nec+nisl.+Maecenas+consequat+interdum+"
"ipsum+a+ultrices.+Nam+sit+amet+mollis+neque.++Morbi+iaculis+justo+quis+"
"ipsum+condimentum+semper.+Vestibulum+a+eleifend+enim.+Aenean+in+elit+et+"
"arcu+ultrices+auctor.+In+tempus+elit+ac+auctor+pellentesque.+Donec+"
"semper+sapien+eu+augue+vestibulum,+ac+facilisis+nunc+sodales.+Ut+"
"facilisis,+nisl+a+gravida+ullamcorper,+mi+felis+viverra+ligula,+eu+"
"commodo+justo+arcu+eget+erat.+Maecenas+id+iaculis+nisi,+non+sagittis+"
"urna.+Vivamus+eget+condimentum+ex,+vel+fringilla+ex.++Etiam+porttitor+"
"facilisis+tellus+quis+aliquam.+In+vitae+elit+quis+orci+porta+placerat.+"
"Proin+laoreet+feugiat+ipsum,+non+commodo+nisi+mollis+molestie.+Nunc+"
"auctor+ante+sed+nisl+tincidunt,+vitae+mattis+urna+auctor.+Fusce+iaculis+"
"laoreet+odio+ac+interdum.+Sed+gravida+dui+diam,+non+blandit+velit+"
"auctor+sit+amet.+Etiam+a+dolor+eu+lorem+porttitor+molestie.+Praesent+"
"mattis+varius+velit+a+tempus.+Etiam+sit+amet+mollis+turpis.+Donec+porta+"
"lectus+urna,+sagittis+fringilla+nulla+tincidunt+nec.+Curabitur+"
"facilisis,+lectus+ut+vulputate+posuere,+magna+ante+fermentum+est,+in+"
"imperdiet+neque+nisl+facilisis+eros.+Quisque+ut+odio+eget+orci+cursus+"
"semper+et+sit+amet+augue.+Nam+nec+nunc+pharetra,+rhoncus+purus+mollis,+"
"posuere+metus.++Sed+vestibulum+nisl+eget+iaculis+ullamcorper.+Quisque+"
"quis+nibh+imperdiet,+eleifend+erat+non,+pulvinar+dolor.+Pellentesque+"
"felis+est,+sollicitudin+a+ipsum+nec,+lacinia+pharetra+metus.+Morbi+"
"neque+leo,+sodales+ac+viverra+in,+sollicitudin+non+est.+Aenean+"
"dignissim+quam+quis+nibh+tempus+rhoncus.+Quisque+in+sapien+vitae+lectus+"
"malesuada+finibus+et+et+n";
TestGolden(kInput, qr_code_generator::CenterImage::kDino,
qr_code_generator::ModuleStyle::kCircles,
qr_code_generator::LocatorStyle::kRounded);
}
} // namespace
} // namespace qrcode_generator