PageRenderTime 74ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/PHPUnit/Fixture.php

https://github.com/CodeYellowBV/piwik
PHP | 771 lines | 582 code | 92 blank | 97 comment | 42 complexity | f6961195144db68e5bcb2eae006d8295 MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. */
  8. use Piwik\Access;
  9. use Piwik\Common;
  10. use Piwik\Config;
  11. use Piwik\DataAccess\ArchiveTableCreator;
  12. use Piwik\DataTable\Manager as DataTableManager;
  13. use Piwik\Date;
  14. use Piwik\Db;
  15. use Piwik\DbHelper;
  16. use Piwik\Log;
  17. use Piwik\Option;
  18. use Piwik\Piwik;
  19. use Piwik\Plugins\LanguagesManager\API as APILanguageManager;
  20. use Piwik\Plugins\MobileMessaging\MobileMessaging;
  21. use Piwik\Plugins\ScheduledReports\API as APIScheduledReports;
  22. use Piwik\Plugins\ScheduledReports\ScheduledReports;
  23. use Piwik\Plugins\SitesManager\API as APISitesManager;
  24. use Piwik\Plugins\UserCountry\LocationProvider;
  25. use Piwik\Plugins\UsersManager\API as APIUsersManager;
  26. use Piwik\Plugins\UsersManager\UsersManager;
  27. use Piwik\ReportRenderer;
  28. use Piwik\Site;
  29. use Piwik\Tracker\Cache;
  30. use Piwik\Translate;
  31. use Piwik\Url;
  32. /**
  33. * Base type for all integration test fixtures. Integration test fixtures
  34. * add visit and related data to the database before a test is run. Different
  35. * tests can use the same fixtures.
  36. *
  37. * This class defines a set of helper methods for fixture types. The helper
  38. * methods are public, but ideally they should only be used by fixture types.
  39. *
  40. * NOTE: YOU SHOULD NOT CREATE A NEW FIXTURE UNLESS THERE IS NO WAY TO MODIFY
  41. * AN EXISTING FIXTURE TO HANDLE YOUR USE CASE.
  42. *
  43. * Related TODO: we should try and reduce the amount of existing fixtures by
  44. * merging some together.
  45. */
  46. class Fixture extends PHPUnit_Framework_Assert
  47. {
  48. const IMAGES_GENERATED_ONLY_FOR_OS = 'linux';
  49. const IMAGES_GENERATED_FOR_PHP = '5.5';
  50. const IMAGES_GENERATED_FOR_GD = '2.1.1';
  51. const DEFAULT_SITE_NAME = 'Piwik test';
  52. const ADMIN_USER_LOGIN = 'superUserLogin';
  53. const ADMIN_USER_PASSWORD = 'superUserPass';
  54. public $dbName = false;
  55. public $createConfig = true;
  56. public $dropDatabaseInSetUp = true;
  57. public $dropDatabaseInTearDown = true;
  58. public $loadTranslations = true;
  59. public $createSuperUser = true;
  60. public $removeExistingSuperUser = true;
  61. public $overwriteExisting = true;
  62. public $configureComponents = true;
  63. public $persistFixtureData = false;
  64. public $resetPersistedFixture = false;
  65. public $printToScreen = false;
  66. public $testEnvironment = null;
  67. /**
  68. * @return string
  69. */
  70. protected static function getPythonBinary()
  71. {
  72. if(\Piwik\SettingsServer::isWindows()) {
  73. return "C:\Python27\python.exe";
  74. }
  75. if(IntegrationTestCase::isTravisCI()) {
  76. return 'python2.6';
  77. }
  78. return 'python';
  79. }
  80. /** Adds data to Piwik. Creates sites, tracks visits, imports log files, etc. */
  81. public function setUp()
  82. {
  83. // empty
  84. }
  85. /** Does any clean up. Most of the time there will be no need to clean up. */
  86. public function tearDown()
  87. {
  88. // empty
  89. }
  90. public function getDbName()
  91. {
  92. if ($this->dbName !== false) {
  93. return $this->dbName;
  94. }
  95. if ($this->persistFixtureData) {
  96. return str_replace("\\", "_", get_class($this));
  97. }
  98. return Config::getInstance()->database_tests['dbname'];
  99. }
  100. public function performSetUp($setupEnvironmentOnly = false)
  101. {
  102. try {
  103. if ($this->createConfig) {
  104. Config::getInstance()->setTestEnvironment();
  105. }
  106. $this->dbName = $this->getDbName();
  107. if ($this->persistFixtureData) {
  108. $this->dropDatabaseInSetUp = false;
  109. $this->dropDatabaseInTearDown = false;
  110. $this->overwriteExisting = false;
  111. $this->removeExistingSuperUser = false;
  112. Config::getInstance()->database_tests['dbname'] = Config::getInstance()->database['dbname'] = $this->dbName;
  113. $this->getTestEnvironment()->dbName = $this->dbName;
  114. }
  115. if ($this->dbName === false) { // must be after test config is created
  116. $this->dbName = Config::getInstance()->database['dbname'];
  117. }
  118. static::connectWithoutDatabase();
  119. if ($this->dropDatabaseInSetUp
  120. || $this->resetPersistedFixture
  121. ) {
  122. $this->dropDatabase();
  123. }
  124. DbHelper::createDatabase($this->dbName);
  125. DbHelper::disconnectDatabase();
  126. // reconnect once we're sure the database exists
  127. Config::getInstance()->database['dbname'] = $this->dbName;
  128. Db::createDatabaseObject();
  129. DbHelper::createTables();
  130. \Piwik\Plugin\Manager::getInstance()->unloadPlugins();
  131. } catch (Exception $e) {
  132. static::fail("TEST INITIALIZATION FAILED: " . $e->getMessage() . "\n" . $e->getTraceAsString());
  133. }
  134. include "DataFiles/SearchEngines.php";
  135. include "DataFiles/Socials.php";
  136. include "DataFiles/Languages.php";
  137. include "DataFiles/Countries.php";
  138. include "DataFiles/Currencies.php";
  139. include "DataFiles/LanguageToCountry.php";
  140. include "DataFiles/Providers.php";
  141. if (!$this->isFixtureSetUp()) {
  142. DbHelper::truncateAllTables();
  143. }
  144. static::createAccessInstance();
  145. // We need to be SU to create websites for tests
  146. Piwik::setUserHasSuperUserAccess();
  147. Cache::deleteTrackerCache();
  148. static::loadAllPlugins();
  149. $_GET = $_REQUEST = array();
  150. $_SERVER['HTTP_REFERER'] = '';
  151. // Make sure translations are loaded to check messages in English
  152. if ($this->loadTranslations) {
  153. Translate::reloadLanguage('en');
  154. APILanguageManager::getInstance()->setLanguageForUser('superUserLogin', 'en');
  155. }
  156. FakeAccess::$superUserLogin = 'superUserLogin';
  157. \Piwik\SettingsPiwik::$cachedKnownSegmentsToArchive = null;
  158. \Piwik\CacheFile::$invalidateOpCacheBeforeRead = true;
  159. if ($this->configureComponents) {
  160. \Piwik\Plugins\PrivacyManager\IPAnonymizer::deactivate();
  161. \Piwik\Plugins\PrivacyManager\DoNotTrackHeaderChecker::deactivate();
  162. }
  163. if ($this->createSuperUser) {
  164. self::createSuperUser($this->removeExistingSuperUser);
  165. }
  166. if ($setupEnvironmentOnly) {
  167. return;
  168. }
  169. $this->getTestEnvironment()->save();
  170. $this->getTestEnvironment()->executeSetupTestEnvHook();
  171. Piwik_TestingEnvironment::addSendMailHook();
  172. if ($this->overwriteExisting
  173. || !$this->isFixtureSetUp()
  174. ) {
  175. $this->setUp();
  176. $this->markFixtureSetUp();
  177. $this->log("Database {$this->dbName} marked as successfully set up.");
  178. } else {
  179. $this->log("Using existing database {$this->dbName}.");
  180. }
  181. }
  182. public function getTestEnvironment()
  183. {
  184. if ($this->testEnvironment === null) {
  185. $this->testEnvironment = new Piwik_TestingEnvironment();
  186. $this->testEnvironment->delete();
  187. }
  188. return $this->testEnvironment;
  189. }
  190. public function isFixtureSetUp()
  191. {
  192. $optionName = get_class($this) . '.setUpFlag';
  193. return Option::get($optionName) !== false;
  194. }
  195. public function markFixtureSetUp()
  196. {
  197. $optionName = get_class($this) . '.setUpFlag';
  198. Option::set($optionName, 1);
  199. }
  200. public function performTearDown()
  201. {
  202. // Note: avoid run SQL in the *tearDown() metohds because it randomly fails on Travis CI
  203. // with error Error while sending QUERY packet. PID=XX
  204. $this->tearDown();
  205. self::unloadAllPlugins();
  206. if ($this->dropDatabaseInTearDown) {
  207. $this->dropDatabase();
  208. }
  209. DataTableManager::getInstance()->deleteAll();
  210. Option::clearCache();
  211. Site::clearCache();
  212. Cache::deleteTrackerCache();
  213. Config::getInstance()->clear();
  214. ArchiveTableCreator::clear();
  215. \Piwik\Plugins\ScheduledReports\API::$cache = array();
  216. \Piwik\Registry::unsetInstance();
  217. \Piwik\EventDispatcher::getInstance()->clearAllObservers();
  218. $_GET = $_REQUEST = array();
  219. Translate::unloadEnglishTranslation();
  220. }
  221. public static function loadAllPlugins()
  222. {
  223. DbHelper::createTables();
  224. $pluginsManager = \Piwik\Plugin\Manager::getInstance();
  225. $plugins = $pluginsManager->getPluginsToLoadDuringTests();
  226. $pluginsManager->loadPlugins($plugins);
  227. // Install plugins
  228. $messages = $pluginsManager->installLoadedPlugins();
  229. if(!empty($messages)) {
  230. Log::info("Plugin loading messages: %s", implode(" --- ", $messages));
  231. }
  232. // Activate them
  233. foreach($plugins as $name) {
  234. if (!$pluginsManager->isPluginActivated($name)) {
  235. $pluginsManager->activatePlugin($name);
  236. }
  237. }
  238. }
  239. public static function unloadAllPlugins()
  240. {
  241. try {
  242. $plugins = \Piwik\Plugin\Manager::getInstance()->getLoadedPlugins();
  243. foreach ($plugins AS $plugin) {
  244. $plugin->uninstall();
  245. }
  246. \Piwik\Plugin\Manager::getInstance()->unloadPlugins();
  247. } catch (Exception $e) {
  248. }
  249. }
  250. /**
  251. * Creates a website, then sets its creation date to a day earlier than specified dateTime
  252. * Useful to create a website now, but force data to be archived back in the past.
  253. *
  254. * @param string $dateTime eg '2010-01-01 12:34:56'
  255. * @param int $ecommerce
  256. * @param string $siteName
  257. *
  258. * @param bool|string $siteUrl
  259. * @param int $siteSearch
  260. * @param null|string $searchKeywordParameters
  261. * @param null|string $searchCategoryParameters
  262. * @return int idSite of website created
  263. */
  264. public static function createWebsite($dateTime, $ecommerce = 0, $siteName = false, $siteUrl = false,
  265. $siteSearch = 1, $searchKeywordParameters = null,
  266. $searchCategoryParameters = null, $timezone = null)
  267. {
  268. if($siteName === false) {
  269. $siteName = self::DEFAULT_SITE_NAME;
  270. }
  271. $idSite = APISitesManager::getInstance()->addSite(
  272. $siteName,
  273. $siteUrl === false ? "http://piwik.net/" : $siteUrl,
  274. $ecommerce,
  275. $siteSearch, $searchKeywordParameters, $searchCategoryParameters,
  276. $ips = null,
  277. $excludedQueryParameters = null,
  278. $timezone,
  279. $currency = null
  280. );
  281. // Manually set the website creation date to a day earlier than the earliest day we record stats for
  282. Db::get()->update(Common::prefixTable("site"),
  283. array('ts_created' => Date::factory($dateTime)->subDay(1)->getDatetime()),
  284. "idsite = $idSite"
  285. );
  286. // Clear the memory Website cache
  287. Site::clearCache();
  288. return $idSite;
  289. }
  290. /**
  291. * Returns URL to Piwik root.
  292. *
  293. * @return string
  294. */
  295. public static function getRootUrl()
  296. {
  297. $piwikUrl = Url::getCurrentUrlWithoutFileName();
  298. $pathBeforeRoot = 'tests';
  299. // Running from a plugin
  300. if (strpos($piwikUrl, 'plugins/') !== false) {
  301. $pathBeforeRoot = 'plugins';
  302. }
  303. $testsInPath = strpos($piwikUrl, $pathBeforeRoot . '/');
  304. if ($testsInPath !== false) {
  305. $piwikUrl = substr($piwikUrl, 0, $testsInPath);
  306. }
  307. // in case force_ssl=1, or assume_secure_protocol=1, is set in tests
  308. // we don't want to require Travis CI or devs to setup HTTPS on their local machine
  309. $piwikUrl = str_replace("https://", "http://", $piwikUrl);
  310. return $piwikUrl;
  311. }
  312. /**
  313. * Returns URL to the proxy script, used to ensure piwik.php
  314. * uses the test environment, and allows variable overwriting
  315. *
  316. * @return string
  317. */
  318. public static function getTrackerUrl()
  319. {
  320. return self::getRootUrl() . 'tests/PHPUnit/proxy/piwik.php';
  321. }
  322. /**
  323. * Returns a PiwikTracker object that you can then use to track pages or goals.
  324. *
  325. * @param int $idSite
  326. * @param string $dateTime
  327. * @param boolean $defaultInit If set to true, the tracker object will have default IP, user agent, time, resolution, etc.
  328. * @param bool $useLocal
  329. *
  330. * @return PiwikTracker
  331. */
  332. public static function getTracker($idSite, $dateTime, $defaultInit = true, $useLocal = false)
  333. {
  334. if ($useLocal) {
  335. require_once PIWIK_INCLUDE_PATH . '/tests/LocalTracker.php';
  336. $t = new Piwik_LocalTracker($idSite, self::getTrackerUrl());
  337. } else {
  338. $t = new PiwikTracker($idSite, self::getTrackerUrl());
  339. }
  340. $t->setForceVisitDateTime($dateTime);
  341. if ($defaultInit) {
  342. $t->setTokenAuth(self::getTokenAuth());
  343. $t->setIp('156.5.3.2');
  344. // Optional tracking
  345. $t->setUserAgent("Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 (.NET CLR 3.5.30729)");
  346. $t->setBrowserLanguage('fr');
  347. $t->setLocalTime('12:34:06');
  348. $t->setResolution(1024, 768);
  349. $t->setBrowserHasCookies(true);
  350. $t->setPlugins($flash = true, $java = true, $director = false);
  351. }
  352. return $t;
  353. }
  354. /**
  355. * Checks that the response is a GIF image as expected.
  356. * Will fail the test if the response is not the expected GIF
  357. *
  358. * @param $response
  359. */
  360. public static function checkResponse($response)
  361. {
  362. $trans_gif_64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
  363. $expectedResponse = base64_decode($trans_gif_64);
  364. $url = "\n =========================== \n URL was: " . PiwikTracker::$DEBUG_LAST_REQUESTED_URL;
  365. self::assertEquals($expectedResponse, $response, "Expected GIF beacon, got: <br/>\n"
  366. . var_export($response, true)
  367. . "\n If you are stuck, you can enable [Tracker] debug=1; in config.ini.php to get more debug info."
  368. . base64_encode($response)
  369. . $url
  370. );
  371. }
  372. /**
  373. * Checks that the response from bulk tracking is a valid JSON
  374. * string. Will fail the test if JSON status is not success.
  375. *
  376. * @param $response
  377. */
  378. public static function checkBulkTrackingResponse($response) {
  379. $data = json_decode($response, true);
  380. if (!is_array($data) || empty($response)) {
  381. throw new Exception("Bulk tracking response (".$response.") is not an array: " . var_export($data, true) . "\n");
  382. }
  383. if(!isset($data['status'])) {
  384. throw new Exception("Returned data didn't have a status: " . var_export($data,true));
  385. }
  386. self::assertArrayHasKey('status', $data);
  387. self::assertEquals('success', $data['status'], "expected success, got: " . var_export($data, true));
  388. }
  389. public static function makeLocation($city, $region, $country, $lat = null, $long = null, $isp = null)
  390. {
  391. return array(LocationProvider::CITY_NAME_KEY => $city,
  392. LocationProvider::REGION_CODE_KEY => $region,
  393. LocationProvider::COUNTRY_CODE_KEY => $country,
  394. LocationProvider::LATITUDE_KEY => $lat,
  395. LocationProvider::LONGITUDE_KEY => $long,
  396. LocationProvider::ISP_KEY => $isp);
  397. }
  398. /**
  399. * Returns the Super User token auth that can be used in tests. Can be used to
  400. * do bulk tracking.
  401. *
  402. * @return string
  403. */
  404. public static function getTokenAuth()
  405. {
  406. return APIUsersManager::getInstance()->getTokenAuth(
  407. self::ADMIN_USER_LOGIN,
  408. UsersManager::getPasswordHash(self::ADMIN_USER_PASSWORD)
  409. );
  410. }
  411. public static function createSuperUser($removeExisting = true)
  412. {
  413. $login = self::ADMIN_USER_LOGIN;
  414. $password = UsersManager::getPasswordHash(self::ADMIN_USER_PASSWORD);
  415. $token = self::getTokenAuth();
  416. $model = new \Piwik\Plugins\UsersManager\Model();
  417. if ($removeExisting) {
  418. $model->deleteUserOnly($login);
  419. }
  420. $user = $model->getUser($login);
  421. if (empty($user)) {
  422. $model->addUser($login, $password, 'hello@example.org', $login, $token, Date::now()->getDatetime());
  423. } else {
  424. $model->updateUser($login, $password, 'hello@example.org', $login, $token);
  425. }
  426. if (empty($user['superuser_access'])) {
  427. $model->setSuperUserAccess($login, true);
  428. }
  429. return $model->getUserByTokenAuth($token);
  430. }
  431. /**
  432. * Create three MAIL and two MOBILE scheduled reports
  433. *
  434. * Reports sent by mail can contain PNG graphs when the user specifies it.
  435. * Depending on the system under test, generated images differ slightly.
  436. * Because of this discrepancy, PNG graphs are only tested if the system under test
  437. * has the characteristics described in 'canImagesBeIncludedInScheduledReports'.
  438. * See tests/README.md for more detail.
  439. *
  440. * @see canImagesBeIncludedInScheduledReports
  441. * @param int $idSite id of website created
  442. */
  443. public static function setUpScheduledReports($idSite)
  444. {
  445. // fake access is needed so API methods can call Piwik::getCurrentUserLogin(), e.g: 'ScheduledReports.addReport'
  446. $pseudoMockAccess = new FakeAccess;
  447. FakeAccess::$superUser = true;
  448. Access::setSingletonInstance($pseudoMockAccess);
  449. // retrieve available reports
  450. $availableReportMetadata = APIScheduledReports::getReportMetadata($idSite, ScheduledReports::EMAIL_TYPE);
  451. $availableReportIds = array();
  452. foreach ($availableReportMetadata as $reportMetadata) {
  453. $availableReportIds[] = $reportMetadata['uniqueId'];
  454. }
  455. //@review should we also test evolution graphs?
  456. // set-up mail report
  457. APIScheduledReports::getInstance()->addReport(
  458. $idSite,
  459. 'Mail Test report',
  460. 'day', // overridden in getApiForTestingScheduledReports()
  461. 0,
  462. ScheduledReports::EMAIL_TYPE,
  463. ReportRenderer::HTML_FORMAT, // overridden in getApiForTestingScheduledReports()
  464. $availableReportIds,
  465. array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY)
  466. );
  467. // set-up sms report for one website
  468. APIScheduledReports::getInstance()->addReport(
  469. $idSite,
  470. 'SMS Test report, one website',
  471. 'day', // overridden in getApiForTestingScheduledReports()
  472. 0,
  473. MobileMessaging::MOBILE_TYPE,
  474. MobileMessaging::SMS_FORMAT,
  475. array("MultiSites_getOne"),
  476. array("phoneNumbers" => array())
  477. );
  478. // set-up sms report for all websites
  479. APIScheduledReports::getInstance()->addReport(
  480. $idSite,
  481. 'SMS Test report, all websites',
  482. 'day', // overridden in getApiForTestingScheduledReports()
  483. 0,
  484. MobileMessaging::MOBILE_TYPE,
  485. MobileMessaging::SMS_FORMAT,
  486. array("MultiSites_getAll"),
  487. array("phoneNumbers" => array())
  488. );
  489. if (self::canImagesBeIncludedInScheduledReports()) {
  490. // set-up mail report with images
  491. APIScheduledReports::getInstance()->addReport(
  492. $idSite,
  493. 'Mail Test report',
  494. 'day', // overridden in getApiForTestingScheduledReports()
  495. 0,
  496. ScheduledReports::EMAIL_TYPE,
  497. ReportRenderer::HTML_FORMAT, // overridden in getApiForTestingScheduledReports()
  498. $availableReportIds,
  499. array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_AND_GRAPHS)
  500. );
  501. // set-up mail report with one row evolution based png graph
  502. APIScheduledReports::getInstance()->addReport(
  503. $idSite,
  504. 'Mail Test report',
  505. 'day',
  506. 0,
  507. ScheduledReports::EMAIL_TYPE,
  508. ReportRenderer::HTML_FORMAT,
  509. array('Actions_getPageTitles'),
  510. array(
  511. ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_GRAPHS_ONLY,
  512. ScheduledReports::EVOLUTION_GRAPH_PARAMETER => 'true',
  513. )
  514. );
  515. }
  516. }
  517. /**
  518. * Return true if system under test has Piwik core team's most common configuration
  519. */
  520. public static function canImagesBeIncludedInScheduledReports()
  521. {
  522. $gdInfo = gd_info();
  523. return
  524. stristr(php_uname(), self::IMAGES_GENERATED_ONLY_FOR_OS) &&
  525. strpos( phpversion(), self::IMAGES_GENERATED_FOR_PHP) !== false &&
  526. strpos( $gdInfo['GD Version'], self::IMAGES_GENERATED_FOR_GD) !== false;
  527. }
  528. public static $geoIpDbUrl = 'http://piwik-team.s3.amazonaws.com/GeoIP.dat.gz';
  529. public static $geoLiteCityDbUrl = 'http://piwik-team.s3.amazonaws.com/GeoLiteCity.dat.gz';
  530. public static function downloadGeoIpDbs()
  531. {
  532. $geoIpOutputDir = PIWIK_INCLUDE_PATH . '/tests/lib/geoip-files';
  533. self::downloadAndUnzip(self::$geoIpDbUrl, $geoIpOutputDir, 'GeoIP.dat');
  534. self::downloadAndUnzip(self::$geoLiteCityDbUrl, $geoIpOutputDir, 'GeoIPCity.dat');
  535. }
  536. public static function downloadAndUnzip($url, $outputDir, $filename)
  537. {
  538. $bufferSize = 1024 * 1024;
  539. if (!is_dir($outputDir)) {
  540. mkdir($outputDir);
  541. }
  542. $deflatedOut = $outputDir . '/' . $filename;
  543. $outfileName = $deflatedOut . '.gz';
  544. if (file_exists($deflatedOut)) {
  545. return;
  546. }
  547. $dump = fopen($url, 'rb');
  548. $outfile = fopen($outfileName, 'wb');
  549. $bytesRead = 0;
  550. while (!feof($dump)) {
  551. fwrite($outfile, fread($dump, $bufferSize), $bufferSize);
  552. $bytesRead += $bufferSize;
  553. }
  554. fclose($dump);
  555. fclose($outfile);
  556. // unzip the dump
  557. exec("gunzip -c \"" . $outfileName . "\" > \"$deflatedOut\"", $output, $return);
  558. if ($return !== 0) {
  559. Log::info("gunzip failed with file that has following contents:");
  560. Log::info(file_get_contents($outfile));
  561. throw new Exception("gunzip failed($return): " . implode("\n", $output));
  562. }
  563. }
  564. protected static function executeLogImporter($logFile, $options)
  565. {
  566. $python = self::getPythonBinary();
  567. // create the command
  568. $cmd = $python
  569. . ' "' . PIWIK_INCLUDE_PATH . '/misc/log-analytics/import_logs.py" ' # script loc
  570. . '-ddd ' // debug
  571. . '--url="' . self::getRootUrl() . 'tests/PHPUnit/proxy/" ' # proxy so that piwik uses test config files
  572. ;
  573. foreach ($options as $name => $value) {
  574. $cmd .= $name;
  575. if ($value !== false) {
  576. $cmd .= '="' . $value . '"';
  577. }
  578. $cmd .= ' ';
  579. }
  580. $cmd .= '"' . $logFile . '" 2>&1';
  581. // run the command
  582. exec($cmd, $output, $result);
  583. if ($result !== 0) {
  584. throw new Exception("log importer failed: " . implode("\n", $output) . "\n\ncommand used: $cmd");
  585. }
  586. return $output;
  587. }
  588. public static function siteCreated($idSite)
  589. {
  590. return Db::fetchOne("SELECT COUNT(*) FROM " . Common::prefixTable('site') . " WHERE idsite = ?", array($idSite)) != 0;
  591. }
  592. public static function goalExists($idSite, $idGoal)
  593. {
  594. return Db::fetchOne("SELECT COUNT(*) FROM " . Common::prefixTable('goal') . " WHERE idgoal = ? AND idsite = ?", array($idGoal, $idSite)) != 0;
  595. }
  596. /**
  597. * Connects to MySQL w/o specifying a database.
  598. */
  599. public static function connectWithoutDatabase()
  600. {
  601. $dbConfig = Config::getInstance()->database;
  602. $oldDbName = $dbConfig['dbname'];
  603. $dbConfig['dbname'] = null;
  604. Db::createDatabaseObject($dbConfig);
  605. $dbConfig['dbname'] = $oldDbName;
  606. }
  607. /**
  608. * Sets up access instance.
  609. */
  610. public static function createAccessInstance()
  611. {
  612. Access::setSingletonInstance(null);
  613. Access::getInstance();
  614. Piwik::postEvent('Request.initAuthenticationObject');
  615. }
  616. public function dropDatabase($dbName = null)
  617. {
  618. $dbName = $dbName ?: $this->dbName;
  619. $this->log("Dropping database '$dbName'...");
  620. $config = _parse_ini_file(PIWIK_INCLUDE_PATH . '/config/config.ini.php', true);
  621. $originalDbName = $config['database']['dbname'];
  622. if ($dbName == $originalDbName
  623. && $dbName != 'piwik_tests'
  624. ) { // santity check
  625. throw new \Exception("Trying to drop original database '$originalDbName'. Something's wrong w/ the tests.");
  626. }
  627. DbHelper::dropDatabase($dbName);
  628. }
  629. public function log($message)
  630. {
  631. if ($this->printToScreen) {
  632. echo $message . "\n";
  633. }
  634. }
  635. // NOTE: since API_Request does sanitization, API methods do not. when calling them, we must
  636. // sometimes do sanitization ourselves.
  637. public static function makeXssContent($type, $sanitize = false)
  638. {
  639. $result = "<script>$('body').html('$type XSS!');</script>";
  640. if ($sanitize) {
  641. $result = Common::sanitizeInputValue($result);
  642. }
  643. return $result;
  644. }
  645. }
  646. // TODO: remove when other plugins don't use BaseFixture
  647. class Test_Piwik_BaseFixture extends Fixture
  648. {
  649. }
  650. // needed by tests that use stored segments w/ the proxy index.php
  651. class Test_Access_OverrideLogin extends Access
  652. {
  653. public function getLogin()
  654. {
  655. return 'superUserLogin';
  656. }
  657. }