Skip to content

Commit 178f444

Browse files
committed
🚨 breakdown tests into separate files
1 parent 5957248 commit 178f444

14 files changed

+421
-282
lines changed

composer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
"phpunit/phpunit": "@stable"
2525
},
2626
"suggest": {
27-
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
28-
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
27+
"bacon/bacon-qr-code": "Needed for BaconQrCodeProvider provider",
28+
"endroid/qr-code": "Needed for EndroidQrCodeProvider"
2929
},
3030
"autoload": {
3131
"psr-4": {
@@ -34,7 +34,7 @@
3434
},
3535
"autoload-dev": {
3636
"psr-4": {
37-
"RobThree\\Auth\\Test\\": "tests"
37+
"Tests\\": "tests/"
3838
}
3939
}
4040
}

tests/MightNotMakeAssertions.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Tests;
4+
5+
trait MightNotMakeAssertions
6+
{
7+
/**
8+
* This is a shim to support PHPUnit for php 5.6 and 7.0.
9+
*
10+
* It has to be named something that doesn't collide with existing
11+
* TestCase methods as we can't support PHP return types right now
12+
*/
13+
public function noAssertionsMade()
14+
{
15+
foreach (class_parents($this) as $parent) {
16+
if (method_exists($parent, 'expectNotToPerformAssertions')) {
17+
return parent::expectNotToPerformAssertions();
18+
}
19+
}
20+
21+
return $this->assertTrue(true);
22+
}
23+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Tests\Providers\Qr;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use RobThree\Auth\TwoFactorAuth;
7+
use RobThree\Auth\TwoFactorAuthException;
8+
9+
class IQRCodeProviderTest extends TestCase
10+
{
11+
private function DecodeDataUri($datauri)
12+
{
13+
if (preg_match('/data:(?P<mimetype>[\w\.\-\/]+);(?P<encoding>\w+),(?P<data>.*)/', $datauri, $m) === 1) {
14+
return array(
15+
'mimetype' => $m['mimetype'],
16+
'encoding' => $m['encoding'],
17+
'data' => base64_decode($m['data'])
18+
);
19+
}
20+
21+
return null;
22+
}
23+
24+
public function testTotpUriIsCorrect()
25+
{
26+
$qr = new TestQrProvider();
27+
28+
$tfa = new TwoFactorAuth('Test&Issuer', 6, 30, 'sha1', $qr);
29+
$data = $this->DecodeDataUri($tfa->getQRCodeImageAsDataUri('Test&Label', 'VMR466AB62ZBOKHE'));
30+
$this->assertEquals('test/test', $data['mimetype']);
31+
$this->assertEquals('base64', $data['encoding']);
32+
$this->assertEquals('otpauth://totp/Test%26Label?secret=VMR466AB62ZBOKHE&issuer=Test%26Issuer&period=30&algorithm=SHA1&digits=6@200', $data['data']);
33+
}
34+
35+
public function testGetQRCodeImageAsDataUriThrowsOnInvalidSize()
36+
{
37+
$qr = new TestQrProvider();
38+
39+
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', $qr);
40+
41+
$this->expectException(TwoFactorAuthException::class);
42+
43+
$tfa->getQRCodeImageAsDataUri('Test', 'VMR466AB62ZBOKHE', 0);
44+
}
45+
}

tests/Providers/Qr/TestQrProvider.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Tests\Providers\Qr;
4+
5+
use RobThree\Auth\Providers\Qr\IQRCodeProvider;
6+
7+
class TestQrProvider implements IQRCodeProvider
8+
{
9+
public function getQRCodeImage($qrtext, $size)
10+
{
11+
return $qrtext . '@' . $size;
12+
}
13+
14+
public function getMimeType()
15+
{
16+
return 'test/test';
17+
}
18+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Tests\Providers\Rng;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Tests\MightNotMakeAssertions;
7+
use RobThree\Auth\Providers\Rng\CSRNGProvider;
8+
9+
class CSRNGProviderTest extends TestCase
10+
{
11+
use NeedsRngLengths, MightNotMakeAssertions;
12+
13+
/**
14+
* @requires function random_bytes
15+
*/
16+
public function testCSRNGProvidersReturnExpectedNumberOfBytes()
17+
{
18+
if (function_exists('random_bytes')) {
19+
$rng = new CSRNGProvider();
20+
foreach ($this->rngTestLengths as $l) {
21+
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
22+
}
23+
$this->assertTrue($rng->isCryptographicallySecure());
24+
} else {
25+
$this->noAssertionsMade();
26+
}
27+
}
28+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Tests\Providers\Rng;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use RobThree\Auth\Providers\Rng\HashRNGProvider;
7+
8+
class HashRNGProviderTest extends TestCase
9+
{
10+
use NeedsRngLengths;
11+
12+
public function testHashRNGProvidersReturnExpectedNumberOfBytes()
13+
{
14+
$rng = new HashRNGProvider();
15+
foreach ($this->rngTestLengths as $l) {
16+
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
17+
}
18+
19+
$this->assertFalse($rng->isCryptographicallySecure());
20+
}
21+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Tests\Providers\Rng;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use RobThree\Auth\TwoFactorAuth;
7+
use RobThree\Auth\TwoFactorAuthException;
8+
9+
class IRNGProviderTest extends TestCase
10+
{
11+
public function testCreateSecretThrowsOnInsecureRNGProvider()
12+
{
13+
$rng = new TestRNGProvider();
14+
15+
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
16+
17+
$this->expectException(TwoFactorAuthException::class);
18+
$tfa->createSecret();
19+
}
20+
21+
public function testCreateSecretOverrideSecureDoesNotThrowOnInsecureRNG()
22+
{
23+
$rng = new TestRNGProvider();
24+
25+
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
26+
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret(80, false));
27+
}
28+
29+
public function testCreateSecretDoesNotThrowOnSecureRNGProvider()
30+
{
31+
$rng = new TestRNGProvider(true);
32+
33+
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
34+
$this->assertEquals('ABCDEFGHIJKLMNOP', $tfa->createSecret());
35+
}
36+
37+
public function testCreateSecretGeneratesDesiredAmountOfEntropy()
38+
{
39+
$rng = new TestRNGProvider(true);
40+
41+
$tfa = new TwoFactorAuth('Test', 6, 30, 'sha1', null, $rng);
42+
$this->assertEquals('A', $tfa->createSecret(5));
43+
$this->assertEquals('AB', $tfa->createSecret(6));
44+
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $tfa->createSecret(128));
45+
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(160));
46+
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', $tfa->createSecret(320));
47+
$this->assertEquals('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567ABCDEFGHIJKLMNOPQRSTUVWXYZ234567A', $tfa->createSecret(321));
48+
}
49+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Tests\Providers\Rng;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Tests\MightNotMakeAssertions;
7+
use RobThree\Auth\Providers\Rng\MCryptRNGProvider;
8+
9+
class MCryptRNGProviderTest extends TestCase
10+
{
11+
use NeedsRngLengths, MightNotMakeAssertions;
12+
13+
/**
14+
* @requires function mcrypt_create_iv
15+
*/
16+
public function testMCryptRNGProvidersReturnExpectedNumberOfBytes()
17+
{
18+
if (function_exists('mcrypt_create_iv')) {
19+
$rng = new MCryptRNGProvider();
20+
21+
foreach ($this->rngTestLengths as $l) {
22+
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
23+
}
24+
25+
$this->assertTrue($rng->isCryptographicallySecure());
26+
} else {
27+
$this->noAssertionsMade();
28+
}
29+
}
30+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Tests\Providers\Rng;
4+
5+
trait NeedsRngLengths
6+
{
7+
protected $rngTestLengths = array(1, 16, 32, 256);
8+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Tests\Providers\Rng;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use RobThree\Auth\Providers\Rng\OpenSSLRNGProvider;
7+
8+
class OpenSSLRNGProviderTest extends TestCase
9+
{
10+
use NeedsRngLengths;
11+
12+
public function testStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
13+
{
14+
$rng = new OpenSSLRNGProvider(true);
15+
foreach ($this->rngTestLengths as $l) {
16+
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
17+
}
18+
19+
$this->assertTrue($rng->isCryptographicallySecure());
20+
}
21+
22+
public function testNonStrongOpenSSLRNGProvidersReturnExpectedNumberOfBytes()
23+
{
24+
$rng = new OpenSSLRNGProvider(false);
25+
foreach ($this->rngTestLengths as $l) {
26+
$this->assertEquals($l, strlen($rng->getRandomBytes($l)));
27+
}
28+
29+
$this->assertFalse($rng->isCryptographicallySecure());
30+
}
31+
}

0 commit comments

Comments
 (0)