Jeroen De Dauw has submitted this change and it was merged.

Change subject: SMW\SQLStore\StatisticsCollector
......................................................................


SMW\SQLStore\StatisticsCollector

Test coverage: 100%
CRAP: 21

* Move statistics into its own StatisticsCollector class to ensure
proper test environment
* SMWSQLStore3::getStatistics only returns results from
StatisticsCollector::doCollect()
* Add profiling point for each count statistic
* Add caching for statistics results using $smwgStatisticsCache and
$smwgStatisticsCacheExpiry settings

## Default settings
$smwgStatisticsCache = true
$smwgStatisticsCacheExpiry = 3600 // 1h

Change-Id: Id189dd17c7e2591764896baf6e344b4590ca65e4
---
M SemanticMediaWiki.hooks.php
M SemanticMediaWiki.settings.php
M includes/Settings.php
M includes/Setup.php
M includes/storage/SQLStore/SMW_SQLStore3_SpecialPageHandlers.php
A includes/storage/SQLStore/StatisticsCollector.php
A tests/phpunit/includes/storage/sqlstore/SpecialPageHandlersTest.php
A tests/phpunit/includes/storage/sqlstore/StatisticsCollectorTest.php
8 files changed, 741 insertions(+), 108 deletions(-)

Approvals:
  Jeroen De Dauw: Verified; Looks good to me, approved



