1: <?php
2:
3: namespace GeoIp2\Test\WebService;
4:
5: use GeoIp2\WebService\Client;
6: use MaxMind\WebService\Client as WsClient;
7:
8: class ClientTest extends \PHPUnit_Framework_TestCase
9: {
10:
11: private $country
12: = array(
13: 'continent' => array(
14: 'code' => 'NA',
15: 'geoname_id' => 42,
16: 'names' => array('en' => 'North America'),
17: ),
18: 'country' => array(
19: 'geoname_id' => 1,
20: 'iso_code' => 'US',
21: 'names' => array('en' => 'United States of America'),
22: ),
23: 'maxmind' => array('queries_remaining' => 11),
24: 'traits' => array(
25: 'ip_address' => '1.2.3.4',
26: ),
27: );
28:
29:
30: private function getResponse($ipAddress)
31: {
32: $responses = array(
33: '1.2.3.4' => $this->response(
34: 'country',
35: 200,
36: $this->country
37: ),
38: 'me' => $this->response(
39: 'country',
40: 200,
41: $this->country
42: ),
43: '1.2.3.5' => $this->response('country', 200),
44: '2.2.3.5' => $this->response('country', 200, 'bad body'),
45: '1.2.3.6' => $this->response(
46: 'error',
47: 400,
48: array(
49: 'code' => 'IP_ADDRESS_INVALID',
50: 'error' => 'The value "1.2.3" is not a valid ip address'
51: )
52: ),
53: '1.2.3.7' => $this->response(
54: 'error',
55: 400
56: ),
57: '1.2.3.8' => $this->response(
58: 'error',
59: 400,
60: array('weird' => 42)
61: ),
62: '1.2.3.9' => $this->response(
63: 'error',
64: 400,
65: null,
66: 'bad body'
67: ),
68: '1.2.3.10' => $this->response(
69: null,
70: 500
71: ),
72: '1.2.3.11' => $this->response(
73: null,
74: 300
75: ),
76: '1.2.3.12' => $this->response(
77: 'error',
78: 406,
79: 'Cannot satisfy your Accept-Charset requirements',
80: null,
81: 'text/plain'
82: ),
83: '1.2.3.13' => $this->response(
84: 'error',
85: 404,
86: array(
87: 'code' => 'IP_ADDRESS_NOT_FOUND',
88: 'error' => 'The address "1.2.3.13" is not in our database.'
89: )
90: ),
91: '1.2.3.14' => $this->response(
92: 'error',
93: 400,
94: array(
95: 'code' => 'IP_ADDRESS_RESERVED',
96: 'error' => 'The address "1.2.3.14" is a private address.'
97: )
98: ),
99: '1.2.3.15' => $this->response(
100: 'error',
101: 401,
102: array(
103: 'code' => 'AUTHORIZATION_INVALID',
104: 'error' => 'A user ID and license key are required to use this service'
105: )
106: ),
107: '1.2.3.16' => $this->response(
108: 'error',
109: 401,
110: array(
111: 'code' => 'LICENSE_KEY_REQUIRED',
112: 'error' => 'A license key is required to use this service'
113: )
114: ),
115: '1.2.3.17' => $this->response(
116: 'error',
117: 401,
118: array(
119: 'code' => 'USER_ID_REQUIRED',
120: 'error' => 'A user ID is required to use this service'
121: )
122: ),
123: '1.2.3.18' => $this->response(
124: 'error',
125: 402,
126: array(
127: 'code' => 'OUT_OF_QUERIES',
128: 'error' => 'The license key you have provided is out of queries.'
129: )
130: ),
131: );
132: return $responses[$ipAddress];
133: }
134:
135: public function testCountry()
136: {
137: $country = $this->makeRequest('Country', '1.2.3.4');
138:
139: $this->assertInstanceOf('GeoIp2\Model\Country', $country);
140:
141: $this->assertEquals(
142: 42,
143: $country->continent->geonameId,
144: 'continent geoname_id is 42'
145: );
146:
147: $this->assertEquals(
148: 'NA',
149: $country->continent->code,
150: 'continent code is NA'
151: );
152:
153: $this->assertEquals(
154: array('en' => 'North America'),
155: $country->continent->names,
156: 'continent names'
157: );
158:
159: $this->assertEquals(
160: 'North America',
161: $country->continent->name,
162: 'continent name is North America'
163: );
164:
165: $this->assertEquals(
166: 1,
167: $country->country->geonameId,
168: 'country geoname_id is 1'
169: );
170:
171: $this->assertEquals(
172: 'US',
173: $country->country->isoCode,
174: 'country iso_code is US'
175: );
176:
177: $this->assertEquals(
178: array('en' => 'United States of America'),
179: $country->country->names,
180: 'country names'
181: );
182:
183: $this->assertEquals(
184: 'United States of America',
185: $country->country->name,
186: 'country name is United States of America'
187: );
188:
189: $this->assertEquals(
190: 11,
191: $country->maxmind->queriesRemaining,
192: 'queriesRemaining is correct'
193: );
194:
195: }
196:
197:
198: public function testInsights()
199: {
200: $record = $this->makeRequest('Insights', '1.2.3.4');
201:
202: $this->assertInstanceOf('GeoIp2\Model\Insights', $record);
203:
204: $this->assertEquals(
205: 42,
206: $record->continent->geonameId,
207: 'continent geoname_id is 42'
208: );
209: }
210:
211: public function testCity()
212: {
213: $city = $this->makeRequest('City', '1.2.3.4');
214:
215: $this->assertInstanceOf('GeoIp2\Model\City', $city);
216: }
217:
218: public function testMe()
219: {
220: $city = $this->makeRequest('City', 'me');
221:
222: $this->assertInstanceOf(
223: 'GeoIp2\Model\City',
224: $city,
225: 'can set ip parameter to me'
226: );
227: }
228:
229: 230: 231: 232:
233: public function testNoBodyException()
234: {
235: $this->makeRequest('Country', '1.2.3.5');
236: }
237:
238: 239: 240: 241:
242: public function testBadBodyException()
243: {
244: $this->makeRequest('Country', '2.2.3.5');
245: }
246:
247:
248: 249: 250: 251: 252:
253: public function testInvalidIPException()
254: {
255: $this->makeRequest('Country', '1.2.3.6');
256: }
257:
258: 259: 260: 261: 262:
263: public function testNoErrorBodyIPException()
264: {
265: $this->makeRequest('Country', '1.2.3.7');
266: }
267:
268: 269: 270: 271:
272: public function testWeirdErrorBodyIPException()
273: {
274: $this->makeRequest('Country', '1.2.3.8');
275:
276: }
277:
278: 279: 280: 281: 282:
283: public function testInvalidErrorBodyIPException()
284: {
285: $this->makeRequest('Country', '1.2.3.9');
286:
287: }
288:
289: 290: 291: 292: 293:
294: public function test500PException()
295: {
296: $this->makeRequest('Country', '1.2.3.10');
297: }
298:
299: 300: 301: 302: 303:
304: public function test3xxException()
305: {
306: $this->makeRequest('Country', '1.2.3.11');
307: }
308:
309: 310: 311: 312: 313:
314: public function test406Exception()
315: {
316: $this->makeRequest('Country','1.2.3.12');
317: }
318:
319: 320: 321: 322:
323: public function testAddressNotFoundException()
324: {
325: $this->makeRequest('Country', '1.2.3.13');
326: }
327:
328: 329: 330: 331:
332: public function testAddressReservedException()
333: {
334: $this->makeRequest('Country', '1.2.3.14');
335: }
336:
337: 338: 339: 340:
341: public function testAuthorizationException()
342: {
343: $this->makeRequest('Country', '1.2.3.15');
344: }
345:
346: 347: 348: 349:
350: public function testMissingLicenseKeyException()
351: {
352: $this->makeRequest('Country', '1.2.3.16');
353: }
354:
355: 356: 357: 358:
359: public function testMissingUserIdException()
360: {
361: $this->makeRequest('Country', '1.2.3.17');
362: }
363:
364: 365: 366: 367:
368: public function testOutOfQueriesException()
369: {
370: $this->makeRequest('Country', '1.2.3.18');
371: }
372:
373: public function testParams()
374: {
375: $this->makeRequest(
376: 'Country',
377: '1.2.3.4',
378: array('en'),
379: array(
380: 'host' => 'api.maxmind.com',
381: 'timeout' => 27,
382: 'connectTimeout' => 72,
383: )
384: );
385: }
386:
387:
388: private function response(
389: $endpoint,
390: $status,
391: $body = null,
392: $bad = null,
393: $contentType = null
394: ) {
395: $headers = array();
396: if ($contentType) {
397: $headers['Content-Type'] = $contentType;
398: } elseif ($status == 200 || ($status >= 400 && $status < 500)) {
399: $headers['Content-Type'] = 'application/vnd.maxmind.com-'
400: . $endpoint . '+json; charset=UTF-8; version=1.0;';
401: }
402:
403: if ($bad) {
404: $body = '{ invalid: }';
405: } elseif (is_array($body)) {
406: $body = json_encode($body);
407: }
408:
409: $headers['Content-Length'] = strlen($body);
410:
411: return array($status, $headers, $body, );
412: }
413:
414: private function makeRequest(
415: $service,
416: $ipAddress,
417: $locales = array('en'),
418: $options = array(),
419: $callsToRequest = 1
420: ) {
421: $userId = 42;
422: $licenseKey = 'abcdef123456';
423:
424: list($statusCode, $headers, $responseBody)
425: = $this->getResponse($ipAddress);
426:
427: $stub = $this->getMockForAbstractClass(
428: 'MaxMind\\WebService\\Http\\Request'
429: );
430: $contentType = isset($headers['Content-Type'])
431: ? $headers['Content-Type']
432: : null;
433: $stub->expects($this->exactly($callsToRequest))
434: ->method('get')
435: ->willReturn(array($statusCode, $contentType, $responseBody));
436: $factory = $this->getMockBuilder(
437: 'MaxMind\\WebService\\Http\\RequestFactory'
438: )->getMock();
439: $host = isset($options['host']) ? $options['host'] : 'geoip.maxmind.com';
440: $url = 'https://' . $host . '/geoip/v2.1/' . strtolower($service)
441: . '/' . $ipAddress;
442: $headers = array(
443: 'Authorization: Basic '
444: . base64_encode($userId . ':' . $licenseKey),
445: 'Accept: application/json',
446: );
447:
448: $reflectionClass = new \ReflectionClass('MaxMind\\WebService\\Client');
449: $file = $reflectionClass->getFileName();
450: $caBundle = dirname($file) . '/cacert.pem';
451:
452: $curlVersion = curl_version();
453: $factory->expects($this->exactly($callsToRequest))
454: ->method('request')
455: ->with(
456: $this->equalTo($url),
457: $this->equalTo(
458: array(
459: 'headers' => $headers,
460: 'userAgent' => 'GeoIP2-API/' . \GeoIp2\WebService\Client::VERSION
461: . ' MaxMind-WS-API/' . WsClient::VERSION
462: . ' PHP/' . PHP_VERSION
463: . ' curl/' . $curlVersion['version'],
464: 'connectTimeout' => isset($options['connectTimeout'])
465: ? $options['connectTimeout'] : null,
466: 'timeout' => isset($options['timeout'])
467: ? $options['timeout'] : null,
468: 'caBundle' => $caBundle,
469: )
470: )
471: )->willReturn($stub);
472: $options['httpRequestFactory'] = $factory;
473:
474: $method = strtolower($service);
475:
476: $client = new \GeoIp2\WebService\Client(
477: $userId,
478: $licenseKey,
479: $locales,
480: $options
481: );
482: return $client->$method($ipAddress);
483: }
484:
485: }
486: