diff --git a/core/composer.json b/core/composer.json index 459c00c..4a109a2 100644 --- a/core/composer.json +++ b/core/composer.json @@ -2,22 +2,28 @@ "name": "drupal/drupal", "description": "Drupal is an open source content management platform powering millions of websites and applications.", "license": "GPL-2.0+", + "repositories": [{ + "type": "vcs", + "url": "https://github.com/msonnabaum/phpunit.git" + } + ], "require": { - "symfony/class-loader": "<2.4", - "symfony/dependency-injection": "<2.4", - "symfony/event-dispatcher": "<2.4", - "symfony/http-foundation": "<2.4", - "symfony/http-kernel": "<2.4", - "symfony/routing": "<2.4", + "symfony/class-loader": "2.2.0-BETA2", + "symfony/dependency-injection": "2.2.0-BETA2", + "symfony/event-dispatcher": "2.2.0-BETA2", + "symfony/http-foundation": "2.2.0-BETA2", + "symfony/http-kernel": "2.2.0-BETA2", + "symfony/routing": "2.2.0-BETA2", "symfony/serializer": "2.2.0-BETA2", - "symfony/validator": "<2.4", - "symfony/yaml": "<2.4", - "twig/twig": "1.*@stable", - "doctrine/common": "2.3.*@stable", - "guzzle/http": "3.1.*@stable", - "kriswallsmith/assetic": "1.1.*@alpha", + "symfony/validator": "2.2.0-BETA2", + "symfony/yaml": "2.2.0-BETA2", + "twig/twig": "1.12.1", + "doctrine/common": "2.3.0", + "guzzle/http": "3.1.0", + "kriswallsmith/assetic": "1.1.0-alpha1", "symfony-cmf/routing": "dev-master#ea4a10", - "easyrdf/easyrdf": "dev-master" + "easyrdf/easyrdf": "0.8.0-beta.1", + "phpunit/phpunit": "3.7 as dev-3.7" }, "minimum-stability": "dev" } diff --git a/core/composer.lock b/core/composer.lock index 6eb40a1..6198c2d 100644 --- a/core/composer.lock +++ b/core/composer.lock @@ -1,5 +1,5 @@ { - "hash": "c087560024f328e26e2ed57c9b2aa703", + "hash": "a8c56a3549ec70f775e4bf795e65a993", "packages": [ { "name": "doctrine/common", @@ -56,7 +56,7 @@ { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com", - "homepage": "http://jmsyst.com", + "homepage": "https://github.com/schmittjoh", "role": "Developer of wrapped JMSSerializerBundle" } ], @@ -72,16 +72,16 @@ }, { "name": "easyrdf/easyrdf", - "version": "dev-master", + "version": "0.8.0-beta.1", "source": { "type": "git", "url": "git://github.com/njh/easyrdf.git", - "reference": "d1c363bd04cd55169fbefe52328e86031c6db3a2" + "reference": "0.8.0-beta.1" }, "dist": { "type": "zip", - "url": "https://github.com/njh/easyrdf/archive/d1c363bd04cd55169fbefe52328e86031c6db3a2.zip", - "reference": "d1c363bd04cd55169fbefe52328e86031c6db3a2", + "url": "https://github.com/njh/easyrdf/archive/0.8.0-beta.1.zip", + "reference": "0.8.0-beta.1", "shasum": "" }, "require": { @@ -95,7 +95,7 @@ "squizlabs/php_codesniffer": ">=1.4.3", "sami/sami": "dev-master" }, - "time": "2013-01-13 01:20:04", + "time": "2013-01-18 15:54:28", "type": "library", "autoload": { "psr-0": { @@ -379,6 +379,399 @@ ] }, { + "name": "phpunit/php-code-coverage", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "git://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "ec7f6f388ca315b6520f61be670ff82fa6ce68fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ec7f6f388ca315b6520f61be670ff82fa6ce68fb", + "reference": "ec7f6f388ca315b6520f61be670ff82fa6ce68fb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": ">=1.3.0@stable", + "phpunit/php-token-stream": ">=1.1.3@stable", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "suggest": { + "ext-dom": "*", + "ext-xdebug": ">=2.0.5" + }, + "time": "2013-01-07 10:45:42", + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "testing", + "coverage", + "xunit" + ] + }, + { + "name": "phpunit/php-file-iterator", + "version": "dev-master", + "source": { + "type": "git", + "url": "git://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "2deb24c65ea78e126daa8d45b2089ddc29ec1d26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2deb24c65ea78e126daa8d45b2089ddc29ec1d26", + "reference": "2deb24c65ea78e126daa8d45b2089ddc29ec1d26", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2013-01-07 10:47:05", + "type": "library", + "autoload": { + "classmap": [ + "File/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ] + }, + { + "name": "phpunit/php-text-template", + "version": "dev-master", + "source": { + "type": "git", + "url": "git://github.com/sebastianbergmann/php-text-template.git", + "reference": "1eeef106193d2f8c539728e566bb4793071a9e18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/1eeef106193d2f8c539728e566bb4793071a9e18", + "reference": "1eeef106193d2f8c539728e566bb4793071a9e18", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2013-01-07 10:56:17", + "type": "library", + "autoload": { + "classmap": [ + "Text/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ] + }, + { + "name": "phpunit/php-timer", + "version": "1.0.x-dev", + "source": { + "type": "git", + "url": "git://github.com/sebastianbergmann/php-timer.git", + "reference": "ecf7920b27003a9412b07dad79dbb5ad1249e6c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/ecf7920b27003a9412b07dad79dbb5ad1249e6c3", + "reference": "ecf7920b27003a9412b07dad79dbb5ad1249e6c3", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2013-01-30 06:08:51", + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ] + }, + { + "name": "phpunit/php-token-stream", + "version": "dev-master", + "source": { + "type": "git", + "url": "git://github.com/sebastianbergmann/php-token-stream.git", + "reference": "c25dd88e1592e66dee2553c99ef244203d5a1b98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c25dd88e1592e66dee2553c99ef244203d5a1b98", + "reference": "c25dd88e1592e66dee2553c99ef244203d5a1b98", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.3.3" + }, + "time": "2013-01-07 10:56:35", + "type": "library", + "autoload": { + "classmap": [ + "PHP/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Wrapper around PHP's tokenizer extension.", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "keywords": [ + "tokenizer" + ] + }, + { + "name": "phpunit/phpunit", + "version": "3.7.0", + "source": { + "type": "git", + "url": "https://github.com/msonnabaum/phpunit.git", + "reference": "3.7.0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/msonnabaum/phpunit/zipball/3.7.0", + "reference": "3.7.0", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-file-iterator": ">=1.3.1@stable", + "phpunit/php-text-template": ">=1.1.1@stable", + "phpunit/php-code-coverage": ">=1.2.0@stable", + "phpunit/php-timer": ">=1.0.2@stable", + "phpunit/phpunit-mock-objects": ">=1.2.0@stable", + "symfony/yaml": ">=2.1.0@stable", + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*" + }, + "suggest": { + "phpunit/php-invoker": ">=1.1.0@stable", + "ext-json": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*" + }, + "time": "2012-09-19 05:07:48", + "bin": [ + "composer/bin/phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.7.x-dev" + } + }, + "autoload": { + "files": [ + "PHPUnit/Autoload.php" + ] + }, + "include-path": [ + "", + "../../symfony/yaml/" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "http://www.phpunit.de/", + "keywords": [ + "phpunit", + "xunit", + "testing" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "irc": "irc://irc.freenode.net/phpunit", + "source": "https://github.com/msonnabaum/phpunit/tree/3.7.0" + } + }, + { + "name": "phpunit/phpunit-mock-objects", + "version": "1.2.x-dev", + "source": { + "type": "git", + "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "d49b5683200b5db9b1c64cb06f52f50d147891c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/d49b5683200b5db9b1c64cb06f52f50d147891c4", + "reference": "d49b5683200b5db9b1c64cb06f52f50d147891c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "phpunit/php-text-template": ">=1.1.1@stable" + }, + "suggest": { + "ext-soap": "*" + }, + "time": "2013-02-05 07:46:41", + "type": "library", + "autoload": { + "classmap": [ + "PHPUnit/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sb@sebastian-bergmann.de", + "role": "lead" + } + ], + "description": "Mock Object library for PHPUnit", + "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "keywords": [ + "mock", + "xunit" + ] + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log", + "reference": "1.0.0" + }, + "dist": { + "type": "zip", + "url": "https://github.com/php-fig/log/archive/1.0.0.zip", + "reference": "1.0.0", + "shasum": "" + }, + "time": "2012-12-21 11:40:51", + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, + { "name": "symfony-cmf/routing", "version": "dev-master", "target-dir": "Symfony/Cmf/Component/Routing", @@ -389,7 +782,7 @@ }, "dist": { "type": "zip", - "url": "https://github.com/symfony-cmf/Routing/archive/ea4a10dd971580a9a57a69397f165e25233ba667.zip", + "url": "https://api.github.com/repos/symfony-cmf/Routing/zipball/72df1da07b3c4edf16df169fb7987f504070fe0d", "reference": "ea4a10", "shasum": "" }, @@ -429,17 +822,17 @@ }, { "name": "symfony/class-loader", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/ClassLoader", "source": { "type": "git", "url": "https://github.com/symfony/ClassLoader", - "reference": "0730d0f8f99cfeafbc23271f1e87f54da15f1e06" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/ClassLoader/archive/0730d0f8f99cfeafbc23271f1e87f54da15f1e06.zip", - "reference": "0730d0f8f99cfeafbc23271f1e87f54da15f1e06", + "url": "https://api.github.com/repos/symfony/ClassLoader/zipball/v2.2.0-BETA2", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { @@ -448,7 +841,7 @@ "require-dev": { "symfony/finder": "2.2.*" }, - "time": "2013-01-04 16:58:00", + "time": "2013-01-23 20:21:00", "type": "library", "extra": { "branch-alias": { @@ -479,17 +872,17 @@ }, { "name": "symfony/dependency-injection", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/DependencyInjection", "source": { "type": "git", "url": "https://github.com/symfony/DependencyInjection", - "reference": "13b47742e1ef22aed78132e5e0930d28571142a4" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/DependencyInjection/archive/13b47742e1ef22aed78132e5e0930d28571142a4.zip", - "reference": "13b47742e1ef22aed78132e5e0930d28571142a4", + "url": "https://github.com/symfony/DependencyInjection/archive/v2.2.0-BETA2.zip", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { @@ -503,7 +896,7 @@ "symfony/yaml": "2.2.*", "symfony/config": "2.2.*" }, - "time": "2013-01-04 16:58:00", + "time": "2013-01-23 20:21:00", "type": "library", "extra": { "branch-alias": { @@ -534,17 +927,17 @@ }, { "name": "symfony/event-dispatcher", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/EventDispatcher", "source": { "type": "git", "url": "https://github.com/symfony/EventDispatcher", - "reference": "0fcc9fa82fa3ea7ec2605af2e8137698fbaca3dc" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/EventDispatcher/archive/0fcc9fa82fa3ea7ec2605af2e8137698fbaca3dc.zip", - "reference": "0fcc9fa82fa3ea7ec2605af2e8137698fbaca3dc", + "url": "https://github.com/symfony/EventDispatcher/archive/v2.2.0-BETA2.zip", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { @@ -557,7 +950,7 @@ "symfony/dependency-injection": "2.2.*", "symfony/http-kernel": "2.2.*" }, - "time": "2013-01-04 17:02:19", + "time": "2013-01-17 15:25:59", "type": "library", "extra": { "branch-alias": { @@ -588,23 +981,23 @@ }, { "name": "symfony/http-foundation", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/HttpFoundation", "source": { "type": "git", "url": "https://github.com/symfony/HttpFoundation", - "reference": "5aa0119417f1fc8de7513d9432dd2f43f9d9e97b" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/HttpFoundation/archive/5aa0119417f1fc8de7513d9432dd2f43f9d9e97b.zip", - "reference": "5aa0119417f1fc8de7513d9432dd2f43f9d9e97b", + "url": "https://github.com/symfony/HttpFoundation/archive/v2.2.0-BETA2.zip", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2013-01-04 17:02:19", + "time": "2013-01-21 16:56:55", "type": "library", "extra": { "branch-alias": { @@ -638,23 +1031,24 @@ }, { "name": "symfony/http-kernel", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/HttpKernel", "source": { "type": "git", "url": "https://github.com/symfony/HttpKernel", - "reference": "ce164c088666b80ffc116173065d504055414137" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/HttpKernel/archive/ce164c088666b80ffc116173065d504055414137.zip", - "reference": "ce164c088666b80ffc116173065d504055414137", + "url": "https://api.github.com/repos/symfony/HttpKernel/zipball/v2.2.0-BETA2", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { "php": ">=5.3.3", "symfony/event-dispatcher": "2.2.*", - "symfony/http-foundation": "2.2.*" + "symfony/http-foundation": "2.2.*", + "psr/log": ">=1.0,<2.0" }, "require-dev": { "symfony/browser-kit": "2.2.*", @@ -675,7 +1069,7 @@ "symfony/dependency-injection": "2.2.*", "symfony/finder": "2.2.*" }, - "time": "2013-01-04 16:58:00", + "time": "2013-01-24 07:15:19", "type": "library", "extra": { "branch-alias": { @@ -711,18 +1105,18 @@ "source": { "type": "git", "url": "https://github.com/symfony/Process", - "reference": "058ae5038a9623fa64b120a2d10ba81f1ade05c7" + "reference": "v2.1.7" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/Process/archive/058ae5038a9623fa64b120a2d10ba81f1ade05c7.zip", - "reference": "058ae5038a9623fa64b120a2d10ba81f1ade05c7", + "url": "https://api.github.com/repos/symfony/Process/zipball/v2.1.7", + "reference": "v2.1.7", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2012-12-06 10:00:55", + "time": "2013-01-16 09:27:54", "type": "library", "autoload": { "psr-0": { @@ -748,34 +1142,35 @@ }, { "name": "symfony/routing", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/Routing", "source": { "type": "git", "url": "https://github.com/symfony/Routing", - "reference": "87a66890450658ccac99702ac5e4f002ece9e23e" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/Routing/archive/87a66890450658ccac99702ac5e4f002ece9e23e.zip", - "reference": "87a66890450658ccac99702ac5e4f002ece9e23e", + "url": "https://api.github.com/repos/symfony/Routing/zipball/v2.2.0-BETA2", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "doctrine/common": ">=2.2,<2.4-dev", "symfony/config": "2.2.*", "symfony/yaml": "2.2.*", - "symfony/http-kernel": "2.2.*" + "symfony/http-kernel": "2.2.*", + "doctrine/common": ">=2.2,<2.4-dev", + "psr/log": ">=1.0,<2.0" }, "suggest": { - "doctrine/common": ">=2.2,<2.4-dev", "symfony/config": "2.2.*", - "symfony/yaml": "2.2.*" + "symfony/yaml": "2.2.*", + "doctrine/common": ">=2.2,<2.4-dev" }, - "time": "2012-12-28 13:21:48", + "time": "2013-01-21 16:57:32", "type": "library", "extra": { "branch-alias": { @@ -853,7 +1248,7 @@ }, { "name": "symfony/translation", - "version": "dev-master", + "version": "2.2.x-dev", "target-dir": "Symfony/Component/Translation", "source": { "type": "git", @@ -862,7 +1257,7 @@ }, "dist": { "type": "zip", - "url": "https://github.com/symfony/Translation/archive/v2.2.0-BETA2.zip", + "url": "https://api.github.com/repos/symfony/Translation/zipball/v2.2.0-BETA2", "reference": "v2.2.0-BETA2", "shasum": "" }, @@ -908,17 +1303,17 @@ }, { "name": "symfony/validator", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/Validator", "source": { "type": "git", "url": "https://github.com/symfony/Validator", - "reference": "f764b2e61c51c45f93bd4c9fe933e6a66928d2d3" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/Validator/archive/f764b2e61c51c45f93bd4c9fe933e6a66928d2d3.zip", - "reference": "f764b2e61c51c45f93bd4c9fe933e6a66928d2d3", + "url": "https://github.com/symfony/Validator/archive/v2.2.0-BETA2.zip", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { @@ -937,7 +1332,7 @@ "symfony/yaml": "2.2.*", "symfony/config": "2.2.*" }, - "time": "2013-01-24 10:00:40", + "time": "2013-01-21 16:57:12", "type": "library", "extra": { "branch-alias": { @@ -968,23 +1363,23 @@ }, { "name": "symfony/yaml", - "version": "dev-master", + "version": "v2.2.0-BETA2", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml", - "reference": "365b4df7802b9bb93084d2cc9a51fe88b488f956" + "reference": "v2.2.0-BETA2" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/Yaml/archive/365b4df7802b9bb93084d2cc9a51fe88b488f956.zip", - "reference": "365b4df7802b9bb93084d2cc9a51fe88b488f956", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.2.0-BETA2", + "reference": "v2.2.0-BETA2", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2012-12-19 07:09:49", + "time": "2013-01-23 20:21:00", "type": "library", "extra": { "branch-alias": { @@ -1015,26 +1410,26 @@ }, { "name": "twig/twig", - "version": "v1.11.1", + "version": "v1.12.1", "source": { "type": "git", "url": "git://github.com/fabpot/Twig.git", - "reference": "v1.11.1" + "reference": "v1.12.1" }, "dist": { "type": "zip", - "url": "https://github.com/fabpot/Twig/archive/v1.11.1.zip", - "reference": "v1.11.1", + "url": "https://github.com/fabpot/Twig/archive/v1.12.1.zip", + "reference": "v1.12.1", "shasum": "" }, "require": { "php": ">=5.2.4" }, - "time": "2012-11-11 17:17:59", + "time": "2013-01-15 20:03:52", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -1065,16 +1460,26 @@ ], "packages-dev": null, "aliases": [ - + { + "alias": "dev-3.7", + "alias_normalized": "dev-3.7", + "version": "3.7.0.0", + "package": "phpunit/phpunit" + } ], "minimum-stability": "dev", "stability-flags": { + "symfony/class-loader": 10, + "symfony/dependency-injection": 10, + "symfony/event-dispatcher": 10, + "symfony/http-foundation": 10, + "symfony/http-kernel": 10, + "symfony/routing": 10, "symfony/serializer": 10, - "twig/twig": 0, - "doctrine/common": 0, - "guzzle/http": 0, + "symfony/validator": 10, + "symfony/yaml": 10, "kriswallsmith/assetic": 15, "symfony-cmf/routing": 20, - "easyrdf/easyrdf": 20 + "easyrdf/easyrdf": 10 } } diff --git a/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php b/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php new file mode 100644 index 0000000..1e2524f --- /dev/null +++ b/core/modules/breakpoint/tests/Drupal/breakpoint/Tests/BreakpointMediaQueryTest.php @@ -0,0 +1,125 @@ + 'Breakpoint media query tests', + 'description' => 'Test validation of media queries.', + 'group' => 'Breakpoint', + ); + } + + /** + * Test valid media queries. + */ + public function testValidMediaQueries() { + $media_queries = array( + // Bartik breakpoints. + '(min-width: 0px)', + 'all and (min-width: 560px) and (max-width:850px)', + 'all and (min-width: 851px)', + // Seven breakpoints. + '(min-width: 0em)', + 'screen and (min-width: 40em)', + // Stark breakpoints. + '(min-width: 0px)', + 'all and (min-width: 480px) and (max-width: 959px)', + 'all and (min-width: 960px)', + // Other media queries. + '(orientation)', + 'all and (orientation)', + 'not all and (orientation)', + 'only all and (orientation)', + 'screen and (width)', + 'screen and (width: 0)', + 'screen and (width: 0px)', + 'screen and (width: 0em)', + 'screen and (min-width: -0)', + 'screen and (max-width: 0)', + 'screen and (max-width: 0.3)', + 'screen and (min-width)', + // Multiline and comments. + 'screen and /* this is a comment */ (min-width)', + "screen\nand /* this is a comment */ (min-width)", + "screen\n\nand /* this is\n a comment */ (min-width)", + // Unrecognized features are allowed. + 'screen and (-webkit-min-device-pixel-ratio: 7)', + 'screen and (min-orientation: landscape)', + 'screen and (max-orientation: landscape)', + ); + + foreach ($media_queries as $media_query) { + $this->assertTrue(Breakpoint::isValidMediaQuery($media_query), $media_query . ' is valid.'); + } + } + + /** + * Test invalid media queries. + */ + public function testInvalidMediaQueries() { + $media_queries = array( + '', + 'not (orientation)', + 'only (orientation)', + 'all and not all', + 'screen and (width: 0xx)', + 'screen and (width: -8xx)', + 'screen and (width: -xx)', + 'screen and (width: xx)', + 'screen and (width: px)', + 'screen and (width: -8px)', + 'screen and (width: -0.8px)', + 'screen and (height: 0xx)', + 'screen and (height: -8xx)', + 'screen and (height: -xx)', + 'screen and (height: xx)', + 'screen and (height: px)', + 'screen and (height: -8px)', + 'screen and (height: -0.8px)', + 'screen and (device-width: 0xx)', + 'screen and (device-width: -8xx)', + 'screen and (device-width: -xx)', + 'screen and (device-width: xx)', + 'screen and (device-width: px)', + 'screen and (device-width: -8px)', + 'screen and (device-width: -0.8px)', + 'screen and (device-height: 0xx)', + 'screen and (device-height: -8xx)', + 'screen and (device-height: -xx)', + 'screen and (device-height: xx)', + 'screen and (device-height: px)', + 'screen and (device-height: -8px)', + 'screen and (device-height: -0.8px)', + 'screen and (min-orientation)', + 'screen and (max-orientation)', + 'screen and (orientation: bogus)', + '(orientation: bogus)', + 'screen and (ori"entation: bogus)', + ); + + foreach ($media_queries as $media_query) { + try { + $this->assertFalse(Breakpoint::isValidMediaQuery($media_query), $media_query . ' is not valid.'); + } + catch (InvalidBreakpointMediaQueryException $e) { + $this->assertTrue(TRUE, sprintf('%s is not valid.', $media_query)); + } + } + } +} diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module index d7adb65..e35ce45 100644 --- a/core/modules/simpletest/simpletest.module +++ b/core/modules/simpletest/simpletest.module @@ -130,6 +130,26 @@ function simpletest_run_tests($test_list, $reporter = 'drupal') { ->useDefaults(array('test_id')) ->execute(); + $phpunit_tests = @$test_list['UnitTest'] ?: array(); + $phpunit_results = simpletest_run_phpunit_tests($test_id, $phpunit_tests); + // Insert the results of the phpunit test run into the db so the results are + // displayed along with simpletest's results. + if (!empty($phpunit_results)) { + $query = db_insert('simpletest')->fields(array_keys($phpunit_results[0])); + foreach ($phpunit_results as $result) { + $query->values($result); + } + $query->execute(); + } + + if (!array_key_exists('WebTest', $test_list) || empty($test_list['WebTest'])) { + // Early return if there are no WebTests to run. + return $test_id; + } + + // Contine with SimpleTests only. + $test_list = $test_list['WebTest']; + // Clear out the previous verbose files. file_unmanaged_delete_recursive('public://simpletest/verbose'); @@ -157,6 +177,84 @@ function simpletest_run_tests($test_list, $reporter = 'drupal') { } /** + * Executes phpunit tests and returns the results of the run. + * + * @param $test_id + * The current test ID. + * @param $unescaped_test_classnames + * An array of test class names, including full namespaces, to be passed as + * a regular expression to phpunit's --filter option. + * + * @return array + * The parsed results of phpunit's junit xml output, in the format of the + * simpletest table's schema. + */ +function simpletest_run_phpunit_tests($test_id, array $unescaped_test_classnames) { + $phpunit_file = simpletest_phpunit_xml_filepath($test_id); + simpletest_phpunit_run_command($unescaped_test_classnames, $phpunit_file); + return simpletest_phpunit_xml_to_rows($test_id, $phpunit_file); +} + +/** + * Returns the path to use for phpunit's --log-junit option. + * + * @param $test_id + * The current test ID. + * @return string + * Path to the phpunit xml file to use for the current test_id. + */ +function simpletest_phpunit_xml_filepath($test_id) { + return drupal_realpath('public://simpletest') . '/phpunit-' . $test_id . '.xml'; +} + +/** + * Returns the path to core's phpunit.xml.dist configuration file. + * + * @return string + * Path to core's phpunit.xml.dist configuration file. + */ +function simpletest_phpunit_configuration_filepath() { + return DRUPAL_ROOT . '/core/phpunit.xml.dist'; +} + +/** + * Executes the phpunit command. We do this via exec in a subshell so that the + * environment is isolated when running tests via the simpletest UI. + * + * @param array $unescaped_test_classnames + * An array of test class names, including full namespaces, to be passed as + * a regular expression to phpunit's --filter option. + * @param string $phpunit_file + * A filepath to use for phpunit's --log-junit option. + */ +function simpletest_phpunit_run_command(array $unescaped_test_classnames, $phpunit_file) { + $phpunit_bin = DRUPAL_ROOT . "/core/vendor/bin/phpunit"; + + // Double escape namespaces so they'll work in a regexp. + $escaped_test_classnames = array_map(function($class) { + return addslashes($class); + }, $unescaped_test_classnames); + + $filter_string = implode("|", $escaped_test_classnames); + + $command = array( + $phpunit_bin, + '--filter', + escapeshellarg($filter_string), + '--log-junit', + escapeshellarg($phpunit_file), + ); + + // Need to change directories before running the command so that we can use + // relative paths in the configuration file's exclusions. + $old_cwd = getcwd(); + chdir(DRUPAL_ROOT . "/core"); + $ret = exec(join($command, " ")); + chdir($old_cwd); + return $ret; +} + +/** * Batch operation callback. */ function _simpletest_batch_operation($test_list_init, $test_id, &$context) { @@ -397,10 +495,22 @@ function simpletest_classloader_register() { $matches = drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.' . $info['extension'] . '$/', $info['dir']); foreach ($matches as $name => $file) { drupal_classloader_register($name, dirname($file->uri)); + drupal_classloader()->registerNamespace('Drupal\\' . $name . '\\Tests', DRUPAL_ROOT . '/' . dirname($file->uri) . '/tests'); // While being there, prime drupal_get_filename(). drupal_get_filename($type, $name, $file->uri); } } + + // Register the core test directory so we can find Drupal\UnitTestCase. + drupal_classloader()->registerNamespace('Drupal\\Tests', DRUPAL_ROOT . '/core/tests'); + + // Manually register phpunit prefixes because they use a classmap instead of a + // prefix. This can be safely removed if we move to using composer's + // autoloader with a classmap. + drupal_classloader()->registerPrefixes(array( + 'PHPUnit' => DRUPAL_ROOT . '/core/vendor/phpunit/phpunit', + 'File_Iterator' => DRUPAL_ROOT . '/core/vendor/phpunit/php-file-iterator/', + )); } /** @@ -568,3 +678,64 @@ function simpletest_library_info() { return $libraries; } + +/** + * Get PHPUnit Classes + * + * @param bool $name_only + * If TRUE, returns a flat array of class names only. + */ +function simpletest_phpunit_get_available_tests() { + // Load the PHPUnit configuration file, which tells us where to find the tests. + $phpunit_config = simpletest_phpunit_configuration_filepath(); + $configuration = PHPUnit_Util_Configuration::getInstance($phpunit_config); + // Find all the tests and get a list of unique class names. + $test_suite = $configuration->getTestSuiteConfiguration(NULL); + $test_classes = array(); + foreach ($test_suite AS $test) { + $name = get_class($test); + if (!array_key_exists($name, $test_classes)) { + $test_classes[$name] = $test->getInfo(); + } + } + + return $test_classes; +} + +/** + * Converts phpunit's junit xml output to an array of rows that can be inserted + * into the simpletest results table. + * + * @param $test_id + * The current test ID. + * @param $phpunit_xml_file + * Path to the phpunit xml file. + */ +function simpletest_phpunit_xml_to_rows($test_id, $phpunit_xml_file) { + $contents = file_get_contents($phpunit_xml_file); + $xml = new SimpleXMLElement($contents); + $records = array(); + foreach ($xml->testsuite as $testsuite) { + foreach ($testsuite as $suite) { + foreach ($suite as $testcase) { + $message = ''; + if ($testcase->failure) { + $lines = explode("\n", $testcase->failure); + $message = $lines[2]; + } + $attributes = $testcase->attributes(); + $records[] = array( + 'test_id' => $test_id, + 'test_class' => (string)$attributes->class, + 'status' => empty($testcase->failure) ? 'pass' : 'fail', + 'message' => $message, + 'message_group' => 'Other', // TODO: Check on the proper values for this. + 'function' => $attributes->class . '->' . $attributes->name . '()', + 'line' => (string)$attributes->line, + 'file' => (string)$attributes->file, + ); + } + } + } + return $records; +} diff --git a/core/modules/simpletest/simpletest.pages.inc b/core/modules/simpletest/simpletest.pages.inc index f1d55d8..d228357 100644 --- a/core/modules/simpletest/simpletest.pages.inc +++ b/core/modules/simpletest/simpletest.pages.inc @@ -8,7 +8,7 @@ /** * List tests arranged in groups that can be selected and run. */ -function simpletest_test_form($form) { +function simpletest_test_form($form, &$form_state) { $form['tests'] = array( '#type' => 'details', '#title' => t('Tests'), @@ -21,6 +21,9 @@ function simpletest_test_form($form) { // Generate the list of tests arranged by group. $groups = simpletest_test_get_all(); + $groups['PHPUnit'] = simpletest_phpunit_get_available_tests(); + $form_state['storage']['PHPUnit'] = $groups['PHPUnit']; + foreach ($groups as $group => $tests) { $form['tests']['table'][$group] = array( '#collapsed' => TRUE, @@ -180,11 +183,15 @@ function simpletest_test_form_submit($form, &$form_state) { // Get list of tests. $tests_list = array(); simpletest_classloader_register(); + + $phpunit_all = array_keys($form_state['storage']['PHPUnit']); + foreach ($form_state['values'] as $class_name => $value) { // Since class_exists() will likely trigger an autoload lookup, // we do the fast check first. if ($value === 1 && class_exists($class_name)) { - $tests_list[] = $class_name; + $test_type = in_array($class_name, $phpunit_all) ? 'UnitTest' : 'WebTest'; + $tests_list[$test_type][] = $class_name; } } if (count($tests_list) > 0 ) { @@ -242,7 +249,6 @@ function simpletest_result_form($form, &$form_state, $test_id) { '#type' => 'details', '#title' => $info['name'], '#description' => $info['description'], - '#collapsible' => TRUE, ); $form['result']['results'][$group]['summary'] = $summary; $group_summary = &$form['result']['results'][$group]['summary']; @@ -455,7 +461,6 @@ function simpletest_settings_form($form, &$form_state) { '#type' => 'details', '#title' => t('HTTP authentication'), '#description' => t('HTTP auth settings to be used by the SimpleTest browser during testing. Useful when the site requires basic HTTP authentication.'), - '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['httpauth']['simpletest_httpauth_method'] = array( @@ -521,4 +526,3 @@ function simpletest_settings_form_validate($form, &$form_state) { form_set_error('simpletest_httpauth_username', t('HTTP authentication credentials must include a username in addition to a password.')); } } - diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist new file mode 100644 index 0000000..6ca7e89 --- /dev/null +++ b/core/phpunit.xml.dist @@ -0,0 +1,16 @@ + + + + + + ./tests/* + ./modules/*/tests/* + ../modules/*/tests/* + ../sites/*/modules/*/tests/* + + ./modules/config/tests/config_test/lib/Drupal/config_test + ./modules/views/tests/views_test_data/lib/Drupal/views_test_data + + + + diff --git a/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php new file mode 100644 index 0000000..2a3db3d --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Cache/BackendChainImplementationUnitTest.php @@ -0,0 +1,308 @@ + 'Backend chain implementation', + 'description' => 'Unit test of backend chain implementation specifics.', + 'group' => 'Cache' + ); + } + + /** + * Chain that will be heavily tested. + * + * @var Drupal\Core\Cache\BackendChain + */ + protected $chain; + + /** + * First backend in the chain. + * + * @var Drupal\Core\Cache\CacheBackendInterface + */ + protected $firstBackend; + + /** + * Second backend in the chain. + * + * @var Drupal\Core\Cache\CacheBackendInterface + */ + protected $secondBackend; + + /** + * Third backend in the chain. + * + * @var Drupal\Core\Cache\CacheBackendInterface + */ + protected $thirdBackend; + + public function setUp() { + parent::setUp(); + + // Set up three memory backends to be used in the chain. + $this->firstBackend = new MemoryBackend('foo'); + $this->secondBackend = new MemoryBackend('bar'); + $this->thirdBackend = new MemoryBackend('baz'); + + // Set an initial fixed dataset for all testing. The next three data + // collections will test two edge cases (last backend has the data, and + // first backend has the data) and will test a normal use case (middle + // backend has the data). We should have a complete unit test with those. + // Note that in all cases, when the same key is set on more than one + // backend, the values are voluntarily different, this ensures in which + // backend we actually fetched the key when doing get calls. + + // Set a key present on all backends (for delete). + $this->firstBackend->set('t123', 1231); + $this->secondBackend->set('t123', 1232); + $this->thirdBackend->set('t123', 1233); + + // Set a key present on the second and the third (for get), those two will + // be different, this will ensure from where we get the key. + $this->secondBackend->set('t23', 232); + $this->thirdBackend->set('t23', 233); + + // Set a key on only the third, we will ensure propagation using this one. + $this->thirdBackend->set('t3', 33); + + // Create the chain. + $this->chain = new BackendChain('foobarbaz'); + $this->chain + ->appendBackend($this->firstBackend) + ->appendBackend($this->secondBackend) + ->appendBackend($this->thirdBackend); + } + + /** + * Test the get feature. + */ + public function testGet() { + $cached = $this->chain->get('t123'); + $this->assertNotEquals(FALSE, $cached, 'Got key that is on all backends'); + $this->assertEquals(1231, $cached->data, 'Got the key from the backend 1'); + + $cached = $this->chain->get('t23'); + $this->assertNotEquals(FALSE, $cached, 'Got key that is on backends 2 and 3'); + $this->assertEquals(232, $cached->data, 'Got the key from the backend 2'); + + $cached = $this->chain->get('t3'); + $this->assertNotEquals(FALSE, $cached, 'Got key that is on the backend 3'); + $this->assertEquals(33, $cached->data, 'Got the key from the backend 3'); + } + + /** + * Test the get multiple feature. + */ + public function testGetMultiple() { + $cids = array('t123', 't23', 't3', 't4'); + + $ret = $this->chain->getMultiple($cids); + $this->assertEquals($ret['t123']->data, 1231, 'Got key 123 and value is from the first backend'); + $this->assertEquals($ret['t23']->data, 232, 'Got key 23 and value is from the second backend'); + $this->assertEquals($ret['t3']->data, 33, 'Got key 3 and value is from the third backend'); + $this->assertFalse(array_key_exists('t4', $ret), "Didn't get the nonexistent key"); + + $this->assertFalse(in_array('t123', $cids), "Existing key 123 has been removed from &\$cids"); + $this->assertFalse(in_array('t23', $cids), "Existing key 23 has been removed from &\$cids"); + $this->assertFalse(in_array('t3', $cids), "Existing key 3 has been removed from &\$cids"); + $this->assertTrue(in_array('t4', $cids), "Non existing key 4 is still in &\$cids"); + } + + /** + * Test that set will propagate. + */ + public function testSet() { + $this->chain->set('test', 123); + + $cached = $this->firstBackend->get('test'); + $this->assertNotEquals(FALSE, $cached, 'Test key is in the first backend'); + $this->assertEquals(123, $cached->data, 'Test key has the right value'); + + $cached = $this->secondBackend->get('test'); + $this->assertNotEquals(FALSE, $cached, 'Test key is in the second backend'); + $this->assertEquals(123, $cached->data, 'Test key has the right value'); + + $cached = $this->thirdBackend->get('test'); + $this->assertNotEquals(FALSE, $cached, 'Test key is in the third backend'); + $this->assertEquals(123, $cached->data, 'Test key has the right value'); + } + + /** + * Test that delete will propagate. + */ + public function testDelete() { + $this->chain->set('test', 5); + + $cached = $this->firstBackend->get('test'); + $this->assertNotEquals(FALSE, $cached, 'Test key has been added to the first backend'); + $cached = $this->secondBackend->get('test'); + $this->assertNotEquals(FALSE, $cached, 'Test key has been added to the first backend'); + $cached = $this->thirdBackend->get('test'); + $this->assertNotEquals(FALSE, $cached, 'Test key has been added to the first backend'); + + $this->chain->delete('test'); + + $cached = $this->firstBackend->get('test'); + $this->assertEquals(FALSE, $cached, 'Test key is removed from the first backend'); + $cached = $this->secondBackend->get('test'); + $this->assertEquals(FALSE, $cached, 'Test key is removed from the second backend'); + $cached = $this->thirdBackend->get('test'); + $this->assertEquals(FALSE, $cached, 'Test key is removed from the third backend'); + } + + /** + * Ensure get values propagation to previous backends. + */ + public function testGetHasPropagated() { + $this->chain->get('t23'); + $cached = $this->firstBackend->get('t23'); + $this->assertNotEquals(FALSE, $cached, 'Test 2 has been propagated to the first backend'); + + $this->chain->get('t3'); + $cached = $this->firstBackend->get('t3'); + $this->assertNotEquals(FALSE, $cached, 'Test 3 has been propagated to the first backend'); + $cached = $this->secondBackend->get('t3'); + $this->assertNotEquals(FALSE, $cached, 'Test 3 has been propagated to the second backend'); + } + + /** + * Ensure get multiple values propagation to previous backends. + */ + public function testGetMultipleHasPropagated() { + $cids = array('t3', 't23'); + $this->chain->getMultiple($cids); + + $cached = $this->firstBackend->get('t3'); + $this->assertNotEquals(FALSE, $cached, 'Test 3 has been propagated to the first backend'); + $this->assertEquals(33, $cached->data, 'And value has been kept'); + $cached = $this->secondBackend->get('t3'); + $this->assertNotEquals(FALSE, $cached, 'Test 3 has been propagated to the second backend'); + $this->assertEquals(33, $cached->data, 'And value has been kept'); + + $cached = $this->firstBackend->get('t23'); + $this->assertNotEquals(FALSE, $cached, 'Test 2 has been propagated to the first backend'); + $this->assertEquals(232, $cached->data, 'And value has been kept'); + } + + /** + * Test that the chain is not empty when at least one backend has data. + */ + public function testNotEmptyIfOneBackendHasTheKey() { + $this->assertFalse($this->chain->isEmpty(), 'Chain is not empty'); + + // This is the only test that needs to start with an empty chain. + $this->chain->deleteAll(); + $this->assertTrue($this->chain->isEmpty(), 'Chain have been emptied by the deleteAll() call'); + + $this->secondBackend->set('test', 5); + $this->assertFalse($this->chain->isEmpty(), 'Chain is not empty anymore now that the second backend has something'); + } + + /** + * Test that the delete all operation is propagated to all backends in the chain. + */ + public function testDeleteAllPropagation() { + // Set both expiring and permanent keys. + $this->chain->set('test1', 1, CacheBackendInterface::CACHE_PERMANENT); + $this->chain->set('test2', 3, time() + 1000); + $this->chain->deleteAll(); + + $this->assertTrue($this->firstBackend->isEmpty(), 'First backend is empty after delete all.'); + $this->assertTrue($this->secondBackend->isEmpty(), 'Second backend is empty after delete all.'); + $this->assertTrue($this->thirdBackend->isEmpty(), 'Third backend is empty after delete all.'); + } + + /** + * Test that the delete tags operation is propagated to all backends + * in the chain. + */ + public function testDeleteTagsPropagation() { + // Create two cache entries with the same tag and tag value. + $this->chain->set('test_cid_clear1', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $this->chain->set('test_cid_clear2', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $this->assertNotEquals(FALSE, $this->firstBackend->get('test_cid_clear1') + && $this->firstBackend->get('test_cid_clear2') + && $this->secondBackend->get('test_cid_clear1') + && $this->secondBackend->get('test_cid_clear2') + && $this->thirdBackend->get('test_cid_clear1') + && $this->thirdBackend->get('test_cid_clear2'), + 'Two cache items were created in all backends.'); + + // Invalidate test_tag of value 1. This should invalidate both entries. + $this->chain->deleteTags(array('test_tag' => 2)); + $this->assertEquals(FALSE, $this->firstBackend->get('test_cid_clear1') + && $this->firstBackend->get('test_cid_clear2') + && $this->secondBackend->get('test_cid_clear1') + && $this->secondBackend->get('test_cid_clear2') + && $this->thirdBackend->get('test_cid_clear1') + && $this->thirdBackend->get('test_cid_clear2'), + 'Two caches removed from all backends after clearing a cache tag.'); + + // Create two cache entries with the same tag and an array tag value. + $this->chain->set('test_cid_clear1', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $this->chain->set('test_cid_clear2', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $this->assertNotEquals(FALSE, $this->firstBackend->get('test_cid_clear1') + && $this->firstBackend->get('test_cid_clear2') + && $this->secondBackend->get('test_cid_clear1') + && $this->secondBackend->get('test_cid_clear2') + && $this->thirdBackend->get('test_cid_clear1') + && $this->thirdBackend->get('test_cid_clear2'), + 'Two cache items were created in all backends.'); + + // Invalidate test_tag of value 1. This should invalidate both entries. + $this->chain->deleteTags(array('test_tag' => array(1))); + $this->assertEquals(FALSE, $this->firstBackend->get('test_cid_clear1') + && $this->firstBackend->get('test_cid_clear2') + && $this->secondBackend->get('test_cid_clear1') + && $this->secondBackend->get('test_cid_clear2') + && $this->thirdBackend->get('test_cid_clear1') + && $this->thirdBackend->get('test_cid_clear2'), + 'Two caches removed from all backends after clearing a cache tag.'); + + // Create three cache entries with a mix of tags and tag values. + $this->chain->set('test_cid_clear1', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $this->chain->set('test_cid_clear2', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2))); + $this->chain->set('test_cid_clear3', 'foo', CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(3))); + $this->assertNotEquals(FALSE, $this->firstBackend->get('test_cid_clear1') + && $this->firstBackend->get('test_cid_clear2') + && $this->firstBackend->get('test_cid_clear3') + && $this->secondBackend->get('test_cid_clear1') + && $this->secondBackend->get('test_cid_clear2') + && $this->secondBackend->get('test_cid_clear3') + && $this->thirdBackend->get('test_cid_clear1') + && $this->thirdBackend->get('test_cid_clear2') + && $this->thirdBackend->get('test_cid_clear3'), + 'Three cached items were created in all backends.'); + + $this->chain->deleteTags(array('test_tag_foo' => array(3))); + $this->assertNotEquals(FALSE, $this->firstBackend->get('test_cid_clear1') + && $this->firstBackend->get('test_cid_clear2') + && $this->secondBackend->get('test_cid_clear1') + && $this->secondBackend->get('test_cid_clear2') + && $this->thirdBackend->get('test_cid_clear1') + && $this->thirdBackend->get('test_cid_clear2'), + 'Cached items not matching the tag were not cleared from any of the backends.'); + + $this->assertEquals(FALSE, $this->firstBackend->get('test_cid_clear3') + && $this->secondBackend->get('test_cid_clear3') + && $this->thirdBackend->get('test_cid_clear3'), + 'Cached item matching the tag was removed from all backends.'); + } +} diff --git a/core/tests/Drupal/Tests/Core/Cache/GenericCacheBackendUnitTestBase.php b/core/tests/Drupal/Tests/Core/Cache/GenericCacheBackendUnitTestBase.php new file mode 100644 index 0000000..9ca9bb7 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Cache/GenericCacheBackendUnitTestBase.php @@ -0,0 +1,541 @@ +testBin)) { + $this->testBin = 'page'; + } + return $this->testBin; + } + + /** + * Creates a cache backend to test. + * + * Override this method to test a CacheBackend. + * + * @param string $bin + * Bin name to use for this backend instance. + * + * @return Drupal\Core\Cache\CacheBackendInterface + * Cache backend to test. + */ + protected abstract function createCacheBackend($bin); + + /** + * Allows specific implementation to change the environment before a test run. + */ + public function setUpCacheBackend() { + } + + /** + * Allows alteration of environment after a test run but before tear down. + * + * Used before the real tear down because the tear down will change things + * such as the database prefix. + */ + public function tearDownCacheBackend() { + } + + /** + * Gets a backend to test; this will get a shared instance set in the object. + * + * @return Drupal\Core\Cache\CacheBackendInterface + * Cache backend to test. + */ + final function getCacheBackend($bin = null) { + if (!isset($bin)) { + $bin = $this->getTestBin(); + } + if (!isset($this->cachebackends[$bin])) { + $this->cachebackends[$bin] = $this->createCacheBackend($bin); + // Ensure the backend is empty. + $this->cachebackends[$bin]->deleteAll(); + } + return $this->cachebackends[$bin]; + } + + public function setUp() { + $this->cachebackends = array(); + $this->defaultValue = $this->randomName(10); + + parent::setUp(); + + $this->setUpCacheBackend(); + } + + public function tearDown() { + // Destruct the registered backend, each test will get a fresh instance, + // properly emptying it here ensure that on persistant data backends they + // will come up empty the next test. + foreach ($this->cachebackends as $bin => $cachebackend) { + $this->cachebackends[$bin]->deleteAll(); + } + unset($this->cachebackends); + + $this->tearDownCacheBackend(); + + parent::tearDown(); + } + + /** + * Tests the get and set methods of Drupal\Core\Cache\CacheBackendInterface. + */ + public function testSetGet() { + $backend = $this->getCacheBackend(); + + $this->assertEquals(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1."); + $backend->set('test1', 7); + $cached = $backend->get('test1'); + $this->assert(is_object($cached), "Backend returned an object for cache id test1."); + $this->assertEquals(7, $cached->data); + $this->assertTrue($cached->valid, 'Item is marked as valid.'); + $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($cached->expire, CacheBackendInterface::CACHE_PERMANENT, 'Expire time is correct.'); + + $this->assertEquals(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2."); + $backend->set('test2', array('value' => 3), REQUEST_TIME + 3); + $cached = $backend->get('test2'); + $this->assert(is_object($cached), "Backend returned an object for cache id test2."); + $this->assertEquals(array('value' => 3), $cached->data); + $this->assertTrue($cached->valid, 'Item is marked as valid.'); + $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($cached->expire, REQUEST_TIME + 3, 'Expire time is correct.'); + + $backend->set('test3', 'foobar', REQUEST_TIME - 3); + $this->assertFalse($backend->get('test3'), 'Invalid item not returned.'); + $cached = $backend->get('test3', TRUE); + $this->assert(is_object($cached), 'Backend returned an object for cache id test3.'); + $this->assertFalse($cached->valid, 'Item is marked as valid.'); + $this->assertEqual($cached->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($cached->expire, REQUEST_TIME - 3, 'Expire time is correct.'); + } + + /** + * Tests Drupal\Core\Cache\CacheBackendInterface::delete(). + */ + public function testDelete() { + $backend = $this->getCacheBackend(); + + $this->assertEquals(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1."); + $backend->set('test1', 7); + $this->assert(is_object($backend->get('test1')), "Backend returned an object for cache id test1."); + + $this->assertEquals(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2."); + $backend->set('test2', 3); + $this->assert(is_object($backend->get('test2')), "Backend returned an object for cache id %cid."); + + $backend->delete('test1'); + $this->assertEquals(FALSE, $backend->get('test1'), "Backend does not contain data for cache id test1 after deletion."); + + $cached = $backend->get('test2'); + $this->assert(is_object($backend->get('test2')), "Backend still has an object for cache id test2."); + + $backend->delete('test2'); + $this->assertEquals(FALSE, $backend->get('test2'), "Backend does not contain data for cache id test2 after deletion."); + } + + /** + * Tests data type preservation. + */ + public function testValueTypeIsKept() { + $backend = $this->getCacheBackend(); + + $variables = array( + 'test1' => 1, + 'test2' => '0', + 'test3' => '', + 'test4' => 12.64, + 'test5' => FALSE, + 'test6' => array(1,2,3), + ); + + // Create cache entries. + foreach ($variables as $cid => $data) { + $backend->set($cid, $data); + } + + // Retrieve and test cache objects. + foreach ($variables as $cid => $value) { + $object = $backend->get($cid); + $this->assert(is_object($object), sprintf("Backend returned an object for cache id %s.", $cid)); + $this->assertEquals($value, $object->data, sprintf("Data of cached id %s kept is identical in type and value", $cid)); + } + } + + /** + * Tests Drupal\Core\Cache\CacheBackendInterface::getMultiple(). + */ + public function testGetMultiple() { + $backend = $this->getCacheBackend(); + + // Set numerous testing keys. + $backend->set('test1', 1); + $backend->set('test2', 3); + $backend->set('test3', 5); + $backend->set('test4', 7); + $backend->set('test5', 11); + $backend->set('test6', 13); + $backend->set('test7', 17); + + // Mismatch order for harder testing. + $reference = array( + 'test3', + 'test7', + 'test21', // Cid does not exist. + 'test6', + 'test19', // Cid does not exist until added before second getMultiple(). + 'test2', + ); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + // Test return - ensure it contains existing cache ids. + $this->assert(isset($ret['test2']), "Existing cache id test2 is set."); + $this->assert(isset($ret['test3']), "Existing cache id test3 is set."); + $this->assert(isset($ret['test6']), "Existing cache id test6 is set."); + $this->assert(isset($ret['test7']), "Existing cache id test7 is set."); + // Test return - ensure that objects has expected properties. + $this->assertTrue($ret['test2']->valid, 'Item is marked as valid.'); + $this->assertEqual($ret['test2']->created, REQUEST_TIME, 'Created time is correct.'); + $this->assertEqual($ret['test2']->expire, CacheBackendInterface::CACHE_PERMANENT, 'Expire time is correct.'); + // Test return - ensure it does not contain nonexistent cache ids. + $this->assertFalse(isset($ret['test19']), "Nonexistent cache id test19 is not set."); + $this->assertFalse(isset($ret['test21']), "Nonexistent cache id test21 is not set."); + // Test values. + $this->assertEquals($ret['test2']->data, 3, "Existing cache id test2 has the correct value."); + $this->assertEquals($ret['test3']->data, 5, "Existing cache id test3 has the correct value."); + $this->assertEquals($ret['test6']->data, 13, "Existing cache id test6 has the correct value."); + $this->assertEquals($ret['test7']->data, 17, "Existing cache id test7 has the correct value."); + // Test $cids array - ensure it contains cache id's that do not exist. + $this->assert(in_array('test19', $cids), "Nonexistent cache id test19 is in cids array."); + $this->assert(in_array('test21', $cids), "Nonexistent cache id test21 is in cids array."); + // Test $cids array - ensure it does not contain cache id's that exist. + $this->assertFalse(in_array('test2', $cids), "Existing cache id test2 is not in cids array."); + $this->assertFalse(in_array('test3', $cids), "Existing cache id test3 is not in cids array."); + $this->assertFalse(in_array('test6', $cids), "Existing cache id test6 is not in cids array."); + $this->assertFalse(in_array('test7', $cids), "Existing cache id test7 is not in cids array."); + + // Test a second time after deleting and setting new keys which ensures that + // if the backend uses statics it does not cause unexpected results. + $backend->delete('test3'); + $backend->delete('test6'); + $backend->set('test19', 57); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + // Test return - ensure it contains existing cache ids. + $this->assert(isset($ret['test2']), "Existing cache id test2 is set"); + $this->assert(isset($ret['test7']), "Existing cache id test7 is set"); + $this->assert(isset($ret['test19']), "Added cache id test19 is set"); + // Test return - ensure it does not contain nonexistent cache ids. + $this->assertFalse(isset($ret['test3']), "Deleted cache id test3 is not set"); + $this->assertFalse(isset($ret['test6']), "Deleted cache id test6 is not set"); + $this->assertFalse(isset($ret['test21']), "Nonexistent cache id test21 is not set"); + // Test values. + $this->assertEquals($ret['test2']->data, 3, "Existing cache id test2 has the correct value."); + $this->assertEquals($ret['test7']->data, 17, "Existing cache id test7 has the correct value."); + $this->assertEquals($ret['test19']->data, 57, "Added cache id test19 has the correct value."); + // Test $cids array - ensure it contains cache id's that do not exist. + $this->assert(in_array('test3', $cids), "Deleted cache id test3 is in cids array."); + $this->assert(in_array('test6', $cids), "Deleted cache id test6 is in cids array."); + $this->assert(in_array('test21', $cids), "Nonexistent cache id test21 is in cids array."); + // Test $cids array - ensure it does not contain cache id's that exist. + $this->assertFalse(in_array('test2', $cids), "Existing cache id test2 is not in cids array."); + $this->assertFalse(in_array('test7', $cids), "Existing cache id test7 is not in cids array."); + $this->assertFalse(in_array('test19', $cids), "Added cache id test19 is not in cids array."); + } + + /** + * Tests Drupal\Core\Cache\CacheBackendInterface::isEmpty(). + */ + public function testIsEmpty() { + $backend = $this->getCacheBackend(); + + $this->assertTrue($backend->isEmpty(), "Backend is empty."); + + $backend->set('pony', "Shetland"); + $this->assertFalse($backend->isEmpty(), "Backend is not empty."); + + $backend->delete('pony'); + $this->assertTrue($backend->isEmpty(), "Backend is empty."); + } + + /** + * Test Drupal\Core\Cache\CacheBackendInterface::delete() and + * Drupal\Core\Cache\CacheBackendInterface::deleteMultiple(). + */ + public function testDeleteMultiple() { + $backend = $this->getCacheBackend(); + + // Set numerous testing keys. + $backend->set('test1', 1); + $backend->set('test2', 3); + $backend->set('test3', 5); + $backend->set('test4', 7); + $backend->set('test5', 11); + $backend->set('test6', 13); + $backend->set('test7', 17); + + $backend->delete('test1'); + $backend->delete('test23'); // Nonexistent key should not cause an error. + $backend->deleteMultiple(array( + 'test3', + 'test5', + 'test7', + 'test19', // Nonexistent key should not cause an error. + 'test21', // Nonexistent key should not cause an error. + )); + + // Test if expected keys have been deleted. + $this->assertEquals(FALSE, $backend->get('test1'), "Cache id test1 deleted."); + $this->assertEquals(FALSE, $backend->get('test3'), "Cache id test3 deleted."); + $this->assertEquals(FALSE, $backend->get('test5'), "Cache id test5 deleted."); + $this->assertEquals(FALSE, $backend->get('test7'), "Cache id test7 deleted."); + + // Test if expected keys exist. + $this->assertNotIdentical(FALSE, $backend->get('test2'), "Cache id test2 exists."); + $this->assertNotIdentical(FALSE, $backend->get('test4'), "Cache id test4 exists."); + $this->assertNotIdentical(FALSE, $backend->get('test6'), "Cache id test6 exists."); + + // Test if that expected keys do not exist. + $this->assertEquals(FALSE, $backend->get('test19'), "Cache id test19 does not exist."); + $this->assertEquals(FALSE, $backend->get('test21'), "Cache id test21 does not exist."); + } + + /** + * Tests Drupal\Core\Cache\CacheBackendInterface::deleteTags(). + */ + function testDeleteTags() { + $backend = $this->getCacheBackend(); + + // Create two cache entries with the same tag and tag value. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.'); + + // Delete test_tag of value 1. This should delete both entries. + $backend->deleteTags(array('test_tag' => 2)); + $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleting a cache tag.'); + $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.'); + + // Create two cache entries with the same tag and an array tag value. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.'); + + // Delete test_tag of value 1. This should delete both entries. + $backend->deleteTags(array('test_tag' => array(1))); + $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after deleted a cache tag.'); + $this->assertFalse($backend->get('test_cid_invalidate1', TRUE) || $backend->get('test_cid_invalidate2', TRUE), 'Two cache items deleted after deleting a cache tag.'); + + // Create three cache entries with a mix of tags and tag values. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2))); + $backend->set('test_cid_invalidate3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(3))); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.'); + $backend->deleteTags(array('test_tag_foo' => array(3))); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cached items not matching the tag were not deleted.'); + $this->assertFalse($backend->get('test_cid_invalidated3', TRUE), 'Cache item matching the tag was deleted.'); + + // Create cache entry in multiple bins. Two cache entries + // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous + // tests. + $tags = array('test_tag' => array(1, 2, 3)); + $bins = array('path', 'bootstrap', 'page'); + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->set('test', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, $tags); + $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.'); + } + + // Delete tag in mulitple bins. + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->deleteTags(array('test_tag' => array(2))); + } + + // Test that cache entry has been deleted in multple bins. + foreach ($bins as $bin) { + $this->assertFalse($this->getCacheBackend($bin)->get('test', TRUE), 'Tag deletion affected item in bin.'); + } + // Test that the cache entry with a matching tag has been invalidated. + $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2', TRUE), 'Cache items matching tag were deleted.'); + // Test that the cache entry with without a matching tag still exists. + $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.'); + } + + /** + * Test Drupal\Core\Cache\CacheBackendInterface::deleteAll(). + */ + public function testDeleteAll() { + $backend = $this->getCacheBackend(); + + // Set both expiring and permanent keys. + $backend->set('test1', 1, CacheBackendInterface::CACHE_PERMANENT); + $backend->set('test2', 3, time() + 1000); + + $backend->deleteAll(); + + $this->assertTrue($backend->isEmpty(), "Backend is empty after deleteAll()."); + + $this->assertFalse($backend->get('test1'), 'First key has been deleted.'); + $this->assertFalse($backend->get('test2'), 'Second key has been deleted.'); + } + + /** + * Test Drupal\Core\Cache\CacheBackendInterface::invalidate() and + * Drupal\Core\Cache\CacheBackendInterface::invalidateMultiple(). + */ + function testInvalidate() { + $backend = $this->getCacheBackend(); + $backend->set('test1', 1); + $backend->set('test2', 2); + $backend->set('test3', 2); + $backend->set('test4', 2); + + $reference = array('test1', 'test2', 'test3', 'test4'); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + $this->assertEqual(count($ret), 4, 'Four items returned.'); + + $backend->invalidate('test1'); + $backend->invalidateMultiple(array('test2', 'test3')); + + $cids = $reference; + $ret = $backend->getMultiple($cids); + $this->assertEqual(count($ret), 1, 'Only one item element returned.'); + + $cids = $reference; + $ret = $backend->getMultiple($cids, TRUE); + $this->assertEqual(count($ret), 4, 'Four items returned.'); + } + + /** + * Tests Drupal\Core\Cache\CacheBackendInterface::invalidateTags(). + */ + function testInvalidateTags() { + $backend = $this->getCacheBackend(); + + // Create two cache entries with the same tag and tag value. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => 2)); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.'); + + // Invalidate test_tag of value 1. This should invalidate both entries. + $backend->invalidateTags(array('test_tag' => 2)); + $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two cache items invalidated after invalidating a cache tag.'); + $this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.'); + + // Create two cache entries with the same tag and an array tag value. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Two cache items were created.'); + + // Invalidate test_tag of value 1. This should invalidate both entries. + $backend->invalidateTags(array('test_tag' => array(1))); + $this->assertFalse($backend->get('test_cid_invalidate1') || $backend->get('test_cid_invalidate2'), 'Two caches removed after invalidating a cache tag.'); + $this->assertTrue($backend->get('test_cid_invalidate1', TRUE) && $backend->get('test_cid_invalidate2', TRUE), 'Cache items not deleted after invalidating a cache tag.'); + + // Create three cache entries with a mix of tags and tag values. + $backend->set('test_cid_invalidate1', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(1))); + $backend->set('test_cid_invalidate2', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag' => array(2))); + $backend->set('test_cid_invalidate3', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, array('test_tag_foo' => array(3))); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2') && $backend->get('test_cid_invalidate3'), 'Three cached items were created.'); + $backend->invalidateTags(array('test_tag_foo' => array(3))); + $this->assertTrue($backend->get('test_cid_invalidate1') && $backend->get('test_cid_invalidate2'), 'Cache items not matching the tag were not invalidated.'); + $this->assertFalse($backend->get('test_cid_invalidated3'), 'Cached item matching the tag was removed.'); + + // Create cache entry in multiple bins. Two cache entries + // (test_cid_invalidate1 and test_cid_invalidate2) still exist from previous + // tests. + $tags = array('test_tag' => array(1, 2, 3)); + $bins = array('path', 'bootstrap', 'page'); + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->set('test', $this->defaultValue, CacheBackendInterface::CACHE_PERMANENT, $tags); + $this->assertTrue($this->getCacheBackend($bin)->get('test'), 'Cache item was set in bin.'); + } + + // Invalidate tag in mulitple bins. + foreach ($bins as $bin) { + $this->getCacheBackend($bin)->invalidateTags(array('test_tag' => array(2))); + } + + // Test that cache entry has been invalidated in multple bins. + foreach ($bins as $bin) { + $this->assertFalse($this->getCacheBackend($bin)->get('test'), 'Tag invalidation affected item in bin.'); + } + // Test that the cache entry with a matching tag has been invalidated. + $this->assertFalse($this->getCacheBackend($bin)->get('test_cid_invalidate2'), 'Cache items matching tag were invalidated.'); + // Test that the cache entry with without a matching tag still exists. + $this->assertTrue($this->getCacheBackend($bin)->get('test_cid_invalidate1'), 'Cache items not matching tag were not invalidated.'); + } + + /** + * Test Drupal\Core\Cache\CacheBackendInterface::invalidateAll(). + */ + public function testInvalidateAll() { + $backend = $this->getCacheBackend(); + + // Set both expiring and permanent keys. + $backend->set('test1', 1, CacheBackendInterface::CACHE_PERMANENT); + $backend->set('test2', 3, time() + 1000); + + $backend->invalidateAll(); + + $this->assertFalse($backend->get('test1'), 'First key has been invalidated.'); + $this->assertFalse($backend->get('test2'), 'Second key has been invalidated.'); + $this->assertTrue($backend->get('test1', TRUE), 'First key has not been deleted.'); + $this->assertTrue($backend->get('test2', TRUE), 'Second key has not been deleted.'); + } + +} diff --git a/core/tests/Drupal/Tests/Core/Cache/NullBackendTest.php b/core/tests/Drupal/Tests/Core/Cache/NullBackendTest.php new file mode 100644 index 0000000..b304116 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Cache/NullBackendTest.php @@ -0,0 +1,39 @@ + 'Cache NullBackend test', + 'description' => 'Tests the cache NullBackend.', + 'group' => 'Cache', + ); + } + + /** + * Tests that the NullBackend does not actually store variables. + */ + function testNullBackend() { + $null_cache = new NullBackend('test'); + + $key = $this->randomName(); + $value = $this->randomName(); + + $null_cache->set($key, $value); + $this->assertTrue($null_cache->isEmpty()); + $this->assertFalse($null_cache->get($key)); + } +} diff --git a/core/tests/Drupal/Tests/Core/NestedArrayUnitTest.php b/core/tests/Drupal/Tests/Core/NestedArrayUnitTest.php new file mode 100644 index 0000000..8473517 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/NestedArrayUnitTest.php @@ -0,0 +1,148 @@ + 'NestedArray functionality', + 'description' => 'Tests the NestedArray helper class.', + 'group' => 'System', + ); + } + + function setUp() { + parent::setUp(); + + // Create a form structure with a nested element. + $this->form['details']['element'] = array( + '#value' => 'Nested element', + ); + + // Set up parent array. + $this->parents = array('details', 'element'); + } + + /** + * Tests getting nested array values. + */ + function testGetValue() { + // Verify getting a value of a nested element. + $value = NestedArray::getValue($this->form, $this->parents); + $this->assertEquals($value['#value'], 'Nested element', 'Nested element value found.'); + + // Verify changing a value of a nested element by reference. + $value = &NestedArray::getValue($this->form, $this->parents); + $value['#value'] = 'New value'; + $value = NestedArray::getValue($this->form, $this->parents); + $this->assertEquals($value['#value'], 'New value', 'Nested element value was changed by reference.'); + $this->assertEquals($this->form['details']['element']['#value'], 'New value', 'Nested element value was changed by reference.'); + + // Verify that an existing key is reported back. + $key_exists = NULL; + NestedArray::getValue($this->form, $this->parents, $key_exists); + $this->assertEquals($key_exists, TRUE, 'Existing key found.'); + + // Verify that a non-existing key is reported back and throws no errors. + $key_exists = NULL; + $parents = $this->parents; + $parents[] = 'foo'; + NestedArray::getValue($this->form, $parents, $key_exists); + $this->assertEquals($key_exists, FALSE, 'Non-existing key not found.'); + } + + /** + * Tests setting nested array values. + */ + function testSetValue() { + $new_value = array( + '#value' => 'New value', + '#required' => TRUE, + ); + + // Verify setting the value of a nested element. + NestedArray::setValue($this->form, $this->parents, $new_value); + $this->assertEquals($this->form['details']['element']['#value'], 'New value', 'Changed nested element value found.'); + $this->assertEquals($this->form['details']['element']['#required'], TRUE, 'New nested element value found.'); + } + + /** + * Tests unsetting nested array values. + */ + function testUnsetValue() { + // Verify unsetting a non-existing nested element throws no errors and the + // non-existing key is properly reported. + $key_existed = NULL; + $parents = $this->parents; + $parents[] = 'foo'; + NestedArray::unsetValue($this->form, $parents, $key_existed); + $this->assertTrue(isset($this->form['details']['element']['#value']), 'Outermost nested element key still exists.'); + $this->assertEquals($key_existed, FALSE, 'Non-existing key not found.'); + + // Verify unsetting a nested element. + $key_existed = NULL; + NestedArray::unsetValue($this->form, $this->parents, $key_existed); + $this->assertFalse(isset($this->form['details']['element']), 'Removed nested element not found.'); + $this->assertEquals($key_existed, TRUE, 'Existing key was found.'); + } + + /** + * Tests existence of array key. + */ + function testKeyExists() { + // Verify that existing key is found. + $this->assertEquals(NestedArray::keyExists($this->form, $this->parents), TRUE, 'Nested key found.'); + + // Verify that non-existing keys are not found. + $parents = $this->parents; + $parents[] = 'foo'; + $this->assertEquals(NestedArray::keyExists($this->form, $parents), FALSE, 'Non-existing nested key not found.'); + } + + /** + * Tests NestedArray::mergeDeepArray(). + */ + function testMergeDeepArray() { + $link_options_1 = array( + 'fragment' => 'x', + 'attributes' => array('title' => 'X', 'class' => array('a', 'b')), + 'language' => 'en', + ); + $link_options_2 = array( + 'fragment' => 'y', + 'attributes' => array('title' => 'Y', 'class' => array('c', 'd')), + 'html' => TRUE, + ); + $expected = array( + 'fragment' => 'y', + 'attributes' => array('title' => 'Y', 'class' => array('a', 'b', 'c', 'd')), + 'language' => 'en', + 'html' => TRUE, + ); + $this->assertEquals(NestedArray::mergeDeepArray(array($link_options_1, $link_options_2)), $expected, 'NestedArray::mergeDeepArray() returned a properly merged array.'); + } +} diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php new file mode 100644 index 0000000..03ad511 --- /dev/null +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -0,0 +1,74 @@ + '', + 'description' => '', + 'group' => '', + ); + } + + /** + * Generates a random string containing letters and numbers. + * + * The string will always start with a letter. The letters may be upper or + * lower case. This method is better for restricted inputs that do not + * accept certain characters. For example, when testing input fields that + * require machine readable values (i.e. without spaces and non-standard + * characters) this method is best. + * + * Do not use this method when testing unvalidated user input. Instead, use + * Drupal\simpletest\TestBase::randomString(). + * + * @param $length + * Length of random string to generate. + * + * @return + * Randomly generated string. + * + * @see Drupal\simpletest\TestBase::randomString() + */ + public static function randomName($length = 8) { + $values = array_merge(range(65, 90), range(97, 122), range(48, 57)); + $max = count($values) - 1; + $str = chr(mt_rand(97, 122)); + for ($i = 1; $i < $length; $i++) { + $str .= chr($values[mt_rand(0, $max)]); + } + return $str; + } + + /** + * Fire an assertion that is always positive. + * + * @param $message + * (optional) A message to display with the assertion. Do not translate + * messages: use format_string() to embed variables in the message text, not + * t(). If left blank, a default message will be displayed. + * @param $group + * (optional) The group this message is in, which is displayed in a column + * in test output. Use 'Debug' to indicate this is debugging output. Do not + * translate this string. Defaults to 'Other'; most tests do not override + * this default. + * @return + * TRUE. + */ + protected function pass($message = NULL, $group = 'Other') { + return $this->assertTrue($message, $group); + } +} diff --git a/core/tests/bootstrap.php b/core/tests/bootstrap.php new file mode 100644 index 0000000..6c947df --- /dev/null +++ b/core/tests/bootstrap.php @@ -0,0 +1,13 @@ +add('Drupal\\', __DIR__); +$loader->add('Drupal\Core', __DIR__ . "/../../core/lib"); +$loader->add('Drupal\Component', __DIR__ . "/../../core/lib"); + +foreach (scandir(__DIR__ . "/../modules") as $module) { + $loader->add('Drupal\\' . $module, __DIR__ . "/../modules/" . $module . "/lib"); +} +// Look into removing this later. +define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);