wiki.techinc.nl/tests/phpunit/includes
Timo Tijhof f37cee996e resourceloader: Replace timestamp system with version hashing
Modules now track their version via getVersionHash() instead of getModifiedTime().

== Background ==

While some resources have observeable timestamps (e.g. files stored on disk),
many other resources do not. E.g. config variables, and module definitions.

For static file modules, one can e.g. revert one of more files in a module to a
previous version and not affect the max timestamp.

Wiki modules include pages only if they exist. The user module supports common.js
and skin.js. By default neither exists. If a user has both, and then the
less-recently modified one is deleted, the max-timestamp remains unchanged.

For client-side caching, batch requests use "Math.max" on the relevant timestamps.
Again, if a module changes but another module is more recent (e.g. out-of-order
deployment, or out-of-order discovery), the change would not result in a cache miss.

More scenarios can be found in the associated Phabricator tasks.

== Version hash ==

Previously we virtually mapped these variables to a timestamp by storing the current
time alongside a hash of the value in ObjectCache. Considering the number of
possible request contexts (wikis * modules * users * skins * languages) this doesn't
work well. It results in needless cache invalidation when the first time observation
is purged due to LRU algorithms. It also has other minor bugs leading to fewer
cache hits.

All modules automatically get the benefits of version hashing with this change.
The old getDefinitionMtime() and getHashMtime() have been replaced with dummies
that return 1. These functions are often called from getModifiedTime() in subclasses.

For backward-compatibility, their respective values (definition summary and hash)
are now included in getVersionHash directly.

As examples, the following modules have been updated to use getVersionHash directly.
Other modules still work fine and can be updated later.

* ResourceLoaderFileModule
* ResourceLoaderEditToolbarModule
* ResourceLoaderStartUpModule
* ResourceLoaderWikiModule

The presence of hashes in place of timestamps increases the startup module size on
a default MediaWiki install from 4.4k to 5.8k (after gzip and minification).

== ETag ==

Since timestamps are no longer tracked, we need a different way to implement caching
for cache proxies (e.g. Varnish) and web browsers. Previously we used the
Last-Modified header (in combination with Cache-Control and Expires).

Instead of Last-Modified (and If-Modified-Since), we use ETag (and If-None-Match).

Entity tags (new in HTTP/1.1) are much stricter than Last-Modified by default.
They instruct browsers to allow usage of partial Range requests. Since our responses
are dynamically generated, we need to use the Weak version of ETag.

While this sounds bad, it's no different than Last-Modified. As reassured by
RFC 2616 <http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3> the
specified behaviour behind Last-Modified follows the same "Weak" caching logic as
Entity tags. It's just that entity tags are capable of a stricter mode (whereas
Last-Modified is inherently weak).

== File cache ==

If $wgUseFileCache is enabled, ResourceLoader uses ResourceFileCache to cache
load.php responses. While the blind TTL handling (during the allowed expiry period)
is still maxage/timestamp based, tryRespondNotModified() now requires the caller to
know the expected ETag.

For this to work, the FileCache handling had to be moved from the top of
ResoureLoader::respond() to after the expected ETag is computed.

This also allows us to remove the duplicate tryRespondNotModified() handling since
that's is already handled by ResourceLoader::respond() meanwhile.

== Misc ==

* Remove redundant modifiedTime cache in ResourceLoaderFileModule.

* Change bugzilla references to Phabricator.

* Centralised inclusion of wgCacheEpoch using getDefinitionSummary. Previously this
  logic was duplicated in each place the modified timestamp was used.

* It's easy to forget calling the parent class in getDefinitionSummary().
  Previously this method only tracked 'class' by default. As such, various
  extensions hardcoded that one value instead of calling the parent and extending
  the array. To better prevent this in the future, getVersionHash() now asserts
  that the '_cacheEpoch' property made it through.

* tests: Don't use getDefinitionSummary() as an API.
  Fix ResourceLoaderWikiModuleTest to call getPages properly.

