diff --git a/core/Tracker.php b/core/Tracker.php index 72bd3cd2891..bd72e049209 100644 --- a/core/Tracker.php +++ b/core/Tracker.php @@ -44,9 +44,6 @@ class Tracker const LENGTH_HEX_ID_STRING = 16; const LENGTH_BINARY_ID = 8; - protected static $forcedDateTime = null; - protected static $forcedIpString = null; - protected static $pluginsNotToLoad = array(); protected static $pluginsToLoad = array(); @@ -90,21 +87,9 @@ protected function outputAccessControlHeaders() public function clear() { - self::$forcedIpString = null; - self::$forcedDateTime = null; $this->stateValid = self::STATE_NOTHING_TO_NOTICE; } - public static function setForceIp($ipString) - { - self::$forcedIpString = $ipString; - } - - public static function setForceDateTime($dateTime) - { - self::$forcedDateTime = $dateTime; - } - /** * Do not load the specified plugins (used during testing, to disable Provider plugin) * @param array $plugins @@ -488,15 +473,13 @@ public static function getDatetimeFromTimestamp($timestamp) /** * Initialization + * @param Request $request */ protected function init(Request $request) { $this->loadTrackerPlugins($request); - $this->handleTrackingApi($request); $this->handleDisabledTracker(); $this->handleEmptyRequest($request); - - Common::printDebug("Current datetime: " . date("Y-m-d H:i:s", $request->getCurrentTimestamp())); } /** @@ -748,29 +731,6 @@ protected function getTokenAuth() return Common::getRequestVar('token_auth', false); } - /** - * This method allows to set custom IP + server time + visitor ID, when using Tracking API. - * These two attributes can be only set by the Super User (passing token_auth). - */ - protected function handleTrackingApi(Request $request) - { - if (!$request->isAuthenticated()) { - return; - } - - // Custom IP to use for this visitor - $customIp = $request->getParam('cip'); - if (!empty($customIp)) { - $this->setForceIp($customIp); - } - - // Custom server date time to use - $customDatetime = $request->getParam('cdt'); - if (!empty($customDatetime)) { - $this->setForceDateTime($customDatetime); - } - } - public static function setTestEnvironment($args = null, $requestMethod = null) { if (is_null($args)) { @@ -816,18 +776,6 @@ public static function setTestEnvironment($args = null, $requestMethod = null) \Piwik\Plugins\PrivacyManager\IPAnonymizer::activate(); } - // Custom IP to use for this visitor - $customIp = Common::getRequestVar('cip', false, null, $args); - if (!empty($customIp)) { - self::setForceIp($customIp); - } - - // Custom server date time to use - $customDatetime = Common::getRequestVar('cdt', false, null, $args); - if (!empty($customDatetime)) { - self::setForceDateTime($customDatetime); - } - $pluginsDisabled = array('Provider'); // Disable provider plugin, because it is so slow to do many reverse ip lookups @@ -870,8 +818,7 @@ protected function trackRequest($params, $tokenAuth) try { if ($this->isVisitValid()) { - $request->setForceDateTime(self::$forcedDateTime); - $request->setForceIp(self::$forcedIpString); + Common::printDebug("Current datetime: " . date("Y-m-d H:i:s", $request->getCurrentTimestamp())); $visit = $this->getNewVisitObject(); $visit->setRequest($request); diff --git a/core/Tracker/Request.php b/core/Tracker/Request.php index 212abbd0d26..aad200660f3 100644 --- a/core/Tracker/Request.php +++ b/core/Tracker/Request.php @@ -35,6 +35,8 @@ class Request const UNKNOWN_RESOLUTION = 'unknown'; + const CUSTOM_TIMESTAMP_DOES_NOT_REQUIRE_TOKENAUTH_WHEN_NEWER_THAN = 14400; // 4 hours + /** * @param $params * @param bool|string $tokenAuth @@ -47,7 +49,6 @@ public function __construct($params, $tokenAuth = false) $this->params = $params; $this->tokenAuth = $tokenAuth; $this->timestamp = time(); - $this->enforcedIp = false; // When the 'url' and referrer url parameter are not given, we might be in the 'Simple Image Tracker' mode. // The URL can default to the Referrer, which will be in this case @@ -319,13 +320,54 @@ public function getParams() public function getCurrentTimestamp() { + $cdt = $this->getCustomTimestamp(); + if(!empty($cdt)) { + return $cdt; + } return $this->timestamp; } - protected function isTimestampValid($time) + protected function getCustomTimestamp() + { + $cdt = $this->getParam('cdt'); + if (empty($cdt)) { + return false; + } + if (!is_numeric($cdt)) { + $cdt = strtotime($cdt); + } + if (!$this->isTimestampValid($cdt, $this->timestamp)) { + Common::printDebug(sprintf("Datetime %s is not valid", date("Y-m-d H:i:m", $cdt))); + return false; + } + + // If timestamp in the past, token_auth is required + $timeFromNow = $this->timestamp - $cdt; + $isTimestampRecent = $timeFromNow < self::CUSTOM_TIMESTAMP_DOES_NOT_REQUIRE_TOKENAUTH_WHEN_NEWER_THAN; + if (!$isTimestampRecent) { + if(!$this->isAuthenticated()) { + Common::printDebug(sprintf("Custom timestamp is %s seconds old, requires &token_auth...", $timeFromNow)); + Common::printDebug("WARN: Tracker API 'cdt' was used with invalid token_auth"); + return false; + } + } + return $cdt; + } + + /** + * Returns true if the timestamp is valid ie. timestamp is sometime in the last 10 years and is not in the future. + * + * @param $time int Timestamp to test + * @param $now int Current timestamp + * @return bool + */ + protected function isTimestampValid($time, $now = null) { - return $time <= $this->getCurrentTimestamp() - && $time > $this->getCurrentTimestamp() - 10 * 365 * 86400; + if(empty($now)) { + $now = $this->getCurrentTimestamp(); + } + return $time <= $now + && $time > $now - 10 * 365 * 86400; } public function getIdSite() @@ -521,33 +563,11 @@ public function getVisitorId() public function getIp() { - if (!empty($this->enforcedIp)) { - $ipString = $this->enforcedIp; - } else { - $ipString = IP::getIpFromHeader(); - } - + $ipString = $this->getIpString(); $ip = IP::P2N($ipString); return $ip; } - public function setForceIp($ip) - { - if (!empty($ip)) { - $this->enforcedIp = $ip; - } - } - - public function setForceDateTime($dateTime) - { - if (!is_numeric($dateTime)) { - $dateTime = strtotime($dateTime); - } - if (!empty($dateTime)) { - $this->timestamp = $dateTime; - } - } - public function getForcedUserId() { $userId = $this->getParam('uid'); @@ -611,4 +631,23 @@ public function getUserIdHashed($userId) { return substr( sha1( $userId ), 0, 16); } + + /** + * @return mixed|string + * @throws Exception + */ + private function getIpString() + { + $cip = $this->getParam('cip'); + + if(empty($cip)) { + return IP::getIpFromHeader(); + } + + if(!$this->isAuthenticated()) { + Common::printDebug("WARN: Tracker API 'cip' was used with invalid token_auth"); + return IP::getIpFromHeader(); + } + return $cip; + } } diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index 0ce45c3659d..c8fb12d3897 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -467,6 +467,7 @@ private function printVisitorInformation() $debugVisitInfo = $this->visitorInfo; $debugVisitInfo['idvisitor'] = bin2hex($debugVisitInfo['idvisitor']); $debugVisitInfo['config_id'] = bin2hex($debugVisitInfo['config_id']); + $debugVisitInfo['location_ip'] = IP::N2P($debugVisitInfo['location_ip']); Common::printDebug($debugVisitInfo); } diff --git a/core/testMinimumPhpVersion.php b/core/testMinimumPhpVersion.php index 542279f8723..8fcface7f81 100644 --- a/core/testMinimumPhpVersion.php +++ b/core/testMinimumPhpVersion.php @@ -91,7 +91,11 @@ function Piwik_ExitWithMessage($message, $optionalTrace = false, $optionalLinks { if (!headers_sent()) { header('Content-Type: text/html; charset=utf-8'); - header('HTTP/1.1 500 Internal Server Error'); + + $isInternalServerError = preg_match('/(sql|database|mysql)/i', $message); + if($isInternalServerError) { + header('HTTP/1.1 500 Internal Server Error'); + } } if ($optionalTrace) { diff --git a/misc/log-analytics/README.md b/misc/log-analytics/README.md index 6c4aadf6752..a9d53d8dfc1 100644 --- a/misc/log-analytics/README.md +++ b/misc/log-analytics/README.md @@ -20,7 +20,7 @@ and will not track bots, static files, or error requests. If you wish to track all requests the following command would be used: - python /path/to/piwik/misc/log-analytics/import_logs.py --url=http://mysite/piwik/ access.log --idsite=1234 --recorders=4 --enable-http-errors --enable-http-redirects --enable-static --enable-bots + python /path/to/piwik/misc/log-analytics/import_logs.py --url=http://mysite/piwik/ --idsite=1234 --recorders=4 --enable-http-errors --enable-http-redirects --enable-static --enable-bots access.log ## How to import your logs automatically every day? diff --git a/plugins/CoreConsole/Commands/TestsRun.php b/plugins/CoreConsole/Commands/TestsRun.php index 41783370576..de32f0b5347 100644 --- a/plugins/CoreConsole/Commands/TestsRun.php +++ b/plugins/CoreConsole/Commands/TestsRun.php @@ -90,7 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private function executeTestFile($testFile, $options, $command, OutputInterface $output) { $params = $options . " " . $testFile; - $cmd = sprintf("cd %s/tests/PHPUnit && %s %s", PIWIK_DOCUMENT_ROOT, $command, $params); + $cmd = $this->getCommand($command, $params); $output->writeln('Executing command: ' . $cmd . ''); passthru($cmd); $output->writeln(""); @@ -104,11 +104,12 @@ private function executeTestGroups($suite, $groups, $options, $command, OutputIn foreach ($groups as $group) { $params = '--group ' . $group . ' ' . str_replace('%group%', $group, $options); + if (!empty($suite)) { $params .= ' --testsuite ' . $suite; } - - $cmd = sprintf('cd %s/tests/PHPUnit && %s %s', PIWIK_DOCUMENT_ROOT, $command, $params); + + $cmd = $this->getCommand($command, $params); $output->writeln('Executing command: ' . $cmd . ''); passthru($cmd); $output->writeln(""); @@ -119,4 +120,15 @@ private function getTestsGroups() { return array('Core', 'Plugins', 'UI'); } + + /** + * @param $command + * @param $params + * @return string + */ + private function getCommand($command, $params) + { + $cmd = sprintf('cd %s/tests/PHPUnit && %s %s', PIWIK_DOCUMENT_ROOT, $command, $params); + return $cmd; + } } \ No newline at end of file diff --git a/plugins/UserSettings/tests/Fixtures/LanguageFixture.php b/plugins/UserSettings/tests/Fixtures/LanguageFixture.php index dc6b4fcb0b2..6cbd9d8343f 100644 --- a/plugins/UserSettings/tests/Fixtures/LanguageFixture.php +++ b/plugins/UserSettings/tests/Fixtures/LanguageFixture.php @@ -54,6 +54,7 @@ private function trackVisits() { $this->dateTime, $defaultInit = false ); + $tracker->setTokenAuth(self::getTokenAuth()); $hour = 1; foreach ($this->getBrowserLangs() as $browserLang) { diff --git a/tests/LocalTracker.php b/tests/LocalTracker.php index afa0a6a4bcc..ecddbe5c9f9 100755 --- a/tests/LocalTracker.php +++ b/tests/LocalTracker.php @@ -45,8 +45,6 @@ protected function sendRequest($url, $method = 'GET', $data = null, $force = fal // unset cached values Cache::$trackerCache = null; - Tracker::setForceIp(null); - Tracker::setForceDateTime(null); // save some values $plugins = Config::getInstance()->Plugins['Plugins']; diff --git a/tests/PHPUnit/Fixtures/OneVisitWithAbnormalPageviewUrls.php b/tests/PHPUnit/Fixtures/OneVisitWithAbnormalPageviewUrls.php index 56c3e294045..22999000ee4 100644 --- a/tests/PHPUnit/Fixtures/OneVisitWithAbnormalPageviewUrls.php +++ b/tests/PHPUnit/Fixtures/OneVisitWithAbnormalPageviewUrls.php @@ -41,7 +41,7 @@ private function trackVisits() { $dateTime = $this->dateTime; $idSite = $this->idSite; - $t = self::getTracker($idSite, $dateTime, $defaultInit = true, $useThirdPartyCookie = 1); + $t = self::getTracker($idSite, $dateTime, $defaultInit = true); $t->setUrlReferrer('http://www.google.com/search?q=piwik'); $t->setUrl('http://example.org/foo/bar.html'); diff --git a/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php b/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php index 9682dd086ba..1985b9090cc 100644 --- a/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php +++ b/tests/PHPUnit/Fixtures/SomeVisitsCustomVariablesCampaignsNotHeuristics.php @@ -63,6 +63,7 @@ private function trackVisits() // Create a new Tracker object, with different attributes $t2 = self::getTracker($idSite, $dateTime, $defaultInit = false); + $t2->setTokenAuth(self::getTokenAuth()); // Make sure the ID is different at first $visitorId2 = $t2->getVisitorId(); diff --git a/tests/PHPUnit/Integration/Tracker/ActionTest.php b/tests/PHPUnit/Integration/Tracker/ActionTest.php index 1246fb15f64..17da150bd69 100644 --- a/tests/PHPUnit/Integration/Tracker/ActionTest.php +++ b/tests/PHPUnit/Integration/Tracker/ActionTest.php @@ -22,6 +22,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later * * @group Core + * @group ActionTest */ class Core_Tracker_ActionTest extends IntegrationTestCase { diff --git a/tests/PHPUnit/Integration/Tracker/Visit2Test.php b/tests/PHPUnit/Integration/Tracker/Visit2Test.php index e28c3ba410d..a5b3c0541cd 100644 --- a/tests/PHPUnit/Integration/Tracker/Visit2Test.php +++ b/tests/PHPUnit/Integration/Tracker/Visit2Test.php @@ -135,6 +135,7 @@ protected function updateExistingVisit($valuesToUpdate) /** * @group Core + * @group VisitTest */ class VisitTest extends IntegrationTestCase { @@ -157,7 +158,6 @@ public function tearDown() public function test_handleNewVisitWithoutConversion_shouldTriggerDimensions() { $request = new \Piwik\Tracker\Request(array()); - $request->setForceIp('127.0.0.1'); $visitor = new \Piwik\Tracker\Visitor($request, ''); $visit = new FakeTrackerVisit($request); @@ -180,7 +180,6 @@ public function test_handleNewVisitWithoutConversion_shouldTriggerDimensions() public function test_handleNewVisitWithConversion_shouldTriggerDimensions() { $request = new \Piwik\Tracker\Request(array()); - $request->setForceIp('127.0.0.1'); $visitor = new \Piwik\Tracker\Visitor($request, ''); $visit = new FakeTrackerVisit($request); @@ -199,7 +198,6 @@ public function test_handleNewVisitWithConversion_shouldTriggerDimensions() public function test_handleExistingVisitWithoutConversion_shouldTriggerDimensions() { $request = new \Piwik\Tracker\Request(array()); - $request->setForceIp('127.0.0.1'); $visitor = new \Piwik\Tracker\Visitor($request, ''); $visit = new FakeTrackerVisit($request); @@ -223,7 +221,6 @@ public function test_handleExistingVisitWithoutConversion_shouldTriggerDimension public function test_handleExistingVisitWithConversion_shouldTriggerDimensions() { $request = new \Piwik\Tracker\Request(array()); - $request->setForceIp('127.0.0.1'); $visitor = new \Piwik\Tracker\Visitor($request, ''); $visit = new FakeTrackerVisit($request); diff --git a/tests/PHPUnit/System/BackwardsCompatibility1XTest.php b/tests/PHPUnit/System/BackwardsCompatibility1XTest.php index 5b27b2e2796..0ed7dc208d2 100644 --- a/tests/PHPUnit/System/BackwardsCompatibility1XTest.php +++ b/tests/PHPUnit/System/BackwardsCompatibility1XTest.php @@ -43,19 +43,31 @@ public static function setUpBeforeClass() Db::query("TRUNCATE TABLE " . Common::prefixTable($table)); } - // add two visits from same visitor on dec. 29 - $t = Fixture::getTracker(1, '2012-12-29 01:01:30', $defaultInit = true); + self::trackTwoVisitsOnSameDay(); + + // launch archiving + VisitFrequencyApi::getInstance()->get(1, 'year', '2012-12-29'); + } + + + /** + * add two visits from same visitor on dec. 29 + */ + private static function trackTwoVisitsOnSameDay() + { + $t = Fixture::getTracker(1, '2012-12-29 01:01:30', $defaultInit = true, $useLocal = true); + $t->enableBulkTracking(); + $t->setUrl('http://site.com/index.htm'); $t->setIp('136.5.3.2'); - Fixture::checkResponse($t->doTrackPageView('incredible title!')); + $t->doTrackPageView('incredible title!'); $t->setForceVisitDateTime('2012-12-29 03:01:30'); $t->setUrl('http://site.com/other/index.htm'); $t->DEBUG_APPEND_URL = '&_idvc=2'; // make sure visit is marked as returning - Fixture::checkResponse($t->doTrackPageView('other incredible title!')); + $t->doTrackPageView('other incredible title!'); - // launch archiving - VisitFrequencyApi::getInstance()->get(1, 'year', '2012-12-29'); + $t->doBulkTrack(); } /** diff --git a/tests/README.md b/tests/README.md index 1e1299eae77..8a418cb143c 100644 --- a/tests/README.md +++ b/tests/README.md @@ -161,7 +161,6 @@ By default tests running on Travis CI will log all messages of at least `INFO` l Note: `DEBUG` and `VERBOSE` messages are not logged by default (to keep Travis page loading fast). At any time you can temporarirly enable logging by [modifying this file](https://github.com/piwik/piwik/blob/master/tests/PHPUnit/config.ini.travis.php#L23-27) and changing `log_level = info` to `log_level = debug` or `log_level = verbose`. - ### Screenshot tests build artifacts The screenshot tests generated by the continuous integration server are uploaded in [builds-artifacts.piwik.org/ui-tests.master/](http://builds-artifacts.piwik.org/ui-tests.master/?C=M;O=D) @@ -171,6 +170,12 @@ The screenshot tests generated by the continuous integration server are uploaded See [tests/README.troubleshooting.md](https://github.com/piwik/piwik/blob/master/tests/README.troubleshooting.md) for troubleshooting the tests. ## Advanced users + +### Debugging tests + +As a software developer writing tests it can be useful to be able to set breakpoints and debug while running tests. If you use Phpstorm [read this answer](http://stackoverflow.com/a/14998884/3759928) to learn to configure Phpstorm with the PHPUnit from Composer. + + ### Benchmarks See [tests/PHPUnit/Benchmarks/README.md](https://github.com/piwik/piwik/blob/master/tests/PHPUnit/Benchmarks/README.md) to learn about running Benchmark tests. diff --git a/tests/README.testing-data.md b/tests/README.testing-data.md index 5ab7b4a67d3..63431a39668 100644 --- a/tests/README.testing-data.md +++ b/tests/README.testing-data.md @@ -5,7 +5,7 @@ As a developer it may be useful to generate test data. Follow these steps: 3. Create a Goal eg. URL Contains "blog" 4. Import data from an anonimized test log file in piwik/tests/resources/ directory. Run the following command: - $ python /home/piwik/misc/log-analytics/import_logs.py --url=http://localhost/path/ /path/to/piwik/tests/resources/access.log-dev-anon-9-days-nov-2012.log.bz2 --idsite=1 --enable-http-errors --enable-http-redirects --enable-static --enable-bots + $ python /home/piwik/misc/log-analytics/import_logs.py --url=http://localhost/path/ --idsite=1 --enable-http-errors --enable-http-redirects --enable-static --enable-bots /path/to/piwik/tests/resources/access.log-dev-anon-9-days-nov-2012.log.bz2 This will import 9 days worth of data from Nov 20th-Nov 29th 2012.