1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
// 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
|