Просмотр исходного кода

:shower: test cleanup & docblocks

codemasher 5 лет назад
Родитель
Сommit
4c47e123a5

+ 1 - 0
phpdoc.xml

@@ -8,6 +8,7 @@
 	</transformer>
 	<files>
 		<directory>src</directory>
+		<directory>tests</directory>
 	</files>
 	<transformations>
 		<template name="responsive-twig"/>

+ 19 - 4
tests/Data/AlphaNumTest.php

@@ -12,14 +12,18 @@
 
 namespace chillerlan\QRCodeTest\Data;
 
-use chillerlan\QRCode\Data\{AlphaNum, QRCodeDataException};
+use chillerlan\QRCode\Data\{AlphaNum, QRCodeDataException, QRDataInterface};
+use chillerlan\QRCode\QROptions;
 
-class AlphaNumTest extends DatainterfaceTestAbstract{
-
-	protected string $FQCN = AlphaNum::class;
+/**
+ * Tests the AlphaNum class
+ */
+final class AlphaNumTest extends DatainterfaceTestAbstract{
 
+	/** @internal */
 	protected string $testdata  = '0 $%*+-./:';
 
+	/** @internal */
 	protected array  $expected  = [
 		32, 80, 36, 212, 252, 15, 175, 251,
 		176, 236, 17, 236, 17, 236, 17, 236,
@@ -36,6 +40,17 @@ class AlphaNumTest extends DatainterfaceTestAbstract{
 		92, 112, 20, 198, 27
 	];
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getDataInterfaceInstance(QROptions $options):QRDataInterface{
+		return new AlphaNum($options);
+	}
+
+	/**
+	 * Tests if an exception is thrown when an invalid character is encountered
+	 */
 	public function testGetCharCodeException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('illegal char: "#" [35]');

+ 15 - 3
tests/Data/ByteTest.php

@@ -13,13 +13,18 @@
 namespace chillerlan\QRCodeTest\Data;
 
 use chillerlan\QRCode\Data\Byte;
+use chillerlan\QRCode\Data\QRDataInterface;
+use chillerlan\QRCode\QROptions;
 
-class ByteTest extends DatainterfaceTestAbstract{
-
-	protected string $FQCN = Byte::class;
+/**
+ * Tests the Byte class
+ */
+final class ByteTest extends DatainterfaceTestAbstract{
 
+	/** @internal */
 	protected string $testdata = '[¯\_(ツ)_/¯]';
 
+	/** @internal */
 	protected array  $expected = [
 		64, 245, 188, 42, 245, 197, 242, 142,
 		56, 56, 66, 149, 242, 252, 42, 245,
@@ -36,5 +41,12 @@ class ByteTest extends DatainterfaceTestAbstract{
 		21, 47, 250, 101
 	];
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getDataInterfaceInstance(QROptions $options):QRDataInterface{
+		return new Byte($options);
+	}
 
 }

+ 73 - 20
tests/Data/DatainterfaceTestAbstract.php

@@ -12,63 +12,116 @@
 
 namespace chillerlan\QRCodeTest\Data;
 
+use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\QROptions;
+use PHPUnit\Framework\TestCase;
 use chillerlan\QRCode\Data\{QRCodeDataException, QRDataInterface, QRMatrix};
-use chillerlan\QRCodeTest\QRTestAbstract;
+use ReflectionClass;
 
 use function str_repeat;
 
-abstract class DatainterfaceTestAbstract extends QRTestAbstract{
+/**
+ * Te data interface test abstract
+ */
+abstract class DatainterfaceTestAbstract extends TestCase{
 
+	/** @internal */
+	protected ReflectionClass $reflection;
+	/** @internal */
 	protected QRDataInterface $dataInterface;
-
+	/** @internal */
 	protected string $testdata;
-
+	/** @internal */
 	protected array  $expected;
 
+	/**
+	 * @internal
+	 */
 	protected function setUp():void{
-		parent::setUp();
-
-		/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
-		$this->dataInterface = $this->reflection->newInstanceArgs([new QROptions(['version' => 4])]);
+		$this->dataInterface = $this->getDataInterfaceInstance(new QROptions(['version' => 4]));
+		$this->reflection    = new ReflectionClass($this->dataInterface);
 	}
 
-	public function testInstance():void{
-		/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
-		$this->dataInterface = $this->reflection->newInstanceArgs([new QROptions, $this->testdata]);
+	/**
+	 * Returns a data interface instance
+	 *
+	 * @internal
+	 */
+	abstract protected function getDataInterfaceInstance(QROptions $options):QRDataInterface;
 
+	/**
+	 * Verifies the data interface instance
+	 */
+	public function testInstance():void{
 		$this::assertInstanceOf(QRDataInterface::class, $this->dataInterface);
 	}
 
-	public function testSetData():void{
+	/**
+	 * Tests ecc masking and verifies against a sample
+	 */
+	public function testMaskEcc():void{
 		$this->dataInterface->setData($this->testdata);
 
-		$this::assertSame($this->expected, $this->getProperty('matrixdata')->getValue($this->dataInterface));
+		$maskECC = $this->reflection->getMethod('maskECC');
+		$maskECC->setAccessible(true);
+
+		$this::assertSame($this->expected, $maskECC->invoke($this->dataInterface));
 	}
 
-	public function testInitMatrix():void{
-		$m = $this->dataInterface->setData($this->testdata)->initMatrix(0);
+	/**
+	 * @see testInitMatrix()
+	 * @internal
+	 * @return int[][]
+	 */
+	public function MaskPatternProvider():array{
+		return [[0], [1], [2], [3], [4], [5], [6], [7]];
+	}
+
+	/**
+	 * Tests initializing the data matrix
+	 *
+	 * @dataProvider MaskPatternProvider
+	 */
+	public function testInitMatrix(int $maskPattern):void{
+		$this->dataInterface->setData($this->testdata);
+
+		$matrix = $this->dataInterface->initMatrix($maskPattern);
 
-		$this::assertInstanceOf(QRMatrix::class, $m);
+		$this::assertInstanceOf(QRMatrix::class, $matrix);
+		$this::assertSame($maskPattern, $matrix->maskPattern());
 	}
 
+	/**
+	 * Tests getting the minimum QR version for the given data
+	 */
 	public function testGetMinimumVersion():void{
-		$this::assertSame(1, $this->getMethod('getMinimumVersion')->invoke($this->dataInterface));
+		$this->dataInterface->setData($this->testdata);
+
+		$getMinimumVersion = $this->reflection->getMethod('getMinimumVersion');
+		$getMinimumVersion->setAccessible(true);
+
+		$this::assertSame(1, $getMinimumVersion->invoke($this->dataInterface));
 	}
 
+	/**
+	 * Tests if an exception is thrown when the data exceeds the maximum version while auto detecting
+	 */
 	public function testGetMinimumVersionException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('data exceeds');
 
-		$this->getProperty('strlen')->setValue($this->dataInterface, 13370);
-		$this->getMethod('getMinimumVersion')->invoke($this->dataInterface);
+		$this->dataInterface = $this->getDataInterfaceInstance(new QROptions(['version' => QRCode::VERSION_AUTO]));
+		$this->dataInterface->setData(str_repeat($this->testdata, 1337));
 	}
 
+	/**
+	 * Tests if an exception is thrown on data overflow
+	 */
 	public function testCodeLengthOverflowException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('code length overflow');
 
-		$this->dataInterface->setData(str_repeat('0', 1337));
+		$this->dataInterface->setData(str_repeat($this->testdata, 1337));
 	}
 
 }

+ 22 - 13
tests/Data/KanjiTest.php

@@ -12,16 +12,18 @@
 
 namespace chillerlan\QRCodeTest\Data;
 
-use chillerlan\QRCode\Data\{Kanji, QRCodeDataException};
+use chillerlan\QRCode\QROptions;
+use chillerlan\QRCode\Data\{Kanji, QRCodeDataException, QRDataInterface};
 
-use function str_repeat;
-
-class KanjiTest extends DatainterfaceTestAbstract{
-
-	protected string $FQCN = Kanji::class;
+/**
+ * Tests the Kanji class
+ */
+final class KanjiTest extends DatainterfaceTestAbstract{
 
+	/** @internal */
 	protected string $testdata = '茗荷茗荷茗荷茗荷茗荷';
 
+	/** @internal */
 	protected array  $expected = [
 		128, 173, 85, 26, 95, 85, 70, 151,
 		213, 81, 165, 245, 84, 105, 125, 85,
@@ -38,6 +40,17 @@ class KanjiTest extends DatainterfaceTestAbstract{
 		96, 113, 54, 191
 	];
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getDataInterfaceInstance(QROptions $options):QRDataInterface{
+		return new Kanji($options);
+	}
+
+	/**
+	 * Tests if an exception is thrown when an invalid character is encountered
+	 */
 	public function testIllegalCharException1():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('illegal char at 1 [16191]');
@@ -45,6 +58,9 @@ class KanjiTest extends DatainterfaceTestAbstract{
 		$this->dataInterface->setData('ÃÃ');
 	}
 
+	/**
+	 * Tests if an exception is thrown when an invalid character is encountered
+	 */
 	public function testIllegalCharException2():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('illegal char at 1');
@@ -52,11 +68,4 @@ class KanjiTest extends DatainterfaceTestAbstract{
 		$this->dataInterface->setData('Ã');
 	}
 
-	public function testCodeLengthOverflowException():void{
-		$this->expectException(QRCodeDataException::class);
-		$this->expectExceptionMessage('code length overflow');
-
-		$this->dataInterface->setData(str_repeat('荷', 1337));
-	}
-
 }

+ 13 - 6
tests/Data/MaskPatternTesterTest.php

@@ -12,20 +12,27 @@
 
 namespace chillerlan\QRCodeTest\Data;
 
-use chillerlan\QRCode\{QROptions, Data\Byte, Data\MaskPatternTester};
-use chillerlan\QRCodeTest\QRTestAbstract;
+use chillerlan\QRCode\QROptions;
+use chillerlan\QRCode\Data\{Byte, MaskPatternTester};
+use PHPUnit\Framework\TestCase;
 
-class MaskPatternTesterTest extends QRTestAbstract{
-
-	protected string $FQCN = MaskPatternTester::class;
+/**
+ * MaskPatternTester coverage test
+ */
+final class MaskPatternTesterTest extends TestCase{
 
-	// coverage
+	/**
+	 * Tests getting the best mask pattern
+	 */
 	public function testMaskpattern():void{
 		$dataInterface = new Byte(new QROptions(['version' => 10]), 'test');
 
 		$this::assertSame(4, (new MaskPatternTester($dataInterface))->getBestMaskPattern());
 	}
 
+	/**
+	 * Tests getting the penalty value for a given mask pattern
+	 */
 	public function testMaskpatternID():void{
 		$dataInterface = new Byte(new QROptions(['version' => 10]), 'test');
 

+ 19 - 4
tests/Data/NumberTest.php

@@ -12,14 +12,18 @@
 
 namespace chillerlan\QRCodeTest\Data;
 
-use chillerlan\QRCode\Data\{Number, QRCodeDataException};
+use chillerlan\QRCode\QROptions;
+use chillerlan\QRCode\Data\{Number, QRCodeDataException, QRDataInterface};
 
-class NumberTest extends DatainterfaceTestAbstract{
-
-	protected string $FQCN = Number::class;
+/**
+ * Tests the Number class
+ */
+final class NumberTest extends DatainterfaceTestAbstract{
 
+	/** @internal */
 	protected string $testdata  = '0123456789';
 
+	/** @internal */
 	protected array $expected = [
 		16, 40, 12, 86, 106, 105, 0, 236,
 		17, 236, 17, 236, 17, 236, 17, 236,
@@ -36,6 +40,17 @@ class NumberTest extends DatainterfaceTestAbstract{
 		89, 63, 168, 151
 	];
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getDataInterfaceInstance(QROptions $options):QRDataInterface{
+		return new Number($options);
+	}
+
+	/**
+	 * Tests if an exception is thrown when an invalid character is encountered
+	 */
 	public function testGetCharCodeException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('illegal char: "#" [35]');

+ 182 - 67
tests/Data/QRMatrixTest.php

@@ -14,58 +14,97 @@ namespace chillerlan\QRCodeTest\Data;
 
 use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\Data\{QRCodeDataException, QRMatrix};
-use chillerlan\QRCodeTest\QRTestAbstract;
+use PHPUnit\Framework\TestCase;
 use ReflectionClass;
 
-class QRMatrixTest extends QRTestAbstract{
-
-	protected string $FQCN = QRMatrix::class;
-
-	protected int $version = 7;
+/**
+ * Tests the QRMatix class
+ */
+final class QRMatrixTest extends TestCase{
 
+	/** @internal */
+	protected const version = 40;
+	/** @internal */
 	protected QRMatrix $matrix;
 
+	/**
+	 * invokes a QRMatrix object
+	 *
+	 * @internal
+	 */
 	protected function setUp():void{
-		parent::setUp();
+		$this->matrix = $this->getMatrix($this::version);
+	}
+
+	/**
+	 * shortcut
+	 *
+	 * @internal
+	 */
+	protected function getMatrix(int $version):QRMatrix{
+		return  new QRMatrix($version, QRCode::ECC_L);
+	}
 
-		/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
-		$this->matrix = $this->reflection->newInstanceArgs([$this->version, QRCode::ECC_L]);
+	/**
+	 * Validates the QRMatrix instance
+	 */
+	public function testInstance():void{
+		$this::assertInstanceOf(QRMatrix::class, $this->matrix);
 	}
 
+	/**
+	 * Tests if an exception is thrown when an invalid QR version was given
+	 */
 	public function testInvalidVersionException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('invalid QR Code version');
 
-		$this->reflection->newInstanceArgs([42, 0]);
+		$this->matrix = new QRMatrix(42, 0);
 	}
 
+	/**
+	 * Tests if an exception is thrown when an invalid ECC level was given
+	 */
 	public function testInvalidEccException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('invalid ecc level');
 
-		$this->reflection->newInstanceArgs([1, 42]);
-	}
-
-	public function testInstance():void{
-		$this::assertInstanceOf($this->FQCN, $this->matrix);
+		$this->matrix = new QRMatrix(1, 42);
 	}
 
+	/**
+	 * Tests if size() returns the actual matrix size/count
+	 */
 	public function testSize():void{
 		$this::assertCount($this->matrix->size(), $this->matrix->matrix());
 	}
 
+	/**
+	 * Tests if version() returns the current (given) version
+	 */
 	public function testVersion():void{
-		$this::assertSame($this->version, $this->matrix->version());
+		$this::assertSame($this::version, $this->matrix->version());
 	}
 
+	/**
+	 * Tests if eccLevel() returns the current (given) ECC level
+	 */
 	public function testECC():void{
 		$this::assertSame(QRCode::ECC_L, $this->matrix->eccLevel());
 	}
 
+	/**
+	 * Tests if maskPattern() returns the current (or default) mask pattern
+	 */
 	public function testMaskPattern():void{
-		$this::assertSame(-1, $this->matrix->maskPattern());
+		$this::assertSame(-1, $this->matrix->maskPattern()); // default
+
+		// @todo: actual mask pattern after mapData()
 	}
 
+	/**
+	 * Tests the set(), get() and check() methods
+	 */
 	public function testGetSetCheck():void{
 		$this->matrix->set(10, 10, true, QRMatrix::M_TEST);
 		$this::assertSame(65280, $this->matrix->get(10, 10));
@@ -76,62 +115,112 @@ class QRMatrixTest extends QRTestAbstract{
 		$this::assertFalse($this->matrix->check(20, 20));
 	}
 
-	public function testSetDarkModule():void{
-		$this->matrix->setDarkModule();
+	/**
+	 * Version data provider for several pattern tests
+	 *
+	 * @return int[][]
+	 * @internal
+	 */
+	public function versionProvider():array{
+		$versions = [];
+
+		for($i = 1; $i <= 40; $i++){
+			$versions[] = [$i];
+		}
 
-		$this::assertSame(QRMatrix::M_DARKMODULE << 8, $this->matrix->get(8, $this->matrix->size() - 8));
+		return $versions;
 	}
 
-	public function testSetFinderPattern():void{
-		$this->matrix->setFinderPattern();
+	/**
+	 * Tests setting the dark module and verifies its position
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetDarkModule(int $version):void{
+		$matrix = $this->getMatrix($version)->setDarkModule();
 
-		$this::assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get(0, 0));
-		$this::assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get(0, $this->matrix->size() - 1));
-		$this::assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get($this->matrix->size() - 1, 0));
+		$this::assertSame(QRMatrix::M_DARKMODULE << 8, $matrix->get(8, $matrix->size() - 8));
 	}
 
-	public function testSetSeparators():void{
-		$this->matrix->setSeparators();
+	/**
+	 * Tests setting the finder patterns and verifies their positions
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetFinderPattern(int $version):void{
+		$matrix = $this->getMatrix($version)->setFinderPattern();
+
+		$this::assertSame(QRMatrix::M_FINDER << 8, $matrix->get(0, 0));
+		$this::assertSame(QRMatrix::M_FINDER << 8, $matrix->get(0, $matrix->size() - 1));
+		$this::assertSame(QRMatrix::M_FINDER << 8, $matrix->get($matrix->size() - 1, 0));
+	}
 
-		$this::assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get(7, 0));
-		$this::assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get(0, 7));
-		$this::assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get(0, $this->matrix->size() - 8));
-		$this::assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get($this->matrix->size() - 8, 0));
+	/**
+	 * Tests the separator patterns and verifies their positions
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetSeparators(int $version):void{
+		$matrix = $this->getMatrix($version)->setSeparators();
+
+		$this::assertSame(QRMatrix::M_SEPARATOR, $matrix->get(7, 0));
+		$this::assertSame(QRMatrix::M_SEPARATOR, $matrix->get(0, 7));
+		$this::assertSame(QRMatrix::M_SEPARATOR, $matrix->get(0, $matrix->size() - 8));
+		$this::assertSame(QRMatrix::M_SEPARATOR, $matrix->get($matrix->size() - 8, 0));
 	}
 
-	public function testSetAlignmentPattern():void{
-		$this->matrix
+	/**
+	 * Tests the alignment patterns and verifies their positions - version 1 (no pattern) skipped
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetAlignmentPattern(int $version):void{
+
+		if($version === 1){
+			$this->markTestSkipped('N/A');
+			return;
+		}
+
+		$matrix = $this
+			->getMatrix($version)
 			->setFinderPattern()
 			->setAlignmentPattern()
 		;
 
-		$alignmentPattern = (new ReflectionClass(QRMatrix::class))->getConstant('alignmentPattern')[$this->version];
+		$alignmentPattern = (new ReflectionClass(QRMatrix::class))->getConstant('alignmentPattern')[$version];
 
 		foreach($alignmentPattern as $py){
 			foreach($alignmentPattern as $px){
 
-				if($this->matrix->get($px, $py) === QRMatrix::M_FINDER << 8){
-					$this::assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get($px, $py), 'skipped finder pattern');
+				if($matrix->get($px, $py) === QRMatrix::M_FINDER << 8){
+					$this::assertSame(QRMatrix::M_FINDER << 8, $matrix->get($px, $py), 'skipped finder pattern');
 					continue;
 				}
 
-				$this::assertSame(QRMatrix::M_ALIGNMENT << 8, $this->matrix->get($px, $py));
+				$this::assertSame(QRMatrix::M_ALIGNMENT << 8, $matrix->get($px, $py));
 			}
 		}
 
 	}
 
-	public function testSetTimingPattern():void{
-		$this->matrix
+	/**
+	 * Tests the timing patterns and verifies their positions
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetTimingPattern(int $version):void{
+
+		$matrix = $this
+			->getMatrix($version)
 			->setAlignmentPattern()
 			->setTimingPattern()
 		;
 
-		$size = $this->matrix->size();
+		$size = $matrix->size();
 
 		for($i = 7; $i < $size - 7; $i++){
 			if($i % 2 === 0){
-				$p1 = $this->matrix->get(6, $i);
+				$p1 = $matrix->get(6, $i);
 
 				if($p1 === QRMatrix::M_ALIGNMENT << 8){
 					$this::assertSame(QRMatrix::M_ALIGNMENT << 8, $p1, 'skipped alignment pattern');
@@ -139,49 +228,75 @@ class QRMatrixTest extends QRTestAbstract{
 				}
 
 				$this::assertSame(QRMatrix::M_TIMING << 8, $p1);
-				$this::assertSame(QRMatrix::M_TIMING << 8, $this->matrix->get($i, 6));
+				$this::assertSame(QRMatrix::M_TIMING << 8, $matrix->get($i, 6));
 			}
 		}
 	}
 
-	public function testSetVersionNumber():void{
-		$this->matrix->setVersionNumber(true);
+	/**
+	 * Tests the version patterns and verifies their positions - version < 7 skipped
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetVersionNumber(int $version):void{
 
-		$this::assertSame(QRMatrix::M_VERSION, $this->matrix->get($this->matrix->size() - 9, 0));
-		$this::assertSame(QRMatrix::M_VERSION, $this->matrix->get($this->matrix->size() - 11, 5));
-		$this::assertSame(QRMatrix::M_VERSION, $this->matrix->get(0, $this->matrix->size() - 9));
-		$this::assertSame(QRMatrix::M_VERSION, $this->matrix->get(5, $this->matrix->size() - 11));
-	}
+		if($version < 7){
+			$this->markTestSkipped('N/A');
+			return;
+		}
 
-	public function testSetFormatInfo():void{
-		$this->matrix->setFormatInfo(0, true);
+		$matrix = $this->getMatrix($version)->setVersionNumber(true);
 
-		$this::assertSame(QRMatrix::M_FORMAT, $this->matrix->get(8, 0));
-		$this::assertSame(QRMatrix::M_FORMAT, $this->matrix->get(0, 8));
-		$this::assertSame(QRMatrix::M_FORMAT, $this->matrix->get($this->matrix->size() - 1, 8));
-		$this::assertSame(QRMatrix::M_FORMAT, $this->matrix->get($this->matrix->size() - 8, 8));
+		$this::assertSame(QRMatrix::M_VERSION, $matrix->get($matrix->size() - 9, 0));
+		$this::assertSame(QRMatrix::M_VERSION, $matrix->get($matrix->size() - 11, 5));
+		$this::assertSame(QRMatrix::M_VERSION, $matrix->get(0, $matrix->size() - 9));
+		$this::assertSame(QRMatrix::M_VERSION, $matrix->get(5, $matrix->size() - 11));
 	}
 
-	public function testSetQuietZone():void{
-		$size = $this->matrix->size();
+	/**
+	 * Tests the format patterns and verifies their positions
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetFormatInfo(int $version):void{
+		$matrix = $this->getMatrix($version)->setFormatInfo(0, true);
+
+		$this::assertSame(QRMatrix::M_FORMAT, $matrix->get(8, 0));
+		$this::assertSame(QRMatrix::M_FORMAT, $matrix->get(0, 8));
+		$this::assertSame(QRMatrix::M_FORMAT, $matrix->get($matrix->size() - 1, 8));
+		$this::assertSame(QRMatrix::M_FORMAT, $matrix->get($matrix->size() - 8, 8));
+	}
+
+	/**
+	 * Tests the quiet zone pattern and verifies its position
+	 *
+	 * @dataProvider versionProvider
+	 */
+	public function testSetQuietZone(int $version):void{
+		$matrix = $this->getMatrix($version);
+
+		$size = $matrix->size();
 		$q    = 5;
 
-		$this->matrix->set(0, 0, true, QRMatrix::M_TEST);
-		$this->matrix->set($size - 1, $size - 1, true, QRMatrix::M_TEST);
+		$matrix->set(0, 0, true, QRMatrix::M_TEST);
+		$matrix->set($size - 1, $size - 1, true, QRMatrix::M_TEST);
 
-		$this->matrix->setQuietZone($q);
+		$matrix->setQuietZone($q);
 
-		$this::assertCount($size + 2 * $q, $this->matrix->matrix());
-		$this::assertCount($size + 2 * $q, $this->matrix->matrix()[$size - 1]);
+		$this::assertCount($size + 2 * $q, $matrix->matrix());
+		$this::assertCount($size + 2 * $q, $matrix->matrix()[$size - 1]);
 
-		$size = $this->matrix->size();
-		$this::assertSame(QRMatrix::M_QUIETZONE, $this->matrix->get(0, 0));
-		$this::assertSame(QRMatrix::M_QUIETZONE, $this->matrix->get($size - 1, $size - 1));
+		$size = $matrix->size();
+		$this::assertSame(QRMatrix::M_QUIETZONE, $matrix->get(0, 0));
+		$this::assertSame(QRMatrix::M_QUIETZONE, $matrix->get($size - 1, $size - 1));
 
-		$this::assertSame(QRMatrix::M_TEST << 8, $this->matrix->get($q, $q));
-		$this::assertSame(QRMatrix::M_TEST << 8, $this->matrix->get($size - 1 - $q, $size - 1 - $q));
+		$this::assertSame(QRMatrix::M_TEST << 8, $matrix->get($q, $q));
+		$this::assertSame(QRMatrix::M_TEST << 8, $matrix->get($size - 1 - $q, $size - 1 - $q));
 	}
 
+	/**
+	 * Tests if an exception is thrown in an attempt to create it before data was written
+	 */
 	public function testSetQuietZoneException():void{
 		$this->expectException(QRCodeDataException::class);
 		$this->expectExceptionMessage('use only after writing data');

+ 7 - 3
tests/Helpers/BitBufferTest.php

@@ -12,10 +12,14 @@
 
 namespace chillerlan\QRCodeTest\Helpers;
 
-use chillerlan\QRCode\{QRCode, Helpers\BitBuffer};
-use chillerlan\QRCodeTest\QRTestAbstract;
+use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Helpers\BitBuffer;
+use PHPUnit\Framework\TestCase;
 
-class BitBufferTest extends QRTestAbstract{
+/**
+ * BitBuffer coverage test
+ */
+final class BitBufferTest extends TestCase{
 
 	protected BitBuffer $bitBuffer;
 

+ 5 - 2
tests/Helpers/PolynomialTest.php

@@ -14,9 +14,12 @@ namespace chillerlan\QRCodeTest\Helpers;
 
 use chillerlan\QRCode\Helpers\Polynomial;
 use chillerlan\QRCode\QRCodeException;
-use chillerlan\QRCodeTest\QRTestAbstract;
+use PHPUnit\Framework\TestCase;
 
-class PolynomialTest extends QRTestAbstract{
+/**
+ * Polynomial coverage test
+ */
+final class PolynomialTest extends TestCase{
 
 	protected Polynomial $polynomial;
 

+ 33 - 19
tests/Output/QRImageTest.php

@@ -12,12 +12,40 @@
 
 namespace chillerlan\QRCodeTest\Output;
 
-use chillerlan\QRCode\{QRCode, Output\QRImage};
+use chillerlan\QRCode\{QRCode, QROptions};
+use chillerlan\QRCode\Output\{QROutputInterface, QRImage};
 
+/**
+ * Tests the QRImage output module
+ */
 class QRImageTest extends QROutputTestAbstract{
 
-	protected string $FQCN = QRImage::class;
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	public function setUp():void{
+
+		if(!extension_loaded('gd')){
+			$this->markTestSkipped('ext-gd not loaded');
+			return;
+		}
+
+		parent::setUp();
+	}
+
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getOutputInterface(QROptions $options):QROutputInterface{
+		return new QRImage($options, $this->matrix);
+	}
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
 	public function types():array{
 		return [
 			'png' => [QRCode::OUTPUT_IMAGE_PNG],
@@ -27,23 +55,8 @@ class QRImageTest extends QROutputTestAbstract{
 	}
 
 	/**
-	 * @dataProvider types
+	 * @inheritDoc
 	 */
-	public function testImageOutput(string $type):void{
-		$this->options->outputType  = $type;
-		$this->options->imageBase64 = false;
-
-		$this->setOutputInterface();
-		$this->outputInterface->dump($this::cachefile.$type);
-		$img = $this->outputInterface->dump();
-
-		if($type === QRCode::OUTPUT_IMAGE_JPG){ // jpeg encoding may cause different results
-			$this->markAsRisky();
-		}
-
-		$this::assertSame($img, file_get_contents($this::cachefile.$type));
-	}
-
 	public function testSetModuleValues():void{
 
 		$this->options->moduleValues = [
@@ -52,7 +65,8 @@ class QRImageTest extends QROutputTestAbstract{
 			4    => [255, 255, 255],
 		];
 
-		$this->setOutputInterface()->dump();
+		$this->outputInterface = $this->getOutputInterface($this->options);
+		$this->outputInterface->dump();
 
 		$this::assertTrue(true); // tricking the code coverage
 	}

+ 29 - 12
tests/Output/QRImagickTest.php

@@ -12,12 +12,18 @@
 
 namespace chillerlan\QRCodeTest\Output;
 
-use chillerlan\QRCode\{QRCode, Output\QRImagick};
+use chillerlan\QRCode\{QRCode, QROptions};
+use chillerlan\QRCode\Output\{QROutputInterface, QRImagick};
 
+/**
+ * Tests the QRImagick output module
+ */
 class QRImagickTest extends QROutputTestAbstract{
 
-	protected string $FQCN = QRImagick::class;
-
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
 	public function setUp():void{
 
 		if(!extension_loaded('imagick')){
@@ -28,17 +34,27 @@ class QRImagickTest extends QROutputTestAbstract{
 		parent::setUp();
 	}
 
-	public function testImageOutput():void{
-		$type = QRCode::OUTPUT_IMAGICK;
-
-		$this->options->outputType = $type;
-		$this->setOutputInterface();
-		$this->outputInterface->dump($this::cachefile.$type);
-		$img = $this->outputInterface->dump();
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getOutputInterface(QROptions $options):QROutputInterface{
+		return new QRImagick($options, $this->matrix);
+	}
 
-		$this::assertSame($img, file_get_contents($this::cachefile.$type));
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	public function types():array{
+		return [
+			'imagick' => [QRCode::OUTPUT_IMAGICK],
+		];
 	}
 
+	/**
+	 * @inheritDoc
+	 */
 	public function testSetModuleValues():void{
 
 		$this->options->moduleValues = [
@@ -47,7 +63,8 @@ class QRImagickTest extends QROutputTestAbstract{
 			4    => '#ECF9BE',
 		];
 
-		$this->setOutputInterface()->dump();
+		$this->outputInterface = $this->getOutputInterface($this->options);
+		$this->outputInterface->dump();
 
 		$this::assertTrue(true); // tricking the code coverage
 	}

+ 18 - 34
tests/Output/QRMarkupTest.php

@@ -12,12 +12,26 @@
 
 namespace chillerlan\QRCodeTest\Output;
 
-use chillerlan\QRCode\{QRCode, Output\QRMarkup};
+use chillerlan\QRCode\{QRCode, QROptions};
+use chillerlan\QRCode\Output\{QROutputInterface, QRMarkup};
 
+/**
+ * Tests the QRMarkup output module
+ */
 class QRMarkupTest extends QROutputTestAbstract{
 
-	protected string $FQCN = QRMarkup::class;
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getOutputInterface(QROptions $options):QROutputInterface{
+		return new QRMarkup($options, $this->matrix);
+	}
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
 	public function types():array{
 		return [
 			'html' => [QRCode::OUTPUT_MARKUP_HTML],
@@ -26,38 +40,8 @@ class QRMarkupTest extends QROutputTestAbstract{
 	}
 
 	/**
-	 * @dataProvider types
+	 * @inheritDoc
 	 */
-	public function testMarkupOutputFile(string $type):void{
-		$this->options->outputType = $type;
-		$this->options->cachefile  = $this::cachefile.$type;
-		$this->setOutputInterface();
-		$data = $this->outputInterface->dump();
-
-		$this::assertSame($data, file_get_contents($this->options->cachefile));
-	}
-
-	/**
-	 * @dataProvider types
-	 */
-	public function testMarkupOutput(string $type):void{
-		$this->options->outputType = $type;
-		$this->setOutputInterface();
-
-		$expected = explode($this->options->eol, file_get_contents($this::cachefile.$type));
-		// cut off the doctype & head
-		array_shift($expected);
-
-		if($type === QRCode::OUTPUT_MARKUP_HTML){
-			// cut off the </body> tag
-			array_pop($expected);
-		}
-
-		$expected = implode($this->options->eol, $expected);
-
-		$this::assertSame(trim($expected), trim($this->outputInterface->dump()));
-	}
-
 	public function testSetModuleValues():void{
 
 		$this->options->moduleValues = [
@@ -66,7 +50,7 @@ class QRMarkupTest extends QROutputTestAbstract{
 			4    => '#ECF9BE',
 		];
 
-		$this->setOutputInterface();
+		$this->outputInterface = $this->getOutputInterface($this->options);
 		$data = $this->outputInterface->dump();
 		$this::assertStringContainsString('#4A6000', $data);
 		$this::assertStringContainsString('#ECF9BE', $data);

+ 99 - 22
tests/Output/QROutputTestAbstract.php

@@ -12,53 +12,130 @@
 
 namespace chillerlan\QRCodeTest\Output;
 
-use chillerlan\QRCode\QROptions;
+use chillerlan\QRCodeExamples\MyCustomOutput;
+use chillerlan\QRCode\{QRCode, QROptions};
 use chillerlan\QRCode\Data\{Byte, QRMatrix};
 use chillerlan\QRCode\Output\{QRCodeOutputException, QROutputInterface};
-use chillerlan\QRCodeTest\QRTestAbstract;
-use chillerlan\Settings\SettingsContainerInterface;
+use PHPUnit\Framework\TestCase;
 
-use function dirname, file_exists, mkdir;
+use function file_exists, mkdir;
 
-abstract class QROutputTestAbstract extends QRTestAbstract{
-
-	protected const cachefile = __DIR__.'/../../.build/output_test/test.';
+/**
+ * Test abstract for the several (built-in) output modules,
+ * should also be used to test custom output modules
+ */
+abstract class QROutputTestAbstract extends TestCase{
 
+	/** @internal  */
+	protected string $builddir = __DIR__.'/../../.build/output_test';
+	/** @internal  */
 	protected QROutputInterface $outputInterface;
-	/** @var \chillerlan\Settings\SettingsContainerInterface|\chillerlan\QRCode\QROptions */
-	protected SettingsContainerInterface $options;
-
+	/** @internal  */
+	protected QROptions $options;
+	/** @internal  */
 	protected QRMatrix $matrix;
 
+	/**
+	 * Attempts to create a directory under /.build and instances several required objects
+	 *
+	 * @internal
+	 */
 	protected function setUp():void{
-		parent::setUp();
 
-		$buildDir = dirname($this::cachefile);
-		if(!file_exists($buildDir)){
-			mkdir($buildDir, 0777, true);
+		if(!file_exists($this->builddir)){
+			mkdir($this->builddir, 0777, true);
 		}
 
-		$this->options = new QROptions;
-		$this->setOutputInterface();
+		$this->options         = new QROptions;
+		$this->matrix          = (new Byte($this->options, 'testdata'))->initMatrix(0);
+		$this->outputInterface = $this->getOutputInterface($this->options);
 	}
 
-	protected function setOutputInterface():QROutputInterface{
-		/** @noinspection PhpFieldAssignmentTypeMismatchInspection */
-		$this->outputInterface = $this->reflection->newInstanceArgs([$this->options, (new Byte($this->options, 'testdata'))->initMatrix(0)]);
-		return $this->outputInterface;
-	}
+	/**
+	 * Returns a QROutputInterface instance with the given options and using $this->matrix
+	 *
+	 * @internal
+	 */
+	abstract protected function getOutputInterface(QROptions $options):QROutputInterface;
 
+	/**
+	 * Validate the instance of the interface
+	 */
 	public function testInstance():void{
 		$this::assertInstanceOf(QROutputInterface::class, $this->outputInterface);
 	}
 
+	/**
+	 * Tests if an exception is thrown when trying to write a cache file to an invalid destination
+	 */
 	public function testSaveException():void{
 		$this->expectException(QRCodeOutputException::class);
 		$this->expectExceptionMessage('Could not write data to cache file: /foo');
 
 		$this->options->cachefile = '/foo';
-		$this->setOutputInterface();
+		$this->outputInterface = $this->getOutputInterface($this->options);
 		$this->outputInterface->dump();
 	}
 
+	/**
+	 * covers the module values settings
+	 */
+	abstract public function testSetModuleValues():void;
+
+	/*
+	 * additional, non-essential, potentially inaccurate coverage tests
+	 */
+
+	/**
+	 * @see testStringOutput()
+	 * @return string[][]
+	 * @internal
+	 */
+	abstract public function types():array;
+
+	/**
+	 * coverage of the built-in output modules
+	 *
+	 * @dataProvider types
+	 */
+	public function testStringOutput(string $type):void{
+		$this->options->outputType  = $type;
+		$this->options->cachefile   = $this->builddir.'/test.'.$type;
+		$this->options->imageBase64 = false;
+
+		$this->outputInterface     = $this->getOutputInterface($this->options);
+		$data                      = $this->outputInterface->dump(); // creates the cache file
+
+		$this::assertSame($data, file_get_contents($this->options->cachefile));
+	}
+
+	/**
+	 * covers the built-in output modules, tests against pre-rendered data
+	 *
+	 * @dataProvider types
+	 */
+	public function testRenderImage(string $type):void{
+		$this->options->outputType = $type;
+
+		$this::assertSame(
+			trim(file_get_contents(__DIR__.'/samples/'.$type)),
+			trim((new QRCode($this->options))->render('test'))
+		);
+	}
+
+	/**
+	 * covers the custom output functionality via an example
+	 */
+	public function testCustomOutput():void{
+		$this->options->version         = 5;
+		$this->options->eccLevel        = QRCode::ECC_L;
+		$this->options->outputType      = QRCode::OUTPUT_CUSTOM;
+		$this->options->outputInterface = MyCustomOutput::class;
+
+		$this::assertSame(
+			trim(file_get_contents(__DIR__.'/samples/custom')),
+			(new QRCode($this->options))->render('test')
+		);
+	}
+
 }

+ 19 - 14
tests/Output/QRStringTest.php

@@ -12,12 +12,26 @@
 
 namespace chillerlan\QRCodeTest\Output;
 
-use chillerlan\QRCode\{QRCode, Output\QRString};
+use chillerlan\QRCode\{QRCode, QROptions};
+use chillerlan\QRCode\Output\{QROutputInterface, QRString};
 
+/**
+ * Tests the QRString output module
+ */
 class QRStringTest extends QROutputTestAbstract{
 
-	protected string $FQCN = QRString::class;
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
+	protected function getOutputInterface(QROptions $options):QROutputInterface{
+		return new QRString($options, $this->matrix);
+	}
 
+	/**
+	 * @inheritDoc
+	 * @internal
+	 */
 	public function types():array{
 		return [
 			'json' => [QRCode::OUTPUT_STRING_JSON],
@@ -26,17 +40,8 @@ class QRStringTest extends QROutputTestAbstract{
 	}
 
 	/**
-	 * @dataProvider types
+	 * @inheritDoc
 	 */
-	public function testStringOutput(string $type):void{
-		$this->options->outputType = $type;
-		$this->options->cachefile  = $this::cachefile.$type;
-		$this->setOutputInterface();
-		$data = $this->outputInterface->dump();
-
-		$this::assertSame($data, file_get_contents($this->options->cachefile));
-	}
-
 	public function testSetModuleValues():void{
 
 		$this->options->moduleValues = [
@@ -45,8 +50,8 @@ class QRStringTest extends QROutputTestAbstract{
 			4    => 'B',
 		];
 
-		$this->setOutputInterface();
-		$data = $this->outputInterface->dump();
+		$this->outputInterface = $this->getOutputInterface($this->options);
+		$data                  = $this->outputInterface->dump();
 
 		$this::assertStringContainsString('A', $data);
 		$this::assertStringContainsString('B', $data);

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tests/Output/samples/custom


+ 1 - 0
tests/Output/samples/gif

@@ -0,0 +1 @@
+data:image/gif;base64,R0lGODlhkQCRAIAAAAQCBP///yH5BAEAAAEALAAAAACRAJEAAAL+jI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpfMpvOpBEin1Kr1ek1gpY6qdgsOU1niMviL7Y4R5raV7I4D0NmGly13w/Nm+tu+dsDXtjcY5nfHkGhgWFY4x7GoIOlXGRmYQnmhKYg56clZEToyOjF6CuqJURrCGoE6pRaLN7vh+nH7AMsFWMuouglcIklIy9vpG0CcmlyMfJzJLGb5DFlN/dvcZ2wdre3Ija0s3T3+PR2+sgx+nd7+ng1tjg6Psk4fX36vT464JX5i3xl3+WTJE+esoDpyA+vtKodwW72ADP8RnAfxYkT+dgpVCLToUFjHBR/TaDRRsk7IZAAvJsT4yJ/Jlfh0VZw50t5NlTlfGuTHEebCc4dcSoSQ8s9ElDuV9jxqk2jDnBSlgnwa9KdMnkI9iqSQa9VXU2NblX11VkPYXgeZsgz2FsRaRWk9zCVZV2xcUXkv7QXb18LdT39FNKq5b+NhnDoXM05s1DHXqpIh0wRaObDazJaxyuM8WC9ozKQVg4bC1ilqHVNX52jt+gbs2DVm087nM/Lnrw9bh4YbR6vujEur+dacgY/wy8vxBv0tOE/zrlRPGr9KvXHw1Kanb1UNne/flw9bXu6snThu7OWtewaPXLR6jMfH9+PODT3l+eT+ed+naxVRMaVWX1vM4XedgEPtFuBkCK4nx0/hAaZggg4CyKAhEsYHXGn5YTfdYhsWZlaFEF7oXIaDjGggCejlhiFpyhHIYXQNzvedabnot6CMdRXoI4kHvpAUWY81ZaSKMRQpAZA5NvmfC0yideSNSXpIg5Pu0ceef1W22IKWxZ0In31f4tjji14itmaZYD6ipplsyukmml6daR6ZPFqI5W17vtfdbYA+mN2fUBgap5KCFtpmoGMeGiVhig4p5WhvbgmkbZVaeiWLQaIYpqV2VsfndxN2IOqo2T3J56l+jdYpjTe6akuNpL4HI5k2TNheqyB+KKQ3l1IJZlKachn+bHqoNgpsTazOwCuzvjL2rAzGRmqqtEhBtV+2JkpaVIxXHmtYU4hyu6W3w+JiLrbNqpYnuOSWqKKYKYZ777i/DtPut/M+am+os0b6763ITrppvV1aCSWdhnb7bqLwElotreIpjOe7scb4sFsYcyXxud8u2S/CjGYsbro9qtvnySBruyoM1/qLJKbuEllyy1Ma3PGd60b1sR7D9SqsqiEepiPMENc68HM1p+yz0YSKOLTSHksNtZ5Q7QwunJlVvK/BO6QKNrUqvyZq2aBanB5nak/86Nhpa0x31ovejXfeeu/Nd99+/w144IIPTnjhhh+OeOKKL854444/DnnkkhcCXgAAOw==

+ 31 - 0
tests/Output/samples/html

@@ -0,0 +1,31 @@
+<div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #000;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+<div><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span><span style="background: #fff;"></span></div>
+</div>

BIN
tests/Output/samples/imagick


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tests/Output/samples/jpg


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
tests/Output/samples/json


+ 1 - 0
tests/Output/samples/png

@@ -0,0 +1 @@
+data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJEAAACRCAIAAABMus10AAAABnRSTlMA/wD/AP83WBt9AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACd0lEQVR4nO3dQW7jIABA0fFo7n/ldFnJC0sMBvu3762bJtUXMnUwHJ/P5w8pf5/+AAzTrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEeznn8zLz6O467Pce20aOX6fa9XuJxeO/SbbzSzDMc469GsR7MezXqm5iAnNy5vHZplrJs4bPuLhhhnPZr1aNajWc+dc5CToavu0NV+6F7GU/OIdQ8cGWc9mvVo1qNZz8I5yFO2TUmeYpz1aNajWY9mPT9hDjKzPKTIOOvRrEezHs16Fs5B1l38n5pWvGQ6Y5z1aNajWY9mPXfOQbY9VDKzHmToq5ltf9EQ46xHsx7NejTrOV7yv/0M38Xwdpr1aNajWc9j+4PcuIvHzKO6626LrFsaa5z1aNajWY9mPfv2BzldhGd2AJm5gM9MOp7a0OzEOOvRrEezHs169u0PMnQB3/ZA7Utumgwxzno069GsR7Oefc/mzkwrtq34uHGrtJnffM0469GsR7MezXqm5iAzx7hse3pl3eKRpxhnPZr1aNajWc9j58XM3DXYtle79SDcQ7MezXo060mem7ttecg717AYZz2a9WjWo1lP8tzc6x9ed7fCfRD+k2Y9mvVo1pM8N3fmfbftALJuHa1x1qNZj2Y9mvUkz6y78fJ+4+LXbef1Gmc9mvVo1qNZT3IOcjLzeM6697UehG+a9WjWo1lP8tzck3WLR2Yez5n54WvGWY9mPZr1aNaTPDf32szK0XW3NnwX86tp1qNZj2Y9P+Hc3N/GOOvRrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEezHs16NOvRrEezni+wifc/oOyB/wAAAABJRU5ErkJggg==

Разница между файлами не показана из-за своего большого размера
+ 2 - 0
tests/Output/samples/svg


+ 29 - 0
tests/Output/samples/text

@@ -0,0 +1,29 @@
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕🔴🔴⭕⭕🔴⭕🔴🔴🔴🔴🔴🔴🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕🔴⭕⭕🔴⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴⭕🔴⭕🔴⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴⭕⭕🔴⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴🔴🔴⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕🔴⭕🔴⭕🔴⭕🔴🔴🔴🔴🔴🔴🔴⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕🔴🔴⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴🔴🔴🔴⭕⭕🔴⭕🔴⭕🔴⭕⭕🔴⭕⭕🔴🔴🔴⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕⭕🔴🔴🔴⭕🔴⭕⭕🔴⭕🔴⭕⭕🔴⭕🔴🔴⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴⭕🔴🔴🔴⭕⭕⭕🔴⭕🔴🔴🔴🔴🔴⭕⭕🔴🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴⭕⭕⭕🔴🔴⭕🔴⭕🔴🔴⭕⭕⭕🔴⭕🔴⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕🔴🔴⭕🔴⭕🔴⭕⭕🔴🔴🔴⭕🔴⭕⭕🔴🔴⭕🔴⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕🔴⭕🔴⭕⭕🔴⭕🔴⭕🔴⭕🔴⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕⭕⭕🔴⭕⭕🔴🔴⭕🔴🔴🔴⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕⭕🔴⭕🔴🔴🔴🔴⭕⭕🔴🔴⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕⭕🔴🔴🔴⭕⭕🔴⭕⭕⭕🔴🔴🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴🔴⭕⭕⭕🔴⭕⭕🔴🔴⭕🔴⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕🔴🔴🔴⭕🔴⭕🔴⭕🔴🔴⭕🔴⭕⭕🔴⭕🔴⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕🔴⭕⭕⭕⭕⭕🔴⭕🔴🔴🔴🔴🔴⭕🔴⭕🔴🔴⭕⭕🔴⭕⭕⭕⭕
+⭕⭕⭕⭕🔴🔴🔴🔴🔴🔴🔴⭕🔴🔴⭕🔴🔴⭕⭕🔴⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕
+⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕⭕

Разница между файлами не показана из-за своего большого размера
+ 44 - 53
tests/QRCodeTest.php


+ 97 - 48
tests/QROptionsTest.php

@@ -8,88 +8,137 @@
  * @author       smiley <smiley@chillerlan.net>
  * @copyright    2018 smiley
  * @license      MIT
+ *
+ * @noinspection PhpUnusedLocalVariableInspection
  */
 
 namespace chillerlan\QRCodeTest;
 
-use chillerlan\Settings\SettingsContainerInterface;
 use chillerlan\QRCode\{QRCode, QRCodeException, QROptions};
 use PHPUnit\Framework\TestCase;
 
+/**
+ * QROptions test
+ */
 class QROptionsTest extends TestCase{
 
-	/** @var \chillerlan\Settings\SettingsContainerInterface|\chillerlan\QRCode\QROptions */
-	protected SettingsContainerInterface $options;
-
-	public function testVersionClamp():void{
-		$o = new QROptions(['version' => 42]);
-		$this::assertSame(40, $o->version);
+	/**
+	 * @see testVersionClamp()
+	 * @return int[][]
+	 * @internal
+	 */
+	public function VersionProvider():array{
+		return [
+			'values > 40 should be clamped to 40'        => [42, 40],
+			'values < 1 should be clamped to 1'          => [-42, 1],
+			'values in between shold not be touched'     => [21, 21],
+			'value -1 should be treated as is (default)' => [QRCode::VERSION_AUTO, -1],
+		];
+	}
 
-		$o = new QROptions(['version' => -42]);
-		$this::assertSame(1, $o->version);
+	/**
+	 * Tests the $version clamping
+	 *
+	 * @dataProvider VersionProvider
+	 */
+	public function testVersionClamp(int $version, int $expected):void{
+		$o = new QROptions(['version' => $version]);
 
-		$o = new QROptions(['version' => 21]);
-		$this::assertSame(21, $o->version);
+		$this::assertSame($expected, $o->version);
+	}
 
-		// QRCode::VERSION_AUTO = -1, default
-		$o = new QROptions;
-		$this::assertSame(QRCode::VERSION_AUTO, $o->version);
+	/**
+	 * @see testVersionMinMaxClamp()
+	 * @return int[][]
+	 * @internal
+	 */
+	public function VersionMinMaxProvider():array{
+		return [
+			'normal clamp'         => [5, 10, 5, 10],
+			'exceeding values'     => [-42, 42, 1, 40],
+			'min > max'            => [10, 5, 5, 10],
+			'min > max, exceeding' => [42, -42, 1, 40],
+		];
 	}
 
-	public function testVersionMinMaxClamp():void{
-		// normal clamp
-		$o = new QROptions(['versionMin' => 5, 'versionMax' => 10]);
-		$this::assertSame(5, $o->versionMin);
-		$this::assertSame(10, $o->versionMax);
-
-		// exceeding values
-		$o = new QROptions(['versionMin' => -42, 'versionMax' => 42]);
-		$this::assertSame(1, $o->versionMin);
-		$this::assertSame(40, $o->versionMax);
-
-		// min > max
-		$o = new QROptions(['versionMin' => 10, 'versionMax' => 5]);
-		$this::assertSame(5, $o->versionMin);
-		$this::assertSame(10, $o->versionMax);
-
-		$o = new QROptions(['versionMin' => 42, 'versionMax' => -42]);
-		$this::assertSame(1, $o->versionMin);
-		$this::assertSame(40, $o->versionMax);
+	/**
+	 * Tests the $versionMin/$versionMax clamping
+	 *
+	 * @dataProvider VersionMinMaxProvider
+	 */
+	public function testVersionMinMaxClamp(int $versionMin, int $versionMax, int $expectedMin, int $expectedMax):void{
+		$o = new QROptions(['versionMin' => $versionMin, 'versionMax' => $versionMax]);
+
+		$this::assertSame($expectedMin, $o->versionMin);
+		$this::assertSame($expectedMax, $o->versionMax);
 	}
 
-	public function testMaskPatternClamp():void{
-		$o = new QROptions(['maskPattern' => 42]);
-		$this::assertSame(7, $o->maskPattern);
+	/**
+	 * @see testMaskPatternClamp()
+	 * @return int[][]
+	 * @internal
+	 */
+	public function MaskPatternProvider():array{
+		return [
+			'exceed max'   => [42, 7,],
+			'exceed min'   => [-42, 0],
+			'default (-1)' => [QRCode::MASK_PATTERN_AUTO, -1],
+		];
+	}
 
-		$o = new QROptions(['maskPattern' => -42]);
-		$this::assertSame(0, $o->maskPattern);
+	/**
+	 * Tests the $maskPattern clamping
+	 *
+	 * @dataProvider MaskPatternProvider
+	 */
+	public function testMaskPatternClamp(int $maskPattern, int $expected):void{
+		$o = new QROptions(['maskPattern' => $maskPattern]);
 
-		// QRCode::MASK_PATTERN_AUTO = -1, default
-		$o = new QROptions;
-		$this::assertSame(QRCode::MASK_PATTERN_AUTO, $o->maskPattern);
+		$this::assertSame($expected, $o->maskPattern);
 	}
 
+	/**
+	 * Tests if an exception is thrown on an incorrect ECC level
+	 */
 	public function testInvalidEccLevelException():void{
 		$this->expectException(QRCodeException::class);
 		$this->expectExceptionMessage('Invalid error correct level: 42');
 
-		/** @noinspection PhpUnusedLocalVariableInspection */
 		$o = new QROptions(['eccLevel' => 42]);
 	}
 
-	public function testClampRGBValues():void{
-		$o = new QROptions(['imageTransparencyBG' => [-1, 0, 999]]);
+	/**
+	 * @see testClampRGBValues()
+	 * @return int[][][]
+	 * @internal
+	 */
+	public function RGBProvider():array{
+		return [
+			'exceeding values' => [[-1, 0, 999], [0, 0 ,255]],
+			'too few values'   => [[1, 2], [255, 255, 255]],
+			'too many values'  => [[1, 2, 3, 4, 5], [1, 2, 3]],
+		];
+	}
 
-		$this::assertSame(0, $o->imageTransparencyBG[0]);
-		$this::assertSame(0, $o->imageTransparencyBG[1]);
-		$this::assertSame(255, $o->imageTransparencyBG[2]);
+	/**
+	 * Tests clamping of the RGB values for $imageTransparencyBG
+	 *
+	 * @dataProvider RGBProvider
+	 */
+	public function testClampRGBValues(array $rgb, array $expected):void{
+		$o = new QROptions(['imageTransparencyBG' => $rgb]);
+
+		$this::assertSame($expected, $o->imageTransparencyBG);
 	}
 
+	/**
+	 * Tests if an exception is thrown when a non-numeric RGB value was encoutered
+	 */
 	public function testInvalidRGBValueException():void{
 		$this->expectException(QRCodeException::class);
 		$this->expectExceptionMessage('Invalid RGB value.');
 
-		/** @noinspection PhpUnusedLocalVariableInspection */
 		$o = new QROptions(['imageTransparencyBG' => ['r', 'g', 'b']]);
 	}
+
 }

+ 0 - 65
tests/QRTestAbstract.php

@@ -1,65 +0,0 @@
-<?php
-/**
- * Class QRTestAbstract
- *
- * @filesource   QRTestAbstract.php
- * @created      17.11.2017
- * @package      chillerlan\QRCodeTest
- * @author       Smiley <smiley@chillerlan.net>
- * @copyright    2017 Smiley
- * @license      MIT
- */
-
-namespace chillerlan\QRCodeTest;
-
-use PHPUnit\Framework\TestCase;
-use ReflectionClass, ReflectionMethod, ReflectionProperty;
-
-abstract class QRTestAbstract extends TestCase{
-
-	protected ReflectionClass $reflection;
-
-	protected string $FQCN;
-
-	protected function setUp():void{
-		$this->reflection = new ReflectionClass($this->FQCN);
-	}
-
-	/**
-	 * @param string $method
-	 *
-	 * @return \ReflectionMethod
-	 */
-	protected function getMethod(string $method):ReflectionMethod{
-		$method = $this->reflection->getMethod($method);
-		$method->setAccessible(true);
-
-		return $method;
-	}
-
-	/**
-	 * @param string $property
-	 *
-	 * @return \ReflectionProperty
-	 */
-	protected function getProperty(string $property):ReflectionProperty{
-		$property = $this->reflection->getProperty($property);
-		$property->setAccessible(true);
-
-		return $property;
-	}
-
-	/**
-	 * @param object $object
-	 * @param string $property
-	 * @param mixed  $value
-	 *
-	 * @return void
-	 */
-	protected function setProperty($object, string $property, $value):void{
-		$property = $this->getProperty($property);
-		$property->setAccessible(true);
-		$property->setValue($object, $value);
-	}
-
-}

Некоторые файлы не были показаны из-за большого количества измененных файлов