Completed
Push — master ( 3e7e88...cdbc34 )
by Tobias
04:55
created

GeoIP2Test::testRetrievingGeodata()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 39
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 39
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 28
nc 8
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Geocoder package.
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license    MIT License
11
 */
12
13
namespace Geocoder\Provider\GeoIP2\Tests;
14
15
use Geocoder\Collection;
16
use Geocoder\IntegrationTest\BaseTestCase;
17
use Geocoder\Location;
18
use Geocoder\Query\GeocodeQuery;
19
use Geocoder\Query\ReverseQuery;
20
use Geocoder\Provider\GeoIP2\GeoIP2;
21
use Geocoder\Provider\GeoIP2\GeoIP2Adapter;
22
use GeoIp2\Database\Reader;
23
24
/**
25
 * @author Jens Wiese <[email protected]>
26
 */
27
class GeoIP2Test extends BaseTestCase
28
{
29
    /**
30
     * @var GeoIP2
31
     */
32
    protected $provider;
33
34
    public function setUp()
35
    {
36
        $this->provider = new GeoIP2($this->getGeoIP2AdapterMock());
37
    }
38
39
    protected function getCacheDir()
40
    {
41
        return __DIR__.'/.cached_responses';
42
    }
43
44
    public function testGetName()
45
    {
46
        $this->assertEquals('geoip2', $this->provider->getName());
47
    }
48
49
    /**
50
     * @expectedException \Geocoder\Exception\UnsupportedOperation
51
     * @expectedExceptionMessage The GeoIP2 provider is not able to do reverse geocoding.
52
     */
53
    public function testQueryingReverseLeadsToException()
54
    {
55
        $this->provider->reverseQuery(ReverseQuery::fromCoordinates(50, 9));
56
    }
57
58
    public function testGeocodeWithLocalhostIPv4()
59
    {
60
        $results = $this->provider->geocodeQuery(GeocodeQuery::create('127.0.0.1'));
61
62
        $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
63
        $this->assertCount(1, $results);
64
65
        /** @var Location $result */
66
        $result = $results->first();
67
        $this->assertInstanceOf('\Geocoder\Model\Address', $result);
68
        $this->assertEquals('localhost', $result->getLocality());
69
        $this->assertEquals('localhost', $result->getCountry()->getName());
70
    }
71
72
    /**
73
     * @expectedException \Geocoder\Exception\UnsupportedOperation
74
     * @expectedExceptionMessage The GeoIP2 provider does not support street addresses, only IP addresses.
75
     */
76
    public function testOnlyIpAddressesCouldBeResolved()
77
    {
78
        $this->provider->geocodeQuery(GeocodeQuery::create('Street 123, Somewhere'));
79
    }
80
81
    /**
82
     * Provides data for geocode test.
83
     *
84
     * @return array
85
     */
86
    public static function provideDataForRetrievingGeodata()
87
    {
88
        $testdata = [
89
            'Response with data' => [
90
                '74.200.247.59',
91
                '{"city":{"geoname_id":2911298,"names":{"de":"Hamburg","en":"Hamburg","es":"Hamburgo","fr":"Hambourg","ja":"\u30cf\u30f3\u30d6\u30eb\u30af","pt-BR":"Hamburgo","ru":"\u0413\u0430\u043c\u0431\u0443\u0440\u0433","zh-CN":"\u6c49\u5821\u5e02"}},"continent":{"code":"EU","geoname_id":6255148,"names":{"de":"Europa","en":"Europe","es":"Europa","fr":"Europe","ja":"\u30e8\u30fc\u30ed\u30c3\u30d1","pt-BR":"Europa","ru":"\u0415\u0432\u0440\u043e\u043f\u0430","zh-CN":"\u6b27\u6d32"}},"country":{"geoname_id":2921044,"iso_code":"DE","names":{"de":"Deutschland","en":"Germany","es":"Alemania","fr":"Allemagne","ja":"\u30c9\u30a4\u30c4\u9023\u90a6\u5171\u548c\u56fd","pt-BR":"Alemanha","ru":"\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u044f","zh-CN":"\u5fb7\u56fd"}},"location":{"latitude":53.55,"longitude":10,"time_zone":"Europe\/Berlin"},"registered_country":{"geoname_id":2921044,"iso_code":"DE","names":{"de":"Deutschland","en":"Germany","es":"Alemania","fr":"Allemagne","ja":"\u30c9\u30a4\u30c4\u9023\u90a6\u5171\u548c\u56fd","pt-BR":"Alemanha","ru":"\u0413\u0435\u0440\u043c\u0430\u043d\u0438\u044f","zh-CN":"\u5fb7\u56fd"}},"subdivisions":[{"geoname_id":2911297,"iso_code":"HH","names":{"de":"Hamburg","en":"Hamburg","es":"Hamburgo","fr":"Hambourg"}}],"traits":{"ip_address":"74.200.247.59"},"postal":{"code":"EC4N"}}',
92
                [
93
                    'latitude' => 53.55,
94
                    'longitude' => 10,
95
                    'boundsDefined' => null,
96
                    'streetNumber' => null,
97
                    'streetName' => null,
98
                    'locality' => 'Hamburg',
99
                    'subLocality' => null,
100
                    'postalCode' => 'EC4N',
101
                    'adminLevels' => [1 => [
102
                        'name' => 'Hamburg',
103
                        'code' => 'HH',
104
                    ]],
105
                    'country' => 'Germany',
106
                    'countryCode' => 'DE',
107
                    'timezone' => 'Europe/Berlin',
108
                ],
109
            ],
110
            'Response with all possible data' => [
111
                '93.36.20.217',
112
                '{"country": {"iso_code": "IT","names": {"pt-BR": "Itália","es": "Italia","ru": "Италия","en": "Italy","zh-CN": "意大利","fr": "Italie","de": "Italien","ja": "イタリア共和国"},"geoname_id": 3175395},"location": {"longitude": 9.2667,"latitude": 45.5833,"time_zone": "Europe/Rome"},"subdivisions": [{"iso_code": "25","names": {"en": "Lombardy","fr": "Lombardie","de": "Lombardei","es": "Lombardía"},"geoname_id": 3174618},{"iso_code": "MB","names": {"en": "Monza Brianza"},"geoname_id": 6955700}],"postal": {"code": "20900"},"city": {"names": {"pt-BR": "Monza","es": "Monza","ru": "Монца","en": "Monza","zh-CN": "蒙扎","fr": "Monza","de": "Monza","ja": "モンツァ"},"geoname_id": 3172629},"continent": {"names": {"pt-BR": "Europa","es": "Europa","ru": "Европа","en": "Europe","zh-CN": "欧洲","fr": "Europe","de": "Europa","ja": "ヨーロッパ"},"geoname_id": 6255148,"code": "EU"},"registered_country": {"iso_code": "IT","names": {"pt-BR": "Itália","es": "Italia","ru": "Италия","en": "Italy","zh-CN": "意大利","fr": "Italie","de": "Italien","ja": "イタリア共和国"},"geoname_id": 3175395},"traits": {"domain": "fastwebnet.it","autonomous_system_number": 12874,"ip_address": "93.36.20.217","organization": "Fastweb","isp": "Fastweb","autonomous_system_organization": "Fastweb SpA"},"represented_country": {"names": {}}}',
113
                [
114
                    'latitude' => 45.5833,
115
                    'longitude' => 9.2667,
116
                    'boundsDefined' => null,
117
                    'streetNumber' => null,
118
                    'streetName' => null,
119
                    'locality' => 'Monza',
120
                    'subLocality' => null,
121
                    'postalCode' => '20900',
122
                    'adminLevels' => [
123
                        1 => [
124
                            'name' => 'Lombardy',
125
                            'code' => '25',
126
                        ],
127
                        2 => [
128
                            'name' => 'Monza Brianza',
129
                            'code' => 'MB',
130
                        ],
131
                    ],
132
                    'country' => 'Italy',
133
                    'countryCode' => 'IT',
134
                    'timezone' => 'Europe/Rome',
135
                ],
136
            ],
137
            'Response with all data null' => [
138
                '74.200.247.59',
139
                '{}',
140
                [
141
                    'latitude' => null,
142
                    'longitude' => null,
143
                    'boundsDefined' => null,
144
                    'streetNumber' => null,
145
                    'streetName' => null,
146
                    'locality' => null,
147
                    'subLocality' => null,
148
                    'postalCode' => null,
149
                    'adminLevels' => [],
150
                    'country' => null,
151
                    'countryCode' => null,
152
                    'timezone' => null,
153
                ],
154
            ],
155
        ];
156
157
        return $testdata;
158
    }
159
160
    /**
161
     * @dataProvider provideDataForRetrievingGeodata
162
     *
163
     * @param string $address
164
     * @param mixed  $adapterResponse
165
     * @param mixed  $expectedGeodata
166
     */
167
    public function testRetrievingGeodata($address, $adapterResponse, $expectedGeodata)
168
    {
169
        $adapter = $this->getGeoIP2AdapterMock($adapterResponse);
170
        $provider = new GeoIP2($adapter);
171
172
        $results = $provider->geocodeQuery(GeocodeQuery::create($address));
173
174
        $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results);
175
        $this->assertCount(1, $results);
176
177
        /** @var Location $result */
178
        $result = $results->first();
179
        $this->assertInstanceOf('\Geocoder\Model\Address', $result);
180
        if (isset($expectedGeodata['latitude'])) {
181
            $this->assertEquals($expectedGeodata['latitude'], $result->getCoordinates()->getLatitude());
182
            $this->assertEquals($expectedGeodata['longitude'], $result->getCoordinates()->getLongitude());
183
        } else {
184
            $this->assertNull($result->getCoordinates());
185
        }
186
187
        if ($expectedGeodata['boundsDefined']) {
188
            $this->assertNotNull($result->getBounds());
189
        } else {
190
            $this->assertNull($result->getBounds());
191
        }
192
193
        $this->assertEquals($expectedGeodata['streetNumber'], $result->getStreetNumber());
194
        $this->assertEquals($expectedGeodata['streetName'], $result->getStreetName());
195
        $this->assertEquals($expectedGeodata['locality'], $result->getLocality());
196
        $this->assertEquals($expectedGeodata['subLocality'], $result->getSubLocality());
197
        $this->assertEquals($expectedGeodata['postalCode'], $result->getPostalCode());
198
        $this->assertEquals($expectedGeodata['country'], $result->getCountry()->getName());
199
        $this->assertEquals($expectedGeodata['countryCode'], $result->getCountry()->getCode());
200
        $this->assertEquals($expectedGeodata['timezone'], $result->getTimezone());
201
        foreach ($expectedGeodata['adminLevels'] as $level => $data) {
202
            $this->assertEquals($data['name'], $result->getAdminLevels()->get($level)->getName());
203
            $this->assertEquals($data['code'], $result->getAdminLevels()->get($level)->getCode());
204
        }
205
    }
