<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[4725] sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/tests/phpunit/tests/wporg-plugin-api-performance.php: Plugin directory tests: add crude API performance tests.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/4725">4725</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/4725","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>tellyworth</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2017-01-18 23:59:05 +0000 (Wed, 18 Jan 2017)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Plugin directory tests: add crude API performance tests.

PHPUnit is not the right tool for this, but it's a start.</pre>

<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorytestsphpunittestswporgpluginapiperformancephp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/tests/phpunit/tests/wporg-plugin-api-performance.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectorytestsphpunittestswporgpluginapiperformancephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/tests/phpunit/tests/wporg-plugin-api-performance.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/tests/phpunit/tests/wporg-plugin-api-performance.php                            (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/tests/phpunit/tests/wporg-plugin-api-performance.php      2017-01-18 23:59:05 UTC (rev 4725)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,176 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
+
+
+/**
+ * @test
+ * @group plugins-api
+ * @group performance
+ */
+
+class Tests_Plugins_API_Performance extends WP_UnitTestCase {
+
+       public $api_endpoint_1_0 = 'http://api.wordpress.org/plugins/info/1.0/';
+       public $api_endpoint_1_1 = 'http://api.wordpress.org/plugins/info/1.1/';
+       public $api_endpoint_plugin_php = 'http://api.wordpress.org/plugins/info/1.0/jetpack.php';
+       public $api_endpoint_plugin_xml = 'http://api.wordpress.org/plugins/info/1.0/jetpack.xml';
+       public $api_endpoint_plugin_json = 'http://api.wordpress.org/plugins/info/1.0/jetpack.json';
+
+       public $user_agent = 'WordPress/4.8'; // Tell the API to use the v3 back-end
+       public $timeout_seconds = 5.0;
+
+       public $fields = array(
+               'short_description' => true,
+               'description'       => true,
+               'sections'          => true,
+               'tested'            => true,
+               'requires'          => true,
+               'rating'            => true,
+               'ratings'           => true,
+               'downloaded'        => true,
+               'downloadlink'      => true,
+               'last_updated'      => true,
+               'added'             => true,
+               'tags'              => true,
+               'compatibility'     => true,
+               'homepage'          => true,
+               'versions'          => true,
+               'stable_tag'        => true,
+               'donate_link'       => true,
+               'reviews'           => true,
+               'banners'           => true,
+               'icons'             => true,
+               'active_installs'   => true,
+               'contributors'      => true,
+       );
+
+       function setUp() {
+               parent::setUp();
+               add_filter( 'http_headers_useragent', array( $this, 'filter_http_headers_useragent' ) );
+       }
+
+       function tearDown() {
+               remove_filter( 'http_headers_useragent', array( $this, 'filter_http_headers_useragent' ) );
+               parent::tearDown();
+       }
+
+       static function averages( $values, $decimals = 4 ) {
+               sort( $values, SORT_NUMERIC );
+               $mean = array_sum( $values ) / count( $values );
+
+               $median = $values[ floor( count( $values ) / 2 ) ];
+
+               return "mean ". number_format( $mean, $decimals ) . ", median " . number_format( $median, $decimals );
+
+       }
+
+       static function tearDownAfterClass() {
+               global $wporg_plugin_api_performance;
+
+               echo "Performance summary for ". get_called_class() . ":\n";
+               foreach ( $wporg_plugin_api_performance[ get_called_class() ] as $type => $deltas ) {
+                       echo "$type: " . self::averages( $deltas ) . "\n";
+               }
+       }
+
+       // Override the user-agent header in plugins_api() requests to force the API to use the new WP codebase.
+       function filter_http_headers_useragent( $user_agent ) {
+               return $this->user_agent;
+       }
+
+       function api_remote_post( $url, $action, $request ) {
+               return wp_remote_post( $url, array(
+                       'timeout' => $this->timeout_seconds,
+                       'body'    => array(
+                               'action'  => $action,
+                               'request' => serialize( (object) $request ),
+                       ),
+                       'headers' => array( 'Host', 'api.wordpress.org' ),
+               ) );
+       }
+
+       function api_remote_get( $url ) {
+               return wp_remote_get( $url, array(
+                       'timeout' => $this->timeout_seconds,
+                       'headers' => array( 'Host', 'api.wordpress.org' ),
+               ) );
+       }
+
+       function performanceTestProvider() {
+
+               // The 50 most common plugin tags
+               $common_terms = explode( ' ', 'widget post admin woocommerce posts comments shortcode twitter google images facebook sidebar image seo page gallery social email links login ecommerce widgets video rss buddypress pages jquery spam content security ajax media slider feed category search analytics menu embed javascript e-commerce link css form comment share youtube custom categories theme');
+
+               // Each item represents the function arguments to a plugins_api() call.
+               $r = array(
+                       array( 'plugin_information', array( 'slug' => 'jetpack', 'fields' => $this->fields ) ),
+                       array( 'query_plugins', array( 'browse' => 'updated', 'per_page' => 24, 'page'=> 103, 'fields' => $this->fields )),
+                       array( 'query_plugins', array( 'user' => 'dd32', 'fields' => $this->fields )),
+                       array( 'query_plugins', array( 'browse' => 'popular', 'per_page' => 20, 'fields' => $this->fields ) ),
+                       array( 'query_plugins', array( 'browse' => 'recommended', 'installed_plugins' => array( 'akismet', 'jetpack' ), 'fields' => $this->fields ) )
+               );
+
+               // 20 random searches
+               for ( $i=0; $i < 20; $i++ ) {
+                       $random_search = join( ' ', array_rand( array_flip( $common_terms ), 3 ) ); // 3 random terms
+                       $r[] = array( 'query_plugins', array( 'search'   => $random_search, 'per_page' => 15, 'page' => 3, 'fields' => $this->fields ) );
+               }
+
+               // 100 recently updated plugins
+               $recently_updated_plugins = plugins_api( 'query_plugins',
+                               array(
+                                       'browse' => 'updated',
+                                       'fields' => array( 'description' => false, 'short_description' => false ),
+                                       'per_page' => 100,
+                                       'page' => rand(0 , 400),
+                                       )
+                               );
+               $this->assertFalse( is_wp_error( $recently_updated_plugins ) );
+               $this->assertEquals( 100, count( $recently_updated_plugins->plugins ));
+               foreach ( $recently_updated_plugins->plugins as $plugin )
+                       $r[] = array( 'plugin_information', array( 'slug' => $plugin->slug, 'fields' => $this->fields ) );
+
+               return $r;
+
+       }
+
+       /**
+        *
+        * @dataProvider performanceTestProvider
+        */
+        function test_api_performance( $action, $args ) {
+               global $wporg_plugin_api_performance;
+
+               $start = microtime( true );
+               $response = plugins_api( $action, $args );
+               $delta = microtime( true ) - $start;
+
+               #error_log( get_class( $this ) . ": $action ". array_keys($args)[0]." ".array_values($args)[0]." took $delta" );
+               $wporg_plugin_api_performance[ get_class( $this ) ][ $action . ' ' . array_keys($args)[0] ][] = $delta;
+
+               $this->assertLessThan( $this->timeout_seconds, $delta, "API call $action took $delta seconds" );
+
+               // Make sure it has returned a result of some kind and not an error or empty set
+               $this->assertFalse( is_wp_error( $response ), "API call $action returned error" );
+               if ( $action === 'plugin_information' ) {
+                       $this->assertObjectHasAttribute( 'slug', $response, 'Slug exits' );
+               } else {
+                       $this->assertObjectHasAttribute( 'info', $response, 'Info exists' );
+                       $this->assertObjectHasAttribute( 'plugins', $response, 'Plugins exists' );
+                       $this->assertAttributeInternalType( 'array', 'plugins', $response, 'Plugins should be an array' );
+                       $this->greaterThanOrEqual( count( $response->plugins ), 1 );
+               }
+       }
+
+}
+
+/**
+ * @test
+ * @group plugins-api
+ * @group performance
+ */
+
+class Tests_Plugins_API_Performance_Old extends Tests_Plugins_API_Performance {
+       public $user_agent = 'WordPress/4.7'; // Tell the API to use the v3 back-end
+}
</ins></span></pre>
</div>
</div>

</body>
</html>