mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-09-10 09:46:26 +00:00
:octocat: +several coverage tests & cleanup
This commit is contained in:
@@ -112,7 +112,7 @@ final class BitBuffer{
|
||||
*/
|
||||
public function read(int $numBits):int{
|
||||
|
||||
if($numBits < 1 || $numBits > 32 || $numBits > $this->available()){
|
||||
if($numBits < 1 || $numBits > $this->available()){
|
||||
throw new QRCodeException('invalid $numBits: '.$numBits);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ final class EccLevel{
|
||||
/**
|
||||
* ISO/IEC 18004:2000 Tables 7-11 - Number of symbol characters and input data capacity for versions 1 to 40
|
||||
*
|
||||
* @var int [][]
|
||||
* @var int[][]
|
||||
*/
|
||||
private const MAX_BITS = [
|
||||
// [ L, M, Q, H] // v => modules
|
||||
|
||||
+8
-1
@@ -90,9 +90,16 @@ final class Mode{
|
||||
|
||||
/**
|
||||
* returns the array of length bits for the given mode
|
||||
*
|
||||
* @throws \chillerlan\QRCode\QRCodeException
|
||||
*/
|
||||
public static function getLengthBitsForMode(int $mode):array{
|
||||
return self::LENGTH_BITS[$mode];
|
||||
|
||||
if(isset(self::LENGTH_BITS[$mode])){
|
||||
return self::LENGTH_BITS[$mode];
|
||||
}
|
||||
|
||||
throw new QRCodeException('invalid mode given');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ final class Version{
|
||||
public function __construct(int $version){
|
||||
|
||||
if($version < 1 || $version > 40){
|
||||
throw new QRCodeException('invalid version number');
|
||||
throw new QRCodeException('invalid version given');
|
||||
}
|
||||
|
||||
$this->version = $version;
|
||||
|
||||
@@ -109,7 +109,7 @@ final class AlphaNum extends QRDataModeAbstract{
|
||||
while($length > 1){
|
||||
|
||||
if($bitBuffer->available() < 11){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$nextTwoCharsBits = $bitBuffer->read(11);
|
||||
@@ -121,7 +121,7 @@ final class AlphaNum extends QRDataModeAbstract{
|
||||
if($length === 1){
|
||||
// special case: one character left
|
||||
if($bitBuffer->available() < 6){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$result .= $toAlphaNumericChar($bitBuffer->read(6));
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ final class Byte extends QRDataModeAbstract{
|
||||
$length = $bitBuffer->read(self::getLengthBits($versionNumber));
|
||||
|
||||
if($bitBuffer->available() < 8 * $length){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$readBytes = '';
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ final class Kanji extends QRDataModeAbstract{
|
||||
$length = $bitBuffer->read(self::getLengthBits($versionNumber));
|
||||
|
||||
if($bitBuffer->available() < $length * 13){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$buffer = [];
|
||||
|
||||
+3
-3
@@ -126,7 +126,7 @@ final class Number extends QRDataModeAbstract{
|
||||
while($length >= 3){
|
||||
// Each 10 bits encodes three digits
|
||||
if($bitBuffer->available() < 10){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$threeDigitsBits = $bitBuffer->read(10);
|
||||
@@ -145,7 +145,7 @@ final class Number extends QRDataModeAbstract{
|
||||
if($length === 2){
|
||||
// Two digits left over to read, encoded in 7 bits
|
||||
if($bitBuffer->available() < 7){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$twoDigitsBits = $bitBuffer->read(7);
|
||||
@@ -160,7 +160,7 @@ final class Number extends QRDataModeAbstract{
|
||||
elseif($length === 1){
|
||||
// One digit left over to read
|
||||
if($bitBuffer->available() < 4){
|
||||
throw new QRCodeDataException('not enough bits available');
|
||||
throw new QRCodeDataException('not enough bits available'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$digitBits = $bitBuffer->read(4);
|
||||
|
||||
@@ -534,17 +534,17 @@ class QRMatrix{
|
||||
throw new QRCodeDataException('ECC level "H" required to add logo space');
|
||||
}
|
||||
|
||||
// if width and height happen to be exactly 0 (default value), just return - nothing to do
|
||||
if($width === 0 || $height === 0){
|
||||
return $this;
|
||||
// if width and height happen to be negative or 0 (default value), just return - nothing to do
|
||||
if($width <= 0 || $height <= 0){
|
||||
return $this; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// $this->moduleCount includes the quiet zone (if created), we need the QR size here
|
||||
$length = $this->version->getDimension();
|
||||
|
||||
// throw if the size is negative or exceeds the qrcode size
|
||||
if($width < 0 || $height < 0 || $width > $length || $height > $length){
|
||||
throw new QRCodeDataException('invalid logo dimensions');
|
||||
// throw if the size is exceeds the qrcode size
|
||||
if($width > $length || $height > $length){
|
||||
throw new QRCodeDataException('logo dimensions exceed matrix size');
|
||||
}
|
||||
|
||||
// we need uneven sizes to center the logo space, adjust if needed
|
||||
|
||||
@@ -103,7 +103,7 @@ final class Binarizer{
|
||||
// If there is too little contrast in the image to pick a meaningful black point, throw rather
|
||||
// than waste time trying to decode the image, and risk false positives.
|
||||
if($secondPeak - $firstPeak <= $numBuckets / 16){
|
||||
throw new QRCodeDecoderException('no meaningful dark point found');
|
||||
throw new QRCodeDecoderException('no meaningful dark point found'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// Find a valley between them that is low and closer to the white peak.
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
namespace chillerlan\QRCodeTest\Common;
|
||||
|
||||
use chillerlan\QRCode\Common\{BitBuffer, Mode};
|
||||
use chillerlan\QRCode\QRCodeException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@@ -42,4 +43,12 @@ final class BitBufferTest extends TestCase{
|
||||
$this::assertSame(4, $this->bitBuffer->getLength());
|
||||
}
|
||||
|
||||
public function testReadException():void{
|
||||
$this->expectException(QRCodeException::class);
|
||||
$this->expectExceptionMessage('invalid $numBits');
|
||||
|
||||
$this->bitBuffer->put(Mode::KANJI, 4);
|
||||
$this->bitBuffer->read($this->bitBuffer->available() + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Class EccLevelTest
|
||||
*
|
||||
* @created 25.07.2022
|
||||
* @author smiley <smiley@chillerlan.net>
|
||||
* @copyright 2022 smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace chillerlan\QRCodeTest\Common;
|
||||
|
||||
use chillerlan\QRCode\Common\EccLevel;
|
||||
use chillerlan\QRCode\Common\MaskPattern;
|
||||
use chillerlan\QRCode\QRCodeException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* EccLevel coverage test
|
||||
*/
|
||||
final class EccLevelTest extends TestCase{
|
||||
|
||||
public function testConstructInvalidEccException():void{
|
||||
$this->expectException(QRCodeException::class);
|
||||
$this->expectExceptionMessage('invalid ECC level');
|
||||
|
||||
$ecc = new EccLevel(69);
|
||||
}
|
||||
|
||||
public function testToString():void{
|
||||
$ecc = new EccLevel(EccLevel::L);
|
||||
|
||||
$this::assertSame('L', (string)$ecc);
|
||||
}
|
||||
|
||||
public function testGetLevel():void{
|
||||
$ecc = new EccLevel(EccLevel::L);
|
||||
|
||||
$this::assertSame(EccLevel::L, $ecc->getLevel());
|
||||
}
|
||||
|
||||
public function testGetOrdinal():void{
|
||||
$ecc = new EccLevel(EccLevel::L);
|
||||
|
||||
$this::assertSame(0, $ecc->getOrdinal());
|
||||
}
|
||||
|
||||
public function testGetformatPattern():void{
|
||||
$ecc = new EccLevel(EccLevel::Q);
|
||||
|
||||
$this::assertSame(0b010010010110100, $ecc->getformatPattern(new MaskPattern(4)));
|
||||
}
|
||||
|
||||
public function getMaxBits():void{
|
||||
$ecc = new EccLevel(EccLevel::Q);
|
||||
|
||||
$this::assertSame(4096, $ecc->getMaxBits()[21]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Class ModeTest
|
||||
*
|
||||
* @created 25.07.2022
|
||||
* @author smiley <smiley@chillerlan.net>
|
||||
* @copyright 2022 smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace chillerlan\QRCodeTest\Common;
|
||||
|
||||
use chillerlan\QRCode\Common\Mode;
|
||||
use chillerlan\QRCode\QRCodeException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Mode coverage test
|
||||
*/
|
||||
final class ModeTest extends TestCase{
|
||||
|
||||
/**
|
||||
* version breakpoints for numeric mode
|
||||
*/
|
||||
public function versionProvider():array{
|
||||
return [
|
||||
[ 1, 10],
|
||||
[ 9, 10],
|
||||
[10, 12],
|
||||
[26, 12],
|
||||
[27, 14],
|
||||
[40, 14],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider versionProvider
|
||||
*/
|
||||
public function testGetLengthBitsForVersionBreakpoints(int $version, int $expected):void{
|
||||
$this::assertSame($expected, Mode::getLengthBitsForVersion(Mode::NUMBER, $version));
|
||||
}
|
||||
|
||||
public function testGetLengthBitsForVersionInvalidModeException():void{
|
||||
$this->expectException(QRCodeException::class);
|
||||
$this->expectExceptionMessage('invalid mode given');
|
||||
|
||||
$bits = Mode::getLengthBitsForVersion(42, 69);
|
||||
}
|
||||
|
||||
public function testGetLengthBitsForVersionInvalidVersionException():void{
|
||||
$this->expectException(QRCodeException::class);
|
||||
$this->expectExceptionMessage('invalid version number');
|
||||
|
||||
$bits = Mode::getLengthBitsForVersion(Mode::BYTE, 69);
|
||||
}
|
||||
|
||||
public function testGetLengthBitsForModeInvalidModeException():void{
|
||||
$this->expectException(QRCodeException::class);
|
||||
$this->expectExceptionMessage('invalid mode given');
|
||||
|
||||
$bits = Mode::getLengthBitsForMode(42);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Class VersionTest
|
||||
*
|
||||
* @created 25.07.2022
|
||||
* @author smiley <smiley@chillerlan.net>
|
||||
* @copyright 2022 smiley
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace chillerlan\QRCodeTest\Common;
|
||||
|
||||
use chillerlan\QRCode\Common\EccLevel;
|
||||
use chillerlan\QRCode\Common\Mode;
|
||||
use chillerlan\QRCode\Common\Version;
|
||||
use chillerlan\QRCode\QRCodeException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Version coverage test
|
||||
*/
|
||||
final class VersionTest extends TestCase{
|
||||
|
||||
private Version $version;
|
||||
|
||||
protected function setUp():void{
|
||||
$this->version = new Version(7);
|
||||
}
|
||||
|
||||
public function testToString():void{
|
||||
$this::assertSame('7', (string)$this->version);
|
||||
}
|
||||
|
||||
public function testGetVersionNumber():void{
|
||||
$this::assertSame(7, $this->version->getVersionNumber());
|
||||
}
|
||||
|
||||
public function testGetDimension():void{
|
||||
$this::assertSame(45, $this->version->getDimension());
|
||||
}
|
||||
|
||||
public function testGetVersionPattern():void{
|
||||
$this::assertSame(0b000111110010010100, $this->version->getVersionPattern());
|
||||
// no pattern for version < 7
|
||||
$this::assertNull((new Version(6))->getVersionPattern());
|
||||
}
|
||||
|
||||
public function testGetAlignmentPattern():void{
|
||||
$this::assertSame([6, 22, 38], $this->version->getAlignmentPattern());
|
||||
}
|
||||
|
||||
public function testGetRSBlocks():void{
|
||||
$this::assertSame([18, [[2, 14], [4, 15]]], $this->version->getRSBlocks(new EccLevel(EccLevel::Q)));
|
||||
}
|
||||
|
||||
public function testGetTotalCodewords():void{
|
||||
$this::assertSame(196, $this->version->getTotalCodewords());
|
||||
}
|
||||
|
||||
public function testConstructInvalidVersion():void{
|
||||
$this->expectException(QRCodeException::class);
|
||||
$this->expectExceptionMessage('invalid version given');
|
||||
|
||||
$version = new Version(69);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -155,6 +155,10 @@ final class QRMatrixTest extends TestCase{
|
||||
$this->matrix->set(20, 20, false, QRMatrix::M_TEST);
|
||||
$this::assertSame(QRMatrix::M_TEST, $this->matrix->get(20, 20));
|
||||
$this::assertFalse($this->matrix->check(20, 20));
|
||||
|
||||
// out of range
|
||||
$this::assertFalse($this->matrix->check(-1, -1));
|
||||
$this::assertSame(-1, $this->matrix->get(-1, -1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,6 +417,20 @@ final class QRMatrixTest extends TestCase{
|
||||
(new QRCode)->addByteSegment('testdata')->getMatrix()->setLogoSpace(50, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether an exception is thrown when width or height exceed the matrix size
|
||||
*/
|
||||
public function testSetLogoSpaceExceedsException():void{
|
||||
$this->expectException(QRCodeDataException::class);
|
||||
$this->expectExceptionMessage('logo dimensions exceed matrix size');
|
||||
|
||||
$o = new QROptions;
|
||||
$o->version = 5;
|
||||
$o->eccLevel = EccLevel::H;
|
||||
|
||||
(new QRCode($o))->addByteSegment('testdata')->getMatrix()->setLogoSpace(69, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether an exception is thrown when the logo space size exceeds the maximum ECC capacity
|
||||
*/
|
||||
@@ -450,4 +468,95 @@ final class QRMatrixTest extends TestCase{
|
||||
$this::assertSame(QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK, $this->matrix->get($x, $y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests checking whether the M_TYPE of a module is not one of an array of M_TYPES
|
||||
*/
|
||||
public function testCheckTypeNotIn():void{
|
||||
$this->matrix->set(10, 10, true, QRMatrix::M_QUIETZONE);
|
||||
|
||||
$this::assertTrue($this->matrix->checkTypeNotIn(10, 10, [QRMatrix::M_DATA, QRMatrix::M_FINDER]));
|
||||
$this::assertFalse($this->matrix->checkTypeNotIn(10, 10, [QRMatrix::M_QUIETZONE, QRMatrix::M_FINDER]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests checking the adjacent modules
|
||||
*/
|
||||
public function testCheckNeighbours():void{
|
||||
|
||||
$this->matrix
|
||||
->setFinderPattern()
|
||||
->setAlignmentPattern()
|
||||
;
|
||||
|
||||
/*
|
||||
* center of finder pattern (surrounded by all dark)
|
||||
*
|
||||
* # # # # # # #
|
||||
* # #
|
||||
* # # # # #
|
||||
* # # 0 # #
|
||||
* # # # # #
|
||||
* # #
|
||||
* # # # # # # #
|
||||
*/
|
||||
$this::assertSame(0b11111111, $this->matrix->checkNeighbours(3, 3));
|
||||
|
||||
/*
|
||||
* center of alignment pattern (surrounded by all light)
|
||||
*
|
||||
* # # # # #
|
||||
* # #
|
||||
* # 0 #
|
||||
* # #
|
||||
* # # # # #
|
||||
*/
|
||||
$this::assertSame(0b00000000, $this->matrix->checkNeighbours(30, 30));
|
||||
|
||||
/*
|
||||
* top left light block of finder pattern
|
||||
*
|
||||
* # # #
|
||||
* # 0
|
||||
* # #
|
||||
*/
|
||||
$this::assertSame(0b11010111, $this->matrix->checkNeighbours(1, 1));
|
||||
|
||||
/*
|
||||
* bottom left light block of finder pattern
|
||||
*
|
||||
* # #
|
||||
* # 0
|
||||
* # # #
|
||||
*/
|
||||
$this::assertSame(0b11110101, $this->matrix->checkNeighbours(1, 5));
|
||||
|
||||
/*
|
||||
* top right light block of finder pattern
|
||||
*
|
||||
* # # #
|
||||
* 0 #
|
||||
* # #
|
||||
*/
|
||||
$this::assertSame(0b01011111, $this->matrix->checkNeighbours(5, 1));
|
||||
|
||||
/*
|
||||
* bottom right light block of finder pattern
|
||||
*
|
||||
* # #
|
||||
* 0 #
|
||||
* # # #
|
||||
*/
|
||||
$this::assertSame(0b01111101, $this->matrix->checkNeighbours(5, 5));
|
||||
|
||||
|
||||
/*
|
||||
* M_TYPE check
|
||||
*
|
||||
* # # #
|
||||
* 0
|
||||
* X X X
|
||||
*/
|
||||
$this::assertSame(0b00000111, $this->matrix->checkNeighbours(3, 1, QRMatrix::M_FINDER));
|
||||
$this::assertSame(0b01110000, $this->matrix->checkNeighbours(3, 1, QRMatrix::M_FINDER_DOT));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user