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