diff --git a/SemanticMediaWiki.hooks.php b/SemanticMediaWiki.hooks.php
index 168a3e7..f8e1154 100644
--- a/SemanticMediaWiki.hooks.php
+++ b/SemanticMediaWiki.hooks.php
@@ -397,7 +397,7 @@
        public static function onSpecialStatsAddExtra( array &$extraStats ) {
                global $wgVersion, $wgLang;
 
-               $semanticStatistics = smwfGetStore()->getStatistics();
+               $semanticStatistics = 
\SMW\StoreFactory::getStore()->getStatistics();
 
                if ( version_compare( $wgVersion, '1.21', '<' ) ) {
                        // Legacy approach to display statistical items
diff --git a/SemanticMediaWiki.settings.php b/SemanticMediaWiki.settings.php
index 36fc19c..8fe8a98 100644
--- a/SemanticMediaWiki.settings.php
+++ b/SemanticMediaWiki.settings.php
@@ -557,3 +557,15 @@
 ##
 $smwgAutoRefreshOnPageMove = true;
 ##
+
+###
+# Enable to serve statistics from cache using the smwgCacheType setting
+#
+# @since 1.9
+###
+$smwgStatisticsCache = true;
+#
+# Number of seconds before the statistics cache expires
+##
+$smwgStatisticsCacheExpiry = 3600;
+##
\ No newline at end of file
diff --git a/includes/Settings.php b/includes/Settings.php
index f53dacb..c7945c9 100644
--- a/includes/Settings.php
+++ b/includes/Settings.php
@@ -153,6 +153,8 @@
                        'smwgNamespace' => $GLOBALS['smwgNamespace'],
                        'smwgMasterStore' => $GLOBALS['smwgMasterStore'],
                        'smwgIQRunningNumber' => 
$GLOBALS['smwgIQRunningNumber'],
+                       'smwgStatisticsCache' => 
$GLOBALS['smwgStatisticsCache'],
+                       'smwgStatisticsCacheExpiry' => 
$GLOBALS['smwgStatisticsCacheExpiry']
                );
 
                if ( self::$instance === null ) {
diff --git a/includes/Setup.php b/includes/Setup.php
index 49ef38d..1392b6e 100644
--- a/includes/Setup.php
+++ b/includes/Setup.php
@@ -145,14 +145,14 @@
        $wgAutoloadClasses['SMW\Subobject']             = $incDir . 
'Subobject.php';
        $wgAutoloadClasses['SMW\RecurringEvents']       = $incDir . 
'RecurringEvents.php';
 
+       $wgAutoloadClasses['SMW\Settings']              = $incDir . 
'Settings.php';
+
        // Formatters
        $wgAutoloadClasses['SMW\ArrayFormatter']           = $incDir . 
'formatters/ArrayFormatter.php';
        $wgAutoloadClasses['SMW\ParserParameterFormatter'] = $incDir . 
'formatters/ParserParameterFormatter.php';
        $wgAutoloadClasses['SMW\MessageFormatter']         = $incDir . 
'formatters/MessageFormatter.php';
 
-       $wgAutoloadClasses['SMW\Settings']               = $incDir . 
'Settings.php';
-
-       $wgAutoloadClasses['SMW\CacheHandler']           = $incDir . 
'/handlers/CacheHandler.php';
+       $wgAutoloadClasses['SMW\CacheHandler']             = $incDir . 
'/handlers/CacheHandler.php';
 
        // Exceptions
        $wgAutoloadClasses['SMW\StoreInstanceException']       = $incDir . 
'/exceptions/StoreInstanceException.php';
@@ -305,6 +305,8 @@
        $stoDirSQL = $smwgIP . 'includes/storage/SQLStore/';
        $wgAutoloadClasses['SMW\SQLStore\PropertyStatisticsTable']              
                = $stoDirSQL . 'PropertyStatisticsTable.php';
        $wgAutoloadClasses['SMW\SQLStore\SimplePropertyStatisticsRebuilder']    
= $stoDirSQL . 'SimplePropertyStatisticsRebuilder.php';
+       $wgAutoloadClasses['SMW\SQLStore\StatisticsCollector']                  
= $stoDirSQL . 'StatisticsCollector.php';
+
        $wgAutoloadClasses['SMWSQLStore3']                     = $stoDirSQL . 
'SMW_SQLStore3.php';
        $wgAutoloadClasses['SMWSql3StubSemanticData']          = $stoDirSQL . 
'SMW_Sql3StubSemanticData.php';
        $wgAutoloadClasses['SMWSql3SmwIds']                    = $stoDirSQL . 
'SMW_Sql3SmwIds.php';
diff --git a/includes/storage/SQLStore/SMW_SQLStore3_SpecialPageHandlers.php 
b/includes/storage/SQLStore/SMW_SQLStore3_SpecialPageHandlers.php
index 52b596e..cc1492f 100644
--- a/includes/storage/SQLStore/SMW_SQLStore3_SpecialPageHandlers.php
+++ b/includes/storage/SQLStore/SMW_SQLStore3_SpecialPageHandlers.php
@@ -189,113 +189,12 @@
 
        /**
         * @see SMWStore::getStatistics
-        *
-        * @note Always ensure to set the array initially to 0 to avoid 
problems when
-        * accessing the array via a key
+        * @see StatisticsCollector:doCollect
         *
         * @return array
         */
        public function getStatistics() {
-               wfProfileIn( 'SMWSQLStore3::getStatistics (SMW)' );
-
-               $dbr = wfGetDB( DB_SLAVE );
-               $result = array();
-               $propertyTables = SMWSQLStore3::getPropertyTables();
-
-               // Properties with their own page
-               $result['OWNPAGE'] = 0;
-               $result['OWNPAGE'] = $dbr->estimateRowCount( 'page', '*', 
array( 'page_namespace' => SMW_NS_PROPERTY ) );
-
-               // Count existing inline queries
-               $result['QUERY'] = 0;
-               $typeProp = new SMWDIProperty( '_ASK' );
-               $typeTable = $propertyTables[SMWSQLStore3::findPropertyTableID( 
$typeProp )];
-               $res = $dbr->select( $typeTable->getName(), 'COUNT(s_id) AS 
count', array(), 'SMW::getStatistics' );
-               $row = $dbr->fetchObject( $res );
-               $result['QUERY'] = $row->count;
-               $dbr->freeResult( $res );
-
-               // Count query size
-               $result['QUERYSIZE'] = 0;
-               $typeProp = new SMWDIProperty( '_ASKSI' );
-               $typeTable = $propertyTables[SMWSQLStore3::findPropertyTableID( 
$typeProp )];
-               $res = $dbr->select( $typeTable->getName(), 'COUNT(s_id) AS 
count', array(), 'SMW::getStatistics' );
-               $row = $dbr->fetchObject( $res );
-               $result['QUERYSIZE'] = $row->count;
-               $dbr->freeResult( $res );
-
-               // Count used formats
-               $result['QUERYFORMATS'] = array();
-               $typeProp = new SMWDIProperty( '_ASKFO' );
-               $typeTable = $propertyTables[SMWSQLStore3::findPropertyTableID( 
$typeProp )];
-               $res = $dbr->select(
-                       $typeTable->getName(),
-                       'o_hash, COUNT(s_id) AS count',
-                       array(),
-                       'SMW::getStatistics',
-                       array(
-                               'ORDER BY' => 'count DESC',
-                               'GROUP BY' => 'o_hash'
-                       )
-               );
-
-               foreach ( $res as $row ) {
-                       $result['QUERYFORMATS'][$row->o_hash] = 
(int)$row->count;
-               }
-               $dbr->freeResult( $res );
-
-               // Count existing concepts
-               $result['CONCEPTS'] = 0;
-               $typeProp = new SMWDIProperty( '_CONC' );
-               $typeTable = $propertyTables[SMWSQLStore3::findPropertyTableID( 
$typeProp )];
-               $res = $dbr->select( $typeTable->getName(), 'COUNT(s_id) AS 
count', array(), 'SMW::getStatistics' );
-               $row = $dbr->fetchObject( $res );
-               $result['CONCEPTS'] = $row->count;
-               $dbr->freeResult( $res );
-
-               // Count existing subobjects
-               $result['SUBOBJECTS'] = 0;
-               $typeProp = new SMWDIProperty( SMWDIProperty::TYPE_SUBOBJECT );
-               $typeTable = $propertyTables[SMWSQLStore3::findPropertyTableID( 
$typeProp )];
-               $res = $dbr->select( $typeTable->getName(), 'COUNT(s_id) AS 
count', array(), 'SMW::getStatistics' );
-               $row = $dbr->fetchObject( $res );
-               $result['SUBOBJECTS'] = $row->count;
-               $dbr->freeResult( $res );
-
-               // count number of declared properties by counting "has type" 
annotations
-               $typeProp = new SMWDIProperty( '_TYPE' );
-               $typeTable = $propertyTables[SMWSQLStore3::findPropertyTableID( 
$typeProp )];
-               $res = $dbr->select( $typeTable->getName(), 'COUNT(s_id) AS 
count', array(), 'SMW::getStatistics' );
-               $row = $dbr->fetchObject( $res );
-               $result['DECLPROPS'] = $row->count;
-               $dbr->freeResult( $res );
-
-               // count property uses by counting rows in property tables,
-               // count used properties by counting distinct properties in 
each table
-               $result['PROPUSES'] = 0;
-               $result['USEDPROPS'] = 0;
-
-               foreach ( SMWSQLStore3::getPropertyTables() as $propertyTable ) 
{
-                       /// Note: subproperties that are part of container 
values are counted individually;
-                       /// It does not seem to be important to filter them by 
adding more conditions.
-                       $res = $dbr->select( $propertyTable->getName(), 
'COUNT(*) AS count', '', 'SMW::getStatistics' );
-                       $row = $dbr->fetchObject( $res );
-                       $result['PROPUSES'] += $row->count;
-                       $dbr->freeResult( $res );
-
-                       if ( !$propertyTable->isFixedPropertyTable() ) {
-                               $res = $dbr->select( $propertyTable->getName(), 
'COUNT(DISTINCT(p_id)) AS count', '', 'SMW::getStatistics' );
-                               $row = $dbr->fetchObject( $res );
-                               $result['USEDPROPS'] += $row->count;
-                       } else {
-                               $res = $dbr->select( $propertyTable->getName(), 
'*', '', 'SMW::getStatistics', array( 'LIMIT' => 1 ) );
-                               if ( $dbr->numRows( $res ) > 0 )  
$result['USEDPROPS']++;
-                       }
-
-                       $dbr->freeResult( $res );
-               }
-
-               wfProfileOut( 'SMWSQLStore3::getStatistics (SMW)' );
-               return $result;
+               // Until the settings object is invoke during Store setup, use 
the factory method here
+               return \SMW\SQLStore\StatisticsCollector::newFromStore( 
$this->store )->doCollect();
        }
 }
diff --git a/includes/storage/SQLStore/StatisticsCollector.php 
b/includes/storage/SQLStore/StatisticsCollector.php
new file mode 100644
index 0000000..80f244d
--- /dev/null
+++ b/includes/storage/SQLStore/StatisticsCollector.php
@@ -0,0 +1,368 @@
+<?php
+
+namespace SMW\SQLStore;
+
+use SMW\CacheHandler;
+use SMW\Settings;
+
+use DatabaseBase;
+use SMWDIProperty;
+use SMWStore;
+
+/**
+ * Collects statistical information provided by the store
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * This class provides access to store related statistical information
+ *
+ * @ingroup SMW
+ */
+class StatisticsCollector {
+
+       /** @var SMWStore */
+       protected $store;
+
+       /** @var DatabaseBase */
+       protected $dbConnection;
+
+       /** @var Settings */
+       protected $settings;
+
+       /** @var Boolean */
+       protected $isCached;
+
+       /**
+        * // FIXME The store itself should know which database connection is 
being
+        * used therefore this info should come from the store object rather 
than
+        * doing an extra injection here
+        *
+        * @since 1.9
+        *
+        * @param Store $store
+        * @param DatabaseBase $dbw
+        * @param Settings $settings
+        */
+       public function __construct( SMWStore $store, DatabaseBase $dbw, 
Settings $settings ) {
+               $this->store = $store;
+               $this->dbConnection = $dbw;
+               $this->settings = $settings;
+               $this->isCached = false;
+       }
+
+       /**
+        * Factory method for immediate instantiation of a StatisticsCollector 
object
+        *
+        * @par Example:
+        * @code
+        * $statistics = \SMW\SQLStore\StatisticsCollector::newFromStore( 
$store )->doCollect();
+        * @endcode
+        *
+        * @since 1.9
+        *
+        * @param SMWStore $store
+        * @param $dbw Boolean or DatabaseBase:
+        * - Boolean: whether to use a dedicated DB or Slave
+        * - DatabaseBase: database connection to use
+        *
+        * @return StatisticsCollector
+        */
+       public static function newFromStore( SMWStore $store, $dbw = false ) {
+
+               $dbw = $dbw instanceof DatabaseBase ? $dbw : wfGetDB( DB_SLAVE 
);
+
+               $settings = Settings::newFromArray( array(
+                       'smwgCacheType' => $GLOBALS['smwgCacheType'],
+                       'smwgStatisticsCache' => 
$GLOBALS['smwgStatisticsCache'],
+                       'smwgStatisticsCacheExpiry' => 
$GLOBALS['smwgStatisticsCacheExpiry']
+               ) );
+
+               return new self( $store, $dbw, $settings );
+       }
+
+       /**
+        * Collects and returns statistical information as an associative array
+        * with the following keys:
+        *
+        * - 'PROPUSES': Number of property instances (value assignments) in 
the dbConnection
+        * - 'USEDPROPS': Number of properties that are used with at least one 
value
+        * - 'DECLPROPS': Number of properties that have been declared (i.e. 
assigned a type)
+        * - 'OWNPAGE': Number of properties with their own page
+        * - 'QUERY': Number of inline queries
+        * - 'QUERYSIZE': Represents collective query size
+        * - 'CONCEPTS': Number of declared concepts
+        * - 'SUBOBJECTS': Number of declared subobjects
+        * - 'QUERYFORMATS': Array of used formats and its usage count
+        *
+        * @note Results are cacheable if necessary settings are available
+        *
+        * @see $smwgStatisticsCache
+        * @see $smwgStatisticsCacheExpiry
+        *
+        * @since 1.9
+        *
+        * @return array
+        */
+       public function doCollect() {
+
+               $cache = CacheHandler::newFromId( $this->settings->get( 
'smwgCacheType' ) );
+               $cache->setCacheEnabled( $this->settings->get( 
'smwgStatisticsCache' ) )->key( 'stats', 'store' );
+
+               if ( $cache->get() ) {
+                       wfDebug( __METHOD__ . ' statistics served from cache' . 
"\n");
+                       $this->isCached = true;
+                       return $cache->get();
+               }
+
+               $statistics = array(
+                       'OWNPAGE' => $this->getPropertyPageCount(),
+                       'QUERY' => $this->getQueryCount(),
+                       'QUERYSIZE' => $this->getQuerySize(),
+                       'QUERYFORMATS' => $this->getQueryFormatsCount(),
+                       'CONCEPTS' => $this->getConceptCount(),
+                       'SUBOBJECTS' => $this->getSubobjectCount(),
+                       'DECLPROPS' => $this->getDeclaredPropertiesCount(),
+                       'PROPUSES' => $this->getPropertyUsageCount(),
+                       'USEDPROPS' => $this->getUsedPropertiesCount()
+               );
+
+               $cache->set( $statistics, $this->settings->get( 
'smwgStatisticsCacheExpiry' ) );
+
+               return $statistics;
+       }
+
+       /**
+        * Returns if the current collection has been recalled from cache
+        *
+        * @since 1.9
+        *
+        * @return boolean
+        */
+       public function isCached() {
+               return $this->isCached;
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getQueryCount() {
+               return $this->count( '_ASK' );
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getQuerySize() {
+               return $this->count( '_ASKSI' );
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getConceptCount() {
+               return $this->count( '_CONC' );
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getSubobjectCount() {
+               return $this->count( SMWDIProperty::TYPE_SUBOBJECT );
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getDeclaredPropertiesCount() {
+               return $this->count( SMWDIProperty::TYPE_HAS_TYPE );
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return array
+        */
+       public function getQueryFormatsCount() {
+               wfProfileIn( __METHOD__ );
+
+               $count = array();
+               $res = $this->dbConnection->select(
+                       $this->getTypeTable( '_ASKFO' )->getName(),
+                       'o_hash, COUNT(s_id) AS count',
+                       array(),
+                       __METHOD__,
+                       array(
+                               'ORDER BY' => 'count DESC',
+                               'GROUP BY' => 'o_hash'
+                       )
+               );
+
+               foreach ( $res as $row ) {
+                       $count[$row->o_hash] = (int)$row->count;
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $count;
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getPropertyPageCount() {
+               wfProfileIn( __METHOD__ );
+
+               $count = 0;
+               $count = $this->dbConnection->estimateRowCount(
+                       'page',
+                       '*',
+                       array( 'page_namespace' => SMW_NS_PROPERTY )
+               );
+
+               wfProfileOut( __METHOD__ );
+               return (int)$count;
+       }
+
+       /**
+        * Count property uses by counting rows in property tables
+        *
+        * @note subproperties that are part of container values are counted
+        * individually and it does not seem to be important to filter them by
+        * adding more conditions.
+        *
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getPropertyUsageCount() {
+               wfProfileIn( __METHOD__ );
+
+               $count = 0;
+               foreach ( $this->store->getPropertyTables() as $propertyTable ) 
{
+                       $res = $this->dbConnection->select(
+                               $propertyTable->getName(),
+                               'COUNT(*) AS count',
+                               array(),
+                               __METHOD__
+                       );
+                       $row = $this->dbConnection->fetchObject( $res );
+                       $count += $row->count;
+               }
+
+               wfProfileOut( __METHOD__ );
+               return (int)$count;
+       }
+
+       /**
+        * @since 1.9
+        *
+        * @return number
+        */
+       public function getUsedPropertiesCount() {
+               wfProfileIn( __METHOD__ );
+
+               $count = 0;
+               foreach ( $this->store->getPropertyTables() as $propertyTable ) 
{
+                       if ( !$propertyTable->isFixedPropertyTable() ) {
+                               $res = $this->dbConnection->select(
+                                       $propertyTable->getName(),
+                                       'COUNT(DISTINCT(p_id)) AS count',
+                                       array(),
+                                       __METHOD__
+                               );
+                               $row = $this->dbConnection->fetchObject( $res );
+                               $count += $row->count;
+                       } else {
+                               $res = $this->dbConnection->select(
+                                       $propertyTable->getName(),
+                                       '*',
+                                       array(),
+                                       __METHOD__,
+                                       array( 'LIMIT' => 1 )
+                               );
+
+                               if ( $this->dbConnection->numRows( $res ) > 0 ) 
{
+                                       $count++;
+                               }
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return (int)$count;
+       }
+
+       /**
+        * Convenience method to count on a single table for a given type
+        *
+        * @since 1.9
+        *
+        * @param string $type
+        *
+        * @return number
+        */
+       protected function count( $type ) {
+               $caller = wfGetCaller();
+               wfProfileIn( $caller );
+
+               $count = 0;
+               $res = $this->dbConnection->select(
+                       $this->getTypeTable( $type )->getName(),
+                       'COUNT(s_id) AS count',
+                       array(),
+                       __METHOD__
+               );
+               $row = $this->dbConnection->fetchObject( $res );
+
+               wfProfileOut( $caller );
+               return (int)$row->count;
+       }
+
+       /**
+        * Returns table declaration for a given property type
+        *
+        * @since 1.9
+        *
+        * @param string $type
+        *
+        * @return array
+        */
+       protected function getTypeTable( $type ) {
+               $typeProp = new SMWDIProperty( $type );
+               $propertyTables = $this->store->getPropertyTables();
+               return $propertyTables[$this->store->findPropertyTableID( 
$typeProp )];
+       }
+}
diff --git 
a/tests/phpunit/includes/storage/sqlstore/SpecialPageHandlersTest.php 
b/tests/phpunit/includes/storage/sqlstore/SpecialPageHandlersTest.php
new file mode 100644
index 0000000..e10fd50
--- /dev/null
+++ b/tests/phpunit/includes/storage/sqlstore/SpecialPageHandlersTest.php
@@ -0,0 +1,99 @@
+<?php
+
+namespace SMW\Test\SQLStore;
+
+use SMW\Store;
+use SMW\Test\SemanticMediaWikiTestCase;
+use SMWSQLStore3SpecialPageHandlers;
+
+/**
+ * Tests for the SMWSQLStore3SpecialPageHandlers class
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup Store
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Tests for the SMWSQLStore3SpecialPageHandlers class
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class SpecialPageHandlersTest extends SemanticMediaWikiTestCase {
+
+       /**
+        * Returns the name of the class to be tested
+        *
+        * @return string|false
+        */
+       public function getClass() {
+               return '\SMWSQLStore3SpecialPageHandlers';
+       }
+
+       /**
+        * Helper method that returns a Store object
+        *
+        * @since 1.9
+        *
+        * @return Store
+        */
+       private function getStore() {
+
+               // FIXME Use StoreFactory::getStore()
+               return smwfGetStore();
+       }
+
+       /**
+        * Helper method that returns a SMWSQLStore3SpecialPageHandlers object
+        *
+        * @param Store $store
+        *
+        * @return SMWSQLStore3SpecialPageHandlers
+        */
+       private function getInstance( $store ) {
+               return new SMWSQLStore3SpecialPageHandlers( $store );
+       }
+
+       /**
+        * @test SMWSQLStore3SpecialPageHandlers::__construct
+        *
+        * @since 1.9
+        */
+       public function testConstructor() {
+               $instance = $this->getInstance( $this->getStore() );
+               $this->assertInstanceOf( $this->getClass(), $instance );
+       }
+
+       /**
+        * @test SMWSQLStore3SpecialPageHandlers::getStatistics
+        *
+        * @since 1.9
+        */
+       public function testGetStatistics() {
+               $instance = $this->getInstance( $this->getStore() );
+               $this->assertInternalType( 'array', $instance->getStatistics() 
);
+       }
+}
diff --git 
a/tests/phpunit/includes/storage/sqlstore/StatisticsCollectorTest.php 
b/tests/phpunit/includes/storage/sqlstore/StatisticsCollectorTest.php
new file mode 100644
index 0000000..aa1dcc6
--- /dev/null
+++ b/tests/phpunit/includes/storage/sqlstore/StatisticsCollectorTest.php
@@ -0,0 +1,251 @@
+<?php
+
+namespace SMW\Test;
+
+use SMW\SQLStore\StatisticsCollector;
+use SMW\Settings;
+use SMW\Store;
+
+/**
+ * Tests for the StatisticsCollector class
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 1.9
+ *
+ * @file
+ * @ingroup SMW
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author mwjames
+ */
+
+/**
+ * Tests for the StatisticsCollector class
+ *
+ * @ingroup Test
+ *
+ * @group SMW
+ * @group SMWExtension
+ */
+class StatisticsCollectorTest extends SemanticMediaWikiTestCase {
+
+       /**
+        * Returns the name of the class to be tested
+        *
+        * @return string|false
+        */
+       public function getClass() {
+               return '\SMW\SQLStore\StatisticsCollector';
+       }
+
+       /**
+        * Helper method that returns a StatisticsCollector object
+        *
+        * @since 1.9
+        *
+        * @param $count
+        * @param $cacheEnabled
+        *
+        * @return StatisticsCollector
+        */
+       private function getInstance( $count = 1, $cacheEnabled = false ) {
+
+               // FIXME Use StoreFactory::getStore()
+               $store = smwfGetStore();
+
+               // fetchObject return object
+               $returnFetchObject = new \StdClass;
+               $returnFetchObject->count = $count;
+               $returnFetchObject->o_hash ='foo';
+
+               // Database stub object which makes the test
+               // independent from the real DB
+               $connection = $this->getMock( 'DatabaseMysql' );
+
+               // Override methods with expected return objects
+               $connection->expects( $this->any() )
+                       ->method( 'select' )
+                       ->will( $this->returnValue( array( $returnFetchObject ) 
) );
+
+               $connection->expects( $this->any() )
+                       ->method( 'fetchObject' )
+                       ->will( $this->returnValue( $returnFetchObject ) );
+
+               $connection->expects( $this->any() )
+                       ->method( 'estimateRowCount' )
+                       ->will( $this->returnValue( $count ) );
+
+               $connection->expects( $this->any() )
+                       ->method( 'numRows' )
+                       ->will( $this->returnValue( $count ) );
+
+               // Settings to be used
+               // hash = HashBagOStuff is used for testing only
+               $settings = Settings::newFromArray( array(
+                       'smwgCacheType' => 'hash',
+                       'smwgStatisticsCache' => $cacheEnabled,
+                       'smwgStatisticsCacheExpiry' => 3600
+               ) );
+
+               return new StatisticsCollector( $store, $connection, $settings 
);
+       }
+
+       /**
+        * @test StatisticsCollector::__construct
+        *
+        * @since 1.9
+        */
+       public function testConstructor() {
+               $instance = $this->getInstance();
+               $this->assertInstanceOf( $this->getClass(), $instance );
+       }
+
+       /**
+        * @test StatisticsCollector::newFromStore
+        *
+        * @since 1.9
+        */
+       public function testNewFromStore() {
+               $instance = StatisticsCollector::newFromStore( smwfGetStore() );
+               $this->assertInstanceOf( $this->getClass(), $instance );
+       }
+
+       /**
+        * @test StatisticsCollector::getUsedPropertiesCount
+        * @test StatisticsCollector::getPropertyUsageCount
+        * @test StatisticsCollector::getDeclaredPropertiesCount
+        * @test StatisticsCollector::getSubobjectCount
+        * @test StatisticsCollector::getConceptCount
+        * @test StatisticsCollector::getQueryFormatsCount
+        * @test StatisticsCollector::getQuerySize
+        * @test StatisticsCollector::getQueryCount
+        * @test StatisticsCollector::getPropertyPageCount
+        * @dataProvider getFunctionDataProvider
+        *
+        * @since 1.9
+        */
+       public function testFunctions( $function, $expectedType ) {
+               $instance = $this->getInstance();
+               $result = call_user_func( array( &$instance, $function ) );
+
+               $this->assertInternalType( $expectedType, $result );
+       }
+
+       /**
+        * @test StatisticsCollector::doCollect
+        * @dataProvider getCollectorDataProvider
+        *
+        * @since 1.9
+        *
+        * @param $segment
+        * @param $expectedType
+        */
+       public function testDoCollect( $segment, $expectedType ) {
+               $instance = $this->getInstance();
+               $result = $instance->doCollect();
+
+               $this->assertInternalType( $expectedType, $result[$segment] );
+       }
+
+       /**
+        * @test StatisticsCollector::doCollect
+        * @dataProvider getCacheNonCacheDataProvider
+        *
+        * @since 1.9
+        *
+        * @param $test
+        * @param $expected
+        */
+       public function testCachNoCache( array $test, array $expected ) {
+
+               // Sample A
+               $instance = $this->getInstance( $test['A'], 
$test['cacheEnabled'] );
+               $result = $instance->doCollect();
+               $this->assertEquals( $expected['A'], $result['OWNPAGE'] );
+
+               // Sample B
+               $instance = $this->getInstance( $test['B'], 
$test['cacheEnabled'] );
+               $result = $instance->doCollect();
+               $this->assertEquals( $expected['B'], $result['OWNPAGE'] );
+
+               $this->assertEquals( $test['cacheEnabled'], 
$instance->isCached() );
+
+       }
+
+       /**
+        * DataProvider
+        *
+        * @return array
+        */
+       public function getFunctionDataProvider() {
+               return array(
+                       array( 'getUsedPropertiesCount',     'integer' ),
+                       array( 'getPropertyUsageCount',      'integer' ),
+                       array( 'getDeclaredPropertiesCount', 'integer' ),
+                       array( 'getSubobjectCount',          'integer' ),
+                       array( 'getConceptCount',            'integer' ),
+                       array( 'getQueryFormatsCount',       'array'   ),
+                       array( 'getQuerySize',               'integer' ),
+                       array( 'getQueryCount',              'integer' ),
+                       array( 'getPropertyPageCount',       'integer' )
+               );
+       }
+
+       /**
+        * DataProvider
+        *
+        * @return array
+        */
+       public function getCollectorDataProvider() {
+               return array(
+                       array( 'OWNPAGE',      'integer' ),
+                       array( 'QUERY',        'integer' ),
+                       array( 'QUERYSIZE',    'integer' ),
+                       array( 'QUERYFORMATS', 'array'   ),
+                       array( 'CONCEPTS',     'integer' ),
+                       array( 'SUBOBJECTS',   'integer' ),
+                       array( 'DECLPROPS',    'integer' ),
+                       array( 'USEDPROPS',    'integer' ),
+                       array( 'PROPUSES',     'integer' )
+               );
+       }
+
+       /**
+        * Cache and non-cache data tests sample
+        *
+        * @return array
+        */
+       public function getCacheNonCacheDataProvider() {
+               return array(
+                       array(
+
+                               // #0 Invoke different A & B count but expect 
that
+                               // A value is returned for both since cache is 
enabled
+                               array( 'cacheEnabled' => true,  'A' => 1001, 
'B' => 9001 ),
+                               array( 'A' => 1001, 'B' => 1001 )
+                       ),
+                       array(
+
+                               // #1 Invoke different A & B count and expect 
that since
+                               // cache is disabled the original result is 
returned
+                               array( 'cacheEnabled' => false, 'A' => 2001, 
'B' => 9001 ),
+                               array( 'A' => 2001, 'B' => 9001 )
+                       )
+               );
+       }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/60092
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id189dd17c7e2591764896baf6e344b4590ca65e4
Gerrit-PatchSet: 8
Gerrit-Project: mediawiki/extensions/SemanticMediaWiki
Gerrit-Branch: master
Gerrit-Owner: Mwjames <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Markus Kroetzsch <[email protected]>
Gerrit-Reviewer: Mwjames <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to