206
207
    public function testRetrievingGeodataNotExistingLocation()
208
    {
209
        $adapter = $this->getGeoIP2AdapterMock('');
210
        $provider = new GeoIP2($adapter);
211
212
        $result = $provider->geocodeQuery(GeocodeQuery::create('74.200.247.59'));
213
        $this->assertInstanceOf(Collection::class, $result);
214
        $this->assertEquals(0, $result->count());
215
    }
216
217
    public function testGeoIp2Encoding()
218
    {
219
        $reader = new Reader(__DIR__.'/fixtures/GeoLite2-City.mmdb');
220
        $adapter = new GeoIP2Adapter($reader);
221
        $provider = new GeoIP2($adapter);
222
        $locality = $provider->geocodeQuery(GeocodeQuery::create('79.114.34.148'))->first()->getLocality();
223
        $this->assertEquals('Timișoara', $locality);
224
    }
225
226
    /**
227
     * @param mixed $returnValue
228
     *
229
     * @return \PHPUnit_Framework_MockObject_MockObject|GeoIP2Adapter
230
     */
231
    private function getGeoIP2AdapterMock($returnValue = '')
232
    {
233
        $mock = $this->getMockBuilder(GeoIP2Adapter::class)
234
            ->disableOriginalConstructor()
235
            ->setMethods(['getContent'])
236
            ->getMock();
237
238
        if ($returnValue instanceof \Exception) {
239
            $returnValue = $this->throwException($returnValue);
240
        } else {
241
            $returnValue = $this->returnValue($returnValue);
242
        }
243
244
        $mock->expects($this->any())->method('getContent')->will($returnValue);
245
246
        return $mock;
247
    }
248
}
249