Skip to content

Commit 6995cd1

Browse files
committed
:octocat: test overhaul
1 parent 227c45d commit 6995cd1

File tree

10 files changed

+239
-195
lines changed

10 files changed

+239
-195
lines changed

tests/AuthenticatorOptionsTest.php

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use chillerlan\Authenticator\AuthenticatorOptions;
1515
use chillerlan\Authenticator\Authenticators\AuthenticatorInterface;
1616
use InvalidArgumentException;
17+
use PHPUnit\Framework\Attributes\Test;
1718
use PHPUnit\Framework\TestCase;
1819

1920
class AuthenticatorOptionsTest extends TestCase{
@@ -24,74 +25,100 @@ protected function setUp():void{
2425
$this->options = new AuthenticatorOptions;
2526
}
2627

27-
public function testSetDigits():void{
28+
#[Test]
29+
public function setDigits():void{
2830
foreach([6, 8] as $digits){
2931
$this->options->digits = $digits;
3032
$this::assertSame($digits, $this->options->digits);
3133
}
3234
}
3335

34-
public function testSetDigitsException():void{
36+
#[Test]
37+
public function setDigitsException():void{
3538
$this->expectException(InvalidArgumentException::class);
3639
$this->expectExceptionMessage('Invalid code length');
3740

3841
$this->options->digits = 7;
3942
}
4043

41-
public function testSetPeriod():void{
44+
#[Test]
45+
public function setPeriod():void{
4246
for($period = 15; $period <= 60; $period++){
4347
$this->options->period = $period;
4448
$this::assertSame($period, $this->options->period);
4549
}
4650
}
4751

48-
public function testSetPeriodException():void{
52+
#[Test]
53+
public function setPeriodException():void{
4954
$this->expectException(InvalidArgumentException::class);
5055
$this->expectExceptionMessage('Invalid period');
5156

5257
$this->options->period = 666;
5358
}
5459

55-
public function testSetAlgorithm():void{
60+
#[Test]
61+
public function setAlgorithm():void{
5662
foreach(AuthenticatorInterface::HASH_ALGOS as $algo){
5763
$this->options->algorithm = $algo;
5864
$this::assertSame($algo, $this->options->algorithm);
5965
}
6066
}
6167

62-
public function testSetAlgorithmException():void{
68+
#[Test]
69+
public function setAlgorithmException():void{
6370
$this->expectException(InvalidArgumentException::class);
6471
$this->expectExceptionMessage('Invalid algorithm');
6572

6673
$this->options->algorithm = 'florps';
6774
}
6875

69-
public function testSetMode():void{
76+
#[Test]
77+
public function setMode():void{
7078
foreach(AuthenticatorInterface::MODES as $mode => $class){
7179
$this->options->mode = $mode;
7280
$this::assertSame($mode, $this->options->mode);
7381
}
7482
}
7583

76-
public function testSetModeException():void{
84+
#[Test]
85+
public function setModeException():void{
7786
$this->expectException(InvalidArgumentException::class);
7887
$this->expectExceptionMessage('Invalid mode');
7988

8089
$this->options->mode = 'florps';
8190
}
8291

83-
public function testSetAdjacent():void{
92+
#[Test]
93+
public function setAdjacent():void{
8494
for($adjacent = 0; $adjacent <= 10; $adjacent++){
8595
$this->options->adjacent = $adjacent;
8696
$this::assertSame($adjacent, $this->options->adjacent);
8797
}
8898
}
8999

90-
public function testSetAdjacentException():void{
100+
#[Test]
101+
public function setAdjacentException():void{
91102
$this->expectException(InvalidArgumentException::class);
92103
$this->expectExceptionMessage('Invalid number of adjacent codes');
93104

94105
$this->options->adjacent = -1;
95106
}
96107

108+
#[Test]
109+
public function setSecretLength():void{
110+
for($secretLength = 16; $secretLength <= 1024; $secretLength += 16){
111+
$this->options->secret_length = $secretLength;
112+
$this::assertSame($secretLength, $this->options->secret_length);
113+
}
114+
}
115+
116+
#[Test]
117+
public function setSecretLengthException():void{
118+
$this->expectException(InvalidArgumentException::class);
119+
$this->expectExceptionMessage('Invalid secret length: 69420');
120+
121+
$this->options->secret_length = 69420;
122+
}
123+
97124
}

tests/AuthenticatorTest.php

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,9 @@
1212
namespace chillerlan\AuthenticatorTest;
1313

1414
use chillerlan\Authenticator\{Authenticator, AuthenticatorOptions};
15-
use chillerlan\Authenticator\Authenticators\AuthenticatorInterface;
16-
use InvalidArgumentException;
15+
use PHPUnit\Framework\Attributes\Test;
1716
use PHPUnit\Framework\TestCase;
18-
use function sprintf;
17+
use InvalidArgumentException;
1918

2019
class AuthenticatorTest extends TestCase{
2120

@@ -31,60 +30,15 @@ protected function setUp():void{
3130
$this->authenticator = new Authenticator($this->options);
3231
}
3332

34-
public function testSetSecretViaConstruct():void{
33+
#[Test]
34+
public function setSecretViaConstruct():void{
3535
$this->authenticator = new Authenticator(secret: self::secret);
3636

3737
$this::assertSame(self::secret, $this->authenticator->getSecret());
3838
}
3939

40-
public function testGetUri():void{
41-
$this->authenticator->setSecret(self::secret);
42-
43-
$label = rawurlencode(self::label);
44-
$issuer = rawurlencode(self::issuer);
45-
46-
$this::assertSame(
47-
sprintf('otpauth://totp/%s?secret=%s&issuer=%s&digits=6&algorithm=SHA1&period=30', $label, self::secret, $issuer),
48-
$this->authenticator->getUri(self::label, self::issuer),
49-
);
50-
51-
$this->options->digits = 8;
52-
$this::assertSame(
53-
sprintf('otpauth://totp/%s?secret=%s&issuer=%s&digits=8&algorithm=SHA1&period=30', $label, self::secret, $issuer),
54-
$this->authenticator->getUri(self::label, self::issuer),
55-
);
56-
57-
$this->options->period = 45;
58-
$this::assertSame(
59-
sprintf('otpauth://totp/%s?secret=%s&issuer=%s&digits=8&algorithm=SHA1&period=45', $label, self::secret, $issuer),
60-
$this->authenticator->getUri(self::label, self::issuer),
61-
);
62-
63-
$this->options->mode = AuthenticatorInterface::HOTP;
64-
// changing the mode resets the AuthenticatorInterface instance
65-
$this->authenticator
66-
->setOptions($this->options)
67-
->setSecret(self::secret);
68-
69-
$this::assertSame(
70-
sprintf('otpauth://hotp/%s?secret=%s&issuer=%s&counter=42&digits=8&algorithm=SHA1', $label, self::secret, $issuer),
71-
$this->authenticator->getUri(self::label, self::issuer, 42),
72-
);
73-
74-
$this->options->algorithm = AuthenticatorInterface::ALGO_SHA512;
75-
$this::assertSame(
76-
sprintf('otpauth://hotp/%s?secret=%s&issuer=%s&counter=0&digits=8&algorithm=SHA512', $label, self::secret, $issuer),
77-
$this->authenticator->getUri(self::label, self::issuer, 0),
78-
);
79-
80-
// test omit settings
81-
$this::assertSame(
82-
sprintf('otpauth://%s/%s?secret=%s&issuer=%s&counter=42', 'hotp', $label, self::secret, $issuer),
83-
$this->authenticator->getUri(self::label, self::issuer, 42, true),
84-
);
85-
}
86-
87-
public function testGetUriEmptyLabelException():void{
40+
#[Test]
41+
public function getUriEmptyLabelException():void{
8842
$this->expectException(InvalidArgumentException::class);
8943
$this->expectExceptionMessage('$label and $issuer cannot be empty');
9044

tests/Authenticators/AuthenticatorInterfaceTestAbstract.php

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
use chillerlan\Authenticator\AuthenticatorOptions;
1515
use chillerlan\Authenticator\Authenticators\AuthenticatorInterface;
1616
use chillerlan\Authenticator\Common\Base32;
17-
use InvalidArgumentException;
1817
use PHPUnit\Framework\TestCase;
19-
use RuntimeException;
20-
use function strlen;
18+
use PHPUnit\Framework\Attributes\{DataProvider, Test};
19+
use InvalidArgumentException, RuntimeException;
20+
use function rawurlencode, sprintf, strlen;
2121

2222
abstract class AuthenticatorInterfaceTestAbstract extends TestCase{
2323

@@ -27,14 +27,18 @@ abstract class AuthenticatorInterfaceTestAbstract extends TestCase{
2727
protected const rawsecret = '12345678901234567890';
2828
protected const secret = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ';
2929

30+
protected const label = 'some test-label';
31+
protected const issuer = 'chillerlan.net';
32+
3033
abstract protected function getInstance(AuthenticatorOptions $options):AuthenticatorInterface;
3134

3235
protected function setUp():void{
3336
$this->options = new AuthenticatorOptions;
3437
$this->authenticatorInterface = $this->getInstance($this->options);
3538
}
3639

37-
public function testSetGetSecret():void{
40+
#[Test]
41+
public function setGetSecret():void{
3842
$this->authenticatorInterface->setSecret($this::secret);
3943

4044
$secret = $this->authenticatorInterface->getSecret();
@@ -43,34 +47,39 @@ public function testSetGetSecret():void{
4347
$this::assertSame($this::rawsecret, Base32::decode($secret));
4448
}
4549

46-
public function testSetEmptySecretException():void{
50+
#[Test]
51+
public function setEmptySecretException():void{
4752
$this->expectException(InvalidArgumentException::class);
4853
$this->expectExceptionMessage('The given secret string is empty');
4954

5055
$this->authenticatorInterface->setSecret('');
5156
}
5257

53-
public function testSetInvalidSecretException():void{
58+
#[Test]
59+
public function setInvalidSecretException():void{
5460
$this->expectException(InvalidArgumentException::class);
5561

5662
$this->authenticatorInterface->setSecret('This_is_an_invalid_secret_phrase!');
5763
}
5864

59-
public function testGetSecretException():void{
65+
#[Test]
66+
public function getSecretException():void{
6067
$this->expectException(RuntimeException::class);
6168
$this->expectExceptionMessage('No secret set');
6269

6370
$this->authenticatorInterface->getSecret();
6471
}
6572

66-
public function testCreateSecretDefaultLength():void{
73+
#[Test]
74+
public function createSecretDefaultLength():void{
6775
$this::assertSame(
6876
$this->options->secret_length,
6977
strlen(Base32::decode($this->authenticatorInterface->createSecret())),
7078
);
7179
}
7280

73-
public function testCreateSecretWithLength():void{
81+
#[Test]
82+
public function createSecretWithLength():void{
7483

7584
for($secretLength = 16; $secretLength <= 512; $secretLength += 8){
7685
$secret = Base32::decode($this->authenticatorInterface->createSecret($secretLength));
@@ -80,28 +89,32 @@ public function testCreateSecretWithLength():void{
8089

8190
}
8291

83-
public function testCreateSecretCheckCharacterSet():void{
92+
#[Test]
93+
public function createSecretCheckCharacterSet():void{
8494
$secret = $this->authenticatorInterface->createSecret(32);
8595

8696
$this::assertMatchesRegularExpression('/^['.Base32::CHARSET.']+$/', $secret);
8797
}
8898

89-
public function testCreateSecretException():void{
99+
#[Test]
100+
public function createSecretException():void{
90101
$this->expectException(InvalidArgumentException::class);
91102
$this->expectExceptionMessage('Invalid secret length');
92103

93104
$this->authenticatorInterface->createSecret(10);
94105
}
95106

96-
public function testGetHMACWithoutSecretException():void{
107+
#[Test]
108+
public function getHMACWithoutSecretException():void{
97109
$this->expectException(RuntimeException::class);
98110
$this->expectExceptionMessage('No secret given');
99111

100112
$this->authenticatorInterface->getHMAC(69);
101113
}
102114

103115
// https://github.com/PHPGangsta/GoogleAuthenticator/pull/25
104-
public function testVerifyCodeWithLeadingZero():void{
116+
#[Test]
117+
public function verifyCodeWithLeadingZero():void{
105118
$this->authenticatorInterface->setSecret($this::secret);
106119

107120
$code = $this->authenticatorInterface->code();
@@ -111,7 +124,8 @@ public function testVerifyCodeWithLeadingZero():void{
111124
}
112125

113126
// coverage
114-
public function testGetServertime():void{
127+
#[Test]
128+
public function getServertime():void{
115129
$this->options->useLocalTime = false;
116130

117131
$servertime = $this->authenticatorInterface->getServerTime();
@@ -123,4 +137,32 @@ public function testGetServertime():void{
123137
$this::assertMatchesRegularExpression('/^\d+$/', (string)$servertime);
124138
}
125139

140+
abstract public static function uriSettingsProvider():array;
141+
142+
/**
143+
* @param array<string, mixed> $options
144+
*/
145+
#[Test]
146+
#[DataProvider('uriSettingsProvider')]
147+
public function getUri(array $options, string $expected):void{
148+
149+
$this->authenticatorInterface
150+
->setOptions($options)
151+
->setSecret(self::secret)
152+
;
153+
154+
$this::assertSame(
155+
sprintf(
156+
'otpauth://%s/%s?secret=%s&issuer=%s%s',
157+
$this->authenticatorInterface::MODE,
158+
rawurlencode(self::label),
159+
self::secret,
160+
rawurlencode(self::issuer),
161+
$expected,
162+
),
163+
$this->authenticatorInterface->getUri(self::label, self::issuer, 42),
164+
);
165+
166+
}
167+
126168
}

tests/Authenticators/HOTPTest.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313

1414
use chillerlan\Authenticator\AuthenticatorOptions;
1515
use chillerlan\Authenticator\Authenticators\{AuthenticatorInterface, HOTP};
16+
use PHPUnit\Framework\Attributes\{DataProvider, Test};
1617
use Generator;
17-
use PHPUnit\Framework\Attributes\DataProvider;
18-
use function bin2hex;
19-
use function sprintf;
18+
use function bin2hex, sprintf;
2019

2120
class HOTPTest extends AuthenticatorInterfaceTestAbstract{
2221

@@ -49,8 +48,9 @@ public static function hotpVectors():Generator{
4948
/**
5049
* @link https://github.com/winauth/winauth/issues/449#issuecomment-353670105
5150
*/
51+
#[Test]
5252
#[DataProvider('hotpVectors')]
53-
public function testHOTP(int $counter, string $hmac, int $code, string $hotp):void{
53+
public function HOTP(int $counter, string $hmac, int $code, string $hotp):void{
5454
$this->authenticatorInterface->setSecret($this::secret);
5555

5656
$hmac_intermediate = $this->authenticatorInterface->getHMAC($counter);
@@ -62,4 +62,13 @@ public function testHOTP(int $counter, string $hmac, int $code, string $hotp):vo
6262
$this::assertTrue($this->authenticatorInterface->verify($hotp, $counter));
6363
}
6464

65+
public static function uriSettingsProvider():array{
66+
return [
67+
'default' => [[], '&counter=42&digits=6&algorithm=SHA1'],
68+
'digits' => [['digits' => 8], '&counter=42&digits=8&algorithm=SHA1'],
69+
'algo' => [['algorithm' => AuthenticatorInterface::ALGO_SHA512], '&counter=42&digits=6&algorithm=SHA512'],
70+
'omit' => [['omitUriSettings' => true], '&counter=42'],
71+
];
72+
}
73+
6574
}

0 commit comments

Comments
 (0)