:octocat: +several coverage tests & cleanup

This commit is contained in:
smiley
2022-07-26 17:15:49 +02:00
parent 4aa66dd574
commit 9db842d6ca
15 changed files with 334 additions and 18 deletions
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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
View File
@@ -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');
}
}
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+6 -6
View File
@@ -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
+1 -1
View File
@@ -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.
+9
View File
@@ -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);
}
}
+60
View File
@@ -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]);
}
}
+64
View File
@@ -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);
}
}
+67
View File
@@ -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);
}
}
+109
View File
@@ -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));
}
}