* In tests, the default timestamp used to be 1388534400000 (which is the unix time
  of 20140101000000; the unit tests' CacheEpoch). The new version hash of these
  modules is "XyCC+PSK", which is the base64 encoded prefix of the SHA1 digest of:
  '{"_class":"ResourceLoaderTestModule","_cacheEpoch":"20140101000000"}'

* Add sha1.js library for client-side hash generation.
  Compared various different implementations for code size (after minfication/gzip),
  and speed (when used for short hexidecimal strings).
  https://jsperf.com/sha1-implementations
  - CryptoJS <https://code.google.com/p/crypto-js/#SHA-1> (min+gzip: 2.5k)
    http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha1.js
    Chrome: 45k, Firefox: 89k, Safari: 92k
  - jsSHA <https://github.com/Caligatio/jsSHA>
    https://github.com/Caligatio/jsSHA/blob/3c1d4f2e/src/sha1.js (min+gzip: 1.8k)
    Chrome: 65k, Firefox: 53k, Safari: 69k
  - phpjs-sha1 <https://github.com/kvz/phpjs> (RL min+gzip: 0.8k)
    https://github.com/kvz/phpjs/blob/1eaab15d/functions/strings/sha1.js
    Chrome: 200k, Firefox: 280k, Safari: 78k

  Modern browsers implement the HTML5 Crypto API. However, this API is asynchronous,
  only enabled when on HTTPS in Chromium, and is quite low-level. It requires boilerplate
  code to actually use with TextEncoder, ArrayBuffer and Uint32Array. Due this being
  needed in the module loader, we'd have to load the fallback regardless. Considering
  this is not used in a critical path for performance, it's not worth shipping two
  implementations for this optimisation.

May also resolve:
* T44094
* T90411
* T94810

Bug: T94074
Change-Id: Ibb292d2416839327d1807a66c78fd96dac0637d0
2015-05-19 22:28:17 +00:00
..
actions UI for adding and removing change tags on revisions and log entries 2015-04-15 18:31:12 +00:00
api API: Also mangle indexed tag names in format=xml 2015-04-30 09:02:17 -04:00
cache Removed BloomFilter classes 2015-04-03 09:10:04 +00:00
changes Add test for IRC line for legacy type block/block 2015-05-01 18:14:22 +00:00
composer tests: Clean up file headers 2015-04-01 00:17:12 +01:00
config Remove deprecated GlobalVarConfig::set() 2014-10-20 16:43:08 +00:00
content Add supportsDirectEditing methods to ContentHandler 2015-04-17 15:55:20 +00:00
context Move Test files under same folder structure where class is (/includes/) 2014-12-16 21:56:44 +01:00
db Avoid direct DatabaseSqlite constructor use in tests 2015-04-27 13:38:28 -07:00
debug API: Overhaul ApiResult, make format=xml not throw, and add json formatversion 2015-04-10 16:57:15 -04:00
deferred SearchUpdateTest does not require database access 2015-03-26 17:18:12 -07:00
diff tests: Clean up file headers 2015-04-01 00:17:12 +01:00
exception Change case of class names to match declarations 2014-12-19 16:01:26 +00:00
externalstore Move Test files under same folder structure where class is (/includes/) 2014-12-16 21:56:44 +01:00
filebackend Replace use of assertType with assertInternalType and assertInstanceOf 2015-04-09 01:15:44 -04:00
filerepo LocalFileTest does not require database access 2015-03-26 17:36:14 -07:00
GlobalFunctions Remove unused "swap" global function 2015-04-10 18:07:38 +01:00
htmlform Add a few PHPUnit tests for HTMLAutoCompleteSelectField 2014-08-26 12:33:21 -07:00
installer InstallDocFormatter: Hyperlink Phabricator task numbers 2014-11-21 03:05:44 -05:00
jobqueue Remove useless sleep() in JobQueueTest 2014-10-24 14:31:00 +02:00
json Replace use of assertType with assertInternalType and assertInstanceOf 2015-04-09 01:15:44 -04:00
libs Consistently name the $this callback variable "$that" 2015-05-13 23:05:07 +01:00
logging Add unit tests for all LogFormatters 2015-05-03 21:58:00 +00:00
mail Merge "Skip MailAddressTest::testNewFromUser on windows" 2014-09-30 22:38:47 +00:00
media Drop unused FormatMetadata::flattenArray method 2015-04-20 15:41:28 +02:00
objectcache Allow for dynamic TTLs in getWithSetCallback() 2015-05-12 13:04:53 -07:00
page Move Test files under same folder structure where class is (/includes/) 2014-12-16 21:56:44 +01:00
parser Add @group Database tags to tests that need it 2015-04-01 11:20:23 +02:00
password Add lots of @throws 2014-12-24 13:49:20 +00:00
poolcounter Break some long lines in maintenance, skins, tests 2014-07-24 19:03:17 +02:00
registration registration: Use a static whitelist of keys that are not attributes 2015-05-17 23:32:33 -07:00
resourceloader resourceloader: Replace timestamp system with version hashing 2015-05-19 22:28:17 +00:00
search Move Test files under same folder structure where class is (/includes/) 2014-12-16 21:56:44 +01:00
site Consistently name the $this callback variable "$that" 2015-05-13 23:05:07 +01:00
skins tests: Clean up file headers 2015-04-01 00:17:12 +01:00
specialpage tests: Clean up file headers 2015-04-01 00:17:12 +01:00
specials Add @group Database tags to tests that need it 2015-04-01 11:20:23 +02:00
title tests: Clean up file headers 2015-04-01 00:17:12 +01:00
upload API: Overhaul ApiResult, make format=xml not throw, and add json formatversion 2015-04-10 16:57:15 -04:00
utils Fix most of IPTest to use data providers 2015-04-10 09:03:58 -07:00
BlockTest.php Let BlockTest.php respect database constraints 2014-10-15 18:09:49 +00:00
CollationTest.php Fixed some @params documentation (tests) 2014-04-17 20:43:42 +02:00
DiffHistoryBlobTest.php Replace a bunch of extension_loaded() checks with checkPHPExtension() 2014-01-23 23:09:53 +00:00
EditPageTest.php Add supportsDirectEditing methods to ContentHandler 2015-04-17 15:55:20 +00:00
ExtraParserTest.php Add @group Database tags to tests that need it 2015-04-01 11:20:23 +02:00
FallbackTest.php Pass phpcs-strict on some test files (2/x) 2014-04-24 17:05:34 +02:00
FauxRequestTest.php WebRequest::getHeader: add optional flag to get back list 2015-05-08 17:58:54 -07:00
FauxResponseTest.php Pass phpcs-strict on some test files (2/x) 2014-04-24 17:05:34 +02:00
FormOptionsInitializationTest.php
FormOptionsTest.php
GitInfoTest.php Fix GitInfoTest::testValidJsonData on windows 2014-09-30 20:44:45 +00:00
HooksTest.php Pass phpcs-strict on some test files (2/x) 2014-04-24 17:05:34 +02:00
HtmlFormatterTest.php Set $wgInternalTidy to false in unit tests when running under HHVM 2014-12-18 14:58:18 -08:00
HtmlTest.php Html::srcSet: allow density to be specified either with or without trailing 'x' 2015-04-05 05:22:47 +00:00
HttpTest.php Profile all external HTTP requests from MW 2015-03-03 20:54:30 -08:00
ImportTest.php Proper namespace handling for WikiImporter 2014-12-10 22:24:47 +11:00
LicensesTest.php
LinkerTest.php Don't double escape in Linker::formatLinksInComment 2015-01-15 18:14:42 +00:00
LinkFilterTest.php Fixed some @params documentation (tests) 2014-04-17 20:43:42 +02:00
MediaWikiVersionFetcherTest.php tests: Clean up file headers 2015-04-01 00:17:12 +01:00
MessageTest.php Message: Clean up unit tests and improve code coverage 2015-04-02 08:36:19 +01:00
MimeMagicTest.php Cleanup some docs (tests) 2014-08-11 20:06:52 +02:00
MovePageTest.php Check $auth parameter in Title::isValidMoveOperation() 2015-02-05 10:52:10 -08:00
MWNamespaceTest.php Standardize @todo 2014-07-23 22:27:20 +02:00
MWTimestampTest.php Reject out-of-range output when converting to TS_MW 2014-12-19 17:06:38 -05:00
OutputPageTest.php Merge "resourceloader: Omit empty parameters from mw.loader.implement calls" 2015-04-06 06:22:45 +00:00
PathRouterTest.php Pass phpcs-strict on some test files (3/x) 2014-04-24 18:51:39 +02:00
PreferencesTest.php Fixed spacing 2013-12-01 20:58:51 +01:00
PrefixSearchTest.php PrefixSearchTest: Move insertPage() from setUp() to addDBData() 2015-03-25 19:10:40 +00:00
RevisionStorageTest.php Pass phpcs-strict on some test files (3/x) 2014-04-24 18:51:39 +02:00
RevisionStorageTestContentHandlerUseDB.php Pass phpcs-strict on some test files (3/x) 2014-04-24 18:51:39 +02:00
RevisionTest.php Pass phpcs-strict on some test files (3/x) 2014-04-24 18:51:39 +02:00
SampleTest.php Verify parameter for MapCacheLRU::has() can be passed to array_key_exists() 2015-03-23 15:26:59 -07:00
SanitizerTest.php Use wikimedia/utfnormal library, add backwards-compatability layer 2015-03-24 12:59:26 -07:00
SanitizerValidateEmailTest.php Standardize @todo 2014-07-23 22:27:20 +02:00
SiteConfigurationTest.php Pass phpcs-strict on some test files (3/x) 2014-04-24 18:51:39 +02:00
StatusTest.php Fix magic getter for $status->ok 2015-02-14 00:05:41 +00:00
TemplateCategoriesTest.php
TemplateParserTest.php TemplateParser: make most functions protected, only expose processTemplate() 2015-03-22 20:31:59 -07:00
TestingAccessWrapper.php Fix TestingAccessWrapper::__call 2015-03-26 09:26:01 +00:00
TestingAccessWrapperTest.php Fix TestingAccessWrapper::__call 2015-03-26 09:26:01 +00:00
TestUser.php Fixed spacing 2014-10-30 17:50:19 +01:00
TimeAdjustTest.php Fixed spacing 2014-07-19 23:12:10 +02:00
TitleArrayFromResultTest.php test: Clean up data providers that should be static 2014-09-18 12:52:44 -07:00
TitleMethodsTest.php Make TitleMethodsTest a LangTestCase 2014-12-30 10:22:56 +01:00
TitlePermissionTest.php Clean up handling of 'infinity' 2015-03-13 11:19:53 -04:00
TitleTest.php Support Title::GAID_FOR_UPDATE for Title->exists 2015-05-05 03:13:26 +00:00
UserArrayFromResultTest.php test: Clean up data providers that should be static 2014-09-18 12:52:44 -07:00
UserTest.php Added CAS logic to User::addAutopromoteOnceGroups 2015-04-16 13:31:40 -07:00
WebRequestTest.php Fixed spacing 2014-07-20 21:41:41 +02:00
XmlJsTest.php test: Clean up data providers that should be static 2014-09-18 12:52:44 -07:00
XmlSelectTest.php Typo fixes and non-code tweaks 2014-12-12 18:31:15 +00:00
XmlTest.php Html: Make addition of 'mw-ui-input' conditional on $wgUseMediaWikiUIEverywhere 2015-03-13 19:02:34 +00:00