mirror of
https://github.com/shlinkio/shlink.git
synced 2026-03-10 09:13:11 +08:00
Updated logic to generate random short codes, increasing entropy
This commit is contained in:
@@ -19,20 +19,21 @@ use Shlinkio\Shlink\Core\Service\ShortUrl\DeleteShortUrlService;
|
||||
|
||||
use function Functional\map;
|
||||
use function range;
|
||||
use function sprintf;
|
||||
|
||||
class DeleteShortUrlServiceTest extends TestCase
|
||||
{
|
||||
/** @var DeleteShortUrlService */
|
||||
private $service;
|
||||
/** @var ObjectProphecy */
|
||||
private $em;
|
||||
/** @var string */
|
||||
private $shortCode;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$shortUrl = (new ShortUrl(''))->setShortCode('abc123')
|
||||
->setVisits(new ArrayCollection(map(range(0, 10), function () {
|
||||
return new Visit(new ShortUrl(''), Visitor::emptyInstance());
|
||||
})));
|
||||
$shortUrl = (new ShortUrl(''))->setVisits(new ArrayCollection(map(range(0, 10), function () {
|
||||
return new Visit(new ShortUrl(''), Visitor::emptyInstance());
|
||||
})));
|
||||
$this->shortCode = $shortUrl->getShortCode();
|
||||
|
||||
$this->em = $this->prophesize(EntityManagerInterface::class);
|
||||
|
||||
@@ -42,55 +43,56 @@ class DeleteShortUrlServiceTest extends TestCase
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function deleteByShortCodeThrowsExceptionWhenThresholdIsReached()
|
||||
public function deleteByShortCodeThrowsExceptionWhenThresholdIsReached(): void
|
||||
{
|
||||
$service = $this->createService();
|
||||
|
||||
$this->expectException(DeleteShortUrlException::class);
|
||||
$this->expectExceptionMessage(
|
||||
'Impossible to delete short URL with short code "abc123" since it has more than "5" visits.'
|
||||
);
|
||||
$this->expectExceptionMessage(sprintf(
|
||||
'Impossible to delete short URL with short code "%s" since it has more than "5" visits.',
|
||||
$this->shortCode
|
||||
));
|
||||
|
||||
$service->deleteByShortCode('abc123');
|
||||
$service->deleteByShortCode($this->shortCode);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButExplicitlyIgnored()
|
||||
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButExplicitlyIgnored(): void
|
||||
{
|
||||
$service = $this->createService();
|
||||
|
||||
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
|
||||
$flush = $this->em->flush()->willReturn(null);
|
||||
|
||||
$service->deleteByShortCode('abc123', true);
|
||||
$service->deleteByShortCode($this->shortCode, true);
|
||||
|
||||
$remove->shouldHaveBeenCalledOnce();
|
||||
$flush->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButCheckIsDisabled()
|
||||
public function deleteByShortCodeDeletesUrlWhenThresholdIsReachedButCheckIsDisabled(): void
|
||||
{
|
||||
$service = $this->createService(false);
|
||||
|
||||
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
|
||||
$flush = $this->em->flush()->willReturn(null);
|
||||
|
||||
$service->deleteByShortCode('abc123');
|
||||
$service->deleteByShortCode($this->shortCode);
|
||||
|
||||
$remove->shouldHaveBeenCalledOnce();
|
||||
$flush->shouldHaveBeenCalledOnce();
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function deleteByShortCodeDeletesUrlWhenThresholdIsNotReached()
|
||||
public function deleteByShortCodeDeletesUrlWhenThresholdIsNotReached(): void
|
||||
{
|
||||
$service = $this->createService(true, 100);
|
||||
|
||||
$remove = $this->em->remove(Argument::type(ShortUrl::class))->willReturn(null);
|
||||
$flush = $this->em->flush()->willReturn(null);
|
||||
|
||||
$service->deleteByShortCode('abc123');
|
||||
$service->deleteByShortCode($this->shortCode);
|
||||
|
||||
$remove->shouldHaveBeenCalledOnce();
|
||||
$flush->shouldHaveBeenCalledOnce();
|
||||
|
||||
@@ -17,7 +17,6 @@ use Prophecy\Argument;
|
||||
use Prophecy\Prophecy\ObjectProphecy;
|
||||
use Shlinkio\Shlink\Core\Entity\ShortUrl;
|
||||
use Shlinkio\Shlink\Core\Entity\Tag;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidShortCodeException;
|
||||
use Shlinkio\Shlink\Core\Exception\InvalidUrlException;
|
||||
use Shlinkio\Shlink\Core\Exception\NonUniqueSlugException;
|
||||
use Shlinkio\Shlink\Core\Exception\RuntimeException;
|
||||
@@ -74,13 +73,13 @@ class UrlShortenerTest extends TestCase
|
||||
/** @test */
|
||||
public function urlIsProperlyShortened(): void
|
||||
{
|
||||
// 10 -> 0Q1Y
|
||||
$shortUrl = $this->urlShortener->urlToShortCode(
|
||||
new Uri('http://foobar.com/12345/hello?foo=bar'),
|
||||
[],
|
||||
ShortUrlMeta::createEmpty()
|
||||
);
|
||||
$this->assertEquals('0Q1Y', $shortUrl->getShortCode());
|
||||
|
||||
$this->assertEquals('http://foobar.com/12345/hello?foo=bar', $shortUrl->getLongUrl());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
@@ -243,9 +242,8 @@ class UrlShortenerTest extends TestCase
|
||||
/** @test */
|
||||
public function shortCodeIsProperlyParsed(): void
|
||||
{
|
||||
$shortCode = '12C1c';
|
||||
$shortUrl = new ShortUrl('expected_url');
|
||||
$shortUrl->setShortCode($shortCode);
|
||||
$shortCode = $shortUrl->getShortCode();
|
||||
|
||||
$repo = $this->prophesize(ShortUrlRepositoryInterface::class);
|
||||
$repo->findOneByShortCode($shortCode, null)->willReturn($shortUrl);
|
||||
@@ -254,11 +252,4 @@ class UrlShortenerTest extends TestCase
|
||||
$url = $this->urlShortener->shortCodeToUrl($shortCode);
|
||||
$this->assertSame($shortUrl, $url);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function invalidCharSetThrowsException(): void
|
||||
{
|
||||
$this->expectException(InvalidShortCodeException::class);
|
||||
$this->urlShortener->shortCodeToUrl('&/(');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user