Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Steur <thomas.steur@googlemail.com>2014-12-04 05:04:02 +0300
committerThomas Steur <thomas.steur@googlemail.com>2014-12-04 05:04:02 +0300
commit9d71fc8e92e5b434fd69c7ab4b83a69169064cf3 (patch)
tree8cb2798746e4defb1a978cd758df72006ec419ae /plugins/BulkTracking
parent784b738f9c4a92c42a9d8e6b85c28a82a3af0a2f (diff)
Tracker refactoring
Diffstat (limited to 'plugins/BulkTracking')
-rw-r--r--plugins/BulkTracking/.gitignore1
-rw-r--r--plugins/BulkTracking/BulkTracking.php84
-rw-r--r--plugins/BulkTracking/README.md18
-rw-r--r--plugins/BulkTracking/Tracker/Handler.php82
-rw-r--r--plugins/BulkTracking/Tracker/Requests.php111
-rw-r--r--plugins/BulkTracking/Tracker/Response.php77
-rw-r--r--plugins/BulkTracking/screenshots/.gitkeep0
-rw-r--r--plugins/BulkTracking/tests/Fixtures/SimpleFixtureTrackFewVisits.php77
-rw-r--r--plugins/BulkTracking/tests/Framework/Mock/Tracker/Requests.php42
-rw-r--r--plugins/BulkTracking/tests/Framework/Mock/Tracker/Response.php21
-rw-r--r--plugins/BulkTracking/tests/Framework/TestCase/BulkTrackingTestCase.php96
-rw-r--r--plugins/BulkTracking/tests/Integration/BulkTrackingTest.php147
-rw-r--r--plugins/BulkTracking/tests/Integration/HandlerTest.php161
-rw-r--r--plugins/BulkTracking/tests/Integration/RequestsTest.php127
-rw-r--r--plugins/BulkTracking/tests/Integration/TrackerTest.php133
-rw-r--r--plugins/BulkTracking/tests/System/TrackerTest.php53
-rw-r--r--plugins/BulkTracking/tests/Unit/RequestsTest.php172
-rw-r--r--plugins/BulkTracking/tests/Unit/ResponseTest.php93
18 files changed, 1495 insertions, 0 deletions
diff --git a/plugins/BulkTracking/.gitignore b/plugins/BulkTracking/.gitignore
new file mode 100644
index 0000000000..c8c9480010
--- /dev/null
+++ b/plugins/BulkTracking/.gitignore
@@ -0,0 +1 @@
+tests/System/processed/*xml \ No newline at end of file
diff --git a/plugins/BulkTracking/BulkTracking.php b/plugins/BulkTracking/BulkTracking.php
new file mode 100644
index 0000000000..b55a681030
--- /dev/null
+++ b/plugins/BulkTracking/BulkTracking.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\BulkTracking;
+use Piwik\Plugins\BulkTracking\Tracker\Handler;
+use Piwik\Plugins\BulkTracking\Tracker\Requests;
+use Piwik\Tracker\RequestSet;
+
+class BulkTracking extends \Piwik\Plugin
+{
+ /**
+ * @var Requests
+ */
+ private $requests;
+
+ /**
+ * @see Piwik\Plugin::getListHooksRegistered
+ */
+ public function getListHooksRegistered()
+ {
+ return array(
+ 'Tracker.newHandler' => 'setHandlerIfBulkRequest',
+ 'Tracker.initRequestSet' => 'initRequestSet',
+ );
+ }
+
+ public function setRequests(Requests $requests)
+ {
+ $this->requests = $requests;
+ }
+
+ public function initRequestSet(RequestSet $requestSet)
+ {
+ if ($this->isUsingBulkRequest()) {
+
+ $bulk = $this->buildBulkRequests();
+
+ list($requests, $token) = $bulk->initRequestsAndTokenAuth($bulk->getRawBulkRequest());
+
+ if ($bulk->requiresAuthentication()) {
+ $bulk->authenticateRequests($requests);
+ }
+
+ if (!$requestSet->getTokenAuth()) {
+ $requestSet->setTokenAuth($token);
+ }
+
+ $requestSet->setRequests($requests);
+ }
+ }
+
+ public function setHandlerIfBulkRequest(&$handler)
+ {
+ if (!is_null($handler)) {
+ return;
+ }
+
+ if ($this->isUsingBulkRequest()) {
+ $handler = new Handler();
+ }
+ }
+
+ private function isUsingBulkRequest()
+ {
+ $requests = $this->buildBulkRequests();
+ $rawData = $requests->getRawBulkRequest();
+
+ return $requests->isUsingBulkRequest($rawData);
+ }
+
+ private function buildBulkRequests()
+ {
+ if (!is_null($this->requests)) {
+ return $this->requests;
+ }
+
+ return new Requests();
+ }
+}
diff --git a/plugins/BulkTracking/README.md b/plugins/BulkTracking/README.md
new file mode 100644
index 0000000000..ecb28c2d7b
--- /dev/null
+++ b/plugins/BulkTracking/README.md
@@ -0,0 +1,18 @@
+# Piwik BulkTracking Plugin
+
+## Description
+
+Add your plugin description here.
+
+## FAQ
+
+__My question?__
+My answer
+
+## Changelog
+
+Here goes the changelog text.
+
+## Support
+
+Please direct any feedback to ... \ No newline at end of file
diff --git a/plugins/BulkTracking/Tracker/Handler.php b/plugins/BulkTracking/Tracker/Handler.php
new file mode 100644
index 0000000000..e260237093
--- /dev/null
+++ b/plugins/BulkTracking/Tracker/Handler.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+namespace Piwik\Plugins\BulkTracking\Tracker;
+
+use Piwik\Tracker;
+use Piwik\Tracker\RequestSet;
+use Piwik\Tracker\TrackerConfig;
+use Exception;
+
+class Handler extends Tracker\Handler
+{
+ private $transactionId = null;
+
+ public function __construct()
+ {
+ $this->setResponse(new Response());
+ }
+
+ public function onStartTrackRequests(Tracker $tracker, RequestSet $requestSet)
+ {
+ if ($this->isTransactionSupported()) {
+ $this->beginTransaction();
+ }
+ }
+
+ public function onAllRequestsTracked(Tracker $tracker, RequestSet $requestSet)
+ {
+ $this->commitTransaction();
+
+ // Do not run schedule task if we are importing logs or doing custom tracking (as it could slow down)
+ }
+
+ public function onException(Tracker $tracker, RequestSet $requestSet, Exception $e)
+ {
+ $this->rollbackTransaction();
+ parent::onException($tracker, $requestSet, $e);
+ }
+
+ private function beginTransaction()
+ {
+ if (empty($this->transactionId)) {
+ $this->transactionId = $this->getDb()->beginTransaction();
+ }
+ }
+
+ private function commitTransaction()
+ {
+ if (!empty($this->transactionId)) {
+ $this->getDb()->commit($this->transactionId);
+ $this->transactionId = null;
+ }
+ }
+
+ private function rollbackTransaction()
+ {
+ if (!empty($this->transactionId)) {
+ $this->getDb()->rollback($this->transactionId);
+ $this->transactionId = null;
+ }
+ }
+
+ private function getDb()
+ {
+ return Tracker::getDatabase();
+ }
+
+ /**
+ * @return bool
+ */
+ private function isTransactionSupported()
+ {
+ return (bool) TrackerConfig::getConfigValue('bulk_requests_use_transaction');
+ }
+
+}
diff --git a/plugins/BulkTracking/Tracker/Requests.php b/plugins/BulkTracking/Tracker/Requests.php
new file mode 100644
index 0000000000..af4eb23a15
--- /dev/null
+++ b/plugins/BulkTracking/Tracker/Requests.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\BulkTracking\Tracker;
+
+use Exception;
+use Piwik\Common;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\TrackerConfig;
+
+class Requests
+{
+
+ public function requiresAuthentication()
+ {
+ $requiresAuth = TrackerConfig::getConfigValue('bulk_requests_require_authentication');
+
+ return !empty($requiresAuth);
+ }
+
+ /**
+ * @param Request[] $requests
+ * @throws Exception
+ */
+ public function authenticateRequests($requests)
+ {
+ foreach ($requests as $request) {
+ $this->checkTokenAuthNotEmpty($request->getTokenAuth());
+
+ if (!$request->isAuthenticated()) {
+ $msg = sprintf("token_auth specified does not have Admin permission for idsite=%s", $request->getIdSite());
+ throw new Exception($msg);
+ }
+ }
+ }
+
+ private function checkTokenAuthNotEmpty($token)
+ {
+ if (empty($token)) {
+ throw new Exception("token_auth must be specified when using Bulk Tracking Import. "
+ . " See <a href='http://developer.piwik.org/api-reference/tracking-api'>Tracking Doc</a>");
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function getRawBulkRequest()
+ {
+ return file_get_contents("php://input");
+ }
+
+ public function isUsingBulkRequest($rawData)
+ {
+ if (!empty($rawData)) {
+ return strpos($rawData, '"requests"') || strpos($rawData, "'requests'");
+ }
+
+ return false;
+ }
+
+ public function getRequestsArrayFromBulkRequest($rawData)
+ {
+ $rawData = trim($rawData);
+ $rawData = Common::sanitizeLineBreaks($rawData);
+
+ // POST data can be array of string URLs or array of arrays w/ visit info
+ $jsonData = json_decode($rawData, $assoc = true);
+
+ $tokenAuth = Common::getRequestVar('token_auth', false, 'string', $jsonData);
+
+ $requests = array();
+ if (isset($jsonData['requests'])) {
+ $requests = $jsonData['requests'];
+ }
+
+ return array($requests, $tokenAuth);
+ }
+
+ public function initRequestsAndTokenAuth($rawData)
+ {
+ list($requests, $tokenAuth) = $this->getRequestsArrayFromBulkRequest($rawData);
+
+ $validRequests = array();
+
+ if (!empty($requests)) {
+
+ foreach ($requests as $index => $request) {
+ // if a string is sent, we assume its a URL and try to parse it
+ if (is_string($request)) {
+ $params = array();
+
+ $url = @parse_url($request);
+ if (!empty($url['query'])) {
+ @parse_str($url['query'], $params);
+ $validRequests[] = new Request($params, $tokenAuth);
+ }
+ } else {
+ $validRequests[] = new Request($request, $tokenAuth);
+ }
+ }
+ }
+
+ return array($validRequests, $tokenAuth);
+ }
+}
diff --git a/plugins/BulkTracking/Tracker/Response.php b/plugins/BulkTracking/Tracker/Response.php
new file mode 100644
index 0000000000..fd3e304a5e
--- /dev/null
+++ b/plugins/BulkTracking/Tracker/Response.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\BulkTracking\Tracker;
+
+use Exception;
+use Piwik\Common;
+use Piwik\Tracker;
+
+class Response extends Tracker\Response
+{
+ /**
+ * Echos an error message & other information, then exits.
+ *
+ * @param Tracker $tracker
+ * @param Exception $e
+ * @param int $statusCode eg 500
+ */
+ public function outputException(Tracker $tracker, Exception $e, $statusCode)
+ {
+ Common::sendResponseCode($statusCode);
+
+ $this->logExceptionToErrorLog($e);
+
+ $result = $this->formatException($tracker, $e);
+
+ echo json_encode($result);
+ }
+
+ public function outputResponse(Tracker $tracker)
+ {
+ if ($this->hasAlreadyPrintedOutput()) {
+ return;
+ }
+
+ $result = $this->formatResponse($tracker);
+
+ echo json_encode($result);
+ }
+
+ public function getOutput()
+ {
+ Common::sendHeader('Content-Type: application/json');
+
+ return parent::getOutput();
+ }
+
+ private function formatException(Tracker $tracker, Exception $e)
+ {
+ // when doing bulk tracking we return JSON so the caller will know how many succeeded
+ $result = array(
+ 'status' => 'error',
+ 'tracked' => $tracker->getCountOfLoggedRequests()
+ );
+
+ // send error when in debug mode
+ if ($tracker->isDebugModeEnabled()) {
+ $result['message'] = $this->getMessageFromException($e);
+ }
+
+ return $result;
+ }
+
+ private function formatResponse(Tracker $tracker)
+ {
+ return array(
+ 'status' => 'success',
+ 'tracked' => $tracker->getCountOfLoggedRequests()
+ );
+ }
+
+}
diff --git a/plugins/BulkTracking/screenshots/.gitkeep b/plugins/BulkTracking/screenshots/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/BulkTracking/screenshots/.gitkeep
diff --git a/plugins/BulkTracking/tests/Fixtures/SimpleFixtureTrackFewVisits.php b/plugins/BulkTracking/tests/Fixtures/SimpleFixtureTrackFewVisits.php
new file mode 100644
index 0000000000..aac9c14a2a
--- /dev/null
+++ b/plugins/BulkTracking/tests/Fixtures/SimpleFixtureTrackFewVisits.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+namespace Piwik\Plugins\BulkTracking\tests\Fixtures;
+
+use Piwik\Date;
+use Piwik\Tests\Framework\Fixture;
+
+/**
+ * Generates tracker testing data for our TrackerTest
+ *
+ * This Simple fixture adds one website and tracks one visit with couple pageviews and an ecommerce conversion
+ */
+class SimpleFixtureTrackFewVisits extends Fixture
+{
+ public $dateTime = '2013-01-23 01:23:45';
+ public $idSite = 1;
+
+ public function setUp()
+ {
+ $this->setUpWebsite();
+ $this->trackFirstVisit();
+ $this->trackSecondVisit();
+ }
+
+ public function tearDown()
+ {
+ // empty
+ }
+
+ private function setUpWebsite()
+ {
+ if (!self::siteCreated($this->idSite)) {
+ $idSite = self::createWebsite($this->dateTime, $ecommerce = 1);
+ $this->assertSame($this->idSite, $idSite);
+ }
+ }
+
+ protected function trackFirstVisit()
+ {
+ $t = self::getTracker($this->idSite, $this->dateTime, $defaultInit = true);
+
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.1)->getDatetime());
+ $t->setUrl('http://example.com/');
+ self::checkResponse($t->doTrackPageView('Viewing homepage'));
+
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.2)->getDatetime());
+ $t->setUrl('http://example.com/sub/page');
+ self::checkResponse($t->doTrackPageView('Second page view'));
+
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.25)->getDatetime());
+ $t->addEcommerceItem($sku = 'SKU_ID', $name = 'Test item!', $category = 'Test & Category', $price = 777, $quantity = 33);
+ self::checkResponse($t->doTrackEcommerceOrder('TestingOrder', $grandTotal = 33 * 77));
+ }
+
+ protected function trackSecondVisit()
+ {
+ $t = self::getTracker($this->idSite, $this->dateTime, $defaultInit = true);
+ $t->setIp('56.11.55.73');
+
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.1)->getDatetime());
+ $t->setUrl('http://example.com/sub/page');
+ self::checkResponse($t->doTrackPageView('Viewing homepage'));
+
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.2)->getDatetime());
+ $t->setUrl('http://example.com/?search=this is a site search query');
+ self::checkResponse($t->doTrackPageView('Site search query'));
+
+ $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.3)->getDatetime());
+ $t->addEcommerceItem($sku = 'SKU_ID2', $name = 'A durable item', $category = 'Best seller', $price = 321);
+ self::checkResponse($t->doTrackEcommerceCartUpdate($grandTotal = 33 * 77));
+ }
+} \ No newline at end of file
diff --git a/plugins/BulkTracking/tests/Framework/Mock/Tracker/Requests.php b/plugins/BulkTracking/tests/Framework/Mock/Tracker/Requests.php
new file mode 100644
index 0000000000..c6c39c4ee9
--- /dev/null
+++ b/plugins/BulkTracking/tests/Framework/Mock/Tracker/Requests.php
@@ -0,0 +1,42 @@
+<?php
+/**
+* Piwik - free/libre analytics platform
+*
+* @link http://piwik.org
+* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+*/
+
+namespace Piwik\Plugins\BulkTracking\tests\Framework\Mock\Tracker;
+
+use Piwik\Tracker;
+
+class Requests extends \Piwik\Plugins\BulkTracking\Tracker\Requests
+{
+ private $rawData;
+ private $requiresAuth = false;
+
+ public function setRawData($rawData)
+ {
+ $this->rawData = $rawData;
+ }
+
+ public function getRawBulkRequest()
+ {
+ if (!is_null($this->rawData)) {
+ return $this->rawData;
+ }
+
+ return parent::getRawBulkRequest();
+ }
+
+ public function enableRequiresAuth()
+ {
+ $this->requiresAuth = true;
+ }
+
+ public function requiresAuthentication()
+ {
+ return $this->requiresAuth;
+ }
+
+}
diff --git a/plugins/BulkTracking/tests/Framework/Mock/Tracker/Response.php b/plugins/BulkTracking/tests/Framework/Mock/Tracker/Response.php
new file mode 100644
index 0000000000..e514745ddb
--- /dev/null
+++ b/plugins/BulkTracking/tests/Framework/Mock/Tracker/Response.php
@@ -0,0 +1,21 @@
+<?php
+/**
+* Piwik - free/libre analytics platform
+*
+* @link http://piwik.org
+* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+*/
+
+namespace Piwik\Plugins\BulkTracking\tests\Framework\Mock\Tracker;
+
+use Piwik\Tracker;
+use Exception;
+
+class Response extends \Piwik\Plugins\BulkTracking\Tracker\Response
+{
+ protected function logExceptionToErrorLog(Exception $e)
+ {
+ // prevent from writing to console in tests
+ }
+
+}
diff --git a/plugins/BulkTracking/tests/Framework/TestCase/BulkTrackingTestCase.php b/plugins/BulkTracking/tests/Framework/TestCase/BulkTrackingTestCase.php
new file mode 100644
index 0000000000..23b96776ae
--- /dev/null
+++ b/plugins/BulkTracking/tests/Framework/TestCase/BulkTrackingTestCase.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Framework\TestCase;
+
+use Piwik\Plugin;
+use Piwik\Plugins\BulkTracking\BulkTracking;
+use Piwik\Tests\Framework\Fixture;
+use Piwik\Plugins\BulkTracking\tests\Framework\Mock\Tracker\Requests;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Tracker\Handler as DefaultHandler;
+use Piwik\Tracker\RequestSet;
+
+/**
+ * @group BulkTracking
+ * @group BulkTrackingTest
+ * @group Plugins
+ * @group Tracker
+ */
+class BulkTrackingTestCase extends IntegrationTestCase
+{
+ /**
+ * @var BulkTracking
+ */
+ protected $bulk;
+
+ private $pluginBackup;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->bulk = new BulkTracking();
+
+ $this->pluginBackup = Plugin\Manager::getInstance()->getLoadedPlugin('BulkTracking');
+ Plugin\Manager::getInstance()->addLoadedPlugin('BulkTracking', $this->bulk);
+ }
+
+ public function tearDown()
+ {
+ Plugin\Manager::getInstance()->addLoadedPlugin('BulkTracking', $this->pluginBackup);
+ parent::tearDown();
+ }
+
+ protected function getSuperUserToken()
+ {
+ Fixture::createSuperUser(false);
+ return Fixture::getTokenAuth();
+ }
+
+ protected function injectRawDataToBulk($rawData, $requiresAuth = false)
+ {
+ $requests = new Requests();
+ $requests->setRawData($rawData);
+
+ if ($requiresAuth) {
+ $requests->enableRequiresAuth();
+ }
+
+ $this->bulk->setRequests($requests);
+ }
+
+ protected function initRequestSet($rawData, $requiresAuth = false, $initToken = null)
+ {
+ $requestSet = new RequestSet();
+
+ if (!is_null($initToken)) {
+ $requestSet->setTokenAuth($initToken);
+ }
+
+ $this->injectRawDataToBulk($rawData, $requiresAuth);
+
+ $this->bulk->initRequestSet($requestSet);
+
+ return $requestSet;
+ }
+
+ protected function getDummyRequest($token = null)
+ {
+ $params = array(array('idsite' => '1', 'rec' => '1'), array('idsite' => '2', 'rec' => '1'));
+ $params = array('requests' => $params);
+
+ if (!is_null($token)) {
+ $params['token_auth'] = $token;
+ }
+
+ $request = json_encode($params);
+
+ return $request;
+ }
+}
diff --git a/plugins/BulkTracking/tests/Integration/BulkTrackingTest.php b/plugins/BulkTracking/tests/Integration/BulkTrackingTest.php
new file mode 100644
index 0000000000..c495afcee1
--- /dev/null
+++ b/plugins/BulkTracking/tests/Integration/BulkTrackingTest.php
@@ -0,0 +1,147 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Integration;
+
+use Piwik\Plugin;
+use Piwik\Plugins\BulkTracking\tests\Framework\TestCase\BulkTrackingTestCase;
+use Piwik\Plugins\BulkTracking\Tracker\Handler;
+use Piwik\Tracker\Handler as DefaultHandler;
+use Piwik\Tracker\RequestSet;
+
+/**
+ * @group BulkTracking
+ * @group BulkTrackingTest
+ * @group Plugins
+ * @group Tracker
+ */
+class BulkTrackingTest extends BulkTrackingTestCase
+{
+ public function test_initRequestSet_shouldNotSetAnything_IfItIsActuallyNotUsingBulkRequest()
+ {
+ $requestSet = new RequestSet();
+ $this->bulk->initRequestSet($requestSet);
+
+ $this->assertEquals(array(), $requestSet->getRequests());
+ $this->assertEquals(false, $requestSet->getTokenAuth());
+ }
+
+ public function test_initRequestSet_shouldNotSetAnything_IfNotBulkRequestRawDataIsGiven()
+ {
+ $requestSet = $this->initRequestSet('invalid:requests');
+
+ $this->assertEquals(array(), $requestSet->getRequests());
+ $this->assertEquals(false, $requestSet->getTokenAuth());
+ }
+
+ public function test_initRequestSet_shouldInitialize_AsItIsABulkRequest()
+ {
+ $token = $this->getSuperUserToken();
+ $request = $this->getDummyRequest($token);
+
+ $requestSet = $this->initRequestSet($request);
+
+ $requests = $requestSet->getRequests();
+ $this->assertCount(2, $requests);
+ $this->assertEquals(array('idsite' => '1', 'rec' => '1'), $requests[0]->getParams());
+ $this->assertEquals(array('idsite' => '2', 'rec' => '1'), $requests[1]->getParams());
+ $this->assertEquals($token, $requestSet->getTokenAuth());
+ }
+
+ public function test_initRequestSet_shouldNotOverwriteAToken_IfOneIsAlreadySet()
+ {
+ $token = $this->getSuperUserToken();
+ $request = $this->getDummyRequest($token);
+
+ $requestSet = $this->initRequestSet($request, false, 'initialtoken');
+
+ $this->assertEquals('initialtoken', $requestSet->getTokenAuth());
+ $this->assertCount(2, $requestSet->getRequests());
+ }
+
+ public function test_initRequestSet_shouldNotFail_IfNoTokenProvided_AsAuthenticationIsDisabledByDefault()
+ {
+ $request = $this->getDummyRequest();
+
+ $requestSet = $this->initRequestSet($request);
+
+ $requests = $requestSet->getRequests();
+ $this->assertCount(2, $requests);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage token_auth must be specified when using Bulk Tracking Import
+ */
+ public function test_initRequestSet_shouldTriggerException_InCaseNoValidTokenProvidedAndAuthenticationIsRequired()
+ {
+ $request = $this->getDummyRequest(false);
+
+ $this->initRequestSet($request, true);
+ }
+
+ public function test_setHandlerIfBulkRequest_shouldSetBulkHandler_InCaseNoHandlerIsSetAndItIsABulkRequest()
+ {
+ $this->injectRawDataToBulk($this->getDummyRequest());
+
+ $handler = null;
+ $this->bulk->setHandlerIfBulkRequest($handler);
+
+ $this->assertTrue($handler instanceof Handler);
+ }
+
+ public function test_setHandlerIfBulkRequest_shouldNotSetAHandler_IfOneIsAlreadySetEvenIfItIsABulkRequest()
+ {
+ $this->injectRawDataToBulk($this->getDummyRequest());
+
+ $default = new DefaultHandler();
+ $handler = $default;
+
+ $this->bulk->setHandlerIfBulkRequest($default);
+
+ $this->assertSame($default, $handler);
+ }
+
+ public function test_setHandlerIfBulkRequest_shouldNotSetAHandler_IfItIsNotABulkRequest()
+ {
+ $this->injectRawDataToBulk('{"test":"not a bulk request"}');
+
+ $handler = null;
+
+ $this->bulk->setHandlerIfBulkRequest($handler);
+
+ $this->assertNull($handler);
+ }
+
+ public function test_getListHooksRegistered_shouldListenToNewTrackerEventAndCreateBulkHandler_IfBulkRequest()
+ {
+ $this->injectRawDataToBulk($this->getDummyRequest());
+
+ $handler = DefaultHandler\Factory::make();
+
+ $this->assertTrue($handler instanceof Handler);
+ }
+
+ public function test_getListHooksRegistered_shouldListenToNewTrackerEventAndNotCreateBulkHandler_IfNotBulkRequest()
+ {
+ $handler = DefaultHandler\Factory::make();
+
+ $this->assertTrue($handler instanceof DefaultHandler);
+ }
+
+ public function test_getListHooksRegistered_shouldListenToInitRequestSetEventAndInit_IfBulkRequest()
+ {
+ $this->injectRawDataToBulk($this->getDummyRequest());
+
+ $requestSet = new RequestSet();
+ $requestSet->initRequestsAndTokenAuth();
+
+ $this->assertCount(2, $requestSet->getRequests());
+ }
+
+}
diff --git a/plugins/BulkTracking/tests/Integration/HandlerTest.php b/plugins/BulkTracking/tests/Integration/HandlerTest.php
new file mode 100644
index 0000000000..1b2b46c8cb
--- /dev/null
+++ b/plugins/BulkTracking/tests/Integration/HandlerTest.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Integration;
+
+use Piwik\Exception\InvalidRequestParameterException;
+use Piwik\Exception\UnexpectedWebsiteFoundException;
+use Piwik\Tests\Framework\Fixture;
+use Piwik\Tests\Framework\Mock\Tracker\Response;
+use Piwik\Tests\Framework\Mock\Tracker\ScheduledTasksRunner;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Tracker;
+use Piwik\Plugins\BulkTracking\Tracker\Handler;
+use Piwik\Tests\Framework\Mock\Tracker\RequestSet;
+use Exception;
+
+/**
+ * @group HandlerTest
+ * @group Handler
+ * @group Tracker
+ */
+class HandlerTest extends IntegrationTestCase
+{
+ /**
+ * @var Handler
+ */
+ private $handler;
+
+ /**
+ * @var Response
+ */
+ private $response;
+
+ /**
+ * @var Tracker
+ */
+ private $tracker;
+
+ /**
+ * @var RequestSet
+ */
+ private $requestSet;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ Fixture::createWebsite('2014-01-01 00:00:00');
+ Tracker\Cache::deleteTrackerCache();
+
+ $this->response = new Response();
+ $this->handler = new Handler();
+ $this->handler->setResponse($this->response);
+ $this->tracker = new Tracker();
+ $this->requestSet = new RequestSet();
+ }
+
+ public function test_init_ShouldInitiateResponseInstance()
+ {
+ $this->handler->init($this->tracker, $this->requestSet);
+
+ $this->assertTrue($this->response->isInit);
+ $this->assertFalse($this->response->isResponseOutput);
+ $this->assertFalse($this->response->isSend);
+ }
+
+ public function test_finish_ShouldOutputAndSendResponse()
+ {
+ $response = $this->handler->finish($this->tracker, $this->requestSet);
+
+ $this->assertEquals('My Dummy Content', $response);
+
+ $this->assertFalse($this->response->isInit);
+ $this->assertFalse($this->response->isExceptionOutput);
+ $this->assertTrue($this->response->isResponseOutput);
+ $this->assertTrue($this->response->isSend);
+ }
+
+ public function test_onException_ShouldOutputAndSendResponse()
+ {
+ $this->executeOnException($this->buildException());
+
+ $this->assertFalse($this->response->isInit);
+ $this->assertFalse($this->response->isResponseOutput);
+ $this->assertTrue($this->response->isExceptionOutput);
+ $this->assertFalse($this->response->isSend);
+ }
+
+ public function test_onException_ShouldPassExceptionToResponse()
+ {
+ $exception = $this->buildException();
+
+ $this->executeOnException($exception);
+
+ $this->assertSame($exception, $this->response->exception);
+ $this->assertSame(500, $this->response->statusCode);
+ }
+
+ public function test_onException_ShouldSendStatusCode400IfUnexpectedWebsite()
+ {
+ $this->executeOnException(new UnexpectedWebsiteFoundException('test'));
+ $this->assertSame(400, $this->response->statusCode);
+ }
+
+ public function test_onException_ShouldSendStatusCode400IfInvalidRequestParameterException()
+ {
+ $this->executeOnException(new InvalidRequestParameterException('test'));
+ $this->assertSame(400, $this->response->statusCode);
+ }
+
+ public function test_onException_ShouldNotRethrowAnException()
+ {
+ $exception = $this->buildException();
+
+ $this->handler->onException($this->tracker, $this->requestSet, $exception);
+ $this->assertTrue(true);
+ }
+
+ public function test_onAllRequestsTracked_ShouldNeverTriggerScheduledTasksEvenIfEnabled()
+ {
+ $runner = new ScheduledTasksRunner();
+ $runner->shouldRun = true;
+
+ $this->handler->setScheduledTasksRunner($runner);
+ $this->handler->onAllRequestsTracked($this->tracker, $this->requestSet);
+
+ $this->assertFalse($runner->ranScheduledTasks);
+ }
+
+ public function test_process_ShouldTrackAllSetRequests()
+ {
+ $this->assertSame(0, $this->tracker->getCountOfLoggedRequests());
+
+ $this->requestSet->setRequests(array(
+ array('idsite' => 1, 'url' => 'http://localhost/foo?bar'),
+ array('idsite' => 1, 'url' => 'http://localhost'),
+ ));
+
+ $this->handler->process($this->tracker, $this->requestSet);
+
+ $this->assertSame(2, $this->tracker->getCountOfLoggedRequests());
+ }
+
+ private function buildException()
+ {
+ return new \Exception('MyMessage', 292);
+ }
+
+ private function executeOnException(Exception $exception)
+ {
+ try {
+ $this->handler->onException($this->tracker, $this->requestSet, $exception);
+ } catch (Exception $e) {
+ }
+ }
+}
diff --git a/plugins/BulkTracking/tests/Integration/RequestsTest.php b/plugins/BulkTracking/tests/Integration/RequestsTest.php
new file mode 100644
index 0000000000..ab45204303
--- /dev/null
+++ b/plugins/BulkTracking/tests/Integration/RequestsTest.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Integration;
+
+use Piwik\Plugins\BulkTracking\Tracker\Requests;
+use Piwik\Plugins\UsersManager\API;
+use Piwik\Plugins\UsersManager\UsersManager;
+use Piwik\Tests\Framework\Fixture;
+use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Tracker\Request;
+use Piwik\Tracker\TrackerConfig;
+
+/**
+ * @group BulkTracking
+ * @group RequestsTest
+ * @group Plugins
+ * @group Tracker
+ */
+class RequestsTest extends IntegrationTestCase
+{
+ /**
+ * @var Requests
+ */
+ private $requests;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->requests = new Requests();
+ }
+
+ public function tearDown()
+ {
+ // clean up your test here if needed
+
+ parent::tearDown();
+ }
+
+ public function test_requiresAuthentication_shouldReturnTrue_IfEnabled()
+ {
+ $oldConfig = TrackerConfig::getConfigValue('bulk_requests_require_authentication');
+ TrackerConfig::setConfigValue('bulk_requests_require_authentication', 1);
+
+ $this->assertTrue($this->requests->requiresAuthentication());
+
+ TrackerConfig::setConfigValue('bulk_requests_require_authentication', $oldConfig);
+ }
+
+ public function test_requiresAuthentication_shouldReturnFalse_IfDisabled()
+ {
+ $oldConfig = TrackerConfig::getConfigValue('bulk_requests_require_authentication');
+ TrackerConfig::setConfigValue('bulk_requests_require_authentication', 0);
+
+ $this->assertFalse($this->requests->requiresAuthentication());
+
+ TrackerConfig::setConfigValue('bulk_requests_require_authentication', $oldConfig);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage token_auth must be specified when using Bulk Tracking Import
+ */
+ public function test_authenticateRequests_shouldThrowAnException_IfTokenAuthIsEmpty()
+ {
+ $requests = array($this->buildDummyRequest());
+ $this->requests->authenticateRequests($requests);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage token_auth must be specified when using Bulk Tracking Import
+ */
+ public function test_authenticateRequests_shouldThrowAnException_IfAnyTokenAuthIsEmpty()
+ {
+ $requests = array($this->buildDummyRequest($this->getSuperUserToken()), $this->buildDummyRequest());
+ $this->requests->authenticateRequests($requests);
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage token_auth specified does not have Admin permission for idsite=1
+ */
+ public function test_authenticateRequests_shouldThrowAnException_IfTokenIsNotValid()
+ {
+ $dummyToken = API::getInstance()->getTokenAuth('test', UsersManager::getPasswordHash('2'));
+ $superUserToken = $this->getSuperUserToken();
+
+ $requests = array($this->buildDummyRequest($superUserToken), $this->buildDummyRequest($dummyToken));
+ $this->requests->authenticateRequests($requests);
+ }
+
+ public function test_authenticateRequests_shouldNotFail_IfAllTokensAreValid()
+ {
+ $superUserToken = $this->getSuperUserToken();
+
+ $requests = array($this->buildDummyRequest($superUserToken), $this->buildDummyRequest($superUserToken));
+ $this->requests->authenticateRequests($requests);
+
+ $this->assertTrue(true);
+ }
+
+ public function test_authenticateRequests_shouldNotFail_IfEmptyRequestSetGiven()
+ {
+ $this->requests->authenticateRequests(array());
+
+ $this->assertTrue(true);
+ }
+
+ private function getSuperUserToken()
+ {
+ Fixture::createSuperUser(false);
+ return Fixture::getTokenAuth();
+ }
+
+ private function buildDummyRequest($token = false)
+ {
+ return new Request(array('idsite' => '1'), $token);
+ }
+
+}
diff --git a/plugins/BulkTracking/tests/Integration/TrackerTest.php b/plugins/BulkTracking/tests/Integration/TrackerTest.php
new file mode 100644
index 0000000000..dd1e37ea70
--- /dev/null
+++ b/plugins/BulkTracking/tests/Integration/TrackerTest.php
@@ -0,0 +1,133 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Integration;
+
+use Piwik\Common;
+use Piwik\Plugin;
+use Piwik\Plugins\BulkTracking\tests\Framework\Mock\Tracker\Response;
+use Piwik\Plugins\BulkTracking\tests\Framework\TestCase\BulkTrackingTestCase;
+use Piwik\Plugins\BulkTracking\Tracker\Handler;
+use Piwik\Tests\Framework\Fixture;
+use Piwik\Tracker;
+use Piwik\Translate;
+use Piwik\Tests\Framework\Mock\Tracker\RequestSet;
+
+class TestIntegrationTracker extends Tracker {
+
+ protected function loadTrackerPlugins()
+ {
+ // if we reload the plugins we would lose the injected data :(
+ }
+}
+
+/**
+ * @group TrackerTest
+ * @group Tracker
+ */
+class TrackerTest extends BulkTrackingTestCase
+{
+ /**
+ * @var TestIntegrationTracker
+ */
+ private $tracker;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->tracker = new TestIntegrationTracker();
+
+ Fixture::createWebsite('2014-01-01 00:00:00');
+ Fixture::createWebsite('2014-01-01 00:00:00');
+
+ $this->injectRawDataToBulk($this->getDummyRequest());
+ }
+
+ public function test_main_shouldIncreaseLoggedRequestsCounter()
+ {
+ $this->tracker->main($this->getHandler(), $this->getEmptyRequestSet());
+
+ $this->assertSame(2, $this->tracker->getCountOfLoggedRequests());
+ }
+
+ public function test_main_shouldUseBulkHandler()
+ {
+ $handler = $this->getHandler();
+ $this->assertTrue($handler instanceof Handler);
+ }
+
+ public function test_main_shouldReturnBulkTrackingResponse()
+ {
+ $response = $this->tracker->main($this->getHandler(), $this->getEmptyRequestSet());
+
+ $this->assertSame('{"status":"success","tracked":2}', $response);
+ }
+
+ public function test_main_shouldReturnErrorResponse_InCaseOfAnyError()
+ {
+ $requestSet = new RequestSet();
+ $requestSet->enableThrowExceptionOnInit();
+
+ $handler = $this->getHandler();
+ $handler->setResponse(new Response());
+
+ $response = $this->tracker->main($handler, $requestSet);
+
+ $this->assertSame('{"status":"error","tracked":0}', $response);
+ }
+
+ public function test_main_shouldReturnErrorResponse_IfNotAuthorized()
+ {
+ $this->injectRawDataToBulk($this->getDummyRequest(), true);
+
+ $handler = $this->getHandler();
+ $handler->setResponse(new Response());
+
+ $response = $this->tracker->main($handler, $this->getEmptyRequestSet());
+
+ $this->assertSame('{"status":"error","tracked":0}', $response);
+ }
+
+ public function test_main_shouldActuallyTrack()
+ {
+ $this->assertEmpty($this->getIdVisit(1));
+ $this->assertEmpty($this->getIdVisit(2));
+
+ $requestSet = $this->getEmptyRequestSet();
+ $this->tracker->main($this->getHandler(), $requestSet);
+
+ $this->assertCount(2, $requestSet->getRequests(), 'Nothing tracked because it could not find 2 requests');
+
+ $visit1 = $this->getIdVisit(1);
+ $visit2 = $this->getIdVisit(2);
+
+ $this->assertNotEmpty($visit1);
+ $this->assertEquals(1, $visit1['idsite']);
+ $this->assertNotEmpty($visit2);
+ $this->assertEquals(2, $visit2['idsite']);
+
+ $this->assertEmpty($this->getIdVisit(3));
+ }
+
+ private function getHandler()
+ {
+ return Tracker\Handler\Factory::make();
+ }
+
+ private function getEmptyRequestSet()
+ {
+ return new Tracker\RequestSet();
+ }
+
+ private function getIdVisit($idVisit)
+ {
+ return Tracker::getDatabase()->fetchRow("SELECT * FROM " . Common::prefixTable('log_visit') . " WHERE idvisit = ?", array($idVisit));
+ }
+
+} \ No newline at end of file
diff --git a/plugins/BulkTracking/tests/System/TrackerTest.php b/plugins/BulkTracking/tests/System/TrackerTest.php
new file mode 100644
index 0000000000..5974a1acd5
--- /dev/null
+++ b/plugins/BulkTracking/tests/System/TrackerTest.php
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\System;
+
+use Piwik\Tests\Framework\Fixture;
+use Piwik\Tests\Framework\TestCase\SystemTestCase;
+
+/**
+ * @group BulkTracking
+ * @group TrackerTest
+ * @group Tracker
+ * @group Plugins
+ */
+class TrackerTest extends SystemTestCase
+{
+ public static $fixture = null;
+
+ /**
+ * @var \PiwikTracker
+ */
+ private $tracker;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $idSite = 1;
+ $dateTime = '2014-01-01 00:00:01';
+
+ if (!Fixture::siteCreated($idSite)) {
+ Fixture::createWebsite($dateTime);
+ }
+
+ $this->tracker = Fixture::getTracker($idSite, $dateTime, $defaultInit = true);
+ $this->tracker->enableBulkTracking();
+ }
+
+ public function test_response_ShouldContainBulkTrackingApiResponse()
+ {
+ $this->tracker->doTrackPageView('Test');
+ $this->tracker->doTrackPageView('Test');
+
+ $response = $this->tracker->doBulkTrack();
+
+ $this->assertEquals('{"status":"success","tracked":2}', $response);
+ }
+} \ No newline at end of file
diff --git a/plugins/BulkTracking/tests/Unit/RequestsTest.php b/plugins/BulkTracking/tests/Unit/RequestsTest.php
new file mode 100644
index 0000000000..8a89e5c220
--- /dev/null
+++ b/plugins/BulkTracking/tests/Unit/RequestsTest.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Unit;
+
+use Piwik\Plugins\BulkTracking\Tracker\Requests;
+use Piwik\Tests\Framework\TestCase\UnitTestCase;
+use Piwik\Tracker\Request;
+
+/**
+ * @group BulkTracking
+ * @group RequestsTest
+ * @group Plugins
+ */
+class RequestsTest extends UnitTestCase
+{
+ /**
+ * @var Requests
+ */
+ private $requests;
+
+ public function setUp()
+ {
+ parent::setUp();
+ $this->requests = new Requests();
+ }
+
+ public function test_isUsingBulkRequest_shouldReturnFalse_IfRequestIsEmpty()
+ {
+ $this->assertFalse($this->requests->isUsingBulkRequest(false));
+ $this->assertFalse($this->requests->isUsingBulkRequest(null));
+ $this->assertFalse($this->requests->isUsingBulkRequest(''));
+ $this->assertFalse($this->requests->isUsingBulkRequest(0));
+ }
+
+ public function test_isUsingBulkRequest_shouldReturnFalse_IfRequestIsNotABulkRequest()
+ {
+ $this->assertFalse($this->requests->isUsingBulkRequest(5));
+ $this->assertFalse($this->requests->isUsingBulkRequest('test'));
+ $this->assertFalse($this->requests->isUsingBulkRequest('requests'));
+ $this->assertFalse($this->requests->isUsingBulkRequest('{"test": "val", "request:" []}'));
+ $this->assertFalse($this->requests->isUsingBulkRequest('[5, 10, "request"]'));
+ }
+
+ public function test_isUsingBulkRequest_shouldReturnTrue_IfRequestIsABulkRequest()
+ {
+ $request = $this->buildRequestRawData(array(array('idsite' => '1')));
+ $this->assertTrue($this->requests->isUsingBulkRequest($request));
+
+ // don't know why this one is supposed to count as bulk request!
+ $this->assertTrue($this->requests->isUsingBulkRequest("{'requests'"));
+ }
+
+ public function test_getRequestsArrayFromBulkRequest_ShouldFindRequestsAndEmptyTokenAndItShouldTrimWhitespaceFromRawData()
+ {
+ $requests = array(array('idsite' => '1'), array('idsite' => '2'));
+ $request = $this->buildRequestRawData($requests);
+
+ $result = $this->requests->getRequestsArrayFromBulkRequest(' ' . $request . ' ');
+
+ $expected = array(array(array('idsite' => '1'), array('idsite' => '2')), '');
+ $this->assertEquals($expected, $result);
+ }
+
+ public function test_getRequestsArrayFromBulkRequest_shouldRecognize()
+ {
+ $token = md5('2');
+
+ $request = $this->buildRequestRawData(array(), $token);
+ $result = $this->requests->getRequestsArrayFromBulkRequest($request);
+
+ $expected = array(array(), $token);
+ $this->assertEquals($expected, $result);
+ }
+
+ public function test_initRequestsAndTokenAuth_NoRequestsSetShouldStillFindToken()
+ {
+ $token = md5('2');
+
+ $request = json_encode(array('requests' => array(), 'token_auth' => $token));
+ $result = $this->requests->initRequestsAndTokenAuth($request);
+
+ $expected = array(array(), $token);
+ $this->assertEquals($expected, $result);
+ }
+
+ public function test_initRequestsAndTokenAuth_ShouldFindRequestsAndEmptyToken()
+ {
+ $params = array(array('idsite' => '1'), array('idsite' => '2'));
+ $request = $this->buildRequestRawData($params);
+
+ $result = $this->requests->initRequestsAndTokenAuth($request);
+
+ /** @var Request[] $requests */
+ $requests = $result[0];
+ $tokenAuth = $result[1];
+
+ $this->assertEquals('', $tokenAuth); // none was set
+
+ $this->assertEquals(array('idsite' => '1'), $requests[0]->getParams());
+ $this->assertEquals('', $requests[0]->getTokenAuth());
+ $this->assertEquals(array('idsite' => '2'), $requests[1]->getParams());
+ $this->assertEquals('', $requests[1]->getTokenAuth());
+ $this->assertCount(2, $requests);
+ }
+
+ public function test_initRequestsAndTokenAuth_ShouldFindRequestsAndASetTokenAndPassItToRequestInstances()
+ {
+ $token = md5(2);
+ $params = array(array('idsite' => '1'), array('idsite' => '2'));
+ $request = $this->buildRequestRawData($params, $token);
+
+ $result = $this->requests->initRequestsAndTokenAuth($request);
+
+ /** @var Request[] $requests */
+ $requests = $result[0];
+
+ $this->assertEquals($token, $result[1]);
+ $this->assertEquals($token, $requests[0]->getTokenAuth());
+ $this->assertEquals($token, $requests[1]->getTokenAuth());
+ }
+
+ public function test_initRequestsAndTokenAuth_ShouldIgnoreEmptyUrls()
+ {
+ $token = md5(2);
+ $params = array(array('idsite' => '1'), '', array('idsite' => '2'));
+ $request = $this->buildRequestRawData($params, $token);
+
+ $result = $this->requests->initRequestsAndTokenAuth($request);
+
+ /** @var Request[] $requests */
+ $requests = $result[0];
+
+ $this->assertEquals(array('idsite' => '1'), $requests[0]->getParams());
+ $this->assertEquals(array('idsite' => '2'), $requests[1]->getParams());
+ $this->assertCount(2, $requests);
+ }
+
+ public function test_initRequestsAndTokenAuth_ShouldResolveUrls()
+ {
+ $token = md5(2);
+ $params = array('piwik.php?idsite=1', '', 'piwik.php?idsite=3&rec=0', array('idsite' => '2'));
+ $request = $this->buildRequestRawData($params, $token);
+
+ $result = $this->requests->initRequestsAndTokenAuth($request);
+
+ /** @var Request[] $requests */
+ $requests = $result[0];
+
+ $this->assertEquals(array('idsite' => '1'), $requests[0]->getParams());
+ $this->assertEquals(array('idsite' => '3', 'rec' => '0'), $requests[1]->getParams());
+ $this->assertEquals(array('idsite' => '2'), $requests[2]->getParams());
+ $this->assertCount(3, $requests);
+ }
+
+ private function buildRequestRawData($requests, $token = null)
+ {
+ $params = array('requests' => $requests);
+
+ if (!empty($token)) {
+ $params['token_auth'] = $token;
+ }
+
+ return json_encode($params);
+ }
+
+}
diff --git a/plugins/BulkTracking/tests/Unit/ResponseTest.php b/plugins/BulkTracking/tests/Unit/ResponseTest.php
new file mode 100644
index 0000000000..9da1e9a6b3
--- /dev/null
+++ b/plugins/BulkTracking/tests/Unit/ResponseTest.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\BulkTracking\tests\Unit;
+
+use Piwik\Plugins\BulkTracking\Tracker\Response;
+use Piwik\Tests\Framework\Mock\Tracker;
+use Piwik\Tests\Framework\TestCase\UnitTestCase;
+use Exception;
+
+class TestResponse extends Response {
+
+ protected function logExceptionToErrorLog(Exception $e)
+ {
+ // prevent console from outputting the error_log message
+ }
+}
+
+/**
+ * @group BulkTracking
+ * @group ResponseTest
+ * @group Plugins
+ */
+class ResponseTest extends UnitTestCase
+{
+ /**
+ * @var TestResponse
+ */
+ private $response;
+
+ public function setUp()
+ {
+ parent::setUp();
+
+ $this->response = new TestResponse();
+ $this->response->init(new Tracker());
+ }
+
+ public function test_outputException_shouldOutputBulkResponse()
+ {
+ $tracker = $this->getTrackerWithCountedRequests();
+
+ $this->response->outputException($tracker, new Exception('My Custom Message'), 400);
+ $content = $this->response->getOutput();
+
+ $this->assertEquals('{"status":"error","tracked":5}', $content);
+ }
+
+ public function test_outputException_shouldOutputDebugMessageIfEnabled()
+ {
+ $tracker = $this->getTrackerWithCountedRequests();
+ $tracker->enableDebugMode();
+
+ $this->response->outputException($tracker, new Exception('My Custom Message'), 400);
+ $content = $this->response->getOutput();
+
+ $this->assertStringStartsWith('{"status":"error","tracked":5,"message":"My Custom Message\n', $content);
+ }
+
+ public function test_outputResponse_shouldOutputBulkResponse()
+ {
+ $tracker = $this->getTrackerWithCountedRequests();
+
+ $this->response->outputResponse($tracker);
+ $content = $this->response->getOutput();
+
+ $this->assertEquals('{"status":"success","tracked":5}', $content);
+ }
+
+ public function test_outputResponse_shouldNotOutputAnything_IfExceptionResponseAlreadySent()
+ {
+ $tracker = $this->getTrackerWithCountedRequests();
+
+ $this->response->outputException($tracker, new Exception('My Custom Message'), 400);
+ $this->response->outputResponse($tracker);
+ $content = $this->response->getOutput();
+
+ $this->assertEquals('{"status":"error","tracked":5}', $content);
+ }
+
+ private function getTrackerWithCountedRequests()
+ {
+ $tracker = new Tracker();
+ $tracker->setCountOfLoggedRequests(5);
+ return $tracker;
+ }
+
+}