PageRenderTime 27ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/core/Common.test.php

https://github.com/quarkness/piwik
PHP | 893 lines | 660 code | 111 blank | 122 comment | 4 complexity | d9e7b437f42c84680a3686b698513984 MD5 | raw file
  1. <?php
  2. if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
  3. {
  4. require_once dirname(__FILE__)."/../../tests/config_test.php";
  5. }
  6. require_once 'Common.php';
  7. class Test_Piwik_Common extends UnitTestCase
  8. {
  9. function __construct( $title = '')
  10. {
  11. parent::__construct( $title );
  12. }
  13. public function setUp()
  14. {
  15. parent::setUp();
  16. $_GET = $_POST = array();
  17. }
  18. public function tearDown()
  19. {
  20. parent::tearDown();
  21. }
  22. function test_isUrl()
  23. {
  24. $valid = array(
  25. 'http://piwik.org',
  26. 'http://www.piwik.org',
  27. 'https://piwik.org',
  28. 'https://piwik.org/dir/dir2/?oeajkgea7aega=&ge=a',
  29. 'ftp://www.pi-wik.org',
  30. 'news://www.pi-wik.org',
  31. 'https://www.tëteâ.org',
  32. 'http://汉语/漢語.cn' //chinese
  33. );
  34. foreach($valid as $url)
  35. {
  36. $this->assertTrue(Piwik_Common::isLookLikeUrl($url), "$url not validated");
  37. }
  38. }
  39. function test_isUrl_notvalid()
  40. {
  41. $notValid = array(
  42. 'it doesnt look like url',
  43. '/index?page=test',
  44. 'test.html',
  45. '/\/\/\/\/\/\\\http://test.com////',
  46. 'jmleslangues.php',
  47. 'http://',
  48. ' http://',
  49. 'testhttp://test.com'
  50. );
  51. foreach($notValid as $url)
  52. {
  53. $this->assertTrue(!Piwik_Common::isLookLikeUrl($url), "$url validated");
  54. }
  55. }
  56. // sanitize an array OK
  57. function test_sanitizeInputValues_array1()
  58. {
  59. $a1 = array('test1' => 't1', 't45', "teatae", 4568, array('test'), 1.52);
  60. $this->assertEqual( $a1, Piwik_Common::sanitizeInputValues($a1));
  61. }
  62. // sanitize an array OK
  63. function test_sanitizeInputValues_array2()
  64. {
  65. $a1 = array('test1' => 't1', 't45', "teatae", 4568, array('test'), 1.52,
  66. array('test1' => 't1', 't45', "teatae", 4568, array('test'), 1.52),
  67. array('test1' => 't1', 't45', "teatae", 4568, array('test'), 1.52),
  68. array( array(array(array('test1' => 't1', 't45', "teatae", 4568, array('test'), 1.52)))
  69. ));
  70. $this->assertEqual( $a1, Piwik_Common::sanitizeInputValues($a1));
  71. }
  72. // sanitize an array with bad value level1
  73. function test_sanitizeInputValues_arrayBadValueL1()
  74. {
  75. $a1 = array('test1' => 't1', 't45', 'tea1"ta"e', 568, 1 => array('t<e"st'), 1.52);
  76. $a1OK = array('test1' => 't1', 't45', 'tea1&quot;ta&quot;e', 568, 1 => array('t&lt;e&quot;st'), 1.52);
  77. $this->assertEqual( $a1OK, Piwik_Common::sanitizeInputValues($a1));
  78. }
  79. // sanitize an array with bad value level2
  80. function test_sanitizeInputValues_arrayBadValueL2()
  81. {
  82. $a1 = array('tea1"ta"e' => array('t<e"st' => array('tgeag454554"t')), 1.52);
  83. $a1OK = array('tea1&quot;ta&quot;e' => array('t&lt;e&quot;st' => array('tgeag454554&quot;t')), 1.52);
  84. $this->assertEqual( $a1OK, Piwik_Common::sanitizeInputValues($a1));
  85. }
  86. // sanitize a string unicode => no change
  87. function test_sanitizeInputValues_arrayBadValueutf8()
  88. {
  89. $a1 = " Поиск в Интернете Поgqegиск страниц на рgeqg8978усском";
  90. $a1OK = " Поиск в Интернете Поgqegиск страниц на рgeqg8978усском";
  91. $this->assertEqual( $a1OK, Piwik_Common::sanitizeInputValues($a1));
  92. }
  93. // sanitize a bad string
  94. function test_sanitizeInputValues_badString()
  95. {
  96. $string = '& " < > 123abc\'';
  97. $stringOK = '&amp; &quot; &lt; &gt; 123abc&#039;';
  98. $this->assertEqual($stringOK, Piwik_Common::sanitizeInputValues($string));
  99. // test filter - expect new line and null byte to be filtered out
  100. $string = "New\nLine\rNull\0Byte";
  101. $stringOK = 'NewLineNullByte';
  102. $this->assertEqual($stringOK, Piwik_Common::sanitizeInputValues($string));
  103. // double encoded - no change (document as user error)
  104. $string = '%48%45%4C%00%4C%4F+%57%4F%52%4C%44';
  105. $stringOK = '%48%45%4C%00%4C%4F+%57%4F%52%4C%44';
  106. $this->assertEqual($stringOK, Piwik_Common::sanitizeInputValues($string));
  107. }
  108. // sanitize an integer
  109. function test_sanitizeInputValues_badInteger()
  110. {
  111. $string = '121564564';
  112. $this->assertEqual($string, Piwik_Common::sanitizeInputValues($string));
  113. $string = '121564564.0121';
  114. $this->assertEqual($string, Piwik_Common::sanitizeInputValues($string));
  115. $string = 121564564.0121;
  116. $this->assertEqual($string, Piwik_Common::sanitizeInputValues($string));
  117. $string = 12121;
  118. $this->assertEqual($string, Piwik_Common::sanitizeInputValues($string));
  119. }
  120. // sanitize HTML
  121. function test_sanitizeInputValues_HTML()
  122. {
  123. $html = "<test toto='mama' piwik=\"cool\">Piwik!!!!!</test>";
  124. $htmlOK = "&lt;test toto=&#039;mama&#039; piwik=&quot;cool&quot;&gt;Piwik!!!!!&lt;/test&gt;";
  125. $this->assertEqual($htmlOK, Piwik_Common::sanitizeInputValues($html));
  126. }
  127. // sanitize a SQL query
  128. function test_sanitizeInputValues_SQLQuery()
  129. {
  130. $sql = "SELECT piwik FROM piwik_tests where test= 'super\"value' AND cool=toto #comment here";
  131. $sqlOK = "SELECT piwik FROM piwik_tests where test= &#039;super&quot;value&#039; AND cool=toto #comment here";
  132. $this->assertEqual($sqlOK, Piwik_Common::sanitizeInputValues($sql));
  133. }
  134. // sanitize php variables
  135. function test_sanitizeInputValues_php()
  136. {
  137. $a = true;
  138. $b = true;
  139. $this->assertEqual($b, Piwik_Common::sanitizeInputValues($a));
  140. $a = false;
  141. $b = false;
  142. $this->assertEqual($b, Piwik_Common::sanitizeInputValues($a));
  143. $a = null;
  144. $b = null;
  145. $this->assertEqual($b, Piwik_Common::sanitizeInputValues($a));
  146. $a = "";
  147. $b = "";
  148. $this->assertEqual($b, Piwik_Common::sanitizeInputValues($a));
  149. }
  150. // sanitize with magic quotes runtime on => shouldnt affect the result
  151. function test_sanitizeInputValues_magicquotesON()
  152. {
  153. if (version_compare(PHP_VERSION, '5.4') < 0)
  154. {
  155. $this->assertTrue(@set_magic_quotes_runtime(1));
  156. $this->assertTrue(@get_magic_quotes_runtime(), 1);
  157. $this->test_sanitizeInputValues_array1();
  158. $this->test_sanitizeInputValues_array2();
  159. $this->test_sanitizeInputValues_badString();
  160. $this->test_sanitizeInputValues_HTML();
  161. }
  162. }
  163. // sanitize with magic quotes off
  164. function test_sanitizeInputValues_agicquotesOFF()
  165. {
  166. if (version_compare(PHP_VERSION, '5.4') < 0)
  167. {
  168. $this->assertTrue(@set_magic_quotes_runtime(0));
  169. $this->assertEqual(@get_magic_quotes_runtime(), 0);
  170. $this->test_sanitizeInputValues_array1();
  171. $this->test_sanitizeInputValues_array2();
  172. $this->test_sanitizeInputValues_badString();
  173. $this->test_sanitizeInputValues_HTML();
  174. }
  175. }
  176. /**
  177. * emptyvarname => exception
  178. */
  179. function test_getRequestVar_emptyVarName()
  180. {
  181. $_GET['']=1;
  182. try {
  183. $test = Piwik_Common::getRequestVar('');
  184. $this->fail("Exception not raised.");
  185. }
  186. catch (Exception $expected) {
  187. return;
  188. }
  189. }
  190. /**
  191. * nodefault Notype Novalue => exception
  192. */
  193. function test_getRequestVar_nodefaultNotypeNovalue()
  194. {
  195. try {
  196. $test = Piwik_Common::getRequestVar('test');
  197. $this->fail("Exception not raised.");
  198. }
  199. catch (Exception $expected) {
  200. return;
  201. }
  202. }
  203. /**
  204. *nodefault Notype WithValue => value
  205. */
  206. function test_getRequestVar_nodefaultNotypeWithValue()
  207. {
  208. $_GET['test'] = 1413.431413;
  209. $this->assertEqual( Piwik_Common::getRequestVar('test'), $_GET['test']);
  210. }
  211. /**
  212. * nodefault Withtype WithValue => exception cos type not matching
  213. */
  214. function test_getRequestVar_nodefaultWithtypeWithValue()
  215. {
  216. $_GET['test'] = 1413.431413;
  217. try {
  218. $this->assertEqual( Piwik_Common::getRequestVar('test', null, 'string'),
  219. (string)$_GET['test']);
  220. $this->fail("Exception not raised.");
  221. }
  222. catch (Exception $expected) {
  223. return;
  224. }
  225. }
  226. /**
  227. * nodefault Withtype WithValue => exception cos type not matching
  228. */
  229. function test_getRequestVar_nodefaultWithtypeWithValue2()
  230. {
  231. try {
  232. $this->assertEqual( Piwik_Common::getRequestVar('test', null, 'string'),
  233. null);
  234. $this->fail("Exception not raised.");
  235. }
  236. catch (Exception $expected) {
  237. return;
  238. }
  239. }
  240. /**
  241. * withdefault Withtype WithValue => value casted as type
  242. */
  243. function test_getRequestVar_withdefaultWithtypeWithValue()
  244. {
  245. $_GET['test'] = 1413.431413;
  246. $this->assertEqual( Piwik_Common::getRequestVar('test', 2, 'int'),
  247. 2);
  248. }
  249. /**
  250. * withdefault Notype NoValue => default value
  251. */
  252. function test_getRequestVar_withdefaultNotypeNoValue()
  253. {
  254. $this->assertEqual( Piwik_Common::getRequestVar('test', 'default'),
  255. 'default');
  256. }
  257. /**
  258. * withdefault Withtype NoValue =>default value casted as type
  259. */
  260. function test_getRequestVar_withdefaultWithtypeNoValue()
  261. {
  262. $this->assertEqual( Piwik_Common::getRequestVar('test', 'default', 'string'),
  263. 'default');
  264. }
  265. /**
  266. * integer as a default value / types
  267. * several tests
  268. */
  269. function test_getRequestVar_integerdefault()
  270. {
  271. $_GET['test'] = 1413.431413;
  272. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'int'), 45);
  273. $_GET['test'] = '';
  274. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'int'), 45);
  275. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'integer'), 45);
  276. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'float'), 45);
  277. $this->assertEqual( Piwik_Common::getRequestVar('test', 45.25, 'float'), 45.25);
  278. }
  279. /**
  280. * string as a default value / types
  281. * several tests
  282. */
  283. function test_getRequestVar_stringdefault()
  284. {
  285. $_GET['test'] = "1413.431413";
  286. $this->assertTrue( is_float(Piwik_Common::getRequestVar('test', 45, 'float')) );
  287. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'int'), 45);
  288. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'string'), "1413.431413");
  289. $_GET['test'] = '';
  290. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'string'), '45');
  291. $this->assertEqual( Piwik_Common::getRequestVar('test', "geaga", 'string'), "geaga");
  292. $this->assertEqual( Piwik_Common::getRequestVar('test', "&#039;}{}}{}{}&#039;", 'string'), "&#039;}{}}{}{}&#039;");
  293. $this->assertEqual( Piwik_Common::getRequestVar('test', "http://url?arg1=val1&arg2=val2", 'string'), "http://url?arg1=val1&amp;arg2=val2");
  294. $_GET['test'] = 'http://url?arg1=val1&arg2=val2';
  295. $this->assertEqual( Piwik_Common::getRequestVar('test', "http://url?arg1=val3&arg2=val4", 'string'), "http://url?arg1=val1&amp;arg2=val2");
  296. }
  297. /**
  298. * array as a default value / types
  299. * several tests
  300. *
  301. */
  302. function test_getRequestVar_arraydefault()
  303. {
  304. $test = array("test", 1345524, array("gaga"));
  305. $_GET['test'] = $test;
  306. $this->assertEqual( Piwik_Common::getRequestVar('test', array(), 'array'), $test);
  307. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'string'), "45");
  308. $this->assertEqual( Piwik_Common::getRequestVar('test', array(1), 'array'), $test);
  309. $this->assertEqual( Piwik_Common::getRequestVar('test', 4, 'int'), 4);
  310. $_GET['test'] = '';
  311. $this->assertEqual( Piwik_Common::getRequestVar('test', array(1), 'array'), array(1));
  312. $this->assertEqual( Piwik_Common::getRequestVar('test', array(), 'array'), array());
  313. }
  314. /**
  315. * we give a number in a string and request for a number
  316. * => it should give the string casted as a number
  317. *
  318. */
  319. function test_getRequestVar_stringedNumericCastedNumeric()
  320. {
  321. $test = "45645646";
  322. $_GET['test'] = $test;
  323. $this->assertEqual( Piwik_Common::getRequestVar('test', 1, 'int'), 45645646);
  324. $this->assertEqual( Piwik_Common::getRequestVar('test', 45, 'integer'), 45645646);
  325. $this->assertEqual( Piwik_Common::getRequestVar('test', "45454", 'string'), $test);
  326. $this->assertEqual( Piwik_Common::getRequestVar('test', array(), 'array'), array());
  327. }
  328. /**
  329. * no query string => null
  330. */
  331. function test_getParameterFromQueryString_noQuerystring()
  332. {
  333. $urlQuery = "";
  334. $parameter = "test''";
  335. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  336. $expectedResult = null;
  337. $this->assertTrue($result === $expectedResult);
  338. }
  339. /**
  340. * param not found => null
  341. */
  342. function test_getParameterFromQueryString_parameternotfound()
  343. {
  344. $urlQuery = "toto=mama&mama=titi";
  345. $parameter = "tot";
  346. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  347. $expectedResult = null;
  348. $this->assertTrue($result === $expectedResult);
  349. }
  350. /**
  351. * missing parameter value => returns false
  352. */
  353. function test_getParameterFromQueryString_missingParamValue()
  354. {
  355. $urlQuery = "toto=mama&mama&tuytyt=teaoi";
  356. $parameter = "mama";
  357. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  358. $expectedResult = false;
  359. $this->assertTrue($result === $expectedResult);
  360. }
  361. /**
  362. * empty parameter value => returns empty string
  363. */
  364. function test_getParameterFromQueryString_emptyParamValue()
  365. {
  366. $urlQuery = "toto=mama&mama=&tuytyt=teaoi";
  367. $parameter = "mama";
  368. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  369. $expectedResult = '';
  370. $this->assertEqual($result, $expectedResult);
  371. }
  372. /**
  373. * twice the parameter => returns the last value in the url
  374. */
  375. function test_getParameterFromQueryString_twiceTheParameterInQuery()
  376. {
  377. $urlQuery = "toto=mama&mama=&tuytyt=teaoi&toto=mama second value";
  378. $parameter = "toto";
  379. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  380. $expectedResult = 'mama second value';
  381. $this->assertEqual($result, $expectedResult);
  382. }
  383. /**
  384. * normal use case => parameter found
  385. */
  386. function test_getParameterFromQueryString_normalCase()
  387. {
  388. $urlQuery = "toto=mama&mama=&tuytyt=teaoi&toto=mama second value";
  389. $parameter = "tuytyt";
  390. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  391. $expectedResult = 'teaoi';
  392. $this->assertEqual($result, $expectedResult);
  393. }
  394. /**
  395. * normal use case with a string with many strange characters
  396. */
  397. function test_getParameterFromQueryString_strangeChars()
  398. {
  399. $urlQuery = 'toto=mama&mama=&tuytyt=Поиск в Интернете Поиск страниц на русском _*()!$!£$^!£$%&toto=mama second value';
  400. $parameter = "tuytyt";
  401. $result = Piwik_Common::getParameterFromQueryString( $urlQuery, $parameter);
  402. $expectedResult = 'Поиск в Интернете Поиск страниц на русском _*()!$!£$^!£$%';
  403. $this->assertEqual($result, $expectedResult);
  404. }
  405. function test_getParameterFromQueryString()
  406. {
  407. $tests = array(
  408. 'x' => false,
  409. 'x=1' => '1',
  410. '?x=1' => '1',
  411. '?x=y==1' => 'y==1',
  412. 'x[]=' => array(''),
  413. 'x[]=1' => array('1'),
  414. 'x[]=y==1' => array('y==1'),
  415. '?x[]=1&x[]=2' => array('1', '2'),
  416. '?x%5b%5d=3&x[]=4' => array('3', '4'),
  417. '?x%5B]=5&x[%5D=6' => array('5', '6'),
  418. // don't unescape the value, otherwise it becomes
  419. // ?x[]=A&y=1
  420. '?x%5B%5D=A%26y%3D1' => array('A%26y%3D1'),
  421. // ?z=y&x[]=1
  422. '?z=y%26x%5b%5d%3d1' => null,
  423. );
  424. // use $i as the test index because simpletest uses sprintf() internally and the percent encoding causes an error
  425. $i = 0;
  426. foreach($tests as $test => $expected)
  427. {
  428. $i++;
  429. $this->assertTrue(Piwik_Common::getParameterFromQueryString($test, 'y') === null, $i);
  430. $this->assertTrue(Piwik_Common::getParameterFromQueryString($test, 'x') === $expected, $i);
  431. }
  432. }
  433. function test_getArrayFromQueryString()
  434. {
  435. $expected = array(
  436. 'a' => false,
  437. 'b' => '',
  438. 'c' => '1',
  439. 'd' => array( false ),
  440. 'e' => array(''),
  441. 'f' => array('a'),
  442. 'g' => array('b', 'c'),
  443. );
  444. $this->assertEqual(serialize(Piwik_Common::getArrayFromQueryString('a&b=&c=1&d[]&e[]=&f[]=a&g[]=b&g[]=c')), serialize($expected));
  445. }
  446. public function test_isValidFilenameValidValues()
  447. {
  448. $valid = array(
  449. "test", "test.txt","test.......", "en-ZHsimplified",
  450. );
  451. foreach($valid as $toTest)
  452. {
  453. $this->assertTrue(Piwik_Common::isValidFilename($toTest), $toTest." not valid!");
  454. }
  455. }
  456. public function test_isValidFilenameNotValidValues()
  457. {
  458. $notvalid = array(
  459. "../test", "/etc/htpasswd", '$var', ';test', '[bizarre]', '', ".htaccess", "very long long eogaioge ageja geau ghaeihieg heiagie aiughaeui hfilename",
  460. );
  461. foreach($notvalid as $toTest)
  462. {
  463. $this->assertFalse(Piwik_Common::isValidFilename($toTest), $toTest." valid but shouldn't!");
  464. }
  465. }
  466. /**
  467. * Data driven tests of getBrowserLanguage
  468. */
  469. public function test_getBrowserLanguage()
  470. {
  471. $a1 = array( // user agent, browser language
  472. array( "en-gb", "en-gb" ),
  473. // filter quality attribute
  474. array( "en-us,en;q=0.5", "en-us,en" ),
  475. // bad user agents
  476. array( "en-us,chrome://global/locale/intl.properties", "en-us" ),
  477. // unregistered language tag
  478. array( "en,en-securid", "en" ),
  479. array( "en-securid,en", "en" ),
  480. array( "en-us,en-securid,en", "en-us,en" ),
  481. // accept private sub tags
  482. array( "en-us,x-en-securid", "en-us,x-en-securid" ),
  483. array( "en-us,en-x-securid", "en-us,en-x-securid" ),
  484. // filter arbitrary white space
  485. array( "en-us, en", "en-us,en" ),
  486. array( "en-ca, en-us ,en", "en-ca,en-us,en" ),
  487. // handle comments
  488. array( " ( comment ) en-us (another comment) ", "en-us" ),
  489. // handle quoted pairs (embedded in comments)
  490. array( " ( \( start ) en-us ( \) end ) ", "en-us" ),
  491. array( " ( \) en-ca, \( ) en-us ( \) ,en ) ", "en-us" ),
  492. );
  493. foreach($a1 as $testdata)
  494. {
  495. $res = Piwik_Common::getBrowserLanguage( $testdata[0] );
  496. $this->assertEqual( $testdata[1], $res );
  497. }
  498. }
  499. /**
  500. * Data driven tests of extractCountryCodeFromBrowserLanguage
  501. */
  502. public function test_extractCountryCodeFromBrowserLanguage()
  503. {
  504. $a1 = array( // browser language, valid countries, expected result
  505. array( "", array(), "xx" ),
  506. array( "", array("us" => 'amn'), "xx" ),
  507. array( "en", array("us" => 'amn'), "xx" ),
  508. array( "en-us", array("us" => 'amn'), "us" ),
  509. array( "en-ca", array("us" => 'amn'), "xx" ),
  510. array( "en-ca", array("us" => 'amn', "ca" => 'amn'), "ca" ),
  511. array( "fr-fr,fr-ca", array("us" => 'amn', "ca" => 'amn'), "ca" ),
  512. array( "fr-fr;q=1.0,fr-ca;q=0.9", array("us" => 'amn', "ca" => 'amn'), "ca" ),
  513. array( "fr-ca,fr;q=0.1", array("us" => 'amn', "ca" => 'amn'), "ca" ),
  514. array( "en-us,en;q=0.5", Piwik_Common::getCountriesList(), "us" ),
  515. array( "fr-ca,fr;q=0.1", array("fr" => 'eur', "us" => 'amn', "ca" => 'amn'), "ca" ),
  516. array( "fr-fr,fr-ca", array("fr" => 'eur', "us" => 'amn', "ca" => 'amn'), "fr" )
  517. );
  518. foreach($a1 as $testdata)
  519. {
  520. $this->assertEqual( $testdata[2], Piwik_Common::extractCountryCodeFromBrowserLanguage( $testdata[0], $testdata[1], true ));
  521. $this->assertEqual( $testdata[2], Piwik_Common::extractCountryCodeFromBrowserLanguage( $testdata[0], $testdata[1], false ));
  522. }
  523. }
  524. /**
  525. * Data driven tests of extractCountryCodeFromBrowserLanguage
  526. */
  527. public function test_extractCountryCodeFromBrowserLanguage_Infer()
  528. {
  529. $a1 = array( // browser language, valid countries, expected result (non-guess vs guess)
  530. array( "fr,en-us", array("us" => 'amn', "ca" => 'amn'), "us", "fr" ),
  531. array( "fr,en-us", array("fr" => 'eur', "us" => 'amn', "ca" => 'amn'), "us", "fr" ),
  532. array( "fr,fr-fr,en-us", array("fr" => 'eur', "us" => 'amn', "ca" => 'amn'), "fr", "fr" ),
  533. array( "fr-fr,fr,en-us", array("fr" => 'eur', "us" => 'amn', "ca" => 'amn'), "fr", "fr" )
  534. );
  535. // do not infer country from language
  536. foreach($a1 as $testdata)
  537. {
  538. $this->assertEqual( $testdata[2], Piwik_Common::extractCountryCodeFromBrowserLanguage( $testdata[0], $testdata[1], $enableLanguageToCountryGuess = false ));
  539. }
  540. // infer country from language
  541. foreach($a1 as $testdata)
  542. {
  543. $this->assertEqual( $testdata[3], Piwik_Common::extractCountryCodeFromBrowserLanguage( $testdata[0], $testdata[1], $enableLanguageToCountryGuess = true ));
  544. }
  545. }
  546. /**
  547. * Data driven tests of extractLanguageCodeFromBrowserLanguage
  548. */
  549. public function test_extractLanguageCodeFromBrowserLanguage()
  550. {
  551. $a1 = array( // browser language, valid languages, expected result
  552. array( "fr-ca", array("fr"), "fr" ),
  553. array( "", array(), "xx" ),
  554. array( "", array("en"), "xx" ),
  555. array( "fr", array("en"), "xx" ),
  556. array( "en", array("en"), "en" ),
  557. array( "en-ca", array("en-ca"), "en-ca" ),
  558. array( "en-ca", array("en"), "en" ),
  559. array( "fr,en-us", array("fr", "en"), "fr" ),
  560. array( "fr,en-us", array("en", "fr"), "fr" ),
  561. array( "fr-fr,fr-ca", array("fr"), "fr" ),
  562. array( "fr-fr,fr-ca", array("fr-ca"), "fr-ca" ),
  563. array( "fr-fr;q=1.0,fr-ca;q=0.9", array("fr-ca"), "fr-ca" ),
  564. array( "fr-ca,fr;q=0.1", array("fr-ca"), "fr-ca" ),
  565. );
  566. foreach($a1 as $testdata)
  567. {
  568. $this->assertEqual( $testdata[2], Piwik_Common::extractLanguageCodeFromBrowserLanguage( $testdata[0], $testdata[1] ), "test with {$testdata[0]} failed, expected {$testdata[2]}");
  569. }
  570. }
  571. public function test_SearchEngines_areDefinedCorrectly()
  572. {
  573. require_once "DataFiles/SearchEngines.php";
  574. $searchEngines = array();
  575. foreach($GLOBALS['Piwik_SearchEngines'] as $host => $info)
  576. {
  577. if(isset($info[2]) && $info[2] !== false)
  578. {
  579. $this->assertTrue(strrpos($info[2], "{k}") !== false, $host . " search URL is not defined correctly, must contain the macro {k}");
  580. }
  581. if(!array_key_exists($info[0], $searchEngines))
  582. {
  583. $searchEngines[$info[0]] = true;
  584. $this->assertTrue(strpos($host, '{}') === false, $host . " search URL is the master record and should not contain {}");
  585. }
  586. }
  587. }
  588. public function test_extractSearchEngineInformationFromUrl()
  589. {
  590. $urls = array(
  591. // normal case
  592. 'http://uk.search.yahoo.com/search?p=piwik&ei=UTF-8&fr=moz2'
  593. => array('name' => 'Yahoo!', 'keywords' => 'piwik'),
  594. // test request trimmed and capitalized
  595. 'http://www.google.com/search?hl=en&q=+piWIk+&btnG=Google+Search&aq=f&oq='
  596. => array('name' => 'Google', 'keywords' => 'piwik'),
  597. // testing special case of Google images
  598. 'http://images.google.com/imgres?imgurl=http://www.linux-corner.info/snapshot1.png&imgrefurl=http://www.oxxus.net/blog/archives/date/2007/10/page/41/&usg=__-xYvnp1IKpRZKjRDQVhpfExMkuM=&h=781&w=937&sz=203&hl=en&start=1&tbnid=P9LqKMIbdhlg-M:&tbnh=123&tbnw=148&prev=/images%3Fq%3Dthis%2Bmy%2Bquery%2Bwith%2Bhttp://domain%2Bname%2Band%2Bstrange%2Bcharacters%2B%2526%2B%255E%2B%257C%2B%253C%253E%2B%2525%2B%2522%2B%2527%2527%2BEOL%26gbv%3D2%26hl%3Den%26sa%3DG'
  599. => array('name' => 'Google Images', 'keywords' => 'this my query with http://domain name and strange characters & ^ | <> % " \'\' eol'),
  600. 'http://www.google.fr/search?hl=en&q=%3C%3E+%26test%3B+piwik+%26quot%3B&ei=GcXJSb-VKoKEsAPmnIjzBw&sa=X&oi=revisions_inline&ct=unquoted-query-link'
  601. => array('name' => 'Google', 'keywords' => '<> &test; piwik &quot;'),
  602. // testing Baidu special case (several variable names possible, and custom encoding)
  603. // see http://dev.piwik.org/trac/ticket/589
  604. // keyword is in "wd"
  605. 'http://www.baidu.com/s?ie=gb2312&bs=%BF%D5%BC%E4+hao123+%7C+%B8%FC%B6%E0%3E%3E&sr=&z=&cl=3&f=8&tn=baidu&wd=%BF%D5%BC%E4+%BA%C3123+%7C+%B8%FC%B6%E0%3E%3E&ct=0'
  606. => array('name' => 'Baidu', 'keywords' => '空间 好123 | 更多>>'),
  607. // keyword is in "word"
  608. 'http://www.baidu.com/s?kw=&sc=web&cl=3&tn=sitehao123&ct=0&rn=&lm=&ie=gb2312&rs2=&myselectvalue=&f=&pv=&z=&from=&word=%B7%E8%BF%F1%CB%B5%D3%A2%D3%EF+%D4%DA%CF%DF%B9%DB%BF%B4'
  609. => array('name' => 'Baidu', 'keywords' => '疯狂说英语 在线观看'),
  610. 'http://www.baidu.com/s?wd=%C1%F7%D0%D0%C3%C0%D3%EF%CF%C2%D4%D8'
  611. => array('name' => 'Baidu', 'keywords' => '流行美语下载'),
  612. 'http://web.gougou.com/search?search=%E5%85%A8%E9%83%A8&id=1'
  613. => array('name' => 'Baidu', 'keywords' => '全部'),
  614. 'http://www.google.cn/search?hl=zh-CN&q=%E6%B5%8F%E8%A7%88%E5%85%AC%E4%BA%A4%E5%9C%B0%E9%93%81%E7%AB%99%E7%82%B9%E4%BF%A1%E6%81%AF&btnG=Google+%E6%90%9C%E7%B4%A2&meta=cr%3DcountryCN&aq=f&oq='
  615. => array('name' => 'Google', 'keywords' => '浏览公交地铁站点信息'),
  616. // testing other exotic unicode characters
  617. 'http://www.yandex.com/yandsearch?text=%D1%87%D0%B0%D1%81%D1%82%D0%BE%D1%82%D0%B0+%D1%80%D0%B0%D1%81%D0%BF%D0%B0%D0%B4%D0%B0+%D1%81%D1%82%D0%B5%D0%BA%D0%BB%D0%B0&stpar2=%2Fh1%2Ftm11%2Fs1&stpar4=%2Fs1&stpar1=%2Fu0%27,%20%27%D1%87%D0%B0%D1%81%D1%82%D0%BE%D1%82%D0%B0+%D1%80%D0%B0%D1%81%D0%BF%D0%B0%D0%B4%D0%B0+%D1%81%D1%82%D0%B5%D0%BA%D0%BB%D0%B0'
  618. => array('name' => 'Yandex', 'keywords' => 'частота распада стекла'),
  619. 'http://www.yandex.ru/yandsearch?text=%D1%81%D0%BF%D0%BE%D1%80%D1%82%D0%B7%D0%B4%D1%80%D0%B0%D0%B2'
  620. => array('name' => 'Yandex', 'keywords' => 'спортздрав'),
  621. 'http://www.google.ge/search?hl=en&q=%E1%83%A1%E1%83%90%E1%83%A5%E1%83%90%E1%83%A0%E1%83%97%E1%83%95%E1%83%94%E1%83%9A%E1%83%9D&btnG=Google+Search'
  622. => array('name' => 'Google', 'keywords' => 'საქართველო'),
  623. // new Google url formats
  624. 'http://www.google.com/url?sa=t&source=web&ct=res&cd=7&url=http%3A%2F%2Fwww.example.com%2Fmypage.htm&ei=0SjdSa-1N5O8M_qW8dQN&rct=j&q=flowers&usg=AFQjCNHJXSUh7Vw7oubPaO3tZOzz-F-u_w&sig2=X8uCFh6IoPtnwmvGMULQfw'
  625. => array('name' => 'Google', 'keywords' => 'flowers'),
  626. 'http://www.google.com/webhp?tab=mw#hl=en&source=hp&q=test+hash&btnG=Google+Search&aq=f&aqi=&aql=&oq=&fp=22b4dcbb1403dc0f'
  627. => false,
  628. 'http://www.google.com/#hl=en&source=hp&q=test+hash&aq=f&aqi=n1g5g-s1g1g-s1g2&aql=&oq=&fp=22b4dcbb1403dc0f'
  629. => false,
  630. // new Google image format
  631. 'http://www.google.com/imgres?imgurl=http://www.imagedomain.com/zoom/34782_ZOOM.jpg&imgrefurl=http://www.mydomain.com/product/Omala-Govindra-Tank-XS-Brown-and-Chile.html&usg=__BD6z_JrJRAFjScDRhj4Tp8Vm_Zo=&h=610&w=465&sz=248&hl=en&start=3&itbs=1&tbnid=aiNVNce9-ZYAPM:&tbnh=136&tbnw=104&prev=/images%3Fq%3DFull%2BSupport%2BTummy%26hl%3Den%26safe%3Doff%26sa%3DG%26gbv%3D2%26tbs%3Disch:1'
  632. => array('name' => 'Google Images', 'keywords' => 'full support tummy'),
  633. 'http://www.google.com/imgres?imgurl=http://www.piwik-connector.com/en/wp-content/themes/analytics/images/piwik-connector.png&imgrefurl=http://www.piwik-connector.com/en/&usg=__ASwTaKUfneQEPcSMyGHp6PslPRo=&h=700&w=900&sz=40&hl=en&start=0&zoom=1&tbnid=K7nGMPzsg3iTHM:&tbnh=131&tbnw=168&ei=r9OpTc1lh96BB4bAgOsI&prev=/images%3Fq%3Dpiwik%26hl%3Den%26safe%3Doff%26biw%3D1280%26bih%3D828%26gbv%3D2%26tbm%3Disch&itbs=1&iact=rc&dur=1400&oei=r9OpTc1lh96BB4bAgOsI&page=1&ndsp=23&ved=1t:429,r:0,s:0&tx=125&ty=88'
  634. => array('name' => 'Google Images', 'keywords' => 'piwik'),
  635. 'http://www.google.com/search?tbm=isch&hl=en&source=hp&biw=1280&bih=793&q=piwik&gbv=2&oq=piwik&aq=f&aqi=g5g-s1g4&aql=&gs_sm=e&gs_upl=1526l2065l0l2178l5l4l0l0l0l0l184l371l1.2l3l0'
  636. => array('name' => 'Google Images', 'keywords' => 'piwik'),
  637. 'http://www.google.fr/imgres?q=piwik&um=1&hl=fr&client=firefox-a&sa=N&rls=org.mozilla:fr:official&tbm=isch&tbnid=Xmlv3vfl6ost2M:&imgrefurl=http://example.com&docid=sCbh1P0moOANNM&w=500&h=690&ei=3OFpTpjvH4T6sgbosYTiBA&zoom=1&iact=hc&vpx=176&vpy=59&dur=299&hovh=264&hovw=191&tx=108&ty=140&page=1&tbnh=140&tbnw=103&start=0&ndsp=39&ved=1t:429,r:0,s:0&biw=1280&bih=885'
  638. => array('name' => 'Google Images', 'keywords' => 'piwik'),
  639. // Google CSE is not standard google
  640. 'http://www.google.com/cse?cx=006944612449134755049%3Ahq5up-97k4u&cof=FORID%3A10&q=piwik&ad=w9&num=10&rurl=http%3A%2F%2Fwww.homepagle.com%2Fsearch.php%3Fcx%3D006944612449134755049%253Ahq5up-97k4u%26cof%3DFORID%253A10%26q%3D89'
  641. => array('name' => 'Google Custom Search', 'keywords' => 'piwik'),
  642. 'http://www.google.com/cse?cx=012634963936527368460%3Aqdoghy8xaco&cof=FORID%3A11%3BNB%3A1&ie=UTF-8&query=geoip&form_id=google_cse_searchbox_form&sa=Search&ad=w9&num=10&rurl=http%3A%2F%2Fpiwik.org%2Fsearch%2F%3Fcx%3D012634963936527368460%253Aqdoghy8xaco%26cof%3DFORID%253A11%253BNB%253A1%26ie%3DUTF-8%26query%3Dgeoip%26form_id%3Dgoogle_cse_searchbox_form%26sa%3DSearch'
  643. => array('name' => 'Google Custom Search', 'keywords' => 'geoip'),
  644. 'http://www.google.com.hk/custom?cx=012634963936527368460%3Aqdoghy8xaco&cof=AH%3Aleft%3BCX%3APiwik%252Eorg%3BDIV%3A%23cccccc%3BFORID%3A11%3BL%3Ahttp%3A%2F%2Fwww.google.com%2Fintl%2Fen%2Fimages%2Flogos%2Fcustom_search_logo_sm.gif%3BLH%3A30%3BLP%3A1%3BVLC%3A%23551a8b%3B&ie=UTF-8&query=mysqli.so&form_id=google_cse_searchbox_form&sa=Search&ad=w9&num=10&adkw=AELymgUTLKONpMqPGM-LbgTWRFfzo9uEj92nMyhi08lOA-wvJ9odphte3hfn5Nz13067or397hodwjlupE3ziTpE1uCKhvuTfzH8e8OHp_IAz7YoBQU6YvuSD-YiwcdcfrGRLxrLPUI3&hl=en&oe=UTF-8&client=google-coop-np&boostcse=0&rurl=http://piwik.org/search/%3Fcx%3D012634963936527368460%253Aqdoghy8xaco%26cof%3DFORID%253A11%253BNB%253A1%26ie%3DUTF-8%26query%3Dmysqli.so%26form_id%3Dgoogle_cse_searchbox_form%26sa%3DSearch'
  645. => array('name' => 'Google Custom Search', 'keywords' => 'mysqli.so'),
  646. // Powered by Google CSE
  647. 'http://www.cathoogle.com/results?cx=partner-pub-6379407697620666%3Alil1v7i1hv0&cof=FORID%3A9&safe=active&q=i+love+piwik&sa=Cathoogle+Search&siteurl=www.cathoogle.com%2F#867'
  648. => array('name' => 'Google Custom Search', 'keywords' => 'i love piwik'),
  649. // Google advanced search
  650. 'http://www.google.ca/search?hl=en&as_q=web+analytics&as_epq=real+time&as_oq=gpl+open+source&as_eq=oracle&num=10&lr=&as_filetype=&ft=i&as_sitesearch=&as_qdr=all&as_rights=&as_occt=any&cr=&as_nlo=&as_nhi=&safe=images'
  651. => array('name' => 'Google', 'keywords' => 'web analytics gpl or open or source "real time" -oracle'),
  652. 'http://www.google.ca/search?as_q=web+analytics&as_epq=real+time&as_oq=gpl+open+source&as_eq=oracle&num=10&lr=&as_filetype=&ft=i&as_sitesearch=&as_qdr=all&as_rights=&as_occt=any&cr=&as_nlo=&as_nhi=&safe=images'
  653. => array('name' => 'Google', 'keywords' => 'web analytics gpl or open or source "real time" -oracle'),
  654. 'http://www.google.ca/url?sa=t&source=web&cd=1&ved=0CBQQFjAA&url=http%3A%2F%2Fwww.robocoder.ca%2F&rct=j&q=web%20analytics%20gpl%20OR%20open%20OR%20source%20%22real%20time%22%20-sco&ei=zv6KTILkGsG88gaxoqz9Cw&usg=AFQjCNEv2Mp3ruU8YCMI40Pqo9ijjXvsUA'
  655. => array('name' => 'Google', 'keywords' => 'web analytics gpl or open or source "real time" -sco'),
  656. // Google Images (advanced search)
  657. 'http://www.google.com/imgres?imgurl=http://www.softwaredevelopment.ca/software/wxtest-red.png&imgrefurl=http://www.softwaredevelopment.ca/wxtestrunner.shtml&usg=__feDWUbLINOfWzPieVKX1iN9uj3A=&h=432&w=615&sz=18&hl=en&start=0&zoom=1&tbnid=V8LgKlxE4zAJnM:&tbnh=143&tbnw=204&ei=w9apTdWzKoLEgQff27X9CA&prev=/images%3Fq%3Dbook%2Bsite:softwaredevelopment.ca%26um%3D1%26hl%3Den%26safe%3Doff%26client%3Dubuntu%26channel%3Dfs%26biw%3D1280%26bih%3D828%26as_st%3Dy%26tbm%3Disch&um=1&itbs=1&iact=hc&vpx=136&vpy=141&dur=19894&hovh=188&hovw=268&tx=124&ty=103&oei=w9apTdWzKoLEgQff27X9CA&page=1&ndsp=3&ved=1t:429,r:0,s:0'
  658. => array('name' => 'Google Images', 'keywords' => 'book site:softwaredevelopment.ca'),
  659. // Google Shopping
  660. 'http://www.google.com/search?q=cameras&tbm=shop&hl=en&aq=f'
  661. => array('name' => 'Google Shopping', 'keywords' => 'cameras'),
  662. // Google cache
  663. 'http://webcache.googleusercontent.com/search?q=cache:CD2SncROLs4J:piwik.org/blog/2010/04/piwik-0-6-security-advisory/+piwik+security&cd=1&hl=en&ct=clnk'
  664. => array('name' => 'Google', 'keywords' => 'piwik security'),
  665. // Bing (subdomains)
  666. 'http://ca.bing.com/search?q=piwik+web+analytics&go=&form=QBLH&filt=all&qs=n&sk='
  667. => array('name' => 'Bing', 'keywords' => 'piwik web analytics'),
  668. 'http://ca.bing.com/images/search?q=anthon+pang&go=&form=QBIR&qs=n&sk=&sc=3-7'
  669. => array('name' => 'Bing Images', 'keywords' => 'anthon pang'),
  670. // Bing cache
  671. 'http://cc.bingj.com/cache.aspx?q=web+analytics&d=5020318678516316&mkt=en-CA&setlang=en-CA&w=6ea8ea88,ff6c44df'
  672. => array('name' => 'Bing', 'keywords' => 'web analytics'),
  673. // Bing Mobile
  674. 'http://m.bing.com/search/search.aspx?Q=piwik&d=&dl=&pq=&a=results&MID=8015'
  675. => array('name' => 'Bing', 'keywords' => 'piwik'),
  676. // Bing image search has a special URL
  677. 'http://www.bing.com/images/search?q=piwik&go=&form=QBIL'
  678. => array('name' => 'Bing Images', 'keywords' => 'piwik'),
  679. // Yahoo! Directory
  680. 'http://search.yahoo.com/search/dir?ei=UTF-8&p=analytics&h=c'
  681. => array('name' => 'Yahoo! Directory', 'keywords' => 'analytics'),
  682. /*
  683. // Bing mobile image search has a special URL
  684. 'http://m.bing.com/search/search.aspx?A=imageresults&Q=piwik&D=Image&MID=8015&SI=0&PN=0&SCO=0'
  685. => array('name' => 'Bing Images', 'keywords' => 'piwik'),
  686. */
  687. /*
  688. // Yahoo (Bing-powered) cache
  689. 'http://74.6.239.84/search/srpcache?ei=UTF-8&p=web+analytics&fr=yfp-t-715&u=http://cc.bingj.com/cache.aspx?q=web+analytics&d=5020318680482405&mkt=en-CA&setlang=en-CA&w=a68d7af0,873cfeb0&icp=1&.intl=ca&sig=x6MgjtrDYvsxi8Zk2ZX.tw--'
  690. => array('name' => 'Yahoo', 'keywords' => 'web analytics'),
  691. 'http://74.6.239.185/search/srpcache?ei=UTF-8&p=piwik&fr=yfp-t-964&fp_ip=ca&u=http://cc.bingj.com/cache.aspx?q=piwik&d=4770519086662477&mkt=en-US&setlang=en-US&w=f4bc05d8,8c8af2e3&icp=1&.intl=us&sig=PXmPDNqapxSQ.scsuhIpZA--'
  692. => array('name' => 'Yahoo', 'keywords' => 'piwik'),
  693. */
  694. // InfoSpace
  695. 'http://infospace.com/ispace/ws/results/Web/real time web analytics/1/417/TopNavigation/Relevance/iq=true/zoom=off/enginefilter=all/_iceUrlFlag=7?_IceUrl=true'
  696. => array('name' => 'InfoSpace', 'keywords' => 'real time web analytics'),
  697. // Powered by InfoSpace metasearch
  698. 'http://search.kiwee.com/pemonitorhosted/ws/results/Web/mobile analytics/1/417/TopNavigation/Source/iq=true/zoom=off/_iceUrlFlag=7?_IceUrl=true'
  699. => array('name' => 'InfoSpace', 'keywords' => 'mobile analytics'),
  700. 'http://ws.copernic.com/pemonitorhosted/ws/results/Web/piwik/1/417/TopNavigation/Source/iq=true/zoom=off/_iceUrlFlag=7?_IceUrl=true'
  701. => array('name' => 'InfoSpace', 'keywords' => 'piwik'),
  702. // 123people
  703. 'http://www.123people.de/s/piwik'
  704. => array('name' => '123people', 'keywords' => 'piwik'),
  705. // msxml.excite.com (using regex)
  706. 'http://msxml.excite.com/excite/ws/results/Images/test/1/408/TopNavigation/Relevance/iq=true/zoom=off/_iceUrlFlag=7?_IceUrl=true&padv=qall%3dpiwik%26qphrase%3d%26qany%3d%26qnot%3d'
  707. => array('name' => 'Excite', 'keywords' => 'test'),
  708. 'http://search.mywebsearch.com/mywebsearch/GGmain.jhtml?searchFor=piwik&tpr=sbt&st=site&ptnrS=ZZ&ss=sub&gcht='
  709. => array('name' => 'MyWebSearch', 'keywords' => 'piwik'),
  710. // Yahoo!
  711. 'http://us.yhs4.search.yahoo.com/yhs/search;_ylt=A0oG7qCW9ZhNdFQAuTQPxQt.?q=piwik'
  712. => array('name' => 'Yahoo!', 'keywords' => 'piwik'),
  713. 'http://us.nc.yhs.search.yahoo.com/if?p=piwik&partnerid=yhs-if-timewarner&fr=yhs-if-timewarner&ei=UTF-8&YST_b=7&vm=p'
  714. => array('name' => 'Yahoo!', 'keywords' => 'piwik'),
  715. // Babylon
  716. 'http://search.babylon.com/?q=piwik'
  717. => array('name' => 'Babylon', 'keywords' => 'piwik'),
  718. 'http://search.babylon.com/web/piwik'
  719. => array('name' => 'Babylon', 'keywords' => 'piwik'),
  720. // ask has country not at beginning
  721. 'http://images.de.ask.com/fr?q=piwik&qt=0'
  722. => array('name' => 'Ask', 'keywords' => 'piwik'),
  723. // test that master record is used to backfill subsequent rows
  724. 'http://www.baidu.com/?wd=test1'
  725. => array('name' => 'Baidu', 'keywords' => 'test1'),
  726. 'http://tieba.baidu.com/?kw=test2'
  727. => array('name' => 'Baidu', 'keywords' => 'test2'),
  728. 'http://web.gougou.com/?search=test3'
  729. => array('name' => 'Baidu', 'keywords' => 'test3'),
  730. );
  731. foreach($urls as $referrerUrl => $expectedReturnedValue) {
  732. $returnedValue = Piwik_Common::extractSearchEngineInformationFromUrl($referrerUrl);
  733. $exported = var_export($returnedValue,true);
  734. $result = $expectedReturnedValue === $returnedValue;
  735. $this->assertTrue($result, $exported);
  736. if(!$result) {
  737. $this->fail("error in extracting from $referrerUrl got ".$exported."<br>");
  738. }
  739. }
  740. }
  741. function test_getLossyUrl()
  742. {
  743. $urls = array(
  744. 'example.com' => 'example.com',
  745. 'm.example.com' => 'example.com',
  746. 'www.example.com' => 'example.com',
  747. 'search.example.com' => 'example.com',
  748. 'example.ca' => 'example.{}',
  749. 'us.example.com' => '{}.example.com',
  750. 'www.m.example.ca' => 'example.{}',
  751. 'www.google.com.af' => 'google.{}',
  752. 'www.google.co.uk' => 'google.{}',
  753. 'images.de.ask.com' => 'images.{}.ask.com',
  754. );
  755. foreach($urls as $input => $expected)
  756. {
  757. $this->assertEqual( Piwik_Common::getLossyUrl($input), $expected);
  758. }
  759. }
  760. }