diff --git a/.gitignore b/.gitignore index b11e888..c42e17f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ composer.lock /drush/ /vendor/ +.DS_Store diff --git a/circle.yml b/circle.yml index 31f760a..9723db3 100644 --- a/circle.yml +++ b/circle.yml @@ -4,67 +4,41 @@ machine: # https://circleci.com/docs/environment#php version: 5.6.14 environment: - # DB config. Using default CircleCI's database. - DB_NAME: "circle_test" - DB_USERNAME: "ubuntu" - DB_PASSWORD: "" - DOCROOT: "$HOME/drupalcore" - SERVER: server.local - WEB_USER: $(whoami) - WEB_GROUP: www-data - hosts: - server.local: 127.0.0.1 + TERMINUS_ENV: ci-$CIRCLE_BUILD_NUM + TERMINUS_SITE: d8lcache + DRUPAL_ADMIN_USERNAME: pantheon + # A random password is set in the dependencies:pre stage as a text file. + # This line reads the same file repeatedly. If the openssl call were used + # in this step, it would result in a different password being used in each + # line of other steps. Each CircleCI command runs in a separate shell. + DRUPAL_ADMIN_PASSWORD: $(cat ~/DRUPAL_ADMIN_PASSWORD) dependencies: cache_directories: - ~/.composer/cache pre: + - echo $(openssl rand -hex 8) > ~/DRUPAL_ADMIN_PASSWORD + # Set the PHP timezone so that Behat script does not fail. + # Using > instead of >> will overwrite the file and disable xdebug. + # xdebug makes composer slower. + #############- echo "date.timezone = 'US/Central'" > /opt/circleci/php/7.0.7/etc/conf.d/xdebug.ini + - git config --global user.email "noreply@pantheon.io" + - git config --global user.name "Circle CI" + override: - composer global require "hirak/prestissimo:^0.3" + - composer global require pantheon-systems/terminus "<0.13.0" - composer global require drush/drush:8.* - # @todo, composer is probably a bad/slow way to install core here. - # Use something like drush's - - git clone --branch 8.1.x https://git.drupal.org/project/drupal.git $DOCROOT - - cd $DOCROOT && composer install - # Add apache config. - # Modify user to make sure that there will be no permission issues. - - sudo usermod -a -G $WEB_GROUP $WEB_USER - # Add apache config. - - | - echo " - UseCanonicalName Off - DocumentRoot %DOCROOT% - ServerName %SERVER% - - Options FollowSymLinks - AllowOverride All - RewriteEngine On - RewriteBase / - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule %DOCROOT%/(.*)$ index.php/?q=$1 [L,QSA] - Order allow,deny - Allow from all - - " > apache-vhost.conf - - cp apache-vhost.conf /etc/apache2/sites-available/default - - sudo sed -e "s?%DOCROOT%?$DOCROOT?g" --in-place /etc/apache2/sites-available/default - - sudo sed -e "s?%SERVER%?$SERVER?g" --in-place /etc/apache2/sites-available/default - - sudo a2enmod rewrite - - sudo service apache2 restart + - composer install + post: + - terminus auth login --machine-token=$TERMINUS_TOKEN test: pre: - # Copy the settings.local into place - # Disable sendmail binary to suppress any mailouts. - - echo 'sendmail_path = /bin/true' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/circle.ini - - drush --yes --root=$DOCROOT site-install --db-url=mysql://$DB_USERNAME:$DB_PASSWORD@127.0.01/$DB_NAME - - curl $SERVER - - cd $DOCROOT && drush en simpletest -y - - cd $DOCROOT && composer config repositories.d8lcache vcs git@github.com:lcache/drupal-8.git - - cd $DOCROOT && composer require "drupal/lcache:dev-master#$CIRCLE_SHA1" - - cd $DOCROOT && drush en lcache -y - - override: - - ./vendor/bin/phpcs --report=full --extensions=php,module,inc,theme,info --standard=vendor/drupal/coder/coder_sniffer/Drupal/ --ignore=vendor . - - cd $DOCROOT && /home/ubuntu/.phpenv/shims/php core/scripts/run-tests.sh --url $SERVER --module lcache --php /home/ubuntu/.phpenv/shims/php --verbose --color - - + #- ./vendor/bin/phpcs --report=full --extensions=php,module,inc,theme,info,install --standard=vendor/drupal/coder/coder_sniffer/Drupal . --ignore=vendor,modules,core,drush,patches,tests + # Make a new multidev env from a vanilla D8 site. + - cd tests/circle-scripts && ./create-fresh-d8-site.sh + - cd tests/circle-scripts && ./clone-repo.sh + - cd tests/circle-scripts && ./core-vs-lcache.sh + # + # - cd tests/circle-scripts && ./enable-modules.sh + # override: + # - cd tests/circle-scripts && ./run-tests.sh diff --git a/composer.json b/composer.json index e5d2695..dc04c44 100644 --- a/composer.json +++ b/composer.json @@ -10,10 +10,18 @@ } ], "require": { - "lcache/lcache": "v0.3.*" + "lcache/lcache": "0.3.*" }, "require-dev": { + "phpunit/phpunit": "4.*", + "phpunit/dbunit": "*", "drupal/coder": "^8.2.0-beta1", - "squizlabs/php_codesniffer": "2.0.*@dev" - } + "squizlabs/php_codesniffer": "2.0.*@dev", + "drush-ops/behat-drush-endpoint": "*", + "drupal/drupal-extension": "dev-master", + "drupal/drupal-driver": "dev-master" + }, + "autoload": { + "psr-4": { "Drupal\\LCache\\Behat\\": "tests/behat/bootstrap/" } + } } diff --git a/src/Backend.php b/src/Backend.php index 07b9bfc..e4c414a 100644 --- a/src/Backend.php +++ b/src/Backend.php @@ -72,7 +72,6 @@ public function get($cid, $allow_invalid = FALSE) { if (is_null($entry->expiration)) { $entry->expiration = CacheBackendInterface::CACHE_PERMANENT; } - $response->expire = $entry->expiration; return $response; } @@ -81,9 +80,11 @@ public function get($cid, $allow_invalid = FALSE) { * {@inheritdoc} */ public function getMultiple(&$cids, $allow_invalid = FALSE) { + if (empty($cids)) { return; } + $cache = array(); foreach ($cids as $cid) { $c = $this->get($cid); @@ -91,6 +92,7 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) { $cache[$cid] = $c; } } + $cids = array_diff($cids, array_keys($cache)); return $cache; } diff --git a/src/BackendFactory.php b/src/BackendFactory.php index bc21d44..d95ffbd 100644 --- a/src/BackendFactory.php +++ b/src/BackendFactory.php @@ -41,7 +41,7 @@ public function __construct(Connection $connection) { $l1 = new \LCache\APCuL1(); } $l2 = new \LCache\DatabaseL2($this->getPdoHandle()); - $this->integrated = new \LCache\Integrated($l1, $l2); + $this->integrated = new \LCache\Integrated($l1, $l2, 100); $this->integrated->synchronize(); } diff --git a/tests/behat/behat-pantheon.yml b/tests/behat/behat-pantheon.yml new file mode 100644 index 0000000..639d06f --- /dev/null +++ b/tests/behat/behat-pantheon.yml @@ -0,0 +1,22 @@ +# +# behat.yml file for testing with a Drupal site on Pantheon. +# +default: + suites: + default: + contexts: + - Drupal\DrupalExtension\Context\DrupalContext + - Drupal\DrupalExtension\Context\DrushContext + - Drupal\DrupalExtension\Context\MinkContext + - Drupal\LCache\Behat\PerformanceHelpers + extensions: + Behat\MinkExtension: + goutte: ~ +# Supplied by env variable. +# base_url: http://dev-d8lcache.pantheonsite.io/ + Drupal\DrupalExtension: + blackbox: ~ + api_driver: 'drush' + drush: +# Supplied by env variable. +# alias: '@pantheon.d8lcache.dev' diff --git a/tests/behat/bootstrap/PerformanceHelpers.php b/tests/behat/bootstrap/PerformanceHelpers.php new file mode 100644 index 0000000..207d672 --- /dev/null +++ b/tests/behat/bootstrap/PerformanceHelpers.php @@ -0,0 +1,133 @@ +getEnvironment(); + $this->minkContext = $environment->getContext('Drupal\DrupalExtension\Context\MinkContext'); + } + + /** + * Fills in form field with specified id|name|label|value + * Example: When I fill in "admin_password2" with a random string "12" characters long + * + * @When I fill in :arg1 with a random string :arg2 characters long + */ + public function fillFieldWithRandomString($field, $length) + { + $this->minkContext->fillField($field, $this->rand_string( $length )); + } + + protected function rand_string( $length ) { + $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + $str = ''; + $size = strlen( $chars ); + for( $i = 0; $i < $length; $i++ ) { + $str .= $chars[ rand( 0, $size - 1 ) ]; + } + + return $str; + } + + + /** + * @When I open the links to all homepage posts + */ + public function iOpenTheLinksToAllHomepagePosts() + { + + $this->minkContext->visit("/"); + + $next_page_exists = TRUE; + $next_page_url =''; + + while($next_page_exists) { + + $page = $this->minkContext->getSession()->getPage(); + $next_page_link = $page->find('css', '.pager__item--next a'); + //echo $this->minkContext->getSession()->getPage()->find('css', '.pager__items')->getHtml(); + if ($next_page_link) { + $next_page_url = $next_page_link->getAttribute('href'); + } + else { + $next_page_exists = FALSE; + } + + $this->openAllPostLinksOnASinglePage($page); + + if (!empty($next_page_link)) { + $this->minkContext->visit($next_page_url); + + print_r("\n\n"); + print_r($next_page_url); + print_r("\n\n"); + + //print_r($this->minkContext->getSession()->getResponseHeaders()); + } + } + echo "last page visited was $next_page_url"; + } + + + protected function openAllPostLinksOnASinglePage($page) { + + $post_urls = $this->getAllPostURLs($page); + + foreach ($post_urls as $post_url) { + $this->minkContext->visit($post_url); + //echo "\n"; + //echo $this->minkContext->getSession()->getPage()->find('css', 'h1.page-title')->getHtml(); + //echo "\n"; + //$this->minkContext->printCurrentUrl(); + //echo "\n"; + //print_r($this->minkContext->getSession()->getResponseHeaders()); + } + + } + + protected function getAllPostURLs($page) { + + $post_links = $page->findAll('css', 'article header h2 a'); + + $post_urls = []; + foreach ($post_links as $post_link) { + $post_urls[] =$post_link->getAttribute('href'); + } + + //print_r("\n\n"); + //print_r($post_urls[0]); + //print_r("\n\n"); + return $post_urls; + } + + /** + * @Given I log in as an admin + */ + public function ILogInAsAnAdmin() + { + $this->minkContext->visit('user'); + $this->minkContext->fillField('name', getenv('DRUPAL_ADMIN_USERNAME')); + $this->minkContext->fillField('pass', getenv('DRUPAL_ADMIN_PASSWORD')); + $this->minkContext->pressButton('Log in'); + //$this->minkContext->printCurrentUrl(); + $this->minkContext->visit('admin'); + //$this->minkContext->printCurrentUrl(); + + } + +} diff --git a/tests/behat/features/create-node-view-all-nodes.feature b/tests/behat/features/create-node-view-all-nodes.feature new file mode 100644 index 0000000..c413ff6 --- /dev/null +++ b/tests/behat/features/create-node-view-all-nodes.feature @@ -0,0 +1,32 @@ +Feature: Create node, view all nodes + + + + Background: + Given I log in as an admin + + @api + Scenario: Create node, view all nodes + + +When I visit "node/add/article" +And I fill in "title[0][value]" with "Test article title" +And I fill in "title[0][value]" with a random string "12" characters long +And I press the "Save and publish" button + +When I visit "node/add/article" +And I fill in "title[0][value]" with "Test article title" +And I fill in "title[0][value]" with a random string "12" characters long +And I press the "Save and publish" button + +When I visit "node/add/article" +And I fill in "title[0][value]" with "Test article title" +And I fill in "title[0][value]" with a random string "12" characters long +And I press the "Save and publish" button + +When I visit "node/add/article" +And I fill in "title[0][value]" with "Test article title" +And I fill in "title[0][value]" with a random string "12" characters long +And I press the "Save and publish" button + +When I open the links to all homepage posts diff --git a/tests/behat/features/node-saving.feature b/tests/behat/features/node-saving.feature new file mode 100644 index 0000000..95c3339 --- /dev/null +++ b/tests/behat/features/node-saving.feature @@ -0,0 +1,11 @@ +Feature: Node saving + + @api + Scenario: Node Saving + Given I am logged in as a user with the "administrator" role + And I visit "/" + When I visit "node/add/article" + And I fill in "title[0][value]" with "First Test Article" + And I press the "Save and publish" button + And I visit "/" + Then I see the text "First Test Article" diff --git a/tests/circle-scripts/clone-repo.sh b/tests/circle-scripts/clone-repo.sh new file mode 100755 index 0000000..92c8301 --- /dev/null +++ b/tests/circle-scripts/clone-repo.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +git clone $(terminus site connection-info --field=git_url) $TERMINUS_SITE +cd $TERMINUS_SITE +git checkout $TERMINUS_ENV diff --git a/tests/circle-scripts/core-vs-lcache.sh b/tests/circle-scripts/core-vs-lcache.sh new file mode 100755 index 0000000..1ac15ad --- /dev/null +++ b/tests/circle-scripts/core-vs-lcache.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +set -ex + +# Create a drush alias file so that Behat tests can be executed against Pantheon. +terminus sites aliases +# Drush Behat driver fails without this option. +echo "\$options['strict'] = 0;" >> ~/.drush/pantheon.aliases.drushrc.php +export BEHAT_PARAMS='{"extensions" : {"Behat\\MinkExtension" : {"base_url" : "http://'$TERMINUS_ENV'-'$TERMINUS_SITE'.pantheonsite.io/"}, "Drupal\\DrupalExtension" : {"drush" : { "alias": "@pantheon.'$TERMINUS_SITE'.'$TERMINUS_ENV'" }}}}' +terminus site set-connection-mode --mode=git + +cd ${TERMINUS_SITE} +git checkout master +git branch -D $TERMINUS_ENV +git pull +git checkout -b $TERMINUS_ENV + +echo "php_version: 7.0 " >> pantheon.yml + +git add pantheon.yml +git commit -m 'Clean install of Drupal Core' +git push --set-upstream origin $TERMINUS_ENV -f + +sleep 30 +{ + terminus drush "si -y" +} &> /dev/null +terminus site clear-cache + + + +# Make a custom admin user because the normal Drush/Behat way of creating users +# 1) is slow and 2) would require rerunning with each Behat run and 3) +# would result nodes getting deleted at the end of each run. +{ + terminus drush "user-create $DRUPAL_ADMIN_USERNAME" + terminus drush "user-add-role administrator $DRUPAL_ADMIN_USERNAME" + terminus drush "upwd $DRUPAL_ADMIN_USERNAME --password=$DRUPAL_ADMIN_PASSWORD" +} &> /dev/null + + +for i in $(seq 50); do + echo "Peformance test pass $i with Core" + ./../../../vendor/bin/behat --config=../../behat/behat-pantheon.yml ../../behat/features/create-node-view-all-nodes.feature +done + + + + +sleep 15 + +# Set up LCache repo +#composer config repositories.drupal composer https://packages.drupal.org/8 +composer config repositories.d8lcache vcs git@github.com:lcache/drupal-8.git +composer require drupal/lcache:dev-master#$CIRCLE_SHA1 + +# A .git directory might in modules/lcache/ +git add modules/lcache/* +git add . +git commit -m 'Adding LCache' +git push + +sleep 60 +{ + terminus drush "si -y" +} &> /dev/null +terminus drush "en lcache -y" +terminus site clear-cache + +# echo "\$settings['cache']['default'] = 'cache.backend.lcache';" >> sites/default/settings.php + +# Swap services for the bins otherwise using ChainedFastBackend +#echo "\$settings['cache']['bins']['bootstrap'] = 'cache.backend.lcache';" >> sites/default/settings.php +#echo "\$settings['cache']['bins']['config'] = 'cache.backend.lcache';" >> sites/default/settings.php +#echo "\$settings['cache']['bins']['discovery'] = 'cache.backend.lcache';" >> sites/default/settings.php + +# Swap services for render, and dynamic page cache. +#echo "\$settings['cache']['bins']['render'] = 'cache.backend.lcache';" >> sites/default/settings.php +#echo "\$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.lcache';" >> sites/default/settings.php +# echo "\$settings['cache']['bins']['toolbar'] = 'cache.backend.lcache';" >> sites/default/settings.php +echo "\$settings['cache']['bins']['menu'] = 'cache.backend.lcache';" >> sites/default/settings.php +#echo "\$settings['cache']['bins']['entity'] = 'cache.backend.lcache';" >> sites/default/settings.php# +#echo "\$settings['cache']['bins']['data'] = 'cache.backend.lcache';" >> sites/default/settings.php + +git add . +git commit -m 'LCache for menu bin' +git push origin $TERMINUS_ENV + + +# Make a custom admin user because the normal Drush/Behat way of creating users +# 1) is slow and 2) would require rerunning with each Behat run and 3) +# would result nodes getting deleted at the end of each run. +{ + terminus drush "user-create $DRUPAL_ADMIN_USERNAME" + terminus drush "user-add-role administrator $DRUPAL_ADMIN_USERNAME" + terminus drush "upwd $DRUPAL_ADMIN_USERNAME --password=$DRUPAL_ADMIN_PASSWORD" +} &> /dev/null + + +for i in $(seq 50); do + echo "Peformance test pass $i with LCache" + ./../../../vendor/bin/behat --config=../../behat/behat-pantheon.yml ../../behat/features/create-node-view-all-nodes.feature +done + + +terminus site clear-cache diff --git a/tests/circle-scripts/create-fresh-d8-site.sh b/tests/circle-scripts/create-fresh-d8-site.sh new file mode 100755 index 0000000..c213e77 --- /dev/null +++ b/tests/circle-scripts/create-fresh-d8-site.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +# @todo, pull in upstream updates, wipe and install drupal. +# Also, it might be cleaner to create an entirely new D8 site rather than making +# multidevs off of the same one repeatedly. +terminus site create-env --to-env=$TERMINUS_ENV --from-env=dev