Completed
Pull Request — master (#402)
by Alejandro
05:51
created

GeolocationDbUpdaterTest::provideBigDays()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
4
namespace ShlinkioTest\Shlink\CLI\Util;
5
6
use Cake\Chronos\Chronos;
7
use GeoIp2\Database\Reader;
8
use InvalidArgumentException;
9
use MaxMind\Db\Reader\Metadata;
10
use PHPUnit\Framework\TestCase;
11
use Prophecy\Prophecy\ObjectProphecy;
12
use Shlinkio\Shlink\CLI\Exception\GeolocationDbUpdateFailedException;
13
use Shlinkio\Shlink\CLI\Util\GeolocationDbUpdater;
14
use Shlinkio\Shlink\Common\Exception\RuntimeException;
15
use Shlinkio\Shlink\Common\IpGeolocation\GeoLite2\DbUpdaterInterface;
16
use Throwable;
17
18
use function Functional\map;
19
use function range;
20
21
class GeolocationDbUpdaterTest extends TestCase
22
{
23
    /** @var GeolocationDbUpdater */
24
    private $geolocationDbUpdater;
25
    /** @var ObjectProphecy */
26
    private $dbUpdater;
27
    /** @var ObjectProphecy */
28
    private $geoLiteDbReader;
29
30
    public function setUp(): void
31
    {
32
        $this->dbUpdater = $this->prophesize(DbUpdaterInterface::class);
33
        $this->geoLiteDbReader = $this->prophesize(Reader::class);
34
35
        $this->geolocationDbUpdater = new GeolocationDbUpdater(
36
            $this->dbUpdater->reveal(),
37
            $this->geoLiteDbReader->reveal()
38
        );
39
    }
40
41
    /** @test */
42
    public function exceptionIsThrownWhenOlderDbDoesNotExistAndDownloadFails(): void
43
    {
44
        $mustBeUpdated = function () {
45
            $this->assertTrue(true);
46
        };
47
        $getMeta = $this->geoLiteDbReader->metadata()->willThrow(InvalidArgumentException::class);
48
        $prev = new RuntimeException('');
49
        $download = $this->dbUpdater->downloadFreshCopy(null)->willThrow($prev);
50
51
        try {
52
            $this->geolocationDbUpdater->checkDbUpdate($mustBeUpdated);
53
            $this->assertTrue(false); // If this is reached, the test will fail
54
        } catch (Throwable $e) {
55
            /** @var GeolocationDbUpdateFailedException $e */
56
            $this->assertInstanceOf(GeolocationDbUpdateFailedException::class, $e);
57
            $this->assertSame($prev, $e->getPrevious());
58
            $this->assertFalse($e->olderDbExists());
59
        }
60
61
        $getMeta->shouldHaveBeenCalledOnce();
62
        $download->shouldHaveBeenCalledOnce();
63
    }
64
65
    /**
66
     * @test
67
     * @dataProvider provideBigDays
68
     */
69
    public function exceptionIsThrownWhenOlderDbIsTooOldAndDownloadFails(int $days): void
70
    {
71
        $getMeta = $this->geoLiteDbReader->metadata()->willReturn(new Metadata([
72
            'binary_format_major_version' => '',
73
            'binary_format_minor_version' => '',
74
            'build_epoch' => Chronos::now()->subDays($days)->getTimestamp(),
75
            'database_type' => '',
76
            'languages' => '',
77
            'description' => '',
78
            'ip_version' => '',
79
            'node_count' => 1,
80
            'record_size' => 4,
81
        ]));
82
        $prev = new RuntimeException('');
83
        $download = $this->dbUpdater->downloadFreshCopy(null)->willThrow($prev);
84
85
        try {
86
            $this->geolocationDbUpdater->checkDbUpdate();
87
            $this->assertTrue(false); // If this is reached, the test will fail
88
        } catch (Throwable $e) {
89
            /** @var GeolocationDbUpdateFailedException $e */
90
            $this->assertInstanceOf(GeolocationDbUpdateFailedException::class, $e);
91
            $this->assertSame($prev, $e->getPrevious());
92
            $this->assertTrue($e->olderDbExists());
93
        }
94
95
        $getMeta->shouldHaveBeenCalledOnce();
96
        $download->shouldHaveBeenCalledOnce();
97
    }
98
99
    public function provideBigDays(): iterable
100
    {
101
        yield [36];
102
        yield [50];
103
        yield [75];
104
        yield [100];
105
    }
106
107
    /**
108
     * @test
109
     * @dataProvider provideSmallDays
110
     */
111
    public function databaseIsNotUpdatedIfItIsYoungerThanOneWeek(int $days): void
112
    {
113
        $getMeta = $this->geoLiteDbReader->metadata()->willReturn(new Metadata([
114
            'binary_format_major_version' => '',
115
            'binary_format_minor_version' => '',
116
            'build_epoch' => Chronos::now()->subDays($days)->getTimestamp(),
117
            'database_type' => '',
118
            'languages' => '',
119
            'description' => '',
120
            'ip_version' => '',
121
            'node_count' => 1,
122
            'record_size' => 4,
123
        ]));
124
        $download = $this->dbUpdater->downloadFreshCopy(null)->will(function () {
125
        });
126
127
        $this->geolocationDbUpdater->checkDbUpdate();
128
129
        $getMeta->shouldHaveBeenCalledOnce();
130
        $download->shouldNotHaveBeenCalled();
131
    }
132
133
    public function provideSmallDays(): iterable
134
    {
135
        return map(range(0, 34), function (int $days) {
136
            return [$days];
137
        });
138
    }
139
}
140