diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FetchType.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FetchType.php index cb5accdb8..b8acabd4c 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FetchType.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/Enumerations/FetchType.php @@ -38,11 +38,11 @@ class FetchType */ private static function addHelper(&$aReturn, $mType) { - if (is_string($mType)) + if (\is_string($mType)) { $aReturn[$mType] = ''; } - else if (is_array($mType) && 2 === count($mType) && is_string($mType[0]) && + else if (\is_array($mType) && 2 === count($mType) && \is_string($mType[0]) && is_callable($mType[1])) { $aReturn[$mType[0]] = $mType[1]; @@ -58,13 +58,13 @@ class FetchType public static function BuildBodyCustomHeaderRequest(array $aHeaders, $bPeek = true) { $sResult = ''; - if (0 < count($aHeaders)) + if (0 < \count($aHeaders)) { - $aHeaders = array_map('trim', $aHeaders); - $aHeaders = array_map('strtoupper', $aHeaders); + $aHeaders = \array_map('trim', $aHeaders); + $aHeaders = \array_map('strtoupper', $aHeaders); $sResult = $bPeek ? self::BODY_PEEK : self::BODY; - $sResult .= '[HEADER.FIELDS ('.implode(' ', $aHeaders).')]'; + $sResult .= '[HEADER.FIELDS ('.\implode(' ', $aHeaders).')]'; } return $sResult; diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php index 2aead1f92..ba786af17 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Imap/ImapClient.php @@ -1697,7 +1697,6 @@ class ImapClient extends \MailSo\Net\NetClient if ($bFindCapa) { -// $this->oLogger->WriteDump($oImapResponse); $this->initCapabilityImapResponse($oImapResponse); } @@ -2022,6 +2021,21 @@ class ImapClient extends \MailSo\Net\NetClient break; } + // TODO + $iClosingPosNext = $iClosingPos + 1; + if ( + isset($this->sResponseBuffer[$iClosingPosNext]) && + ' ' !== $this->sResponseBuffer[$iClosingPosNext] && + "\r" !== $this->sResponseBuffer[$iClosingPosNext] && + "\n" !== $this->sResponseBuffer[$iClosingPosNext] && + ']' !== $this->sResponseBuffer[$iClosingPosNext] && + ')' !== $this->sResponseBuffer[$iClosingPosNext] + ) + { + $iClosingPos++; + continue; + } + $iSlashCount = 0; while ('\\' === $this->sResponseBuffer[$iClosingPos - $iSlashCount - 1]) { diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index b40d8312d..4abf7f48d 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -152,28 +152,28 @@ class MailClient return \MailSo\Imap\Enumerations\FetchType::BODY_HEADER_PEEK; // return \MailSo\Imap\Enumerations\FetchType::ENVELOPE; - - return \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array( - \MailSo\Mime\Enumerations\Header::RETURN_PATH, - \MailSo\Mime\Enumerations\Header::RECEIVED, - \MailSo\Mime\Enumerations\Header::MIME_VERSION, - \MailSo\Mime\Enumerations\Header::MESSAGE_ID, - \MailSo\Mime\Enumerations\Header::FROM_, - \MailSo\Mime\Enumerations\Header::TO_, - \MailSo\Mime\Enumerations\Header::CC, - \MailSo\Mime\Enumerations\Header::BCC, - \MailSo\Mime\Enumerations\Header::SENDER, - \MailSo\Mime\Enumerations\Header::REPLY_TO, - \MailSo\Mime\Enumerations\Header::IN_REPLY_TO, - \MailSo\Mime\Enumerations\Header::DATE, - \MailSo\Mime\Enumerations\Header::SUBJECT, - \MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY, - \MailSo\Mime\Enumerations\Header::IMPORTANCE, - \MailSo\Mime\Enumerations\Header::X_PRIORITY, - \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, - \MailSo\Mime\Enumerations\Header::REFERENCES, - \MailSo\Mime\Enumerations\Header::X_DRAFT_INFO, - ), true); +// +// return \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array( +// \MailSo\Mime\Enumerations\Header::RETURN_PATH, +// \MailSo\Mime\Enumerations\Header::RECEIVED, +// \MailSo\Mime\Enumerations\Header::MIME_VERSION, +// \MailSo\Mime\Enumerations\Header::MESSAGE_ID, +// \MailSo\Mime\Enumerations\Header::FROM_, +// \MailSo\Mime\Enumerations\Header::TO_, +// \MailSo\Mime\Enumerations\Header::CC, +// \MailSo\Mime\Enumerations\Header::BCC, +// \MailSo\Mime\Enumerations\Header::SENDER, +// \MailSo\Mime\Enumerations\Header::REPLY_TO, +// \MailSo\Mime\Enumerations\Header::IN_REPLY_TO, +// \MailSo\Mime\Enumerations\Header::DATE, +// \MailSo\Mime\Enumerations\Header::SUBJECT, +// \MailSo\Mime\Enumerations\Header::X_MSMAIL_PRIORITY, +// \MailSo\Mime\Enumerations\Header::IMPORTANCE, +// \MailSo\Mime\Enumerations\Header::X_PRIORITY, +// \MailSo\Mime\Enumerations\Header::CONTENT_TYPE, +// \MailSo\Mime\Enumerations\Header::REFERENCES, +// \MailSo\Mime\Enumerations\Header::X_DRAFT_INFO, +// ), true); } /** diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index 9c686463d..5e76f07b6 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -1946,7 +1946,6 @@ class Actions $bMainCache = false; $bFilesCache = false; - $bPing = false; $iOneDay1 = 60 * 60 * 23; $iOneDay2 = 60 * 60 * 25; @@ -1958,7 +1957,6 @@ class Actions $iMainCacheTime = !empty($aTimers[0]) && \is_numeric($aTimers[0]) ? (int) $aTimers[0] : 0; $iFilesCacheTime = !empty($aTimers[1]) && \is_numeric($aTimers[1]) ? (int) $aTimers[1] : 0; - $iPingTime = !empty($aTimers[2]) && \is_numeric($aTimers[2]) ? (int) $aTimers[2] : 0; if (0 === $iMainCacheTime || $iMainCacheTime + $iOneDay1 < \time()) { @@ -1972,19 +1970,13 @@ class Actions $iFilesCacheTime = \time(); } - if (0 === $iPingTime || $iPingTime + $iOneDay1 < \time()) - { - $bPing = true; - $iPingTime = \time(); - } - - if ($bMainCache || $bFilesCache || $bPing) + if ($bMainCache || $bFilesCache) { if (!$this->StorageProvider()->Put(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers', - \implode(',', array($iMainCacheTime, $iFilesCacheTime, $iPingTime)))) + \implode(',', array($iMainCacheTime, $iFilesCacheTime)))) { - $bMainCache = $bFilesCache = $bPing = false; + $bMainCache = $bFilesCache = false; } } @@ -2002,11 +1994,6 @@ class Actions $this->Logger()->Write('Files GC: End'); } - if ($bPing) - { - $this->KeenIO('Ping'); - } - $this->Plugins()->RunHook('service.app-delay-start-end'); return $this->TrueResponse(__FUNCTION__); diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 000000000..4e0ac9ad2 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/data/mails/uid-01.eml b/tests/data/mails/uid-01.eml new file mode 100644 index 000000000..945568682 --- /dev/null +++ b/tests/data/mails/uid-01.eml @@ -0,0 +1,232 @@ +MIME-Version: 1.0 +Message-ID: <45a92f7.0e89f233c32fbd2b9d191d4cb28775c9@domain.com> +From: from@domain.com +To: test@domain.com +Subject: TEST HTML MESSAGE WITH ATTACHMENT +Date: Thu, 6 May 2010 07:26:37 -0700 (PDT) +Content-Type: multipart/mixed; + boundary="--=_NextPart_11de424d3d872ac110be4ecfffc45411" + +----=_NextPart_11de424d3d872ac110be4ecfffc45411 +Content-Type: text/html; + charset="utf-8" +Content-Transfer-Encoding: Quoted-Printable + +TEST HTML MESSAGE WITH ATTACHMENT + +----=_NextPart_11de424d3d872ac110be4ecfffc45411 +Content-Type: image/gif; + name="av-7.gif" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="av-7.gif" + +R0lGODdhMgAyAOfXAAAAADMAAGYAAJkAAMwAAP8AAAAzADMzAGYzAJkzAMwzAP8zAABmADNmAGZm +AJlmAMxmAP9mAACZADOZAGaZAJmZAMyZAP+ZAADMADPMAGbMAJnMAMzMAP/MAAD/ADP/AGb/AJn/ +AMz/AP//AAAAMzMAM2YAM5kAM8wAM/8AMwAzMzMzM2YzM5kzM8wzM/8zMwBmMzNmM2ZmM5lmM8xm +M/9mMwCZMzOZM2aZM5mZM8yZM/+ZMwDMMzPMM2bMM5nMM8zMM//MMwD/MzP/M2b/M5n/M8z/M/// +MwAAZjMAZmYAZpkAZswAZv8AZgAzZjMzZmYzZpkzZswzZv8zZgBmZjNmZmZmZplmZsxmZv9mZgCZ +ZjOZZmaZZpmZZsyZZv+ZZgDMZjPMZmbMZpnMZszMZv/MZgD/ZjP/Zmb/Zpn/Zsz/Zv//ZgAAmTMA +mWYAmZkAmcwAmf8AmQAzmTMzmWYzmZkzmcwzmf8zmQBmmTNmmWZmmZlmmcxmmf9mmQCZmTOZmWaZ +mZmZmcyZmf+ZmQDMmTPMmWbMmZnMmczMmf/MmQD/mTP/mWb/mZn/mcz/mf//mQAAzDMAzGYAzJkA +zMwAzP8AzAAzzDMzzGYzzJkzzMwzzP8zzABmzDNmzGZmzJlmzMxmzP9mzACZzDOZzGaZzJmZzMyZ +zP+ZzADMzDPMzGbMzJnMzMzMzP/MzAD/zDP/zGb/zJn/zMz/zP//zAAA/zMA/2YA/5kA/8wA//8A +/wAz/zMz/2Yz/5kz/8wz//8z/wBm/zNm/2Zm/5lm/8xm//9m/wCZ/zOZ/2aZ/5mZ/8yZ//+Z/wDM +/zPM/2bM/5nM/8zM///M/wD//zP//2b//5n//8z//////////wAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEA +AAAh+QQFCADYACwAAAAAMgAyAAAI/gCvCRxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzaswYiNVG +ioFWAAg0kOTHhitYsQJwjZVIKycXBoJ5jeXMa1ZMxjyYUyDLkddS7kTYM2RIn0MRCl0xk+TRpARV +Mg0EwCXJnklZWRG5oqtXkSpZDp0JAKtBqmV3umTqUSbQj1p1NrS68aZEl20v2qW4AuPKi1ovMsXY +12JVVh0R530YSG7Em1a2rogs0AqAy5gx86y4V3BFsxfFThycUbRE0BVdcqZ5ETXEvxhNj3Z8V/bd +whVJW6RMcatG3Q+1Cv3NumHIro1BGtzaUaZXxJIXN9z6tuTlyY1VJrY8mGtl3A7Zcb5sihw6gK6S +mwtMadmjb8aDETc1SRa8QaFUPQJneDyn9pkizVTcfW2FBF1EUnnFXFv7FTQcTjBV9dGDB5n2l2uc +2WeQbDl11hptUdk3k2oZ4aUQiSX1ZRtIGhbkoWorUiSdQz9BxZBVLdpIkIADDhQQACH5BAUIANgA +LAYAIwAlAA8AAAivALEJHEiwoMGD2AAAWBGI4LWHEB8inCgwECtW1wIBsDIwokdsKygWXEFy48MV +HLF5XJkQJMmQE6+xIomRocqVEGeqFNnxoRUr137exGllhcyiDUVG5HgNAEaPrALRZAUgKc+IVIOm +DBSo6EJWLsHyXPEUohWLIVF2bRh1I0+HH4ECwCb1bNeNYt8KXMlKbsWuZ/Pq3etRatPBVwufhYl4 +sFSGOCNLljyz4eTLmCMGBAAh+QQFCADYACwHAAYAJQArAAAI/gCxCRxIsCBBVgYTKlxYMBCAFQwj +SmS14poViBQBIJTIEZuVQNewQbRiZWNHiSsQBiqpERuAazBjyjwpMCW2lYEqIpTJMyRNmytw3rRC +M+JLVi9fXgtatODFFQAAuIwK9RrFnjwXrnzIilVPilCJNs2JzSvWmKwumuxI9OzZnGuNgnTr1mZE +h2bp1o2INFBTgisZktRLOGRcgi3/Avab8CrUqA8FOoRMWSlPiAkHFyaMWXFHqZ5Diy5IcXTEjws7 +h05MMGZZ0WS1ivUMgHHBmbabrrBy9iDosRoDBTrsOzfHi8itACi5EKxxhZOFd4WpnLhAVjlrCze4 +9fVDqCmvbwXGRhfpiseUg5otCzNtRfHPnVZs61bgTKW/EzoU3/EySNQGZYTdbhxlVdF2Ti3Hn0cF +8vTSTR6d99BcJAlk2VkXxhQUThqZNR5NWOFE1EcInUeeaw3ytBKJu2HWU34LYeWcaSf2RGCKm+Wo +Y2EBAQAh+QQFCADYACwHACEAJQAOAAAImACxCRxIsKBBgwASKgx0sKFDg6yuSZQYyMrDiwcjCgwU +8VpFjCCxKVyxwgqAFRJXsAoJcqJEKyitWHQYCAA2hhhdXmOlkqdOnSs4hvwp8xqAnxJ5slo5VGcg +lEd/1gx0TeUKlgR9Rk1a8+rTkCohQqW4AoCViDWZYi049ilVVlPVtkR60so1mVZq5l2LDelOqhvz +ysXqd2JAACH5BAUIANgALAgABgAlACsAAAj+AK8JHEiwoMGDCBMqDMQKm8OHECM6VHgw0AoAgQZm +pMix4ApWrABgY3VRosmTJgNZEQjgmkpsVgKhnGkyJstrGK+NpMnzYUxsFi2y7En047UVKmVapNnx +GkigMklm/DlTISsrF1do3XoRpEimFbEBoCoxEICxHCWSRNqQptmNCSNelUl0JNKmL+s+JNnWpEYr +eiWuiDvya2CIDRE6RHpYsEIAIBmyYtiUYCC6ZR1awbpis+azoEPXbBx4BenTEitTNIx6JkmUgFvD +xCwXm+qErAXTbhzSte3bHndL3Ax8IGCuH03evX2VreSZnVVbHGyQbESslBdyDT22sHCHFgFldL4c +GaQV8XQZpqTZcPNWzup54uw7fHBs0kYPhnSZm2jv/AUtRVJ/fhkkEoAaQXbUfWAV9BUrAzUknnkM +VnUQZBOZ1RmE2DCGGoMK8mdFQ6/Jp5hmbGlFn2wOhYQeiyitCONDAQEAIfkEBQgA2AAsCAAgACUA +EQAACKAAsQkcSLCgwYNWWAVidbChw4cEA0GcePCaRYusVkikyDGQlRUgA1kEwJEiAI2sUmITGWhF +yYkXL67MyJEkxJgXXWK75tCKlZI4La5gBYCnQ5UUg16zslEpT5YvCzIVqHTFz4xDHxatyhCnQmxW +hEYtqNGlRY8AAonMyHDswEA2r8FdeBZASps3ncb8adHKybY/3RaUC+BkQsEP9SperDQgACH5BAUI +ANgALAkABgAkACoAAAj+ALEJHEiwoEBWBhMqXEgwEIAVDCNGZLXimhWIFAEglMjRSqBr2CBasbKR +o8QVCAOR1IgNwLWXMGOCNIkSm8pAFRHK3GkyJMIVN21a6RnRJSuXLq8BJVrw4goAAFpCfXqN4k6e +BlU+ZMVqJ8WnQ5nixNb1KkxWF0t2xGbWLE61DAF8bNu2JkOHZenWZXg0ENOCKheO1EsYJNyBLP8C +9mvQ6lOoDwU6hEw5qUyIBgcXJoxZscmonkOLbtx5tEKPCkuHTlzQ8OixCgOLfug0UMmXNkM/tckq +kEPGB0H/xelVeHDgJtP69jj3YsGvyBdOXvH05sWPrA/ilOs7q5Wo0GVWhrQ41yv1x5SBliXbOKrK +tjaJw1/YO2xWlNRDo5aOzT5RkdGxxxVUntkFGEn9+ZfaYZIZBACCATJFUUn5veRQT4SF9RJaVuBm +WkgN9oebaqaV56FpAQEAIfkEBQgA2AAsCQAfACQAEgAACKkAsQkcSLCgQYMrElpJyOqgw4cErVhh +1ZBVoBUQMx5kda2jR1YANIrEFsgKgJMnA10jORLiQowcr7FaYRFjy4MhsXn0KHHmQ5Mjd3oseS3n +QSsCkd4UOLOoQ5DXlC7F1hSAUI8kA7GcKvHi1ahIbU4VGIioUGw2V1j9itUhAIk6d2LLaXRsWa0f +E1Id+1CmWpUXKYrlyxRAII4mGxI+uKLk28U/SyqGbDAgACH5BAUIANgALAkABgAlACwAAAj+AK8J +HEiwoMGDCBMmDMQKm8OHECM+VGgw0AoAgQZmpMix4ApWrABgY3VRosmTJgNZEQjgmkpsVgKhnGky +JstrGK+NpMnzYUxsFi2y7En047UVKmVa5NkRJFCZJDP+pJmQlZWLK7JqvQhSJNOK2ABMlRgIgNiO +EUkibUiz7EaFEK3KJDoSaUeXVujG/ThT4Eu9EVfADQlYYsOE2JAWlig4IQCQDFkxvEsw0FyyDq1c +XaE5s9nPoGsuBrxitGmJlCl6PU2TJMq8rGFeTostteOZik+HtMybtm2DWFVexQhR8++BVyXmZevQ +rm2rH602zwz7IefUFjlntcKcYc21FLNtJ+YLUehjslhjRo5sBUDutwVFjk1rsf32rN4hIqzLKiHn +2SjtRxJzEQlV2lcGPdTfQWsRtV9YCxakkk48tYRQSHlV1BJhCKb2GEmrsUaQdNdoFuJpGhmVXGwT +lfjYUaU5xSJ/as2YVlbE2fhQQAAh+QQFCADYACwKAB4AJQAUAAAIrgCxCRxIsKDBg6wSsjrIsCHD +FQBWSLQSyKHFgxJZXdt4LRDFiyAJsgqk8BorAAtDXgwUUeKKQB1XqHTIEpvGjSexXQMws6BLiTo5 +brRi5drLngatMAy0omNFgwl5ghRKdcVImQitTqXKkShTrhuxedwK9ho2AE8L5gxZti3HlxVTPrzp +FuxXpCpzpsVrsGpRrHz7vi1aM7DgaxRNAjZMcCjMk3sZCzSpk9VRyQUDAgAh+QQFCADYACwJAAYA +JwAsAAAI/gCxCRxIsKBAVgYTKlyYMBCAFQwjSjy44poViKxWAEA4sSM2K4GuYYNoxQpHjxNXIAxk +ciM2ANdiypw506NKbCwDVURIs6dMmwhX5MRpBeVEmKxgwrwm1GjCixoBvATwEGlFnz4bWnnIilXP +jBqLOhWoE5tXrDFZXTyJsihanzrZHg35FuvNiQ7P1rU7MWmgsQNZSiy5d6/ZiC4BB/67MCNTqlQh +4oRMmapPyQoJF96LWXFHqZ5DizaYcfRgxgs7K3bZVS42ka6N/tW4grbYwLcBAwik9xrLuzFxKl5h +RWSgnMFzJwUcdyvIklItsvVr9KLD4jV3qgaLmqFDqbt9Y4ZvSpCVzt3HDbKUuhytTot0v26NSlno +WbNvJWP3ufYqVoFvrdddQRsNqNBmCv11DWgRIZgQeaYlCJNbb3mWVFcRZlZcbhmSZZaBGSqYVEkd +UhRUSCUKJBlLm7VIU0nEuehiQAAh+QQFCADYACwMAB0AJQAVAAAIogCxCRxIsKDBg4FYsTrIsKFD +KysAALDisGLDaxgxsoK40KJHbIEkSlwR6Bo2AIE+OgxJUqMVlNesUFRpcGTJjBpboqRp8CbOjKwA +LJzJU6DPnxllyixKEOlPVhE7EkwZiOhFpzgVHiQplalFANisem0oM+bYjwu7nsWGU6DZtQxTYlML +tyBGsXXnzr0WdEXeghShav07FwDGFXjrBiKJmDDBgAAh+QQFCADYACwJAAYAKAAsAAAI/gCvCRxI +sKDBgwgTKhQYiBW2hxAjSpy4sGCgFQACDdRYsaPBFaxYAcDGCuPEkyhTYgtkRSCAayyxWQmksibK +mS6vZbxG0qbPiDNXrrjo8qdRbCCvDQ160WjHkCtpltQY9GdCVlYwrtjKFWPIkU4N0gRQdWIgAGQ9 +CpRYcqjDmmc5doyIlabRqWoZWjkKseTbmnr5SlwxV6RgttgqIrV7GCLhigBCNmTVMC9DxijtWsm6 +YvNDK2hDiz65t7HgFaZTq7ScEKxqnyVtllaNU6FD1gdXht5a9uFQ1SJ/k6TceWBP3ASHCqRcm+Xf +zcivZYWJceZOnoPlqsU6tPNfpCBPaBZXe7FzRtKEs0rMWllhebRWvg8WLvEigM6BJk8GLRwzyq3+ +9SUSZ50BKN9rFwWYWkIk5fcaXKih9uBDCK3E00KveabghA+JxIpSHFJYUFAHvmbRY1uFmNhGj8Wk +Yn0kufYiRNdMNWNAACH5BAUIANgALAwAHgAlABQAAAiGALEJHEiwoMGCK1YAAJAQG6uDECMStOLw +2rWBAB5K3DhxYKCPGDmKdIiN4cAVgbAFAjBSohWWKT1aSbmi5cGFKzQWjBnT5k6LQINeC0SRpc+B +rIQqHUry6MClUCHqdMoRJUWqHFkZxbqRVU2uIr+CHUu27MarZgU+1LjV7EVsFnOmPTjVbEAAIfkE +BQgA2AAsCQAGACkALAAACP4AsQkcSLCgQFYGEypcuDAQgBUMI0okyGrFNSsQKwJAOLHjQCuBrmGD +aMUKR48eVyAMZHIjNgDXYsqcSVNkR5XYWAayiLCmT5kpEa7QmdMKSo8wWcGEeW3o0YUYVwAA8HKq +1GsVf2pNyPIhK1Y1K0o1+pTgTmxgtWLFePKpUbU1d7ZFGhKuT5weHaa1e9ej0kBlB7LsWJIvXLQT +XQYWDDhiVqlTHwp0GLkyU5oQIxY2DDfz4qNUP4sezbAiacKNI3r+DCDQTsgrTBIUOfcp4NhfYwol +O5l34NZYWQX6ii0m2+IiUz+N/Tr2iucbL3pWGninQ7Q0X6INfbD1UStW91fSrCiX4nPlDSNbsTt1 +rnCprtEXpUqes1ZW4CFXHppWoP2tOKl1GjYlDejYRoMZyNVqCi6El0KXGcZVgxSW9WCFAzn1km8N +shTTSBgOhJBS/3EmolkVBgQAIfkEBQgA2AAsDAAcACYAFgAACJgAsQkcSLCgQYOBAq1YaCUQq4MQ +IxJcAcCKFVYYA1lZEUiiR4SsrokceY0VgI4fPz7ERhGAy4ohOab0yMrKSZI1V1xTONOjFWwkR7I0 +2dPgip+BggbF1rBowYVKo4p0OrAi1acrrjoFoLWr14JKBTb9+vEnWYkPuUpcsZKqxbNwuz5EGfeg +2YV1BxIVm3egzL4Er2GjCxhbQAAh+QQFCADYACwJAAYAKQAsAAAI/gCvCRxIsKDBgwgTKhwYiBW2 +hxAjSpyIbWHBQCsABGJosSPCFaxYAcDGKiPFkyhPBrIiEMC1ldisBEpJE6XMltc0XiNZs6dEmdgw +Ymzps+hDkNdWrJyJ0WjHkEFnltwItGhCVlYyrtjKNWPIkU4NzgRQdWIgAGQ9DpRYUqlDmmc3qo2I +dWbRqWoZWjEKseTbmgJh8o24wiNJsIP7VrSITWliiYU7AgjZkFXDvIHtprRrJeuKzg+toB1NmuLe +x4lXoF4NGDNCxKx7lhRomXLBmLFjdgbwmStsh64PorXyF6LmxscTi2T1cmmgy8t5BieodOZnmZ4b +Ruw8/ZrorcmDYXLVrNQ11pGnT9YmzFItxuGJs15WiHGrRtTvPz+nHPK73fCDQfVdb27lxpZqBtbU +WXoJUhRdg4sZBFqECOX2IIQHgcaggQYttxOEFArkGICxXdQebCAeJtCEKUb0EoIgBgQAIfkEBQgA +2AAsDQAcACUAFgAACJsAsQkcSLCgwYKsrKwAwBCAFVYHI0oUuKJioEDXMl4LBCDQxI8EA7HKyKrk +yIwAIIL8eC3hwooLrWALJHPlRIVWMGpMyLCmzYhWNAod+tMgw5NDkxYtuMLj0p9Hn0qdig1mRaoF +kwLAutIpV4NEvX49KHYigKRo0+YsO3Ygq61ts2bMqTIuQYV2DbJaAZHt2Gt8Z8LNi1dgXbsBAQAh ++QQFEADYACwJAAYAKQAsAAAI/gCxCRxIsKBAVgYTKly4MBCAFQwjSiTIasU1KxArAkA4seNAK4Gu +YYNoxQpHjx5XIAxkciM2ANdiypxJU2RHldhYBrKIsKZPmSkRrtCZ0wpKjzBZwYR5bejRhRhXAADw +cqrUaxV/ak3I8iErVjUrSjX6lOBObGC1YsV48qlRtTV3tkUaEq5PnB4dprV716PSQGUHsuxYki9c +tBNdBhYMOGJWqVMfCnQYuTJTmhAjFjYMN/Pio1Q/ix7NsOLknStWgCRdsGRUk6wCaeTo+TNV2T6V +gkX8eWfMQJStAh482LbshyZlooYYM+di1Wxzy+aoNLDDoXwH/j1qZWpduxRTVjeOGHwveIo7AQAf +L7g72tSctbKKavkhbpFzI6pVb0Ut66Ls/ZfQUMAJqFBPtRlI0GoS4WVbfgpORlaEBTkkUoIROkjh +QCphFdqGgMXk1IanqRdffAEBACH5BAUIANgALAgABgAqACwAAAj+AK8JHEiwoMGDCA1iW8iwoUNW +CSMedEiRoRUAViRqFFhx4YoVrLAFWoGN5EaJHa0ECgQAm0qRK05G7Aiy5MqM1wDITJgyEExWMXPu +RNgxkJWFAFglvWZyaMGO2JaKtJJRpdOTVK9Z+Qiga9cVKiFePah0BYBAIRuyGonRJ1SKCT+6hRoS +QM23DBGCxftwxdy3B41eXcnXICucg48CJgh07ECqiweudCxQadqKBYNS1qoY88DDFC96Hd0Sm9LR +rIBCZRxo88DSngVadZ3zskOCgmmD1JjbtemNOmkH1zibcsmTI10Xlwi0tePjMkeKveo3MsGtY43i +NczW+cnDnfmXmjar8mLTiGv3il+o1OfhpNqtTK+8dmv1hixJdjwr0q7fyluRZhdVbaW2klngVQSZ +dCXNV5BSVk31EVXuJUWRUj955CBjZ7VEGEPpWRiaT/xpGJGFRpk12n0V+TUSXAktJ5Nq6i3UW2CI +7WSUZbjleNBwOsqnWWVDHiTjRjsW2VhELDml0o2V8bYefn75SBtRZxV55UEBAQAh+QQFCADYACwH +ACMAJgAPAAAIsACxCRQYyMqKgwMTKlzIcCGrg4FYsbrWsKLFhACsXGNlBYDHQIEIXhR4raRJkwKt +aHy4YqIVhR5jesQGYEWgkzhLYmMFYCIAbChHSrSZEyc2lddaniRZVKdSg01L8mR11OjIQCuAvtRY +tGDSiUtHCjw4NGNEqgQ1AsgpdmCgjDuxHrSJreBDtm0FcjQrESvVl3et5tWrcm7Iui1X4B188efa +xYwb8lQctbLly5gzlwwIACH5BAUIANgALAcABwAlACoAAAj+ALEJHEiwIKsVVgoqXMhw4MGBAAJZ +Sdiw4kJWVgIBYMVK4EOLIAteWxEo0Ipr17B1DAlSokoA1zZiW7GSZcWDKLEF0okto02BKIMKHdkx +o5UVOin+bDhR54oVAJ5GzRio5lKPCAFkZFX1GleoCK1etcJq6NCdWq/uDGS2LcqjYitKdEv3msm4 +F63UrXtwp8WTe/lGlOv36kCNFQEH3kuSIUaFGgFInixZYOTJXxuyXRwYAEOlhlm6DM0SL2nHnk9D +ZFqY9MeFJlX3BG2Q52maA9siJt24YdmmhnfixRh1Mu2QJs1ajij04OCQzk179gpVMsKnZB1H3qyc +pletbB9qej36FHv1qNx1h0cq1HtQjly/2sW2N+PI9ClBnuxZESYrmENZdFBTT0lnl14BgvQfbjPF +BRNJykGXEEo7IVRSRzABmKBNSJXFVUJ6ZdhWaOx5RZ9nCG4I0lnnUaTViLIBVVeM9HFmY1sBAQAh ++QQFCADYACwGACEAJQAOAAAImACxCcQWaMUKKwZXDFzIsKHDhSsCsZI4UeHDixhXsLrGsSPGjw6t +BLqGbQWAkyhBqsQGgBUrACM7kmS1EiOrFdesWJHJsebHQNiuteRJEqQVlkAfBrJyk2jRjBEFbnQq +cqnTlRpfSiS6lOZVldeiImQqs6tFnwwPkrQCICLHggfRNmSFcGRFnCU1ynV4E2bFqU577qV78GhA +ACH5BAUIANgALAYABwAlACoAAAj+AK8JHEiwoEBWBhMqXFjQCgBsDCMqXLECYSBs2FZcxMixo8eP +IAMFAnDNysWLEguC5Fgxo0grAkmmHLgSo0lsF1lBvCZz5rWaOGHyZAVAZ0ugSD0WdWkFpkmfP4E2 +LUkRgFWrK0wiZJg0I4BAOjuyCrTiYSCoBClurDkWQEW0WbtyZKXRZyArcj2KVAmSFd68eoUK7LsC +MMimQEUa/kg0bMIVaBUiXvm3o8OrmB9iI4qZFd2VYRcDvik679rSXe+i9lh4Zc/IBTUfPl2abE2U +sAmSJkzb8Ge9d9duhY2TMjaTeHOr/tjb4VmffitznEqVYtayOCWOjetR58/Cnj1en7z7dfjBsVbU +HpbO9nLmsrs/kk6YtCLuiWNLf72WdaH93l1ZdRZ1BmkUX15NFcXfTgW9xB5gIyGEnXkcAZgXXWf5 +5dZzQSlkmENCZQTZaoS91RiJoF3VGoqggYVNQAAh+QQFCADYACwGACEAJQAQAAAInwCxCcS2AoBB +ANiuKVzIsKHDawMjFky4UCCriBgzaowYyIrCQCCtXNxIkiSrFRdXWLHScYXLkjAxrsDGsmHMmwNB +UrSJE2ZHlj0jAoB4EyXJhxWt3Aw09CHOa6wAjMyo1GjQgSsCXWM6FaMVq1cFotwq1eFFqWEHshIJ +tSBbhdhYdU17kiIrph6JppUY1+XbrHr3ZuwI4GtWwTEDyVUYEAAh+QQFCADYACwGAAcAJAAqAAAI +/gCxCRxIsCA2ViusGFzIcCHCgQACWVHYsKJBVlYCAWDFSuBDiyAJXlsRKNCKa9cOhgQp8SCAaxux +rei4siJClNgC5cSWsSbKn0BRzuQpcUVOijUbTsy5YgWApk8zBqKZdCBCKwAyspp6bavThFSr8mQV +NKjOrFV1BirLFqWVoSEltp17zWRYhhjp0kWos+JJvXsjNiwptqDGhn8B6yXpEOlAjQAiS44sELJk +rwzXKgYMYKHjwiw/g254dzTpzqYhMuyZ+qNBk6l5Ot7aUrBpuDmzZnSKGjTjyjOBYhS9UidNVhFR +cuSY0kppiyaBTqzbtHpnp31BIowJkexG4diyajZ1jheyZqAvdbI92PVt9YS8O58P+vL3QuEcp9pl +37b+87iwMfTSTlUhF1N2F9lXFWNGLUQYaBO9dA1rBHUkYVkhTfSXSQjqpd1AwZnUIDYerlQXd+H1 +lpqEyCkYm0BAmdTZgC9exBE2AQEAIfkEBQgA2AAsBQAfACUAEgAACK4AsQlkZQWblUAFBSpcyLCh +w4ErrByUuOKhxYvYWK1gda2jR4wgGa4IdC3QipMRWQn0yLKly4asAFyzspEVQoErAAAIeRHhNQAc +WWILxBPjQZMuOw4t+hChyqQziWJcAbXjwadJQVKVaNEkNplZQSa8KJMpQ502jR40q/AkQapQTapk +iy1iQZovQ1ZVWpcoTZIf6TrUSDIQgIN8BTs8aRUAScUWrThOC7knzZHYAgIAIfkEBQgA2AAsBQAH +ACQAKwAACP4ArwkcSLDgQFYGEypcSNAKAGwMIyZcsQJhIGzYVlzEyLGjx48fAwUCcM3KxYsSB4Ls +WDGjSCsCSaa8tpKjSWwXWUG8JjNlTYyBYPJkBUBny59IOxZ1aQWmyZlJm5akCKBq1RUmESpMinEF +gEA6O7IK5BXnzIIUN9YcC6Di2WtYuXJkpXFmULkeRapcycoK3pBC+a74C7JpTZGEPxLVanDF24WG +C390aLXyQ2xEK7OiCzJsYrw3P8tVKzrp3dIsV/Z8bPDyZNKiyRLcvFk264KhR1Kk+hU1Z2wO/Xa0 +4vi2QJwYlwIHjtCv8dNkM950iNzs2b7CgQ/eOTBo24eBJHCOjctxcGSPi8liZSywdkaNHiuG/ni0 +r1fLXq14Zkl3f2Llrx21EkOYSZWQdwtxBVNRBxKXYFJFoWQQTuwVxNVDJQlFEGocVRVeXRtyCJxD +NOkXooiYOUZXeMehiBFxCFGEkIs2YQgcTTRiRFRTfgUEACH5BAUIANgALAMAHwAlABMAAAiuALEJ +xMbKCoCDVlasGMiwocOHAxMGukYxkBWIGDNiCwSAoseKBDWKJAhg4oqDCFmNHMnxWiBsHxVaubgS +4wqTLx0qrAkRgMqOHz1iu2mxJE+S16xMDCq0IcqnABY+ZOVzBSumTTVaxHqN1UkrXCmOvOYTIqur +Ya+xDLQirduVZFU2dJtVK1umRzW2LRk0b0afVNGK9WvTJdDBhB/eVNsWcWKHfIc6fsyQKkyv1wIC +ACH5BAUIANgALAMABwAmACsAAAj+ALEJHEiwIEFWK6wYXMiwIcKBAAJZUdiwIkNWVgIBYMVK4EOL +IA1eWxEo0Ipr17B1DBlSokoA1zZiW7GSpUWEKLEF0oktI0uUQIMKpdlT4gqdFG1anKhzxQoATqFm +DFRT6cGEADKyonpt69OEVa0KtMJKqNCdWcXyDGS2LUorRG1KdEv3msmwDq3UrYtwJ8iTe/lGtFhS +LUGNFgEH3ksyr0GNACJLjiwQsmSvFdkuDgygYVLDLF2CZol3tMPOpgWiZujT9MfKViI7dZqaqUqn +XDnG9gs6LkmUW8t2Xa22cU9sXZ3CdYrxs9KdHRFy/A1c406yVk0CpXlNoVlWUJ9o8r75tOZG8MLN +xl6OfeHWyJqBwpxYV2DX5bPhStbZNnz6tvYBxVFwd8HkFnKBgQSTcSItdpNOJjG02V96yZRaRZhd +iCFPGhpE2V0dGuRUd86F2BNZrZno0UYkqjiQS+gFuNmMEoGITUAAIfkEBQgA2AAsAQAeACYAFAAA +CKYAsQnExsrKCgAIAQxcyLChQ4asVlhhda3itYcYMwq0AiDQNVaBDK4IpLHkQlYdrwXqCJIVto4m +S1qxck2iRYvYDiq8ybMnzoEAQK6g6JMkwpgNUdbE5vMm0ocShzbF6fLpSZpTf2oMtMJh1p4luwa1 +6nUq05lkn45N+3TmNbRsY1JUGNeklYFO6zoEUJGkXo0rKg79i3HkR5iEk47lejExw5WslAYEACH5 +BAUIANgALAEABwAoACsAAAj+AK8JHEiwoMFrrA4qXMiQoBUA2BpKXLhiRcJA2LCtwJixo8ePIEN2 +DBQIwDUrGDFOFCgypEWNJK0INLmyJUiU2DCyiniN5kSbHwPJ7MkKwM6XQJOCNArTikyUNZVmdHqy +IoCrV1egTKhQqscVAALt9MgqENicKyluBFoWgMW0BbV6xcZqI1yBQueODDRQKSsrej0KZcl2ReCP +TpWSPEzWqMQVdxUmBgoYMdbLVzMWvcyqLlvGh3GCnstxtNe8pjMaBuozcsHWCElW3Ch6tFmCs610 +NuvWdUGoArUKLMu16FjGnj0KfPhQuBXIvq/l7Gi4buWcD4W+jYx6bM/SI8FjuuWb9u/1jpND8oZI +nmFZuR4hJt0ZMyzXgbs1rgUJ3u9DzG5pdVxqLe20EIGaGbYfgjbddhCDGWHEFIQuXWPWgBR2dFR/ +GWpEF2zSZbiTgQRlCNhy7YVIIVVFnSdiWBauhk1AACH5BAUIANgALAEAHgAlABQAAAiDALEJxMYq +UKAVK6wYHMiwocOHAwMBUBgIWyArEDNqtAiAlUBWrK6JxLai4saNBz2yWkHypEuGJS3KbGgF48uH +1wiuFMlTJCubNx1exNYxqNEVHXsqHWmU4dKnPJtKdXlwatCiVrNq3cq1q1eXNb+iBCo2oUCWYgcm +zRkSqtu3PdF6DAgAIfkEBQgA2AAsAQAHACgAKwAACP4AsQkcSLCgQVYrrBhcyLChQIQDAQSyotCh +RYasrAQCwIrVwxUXQy68tiJQoBXXrmHzKFLkxJUArnHEtoJly4sIU2ILtBObRpEpgwodmrKmz4kg +X94MSXHnihUAnkbVGMjm0oIIrQDQyKrqta5QE1q9OtAKK6JCeW4lK5BnILRwrRhdOhGu3Wsnx1rM +ePcuQp4iUfb1KzGkSbYDN4YUPLhvyb0VCW4EQLky5baWOZ68+LbxYAAWIyNuqXS0SL2mHbICnRob +64dIS1b9aRqiwKcKO1IMm7rpamxw3Zqu+Rtv5q1VX5N9XFcr16Abd7Pl6bGkWLhSRbtkjLvv5LUh +EVHOhN34JEWJgA9O7ux5qMCvcp/ihnqZvdCbGoV27Aq2LtzWBMmEGll3gUYbgA11pByCDD3G4IOj +aQchTUUNCCFCFrYmV1sgTVhWRQ56aFNpAQEAIfkEBQgA2AAsAAAcACYAFgAACKAAsQkUyMpKIIOs +BipcyLDhwkAAVgg8uGKFFYkOMzoMtCLQtY8gWQXSSHLhRVYFK1ZEeK1kSVYArsG0glIkx44jXWY8 +yGoFK5BAsVm0YkVnw4QAfgIFmvAitoRGBy6dCrSoxJxRqWptCUCoRahRjYLNiDGsQp9m0+qcqpZk +2bYuOcKNOnZuw6J2o2LNa7IozL18G3YNnJEo4YxJDysc7DMgACH5BAUIANgALAAABwApACsAAAj+ +AK8JHEiwoEGBrA4qXMiwoBUA2BpKZLhiRcJA2LCtwJixo8ePIEN6DBQIwDUrGDFOFChSpEWNJK0I +NLmyZUiU2DCyiniN5kSbIAPJ7MkKwM6XQJOGNArTikyUNZV2dHqyIoCrV1egTKhQ6scVAALt9Mgq +ENicKyluBFoWgMW0BrV6xcZqI9yBQud2JDlQKisrekcOVVo38EenUkkaJmt04oq7ChEnBXwYq+Wr +GYtaZlWY7eLFOD/r5Sjao8S8pTOu6NjWMjYrRSErhPja7diMQq+S/mzW9DXOYhO+5il7YOhAJ91q +PSt27efCdR/C/mi24uPi13JGRC2yJMTi3AlUY0We9i/luXUxk2dYVi7v3GILAtfoPPXfy1m13k5t +Mzx/kXXF1tV/HklGoE0CGnSgR3YpuOB2PhH0oHZaOfjgb29J+OBadRU0YYA5XcfShFRl51FAACH5 +BAUIANgALAAAHAAmABYAAAiiALEJZGVlxQorVgKxEsiwocOHEAVaAYCNFatAgQquCBSxY8dAK66J +HCmSoMeTDVmFxFYQgMuErK5xRHnyGrYVFGNeu4jTCjYAC2lG3GmRJEmEA4VCNMq05AqlUCH6jNqw +qVWbVLOyAspwataoOF2KBYD0q9mvV69RfHpW6Ma2KDGyhUsXbtm6EbcGxevwqc+RfLsuvBsYG0eR +bwsLBMBx67WAACH5BAUQANgALAEABwAoACsAAAj+ALEJHEiwoEFWK6wYXMiwoUCEAwEEsqLQoUWG +rKwEAsCK1cMVF0MuvLYiUKAV165h8yhS5MSVAK5xxLaCZcuLCFNiC7QTm0aRKYMKHZqyps+JIF/e +DElx54oVAJ5G1RjI5tKCCK0A0Miq6rWuUBNavTrQCiuiQnluJSuQZyC0cK0YXToRrt1rJ8dazHj3 +LkKeIlH29SsxpEm2AzeGFDy4b8m9FQluBEC5MuW2ljmevPi28WAAFiMjbql0tEGTVFnqNX2y5E/K +JkGbFiixJtrNgEcjNIo0ocmUcmc33Viyo9qSKnOzrTmx89CTGmUv5zm4NUiyPD02ZkVZtEvGnmVU +whaJcCZdn0/NYpzsPHxQkF/lPk0PNepOtFeFduwKVqPd2QZdB2BDOZk3oEObHeiQTAqG5l2DBHEH +IUMkPQhhTMlNSFBCRa12oEceJajhThKpZFNAADs= + + +----=_NextPart_11de424d3d872ac110be4ecfffc45411-- + + diff --git a/tests/data/mails/uid-02.eml b/tests/data/mails/uid-02.eml new file mode 100644 index 000000000..5c3a73f39 --- /dev/null +++ b/tests/data/mails/uid-02.eml @@ -0,0 +1,16 @@ +MIME-Version: 1.0 +From: test@domain.com +To: test@domain.com +Subject: TEST MESSAGE +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: 8bit +Date: Wed, 28 Apr 2010 02:04:20 -0700 +Message-ID: <16800462619664130307453@TEST-TEST> + +TEST + +. + +. MESSGAE + +BODY diff --git a/tests/data/mails/uid-03.eml b/tests/data/mails/uid-03.eml new file mode 100644 index 000000000..71d3108a5 --- /dev/null +++ b/tests/data/mails/uid-03.eml @@ -0,0 +1,18 @@ +Envelope-to: webmail@test.com +Delivery-date: Tue, 15 Jun 2010 22:48:56 -0700 +Received: from [84.51.195.105] (helo=local) + by mail.test.com with esmtpa (Exim 4.71) + (envelope-from ) + id 1OOlUe-0002EQ-IJ + for webmail@test.com; Tue, 15 Jun 2010 22:48:56 -0700 +Date: Wed, 16 Jun 2010 09:48:42 +0400 +From: sss +X-Mailer: The Bat! (v4.0.24) Professional +Reply-To: sss +X-Priority: 3 (Normal) +Message-ID: <708372127.20100616094842@test.com> +To: webmail@test.com +Subject: =?iso-8859-5?B?v+DY4eLj39DvIA==?= =?iso-8859-5?B?2iDg0NHe4tUg4Q==?= =?iso-8859-5?B?3iDh2+PW0d7ZIA==?= =?iso-8859-5?B?V2luZG93cyBMaQ==?= =?iso-8859-5?B?dmUgSG90bWFpbA==?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=windows-1251 +Content-Transfer-Encoding: 8bit diff --git a/tests/data/mails/uid-04.eml b/tests/data/mails/uid-04.eml new file mode 100644 index 000000000..e5f692188 --- /dev/null +++ b/tests/data/mails/uid-04.eml @@ -0,0 +1,55 @@ +MIME-Version: 1.0 +Message-ID: <45a92f7.0e89f233c32fbd2b9d191d4cb28775c9@domain.com> +From: from@domain.com +To: test@domain.com +Subject: TEST HTML MESSAGE WITH ATTACHMENT +Date: Thu, 6 May 2010 07:26:37 -0700 (PDT) +Content-Type: multipart/mixed; + boundary="--=_NextPart_11de424d3d872ac110be4ecfffc45411" + +----=_NextPart_11de424d3d872ac110be4ecfffc45411 +Content-Type: text/html; + charset="utf-8" +Content-Transfer-Encoding: Quoted-Printable + +TEST HTML MESSAGE WITH ATTACHMENT + +----=_NextPart_11de424d3d872ac110be4ecfffc45411 +Content-Type: image/gif; + name="av-7.gif" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; + filename="av-7.gif" + +R0lGODdhMgAyAOfXAAAAADMAAGYAAJkAAMwAAP8AAAAzADMzAGYzAJkzAMwzAP8zAABmADNmAGZm +AJlmAMxmAP9mAACZADOZAGaZAJmZAMyZAP+ZAADMADPMAGbMAJnMAMzMAP/MAAD/ADP/AGb/AJn/ +AMz/AP//AAAAMzMAM2YAM5kAM8wAM/8AMwAzMzMzM2YzM5kzM8wzM/8zMwBmMzNmM2ZmM5lmM8xm +JkGbFiixJtrNgEcjNIo0ocmUcmc33Viyo9qSKnOzrTmx89CTGmUv5zm4NUiyPD02ZkVZtEvGnmVU +whaJcCZdn0/NYpzsPHxQkF/lPk0PNepOtFeFduwKVqPd2QZdB2BDOZk3oEObHeiQTAqG5l2DBHEH +IUMkPQhhTMlNSFBCRa12oEceJajhThKpZFNAADs= + + +----=_NextPart_11de424d3d872ac110be4ecfffc45411 +Content-Type: image/gif; +Content-Transfer-Encoding: base64 + +R0lGODdhMgAyAOfXAAAAADMAAGYAAJkAAMwAAP8AAAAzADMzAGYzAJkzAMwzAP8zAABmADNmAGZm +AJlmAMxmAP9mAACZADOZAGaZAJmZAMyZAP+ZAADMADPMAGbMAJnMAMzMAP/MAAD/ADP/AGb/AJn/ +AMz/AP//AAAAMzMAM2YAM5kAM8wAM/8AMwAzMzMzM2YzM5kzM8wzM/8zMwBmMzNmM2ZmM5lmM8xm +JkGbFiixJtrNgEcjNIo0ocmUcmc33Viyo9qSKnOzrTmx89CTGmUv5zm4NUiyPD02ZkVZtEvGnmVU +whaJcCZdn0/NYpzsPHxQkF/lPk0PNepOtFeFduwKVqPd2QZdB2BDOZk3oEObHeiQTAqG5l2DBHEH +IUMkPQhhTMlNSFBCRa12oEceJajhThKpZFNAADs= + + +----=_NextPart_11de424d3d872ac110be4ecfffc45411 +Content-Type: image/png +Content-Transfer-Encoding: Quoted-Printable +Content-Disposition: attachment; + filename*0*=111; filename*1*=222.gif; + +TEST HTML MESSAGE WITH ATTACHMENT + + +----=_NextPart_11de424d3d872ac110be4ecfffc45411-- + + diff --git a/tests/data/mails/uid-05.eml b/tests/data/mails/uid-05.eml new file mode 100644 index 000000000..07bd6be69 --- /dev/null +++ b/tests/data/mails/uid-05.eml @@ -0,0 +1,54 @@ +From: alex +To: alex +Date: Thu, 22 Nov 2013 09:42:17 +0100 +Subject: + -------1---------2---------3---------4---------5---------1---------2---------3---------4---------5---------1---------2---------3---------4---------5---------1---------2---------3---------4---------5---------1---------2---------3---------4---------5----... +Thread-Topic: + -------1---------2---------3---------4---------5---------1---------2---------3---------4---------5---------1---------2---------3---------4---------5---------1---------2---------3---------4---------5---------1---------2---------3---------4---------5----... +Message-ID: <50ADE569.2000807@local> +Accept-Language: de-DE +Content-Language: de-DE +X-MS-Has-Attach: +X-MS-TNEF-Correlator: +user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20121026 + Thunderbird/16.0.2 +Content-Type: multipart/alternative; + boundary="_000_50ADE5692000807omninetlocal_" +MIME-Version: 1.0 + +--_000_50ADE5692000807omninetlocal_ +Content-Type: text/plain; charset="iso-8859-15" +Content-Transfer-Encoding: quoted-printable + +Test +-------1---------2---------3---------4---------5---------1---------2-------= +--3---------4---------5---------1---------2---------3---------4---------5--= +-------1---------2---------3---------4---------5---------1---------2-------= +--3---------4---------5---------1---------2---------3---------4---------5-- + +--_000_50ADE5692000807omninetlocal_ +Content-Type: text/html; charset="iso-8859-15" +Content-Transfer-Encoding: quoted-printable + + + + + + + Test
+ + -------1---------2---------3---------4---------5---------1-------= +--2---------3---------4---------5---------1---------2---------3---------4--= +-------5---------1---------2---------3---------4---------5---------1-------= +--2---------3---------4---------5---------1---------2---------3---------4--= +-------5-- + HTML + + HTML + + + +--_000_50ADE5692000807omninetlocal_-- diff --git a/tests/lib/MailSo/Base/LinkFinderTest.php b/tests/lib/MailSo/Base/LinkFinderTest.php new file mode 100644 index 000000000..efd189626 --- /dev/null +++ b/tests/lib/MailSo/Base/LinkFinderTest.php @@ -0,0 +1,96 @@ +object = \MailSo\Base\LinkFinder::NewInstance(); + } + + protected function tearDown() + { + $this->object = null; + } + + public function testNewInstance() + { + $this->assertTrue($this->object instanceof \MailSo\Base\LinkFinder); + } + + public function testClear() + { + $this->object->Text('111'); + $this->assertEquals('111', $this->object->CompileText()); + $this->object->Clear(); + $this->assertEquals('', $this->object->CompileText()); + } + + public function testText() + { + $this->object->Text('222'); + $this->assertEquals('222', $this->object->CompileText()); + } + + public function testLinkWrapper() + { + $this->object + ->Text('333 http://domain.com 333') + ->LinkWrapper(function ($sLink) { + return '!'.$sLink.'!'; + }) + ; + + $this->assertEquals('333 !http://domain.com! 333', $this->object->CompileText()); + } + + public function testMailWrapper() + { + $this->object + ->Text('444 user@domain.com 444') + ->MailWrapper(function ($sMail) { + return '!'.$sMail.'!'; + }) + ; + + $this->assertEquals('444 !user@domain.com! 444', $this->object->CompileText()); + } + + public function testUseDefaultWrappers() + { + $this->object + ->Text('555 http://domain.com user@domain.com 555') + ->UseDefaultWrappers() + ; + + $this->assertEquals('555 http://domain.com user@domain.com 555', + $this->object->CompileText()); + + $this->object->UseDefaultWrappers(true); + + $this->assertEquals('555 http://domain.com user@domain.com 555', + $this->object->CompileText()); + } + + public function testCompileText() + { + $this->object + ->Text('777 http://domain.com user@domain.com <> 777') + ->LinkWrapper(function ($sLink) { + return '~'.$sLink.'~'; + }) + ->MailWrapper(function ($sMail) { + return '~'.$sMail.'~'; + }) + ; + + $this->assertEquals('777 ~http://domain.com~ ~user@domain.com~ <> 777', $this->object->CompileText(true)); + $this->assertEquals('777 ~http://domain.com~ ~user@domain.com~ <> 777', $this->object->CompileText(false)); + } +} diff --git a/tests/lib/MailSo/Imap/ImapClientTest.php b/tests/lib/MailSo/Imap/ImapClientTest.php new file mode 100644 index 000000000..92d994029 --- /dev/null +++ b/tests/lib/MailSo/Imap/ImapClientTest.php @@ -0,0 +1,85 @@ +TestSetValues($rConnect, array('NAMESPACE')); + $oResult = $oImapClient->GetNamespace(); + + $this->assertTrue($oResult instanceof \MailSo\Imap\NamespaceResult); + } + + public function testQuota() + { + $rConnect = \MailSo\Base\StreamWrappers\Test::CreateStream( + '* QUOTAROOT "INBOX" ""'.self::CRLF. + '* QUOTA "" (STORAGE 55163 10511217)'.self::CRLF. + 'TAG1 OK Success'.self::CRLF + ); + + $oImapClient = \MailSo\Imap\ImapClient::NewInstance()->TestSetValues($rConnect, array('QUOTA')); + + $aResult = $oImapClient->Quota(); + $this->assertTrue(is_array($aResult)); + $this->assertEquals(4, count($aResult)); + $this->assertEquals(55163, $aResult[0]); + $this->assertEquals(10511217, $aResult[1]); + } + + public function testFolderList() + { + $rConnect = \MailSo\Base\StreamWrappers\Test::CreateStream( +'* LIST (\Noselect) "/" 0'.self::CRLF. +'* LIST (\UnMarked) "/" 0/1'.self::CRLF. +'* LIST (\Noselect) "/" 1'.self::CRLF. +'* LIST (\Noselect) "/" 1/2'.self::CRLF. +'* LIST (\UnMarked) "/" 1/2/3'.self::CRLF. +'* LIST (\UnMarked \Inbox) "/" INBOX'.self::CRLF. +'* LIST (\UnMarked) "/" "INBOX/XXX XXX"'.self::CRLF. +'* LIST (\UnMarked) "/" &-BT,MAQBDoEM'.self::CRLF. +'* LIST (\UnMarked) "NIL" NILDelimiteFolder'.self::CRLF. +'* LIST (\UnMarked) "" EmptyDelimiteFolder'.self::CRLF. +'TAG1 OK Success'.self::CRLF + ); + + $oImapClient = \MailSo\Imap\ImapClient::NewInstance()->TestSetValues($rConnect); + + $aResult = $oImapClient->FolderList(); + $this->assertTrue(is_array($aResult) && 0 < count($aResult)); + $this->assertTrue($aResult[0] instanceof \MailSo\Imap\Folder); + + $this->assertEquals('0', $aResult[0]->FullNameRaw()); + $this->assertEquals('0', $aResult[0]->NameRaw()); + $this->assertEquals('0/1', $aResult[1]->FullNameRaw()); + $this->assertEquals('1', $aResult[1]->NameRaw()); + $this->assertEquals('1', $aResult[2]->FullNameRaw()); + $this->assertEquals('1/2', $aResult[3]->FullNameRaw()); + $this->assertEquals('1/2/3', $aResult[4]->FullNameRaw()); + $this->assertEquals('3', $aResult[4]->NameRaw()); + $this->assertEquals('INBOX', $aResult[5]->FullNameRaw()); + $this->assertEquals('INBOX/XXX XXX', $aResult[6]->FullNameRaw()); + $this->assertEquals('XXX XXX', $aResult[6]->NameRaw()); + $this->assertEquals('&-BT,MAQBDoEM', $aResult[7]->FullNameRaw()); + + $this->assertTrue($aResult[5] instanceof \MailSo\Imap\Folder); + $this->assertEquals('/', $aResult[5]->Delimiter()); + $this->assertEquals(2, count($aResult[5]->FlagsLowerCase())); + $this->assertTrue(in_array('\inbox', $aResult[5]->FlagsLowerCase())); + + $this->assertTrue($aResult[8] instanceof \MailSo\Imap\Folder); + $this->assertEquals('.', $aResult[8]->Delimiter()); + + $this->assertTrue($aResult[9] instanceof \MailSo\Imap\Folder); + $this->assertEquals('.', $aResult[8]->Delimiter()); + } +} diff --git a/tests/lib/MailSo/Mime/EmailCollectionTest.php b/tests/lib/MailSo/Mime/EmailCollectionTest.php new file mode 100644 index 000000000..382a16381 --- /dev/null +++ b/tests/lib/MailSo/Mime/EmailCollectionTest.php @@ -0,0 +1,18 @@ +assertEquals(1, $oMails->Count()); + } + + public function testNewInstance1() + { + $oMails = \MailSo\Mime\EmailCollection::NewInstance('User Name , User D\'Name , "User Name" '); + $this->assertEquals(3, $oMails->Count()); + } +} diff --git a/tests/lib/MailSo/Mime/EmailTest.php b/tests/lib/MailSo/Mime/EmailTest.php new file mode 100644 index 000000000..e4a777e16 --- /dev/null +++ b/tests/lib/MailSo/Mime/EmailTest.php @@ -0,0 +1,131 @@ +assertEquals('admin@example.com', $oEmail->GetEmail()); + $this->assertEquals('Administrator', $oEmail->GetDisplayName()); + $this->assertEquals('Remark', $oEmail->GetRemark()); + $this->assertEquals('admin', $oEmail->GetAccountName()); + $this->assertEquals('example.com', $oEmail->GetDomain()); + $this->assertEquals('"Administrator" (Remark)', $oEmail->ToString()); + $this->assertEquals(array('Administrator', 'admin@example.com', 'Remark'), $oEmail->ToArray()); + } + + public function testNewInstance1() + { + $oEmail = \MailSo\Mime\Email::NewInstance('admin@example.com'); + $this->assertEquals('admin@example.com', $oEmail->GetEmail()); + $this->assertEquals('', $oEmail->GetDisplayName()); + $this->assertEquals('', $oEmail->GetRemark()); + $this->assertEquals('admin@example.com', $oEmail->ToString()); + $this->assertEquals(array('', 'admin@example.com', ''), $oEmail->ToArray()); + } + + public function testNewInstance2() + { + $oEmail = \MailSo\Mime\Email::NewInstance('admin@example.com', 'Administrator'); + $this->assertEquals('admin@example.com', $oEmail->GetEmail()); + $this->assertEquals('Administrator', $oEmail->GetDisplayName()); + $this->assertEquals('', $oEmail->GetRemark()); + $this->assertEquals('"Administrator" ', $oEmail->ToString()); + $this->assertEquals(array('Administrator', 'admin@example.com', ''), $oEmail->ToArray()); + } + + public function testNewInstance3() + { + $oEmail = \MailSo\Mime\Email::NewInstance('admin@example.com', '', 'Remark'); + $this->assertEquals('admin@example.com', $oEmail->GetEmail()); + $this->assertEquals('', $oEmail->GetDisplayName()); + $this->assertEquals('Remark', $oEmail->GetRemark()); + $this->assertEquals(' (Remark)', $oEmail->ToString()); + $this->assertEquals(array('', 'admin@example.com', 'Remark'), $oEmail->ToArray()); + } + + /** + * @expectedException \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function testNewInstance4() + { + \MailSo\Mime\Email::NewInstance(''); + } + + public function testParse1() + { + $oEmail = \MailSo\Mime\Email::Parse('help@example.com'); + $this->assertEquals('help@example.com', $oEmail->GetEmail()); + + $oEmail = \MailSo\Mime\Email::Parse(''); + $this->assertEquals('help@example.com', $oEmail->GetEmail()); + } + + public function testParse2() + { + $oEmail = \MailSo\Mime\Email::Parse('"Тест" (Ремарка)'); + $this->assertEquals('"Тест" (Ремарка)', $oEmail->ToString()); + $this->assertEquals('"=?utf-8?B?0KLQtdGB0YI=?=" (=?utf-8?B?0KDQtdC80LDRgNC60LA=?=)', $oEmail->ToString(true)); + } + + /** + * @expectedException \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function testParse5() + { + \MailSo\Mime\Email::Parse(''); + } + + /** + * @expectedException \MailSo\Base\Exceptions\InvalidArgumentException + */ + public function testParse6() + { + \MailSo\Mime\Email::Parse('example.com'); + } + + public function testParsePuny1() + { + $oMail = \MailSo\Mime\Email::Parse('help@xn--d1acufc.xn--p1ai'); + $this->assertEquals('help@xn--d1acufc.xn--p1ai', $oMail->ToString()); + $this->assertEquals('help@домен.рф', $oMail->ToString(false, true)); + } + + public function testParsePuny2() + { + $oMail = \MailSo\Mime\Email::Parse('help@домен.рф'); + $this->assertEquals('help@xn--d1acufc.xn--p1ai', $oMail->ToString()); + $this->assertEquals('help@домен.рф', $oMail->ToString(false, true)); + } + + public static function providerForParse() + { + return array( + array('test ', + array('test', 'help@example.com', '')), + array('test', + array('test', 'help@example.com', '')), + array('test< help@example.com >', + array('test', 'help@example.com', '')), + array(' (Remark)', + array('', 'help@example.com', 'Remark')), + array('"New \" Admin" (Rem)', + array('New " Admin', 'help@example.com', 'Rem')), + array('"Тест" (Ремарка)', + array('Тест', 'help@example.com', 'Ремарка')), + array('Microsoft Outlook', + array('Microsoft Outlook', 'microsoftexchange329e71ec88ae4615bbc36ab6ce41109e@ppth.private', '')), + ); + } + + /** + * @dataProvider providerForParse + */ + public function testParseWithProvider($sValue, $aResult) + { + $oMail = \MailSo\Mime\Email::Parse($sValue); + $this->assertEquals($aResult, $oMail->ToArray()); + } +} diff --git a/vendors/phpunit.phar b/vendors/phpunit.phar new file mode 100644 index 000000000..ac15da41b --- /dev/null +++ b/vendors/phpunit.phar @@ -0,0 +1,72848 @@ +#!/usr/bin/env php + '/php-file-iterator/Iterator.php', + 'file_iterator_facade' => '/php-file-iterator/Iterator/Facade.php', + 'file_iterator_factory' => '/php-file-iterator/Iterator/Factory.php', + 'php_codecoverage' => '/php-code-coverage/CodeCoverage.php', + 'php_codecoverage_driver' => '/php-code-coverage/CodeCoverage/Driver.php', + 'php_codecoverage_driver_hhvm' => '/php-code-coverage/CodeCoverage/Driver/HHVM.php', + 'php_codecoverage_driver_xdebug' => '/php-code-coverage/CodeCoverage/Driver/Xdebug.php', + 'php_codecoverage_exception' => '/php-code-coverage/CodeCoverage/Exception.php', + 'php_codecoverage_exception_unintentionallycoveredcode' => '/php-code-coverage/CodeCoverage/Exception/UnintentionallyCoveredCode.php', + 'php_codecoverage_filter' => '/php-code-coverage/CodeCoverage/Filter.php', + 'php_codecoverage_report_clover' => '/php-code-coverage/CodeCoverage/Report/Clover.php', + 'php_codecoverage_report_crap4j' => '/php-code-coverage/CodeCoverage/Report/Crap4j.php', + 'php_codecoverage_report_factory' => '/php-code-coverage/CodeCoverage/Report/Factory.php', + 'php_codecoverage_report_html' => '/php-code-coverage/CodeCoverage/Report/HTML.php', + 'php_codecoverage_report_html_renderer' => '/php-code-coverage/CodeCoverage/Report/HTML/Renderer.php', + 'php_codecoverage_report_html_renderer_dashboard' => '/php-code-coverage/CodeCoverage/Report/HTML/Renderer/Dashboard.php', + 'php_codecoverage_report_html_renderer_directory' => '/php-code-coverage/CodeCoverage/Report/HTML/Renderer/Directory.php', + 'php_codecoverage_report_html_renderer_file' => '/php-code-coverage/CodeCoverage/Report/HTML/Renderer/File.php', + 'php_codecoverage_report_node' => '/php-code-coverage/CodeCoverage/Report/Node.php', + 'php_codecoverage_report_node_directory' => '/php-code-coverage/CodeCoverage/Report/Node/Directory.php', + 'php_codecoverage_report_node_file' => '/php-code-coverage/CodeCoverage/Report/Node/File.php', + 'php_codecoverage_report_node_iterator' => '/php-code-coverage/CodeCoverage/Report/Node/Iterator.php', + 'php_codecoverage_report_php' => '/php-code-coverage/CodeCoverage/Report/PHP.php', + 'php_codecoverage_report_text' => '/php-code-coverage/CodeCoverage/Report/Text.php', + 'php_codecoverage_report_xml' => '/php-code-coverage/CodeCoverage/Report/XML.php', + 'php_codecoverage_report_xml_directory' => '/php-code-coverage/CodeCoverage/Report/XML/Directory.php', + 'php_codecoverage_report_xml_file' => '/php-code-coverage/CodeCoverage/Report/XML/File.php', + 'php_codecoverage_report_xml_file_coverage' => '/php-code-coverage/CodeCoverage/Report/XML/File/Coverage.php', + 'php_codecoverage_report_xml_file_method' => '/php-code-coverage/CodeCoverage/Report/XML/File/Method.php', + 'php_codecoverage_report_xml_file_report' => '/php-code-coverage/CodeCoverage/Report/XML/File/Report.php', + 'php_codecoverage_report_xml_file_unit' => '/php-code-coverage/CodeCoverage/Report/XML/File/Unit.php', + 'php_codecoverage_report_xml_node' => '/php-code-coverage/CodeCoverage/Report/XML/Node.php', + 'php_codecoverage_report_xml_project' => '/php-code-coverage/CodeCoverage/Report/XML/Project.php', + 'php_codecoverage_report_xml_tests' => '/php-code-coverage/CodeCoverage/Report/XML/Tests.php', + 'php_codecoverage_report_xml_totals' => '/php-code-coverage/CodeCoverage/Report/XML/Totals.php', + 'php_codecoverage_util' => '/php-code-coverage/CodeCoverage/Util.php', + 'php_codecoverage_util_invalidargumenthelper' => '/php-code-coverage/CodeCoverage/Util/InvalidArgumentHelper.php', + 'php_invoker' => '/php-invoker/Invoker.php', + 'php_invoker_timeoutexception' => '/php-invoker/Invoker/TimeoutException.php', + 'php_timer' => '/php-timer/Timer.php', + 'php_token' => '/php-token-stream/Token.php', + 'php_token_abstract' => '/php-token-stream/Token.php', + 'php_token_ampersand' => '/php-token-stream/Token.php', + 'php_token_and_equal' => '/php-token-stream/Token.php', + 'php_token_array' => '/php-token-stream/Token.php', + 'php_token_array_cast' => '/php-token-stream/Token.php', + 'php_token_as' => '/php-token-stream/Token.php', + 'php_token_at' => '/php-token-stream/Token.php', + 'php_token_backtick' => '/php-token-stream/Token.php', + 'php_token_bad_character' => '/php-token-stream/Token.php', + 'php_token_bool_cast' => '/php-token-stream/Token.php', + 'php_token_boolean_and' => '/php-token-stream/Token.php', + 'php_token_boolean_or' => '/php-token-stream/Token.php', + 'php_token_break' => '/php-token-stream/Token.php', + 'php_token_callable' => '/php-token-stream/Token.php', + 'php_token_caret' => '/php-token-stream/Token.php', + 'php_token_case' => '/php-token-stream/Token.php', + 'php_token_catch' => '/php-token-stream/Token.php', + 'php_token_character' => '/php-token-stream/Token.php', + 'php_token_class' => '/php-token-stream/Token.php', + 'php_token_class_c' => '/php-token-stream/Token.php', + 'php_token_class_name_constant' => '/php-token-stream/Token.php', + 'php_token_clone' => '/php-token-stream/Token.php', + 'php_token_close_bracket' => '/php-token-stream/Token.php', + 'php_token_close_curly' => '/php-token-stream/Token.php', + 'php_token_close_square' => '/php-token-stream/Token.php', + 'php_token_close_tag' => '/php-token-stream/Token.php', + 'php_token_colon' => '/php-token-stream/Token.php', + 'php_token_comma' => '/php-token-stream/Token.php', + 'php_token_comment' => '/php-token-stream/Token.php', + 'php_token_concat_equal' => '/php-token-stream/Token.php', + 'php_token_const' => '/php-token-stream/Token.php', + 'php_token_constant_encapsed_string' => '/php-token-stream/Token.php', + 'php_token_continue' => '/php-token-stream/Token.php', + 'php_token_curly_open' => '/php-token-stream/Token.php', + 'php_token_dec' => '/php-token-stream/Token.php', + 'php_token_declare' => '/php-token-stream/Token.php', + 'php_token_default' => '/php-token-stream/Token.php', + 'php_token_dir' => '/php-token-stream/Token.php', + 'php_token_div' => '/php-token-stream/Token.php', + 'php_token_div_equal' => '/php-token-stream/Token.php', + 'php_token_dnumber' => '/php-token-stream/Token.php', + 'php_token_do' => '/php-token-stream/Token.php', + 'php_token_doc_comment' => '/php-token-stream/Token.php', + 'php_token_dollar' => '/php-token-stream/Token.php', + 'php_token_dollar_open_curly_braces' => '/php-token-stream/Token.php', + 'php_token_dot' => '/php-token-stream/Token.php', + 'php_token_double_arrow' => '/php-token-stream/Token.php', + 'php_token_double_cast' => '/php-token-stream/Token.php', + 'php_token_double_colon' => '/php-token-stream/Token.php', + 'php_token_double_quotes' => '/php-token-stream/Token.php', + 'php_token_echo' => '/php-token-stream/Token.php', + 'php_token_else' => '/php-token-stream/Token.php', + 'php_token_elseif' => '/php-token-stream/Token.php', + 'php_token_empty' => '/php-token-stream/Token.php', + 'php_token_encapsed_and_whitespace' => '/php-token-stream/Token.php', + 'php_token_end_heredoc' => '/php-token-stream/Token.php', + 'php_token_enddeclare' => '/php-token-stream/Token.php', + 'php_token_endfor' => '/php-token-stream/Token.php', + 'php_token_endforeach' => '/php-token-stream/Token.php', + 'php_token_endif' => '/php-token-stream/Token.php', + 'php_token_endswitch' => '/php-token-stream/Token.php', + 'php_token_endwhile' => '/php-token-stream/Token.php', + 'php_token_equal' => '/php-token-stream/Token.php', + 'php_token_eval' => '/php-token-stream/Token.php', + 'php_token_exclamation_mark' => '/php-token-stream/Token.php', + 'php_token_exit' => '/php-token-stream/Token.php', + 'php_token_extends' => '/php-token-stream/Token.php', + 'php_token_file' => '/php-token-stream/Token.php', + 'php_token_final' => '/php-token-stream/Token.php', + 'php_token_finally' => '/php-token-stream/Token.php', + 'php_token_for' => '/php-token-stream/Token.php', + 'php_token_foreach' => '/php-token-stream/Token.php', + 'php_token_func_c' => '/php-token-stream/Token.php', + 'php_token_function' => '/php-token-stream/Token.php', + 'php_token_global' => '/php-token-stream/Token.php', + 'php_token_goto' => '/php-token-stream/Token.php', + 'php_token_gt' => '/php-token-stream/Token.php', + 'php_token_halt_compiler' => '/php-token-stream/Token.php', + 'php_token_if' => '/php-token-stream/Token.php', + 'php_token_implements' => '/php-token-stream/Token.php', + 'php_token_inc' => '/php-token-stream/Token.php', + 'php_token_include' => '/php-token-stream/Token.php', + 'php_token_include_once' => '/php-token-stream/Token.php', + 'php_token_includes' => '/php-token-stream/Token.php', + 'php_token_inline_html' => '/php-token-stream/Token.php', + 'php_token_instanceof' => '/php-token-stream/Token.php', + 'php_token_insteadof' => '/php-token-stream/Token.php', + 'php_token_int_cast' => '/php-token-stream/Token.php', + 'php_token_interface' => '/php-token-stream/Token.php', + 'php_token_is_equal' => '/php-token-stream/Token.php', + 'php_token_is_greater_or_equal' => '/php-token-stream/Token.php', + 'php_token_is_identical' => '/php-token-stream/Token.php', + 'php_token_is_not_equal' => '/php-token-stream/Token.php', + 'php_token_is_not_identical' => '/php-token-stream/Token.php', + 'php_token_is_smaller_or_equal' => '/php-token-stream/Token.php', + 'php_token_isset' => '/php-token-stream/Token.php', + 'php_token_line' => '/php-token-stream/Token.php', + 'php_token_list' => '/php-token-stream/Token.php', + 'php_token_lnumber' => '/php-token-stream/Token.php', + 'php_token_logical_and' => '/php-token-stream/Token.php', + 'php_token_logical_or' => '/php-token-stream/Token.php', + 'php_token_logical_xor' => '/php-token-stream/Token.php', + 'php_token_lt' => '/php-token-stream/Token.php', + 'php_token_method_c' => '/php-token-stream/Token.php', + 'php_token_minus' => '/php-token-stream/Token.php', + 'php_token_minus_equal' => '/php-token-stream/Token.php', + 'php_token_mod_equal' => '/php-token-stream/Token.php', + 'php_token_mul_equal' => '/php-token-stream/Token.php', + 'php_token_mult' => '/php-token-stream/Token.php', + 'php_token_namespace' => '/php-token-stream/Token.php', + 'php_token_new' => '/php-token-stream/Token.php', + 'php_token_ns_c' => '/php-token-stream/Token.php', + 'php_token_ns_separator' => '/php-token-stream/Token.php', + 'php_token_num_string' => '/php-token-stream/Token.php', + 'php_token_object_cast' => '/php-token-stream/Token.php', + 'php_token_object_operator' => '/php-token-stream/Token.php', + 'php_token_open_bracket' => '/php-token-stream/Token.php', + 'php_token_open_curly' => '/php-token-stream/Token.php', + 'php_token_open_square' => '/php-token-stream/Token.php', + 'php_token_open_tag' => '/php-token-stream/Token.php', + 'php_token_open_tag_with_echo' => '/php-token-stream/Token.php', + 'php_token_or_equal' => '/php-token-stream/Token.php', + 'php_token_paamayim_nekudotayim' => '/php-token-stream/Token.php', + 'php_token_percent' => '/php-token-stream/Token.php', + 'php_token_pipe' => '/php-token-stream/Token.php', + 'php_token_plus' => '/php-token-stream/Token.php', + 'php_token_plus_equal' => '/php-token-stream/Token.php', + 'php_token_print' => '/php-token-stream/Token.php', + 'php_token_private' => '/php-token-stream/Token.php', + 'php_token_protected' => '/php-token-stream/Token.php', + 'php_token_public' => '/php-token-stream/Token.php', + 'php_token_question_mark' => '/php-token-stream/Token.php', + 'php_token_require' => '/php-token-stream/Token.php', + 'php_token_require_once' => '/php-token-stream/Token.php', + 'php_token_return' => '/php-token-stream/Token.php', + 'php_token_semicolon' => '/php-token-stream/Token.php', + 'php_token_sl' => '/php-token-stream/Token.php', + 'php_token_sl_equal' => '/php-token-stream/Token.php', + 'php_token_sr' => '/php-token-stream/Token.php', + 'php_token_sr_equal' => '/php-token-stream/Token.php', + 'php_token_start_heredoc' => '/php-token-stream/Token.php', + 'php_token_static' => '/php-token-stream/Token.php', + 'php_token_stream' => '/php-token-stream/Token/Stream.php', + 'php_token_stream_cachingfactory' => '/php-token-stream/Token/Stream/CachingFactory.php', + 'php_token_string' => '/php-token-stream/Token.php', + 'php_token_string_cast' => '/php-token-stream/Token.php', + 'php_token_string_varname' => '/php-token-stream/Token.php', + 'php_token_switch' => '/php-token-stream/Token.php', + 'php_token_throw' => '/php-token-stream/Token.php', + 'php_token_tilde' => '/php-token-stream/Token.php', + 'php_token_trait' => '/php-token-stream/Token.php', + 'php_token_trait_c' => '/php-token-stream/Token.php', + 'php_token_try' => '/php-token-stream/Token.php', + 'php_token_unset' => '/php-token-stream/Token.php', + 'php_token_unset_cast' => '/php-token-stream/Token.php', + 'php_token_use' => '/php-token-stream/Token.php', + 'php_token_var' => '/php-token-stream/Token.php', + 'php_token_variable' => '/php-token-stream/Token.php', + 'php_token_while' => '/php-token-stream/Token.php', + 'php_token_whitespace' => '/php-token-stream/Token.php', + 'php_token_xor_equal' => '/php-token-stream/Token.php', + 'php_token_yield' => '/php-token-stream/Token.php', + 'php_tokenwithscope' => '/php-token-stream/Token.php', + 'php_tokenwithscopeandvisibility' => '/php-token-stream/Token.php', + 'phpunit_exception' => '/phpunit/Exception.php', + 'phpunit_extensions_database_abstracttester' => '/dbunit/Extensions/Database/AbstractTester.php', + 'phpunit_extensions_database_constraint_datasetisequal' => '/dbunit/Extensions/Database/Constraint/DataSetIsEqual.php', + 'phpunit_extensions_database_constraint_tableisequal' => '/dbunit/Extensions/Database/Constraint/TableIsEqual.php', + 'phpunit_extensions_database_constraint_tablerowcount' => '/dbunit/Extensions/Database/Constraint/TableRowCount.php', + 'phpunit_extensions_database_dataset_abstractdataset' => '/dbunit/Extensions/Database/DataSet/AbstractDataSet.php', + 'phpunit_extensions_database_dataset_abstracttable' => '/dbunit/Extensions/Database/DataSet/AbstractTable.php', + 'phpunit_extensions_database_dataset_abstracttablemetadata' => '/dbunit/Extensions/Database/DataSet/AbstractTableMetaData.php', + 'phpunit_extensions_database_dataset_abstractxmldataset' => '/dbunit/Extensions/Database/DataSet/AbstractXmlDataSet.php', + 'phpunit_extensions_database_dataset_compositedataset' => '/dbunit/Extensions/Database/DataSet/CompositeDataSet.php', + 'phpunit_extensions_database_dataset_csvdataset' => '/dbunit/Extensions/Database/DataSet/CsvDataSet.php', + 'phpunit_extensions_database_dataset_datasetfilter' => '/dbunit/Extensions/Database/DataSet/DataSetFilter.php', + 'phpunit_extensions_database_dataset_defaultdataset' => '/dbunit/Extensions/Database/DataSet/DefaultDataSet.php', + 'phpunit_extensions_database_dataset_defaulttable' => '/dbunit/Extensions/Database/DataSet/DefaultTable.php', + 'phpunit_extensions_database_dataset_defaulttableiterator' => '/dbunit/Extensions/Database/DataSet/DefaultTableIterator.php', + 'phpunit_extensions_database_dataset_defaulttablemetadata' => '/dbunit/Extensions/Database/DataSet/DefaultTableMetaData.php', + 'phpunit_extensions_database_dataset_flatxmldataset' => '/dbunit/Extensions/Database/DataSet/FlatXmlDataSet.php', + 'phpunit_extensions_database_dataset_idataset' => '/dbunit/Extensions/Database/DataSet/IDataSet.php', + 'phpunit_extensions_database_dataset_ipersistable' => '/dbunit/Extensions/Database/DataSet/IPersistable.php', + 'phpunit_extensions_database_dataset_ispec' => '/dbunit/Extensions/Database/DataSet/ISpec.php', + 'phpunit_extensions_database_dataset_itable' => '/dbunit/Extensions/Database/DataSet/ITable.php', + 'phpunit_extensions_database_dataset_itableiterator' => '/dbunit/Extensions/Database/DataSet/ITableIterator.php', + 'phpunit_extensions_database_dataset_itablemetadata' => '/dbunit/Extensions/Database/DataSet/ITableMetaData.php', + 'phpunit_extensions_database_dataset_iyamlparser' => '/dbunit/Extensions/Database/DataSet/IYamlParser.php', + 'phpunit_extensions_database_dataset_mysqlxmldataset' => '/dbunit/Extensions/Database/DataSet/MysqlXmlDataSet.php', + 'phpunit_extensions_database_dataset_persistors_abstract' => '/dbunit/Extensions/Database/DataSet/Persistors/Abstract.php', + 'phpunit_extensions_database_dataset_persistors_factory' => '/dbunit/Extensions/Database/DataSet/Persistors/Factory.php', + 'phpunit_extensions_database_dataset_persistors_flatxml' => '/dbunit/Extensions/Database/DataSet/Persistors/FlatXml.php', + 'phpunit_extensions_database_dataset_persistors_mysqlxml' => '/dbunit/Extensions/Database/DataSet/Persistors/MysqlXml.php', + 'phpunit_extensions_database_dataset_persistors_xml' => '/dbunit/Extensions/Database/DataSet/Persistors/Xml.php', + 'phpunit_extensions_database_dataset_persistors_yaml' => '/dbunit/Extensions/Database/DataSet/Persistors/Yaml.php', + 'phpunit_extensions_database_dataset_querydataset' => '/dbunit/Extensions/Database/DataSet/QueryDataSet.php', + 'phpunit_extensions_database_dataset_querytable' => '/dbunit/Extensions/Database/DataSet/QueryTable.php', + 'phpunit_extensions_database_dataset_replacementdataset' => '/dbunit/Extensions/Database/DataSet/ReplacementDataSet.php', + 'phpunit_extensions_database_dataset_replacementtable' => '/dbunit/Extensions/Database/DataSet/ReplacementTable.php', + 'phpunit_extensions_database_dataset_replacementtableiterator' => '/dbunit/Extensions/Database/DataSet/ReplacementTableIterator.php', + 'phpunit_extensions_database_dataset_specs_csv' => '/dbunit/Extensions/Database/DataSet/Specs/Csv.php', + 'phpunit_extensions_database_dataset_specs_dbquery' => '/dbunit/Extensions/Database/DataSet/Specs/DbQuery.php', + 'phpunit_extensions_database_dataset_specs_dbtable' => '/dbunit/Extensions/Database/DataSet/Specs/DbTable.php', + 'phpunit_extensions_database_dataset_specs_factory' => '/dbunit/Extensions/Database/DataSet/Specs/Factory.php', + 'phpunit_extensions_database_dataset_specs_flatxml' => '/dbunit/Extensions/Database/DataSet/Specs/FlatXml.php', + 'phpunit_extensions_database_dataset_specs_ifactory' => '/dbunit/Extensions/Database/DataSet/Specs/IFactory.php', + 'phpunit_extensions_database_dataset_specs_xml' => '/dbunit/Extensions/Database/DataSet/Specs/Xml.php', + 'phpunit_extensions_database_dataset_specs_yaml' => '/dbunit/Extensions/Database/DataSet/Specs/Yaml.php', + 'phpunit_extensions_database_dataset_symfonyyamlparser' => '/dbunit/Extensions/Database/DataSet/SymfonyYamlParser.php', + 'phpunit_extensions_database_dataset_tablefilter' => '/dbunit/Extensions/Database/DataSet/TableFilter.php', + 'phpunit_extensions_database_dataset_tablemetadatafilter' => '/dbunit/Extensions/Database/DataSet/TableMetaDataFilter.php', + 'phpunit_extensions_database_dataset_xmldataset' => '/dbunit/Extensions/Database/DataSet/XmlDataSet.php', + 'phpunit_extensions_database_dataset_yamldataset' => '/dbunit/Extensions/Database/DataSet/YamlDataSet.php', + 'phpunit_extensions_database_db_dataset' => '/dbunit/Extensions/Database/DB/DataSet.php', + 'phpunit_extensions_database_db_defaultdatabaseconnection' => '/dbunit/Extensions/Database/DB/DefaultDatabaseConnection.php', + 'phpunit_extensions_database_db_filtereddataset' => '/dbunit/Extensions/Database/DB/FilteredDataSet.php', + 'phpunit_extensions_database_db_idatabaseconnection' => '/dbunit/Extensions/Database/DB/IDatabaseConnection.php', + 'phpunit_extensions_database_db_imetadata' => '/dbunit/Extensions/Database/DB/IMetaData.php', + 'phpunit_extensions_database_db_metadata' => '/dbunit/Extensions/Database/DB/MetaData.php', + 'phpunit_extensions_database_db_metadata_dblib' => '/dbunit/Extensions/Database/DB/MetaData/Dblib.php', + 'phpunit_extensions_database_db_metadata_firebird' => '/dbunit/Extensions/Database/DB/MetaData/Firebird.php', + 'phpunit_extensions_database_db_metadata_informationschema' => '/dbunit/Extensions/Database/DB/MetaData/InformationSchema.php', + 'phpunit_extensions_database_db_metadata_mysql' => '/dbunit/Extensions/Database/DB/MetaData/MySQL.php', + 'phpunit_extensions_database_db_metadata_oci' => '/dbunit/Extensions/Database/DB/MetaData/Oci.php', + 'phpunit_extensions_database_db_metadata_pgsql' => '/dbunit/Extensions/Database/DB/MetaData/PgSQL.php', + 'phpunit_extensions_database_db_metadata_sqlite' => '/dbunit/Extensions/Database/DB/MetaData/Sqlite.php', + 'phpunit_extensions_database_db_metadata_sqlsrv' => '/dbunit/Extensions/Database/DB/MetaData/SqlSrv.php', + 'phpunit_extensions_database_db_resultsettable' => '/dbunit/Extensions/Database/DB/ResultSetTable.php', + 'phpunit_extensions_database_db_table' => '/dbunit/Extensions/Database/DB/Table.php', + 'phpunit_extensions_database_db_tableiterator' => '/dbunit/Extensions/Database/DB/TableIterator.php', + 'phpunit_extensions_database_db_tablemetadata' => '/dbunit/Extensions/Database/DB/TableMetaData.php', + 'phpunit_extensions_database_defaulttester' => '/dbunit/Extensions/Database/DefaultTester.php', + 'phpunit_extensions_database_exception' => '/dbunit/Extensions/Database/Exception.php', + 'phpunit_extensions_database_idatabaselistconsumer' => '/dbunit/Extensions/Database/IDatabaseListConsumer.php', + 'phpunit_extensions_database_itester' => '/dbunit/Extensions/Database/ITester.php', + 'phpunit_extensions_database_operation_composite' => '/dbunit/Extensions/Database/Operation/Composite.php', + 'phpunit_extensions_database_operation_delete' => '/dbunit/Extensions/Database/Operation/Delete.php', + 'phpunit_extensions_database_operation_deleteall' => '/dbunit/Extensions/Database/Operation/DeleteAll.php', + 'phpunit_extensions_database_operation_exception' => '/dbunit/Extensions/Database/Operation/Exception.php', + 'phpunit_extensions_database_operation_factory' => '/dbunit/Extensions/Database/Operation/Factory.php', + 'phpunit_extensions_database_operation_idatabaseoperation' => '/dbunit/Extensions/Database/Operation/IDatabaseOperation.php', + 'phpunit_extensions_database_operation_insert' => '/dbunit/Extensions/Database/Operation/Insert.php', + 'phpunit_extensions_database_operation_null' => '/dbunit/Extensions/Database/Operation/Null.php', + 'phpunit_extensions_database_operation_replace' => '/dbunit/Extensions/Database/Operation/Replace.php', + 'phpunit_extensions_database_operation_rowbased' => '/dbunit/Extensions/Database/Operation/RowBased.php', + 'phpunit_extensions_database_operation_truncate' => '/dbunit/Extensions/Database/Operation/Truncate.php', + 'phpunit_extensions_database_operation_update' => '/dbunit/Extensions/Database/Operation/Update.php', + 'phpunit_extensions_database_testcase' => '/dbunit/Extensions/Database/TestCase.php', + 'phpunit_extensions_database_ui_command' => '/dbunit/Extensions/Database/UI/Command.php', + 'phpunit_extensions_database_ui_context' => '/dbunit/Extensions/Database/UI/Context.php', + 'phpunit_extensions_database_ui_imedium' => '/dbunit/Extensions/Database/UI/IMedium.php', + 'phpunit_extensions_database_ui_imediumprinter' => '/dbunit/Extensions/Database/UI/IMediumPrinter.php', + 'phpunit_extensions_database_ui_imode' => '/dbunit/Extensions/Database/UI/IMode.php', + 'phpunit_extensions_database_ui_imodefactory' => '/dbunit/Extensions/Database/UI/IModeFactory.php', + 'phpunit_extensions_database_ui_invalidmodeexception' => '/dbunit/Extensions/Database/UI/InvalidModeException.php', + 'phpunit_extensions_database_ui_mediums_text' => '/dbunit/Extensions/Database/UI/Mediums/Text.php', + 'phpunit_extensions_database_ui_modefactory' => '/dbunit/Extensions/Database/UI/ModeFactory.php', + 'phpunit_extensions_database_ui_modes_exportdataset' => '/dbunit/Extensions/Database/UI/Modes/ExportDataSet.php', + 'phpunit_extensions_database_ui_modes_exportdataset_arguments' => '/dbunit/Extensions/Database/UI/Modes/ExportDataSet/Arguments.php', + 'phpunit_extensions_grouptestsuite' => '/phpunit/Extensions/GroupTestSuite.php', + 'phpunit_extensions_phpttestcase' => '/phpunit/Extensions/PhptTestCase.php', + 'phpunit_extensions_phpttestsuite' => '/phpunit/Extensions/PhptTestSuite.php', + 'phpunit_extensions_repeatedtest' => '/phpunit/Extensions/RepeatedTest.php', + 'phpunit_extensions_selenium2testcase' => '/phpunit-selenium/Extensions/Selenium2TestCase.php', + 'phpunit_extensions_selenium2testcase_command' => '/phpunit-selenium/Extensions/Selenium2TestCase/Command.php', + 'phpunit_extensions_selenium2testcase_commandsholder' => '/phpunit-selenium/Extensions/Selenium2TestCase/CommandsHolder.php', + 'phpunit_extensions_selenium2testcase_driver' => '/phpunit-selenium/Extensions/Selenium2TestCase/Driver.php', + 'phpunit_extensions_selenium2testcase_element' => '/phpunit-selenium/Extensions/Selenium2TestCase/Element.php', + 'phpunit_extensions_selenium2testcase_element_accessor' => '/phpunit-selenium/Extensions/Selenium2TestCase/Element/Accessor.php', + 'phpunit_extensions_selenium2testcase_element_select' => '/phpunit-selenium/Extensions/Selenium2TestCase/Element/Select.php', + 'phpunit_extensions_selenium2testcase_elementcommand_attribute' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Attribute.php', + 'phpunit_extensions_selenium2testcase_elementcommand_click' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Click.php', + 'phpunit_extensions_selenium2testcase_elementcommand_css' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Css.php', + 'phpunit_extensions_selenium2testcase_elementcommand_equals' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Equals.php', + 'phpunit_extensions_selenium2testcase_elementcommand_genericaccessor' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/GenericAccessor.php', + 'phpunit_extensions_selenium2testcase_elementcommand_genericpost' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/GenericPost.php', + 'phpunit_extensions_selenium2testcase_elementcommand_value' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Value.php', + 'phpunit_extensions_selenium2testcase_elementcriteria' => '/phpunit-selenium/Extensions/Selenium2TestCase/ElementCriteria.php', + 'phpunit_extensions_selenium2testcase_exception' => '/phpunit-selenium/Extensions/Selenium2TestCase/Exception.php', + 'phpunit_extensions_selenium2testcase_keys' => '/phpunit-selenium/Extensions/Selenium2TestCase/Keys.php', + 'phpunit_extensions_selenium2testcase_keysholder' => '/phpunit-selenium/Extensions/Selenium2TestCase/KeysHolder.php', + 'phpunit_extensions_selenium2testcase_noseleniumexception' => '/phpunit-selenium/Extensions/Selenium2TestCase/NoSeleniumException.php', + 'phpunit_extensions_selenium2testcase_response' => '/phpunit-selenium/Extensions/Selenium2TestCase/Response.php', + 'phpunit_extensions_selenium2testcase_screenshotlistener' => '/phpunit-selenium/Extensions/Selenium2TestCase/ScreenshotListener.php', + 'phpunit_extensions_selenium2testcase_session' => '/phpunit-selenium/Extensions/Selenium2TestCase/Session.php', + 'phpunit_extensions_selenium2testcase_session_cookie' => '/phpunit-selenium/Extensions/Selenium2TestCase/Session/Cookie.php', + 'phpunit_extensions_selenium2testcase_session_cookie_builder' => '/phpunit-selenium/Extensions/Selenium2TestCase/Session/Cookie/Builder.php', + 'phpunit_extensions_selenium2testcase_session_storage' => '/phpunit-selenium/Extensions/Selenium2TestCase/Session/Storage.php', + 'phpunit_extensions_selenium2testcase_session_timeouts' => '/phpunit-selenium/Extensions/Selenium2TestCase/Session/Timeouts.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_acceptalert' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/AcceptAlert.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_alerttext' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/AlertText.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_click' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Click.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_dismissalert' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/DismissAlert.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_file' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/File.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_frame' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Frame.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_genericaccessor' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/GenericAccessor.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_genericattribute' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/GenericAttribute.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_keys' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Keys.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_location' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Location.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_log' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Log.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_moveto' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/MoveTo.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_orientation' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Orientation.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_url' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Url.php', + 'phpunit_extensions_selenium2testcase_sessioncommand_window' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Window.php', + 'phpunit_extensions_selenium2testcase_sessionstrategy' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionStrategy.php', + 'phpunit_extensions_selenium2testcase_sessionstrategy_isolated' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionStrategy/Isolated.php', + 'phpunit_extensions_selenium2testcase_sessionstrategy_shared' => '/phpunit-selenium/Extensions/Selenium2TestCase/SessionStrategy/Shared.php', + 'phpunit_extensions_selenium2testcase_statecommand' => '/phpunit-selenium/Extensions/Selenium2TestCase/StateCommand.php', + 'phpunit_extensions_selenium2testcase_url' => '/phpunit-selenium/Extensions/Selenium2TestCase/URL.php', + 'phpunit_extensions_selenium2testcase_waituntil' => '/phpunit-selenium/Extensions/Selenium2TestCase/WaitUntil.php', + 'phpunit_extensions_selenium2testcase_webdriverexception' => '/phpunit-selenium/Extensions/Selenium2TestCase/WebDriverException.php', + 'phpunit_extensions_selenium2testcase_window' => '/phpunit-selenium/Extensions/Selenium2TestCase/Window.php', + 'phpunit_extensions_seleniumbrowsersuite' => '/phpunit-selenium/Extensions/SeleniumBrowserSuite.php', + 'phpunit_extensions_seleniumcommon_exithandler' => '/phpunit-selenium/Extensions/SeleniumCommon/ExitHandler.php', + 'phpunit_extensions_seleniumcommon_remotecoverage' => '/phpunit-selenium/Extensions/SeleniumCommon/RemoteCoverage.php', + 'phpunit_extensions_seleniumtestcase' => '/phpunit-selenium/Extensions/SeleniumTestCase.php', + 'phpunit_extensions_seleniumtestcase_driver' => '/phpunit-selenium/Extensions/SeleniumTestCase/Driver.php', + 'phpunit_extensions_seleniumtestsuite' => '/phpunit-selenium/Extensions/SeleniumTestSuite.php', + 'phpunit_extensions_testdecorator' => '/phpunit/Extensions/TestDecorator.php', + 'phpunit_extensions_ticketlistener' => '/phpunit/Extensions/TicketListener.php', + 'phpunit_framework_assert' => '/phpunit/Framework/Assert.php', + 'phpunit_framework_assertionfailederror' => '/phpunit/Framework/AssertionFailedError.php', + 'phpunit_framework_basetestlistener' => '/phpunit/Framework/BaseTestListener.php', + 'phpunit_framework_codecoverageexception' => '/phpunit/Framework/CodeCoverageException.php', + 'phpunit_framework_constraint' => '/phpunit/Framework/Constraint.php', + 'phpunit_framework_constraint_and' => '/phpunit/Framework/Constraint/And.php', + 'phpunit_framework_constraint_arrayhaskey' => '/phpunit/Framework/Constraint/ArrayHasKey.php', + 'phpunit_framework_constraint_attribute' => '/phpunit/Framework/Constraint/Attribute.php', + 'phpunit_framework_constraint_callback' => '/phpunit/Framework/Constraint/Callback.php', + 'phpunit_framework_constraint_classhasattribute' => '/phpunit/Framework/Constraint/ClassHasAttribute.php', + 'phpunit_framework_constraint_classhasstaticattribute' => '/phpunit/Framework/Constraint/ClassHasStaticAttribute.php', + 'phpunit_framework_constraint_composite' => '/phpunit/Framework/Constraint/Composite.php', + 'phpunit_framework_constraint_count' => '/phpunit/Framework/Constraint/Count.php', + 'phpunit_framework_constraint_exception' => '/phpunit/Framework/Constraint/Exception.php', + 'phpunit_framework_constraint_exceptioncode' => '/phpunit/Framework/Constraint/ExceptionCode.php', + 'phpunit_framework_constraint_exceptionmessage' => '/phpunit/Framework/Constraint/ExceptionMessage.php', + 'phpunit_framework_constraint_fileexists' => '/phpunit/Framework/Constraint/FileExists.php', + 'phpunit_framework_constraint_greaterthan' => '/phpunit/Framework/Constraint/GreaterThan.php', + 'phpunit_framework_constraint_isanything' => '/phpunit/Framework/Constraint/IsAnything.php', + 'phpunit_framework_constraint_isempty' => '/phpunit/Framework/Constraint/IsEmpty.php', + 'phpunit_framework_constraint_isequal' => '/phpunit/Framework/Constraint/IsEqual.php', + 'phpunit_framework_constraint_isfalse' => '/phpunit/Framework/Constraint/IsFalse.php', + 'phpunit_framework_constraint_isidentical' => '/phpunit/Framework/Constraint/IsIdentical.php', + 'phpunit_framework_constraint_isinstanceof' => '/phpunit/Framework/Constraint/IsInstanceOf.php', + 'phpunit_framework_constraint_isjson' => '/phpunit/Framework/Constraint/IsJson.php', + 'phpunit_framework_constraint_isnull' => '/phpunit/Framework/Constraint/IsNull.php', + 'phpunit_framework_constraint_istrue' => '/phpunit/Framework/Constraint/IsTrue.php', + 'phpunit_framework_constraint_istype' => '/phpunit/Framework/Constraint/IsType.php', + 'phpunit_framework_constraint_jsonmatches' => '/phpunit/Framework/Constraint/JsonMatches.php', + 'phpunit_framework_constraint_jsonmatches_errormessageprovider' => '/phpunit/Framework/Constraint/JsonMatches/ErrorMessageProvider.php', + 'phpunit_framework_constraint_lessthan' => '/phpunit/Framework/Constraint/LessThan.php', + 'phpunit_framework_constraint_not' => '/phpunit/Framework/Constraint/Not.php', + 'phpunit_framework_constraint_objecthasattribute' => '/phpunit/Framework/Constraint/ObjectHasAttribute.php', + 'phpunit_framework_constraint_or' => '/phpunit/Framework/Constraint/Or.php', + 'phpunit_framework_constraint_pcrematch' => '/phpunit/Framework/Constraint/PCREMatch.php', + 'phpunit_framework_constraint_samesize' => '/phpunit/Framework/Constraint/SameSize.php', + 'phpunit_framework_constraint_stringcontains' => '/phpunit/Framework/Constraint/StringContains.php', + 'phpunit_framework_constraint_stringendswith' => '/phpunit/Framework/Constraint/StringEndsWith.php', + 'phpunit_framework_constraint_stringmatches' => '/phpunit/Framework/Constraint/StringMatches.php', + 'phpunit_framework_constraint_stringstartswith' => '/phpunit/Framework/Constraint/StringStartsWith.php', + 'phpunit_framework_constraint_traversablecontains' => '/phpunit/Framework/Constraint/TraversableContains.php', + 'phpunit_framework_constraint_traversablecontainsonly' => '/phpunit/Framework/Constraint/TraversableContainsOnly.php', + 'phpunit_framework_constraint_xor' => '/phpunit/Framework/Constraint/Xor.php', + 'phpunit_framework_error' => '/phpunit/Framework/Error.php', + 'phpunit_framework_error_deprecated' => '/phpunit/Framework/Error/Deprecated.php', + 'phpunit_framework_error_notice' => '/phpunit/Framework/Error/Notice.php', + 'phpunit_framework_error_warning' => '/phpunit/Framework/Error/Warning.php', + 'phpunit_framework_exception' => '/phpunit/Framework/Exception.php', + 'phpunit_framework_expectationfailedexception' => '/phpunit/Framework/ExpectationFailedException.php', + 'phpunit_framework_incompletetest' => '/phpunit/Framework/IncompleteTest.php', + 'phpunit_framework_incompletetesterror' => '/phpunit/Framework/IncompleteTestError.php', + 'phpunit_framework_invalidcoverstargeterror' => '/phpunit/Framework/InvalidCoversTargetError.php', + 'phpunit_framework_invalidcoverstargetexception' => '/phpunit/Framework/InvalidCoversTargetException.php', + 'phpunit_framework_mockobject_builder_identity' => '/phpunit-mock-objects/Framework/MockObject/Builder/Identity.php', + 'phpunit_framework_mockobject_builder_invocationmocker' => '/phpunit-mock-objects/Framework/MockObject/Builder/InvocationMocker.php', + 'phpunit_framework_mockobject_builder_match' => '/phpunit-mock-objects/Framework/MockObject/Builder/Match.php', + 'phpunit_framework_mockobject_builder_methodnamematch' => '/phpunit-mock-objects/Framework/MockObject/Builder/MethodNameMatch.php', + 'phpunit_framework_mockobject_builder_namespace' => '/phpunit-mock-objects/Framework/MockObject/Builder/Namespace.php', + 'phpunit_framework_mockobject_builder_parametersmatch' => '/phpunit-mock-objects/Framework/MockObject/Builder/ParametersMatch.php', + 'phpunit_framework_mockobject_builder_stub' => '/phpunit-mock-objects/Framework/MockObject/Builder/Stub.php', + 'phpunit_framework_mockobject_exception' => '/phpunit-mock-objects/Framework/MockObject/Exception.php', + 'phpunit_framework_mockobject_generator' => '/phpunit-mock-objects/Framework/MockObject/Generator.php', + 'phpunit_framework_mockobject_invocation' => '/phpunit-mock-objects/Framework/MockObject/Invocation.php', + 'phpunit_framework_mockobject_invocation_object' => '/phpunit-mock-objects/Framework/MockObject/Invocation/Object.php', + 'phpunit_framework_mockobject_invocation_static' => '/phpunit-mock-objects/Framework/MockObject/Invocation/Static.php', + 'phpunit_framework_mockobject_invocationmocker' => '/phpunit-mock-objects/Framework/MockObject/InvocationMocker.php', + 'phpunit_framework_mockobject_invokable' => '/phpunit-mock-objects/Framework/MockObject/Invokable.php', + 'phpunit_framework_mockobject_matcher' => '/phpunit-mock-objects/Framework/MockObject/Matcher.php', + 'phpunit_framework_mockobject_matcher_anyinvokedcount' => '/phpunit-mock-objects/Framework/MockObject/Matcher/AnyInvokedCount.php', + 'phpunit_framework_mockobject_matcher_anyparameters' => '/phpunit-mock-objects/Framework/MockObject/Matcher/AnyParameters.php', + 'phpunit_framework_mockobject_matcher_consecutiveparameters' => '/phpunit-mock-objects/Framework/MockObject/Matcher/ConsecutiveParameters.php', + 'phpunit_framework_mockobject_matcher_invocation' => '/phpunit-mock-objects/Framework/MockObject/Matcher/Invocation.php', + 'phpunit_framework_mockobject_matcher_invokedatindex' => '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtIndex.php', + 'phpunit_framework_mockobject_matcher_invokedatleastonce' => '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtLeastOnce.php', + 'phpunit_framework_mockobject_matcher_invokedcount' => '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedCount.php', + 'phpunit_framework_mockobject_matcher_invokedrecorder' => '/phpunit-mock-objects/Framework/MockObject/Matcher/InvokedRecorder.php', + 'phpunit_framework_mockobject_matcher_methodname' => '/phpunit-mock-objects/Framework/MockObject/Matcher/MethodName.php', + 'phpunit_framework_mockobject_matcher_parameters' => '/phpunit-mock-objects/Framework/MockObject/Matcher/Parameters.php', + 'phpunit_framework_mockobject_matcher_statelessinvocation' => '/phpunit-mock-objects/Framework/MockObject/Matcher/StatelessInvocation.php', + 'phpunit_framework_mockobject_mockbuilder' => '/phpunit-mock-objects/Framework/MockObject/MockBuilder.php', + 'phpunit_framework_mockobject_mockobject' => '/phpunit-mock-objects/Framework/MockObject/MockObject.php', + 'phpunit_framework_mockobject_stub' => '/phpunit-mock-objects/Framework/MockObject/Stub.php', + 'phpunit_framework_mockobject_stub_consecutivecalls' => '/phpunit-mock-objects/Framework/MockObject/Stub/ConsecutiveCalls.php', + 'phpunit_framework_mockobject_stub_exception' => '/phpunit-mock-objects/Framework/MockObject/Stub/Exception.php', + 'phpunit_framework_mockobject_stub_matchercollection' => '/phpunit-mock-objects/Framework/MockObject/Stub/MatcherCollection.php', + 'phpunit_framework_mockobject_stub_return' => '/phpunit-mock-objects/Framework/MockObject/Stub/Return.php', + 'phpunit_framework_mockobject_stub_returnargument' => '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnArgument.php', + 'phpunit_framework_mockobject_stub_returncallback' => '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnCallback.php', + 'phpunit_framework_mockobject_stub_returnself' => '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnSelf.php', + 'phpunit_framework_mockobject_stub_returnvaluemap' => '/phpunit-mock-objects/Framework/MockObject/Stub/ReturnValueMap.php', + 'phpunit_framework_mockobject_verifiable' => '/phpunit-mock-objects/Framework/MockObject/Verifiable.php', + 'phpunit_framework_outputerror' => '/phpunit/Framework/OutputError.php', + 'phpunit_framework_riskytest' => '/phpunit/Framework/RiskyTest.php', + 'phpunit_framework_riskytesterror' => '/phpunit/Framework/RiskyTestError.php', + 'phpunit_framework_selfdescribing' => '/phpunit/Framework/SelfDescribing.php', + 'phpunit_framework_skippedtest' => '/phpunit/Framework/SkippedTest.php', + 'phpunit_framework_skippedtesterror' => '/phpunit/Framework/SkippedTestError.php', + 'phpunit_framework_skippedtestsuiteerror' => '/phpunit/Framework/SkippedTestSuiteError.php', + 'phpunit_framework_syntheticerror' => '/phpunit/Framework/SyntheticError.php', + 'phpunit_framework_test' => '/phpunit/Framework/Test.php', + 'phpunit_framework_testcase' => '/phpunit/Framework/TestCase.php', + 'phpunit_framework_testfailure' => '/phpunit/Framework/TestFailure.php', + 'phpunit_framework_testlistener' => '/phpunit/Framework/TestListener.php', + 'phpunit_framework_testresult' => '/phpunit/Framework/TestResult.php', + 'phpunit_framework_testsuite' => '/phpunit/Framework/TestSuite.php', + 'phpunit_framework_testsuite_dataprovider' => '/phpunit/Framework/TestSuite/DataProvider.php', + 'phpunit_framework_unintentionallycoveredcodeerror' => '/phpunit/Framework/UnintentionallyCoveredCodeError.php', + 'phpunit_framework_warning' => '/phpunit/Framework/Warning.php', + 'phpunit_runner_basetestrunner' => '/phpunit/Runner/BaseTestRunner.php', + 'phpunit_runner_exception' => '/phpunit/Runner/Exception.php', + 'phpunit_runner_filter_factory' => '/phpunit/Runner/Filter/Factory.php', + 'phpunit_runner_filter_group_exclude' => '/phpunit/Runner/Filter/Group/Exclude.php', + 'phpunit_runner_filter_group_include' => '/phpunit/Runner/Filter/Group/Include.php', + 'phpunit_runner_filter_groupfilteriterator' => '/phpunit/Runner/Filter/Group.php', + 'phpunit_runner_filter_test' => '/phpunit/Runner/Filter/Test.php', + 'phpunit_runner_standardtestsuiteloader' => '/phpunit/Runner/StandardTestSuiteLoader.php', + 'phpunit_runner_testsuiteloader' => '/phpunit/Runner/TestSuiteLoader.php', + 'phpunit_runner_version' => '/phpunit/Runner/Version.php', + 'phpunit_textui_command' => '/phpunit/TextUI/Command.php', + 'phpunit_textui_resultprinter' => '/phpunit/TextUI/ResultPrinter.php', + 'phpunit_textui_testrunner' => '/phpunit/TextUI/TestRunner.php', + 'phpunit_util_blacklist' => '/phpunit/Util/Blacklist.php', + 'phpunit_util_configuration' => '/phpunit/Util/Configuration.php', + 'phpunit_util_deprecatedfeature' => '/phpunit/Util/DeprecatedFeature.php', + 'phpunit_util_deprecatedfeature_logger' => '/phpunit/Util/DeprecatedFeature/Logger.php', + 'phpunit_util_errorhandler' => '/phpunit/Util/ErrorHandler.php', + 'phpunit_util_fileloader' => '/phpunit/Util/Fileloader.php', + 'phpunit_util_filesystem' => '/phpunit/Util/Filesystem.php', + 'phpunit_util_filter' => '/phpunit/Util/Filter.php', + 'phpunit_util_getopt' => '/phpunit/Util/Getopt.php', + 'phpunit_util_globalstate' => '/phpunit/Util/GlobalState.php', + 'phpunit_util_invalidargumenthelper' => '/phpunit/Util/InvalidArgumentHelper.php', + 'phpunit_util_log_json' => '/phpunit/Util/Log/JSON.php', + 'phpunit_util_log_junit' => '/phpunit/Util/Log/JUnit.php', + 'phpunit_util_log_tap' => '/phpunit/Util/Log/TAP.php', + 'phpunit_util_php' => '/phpunit/Util/PHP.php', + 'phpunit_util_php_default' => '/phpunit/Util/PHP/Default.php', + 'phpunit_util_php_windows' => '/phpunit/Util/PHP/Windows.php', + 'phpunit_util_printer' => '/phpunit/Util/Printer.php', + 'phpunit_util_string' => '/phpunit/Util/String.php', + 'phpunit_util_test' => '/phpunit/Util/Test.php', + 'phpunit_util_testdox_nameprettifier' => '/phpunit/Util/TestDox/NamePrettifier.php', + 'phpunit_util_testdox_resultprinter' => '/phpunit/Util/TestDox/ResultPrinter.php', + 'phpunit_util_testdox_resultprinter_html' => '/phpunit/Util/TestDox/ResultPrinter/HTML.php', + 'phpunit_util_testdox_resultprinter_text' => '/phpunit/Util/TestDox/ResultPrinter/Text.php', + 'phpunit_util_testsuiteiterator' => '/phpunit/Util/TestSuiteIterator.php', + 'phpunit_util_type' => '/phpunit/Util/Type.php', + 'phpunit_util_xml' => '/phpunit/Util/XML.php', + 'sebastianbergmann\\comparator\\arraycomparator' => '/sebastian-comparator/ArrayComparator.php', + 'sebastianbergmann\\comparator\\comparator' => '/sebastian-comparator/Comparator.php', + 'sebastianbergmann\\comparator\\comparisonfailure' => '/sebastian-comparator/ComparisonFailure.php', + 'sebastianbergmann\\comparator\\datetimecomparator' => '/sebastian-comparator/DateTimeComparator.php', + 'sebastianbergmann\\comparator\\domnodecomparator' => '/sebastian-comparator/DOMNodeComparator.php', + 'sebastianbergmann\\comparator\\doublecomparator' => '/sebastian-comparator/DoubleComparator.php', + 'sebastianbergmann\\comparator\\exceptioncomparator' => '/sebastian-comparator/ExceptionComparator.php', + 'sebastianbergmann\\comparator\\factory' => '/sebastian-comparator/Factory.php', + 'sebastianbergmann\\comparator\\mockobjectcomparator' => '/sebastian-comparator/MockObjectComparator.php', + 'sebastianbergmann\\comparator\\numericcomparator' => '/sebastian-comparator/NumericComparator.php', + 'sebastianbergmann\\comparator\\objectcomparator' => '/sebastian-comparator/ObjectComparator.php', + 'sebastianbergmann\\comparator\\resourcecomparator' => '/sebastian-comparator/ResourceComparator.php', + 'sebastianbergmann\\comparator\\scalarcomparator' => '/sebastian-comparator/ScalarComparator.php', + 'sebastianbergmann\\comparator\\splobjectstoragecomparator' => '/sebastian-comparator/SplObjectStorageComparator.php', + 'sebastianbergmann\\comparator\\typecomparator' => '/sebastian-comparator/TypeComparator.php', + 'sebastianbergmann\\diff\\chunk' => '/sebastian-diff/Chunk.php', + 'sebastianbergmann\\diff\\diff' => '/sebastian-diff/Diff.php', + 'sebastianbergmann\\diff\\differ' => '/sebastian-diff/Differ.php', + 'sebastianbergmann\\diff\\line' => '/sebastian-diff/Line.php', + 'sebastianbergmann\\diff\\parser' => '/sebastian-diff/Parser.php', + 'sebastianbergmann\\environment\\runtime' => '/sebastian-environment/Runtime.php', + 'sebastianbergmann\\exporter\\context' => '/sebastian-exporter/Context.php', + 'sebastianbergmann\\exporter\\exception' => '/sebastian-exporter/Exception.php', + 'sebastianbergmann\\exporter\\exporter' => '/sebastian-exporter/Exporter.php', + 'sebastianbergmann\\version' => '/sebastian-version/Version.php', + 'symfony\\component\\yaml\\dumper' => '/symfony/yaml/Symfony/Component/Yaml/Dumper.php', + 'symfony\\component\\yaml\\escaper' => '/symfony/yaml/Symfony/Component/Yaml/Escaper.php', + 'symfony\\component\\yaml\\exception\\dumpexception' => '/symfony/yaml/Symfony/Component/Yaml/Exception/DumpException.php', + 'symfony\\component\\yaml\\exception\\exceptioninterface' => '/symfony/yaml/Symfony/Component/Yaml/Exception/ExceptionInterface.php', + 'symfony\\component\\yaml\\exception\\parseexception' => '/symfony/yaml/Symfony/Component/Yaml/Exception/ParseException.php', + 'symfony\\component\\yaml\\exception\\runtimeexception' => '/symfony/yaml/Symfony/Component/Yaml/Exception/RuntimeException.php', + 'symfony\\component\\yaml\\inline' => '/symfony/yaml/Symfony/Component/Yaml/Inline.php', + 'symfony\\component\\yaml\\parser' => '/symfony/yaml/Symfony/Component/Yaml/Parser.php', + 'symfony\\component\\yaml\\unescaper' => '/symfony/yaml/Symfony/Component/Yaml/Unescaper.php', + 'symfony\\component\\yaml\\yaml' => '/symfony/yaml/Symfony/Component/Yaml/Yaml.php', + 'text_template' => '/php-text-template/Template.php' + ); + } + + $class = strtolower($class); + + if (isset($classes[$class])) { + require __PHPUNIT_PHAR_ROOT__ . $classes[$class]; + } + } +); + +Phar::mapPhar('phpunit-4.1.1.phar'); + +if (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == '--manifest') { + print file_get_contents(__PHPUNIT_PHAR_ROOT__ . '/manifest.txt'); + exit; +} + +if ($GLOBALS['_SERVER']['SCRIPT_NAME'] != '-') { + PHPUnit_TextUI_Command::main(); +} + +__HALT_COMPILER(); ?> +phpunit-4.1.1.phar$phpunit/Framework/RiskyTestError.php) +7yS) +y0phpunit/Framework/ExpectationFailedException.php 7yS -.phpunit/Framework/InvalidCoversTargetError.phph +7ySh +޶$phpunit/Framework/SelfDescribing.php< +7yS< +l$phpunit/Framework/IncompleteTest.php +7yS +8!phpunit/Framework/TestFailure.php7ySŶ phpunit/Framework/Constraint.php7yS/Vpж2phpunit/Framework/InvalidCoversTargetException.php 7yS ں&phpunit/Framework/SkippedTestError.php/ +7yS/ +&ֳ)phpunit/Framework/IncompleteTestError.php9 +7yS9 +#Y"phpunit/Framework/TestListener.phps7ySsB&phpunit/Framework/Assert/Functions.phpp7ySp[ʶ phpunit/Framework/TestResult.phpt7ySt{z$phpunit/Framework/SyntheticError.phpA7ySA/3+phpunit/Framework/SkippedTestSuiteError.php: +7yS: + +phpunit/Framework/CodeCoverageException.php 7yS 5&^phpunit/Framework/Assert.php}7yS}Ll!phpunit/Framework/SkippedTest.php 7yS K9phpunit/Framework/Warning.php 7yS l,phpunit/Framework/TestSuite/DataProvider.php +7yS +T`phpunit/Framework/RiskyTest.php 7yS 7phpunit/Framework/TestCase.php7ySE_phpunit/Framework/TestSuite.phpi7ySia*phpunit/Framework/AssertionFailedError.php +7yS +~Vpphpunit/Framework/Test.php +7yS +S!phpunit/Framework/OutputError.php +7yS +MԺphpunit/Framework/Error.php8 7yS8 nV$phpunit/Framework/Constraint/Xor.php7yST}82phpunit/Framework/Constraint/ClassHasAttribute.phpd7ySdX,(phpunit/Framework/Constraint/IsEmpty.php7yS蝬&phpunit/Framework/Constraint/Count.phpL7ySLῂ1phpunit/Framework/Constraint/StringStartsWith.phpv 7ySv n>)phpunit/Framework/Constraint/SameSize.php 7yS ~(phpunit/Framework/Constraint/IsEqual.php7ySӷ#phpunit/Framework/Constraint/Or.php{7yS{oc/phpunit/Framework/Constraint/StringContains.php7yS67[*phpunit/Framework/Constraint/Composite.php7yS[Lm1phpunit/Framework/Constraint/ExceptionMessage.php{7yS{FXc'phpunit/Framework/Constraint/IsNull.php! 7yS! .phpunit/Framework/Constraint/StringMatches.php7ySښ'phpunit/Framework/Constraint/IsType.php7ySF-phpunit/Framework/Constraint/IsInstanceOf.php[7yS[ߘ'phpunit/Framework/Constraint/IsTrue.php! 7yS! 0߶(phpunit/Framework/Constraint/IsFalse.php% 7yS% .phpunit/Framework/Constraint/ExceptionCode.php7ySV)'phpunit/Framework/Constraint/IsJson.php7ySKh$phpunit/Framework/Constraint/Not.php7yS,phpunit/Framework/Constraint/ArrayHasKey.phpk7ySk|o*phpunit/Framework/Constraint/PCREMatch.phpj7ySj1#׶$phpunit/Framework/Constraint/And.phpC7ySCZ)phpunit/Framework/Constraint/Callback.phpK7ySKO8phpunit/Framework/Constraint/TraversableContainsOnly.php7ySϸ_*phpunit/Framework/Constraint/Attribute.php7ySJ)phpunit/Framework/Constraint/LessThan.phpn 7ySn `,phpunit/Framework/Constraint/JsonMatches.php<7yS<t,phpunit/Framework/Constraint/GreaterThan.phpw 7ySw p4phpunit/Framework/Constraint/TraversableContains.php7yS+phpunit/Framework/Constraint/FileExists.php[7yS[yF?+phpunit/Framework/Constraint/IsAnything.php7ySCW3phpunit/Framework/Constraint/ObjectHasAttribute.phpM 7ySM Aphpunit/Framework/Constraint/JsonMatches/ErrorMessageProvider.php7yS 8phpunit/Framework/Constraint/ClassHasStaticAttribute.php*7yS*F*8*phpunit/Framework/Constraint/Exception.php7ySw/phpunit/Framework/Constraint/StringEndsWith.php 7yS ȶ,phpunit/Framework/Constraint/IsIdentical.php7yS4&phpunit/Framework/Error/Deprecated.phpx +7ySx +9*"phpunit/Framework/Error/Notice.phpb +7ySb +ֶ#phpunit/Framework/Error/Warning.phpe +7ySe +0flphpunit/Framework/Exception.php 7yS |&phpunit/Framework/BaseTestListener.php@ 7yS@ 9pu5phpunit/Framework/UnintentionallyCoveredCodeError.php- +7yS- +q⮶phpunit/Util/Log/TAP.php7ySS`phpunit/Util/Log/JSON.php| 7yS| H7phpunit/Util/Log/JUnit.php#<7yS#<6`Wphpunit/Util/PHP.php!7yS!v**8phpunit/Util/XML.phpc}7ySc}۶phpunit/Util/Getopt.phpO7ySOsOL޶phpunit/Util/PHP/Windows.php 7yS 2u@phpunit/Util/PHP/Default.php7yS@%ƶ1phpunit/Util/PHP/Template/TestCaseMethod.tpl.dist?7yS?Yնphpunit/Util/Filesystem.php 7yS f%phpunit/Util/Type.php 7yS `"phpunit/Util/DeprecatedFeature.php 7yS Fpiphpunit/Util/Filter.phpE7ySEe/)phpunit/Util/DeprecatedFeature/Logger.phpC7ySCQphpunit/Util/String.php7yS@R"phpunit/Util/TestSuiteIterator.phph7yShQҘphpunit/Util/GlobalState.php^17yS^1˕phpunit/Util/Fileloader.php7ySphpunit/Util/Test.phpd|7ySd|/Cphpunit/Util/Printer.php]7yS]g\phpunit/Util/Configuration.php7ySk0&phpunit/Util/InvalidArgumentHelper.php 7yS ث1phpunit/Util/Blacklist.php7yS'phpunit/Util/TestDox/NamePrettifier.phpz7ySzuZE&phpunit/Util/TestDox/ResultPrinter.php(7yS(Yö+phpunit/Util/TestDox/ResultPrinter/HTML.php7yS7m{+phpunit/Util/TestDox/ResultPrinter/Text.php 7yS c"phpunit/Util/ErrorHandler.php,7yS,=nphpunit/TextUI/Command.php}7yS}j;2 phpunit/TextUI/ResultPrinter.phpO7ySOxڶphpunit/TextUI/TestRunner.php7ySEG!phpunit/Runner/BaseTestRunner.phpD7ySD q"phpunit/Runner/TestSuiteLoader.php 7yS @'phpunit/Runner/Filter/Group/Exclude.php +7yS +հ'phpunit/Runner/Filter/Group/Include.php +7yS +/!phpunit/Runner/Filter/Factory.php 7yS Uԃphpunit/Runner/Filter/Group.php 7yS t`phpunit/Runner/Filter/Test.php&7yS&*phpunit/Runner/StandardTestSuiteLoader.php7ySΝphpunit/Runner/Exception.php 7yS 3 phpunit/Runner/Version.php 7yS @3;#phpunit/Extensions/PhptTestCase.php7yS^f@#phpunit/Extensions/RepeatedTest.phpn7ySnM5Y$phpunit/Extensions/TestDecorator.phpi7ySiQݶ%phpunit/Extensions/GroupTestSuite.php7ySV%phpunit/Extensions/TicketListener.php 7yS $phpunit/Extensions/PhptTestSuite.phpZ 7ySZ [Mphpunit/Exception.php 7yS 7yS>*dBʶ1phpunit-selenium/Extensions/SeleniumTestSuite.php7yS8phpunit-selenium/Extensions/Selenium2TestCase/Driver.php/7yS/z}Lphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/AcceptAlert.php1 +7yS1 +BHQphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/GenericAttribute.php +7yS +BLphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Orientation.php 7yS @\WIJphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/AlertText.phpC 7ySC lXimEphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/File.php7yS0ߗPphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/GenericAccessor.phpT +7yST +XIphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Location.php 7yS Mphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/DismissAlert.php6 +7yS6 +vlFphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Click.php 7yS ^aDphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Url.php 7yS KEphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Keys.php$7yS$wͶFphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Frame.php 7yS z"Gphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/MoveTo.php7yS- +Dphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Log.php 7yS "=Gphpunit-selenium/Extensions/Selenium2TestCase/SessionCommand/Window.php +7yS +@phpunit-selenium/Extensions/Selenium2TestCase/CommandsHolder.php7ySZewDphpunit-selenium/Extensions/Selenium2TestCase/ScreenshotListener.php7yS|aHphpunit-selenium/Extensions/Selenium2TestCase/SessionStrategy/Shared.phpH7ySHVmJphpunit-selenium/Extensions/Selenium2TestCase/SessionStrategy/Isolated.php 7yS Ͷ9phpunit-selenium/Extensions/Selenium2TestCase/Session.php/7yS/ĶAphpunit-selenium/Extensions/Selenium2TestCase/ElementCriteria.phpN 7ySN ¶Ephpunit-selenium/Extensions/Selenium2TestCase/NoSeleniumException.php 7yS k9phpunit-selenium/Extensions/Selenium2TestCase/Command.phpL 7ySL cyƶBphpunit-selenium/Extensions/Selenium2TestCase/Element/Accessor.php7yS\w@phpunit-selenium/Extensions/Selenium2TestCase/Element/Select.php7ySL@"Pphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/GenericAccessor.phpi +7ySi +PeLphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/GenericPost.phpW +7ySW +LqFphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Click.php+ +7yS+ +ĻGphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Equals.php` 7yS` nնDphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Css.phpi 7ySi Jphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Attribute.phpt 7ySt  ˈFphpunit-selenium/Extensions/Selenium2TestCase/ElementCommand/Value.php +7yS +.$5phpunit-selenium/Extensions/Selenium2TestCase/URL.php7ySHF>phpunit-selenium/Extensions/Selenium2TestCase/StateCommand.phpw +7ySw +e3Z6phpunit-selenium/Extensions/Selenium2TestCase/Keys.phpI7ySIͶ9phpunit-selenium/Extensions/Selenium2TestCase/Element.php7yS:phpunit-selenium/Extensions/Selenium2TestCase/Response.php7ySTZ8phpunit-selenium/Extensions/Selenium2TestCase/Window.phpO 7ySO SAphpunit-selenium/Extensions/Selenium2TestCase/SessionStrategy.php 7yS ̳rDphpunit-selenium/Extensions/Selenium2TestCase/WebDriverException.phpf 7ySf K1<phpunit-selenium/Extensions/Selenium2TestCase/KeysHolder.php7yS|HAphpunit-selenium/Extensions/Selenium2TestCase/Session/Storage.php8 7yS8 Hphpunit-selenium/Extensions/Selenium2TestCase/Session/Cookie/Builder.php7ySӸqBphpunit-selenium/Extensions/Selenium2TestCase/Session/Timeouts.php]7yS]/X@phpunit-selenium/Extensions/Selenium2TestCase/Session/Cookie.php7yS$!;phpunit-selenium/Extensions/Selenium2TestCase/WaitUntil.php7ySsX;phpunit-selenium/Extensions/Selenium2TestCase/Exception.php 7yS H"[4phpunit-selenium/Extensions/SeleniumBrowserSuite.php7ySD0phpunit-selenium/Extensions/SeleniumTestCase.phpЖ7ySЖ`ec1phpunit-selenium/Extensions/Selenium2TestCase.phpkC7ySkCmf7phpunit-selenium/Extensions/SeleniumTestCase/Driver.php^7yS^7'q߶!sebastian-environment/Runtime.php7ySj8phpunit-mock-objects/Framework/MockObject/Invocation.php 7yS a?>phpunit-mock-objects/Framework/MockObject/InvocationMocker.php{7yS{h5phpunit-mock-objects/Framework/MockObject/Matcher.php(7yS(L7phpunit-mock-objects/Framework/MockObject/Generator.php$7yS$z>ox7phpunit-mock-objects/Framework/MockObject/Invokable.php 7yS ]Dphpunit-mock-objects/Framework/MockObject/Stub/MatcherCollection.php 7yS  =phpunit-mock-objects/Framework/MockObject/Stub/ReturnSelf.php 7yS Á9phpunit-mock-objects/Framework/MockObject/Stub/Return.php 7yS Aphpunit-mock-objects/Framework/MockObject/Stub/ReturnCallback.php 7yS '޶Aphpunit-mock-objects/Framework/MockObject/Stub/ReturnValueMap.php 7yS #j{5Cphpunit-mock-objects/Framework/MockObject/Stub/ConsecutiveCalls.php 7yS #|<phpunit-mock-objects/Framework/MockObject/Stub/Exception.phpX 7ySX ȝ>nAphpunit-mock-objects/Framework/MockObject/Stub/ReturnArgument.phpe 7ySe M#?phpunit-mock-objects/Framework/MockObject/Invocation/Object.php 7yS a|¶?phpunit-mock-objects/Framework/MockObject/Invocation/Static.phpt7ySt>gKphpunit-mock-objects/Framework/MockObject/Generator/proxied_method.tpl.dist7yS?aPphpunit-mock-objects/Framework/MockObject/Generator/mocked_class_method.tpl.dist7yS4޶Iphpunit-mock-objects/Framework/MockObject/Generator/mocked_clone.tpl.dist7ySaTJphpunit-mock-objects/Framework/MockObject/Generator/mocked_method.tpl.dist7ySbVIphpunit-mock-objects/Framework/MockObject/Generator/mocked_class.tpl.dist 7yS FZHphpunit-mock-objects/Framework/MockObject/Generator/wsdl_method.tpl.dist<7yS<iGphpunit-mock-objects/Framework/MockObject/Generator/wsdl_class.tpl.dist7ySw&SHphpunit-mock-objects/Framework/MockObject/Generator/trait_class.tpl.dist77yS7[$~Kphpunit-mock-objects/Framework/MockObject/Generator/unmocked_clone.tpl.dist7yS8W}ض9phpunit-mock-objects/Framework/MockObject/MockBuilder.php%7yS% +d8phpunit-mock-objects/Framework/MockObject/Verifiable.php 7yS &nFphpunit-mock-objects/Framework/MockObject/Builder/InvocationMocker.php$7yS$p +OEphpunit-mock-objects/Framework/MockObject/Builder/ParametersMatch.phpa7ySa#$ Ephpunit-mock-objects/Framework/MockObject/Builder/MethodNameMatch.php 7yS ?phpunit-mock-objects/Framework/MockObject/Builder/Namespace.php7ySca>phpunit-mock-objects/Framework/MockObject/Builder/Identity.php 7yS Nts:phpunit-mock-objects/Framework/MockObject/Builder/Stub.php 7yS t ;phpunit-mock-objects/Framework/MockObject/Builder/Match.php 7yS ڂ8phpunit-mock-objects/Framework/MockObject/MockObject.php>7yS>AEphpunit-mock-objects/Framework/MockObject/Matcher/AnyInvokedCount.phpA 7ySA tM8@phpunit-mock-objects/Framework/MockObject/Matcher/Invocation.phpe7ySe̸Iphpunit-mock-objects/Framework/MockObject/Matcher/StatelessInvocation.php7yS7gEphpunit-mock-objects/Framework/MockObject/Matcher/InvokedRecorder.php7yS; =PDphpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtIndex.phpu7ySua @phpunit-mock-objects/Framework/MockObject/Matcher/MethodName.phpB7ySB`5hHphpunit-mock-objects/Framework/MockObject/Matcher/InvokedAtLeastOnce.php/ 7yS/ mrَ@phpunit-mock-objects/Framework/MockObject/Matcher/Parameters.php7ySe?Bphpunit-mock-objects/Framework/MockObject/Matcher/InvokedCount.php7yS92Cphpunit-mock-objects/Framework/MockObject/Matcher/AnyParameters.php 7yS eKphpunit-mock-objects/Framework/MockObject/Matcher/ConsecutiveParameters.php7yStY2phpunit-mock-objects/Framework/MockObject/Stub.php 7yS Y7phpunit-mock-objects/Framework/MockObject/Exception.php 7yS ͚php-file-iterator/Iterator.phpc7ySc~ԃ&php-file-iterator/Iterator/Factory.phph7yShڶ%php-file-iterator/Iterator/Facade.php7ySlca.pem +7yS +ssebastian-version/Version.php 7yS Y +sebastian-comparator/DateTimeComparator.phpZ7ySZ@Cp)sebastian-comparator/ScalarComparator.php7yS_붶(sebastian-comparator/ArrayComparator.phpB7ySBj#sebastian-comparator/Comparator.php7yS6*sebastian-comparator/NumericComparator.phpA7ySA۶*sebastian-comparator/ComparisonFailure.php7yS "Ҷ)sebastian-comparator/DoubleComparator.php7ySO)sebastian-comparator/ObjectComparator.php7ySt sebastian-comparator/Factory.php77yS7E,sebastian-comparator/ExceptionComparator.php 7yS 3sebastian-comparator/SplObjectStorageComparator.php7yS϶'sebastian-comparator/TypeComparator.php 7yS -sebastian-comparator/MockObjectComparator.php 7yS *)+*sebastian-comparator/DOMNodeComparator.php7yS*+sebastian-comparator/ResourceComparator.phpV7ySV sebastian-diff/Parser.php7ySH.wsebastian-diff/Line.php 7yS pBsebastian-diff/Chunk.php 7yS %sebastian-diff/Differ.php!7yS!ohrŶsebastian-diff/Diff.php 7yS ̶,dbunit/Extensions/Database/DefaultTester.php 7yS :&dbunit/Extensions/Database/ITester.php7ySo;dbunit/Extensions/Database/DB/DefaultDatabaseConnection.php 7yS ʉ10dbunit/Extensions/Database/DB/ResultSetTable.php 7yS [5dbunit/Extensions/Database/DB/IDatabaseConnection.php7ySD+dbunit/Extensions/Database/DB/IMetaData.php67yS6vi'dbunit/Extensions/Database/DB/Table.php 7yS s5<dbunit/Extensions/Database/DB/MetaData/InformationSchema.phpt7yStö0dbunit/Extensions/Database/DB/MetaData/MySQL.php7yS01dbunit/Extensions/Database/DB/MetaData/Sqlite.php>7yS>=^ف.dbunit/Extensions/Database/DB/MetaData/Oci.phpV7ySV+ E0dbunit/Extensions/Database/DB/MetaData/PgSQL.php7ySgĶ3dbunit/Extensions/Database/DB/MetaData/Firebird.php7ySBp0dbunit/Extensions/Database/DB/MetaData/Dblib.php 7yS {ڧ1dbunit/Extensions/Database/DB/MetaData/SqlSrv.php7yS0 )dbunit/Extensions/Database/DB/DataSet.php7yS`Wk/dbunit/Extensions/Database/DB/TableIterator.php7ySl*dbunit/Extensions/Database/DB/MetaData.phpL 7ySL !!1dbunit/Extensions/Database/DB/FilteredDataSet.phpM 7ySM /dbunit/Extensions/Database/DB/TableMetaData.php 7yS K1dbunit/Extensions/Database/DataSet/CsvDataSet.php7yS/0(6dbunit/Extensions/Database/DataSet/Persistors/Yaml.php7ySn:dbunit/Extensions/Database/DataSet/Persistors/MysqlXml.php7ySf]-9dbunit/Extensions/Database/DataSet/Persistors/FlatXml.phpj7ySj_9dbunit/Extensions/Database/DataSet/Persistors/Factory.php7yS[̶:dbunit/Extensions/Database/DataSet/Persistors/Abstract.php7yS75dbunit/Extensions/Database/DataSet/Persistors/Xml.php7ySw:3dbunit/Extensions/Database/DataSet/DefaultTable.php7yS2F5dbunit/Extensions/Database/DataSet/ITableIterator.php + 7yS + "h-dbunit/Extensions/Database/DataSet/ITable.php 7yS 9<dbunit/Extensions/Database/DataSet/AbstractTableMetaData.php7yS7dbunit/Extensions/Database/DataSet/ReplacementTable.php37yS3`藶,dbunit/Extensions/Database/DataSet/ISpec.php +7yS +fC6dbunit/Extensions/Database/DataSet/AbstractDataSet.php7yS[9;dbunit/Extensions/Database/DataSet/DefaultTableMetaData.php 7yS 1dbunit/Extensions/Database/DataSet/XmlDataSet.php7ySLNȶ2dbunit/Extensions/Database/DataSet/IYamlParser.php 7yS Cp7dbunit/Extensions/Database/DataSet/CompositeDataSet.php7ySN=2dbunit/Extensions/Database/DataSet/TableFilter.php7yS*E3dbunit/Extensions/Database/DataSet/IPersistable.php +7yS +?dbunit/Extensions/Database/DataSet/ReplacementTableIterator.php7ySB! 5dbunit/Extensions/Database/DataSet/DefaultDataSet.php 7yS kr0dbunit/Extensions/Database/DataSet/Specs/Csv.phpa7ySa=Kj1dbunit/Extensions/Database/DataSet/Specs/Yaml.php 7yS SD\4dbunit/Extensions/Database/DataSet/Specs/FlatXml.php 7yS .4dbunit/Extensions/Database/DataSet/Specs/Factory.php 7yS >34dbunit/Extensions/Database/DataSet/Specs/DbQuery.php7yS5v0dbunit/Extensions/Database/DataSet/Specs/Xml.php 7yS )5T5dbunit/Extensions/Database/DataSet/Specs/IFactory.phpQ +7ySQ +f4dbunit/Extensions/Database/DataSet/Specs/DbTable.php7ySJ3dbunit/Extensions/Database/DataSet/QueryDataSet.phpo7ySo1Г8dbunit/Extensions/Database/DataSet/SymfonyYamlParser.php +7yS +n| 2dbunit/Extensions/Database/DataSet/YamlDataSet.php7ySL5dbunit/Extensions/Database/DataSet/FlatXmlDataSet.phpV7ySVN@Զ:dbunit/Extensions/Database/DataSet/TableMetaDataFilter.php*7yS* +۶/dbunit/Extensions/Database/DataSet/IDataSet.php 7yS -oB4dbunit/Extensions/Database/DataSet/DataSetFilter.php7yS_ƴ6dbunit/Extensions/Database/DataSet/MysqlXmlDataSet.php/7yS/8o1dbunit/Extensions/Database/DataSet/QueryTable.php7yS!9dbunit/Extensions/Database/DataSet/AbstractXmlDataSet.phpt7ySt3!5dbunit/Extensions/Database/DataSet/ITableMetaData.php8 7yS8 qjY9dbunit/Extensions/Database/DataSet/ReplacementDataSet.php`7yS`ք4dbunit/Extensions/Database/DataSet/AbstractTable.phpW!7ySW!|;dbunit/Extensions/Database/DataSet/DefaultTableIterator.php7ySr-dbunit/Extensions/Database/AbstractTester.php$7yS$Q-dbunit/Extensions/Database/UI/ModeFactory.php)7yS)X.dbunit/Extensions/Database/UI/Mediums/Text.php7yS2Zv)dbunit/Extensions/Database/UI/Command.phpR 7ySR !B?dbunit/Extensions/Database/UI/Modes/ExportDataSet/Arguments.php7yS'WҶ)dbunit/Extensions/Database/UI/IMedium.phpY 7ySY 1.dbunit/Extensions/Database/UI/IModeFactory.php +7yS +F$6dbunit/Extensions/Database/UI/InvalidModeException.php 7yS 0dbunit/Extensions/Database/UI/IMediumPrinter.php +7yS +)dbunit/Extensions/Database/UI/Context.php 7yS c$4dbunit/Extensions/Database/IDatabaseListConsumer.phpA +7ySA +SӶ'dbunit/Extensions/Database/TestCase.php(%7yS(%s/dbunit/Extensions/Database/Operation/Delete.php7yS2_Ͷ0dbunit/Extensions/Database/Operation/Replace.phpf7ySf8w@2dbunit/Extensions/Database/Operation/Composite.php7yS9$ ;dbunit/Extensions/Database/Operation/IDatabaseOperation.php 7yS f0dbunit/Extensions/Database/Operation/Factory.php7ySt¶1dbunit/Extensions/Database/Operation/Truncate.php 7yS p/dbunit/Extensions/Database/Operation/Insert.php7yS-dbunit/Extensions/Database/Operation/Null.php +7yS +I9/dbunit/Extensions/Database/Operation/Update.php7yS2dbunit/Extensions/Database/Operation/Exception.php7yS2dbunit/Extensions/Database/Operation/DeleteAll.php 7yS l+1dbunit/Extensions/Database/Operation/RowBased.php*7yS*+*Ҷ6dbunit/Extensions/Database/Constraint/TableIsEqual.phpd7ySdNjǶ7dbunit/Extensions/Database/Constraint/TableRowCount.phpc 7ySc +/8dbunit/Extensions/Database/Constraint/DataSetIsEqual.phpr7ySrT((dbunit/Extensions/Database/Exception.php +7yS +x +!php-invoker/Invoker.php&7yS&-顶(php-invoker/Invoker/TimeoutException.php 7yS nphp-timer/Timer.php67yS6#X60php-token-stream/Token/Stream/CachingFactory.php 7yS Ӓն!php-token-stream/Token/Stream.phpuD7ySuDrSͶphp-token-stream/Token.php\7yS\C2}php-text-template/Template.php7yS;$. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of a risky test. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Framework_RiskyTestError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_RiskyTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Exception for expectations which failed their check. + * + * The exception contains the error message and optionally a + * SebastianBergmann\Comparator\ComparisonFailure which is used to + * generate diff output of the failed expectations. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_ExpectationFailedException extends PHPUnit_Framework_AssertionFailedError +{ + /** + * @var SebastianBergmann\Comparator\ComparisonFailure + */ + protected $comparisonFailure; + + public function __construct($message, SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure = null, Exception $previous = null) + { + $this->comparisonFailure = $comparisonFailure; + + parent::__construct($message, 0, $previous); + } + + /** + * @return SebastianBergmann\Comparator\ComparisonFailure + */ + public function getComparisonFailure() + { + return $this->comparisonFailure; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of a test that is skipped because of an invalid @covers annotation. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Framework_InvalidCoversTargetError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_SkippedTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Interface for classes that can return a description of itself. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 3.0.0 + */ +interface PHPUnit_Framework_SelfDescribing +{ + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString(); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A marker interface for marking any exception/error as result of an unit + * test as incomplete implementation or currently not implemented. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 2.0.0 + */ +interface PHPUnit_Framework_IncompleteTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A TestFailure collects a failed test together with the caught exception. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Framework_TestFailure +{ + /** + * @var PHPUnit_Framework_Test + */ + protected $failedTest; + + /** + * @var Exception + */ + protected $thrownException; + + /** + * Constructs a TestFailure with the given test and exception. + * + * @param PHPUnit_Framework_Test $failedTest + * @param Exception $thrownException + */ + public function __construct(PHPUnit_Framework_Test $failedTest, Exception $thrownException) + { + $this->failedTest = $failedTest; + $this->thrownException = $thrownException; + } + + /** + * Returns a short description of the failure. + * + * @return string + */ + public function toString() + { + return sprintf( + '%s: %s', + + $this->failedTest->toString(), + $this->thrownException->getMessage() + ); + } + + /** + * Returns a description for the thrown exception. + * + * @return string + * @since Method available since Release 3.4.0 + */ + public function getExceptionAsString() + { + return self::exceptionToString($this->thrownException); + } + + /** + * Returns a description for an exception. + * + * @param Exception $e + * @return string + * @since Method available since Release 3.2.0 + */ + public static function exceptionToString(Exception $e) + { + if ($e instanceof PHPUnit_Framework_SelfDescribing) { + $buffer = $e->toString(); + + if ($e instanceof PHPUnit_Framework_ExpectationFailedException && $e->getComparisonFailure()) { + $buffer = $buffer . $e->getComparisonFailure()->getDiff(); + } + + if (!empty($buffer)) { + $buffer = trim($buffer) . "\n"; + } + } elseif ($e instanceof PHPUnit_Framework_Error) { + $buffer = $e->getMessage() . "\n"; + } else { + $buffer = get_class($e) . ': ' . $e->getMessage() . "\n"; + } + + return $buffer; + } + + /** + * Gets the failed test. + * + * @return PHPUnit_Framework_Test + */ + public function failedTest() + { + return $this->failedTest; + } + + /** + * Gets the thrown exception. + * + * @return Exception + */ + public function thrownException() + { + return $this->thrownException; + } + + /** + * Returns the exception's message. + * + * @return string + */ + public function exceptionMessage() + { + return $this->thrownException()->getMessage(); + } + + /** + * Returns true if the thrown exception + * is of type AssertionFailedError. + * + * @return boolean + */ + public function isFailure() + { + return ($this->thrownException() instanceof PHPUnit_Framework_AssertionFailedError); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +use SebastianBergmann\Exporter\Exporter; + +/** + * Abstract base class for constraints. which are placed upon any value. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 3.0.0 + */ +abstract class PHPUnit_Framework_Constraint implements Countable, PHPUnit_Framework_SelfDescribing +{ + protected $exporter; + + public function __construct() + { + $this->exporter = new Exporter; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = false; + + if ($this->matches($other)) { + $success = true; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return false; + } + + /** + * Counts the number of constraint elements. + * + * @return integer + * @since Method available since Release 3.4.0 + */ + public function count() + { + return 1; + } + + /** + * Throws an exception for the given compared value and test description + * + * @param mixed $other Evaluated value or object. + * @param string $description Additional information about the test + * @param SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure + * @throws PHPUnit_Framework_ExpectationFailedException + */ + protected function fail($other, $description, SebastianBergmann\Comparator\ComparisonFailure $comparisonFailure = null) + { + $failureDescription = sprintf( + 'Failed asserting that %s.', + $this->failureDescription($other) + ); + + $additionalFailureDescription = $this->additionalFailureDescription($other); + + if ($additionalFailureDescription) { + $failureDescription .= "\n" . $additionalFailureDescription; + } + + if (!empty($description)) { + $failureDescription = $description . "\n" . $failureDescription; + } + + throw new PHPUnit_Framework_ExpectationFailedException( + $failureDescription, + $comparisonFailure + ); + } + + /** + * Return additional failure description where needed + * + * The function can be overridden to provide additional failure + * information like a diff + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function additionalFailureDescription($other) + { + return ''; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * To provide additional failure information additionalFailureDescription + * can be used. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return $this->exporter->export($other) . ' ' . $this->toString(); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Framework_InvalidCoversTargetException extends PHPUnit_Framework_CodeCoverageException +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of a skipped test. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_SkippedTestError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_SkippedTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of an incomplete test. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Framework_IncompleteTestError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_IncompleteTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A Listener for test progress. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 2.0.0 + */ +interface PHPUnit_Framework_TestListener +{ + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time); + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time); + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time); + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time); + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time); + + /** + * A test suite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite); + + /** + * A test suite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite); + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test); + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.0 + */ + +/** + * Returns a matcher that matches when the method it is evaluated for + * is executed zero or more times. + * + * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount + * @since Method available since Release 3.0.0 + */ +function any() +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::any', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsAnything matcher object. + * + * @return PHPUnit_Framework_Constraint_IsAnything + * @since Method available since Release 3.0.0 + */ +function anything() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::anything', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_ArrayHasKey matcher object. + * + * @param mixed $key + * @return PHPUnit_Framework_Constraint_ArrayHasKey + * @since Method available since Release 3.0.0 + */ +function arrayHasKey($key) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::arrayHasKey', + func_get_args() + ); +} + +/** + * Asserts that an array has a specified key. + * + * @param mixed $key + * @param array|ArrayAccess $array + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertArrayHasKey($key, $array, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertArrayHasKey', + func_get_args() + ); +} + +/** + * Asserts that an array does not have a specified key. + * + * @param mixed $key + * @param array|ArrayAccess $array + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertArrayNotHasKey($key, $array, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertArrayNotHasKey', + func_get_args() + ); +} + +/** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object contains a needle. + * + * @param mixed $needle + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 3.0.0 + */ +function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeContains', + func_get_args() + ); +} + +/** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object contains only values of a given type. + * + * @param string $type + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ +function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeContainsOnly', + func_get_args() + ); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable + * that is stored in an attribute. + * + * @param integer $expectedCount + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.6.0 + */ +function assertAttributeCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeCount', + func_get_args() + ); +} + +/** + * Asserts that a static attribute of a class or an attribute of an object + * is empty. + * + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertAttributeEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeEmpty', + func_get_args() + ); +} + +/** + * Asserts that a variable is equal to an attribute of an object. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + */ +function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeEquals', + func_get_args() + ); +} + +/** + * Asserts that an attribute is greater than another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeGreaterThan', + func_get_args() + ); +} + +/** + * Asserts that an attribute is greater than or equal to another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeGreaterThanOrEqual', + func_get_args() + ); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeInstanceOf', + func_get_args() + ); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeInternalType', + func_get_args() + ); +} + +/** + * Asserts that an attribute is smaller than another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeLessThan', + func_get_args() + ); +} + +/** + * Asserts that an attribute is smaller than or equal to another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeLessThanOrEqual', + func_get_args() + ); +} + +/** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object does not contain a needle. + * + * @param mixed $needle + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 3.0.0 + */ +function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotContains', + func_get_args() + ); +} + +/** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object does not contain only values of a given + * type. + * + * @param string $type + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ +function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotContainsOnly', + func_get_args() + ); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable + * that is stored in an attribute. + * + * @param integer $expectedCount + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.6.0 + */ +function assertAttributeNotCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotCount', + func_get_args() + ); +} + +/** + * Asserts that a static attribute of a class or an attribute of an object + * is not empty. + * + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertAttributeNotEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotEmpty', + func_get_args() + ); +} + +/** + * Asserts that a variable is not equal to an attribute of an object. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + */ +function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotEquals', + func_get_args() + ); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotInstanceOf', + func_get_args() + ); +} + +/** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotInternalType', + func_get_args() + ); +} + +/** + * Asserts that a variable and an attribute of an object do not have the + * same type and value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param object $actualClassOrObject + * @param string $message + */ +function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeNotSame', + func_get_args() + ); +} + +/** + * Asserts that a variable and an attribute of an object have the same type + * and value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param object $actualClassOrObject + * @param string $message + */ +function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertAttributeSame', + func_get_args() + ); +} + +/** + * Asserts that a class has a specified attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertClassHasAttribute($attributeName, $className, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertClassHasAttribute', + func_get_args() + ); +} + +/** + * Asserts that a class has a specified static attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertClassHasStaticAttribute($attributeName, $className, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertClassHasStaticAttribute', + func_get_args() + ); +} + +/** + * Asserts that a class does not have a specified attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertClassNotHasAttribute($attributeName, $className, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertClassNotHasAttribute', + func_get_args() + ); +} + +/** + * Asserts that a class does not have a specified static attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertClassNotHasStaticAttribute($attributeName, $className, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertClassNotHasStaticAttribute', + func_get_args() + ); +} + +/** + * Asserts that a haystack contains a needle. + * + * @param mixed $needle + * @param mixed $haystack + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 2.1.0 + */ +function assertContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertContains', + func_get_args() + ); +} + +/** + * Asserts that a haystack contains only values of a given type. + * + * @param string $type + * @param mixed $haystack + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ +function assertContainsOnly($type, $haystack, $isNativeType = null, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertContainsOnly', + func_get_args() + ); +} + +/** + * Asserts that a haystack contains only instances of a given classname + * + * @param string $classname + * @param array|Traversable $haystack + * @param string $message + */ +function assertContainsOnlyInstancesOf($classname, $haystack, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertContainsOnlyInstancesOf', + func_get_args() + ); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param integer $expectedCount + * @param mixed $haystack + * @param string $message + */ +function assertCount($expectedCount, $haystack, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertCount', + func_get_args() + ); +} + +/** + * Asserts that a variable is empty. + * + * @param mixed $actual + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ +function assertEmpty($actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertEmpty', + func_get_args() + ); +} + +/** + * Asserts that a hierarchy of DOMElements matches. + * + * @param DOMElement $expectedElement + * @param DOMElement $actualElement + * @param boolean $checkAttributes + * @param string $message + * @author Mattis Stordalen Flister + * @since Method available since Release 3.3.0 + */ +function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = false, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertEqualXMLStructure', + func_get_args() + ); +} + +/** + * Asserts that two variables are equal. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + */ +function assertEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertEquals', + func_get_args() + ); +} + +/** + * Asserts that a condition is not true. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ +function assertNotTrue($condition, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotTrue', + func_get_args() + ); +} + +/** + * Asserts that a condition is false. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ +function assertFalse($condition, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertFalse', + func_get_args() + ); +} + +/** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @param string $expected + * @param string $actual + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.2.14 + */ +function assertFileEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertFileEquals', + func_get_args() + ); +} + +/** + * Asserts that a file exists. + * + * @param string $filename + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertFileExists($filename, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertFileExists', + func_get_args() + ); +} + +/** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @param string $expected + * @param string $actual + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.2.14 + */ +function assertFileNotEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertFileNotEquals', + func_get_args() + ); +} + +/** + * Asserts that a file does not exist. + * + * @param string $filename + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertFileNotExists($filename, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertFileNotExists', + func_get_args() + ); +} + +/** + * Asserts that a value is greater than another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertGreaterThan($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertGreaterThan', + func_get_args() + ); +} + +/** + * Asserts that a value is greater than or equal to another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertGreaterThanOrEqual($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertGreaterThanOrEqual', + func_get_args() + ); +} + +/** + * Asserts that a variable is of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertInstanceOf($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertInstanceOf', + func_get_args() + ); +} + +/** + * Asserts that a variable is of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertInternalType($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertInternalType', + func_get_args() + ); +} + +/** + * Asserts that a string is a valid JSON string. + * + * @param string $filename + * @param string $message + * @since Method available since Release 3.7.20 + */ +function assertJson($expectedJson, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJson', + func_get_args() + ); +} + +/** + * Asserts that two JSON files are equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + */ +function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJsonFileEqualsJsonFile', + func_get_args() + ); +} + +/** + * Asserts that two JSON files are not equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + */ +function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJsonFileNotEqualsJsonFile', + func_get_args() + ); +} + +/** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @param string $expectedFile + * @param string $actualJson + * @param string $message + */ +function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJsonStringEqualsJsonFile', + func_get_args() + ); +} + +/** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @param string $expectedJson + * @param string $actualJson + * @param string $message + */ +function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJsonStringEqualsJsonString', + func_get_args() + ); +} + +/** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @param string $expectedFile + * @param string $actualJson + * @param string $message + */ +function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonFile', + func_get_args() + ); +} + +/** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @param string $expectedJson + * @param string $actualJson + * @param string $message + */ +function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertJsonStringNotEqualsJsonString', + func_get_args() + ); +} + +/** + * Asserts that a value is smaller than another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertLessThan($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertLessThan', + func_get_args() + ); +} + +/** + * Asserts that a value is smaller than or equal to another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertLessThanOrEqual($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertLessThanOrEqual', + func_get_args() + ); +} + +/** + * Asserts that a haystack does not contain a needle. + * + * @param mixed $needle + * @param mixed $haystack + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 2.1.0 + */ +function assertNotContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotContains', + func_get_args() + ); +} + +/** + * Asserts that a haystack does not contain only values of a given type. + * + * @param string $type + * @param mixed $haystack + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ +function assertNotContainsOnly($type, $haystack, $isNativeType = null, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotContainsOnly', + func_get_args() + ); +} + +/** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param integer $expectedCount + * @param mixed $haystack + * @param string $message + */ +function assertNotCount($expectedCount, $haystack, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotCount', + func_get_args() + ); +} + +/** + * Asserts that a variable is not empty. + * + * @param mixed $actual + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ +function assertNotEmpty($actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotEmpty', + func_get_args() + ); +} + +/** + * Asserts that two variables are not equal. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 2.3.0 + */ +function assertNotEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotEquals', + func_get_args() + ); +} + +/** + * Asserts that a variable is not of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertNotInstanceOf($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotInstanceOf', + func_get_args() + ); +} + +/** + * Asserts that a variable is not of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertNotInternalType($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotInternalType', + func_get_args() + ); +} + +/** + * Asserts that a condition is not false. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ +function assertNotFalse($condition, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotFalse', + func_get_args() + ); +} + +/** + * Asserts that a variable is not null. + * + * @param mixed $actual + * @param string $message + */ +function assertNotNull($actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotNull', + func_get_args() + ); +} + +/** + * Asserts that a string does not match a given regular expression. + * + * @param string $pattern + * @param string $string + * @param string $message + * @since Method available since Release 2.1.0 + */ +function assertNotRegExp($pattern, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotRegExp', + func_get_args() + ); +} + +/** + * Asserts that two variables do not have the same type and value. + * Used on objects, it asserts that two variables do not reference + * the same object. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + */ +function assertNotSame($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotSame', + func_get_args() + ); +} + +/** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @param array|Countable|Traversable $expected + * @param array|Countable|Traversable $actual + * @param string $message + */ +function assertNotSameSize($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotSameSize', + func_get_args() + ); +} + +/** + * This assertion is the exact opposite of assertTag(). + * + * Rather than asserting that $matcher results in a match, it asserts that + * $matcher does not match. + * + * @param array $matcher + * @param string $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ +function assertNotTag($matcher, $actual, $message = '', $isHtml = true) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNotTag', + func_get_args() + ); +} + +/** + * Asserts that a variable is null. + * + * @param mixed $actual + * @param string $message + */ +function assertNull($actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertNull', + func_get_args() + ); +} + +/** + * Asserts that an object has a specified attribute. + * + * @param string $attributeName + * @param object $object + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertObjectHasAttribute($attributeName, $object, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertObjectHasAttribute', + func_get_args() + ); +} + +/** + * Asserts that an object does not have a specified attribute. + * + * @param string $attributeName + * @param object $object + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertObjectNotHasAttribute($attributeName, $object, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertObjectNotHasAttribute', + func_get_args() + ); +} + +/** + * Asserts that a string matches a given regular expression. + * + * @param string $pattern + * @param string $string + * @param string $message + */ +function assertRegExp($pattern, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertRegExp', + func_get_args() + ); +} + +/** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + */ +function assertSame($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertSame', + func_get_args() + ); +} + +/** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @param array|Countable|Traversable $expected + * @param array|Countable|Traversable $actual + * @param string $message + */ +function assertSameSize($expected, $actual, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertSameSize', + func_get_args() + ); +} + +/** + * Assert the presence, absence, or count of elements in a document matching + * the CSS $selector, regardless of the contents of those elements. + * + * The first argument, $selector, is the CSS selector used to match + * the elements in the $actual document. + * + * The second argument, $count, can be either boolean or numeric. + * When boolean, it asserts for presence of elements matching the selector + * (true) or absence of elements (false). + * When numeric, it asserts the count of elements. + * + * assertSelectCount("#binder", true, $xml); // any? + * assertSelectCount(".binder", 3, $xml); // exactly 3? + * + * @param array $selector + * @param integer $count + * @param mixed $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ +function assertSelectCount($selector, $count, $actual, $message = '', $isHtml = true) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertSelectCount', + func_get_args() + ); +} + +/** + * assertSelectEquals("#binder .name", "Chuck", true, $xml); // any? + * assertSelectEquals("#binder .name", "Chuck", false, $xml); // none? + * + * @param array $selector + * @param string $content + * @param integer $count + * @param mixed $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ +function assertSelectEquals($selector, $content, $count, $actual, $message = '', $isHtml = true) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertSelectEquals', + func_get_args() + ); +} + +/** + * assertSelectRegExp("#binder .name", "/Mike|Derek/", true, $xml); // any? + * assertSelectRegExp("#binder .name", "/Mike|Derek/", 3, $xml);// 3? + * + * @param array $selector + * @param string $pattern + * @param integer $count + * @param mixed $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ +function assertSelectRegExp($selector, $pattern, $count, $actual, $message = '', $isHtml = true) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertSelectRegExp', + func_get_args() + ); +} + +/** + * Asserts that a string ends not with a given prefix. + * + * @param string $suffix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ +function assertStringEndsNotWith($suffix, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringEndsNotWith', + func_get_args() + ); +} + +/** + * Asserts that a string ends with a given prefix. + * + * @param string $suffix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ +function assertStringEndsWith($suffix, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringEndsWith', + func_get_args() + ); +} + +/** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @param string $expectedFile + * @param string $actualString + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.3.0 + */ +function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringEqualsFile', + func_get_args() + ); +} + +/** + * Asserts that a string matches a given format string. + * + * @param string $format + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertStringMatchesFormat($format, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringMatchesFormat', + func_get_args() + ); +} + +/** + * Asserts that a string matches a given format file. + * + * @param string $formatFile + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertStringMatchesFormatFile($formatFile, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringMatchesFormatFile', + func_get_args() + ); +} + +/** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @param string $expectedFile + * @param string $actualString + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.3.0 + */ +function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringNotEqualsFile', + func_get_args() + ); +} + +/** + * Asserts that a string does not match a given format string. + * + * @param string $format + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertStringNotMatchesFormat($format, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringNotMatchesFormat', + func_get_args() + ); +} + +/** + * Asserts that a string does not match a given format string. + * + * @param string $formatFile + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ +function assertStringNotMatchesFormatFile($formatFile, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringNotMatchesFormatFile', + func_get_args() + ); +} + +/** + * Asserts that a string starts not with a given prefix. + * + * @param string $prefix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ +function assertStringStartsNotWith($prefix, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringStartsNotWith', + func_get_args() + ); +} + +/** + * Asserts that a string starts with a given prefix. + * + * @param string $prefix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ +function assertStringStartsWith($prefix, $string, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertStringStartsWith', + func_get_args() + ); +} + +/** + * Evaluate an HTML or XML string and assert its structure and/or contents. + * + * The first argument ($matcher) is an associative array that specifies the + * match criteria for the assertion: + * + * - `id` : the node with the given id attribute must match the + * corresponding value. + * - `tag` : the node type must match the corresponding value. + * - `attributes` : a hash. The node's attributes must match the + * corresponding values in the hash. + * - `content` : The text content must match the given value. + * - `parent` : a hash. The node's parent must match the + * corresponding hash. + * - `child`: a hash. At least one of the node's immediate children + * must meet the criteria described by the hash. + * - `ancestor` : a hash. At least one of the node's ancestors must + * meet the criteria described by the hash. + * - `descendant` : a hash. At least one of the node's descendants must + * meet the criteria described by the hash. + * - `children` : a hash, for counting children of a node. + * Accepts the keys: + *- `count`: a number which must equal the number of children + * that match + *- `less_than`: the number of matching children must be greater + * than this number + *- `greater_than` : the number of matching children must be less than + * this number + *- `only` : another hash consisting of the keys to use to match + * on the children, and only matching children will be + * counted + * + * + * // Matcher that asserts that there is an element with an id="my_id". + * $matcher = array('id' => 'my_id'); + * + * // Matcher that asserts that there is a "span" tag. + * $matcher = array('tag' => 'span'); + * + * // Matcher that asserts that there is a "span" tag with the content + * // "Hello World". + * $matcher = array('tag' => 'span', 'content' => 'Hello World'); + * + * // Matcher that asserts that there is a "span" tag with content matching + * // the regular expression pattern. + * $matcher = array('tag' => 'span', 'content' => 'regexp:/Try P(HP|ython)/'); + * + * // Matcher that asserts that there is a "span" with an "list" class + * // attribute. + * $matcher = array( + * 'tag'=> 'span', + * 'attributes' => array('class' => 'list') + * ); + * + * // Matcher that asserts that there is a "span" inside of a "div". + * $matcher = array( + * 'tag'=> 'span', + * 'parent' => array('tag' => 'div') + * ); + * + * // Matcher that asserts that there is a "span" somewhere inside a + * // "table". + * $matcher = array( + * 'tag' => 'span', + * 'ancestor' => array('tag' => 'table') + * ); + * + * // Matcher that asserts that there is a "span" with at least one "em" + * // child. + * $matcher = array( + * 'tag' => 'span', + * 'child' => array('tag' => 'em') + * ); + * + * // Matcher that asserts that there is a "span" containing a (possibly + * // nested) "strong" tag. + * $matcher = array( + * 'tag'=> 'span', + * 'descendant' => array('tag' => 'strong') + * ); + * + * // Matcher that asserts that there is a "span" containing 5-10 "em" tags + * // as immediate children. + * $matcher = array( + * 'tag' => 'span', + * 'children' => array( + * 'less_than'=> 11, + * 'greater_than' => 4, + * 'only' => array('tag' => 'em') + * ) + * ); + * + * // Matcher that asserts that there is a "div", with an "ul" ancestor and + * // a "li" parent (with class="enum"), and containing a "span" descendant + * // that contains an element with id="my_test" and the text "Hello World". + * $matcher = array( + * 'tag'=> 'div', + * 'ancestor' => array('tag' => 'ul'), + * 'parent' => array( + * 'tag'=> 'li', + * 'attributes' => array('class' => 'enum') + * ), + * 'descendant' => array( + * 'tag' => 'span', + * 'child' => array( + * 'id' => 'my_test', + * 'content' => 'Hello World' + * ) + * ) + * ); + * + * // Use assertTag() to apply a $matcher to a piece of $html. + * $this->assertTag($matcher, $html); + * + * // Use assertTag() to apply a $matcher to a piece of $xml. + * $this->assertTag($matcher, $xml, '', false); + * + * + * The second argument ($actual) is a string containing either HTML or + * XML text to be tested. + * + * The third argument ($message) is an optional message that will be + * used if the assertion fails. + * + * The fourth argument ($html) is an optional flag specifying whether + * to load the $actual string into a DOMDocument using the HTML or + * XML load strategy. It is true by default, which assumes the HTML + * load strategy. In many cases, this will be acceptable for XML as well. + * + * @param array $matcher + * @param string $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ +function assertTag($matcher, $actual, $message = '', $isHtml = true) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertTag', + func_get_args() + ); +} + +/** + * Evaluates a PHPUnit_Framework_Constraint matcher object. + * + * @param mixed$value + * @param PHPUnit_Framework_Constraint $constraint + * @param string $message + * @since Method available since Release 3.0.0 + */ +function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertThat', + func_get_args() + ); +} + +/** + * Asserts that a condition is true. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ +function assertTrue($condition, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertTrue', + func_get_args() + ); +} + +/** + * Asserts that two XML files are equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertXmlFileEqualsXmlFile', + func_get_args() + ); +} + +/** + * Asserts that two XML files are not equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertXmlFileNotEqualsXmlFile', + func_get_args() + ); +} + +/** + * Asserts that two XML documents are equal. + * + * @param string $expectedFile + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.3.0 + */ +function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertXmlStringEqualsXmlFile', + func_get_args() + ); +} + +/** + * Asserts that two XML documents are equal. + * + * @param string $expectedXml + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertXmlStringEqualsXmlString', + func_get_args() + ); +} + +/** + * Asserts that two XML documents are not equal. + * + * @param string $expectedFile + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.3.0 + */ +function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlFile', + func_get_args() + ); +} + +/** + * Asserts that two XML documents are not equal. + * + * @param string $expectedXml + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.1.0 + */ +function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '') +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::assertXmlStringNotEqualsXmlString', + func_get_args() + ); +} + +/** + * Returns a matcher that matches when the method it is evaluated for + * is invoked at the given $index. + * + * @param integer $index + * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex + * @since Method available since Release 3.0.0 + */ +function at($index) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::at', + func_get_args() + ); +} + +/** + * Returns a matcher that matches when the method it is evaluated for + * is executed at least once. + * + * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce + * @since Method available since Release 3.0.0 + */ +function atLeastOnce() +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::atLeastOnce', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Attribute matcher object. + * + * @param PHPUnit_Framework_Constraint $constraint + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_Attribute + * @since Method available since Release 3.1.0 + */ +function attribute(PHPUnit_Framework_Constraint $constraint, $attributeName) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::attribute', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object + * that is wrapped in a PHPUnit_Framework_Constraint_Attribute matcher + * object. + * + * @param string $attributeName + * @param mixed $value + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @return PHPUnit_Framework_Constraint_Attribute + * @since Method available since Release 3.1.0 + */ +function attributeEqualTo($attributeName, $value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::attributeEqualTo', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Callback matcher object. + * + * @param callable $callback + * @return PHPUnit_Framework_Constraint_Callback + */ +function callback($callback) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::callback', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_ClassHasAttribute matcher object. + * + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_ClassHasAttribute + * @since Method available since Release 3.1.0 + */ +function classHasAttribute($attributeName) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::classHasAttribute', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_ClassHasStaticAttribute matcher + * object. + * + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_ClassHasStaticAttribute + * @since Method available since Release 3.1.0 + */ +function classHasStaticAttribute($attributeName) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::classHasStaticAttribute', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_TraversableContains matcher + * object. + * + * @param mixed $value + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @return PHPUnit_Framework_Constraint_TraversableContains + * @since Method available since Release 3.0.0 + */ +function contains($value, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::contains', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher + * object. + * + * @param string $type + * @return PHPUnit_Framework_Constraint_TraversableContainsOnly + * @since Method available since Release 3.1.4 + */ +function containsOnly($type) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::containsOnly', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher + * object. + * + * @param string $classname + * @return PHPUnit_Framework_Constraint_TraversableContainsOnly + */ +function containsOnlyInstancesOf($classname) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::containsOnlyInstancesOf', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object. + * + * @param mixed $value + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @return PHPUnit_Framework_Constraint_IsEqual + * @since Method available since Release 3.0.0 + */ +function equalTo($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::equalTo', + func_get_args() + ); +} + +/** + * Returns a matcher that matches when the method it is evaluated for + * is executed exactly $count times. + * + * @param integer $count + * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount + * @since Method available since Release 3.0.0 + */ +function exactly($count) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::exactly', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_FileExists matcher object. + * + * @return PHPUnit_Framework_Constraint_FileExists + * @since Method available since Release 3.0.0 + */ +function fileExists() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::fileExists', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_GreaterThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_GreaterThan + * @since Method available since Release 3.0.0 + */ +function greaterThan($value) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::greaterThan', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps + * a PHPUnit_Framework_Constraint_IsEqual and a + * PHPUnit_Framework_Constraint_GreaterThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_Or + * @since Method available since Release 3.1.0 + */ +function greaterThanOrEqual($value) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::greaterThanOrEqual', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsIdentical matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_IsIdentical + * @since Method available since Release 3.0.0 + */ +function identicalTo($value) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::identicalTo', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsEmpty matcher object. + * + * @return PHPUnit_Framework_Constraint_IsEmpty + * @since Method available since Release 3.5.0 + */ +function isEmpty() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isEmpty', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsFalse matcher object. + * + * @return PHPUnit_Framework_Constraint_IsFalse + * @since Method available since Release 3.3.0 + */ +function isFalse() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isFalse', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsInstanceOf matcher object. + * + * @param string $className + * @return PHPUnit_Framework_Constraint_IsInstanceOf + * @since Method available since Release 3.0.0 + */ +function isInstanceOf($className) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isInstanceOf', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsJson matcher object. + * + * @return PHPUnit_Framework_Constraint_IsJson + * @since Method available since Release 3.7.20 + */ +function isJson() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isJson', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsNull matcher object. + * + * @return PHPUnit_Framework_Constraint_IsNull + * @since Method available since Release 3.3.0 + */ +function isNull() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isNull', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsTrue matcher object. + * + * @return PHPUnit_Framework_Constraint_IsTrue + * @since Method available since Release 3.3.0 + */ +function isTrue() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isTrue', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_IsType matcher object. + * + * @param string $type + * @return PHPUnit_Framework_Constraint_IsType + * @since Method available since Release 3.0.0 + */ +function isType($type) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::isType', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_LessThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_LessThan + * @since Method available since Release 3.0.0 + */ +function lessThan($value) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::lessThan', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps + * a PHPUnit_Framework_Constraint_IsEqual and a + * PHPUnit_Framework_Constraint_LessThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_Or + * @since Method available since Release 3.1.0 + */ +function lessThanOrEqual($value) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::lessThanOrEqual', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_And matcher object. + * + * @return PHPUnit_Framework_Constraint_And + * @since Method available since Release 3.0.0 + */ +function logicalAnd() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::logicalAnd', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Not matcher object. + * + * @param PHPUnit_Framework_Constraint $constraint + * @return PHPUnit_Framework_Constraint_Not + * @since Method available since Release 3.0.0 + */ +function logicalNot(PHPUnit_Framework_Constraint $constraint) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::logicalNot', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Or matcher object. + * + * @return PHPUnit_Framework_Constraint_Or + * @since Method available since Release 3.0.0 + */ +function logicalOr() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::logicalOr', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_Xor matcher object. + * + * @return PHPUnit_Framework_Constraint_Xor + * @since Method available since Release 3.0.0 + */ +function logicalXor() +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::logicalXor', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_StringMatches matcher object. + * + * @param string $string + * @return PHPUnit_Framework_Constraint_StringMatches + * @since Method available since Release 3.5.0 + */ +function matches($string) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::matches', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_PCREMatch matcher object. + * + * @param string $pattern + * @return PHPUnit_Framework_Constraint_PCREMatch + * @since Method available since Release 3.0.0 + */ +function matchesRegularExpression($pattern) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::matchesRegularExpression', + func_get_args() + ); +} + +/** + * Returns a matcher that matches when the method it is evaluated for + * is never executed. + * + * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount + * @since Method available since Release 3.0.0 + */ +function never() +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::never', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_ObjectHasAttribute matcher object. + * + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_ObjectHasAttribute + * @since Method available since Release 3.0.0 + */ +function objectHasAttribute($attributeName) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::objectHasAttribute', + func_get_args() + ); +} + +/** + * @param mixed $value, ... + * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls + * @since Method available since Release 3.0.0 + */ +function onConsecutiveCalls() +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::onConsecutiveCalls', + func_get_args() + ); +} + +/** + * Returns a matcher that matches when the method it is evaluated for + * is executed exactly once. + * + * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount + * @since Method available since Release 3.0.0 + */ +function once() +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::once', + func_get_args() + ); +} + +/** + * + * + * @param integer $argumentIndex + * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument + * @since Method available since Release 3.3.0 + */ +function returnArgument($argumentIndex) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::returnArgument', + func_get_args() + ); +} + +/** + * + * + * @param mixed $callback + * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback + * @since Method available since Release 3.3.0 + */ +function returnCallback($callback) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::returnCallback', + func_get_args() + ); +} + +/** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + * + * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf + * @since Method available since Release 3.6.0 + */ +function returnSelf() +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::returnSelf', + func_get_args() + ); +} + +/** + * + * + * @param mixed $value + * @return PHPUnit_Framework_MockObject_Stub_Return + * @since Method available since Release 3.0.0 + */ +function returnValue($value) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::returnValue', + func_get_args() + ); +} + +/** + * + * + * @param array $valueMap + * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap + * @since Method available since Release 3.6.0 + */ +function returnValueMap(array $valueMap) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::returnValueMap', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_StringContains matcher object. + * + * @param string $string + * @param boolean $case + * @return PHPUnit_Framework_Constraint_StringContains + * @since Method available since Release 3.0.0 + */ +function stringContains($string, $case = true) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::stringContains', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_StringEndsWith matcher object. + * + * @param mixed $suffix + * @return PHPUnit_Framework_Constraint_StringEndsWith + * @since Method available since Release 3.4.0 + */ +function stringEndsWith($suffix) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::stringEndsWith', + func_get_args() + ); +} + +/** + * Returns a PHPUnit_Framework_Constraint_StringStartsWith matcher object. + * + * @param mixed $prefix + * @return PHPUnit_Framework_Constraint_StringStartsWith + * @since Method available since Release 3.4.0 + */ +function stringStartsWith($prefix) +{ + return call_user_func_array( + 'PHPUnit_Framework_Assert::stringStartsWith', + func_get_args() + ); +} + +/** + * + * + * @param Exception $exception + * @return PHPUnit_Framework_MockObject_Stub_Exception + * @since Method available since Release 3.1.0 + */ +function throwException(Exception $exception) +{ + return call_user_func_array( + 'PHPUnit_Framework_TestCase::throwException', + func_get_args() + ); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A TestResult collects the results of executing a test case. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Framework_TestResult implements Countable +{ + /** + * @var array + */ + protected $passed = array(); + + /** + * @var array + */ + protected $errors = array(); + + /** + * @var array + */ + protected $deprecatedFeatures = array(); + + /** + * @var array + */ + protected $failures = array(); + + /** + * @var array + */ + protected $notImplemented = array(); + + /** + * @var array + */ + protected $risky = array(); + + /** + * @var array + */ + protected $skipped = array(); + + /** + * @var array + */ + protected $listeners = array(); + + /** + * @var integer + */ + protected $runTests = 0; + + /** + * @var float + */ + protected $time = 0; + + /** + * @var PHPUnit_Framework_TestSuite + */ + protected $topTestSuite = null; + + /** + * Code Coverage information. + * + * @var PHP_CodeCoverage + */ + protected $codeCoverage; + + /** + * @var boolean + */ + protected $convertErrorsToExceptions = true; + + /** + * @var boolean + */ + protected $stop = false; + + /** + * @var boolean + */ + protected $stopOnError = false; + + /** + * @var boolean + */ + protected $stopOnFailure = false; + + /** + * @var boolean + */ + protected $beStrictAboutTestsThatDoNotTestAnything = false; + + /** + * @var boolean + */ + protected $beStrictAboutOutputDuringTests = false; + + /** + * @var boolean + */ + protected $beStrictAboutTestSize = false; + + /** + * @var boolean + */ + protected $stopOnRisky = false; + + /** + * @var boolean + */ + protected $stopOnIncomplete = false; + + /** + * @var boolean + */ + protected $stopOnSkipped = false; + + /** + * @var boolean + */ + protected $lastTestFailed = false; + + /** + * @var integer + */ + protected $timeoutForSmallTests = 1; + + /** + * @var integer + */ + protected $timeoutForMediumTests = 10; + + /** + * @var integer + */ + protected $timeoutForLargeTests = 60; + + /** + * Registers a TestListener. + * + * @param PHPUnit_Framework_TestListener + */ + public function addListener(PHPUnit_Framework_TestListener $listener) + { + $this->listeners[] = $listener; + } + + /** + * Unregisters a TestListener. + * + * @param PHPUnit_Framework_TestListener $listener + */ + public function removeListener(PHPUnit_Framework_TestListener $listener) + { + foreach ($this->listeners as $key => $_listener) { + if ($listener === $_listener) { + unset($this->listeners[$key]); + } + } + } + + /** + * Flushes all flushable TestListeners. + * + * @since Method available since Release 3.0.0 + */ + public function flushListeners() + { + foreach ($this->listeners as $listener) { + if ($listener instanceof PHPUnit_Util_Printer) { + $listener->flush(); + } + } + } + + /** + * Adds an error to the list of errors. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($e instanceof PHPUnit_Framework_RiskyTest) { + $this->risky[] = new PHPUnit_Framework_TestFailure( + $test, $e + ); + + $notifyMethod = 'addRiskyTest'; + + if ($this->stopOnRisky) { + $this->stop(); + } + } elseif ($e instanceof PHPUnit_Framework_IncompleteTest) { + $this->notImplemented[] = new PHPUnit_Framework_TestFailure( + $test, $e + ); + + $notifyMethod = 'addIncompleteTest'; + + if ($this->stopOnIncomplete) { + $this->stop(); + } + } elseif ($e instanceof PHPUnit_Framework_SkippedTest) { + $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e); + $notifyMethod = 'addSkippedTest'; + + if ($this->stopOnSkipped) { + $this->stop(); + } + } else { + $this->errors[] = new PHPUnit_Framework_TestFailure($test, $e); + $notifyMethod = 'addError'; + + if ($this->stopOnError || $this->stopOnFailure) { + $this->stop(); + } + } + + foreach ($this->listeners as $listener) { + $listener->$notifyMethod($test, $e, $time); + } + + $this->lastTestFailed = true; + $this->time += $time; + } + + /** + * Adds a failure to the list of failures. + * The passed in exception caused the failure. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + if ($e instanceof PHPUnit_Framework_RiskyTest) { + $this->risky[] = new PHPUnit_Framework_TestFailure( + $test, $e + ); + + $notifyMethod = 'addRiskyTest'; + + if ($this->stopOnRisky) { + $this->stop(); + } + } elseif ($e instanceof PHPUnit_Framework_IncompleteTest) { + $this->notImplemented[] = new PHPUnit_Framework_TestFailure( + $test, $e + ); + + $notifyMethod = 'addIncompleteTest'; + + if ($this->stopOnIncomplete) { + $this->stop(); + } + } elseif ($e instanceof PHPUnit_Framework_SkippedTest) { + $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e); + $notifyMethod = 'addSkippedTest'; + + if ($this->stopOnSkipped) { + $this->stop(); + } + } else { + $this->failures[] = new PHPUnit_Framework_TestFailure($test, $e); + $notifyMethod = 'addFailure'; + + if ($this->stopOnFailure) { + $this->stop(); + } + } + + foreach ($this->listeners as $listener) { + $listener->$notifyMethod($test, $e, $time); + } + + $this->lastTestFailed = true; + $this->time += $time; + } + + /** + * Adds a deprecated feature notice to the list of deprecated features used during run + * + * @param PHPUnit_Util_DeprecatedFeature $deprecatedFeature + */ + public function addDeprecatedFeature(PHPUnit_Util_DeprecatedFeature $deprecatedFeature) + { + $this->deprecatedFeatures[] = $deprecatedFeature; + } + + /** + * Informs the result that a testsuite will be started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + if ($this->topTestSuite === null) { + $this->topTestSuite = $suite; + } + + foreach ($this->listeners as $listener) { + $listener->startTestSuite($suite); + } + } + + /** + * Informs the result that a testsuite was completed. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + foreach ($this->listeners as $listener) { + $listener->endTestSuite($suite); + } + } + + /** + * Informs the result that a test will be started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + $this->lastTestFailed = false; + $this->runTests += count($test); + + foreach ($this->listeners as $listener) { + $listener->startTest($test); + } + } + + /** + * Informs the result that a test was completed. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + foreach ($this->listeners as $listener) { + $listener->endTest($test, $time); + } + + if (!$this->lastTestFailed && $test instanceof PHPUnit_Framework_TestCase) { + $class = get_class($test); + $key = $class . '::' . $test->getName(); + + $this->passed[$key] = array( + 'result' => $test->getResult(), + 'size' => PHPUnit_Util_Test::getSize( + $class, $test->getName(false) + ) + ); + + $this->time += $time; + } + } + + /** + * Returns true if no risky test occurred. + * + * @return boolean + * @since Method available since Release 4.0.0 + */ + public function allHarmless() + { + return $this->riskyCount() == 0; + } + + /** + * Gets the number of risky tests. + * + * @return integer + * @since Method available since Release 4.0.0 + */ + public function riskyCount() + { + return count($this->risky); + } + + /** + * Returns true if no incomplete test occurred. + * + * @return boolean + */ + public function allCompletelyImplemented() + { + return $this->notImplementedCount() == 0; + } + + /** + * Gets the number of incomplete tests. + * + * @return integer + */ + public function notImplementedCount() + { + return count($this->notImplemented); + } + + /** + * Returns an Enumeration for the risky tests. + * + * @return array + * @since Method available since Release 4.0.0 + */ + public function risky() + { + return $this->risky; + } + + /** + * Returns an Enumeration for the incomplete tests. + * + * @return array + */ + public function notImplemented() + { + return $this->notImplemented; + } + + /** + * Returns true if no test has been skipped. + * + * @return boolean + * @since Method available since Release 3.0.0 + */ + public function noneSkipped() + { + return $this->skippedCount() == 0; + } + + /** + * Gets the number of skipped tests. + * + * @return integer + * @since Method available since Release 3.0.0 + */ + public function skippedCount() + { + return count($this->skipped); + } + + /** + * Returns an Enumeration for the skipped tests. + * + * @return array + * @since Method available since Release 3.0.0 + */ + public function skipped() + { + return $this->skipped; + } + + /** + * Gets the number of detected errors. + * + * @return integer + */ + public function errorCount() + { + return count($this->errors); + } + + /** + * Returns an Enumeration for the errors. + * + * @return array + */ + public function errors() + { + return $this->errors; + } + + /** + * Returns an Enumeration for the deprecated features used. + * + * @return array + * @since Method available since Release 3.5.7 + */ + public function deprecatedFeatures() + { + return $this->deprecatedFeatures; + } + + /** + * Returns an Enumeration for the deprecated features used. + * + * @return array + * @since Method available since Release 3.5.7 + */ + public function deprecatedFeaturesCount() + { + return count($this->deprecatedFeatures); + } + + /** + * Gets the number of detected failures. + * + * @return integer + */ + public function failureCount() + { + return count($this->failures); + } + + /** + * Returns an Enumeration for the failures. + * + * @return array + */ + public function failures() + { + return $this->failures; + } + + /** + * Returns the names of the tests that have passed. + * + * @return array + * @since Method available since Release 3.4.0 + */ + public function passed() + { + return $this->passed; + } + + /** + * Returns the (top) test suite. + * + * @return PHPUnit_Framework_TestSuite + * @since Method available since Release 3.0.0 + */ + public function topTestSuite() + { + return $this->topTestSuite; + } + + /** + * Returns whether code coverage information should be collected. + * + * @return boolean If code coverage should be collected + * @since Method available since Release 3.2.0 + */ + public function getCollectCodeCoverageInformation() + { + return $this->codeCoverage !== null; + } + + /** + * Runs a TestCase. + * + * @param PHPUnit_Framework_Test $test + */ + public function run(PHPUnit_Framework_Test $test) + { + PHPUnit_Framework_Assert::resetCount(); + + $error = false; + $failure = false; + $incomplete = false; + $risky = false; + $skipped = false; + + $this->startTest($test); + + $errorHandlerSet = false; + + if ($this->convertErrorsToExceptions) { + $oldErrorHandler = set_error_handler( + array('PHPUnit_Util_ErrorHandler', 'handleError'), + E_ALL | E_STRICT + ); + + if ($oldErrorHandler === null) { + $errorHandlerSet = true; + } else { + restore_error_handler(); + } + } + + $collectCodeCoverage = $this->codeCoverage !== null && + !$test instanceof PHPUnit_Extensions_SeleniumTestCase && + !$test instanceof PHPUnit_Framework_Warning; + + if ($collectCodeCoverage) { + // We need to blacklist test source files when no whitelist is used. + if (!$this->codeCoverage->filter()->hasWhitelist()) { + $classes = $this->getHierarchy(get_class($test), true); + + foreach ($classes as $class) { + $this->codeCoverage->filter()->addFileToBlacklist( + $class->getFileName() + ); + } + } + + $this->codeCoverage->start($test); + } + + PHP_Timer::start(); + + try { + if (!$test instanceof PHPUnit_Framework_Warning && + $this->beStrictAboutTestSize && + extension_loaded('pcntl') && class_exists('PHP_Invoker')) { + switch ($test->getSize()) { + case PHPUnit_Util_Test::SMALL: { + $_timeout = $this->timeoutForSmallTests; + } + break; + + case PHPUnit_Util_Test::MEDIUM: { + $_timeout = $this->timeoutForMediumTests; + } + break; + + case PHPUnit_Util_Test::LARGE: { + $_timeout = $this->timeoutForLargeTests; + } + break; + } + + $invoker = new PHP_Invoker; + $invoker->invoke(array($test, 'runBare'), array(), $_timeout); + } else { + $test->runBare(); + } + } catch (PHPUnit_Framework_AssertionFailedError $e) { + $failure = true; + + if ($e instanceof PHPUnit_Framework_RiskyTestError) { + $risky = true; + } elseif ($e instanceof PHPUnit_Framework_IncompleteTestError) { + $incomplete = true; + } elseif ($e instanceof PHPUnit_Framework_SkippedTestError) { + $skipped = true; + } + } catch (Exception $e) { + $error = true; + } + + $time = PHP_Timer::stop(); + $test->addToAssertionCount(PHPUnit_Framework_Assert::getCount()); + + if ($this->beStrictAboutTestsThatDoNotTestAnything && + $test->getNumAssertions() == 0) { + $risky = true; + } + + if ($collectCodeCoverage) { + $append = !$risky && !$incomplete && !$skipped; + $linesToBeCovered = array(); + $linesToBeUsed = array(); + + if ($append && $test instanceof PHPUnit_Framework_TestCase) { + $linesToBeCovered = PHPUnit_Util_Test::getLinesToBeCovered( + get_class($test), $test->getName(false) + ); + + $linesToBeUsed = PHPUnit_Util_Test::getLinesToBeUsed( + get_class($test), $test->getName(false) + ); + } + + try { + $this->codeCoverage->stop( + $append, $linesToBeCovered, $linesToBeUsed + ); + } catch (PHP_CodeCoverage_Exception_UnintentionallyCoveredCode $cce) { + $this->addFailure( + $test, + new PHPUnit_Framework_UnintentionallyCoveredCodeError( + 'This test executed code that is not listed as code to be covered or used:' . + PHP_EOL . $cce->getMessage() + ), + $time + ); + } catch (PHPUnit_Framework_InvalidCoversTargetException $cce) { + $this->addFailure( + $test, + new PHPUnit_Framework_InvalidCoversTargetError( + $cce->getMessage() + ), + $time + ); + } catch (PHP_CodeCoverage_Exception $cce) { + $error = true; + + if (!isset($e)) { + $e = $cce; + } + } + } + + if ($errorHandlerSet === true) { + restore_error_handler(); + } + + if ($error === true) { + $this->addError($test, $e, $time); + } elseif ($failure === true) { + $this->addFailure($test, $e, $time); + } elseif ($this->beStrictAboutTestsThatDoNotTestAnything && + $test->getNumAssertions() == 0) { + $this->addFailure( + $test, + new PHPUnit_Framework_RiskyTestError( + 'This test did not perform any assertions' + ), + $time + ); + } elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) { + $this->addFailure( + $test, + new PHPUnit_Framework_OutputError( + sprintf( + 'This test printed output: %s', + $test->getActualOutput() + ) + ), + $time + ); + } + + $this->endTest($test, $time); + } + + /** + * Gets the number of run tests. + * + * @return integer + */ + public function count() + { + return $this->runTests; + } + + /** + * Checks whether the test run should stop. + * + * @return boolean + */ + public function shouldStop() + { + return $this->stop; + } + + /** + * Marks that the test run should stop. + * + */ + public function stop() + { + $this->stop = true; + } + + /** + * Returns the PHP_CodeCoverage object. + * + * @return PHP_CodeCoverage + * @since Method available since Release 3.5.0 + */ + public function getCodeCoverage() + { + return $this->codeCoverage; + } + + /** + * Sets the PHP_CodeCoverage object. + * + * @param PHP_CodeCoverage $codeCoverage + * @since Method available since Release 3.6.0 + */ + public function setCodeCoverage(PHP_CodeCoverage $codeCoverage) + { + $this->codeCoverage = $codeCoverage; + } + + /** + * Enables or disables the error-to-exception conversion. + * + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.2.14 + */ + public function convertErrorsToExceptions($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->convertErrorsToExceptions = $flag; + } + + /** + * Returns the error-to-exception conversion setting. + * + * @return boolean + * @since Method available since Release 3.4.0 + */ + public function getConvertErrorsToExceptions() + { + return $this->convertErrorsToExceptions; + } + + /** + * Enables or disables the stopping when an error occurs. + * + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.5.0 + */ + public function stopOnError($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->stopOnError = $flag; + } + + /** + * Enables or disables the stopping when a failure occurs. + * + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.1.0 + */ + public function stopOnFailure($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->stopOnFailure = $flag; + } + + /** + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 4.0.0 + */ + public function beStrictAboutTestsThatDoNotTestAnything($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->beStrictAboutTestsThatDoNotTestAnything = $flag; + } + + /** + * @return boolean + * @since Method available since Release 4.0.0 + */ + public function isStrictAboutTestsThatDoNotTestAnything() + { + return $this->beStrictAboutTestsThatDoNotTestAnything; + } + + /** + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 4.0.0 + */ + public function beStrictAboutOutputDuringTests($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->beStrictAboutOutputDuringTests = $flag; + } + + /** + * @return boolean + * @since Method available since Release 4.0.0 + */ + public function isStrictAboutOutputDuringTests() + { + return $this->beStrictAboutOutputDuringTests; + } + + /** + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 4.0.0 + */ + public function beStrictAboutTestSize($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->beStrictAboutTestSize = $flag; + } + + /** + * @return boolean + * @since Method available since Release 4.0.0 + */ + public function isStrictAboutTestSize() + { + return $this->beStrictAboutTestSize; + } + + /** + * Enables or disables the stopping for risky tests. + * + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 4.0.0 + */ + public function stopOnRisky($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->stopOnRisky = $flag; + } + + /** + * Enables or disables the stopping for incomplete tests. + * + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.5.0 + */ + public function stopOnIncomplete($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->stopOnIncomplete = $flag; + } + + /** + * Enables or disables the stopping for skipped tests. + * + * @param boolean $flag + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.1.0 + */ + public function stopOnSkipped($flag) + { + if (!is_bool($flag)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + + $this->stopOnSkipped = $flag; + } + + /** + * Returns the time spent running the tests. + * + * @return float + */ + public function time() + { + return $this->time; + } + + /** + * Returns whether the entire test was successful or not. + * + * @return boolean + */ + public function wasSuccessful() + { + return empty($this->errors) && empty($this->failures); + } + + /** + * Sets the timeout for small tests. + * + * @param integer $timeout + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.6.0 + */ + public function setTimeoutForSmallTests($timeout) + { + if (!is_integer($timeout)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer'); + } + + $this->timeoutForSmallTests = $timeout; + } + + /** + * Sets the timeout for medium tests. + * + * @param integer $timeout + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.6.0 + */ + public function setTimeoutForMediumTests($timeout) + { + if (!is_integer($timeout)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer'); + } + + $this->timeoutForMediumTests = $timeout; + } + + /** + * Sets the timeout for large tests. + * + * @param integer $timeout + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.6.0 + */ + public function setTimeoutForLargeTests($timeout) + { + if (!is_integer($timeout)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer'); + } + + $this->timeoutForLargeTests = $timeout; + } + + /** + * Returns the class hierarchy for a given class. + * + * @param string $className + * @param boolean $asReflectionObjects + * @return array + */ + protected function getHierarchy($className, $asReflectionObjects = false) + { + if ($asReflectionObjects) { + $classes = array(new ReflectionClass($className)); + } else { + $classes = array($className); + } + + $done = false; + + while (!$done) { + if ($asReflectionObjects) { + $class = new ReflectionClass( + $classes[count($classes)-1]->getName() + ); + } else { + $class = new ReflectionClass($classes[count($classes)-1]); + } + + $parent = $class->getParentClass(); + + if ($parent !== false) { + if ($asReflectionObjects) { + $classes[] = $parent; + } else { + $classes[] = $parent->getName(); + } + } else { + $done = true; + } + } + + return $classes; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.0 + */ + +/** + * Creates a synthetic failed assertion. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.5.0 + */ +class PHPUnit_Framework_SyntheticError extends PHPUnit_Framework_AssertionFailedError +{ + /** + * The synthetic file. + * + * @var string + */ + protected $syntheticFile = ''; + + /** + * The synthetic line number. + * + * @var integer + */ + protected $syntheticLine = 0; + + /** + * The synthetic trace. + * + * @var array + */ + protected $syntheticTrace = array(); + + /** + * Constructor. + * + * @param string $message + * @param integer $code + * @param string $file + * @param integer $line + * @param array $trace + */ + public function __construct($message, $code, $file, $line, $trace) + { + parent::__construct($message, $code); + + $this->syntheticFile = $file; + $this->syntheticLine = $line; + $this->syntheticTrace = $trace; + } + + /** + * @return string + */ + public function getSyntheticFile() + { + return $this->syntheticFile; + } + + /** + * @return integer + */ + public function getSyntheticLine() + { + return $this->syntheticLine; + } + + /** + * @return array + */ + public function getSyntheticTrace() + { + return $this->syntheticTrace; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of a skipped test suite. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.0 + */ +class PHPUnit_Framework_SkippedTestSuiteError extends PHPUnit_Framework_AssertionFailedError implements PHPUnit_Framework_SkippedTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Framework_CodeCoverageException extends PHPUnit_Framework_Exception +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A set of assert methods. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +abstract class PHPUnit_Framework_Assert +{ + /** + * @var integer + */ + private static $count = 0; + + /** + * Asserts that an array has a specified key. + * + * @param mixed $key + * @param array|ArrayAccess $array + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertArrayHasKey($key, $array, $message = '') + { + if (!(is_integer($key) || is_string($key))) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'integer or string' + ); + } + + if (!(is_array($array) || $array instanceof ArrayAccess)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array or ArrayAccess' + ); + } + + $constraint = new PHPUnit_Framework_Constraint_ArrayHasKey($key); + + self::assertThat($array, $constraint, $message); + } + + /** + * Asserts that an array does not have a specified key. + * + * @param mixed $key + * @param array|ArrayAccess $array + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertArrayNotHasKey($key, $array, $message = '') + { + if (!(is_integer($key) || is_string($key))) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'integer or string' + ); + } + + if (!(is_array($array) || $array instanceof ArrayAccess)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array or ArrayAccess' + ); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_ArrayHasKey($key) + ); + + self::assertThat($array, $constraint, $message); + } + + /** + * Asserts that a haystack contains a needle. + * + * @param mixed $needle + * @param mixed $haystack + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 2.1.0 + */ + public static function assertContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) + { + if (is_array($haystack) || + is_object($haystack) && $haystack instanceof Traversable) { + $constraint = new PHPUnit_Framework_Constraint_TraversableContains( + $needle, $checkForObjectIdentity, $checkForNonObjectIdentity + ); + } elseif (is_string($haystack)) { + $constraint = new PHPUnit_Framework_Constraint_StringContains( + $needle, $ignoreCase + ); + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array, traversable or string' + ); + } + + self::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object contains a needle. + * + * @param mixed $needle + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 3.0.0 + */ + public static function assertAttributeContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) + { + self::assertContains( + $needle, + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message, + $ignoreCase, + $checkForObjectIdentity, + $checkForNonObjectIdentity + ); + } + + /** + * Asserts that a haystack does not contain a needle. + * + * @param mixed $needle + * @param mixed $haystack + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 2.1.0 + */ + public static function assertNotContains($needle, $haystack, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) + { + if (is_array($haystack) || + is_object($haystack) && $haystack instanceof Traversable) { + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_TraversableContains( + $needle, $checkForObjectIdentity, $checkForNonObjectIdentity + ) + ); + } elseif (is_string($haystack)) { + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_StringContains( + $needle, $ignoreCase + ) + ); + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array, traversable or string' + ); + } + + self::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object does not contain a needle. + * + * @param mixed $needle + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @param boolean $ignoreCase + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @since Method available since Release 3.0.0 + */ + public static function assertAttributeNotContains($needle, $haystackAttributeName, $haystackClassOrObject, $message = '', $ignoreCase = false, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) + { + self::assertNotContains( + $needle, + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message, + $ignoreCase, + $checkForObjectIdentity, + $checkForNonObjectIdentity + ); + } + + /** + * Asserts that a haystack contains only values of a given type. + * + * @param string $type + * @param mixed $haystack + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ + public static function assertContainsOnly($type, $haystack, $isNativeType = null, $message = '') + { + if (!(is_array($haystack) || + is_object($haystack) && $haystack instanceof Traversable)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array or traversable' + ); + } + + if ($isNativeType == null) { + $isNativeType = PHPUnit_Util_Type::isType($type); + } + + self::assertThat( + $haystack, + new PHPUnit_Framework_Constraint_TraversableContainsOnly( + $type, $isNativeType + ), + $message + ); + } + + /** + * Asserts that a haystack contains only instances of a given classname + * + * @param string $classname + * @param array|Traversable $haystack + * @param string $message + */ + public static function assertContainsOnlyInstancesOf($classname, $haystack, $message = '') + { + if (!(is_array($haystack) || + is_object($haystack) && $haystack instanceof Traversable)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array or traversable' + ); + } + + self::assertThat( + $haystack, + new PHPUnit_Framework_Constraint_TraversableContainsOnly( + $classname, false + ), + $message + ); + } + + /** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object contains only values of a given type. + * + * @param string $type + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ + public static function assertAttributeContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') + { + self::assertContainsOnly( + $type, + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $isNativeType, + $message + ); + } + + /** + * Asserts that a haystack does not contain only values of a given type. + * + * @param string $type + * @param mixed $haystack + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ + public static function assertNotContainsOnly($type, $haystack, $isNativeType = null, $message = '') + { + if (!(is_array($haystack) || + is_object($haystack) && $haystack instanceof Traversable)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'array or traversable' + ); + } + + if ($isNativeType == null) { + $isNativeType = PHPUnit_Util_Type::isType($type); + } + + self::assertThat( + $haystack, + new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_TraversableContainsOnly( + $type, $isNativeType + ) + ), + $message + ); + } + + /** + * Asserts that a haystack that is stored in a static attribute of a class + * or an attribute of an object does not contain only values of a given + * type. + * + * @param string $type + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param boolean $isNativeType + * @param string $message + * @since Method available since Release 3.1.4 + */ + public static function assertAttributeNotContainsOnly($type, $haystackAttributeName, $haystackClassOrObject, $isNativeType = null, $message = '') + { + self::assertNotContainsOnly( + $type, + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $isNativeType, + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param integer $expectedCount + * @param mixed $haystack + * @param string $message + */ + public static function assertCount($expectedCount, $haystack, $message = '') + { + if (!is_int($expectedCount)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer'); + } + + if (!$haystack instanceof Countable && + !$haystack instanceof Traversable && + !is_array($haystack)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable or traversable'); + } + + self::assertThat( + $haystack, + new PHPUnit_Framework_Constraint_Count($expectedCount), + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable + * that is stored in an attribute. + * + * @param integer $expectedCount + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.6.0 + */ + public static function assertAttributeCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') + { + self::assertCount( + $expectedCount, + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable. + * + * @param integer $expectedCount + * @param mixed $haystack + * @param string $message + */ + public static function assertNotCount($expectedCount, $haystack, $message = '') + { + if (!is_int($expectedCount)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer'); + } + + if (!$haystack instanceof Countable && + !$haystack instanceof Traversable && + !is_array($haystack)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable or traversable'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_Count($expectedCount) + ); + + self::assertThat($haystack, $constraint, $message); + } + + /** + * Asserts the number of elements of an array, Countable or Traversable + * that is stored in an attribute. + * + * @param integer $expectedCount + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.6.0 + */ + public static function assertAttributeNotCount($expectedCount, $haystackAttributeName, $haystackClassOrObject, $message = '') + { + self::assertNotCount( + $expectedCount, + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts that two variables are equal. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + */ + public static function assertEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + $constraint = new PHPUnit_Framework_Constraint_IsEqual( + $expected, $delta, $maxDepth, $canonicalize, $ignoreCase + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that a variable is equal to an attribute of an object. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + */ + public static function assertAttributeEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + self::assertEquals( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that two variables are not equal. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 2.3.0 + */ + public static function assertNotEquals($expected, $actual, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_IsEqual( + $expected, $delta, $maxDepth, $canonicalize, $ignoreCase + ) + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that a variable is not equal to an attribute of an object. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + */ + public static function assertAttributeNotEquals($expected, $actualAttributeName, $actualClassOrObject, $message = '', $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + self::assertNotEquals( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message, + $delta, + $maxDepth, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that a variable is empty. + * + * @param mixed $actual + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function assertEmpty($actual, $message = '') + { + self::assertThat($actual, self::isEmpty(), $message); + } + + /** + * Asserts that a static attribute of a class or an attribute of an object + * is empty. + * + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertAttributeEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') + { + self::assertEmpty( + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts that a variable is not empty. + * + * @param mixed $actual + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function assertNotEmpty($actual, $message = '') + { + self::assertThat($actual, self::logicalNot(self::isEmpty()), $message); + } + + /** + * Asserts that a static attribute of a class or an attribute of an object + * is not empty. + * + * @param string $haystackAttributeName + * @param mixed $haystackClassOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertAttributeNotEmpty($haystackAttributeName, $haystackClassOrObject, $message = '') + { + self::assertNotEmpty( + self::readAttribute($haystackClassOrObject, $haystackAttributeName), + $message + ); + } + + /** + * Asserts that a value is greater than another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertGreaterThan($expected, $actual, $message = '') + { + self::assertThat($actual, self::greaterThan($expected), $message); + } + + /** + * Asserts that an attribute is greater than another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertAttributeGreaterThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') + { + self::assertGreaterThan( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a value is greater than or equal to another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertGreaterThanOrEqual($expected, $actual, $message = '') + { + self::assertThat( + $actual, self::greaterThanOrEqual($expected), $message + ); + } + + /** + * Asserts that an attribute is greater than or equal to another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertAttributeGreaterThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') + { + self::assertGreaterThanOrEqual( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a value is smaller than another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertLessThan($expected, $actual, $message = '') + { + self::assertThat($actual, self::lessThan($expected), $message); + } + + /** + * Asserts that an attribute is smaller than another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertAttributeLessThan($expected, $actualAttributeName, $actualClassOrObject, $message = '') + { + self::assertLessThan( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a value is smaller than or equal to another value. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertLessThanOrEqual($expected, $actual, $message = '') + { + self::assertThat($actual, self::lessThanOrEqual($expected), $message); + } + + /** + * Asserts that an attribute is smaller than or equal to another value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param string $actualClassOrObject + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertAttributeLessThanOrEqual($expected, $actualAttributeName, $actualClassOrObject, $message = '') + { + self::assertLessThanOrEqual( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that the contents of one file is equal to the contents of another + * file. + * + * @param string $expected + * @param string $actual + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.2.14 + */ + public static function assertFileEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) + { + self::assertFileExists($expected, $message); + self::assertFileExists($actual, $message); + + self::assertEquals( + file_get_contents($expected), + file_get_contents($actual), + $message, + 0, + 10, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that the contents of one file is not equal to the contents of + * another file. + * + * @param string $expected + * @param string $actual + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.2.14 + */ + public static function assertFileNotEquals($expected, $actual, $message = '', $canonicalize = false, $ignoreCase = false) + { + self::assertFileExists($expected, $message); + self::assertFileExists($actual, $message); + + self::assertNotEquals( + file_get_contents($expected), + file_get_contents($actual), + $message, + 0, + 10, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that the contents of a string is equal + * to the contents of a file. + * + * @param string $expectedFile + * @param string $actualString + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.3.0 + */ + public static function assertStringEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) + { + self::assertFileExists($expectedFile, $message); + + self::assertEquals( + file_get_contents($expectedFile), + $actualString, + $message, + 0, + 10, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that the contents of a string is not equal + * to the contents of a file. + * + * @param string $expectedFile + * @param string $actualString + * @param string $message + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @since Method available since Release 3.3.0 + */ + public static function assertStringNotEqualsFile($expectedFile, $actualString, $message = '', $canonicalize = false, $ignoreCase = false) + { + self::assertFileExists($expectedFile, $message); + + self::assertNotEquals( + file_get_contents($expectedFile), + $actualString, + $message, + 0, + 10, + $canonicalize, + $ignoreCase + ); + } + + /** + * Asserts that a file exists. + * + * @param string $filename + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertFileExists($filename, $message = '') + { + if (!is_string($filename)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_FileExists; + + self::assertThat($filename, $constraint, $message); + } + + /** + * Asserts that a file does not exist. + * + * @param string $filename + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertFileNotExists($filename, $message = '') + { + if (!is_string($filename)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_FileExists + ); + + self::assertThat($filename, $constraint, $message); + } + + /** + * Asserts that a condition is true. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function assertTrue($condition, $message = '') + { + self::assertThat($condition, self::isTrue(), $message); + } + + /** + * Asserts that a condition is not true. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function assertNotTrue($condition, $message = '') + { + self::assertThat($condition, self::logicalNot(self::isTrue()), $message); + } + + /** + * Asserts that a condition is false. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function assertFalse($condition, $message = '') + { + self::assertThat($condition, self::isFalse(), $message); + } + + /** + * Asserts that a condition is not false. + * + * @param boolean $condition + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function assertNotFalse($condition, $message = '') + { + self::assertThat($condition, self::logicalNot(self::isFalse()), $message); + } + + /** + * Asserts that a variable is not null. + * + * @param mixed $actual + * @param string $message + */ + public static function assertNotNull($actual, $message = '') + { + self::assertThat($actual, self::logicalNot(self::isNull()), $message); + } + + /** + * Asserts that a variable is null. + * + * @param mixed $actual + * @param string $message + */ + public static function assertNull($actual, $message = '') + { + self::assertThat($actual, self::isNull(), $message); + } + + /** + * Asserts that a class has a specified attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertClassHasAttribute($attributeName, $className, $message = '') + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!is_string($className) || !class_exists($className, false)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name'); + } + + $constraint = new PHPUnit_Framework_Constraint_ClassHasAttribute( + $attributeName + ); + + self::assertThat($className, $constraint, $message); + } + + /** + * Asserts that a class does not have a specified attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertClassNotHasAttribute($attributeName, $className, $message = '') + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!is_string($className) || !class_exists($className, false)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_ClassHasAttribute($attributeName) + ); + + self::assertThat($className, $constraint, $message); + } + + /** + * Asserts that a class has a specified static attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertClassHasStaticAttribute($attributeName, $className, $message = '') + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!is_string($className) || !class_exists($className, false)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name'); + } + + $constraint = new PHPUnit_Framework_Constraint_ClassHasStaticAttribute( + $attributeName + ); + + self::assertThat($className, $constraint, $message); + } + + /** + * Asserts that a class does not have a specified static attribute. + * + * @param string $attributeName + * @param string $className + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertClassNotHasStaticAttribute($attributeName, $className, $message = '') + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!is_string($className) || !class_exists($className, false)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'class name'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_ClassHasStaticAttribute( + $attributeName + ) + ); + + self::assertThat($className, $constraint, $message); + } + + /** + * Asserts that an object has a specified attribute. + * + * @param string $attributeName + * @param object $object + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertObjectHasAttribute($attributeName, $object, $message = '') + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!is_object($object)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'object'); + } + + $constraint = new PHPUnit_Framework_Constraint_ObjectHasAttribute( + $attributeName + ); + + self::assertThat($object, $constraint, $message); + } + + /** + * Asserts that an object does not have a specified attribute. + * + * @param string $attributeName + * @param object $object + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertObjectNotHasAttribute($attributeName, $object, $message = '') + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'valid attribute name'); + } + + if (!is_object($object)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'object'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_ObjectHasAttribute($attributeName) + ); + + self::assertThat($object, $constraint, $message); + } + + /** + * Asserts that two variables have the same type and value. + * Used on objects, it asserts that two variables reference + * the same object. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + */ + public static function assertSame($expected, $actual, $message = '') + { + if (is_bool($expected) && is_bool($actual)) { + self::assertEquals($expected, $actual, $message); + } else { + $constraint = new PHPUnit_Framework_Constraint_IsIdentical( + $expected + ); + + self::assertThat($actual, $constraint, $message); + } + } + + /** + * Asserts that a variable and an attribute of an object have the same type + * and value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param object $actualClassOrObject + * @param string $message + */ + public static function assertAttributeSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') + { + self::assertSame( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that two variables do not have the same type and value. + * Used on objects, it asserts that two variables do not reference + * the same object. + * + * @param mixed $expected + * @param mixed $actual + * @param string $message + */ + public static function assertNotSame($expected, $actual, $message = '') + { + if (is_bool($expected) && is_bool($actual)) { + self::assertNotEquals($expected, $actual, $message); + } else { + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_IsIdentical($expected) + ); + + self::assertThat($actual, $constraint, $message); + } + } + + /** + * Asserts that a variable and an attribute of an object do not have the + * same type and value. + * + * @param mixed $expected + * @param string $actualAttributeName + * @param object $actualClassOrObject + * @param string $message + */ + public static function assertAttributeNotSame($expected, $actualAttributeName, $actualClassOrObject, $message = '') + { + self::assertNotSame( + $expected, + self::readAttribute($actualClassOrObject, $actualAttributeName), + $message + ); + } + + /** + * Asserts that a variable is of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertInstanceOf($expected, $actual, $message = '') + { + if (!(is_string($expected) && (class_exists($expected) || interface_exists($expected)))) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'class or interface name'); + } + + $constraint = new PHPUnit_Framework_Constraint_IsInstanceOf( + $expected + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertAttributeInstanceOf($expected, $attributeName, $classOrObject, $message = '') + { + self::assertInstanceOf( + $expected, + self::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a variable is not of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertNotInstanceOf($expected, $actual, $message = '') + { + if (!(is_string($expected) && (class_exists($expected) || interface_exists($expected)))) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'class or interface name'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_IsInstanceOf($expected) + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertAttributeNotInstanceOf($expected, $attributeName, $classOrObject, $message = '') + { + self::assertNotInstanceOf( + $expected, + self::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a variable is of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertInternalType($expected, $actual, $message = '') + { + if (!is_string($expected)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_IsType( + $expected + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertAttributeInternalType($expected, $attributeName, $classOrObject, $message = '') + { + self::assertInternalType( + $expected, + self::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a variable is not of a given type. + * + * @param string $expected + * @param mixed $actual + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertNotInternalType($expected, $actual, $message = '') + { + if (!is_string($expected)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_IsType($expected) + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that an attribute is of a given type. + * + * @param string $expected + * @param string $attributeName + * @param mixed $classOrObject + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertAttributeNotInternalType($expected, $attributeName, $classOrObject, $message = '') + { + self::assertNotInternalType( + $expected, + self::readAttribute($classOrObject, $attributeName), + $message + ); + } + + /** + * Asserts that a string matches a given regular expression. + * + * @param string $pattern + * @param string $string + * @param string $message + */ + public static function assertRegExp($pattern, $string, $message = '') + { + if (!is_string($pattern)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_PCREMatch($pattern); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string does not match a given regular expression. + * + * @param string $pattern + * @param string $string + * @param string $message + * @since Method available since Release 2.1.0 + */ + public static function assertNotRegExp($pattern, $string, $message = '') + { + if (!is_string($pattern)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_PCREMatch($pattern) + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is the same. + * + * @param array|Countable|Traversable $expected + * @param array|Countable|Traversable $actual + * @param string $message + */ + public static function assertSameSize($expected, $actual, $message = '') + { + if (!$expected instanceof Countable && + !$expected instanceof Traversable && + !is_array($expected)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'countable or traversable'); + } + + if (!$actual instanceof Countable && + !$actual instanceof Traversable && + !is_array($actual)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable or traversable'); + } + + self::assertThat( + $actual, + new PHPUnit_Framework_Constraint_SameSize($expected), + $message + ); + } + + /** + * Assert that the size of two arrays (or `Countable` or `Traversable` objects) + * is not the same. + * + * @param array|Countable|Traversable $expected + * @param array|Countable|Traversable $actual + * @param string $message + */ + public static function assertNotSameSize($expected, $actual, $message = '') + { + if (!$expected instanceof Countable && + !$expected instanceof Traversable && + !is_array($expected)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'countable or traversable'); + } + + if (!$actual instanceof Countable && + !$actual instanceof Traversable && + !is_array($actual)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'countable or traversable'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_SameSize($expected) + ); + + self::assertThat($actual, $constraint, $message); + } + + /** + * Asserts that a string matches a given format string. + * + * @param string $format + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertStringMatchesFormat($format, $string, $message = '') + { + if (!is_string($format)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_StringMatches($format); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string does not match a given format string. + * + * @param string $format + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertStringNotMatchesFormat($format, $string, $message = '') + { + if (!is_string($format)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_StringMatches($format) + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string matches a given format file. + * + * @param string $formatFile + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertStringMatchesFormatFile($formatFile, $string, $message = '') + { + self::assertFileExists($formatFile, $message); + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_StringMatches( + file_get_contents($formatFile) + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string does not match a given format string. + * + * @param string $formatFile + * @param string $string + * @param string $message + * @since Method available since Release 3.5.0 + */ + public static function assertStringNotMatchesFormatFile($formatFile, $string, $message = '') + { + self::assertFileExists($formatFile, $message); + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_StringMatches( + file_get_contents($formatFile) + ) + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string starts with a given prefix. + * + * @param string $prefix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ + public static function assertStringStartsWith($prefix, $string, $message = '') + { + if (!is_string($prefix)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_StringStartsWith( + $prefix + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string starts not with a given prefix. + * + * @param string $prefix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ + public static function assertStringStartsNotWith($prefix, $string, $message = '') + { + if (!is_string($prefix)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_StringStartsWith($prefix) + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string ends with a given suffix. + * + * @param string $suffix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ + public static function assertStringEndsWith($suffix, $string, $message = '') + { + if (!is_string($suffix)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_StringEndsWith($suffix); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that a string ends not with a given suffix. + * + * @param string $suffix + * @param string $string + * @param string $message + * @since Method available since Release 3.4.0 + */ + public static function assertStringEndsNotWith($suffix, $string, $message = '') + { + if (!is_string($suffix)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_string($string)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + $constraint = new PHPUnit_Framework_Constraint_Not( + new PHPUnit_Framework_Constraint_StringEndsWith($suffix) + ); + + self::assertThat($string, $constraint, $message); + } + + /** + * Asserts that two XML files are equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertXmlFileEqualsXmlFile($expectedFile, $actualFile, $message = '') + { + self::assertFileExists($expectedFile); + self::assertFileExists($actualFile); + + $expected = new DOMDocument; + $expected->preserveWhiteSpace = false; + $expected->load($expectedFile); + + $actual = new DOMDocument; + $actual->preserveWhiteSpace = false; + $actual->load($actualFile); + + self::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML files are not equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertXmlFileNotEqualsXmlFile($expectedFile, $actualFile, $message = '') + { + self::assertFileExists($expectedFile); + self::assertFileExists($actualFile); + + $expected = new DOMDocument; + $expected->preserveWhiteSpace = false; + $expected->load($expectedFile); + + $actual = new DOMDocument; + $actual->preserveWhiteSpace = false; + $actual->load($actualFile); + + self::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @param string $expectedFile + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.3.0 + */ + public static function assertXmlStringEqualsXmlFile($expectedFile, $actualXml, $message = '') + { + self::assertFileExists($expectedFile); + + $expected = new DOMDocument; + $expected->preserveWhiteSpace = false; + $expected->load($expectedFile); + + $actual = new DOMDocument; + $actual->preserveWhiteSpace = false; + $actual->loadXML($actualXml); + + self::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @param string $expectedFile + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.3.0 + */ + public static function assertXmlStringNotEqualsXmlFile($expectedFile, $actualXml, $message = '') + { + self::assertFileExists($expectedFile); + + $expected = new DOMDocument; + $expected->preserveWhiteSpace = false; + $expected->load($expectedFile); + + $actual = new DOMDocument; + $actual->preserveWhiteSpace = false; + $actual->loadXML($actualXml); + + self::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are equal. + * + * @param string $expectedXml + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertXmlStringEqualsXmlString($expectedXml, $actualXml, $message = '') + { + $expected = new DOMDocument; + $expected->preserveWhiteSpace = false; + $expected->loadXML($expectedXml); + + $actual = new DOMDocument; + $actual->preserveWhiteSpace = false; + $actual->loadXML($actualXml); + + self::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two XML documents are not equal. + * + * @param string $expectedXml + * @param string $actualXml + * @param string $message + * @since Method available since Release 3.1.0 + */ + public static function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, $message = '') + { + $expected = new DOMDocument; + $expected->preserveWhiteSpace = false; + $expected->loadXML($expectedXml); + + $actual = new DOMDocument; + $actual->preserveWhiteSpace = false; + $actual->loadXML($actualXml); + + self::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that a hierarchy of DOMElements matches. + * + * @param DOMElement $expectedElement + * @param DOMElement $actualElement + * @param boolean $checkAttributes + * @param string $message + * @author Mattis Stordalen Flister + * @since Method available since Release 3.3.0 + */ + public static function assertEqualXMLStructure(DOMElement $expectedElement, DOMElement $actualElement, $checkAttributes = false, $message = '') + { + self::assertEquals( + $expectedElement->tagName, + $actualElement->tagName, + $message + ); + + if ($checkAttributes) { + self::assertEquals( + $expectedElement->attributes->length, + $actualElement->attributes->length, + sprintf( + '%s%sNumber of attributes on node "%s" does not match', + $message, + !empty($message) ? "\n" : '', + $expectedElement->tagName + ) + ); + + for ($i = 0 ; $i < $expectedElement->attributes->length; $i++) { + $expectedAttribute = $expectedElement->attributes->item($i); + $actualAttribute = $actualElement->attributes->getNamedItem( + $expectedAttribute->name + ); + + if (!$actualAttribute) { + self::fail( + sprintf( + '%s%sCould not find attribute "%s" on node "%s"', + $message, + !empty($message) ? "\n" : '', + $expectedAttribute->name, + $expectedElement->tagName + ) + ); + } + } + } + + PHPUnit_Util_XML::removeCharacterDataNodes($expectedElement); + PHPUnit_Util_XML::removeCharacterDataNodes($actualElement); + + self::assertEquals( + $expectedElement->childNodes->length, + $actualElement->childNodes->length, + sprintf( + '%s%sNumber of child nodes of "%s" differs', + $message, + !empty($message) ? "\n" : '', + $expectedElement->tagName + ) + ); + + for ($i = 0; $i < $expectedElement->childNodes->length; $i++) { + self::assertEqualXMLStructure( + $expectedElement->childNodes->item($i), + $actualElement->childNodes->item($i), + $checkAttributes, + $message + ); + } + } + + /** + * Assert the presence, absence, or count of elements in a document matching + * the CSS $selector, regardless of the contents of those elements. + * + * The first argument, $selector, is the CSS selector used to match + * the elements in the $actual document. + * + * The second argument, $count, can be either boolean or numeric. + * When boolean, it asserts for presence of elements matching the selector + * (true) or absence of elements (false). + * When numeric, it asserts the count of elements. + * + * assertSelectCount("#binder", true, $xml); // any? + * assertSelectCount(".binder", 3, $xml); // exactly 3? + * + * @param array $selector + * @param integer $count + * @param mixed $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function assertSelectCount($selector, $count, $actual, $message = '', $isHtml = true) + { + self::assertSelectEquals( + $selector, true, $count, $actual, $message, $isHtml + ); + } + + /** + * assertSelectRegExp("#binder .name", "/Mike|Derek/", true, $xml); // any? + * assertSelectRegExp("#binder .name", "/Mike|Derek/", 3, $xml); // 3? + * + * @param array $selector + * @param string $pattern + * @param integer $count + * @param mixed $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function assertSelectRegExp($selector, $pattern, $count, $actual, $message = '', $isHtml = true) + { + self::assertSelectEquals( + $selector, "regexp:$pattern", $count, $actual, $message, $isHtml + ); + } + + /** + * assertSelectEquals("#binder .name", "Chuck", true, $xml); // any? + * assertSelectEquals("#binder .name", "Chuck", false, $xml); // none? + * + * @param array $selector + * @param string $content + * @param integer $count + * @param mixed $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function assertSelectEquals($selector, $content, $count, $actual, $message = '', $isHtml = true) + { + $tags = PHPUnit_Util_XML::cssSelect( + $selector, $content, $actual, $isHtml + ); + + // assert specific number of elements + if (is_numeric($count)) { + $counted = $tags ? count($tags) : 0; + self::assertEquals($count, $counted, $message); + } + + // assert any elements exist if true, assert no elements exist if false + else if (is_bool($count)) { + $any = count($tags) > 0 && $tags[0] instanceof DOMNode; + + if ($count) { + self::assertTrue($any, $message); + } else { + self::assertFalse($any, $message); + } + } + + // check for range number of elements + else if (is_array($count) && + (isset($count['>']) || isset($count['<']) || + isset($count['>=']) || isset($count['<=']))) { + $counted = $tags ? count($tags) : 0; + + if (isset($count['>'])) { + self::assertTrue($counted > $count['>'], $message); + } + + if (isset($count['>='])) { + self::assertTrue($counted >= $count['>='], $message); + } + + if (isset($count['<'])) { + self::assertTrue($counted < $count['<'], $message); + } + + if (isset($count['<='])) { + self::assertTrue($counted <= $count['<='], $message); + } + } else { + throw new PHPUnit_Framework_Exception; + } + } + + /** + * Evaluate an HTML or XML string and assert its structure and/or contents. + * + * The first argument ($matcher) is an associative array that specifies the + * match criteria for the assertion: + * + * - `id` : the node with the given id attribute must match the + * corresponding value. + * - `tag` : the node type must match the corresponding value. + * - `attributes` : a hash. The node's attributes must match the + * corresponding values in the hash. + * - `content` : The text content must match the given value. + * - `parent` : a hash. The node's parent must match the + * corresponding hash. + * - `child` : a hash. At least one of the node's immediate children + * must meet the criteria described by the hash. + * - `ancestor` : a hash. At least one of the node's ancestors must + * meet the criteria described by the hash. + * - `descendant` : a hash. At least one of the node's descendants must + * meet the criteria described by the hash. + * - `children` : a hash, for counting children of a node. + * Accepts the keys: + * - `count` : a number which must equal the number of children + * that match + * - `less_than` : the number of matching children must be greater + * than this number + * - `greater_than` : the number of matching children must be less than + * this number + * - `only` : another hash consisting of the keys to use to match + * on the children, and only matching children will be + * counted + * + * + * // Matcher that asserts that there is an element with an id="my_id". + * $matcher = array('id' => 'my_id'); + * + * // Matcher that asserts that there is a "span" tag. + * $matcher = array('tag' => 'span'); + * + * // Matcher that asserts that there is a "span" tag with the content + * // "Hello World". + * $matcher = array('tag' => 'span', 'content' => 'Hello World'); + * + * // Matcher that asserts that there is a "span" tag with content matching + * // the regular expression pattern. + * $matcher = array('tag' => 'span', 'content' => 'regexp:/Try P(HP|ython)/'); + * + * // Matcher that asserts that there is a "span" with an "list" class + * // attribute. + * $matcher = array( + * 'tag' => 'span', + * 'attributes' => array('class' => 'list') + * ); + * + * // Matcher that asserts that there is a "span" inside of a "div". + * $matcher = array( + * 'tag' => 'span', + * 'parent' => array('tag' => 'div') + * ); + * + * // Matcher that asserts that there is a "span" somewhere inside a + * // "table". + * $matcher = array( + * 'tag' => 'span', + * 'ancestor' => array('tag' => 'table') + * ); + * + * // Matcher that asserts that there is a "span" with at least one "em" + * // child. + * $matcher = array( + * 'tag' => 'span', + * 'child' => array('tag' => 'em') + * ); + * + * // Matcher that asserts that there is a "span" containing a (possibly + * // nested) "strong" tag. + * $matcher = array( + * 'tag' => 'span', + * 'descendant' => array('tag' => 'strong') + * ); + * + * // Matcher that asserts that there is a "span" containing 5-10 "em" tags + * // as immediate children. + * $matcher = array( + * 'tag' => 'span', + * 'children' => array( + * 'less_than' => 11, + * 'greater_than' => 4, + * 'only' => array('tag' => 'em') + * ) + * ); + * + * // Matcher that asserts that there is a "div", with an "ul" ancestor and + * // a "li" parent (with class="enum"), and containing a "span" descendant + * // that contains an element with id="my_test" and the text "Hello World". + * $matcher = array( + * 'tag' => 'div', + * 'ancestor' => array('tag' => 'ul'), + * 'parent' => array( + * 'tag' => 'li', + * 'attributes' => array('class' => 'enum') + * ), + * 'descendant' => array( + * 'tag' => 'span', + * 'child' => array( + * 'id' => 'my_test', + * 'content' => 'Hello World' + * ) + * ) + * ); + * + * // Use assertTag() to apply a $matcher to a piece of $html. + * $this->assertTag($matcher, $html); + * + * // Use assertTag() to apply a $matcher to a piece of $xml. + * $this->assertTag($matcher, $xml, '', false); + * + * + * The second argument ($actual) is a string containing either HTML or + * XML text to be tested. + * + * The third argument ($message) is an optional message that will be + * used if the assertion fails. + * + * The fourth argument ($html) is an optional flag specifying whether + * to load the $actual string into a DOMDocument using the HTML or + * XML load strategy. It is true by default, which assumes the HTML + * load strategy. In many cases, this will be acceptable for XML as well. + * + * @param array $matcher + * @param string $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function assertTag($matcher, $actual, $message = '', $isHtml = true) + { + $dom = PHPUnit_Util_XML::load($actual, $isHtml); + $tags = PHPUnit_Util_XML::findNodes($dom, $matcher, $isHtml); + $matched = count($tags) > 0 && $tags[0] instanceof DOMNode; + + self::assertTrue($matched, $message); + } + + /** + * This assertion is the exact opposite of assertTag(). + * + * Rather than asserting that $matcher results in a match, it asserts that + * $matcher does not match. + * + * @param array $matcher + * @param string $actual + * @param string $message + * @param boolean $isHtml + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function assertNotTag($matcher, $actual, $message = '', $isHtml = true) + { + $dom = PHPUnit_Util_XML::load($actual, $isHtml); + $tags = PHPUnit_Util_XML::findNodes($dom, $matcher, $isHtml); + $matched = count($tags) > 0 && $tags[0] instanceof DOMNode; + + self::assertFalse($matched, $message); + } + + /** + * Evaluates a PHPUnit_Framework_Constraint matcher object. + * + * @param mixed $value + * @param PHPUnit_Framework_Constraint $constraint + * @param string $message + * @since Method available since Release 3.0.0 + */ + public static function assertThat($value, PHPUnit_Framework_Constraint $constraint, $message = '') + { + self::$count += count($constraint); + + $constraint->evaluate($value, $message); + } + + /** + * Asserts that a string is a valid JSON string. + * + * @param string $actualJson + * @param string $message + * @since Method available since Release 3.7.20 + */ + public static function assertJson($actualJson, $message = '') + { + if (!is_string($actualJson)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + self::assertThat($actualJson, self::isJson(), $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are equal. + * + * @param string $expectedJson + * @param string $actualJson + * @param string $message + */ + public static function assertJsonStringEqualsJsonString($expectedJson, $actualJson, $message = '') + { + self::assertJson($expectedJson, $message); + self::assertJson($actualJson, $message); + + $expected = json_decode($expectedJson); + $actual = json_decode($actualJson); + + self::assertEquals($expected, $actual, $message); + } + + /** + * Asserts that two given JSON encoded objects or arrays are not equal. + * + * @param string $expectedJson + * @param string $actualJson + * @param string $message + */ + public static function assertJsonStringNotEqualsJsonString($expectedJson, $actualJson, $message = '') + { + self::assertJson($expectedJson, $message); + self::assertJson($actualJson, $message); + + $expected = json_decode($expectedJson); + $actual = json_decode($actualJson); + + self::assertNotEquals($expected, $actual, $message); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are equal. + * + * @param string $expectedFile + * @param string $actualJson + * @param string $message + */ + public static function assertJsonStringEqualsJsonFile($expectedFile, $actualJson, $message = '') + { + self::assertFileExists($expectedFile, $message); + $expectedJson = file_get_contents($expectedFile); + + self::assertJson($expectedJson, $message); + self::assertJson($actualJson, $message); + + // call constraint + $constraint = new PHPUnit_Framework_Constraint_JsonMatches( + $expectedJson + ); + + self::assertThat($actualJson, $constraint, $message); + } + + /** + * Asserts that the generated JSON encoded object and the content of the given file are not equal. + * + * @param string $expectedFile + * @param string $actualJson + * @param string $message + */ + public static function assertJsonStringNotEqualsJsonFile($expectedFile, $actualJson, $message = '') + { + self::assertFileExists($expectedFile, $message); + $expectedJson = file_get_contents($expectedFile); + + self::assertJson($expectedJson, $message); + self::assertJson($actualJson, $message); + + // call constraint + $constraint = new PHPUnit_Framework_Constraint_JsonMatches( + $expectedJson + ); + + self::assertThat($actualJson, new PHPUnit_Framework_Constraint_Not($constraint), $message); + } + + /** + * Asserts that two JSON files are not equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + */ + public static function assertJsonFileNotEqualsJsonFile($expectedFile, $actualFile, $message = '') + { + self::assertFileExists($expectedFile, $message); + self::assertFileExists($actualFile, $message); + + $actualJson = file_get_contents($actualFile); + $expectedJson = file_get_contents($expectedFile); + + self::assertJson($expectedJson, $message); + self::assertJson($actualJson, $message); + + // call constraint + $constraintExpected = new PHPUnit_Framework_Constraint_JsonMatches( + $expectedJson + ); + + $constraintActual = new PHPUnit_Framework_Constraint_JsonMatches($actualJson); + + self::assertThat($expectedJson, new PHPUnit_Framework_Constraint_Not($constraintActual), $message); + self::assertThat($actualJson, new PHPUnit_Framework_Constraint_Not($constraintExpected), $message); + } + + /** + * Asserts that two JSON files are equal. + * + * @param string $expectedFile + * @param string $actualFile + * @param string $message + */ + public static function assertJsonFileEqualsJsonFile($expectedFile, $actualFile, $message = '') + { + self::assertFileExists($expectedFile, $message); + self::assertFileExists($actualFile, $message); + + $actualJson = file_get_contents($actualFile); + $expectedJson = file_get_contents($expectedFile); + + self::assertJson($expectedJson, $message); + self::assertJson($actualJson, $message); + + // call constraint + $constraintExpected = new PHPUnit_Framework_Constraint_JsonMatches( + $expectedJson + ); + + $constraintActual = new PHPUnit_Framework_Constraint_JsonMatches($actualJson); + + self::assertThat($expectedJson, $constraintActual, $message); + self::assertThat($actualJson, $constraintExpected, $message); + } + + /** + * Returns a PHPUnit_Framework_Constraint_And matcher object. + * + * @return PHPUnit_Framework_Constraint_And + * @since Method available since Release 3.0.0 + */ + public static function logicalAnd() + { + $constraints = func_get_args(); + + $constraint = new PHPUnit_Framework_Constraint_And; + $constraint->setConstraints($constraints); + + return $constraint; + } + + /** + * Returns a PHPUnit_Framework_Constraint_Or matcher object. + * + * @return PHPUnit_Framework_Constraint_Or + * @since Method available since Release 3.0.0 + */ + public static function logicalOr() + { + $constraints = func_get_args(); + + $constraint = new PHPUnit_Framework_Constraint_Or; + $constraint->setConstraints($constraints); + + return $constraint; + } + + /** + * Returns a PHPUnit_Framework_Constraint_Not matcher object. + * + * @param PHPUnit_Framework_Constraint $constraint + * @return PHPUnit_Framework_Constraint_Not + * @since Method available since Release 3.0.0 + */ + public static function logicalNot(PHPUnit_Framework_Constraint $constraint) + { + return new PHPUnit_Framework_Constraint_Not($constraint); + } + + /** + * Returns a PHPUnit_Framework_Constraint_Xor matcher object. + * + * @return PHPUnit_Framework_Constraint_Xor + * @since Method available since Release 3.0.0 + */ + public static function logicalXor() + { + $constraints = func_get_args(); + + $constraint = new PHPUnit_Framework_Constraint_Xor; + $constraint->setConstraints($constraints); + + return $constraint; + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsAnything matcher object. + * + * @return PHPUnit_Framework_Constraint_IsAnything + * @since Method available since Release 3.0.0 + */ + public static function anything() + { + return new PHPUnit_Framework_Constraint_IsAnything; + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsTrue matcher object. + * + * @return PHPUnit_Framework_Constraint_IsTrue + * @since Method available since Release 3.3.0 + */ + public static function isTrue() + { + return new PHPUnit_Framework_Constraint_IsTrue; + } + + /** + * Returns a PHPUnit_Framework_Constraint_Callback matcher object. + * + * @param callable $callback + * @return PHPUnit_Framework_Constraint_Callback + */ + public static function callback($callback) + { + return new PHPUnit_Framework_Constraint_Callback($callback); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsFalse matcher object. + * + * @return PHPUnit_Framework_Constraint_IsFalse + * @since Method available since Release 3.3.0 + */ + public static function isFalse() + { + return new PHPUnit_Framework_Constraint_IsFalse; + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsJson matcher object. + * + * @return PHPUnit_Framework_Constraint_IsJson + * @since Method available since Release 3.7.20 + */ + public static function isJson() + { + return new PHPUnit_Framework_Constraint_IsJson; + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsNull matcher object. + * + * @return PHPUnit_Framework_Constraint_IsNull + * @since Method available since Release 3.3.0 + */ + public static function isNull() + { + return new PHPUnit_Framework_Constraint_IsNull; + } + + /** + * Returns a PHPUnit_Framework_Constraint_Attribute matcher object. + * + * @param PHPUnit_Framework_Constraint $constraint + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_Attribute + * @since Method available since Release 3.1.0 + */ + public static function attribute(PHPUnit_Framework_Constraint $constraint, $attributeName) + { + return new PHPUnit_Framework_Constraint_Attribute( + $constraint, $attributeName + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_TraversableContains matcher + * object. + * + * @param mixed $value + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @return PHPUnit_Framework_Constraint_TraversableContains + * @since Method available since Release 3.0.0 + */ + public static function contains($value, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) + { + return new PHPUnit_Framework_Constraint_TraversableContains($value, $checkForObjectIdentity, $checkForNonObjectIdentity); + } + + /** + * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher + * object. + * + * @param string $type + * @return PHPUnit_Framework_Constraint_TraversableContainsOnly + * @since Method available since Release 3.1.4 + */ + public static function containsOnly($type) + { + return new PHPUnit_Framework_Constraint_TraversableContainsOnly($type); + } + + /** + * Returns a PHPUnit_Framework_Constraint_TraversableContainsOnly matcher + * object. + * + * @param string $classname + * @return PHPUnit_Framework_Constraint_TraversableContainsOnly + */ + public static function containsOnlyInstancesOf($classname) + { + return new PHPUnit_Framework_Constraint_TraversableContainsOnly($classname, false); + } + + /** + * Returns a PHPUnit_Framework_Constraint_ArrayHasKey matcher object. + * + * @param mixed $key + * @return PHPUnit_Framework_Constraint_ArrayHasKey + * @since Method available since Release 3.0.0 + */ + public static function arrayHasKey($key) + { + return new PHPUnit_Framework_Constraint_ArrayHasKey($key); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object. + * + * @param mixed $value + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @return PHPUnit_Framework_Constraint_IsEqual + * @since Method available since Release 3.0.0 + */ + public static function equalTo($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + return new PHPUnit_Framework_Constraint_IsEqual( + $value, $delta, $maxDepth, $canonicalize, $ignoreCase + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsEqual matcher object + * that is wrapped in a PHPUnit_Framework_Constraint_Attribute matcher + * object. + * + * @param string $attributeName + * @param mixed $value + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @return PHPUnit_Framework_Constraint_Attribute + * @since Method available since Release 3.1.0 + */ + public static function attributeEqualTo($attributeName, $value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + return self::attribute( + self::equalTo( + $value, $delta, $maxDepth, $canonicalize, $ignoreCase + ), + $attributeName + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsEmpty matcher object. + * + * @return PHPUnit_Framework_Constraint_IsEmpty + * @since Method available since Release 3.5.0 + */ + public static function isEmpty() + { + return new PHPUnit_Framework_Constraint_IsEmpty; + } + + /** + * Returns a PHPUnit_Framework_Constraint_FileExists matcher object. + * + * @return PHPUnit_Framework_Constraint_FileExists + * @since Method available since Release 3.0.0 + */ + public static function fileExists() + { + return new PHPUnit_Framework_Constraint_FileExists; + } + + /** + * Returns a PHPUnit_Framework_Constraint_GreaterThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_GreaterThan + * @since Method available since Release 3.0.0 + */ + public static function greaterThan($value) + { + return new PHPUnit_Framework_Constraint_GreaterThan($value); + } + + /** + * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps + * a PHPUnit_Framework_Constraint_IsEqual and a + * PHPUnit_Framework_Constraint_GreaterThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_Or + * @since Method available since Release 3.1.0 + */ + public static function greaterThanOrEqual($value) + { + return self::logicalOr( + new PHPUnit_Framework_Constraint_IsEqual($value), + new PHPUnit_Framework_Constraint_GreaterThan($value) + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_ClassHasAttribute matcher object. + * + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_ClassHasAttribute + * @since Method available since Release 3.1.0 + */ + public static function classHasAttribute($attributeName) + { + return new PHPUnit_Framework_Constraint_ClassHasAttribute( + $attributeName + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_ClassHasStaticAttribute matcher + * object. + * + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_ClassHasStaticAttribute + * @since Method available since Release 3.1.0 + */ + public static function classHasStaticAttribute($attributeName) + { + return new PHPUnit_Framework_Constraint_ClassHasStaticAttribute( + $attributeName + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_ObjectHasAttribute matcher object. + * + * @param string $attributeName + * @return PHPUnit_Framework_Constraint_ObjectHasAttribute + * @since Method available since Release 3.0.0 + */ + public static function objectHasAttribute($attributeName) + { + return new PHPUnit_Framework_Constraint_ObjectHasAttribute( + $attributeName + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsIdentical matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_IsIdentical + * @since Method available since Release 3.0.0 + */ + public static function identicalTo($value) + { + return new PHPUnit_Framework_Constraint_IsIdentical($value); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsInstanceOf matcher object. + * + * @param string $className + * @return PHPUnit_Framework_Constraint_IsInstanceOf + * @since Method available since Release 3.0.0 + */ + public static function isInstanceOf($className) + { + return new PHPUnit_Framework_Constraint_IsInstanceOf($className); + } + + /** + * Returns a PHPUnit_Framework_Constraint_IsType matcher object. + * + * @param string $type + * @return PHPUnit_Framework_Constraint_IsType + * @since Method available since Release 3.0.0 + */ + public static function isType($type) + { + return new PHPUnit_Framework_Constraint_IsType($type); + } + + /** + * Returns a PHPUnit_Framework_Constraint_LessThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_LessThan + * @since Method available since Release 3.0.0 + */ + public static function lessThan($value) + { + return new PHPUnit_Framework_Constraint_LessThan($value); + } + + /** + * Returns a PHPUnit_Framework_Constraint_Or matcher object that wraps + * a PHPUnit_Framework_Constraint_IsEqual and a + * PHPUnit_Framework_Constraint_LessThan matcher object. + * + * @param mixed $value + * @return PHPUnit_Framework_Constraint_Or + * @since Method available since Release 3.1.0 + */ + public static function lessThanOrEqual($value) + { + return self::logicalOr( + new PHPUnit_Framework_Constraint_IsEqual($value), + new PHPUnit_Framework_Constraint_LessThan($value) + ); + } + + /** + * Returns a PHPUnit_Framework_Constraint_PCREMatch matcher object. + * + * @param string $pattern + * @return PHPUnit_Framework_Constraint_PCREMatch + * @since Method available since Release 3.0.0 + */ + public static function matchesRegularExpression($pattern) + { + return new PHPUnit_Framework_Constraint_PCREMatch($pattern); + } + + /** + * Returns a PHPUnit_Framework_Constraint_StringMatches matcher object. + * + * @param string $string + * @return PHPUnit_Framework_Constraint_StringMatches + * @since Method available since Release 3.5.0 + */ + public static function matches($string) + { + return new PHPUnit_Framework_Constraint_StringMatches($string); + } + + /** + * Returns a PHPUnit_Framework_Constraint_StringStartsWith matcher object. + * + * @param mixed $prefix + * @return PHPUnit_Framework_Constraint_StringStartsWith + * @since Method available since Release 3.4.0 + */ + public static function stringStartsWith($prefix) + { + return new PHPUnit_Framework_Constraint_StringStartsWith($prefix); + } + + /** + * Returns a PHPUnit_Framework_Constraint_StringContains matcher object. + * + * @param string $string + * @param boolean $case + * @return PHPUnit_Framework_Constraint_StringContains + * @since Method available since Release 3.0.0 + */ + public static function stringContains($string, $case = true) + { + return new PHPUnit_Framework_Constraint_StringContains($string, $case); + } + + /** + * Returns a PHPUnit_Framework_Constraint_StringEndsWith matcher object. + * + * @param mixed $suffix + * @return PHPUnit_Framework_Constraint_StringEndsWith + * @since Method available since Release 3.4.0 + */ + public static function stringEndsWith($suffix) + { + return new PHPUnit_Framework_Constraint_StringEndsWith($suffix); + } + + /** + * Returns a PHPUnit_Framework_Constraint_Count matcher object. + * + * @param int $count + * @return PHPUnit_Framework_Constraint_Count + */ + public static function countOf($count) + { + return new PHPUnit_Framework_Constraint_Count($count); + } + /** + * Fails a test with the given message. + * + * @param string $message + * @throws PHPUnit_Framework_AssertionFailedError + */ + public static function fail($message = '') + { + throw new PHPUnit_Framework_AssertionFailedError($message); + } + + /** + * Returns the value of an attribute of a class or an object. + * This also works for attributes that are declared protected or private. + * + * @param mixed $classOrObject + * @param string $attributeName + * @return mixed + * @throws PHPUnit_Framework_Exception + */ + public static function readAttribute($classOrObject, $attributeName) + { + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'valid attribute name'); + } + + if (is_string($classOrObject)) { + if (!class_exists($classOrObject)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'class name' + ); + } + + return self::getStaticAttribute( + $classOrObject, + $attributeName + ); + } elseif (is_object($classOrObject)) { + return self::getObjectAttribute( + $classOrObject, + $attributeName + ); + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'class name or object' + ); + } + } + + /** + * Returns the value of a static attribute. + * This also works for attributes that are declared protected or private. + * + * @param string $className + * @param string $attributeName + * @return mixed + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 4.0.0 + */ + public static function getStaticAttribute($className, $attributeName) + { + if (!is_string($className)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!class_exists($className)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'class name'); + } + + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'valid attribute name'); + } + + $class = new ReflectionClass($className); + + while ($class) { + $attributes = $class->getStaticProperties(); + + if (array_key_exists($attributeName, $attributes)) { + return $attributes[$attributeName]; + } + + $class = $class->getParentClass(); + } + + throw new PHPUnit_Framework_Exception( + sprintf( + 'Attribute "%s" not found in class.', + $attributeName + ) + ); + } + + /** + * Returns the value of an object's attribute. + * This also works for attributes that are declared protected or private. + * + * @param object $object + * @param string $attributeName + * @return mixed + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 4.0.0 + */ + public static function getObjectAttribute($object, $attributeName) + { + if (!is_object($object)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'object'); + } + + if (!is_string($attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'string'); + } + + if (!preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $attributeName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'valid attribute name'); + } + + try { + $attribute = new ReflectionProperty($object, $attributeName); + } catch (ReflectionException $e) { + $reflector = new ReflectionObject($object); + + while ($reflector = $reflector->getParentClass()) { + try { + $attribute = $reflector->getProperty($attributeName); + break; + } catch (ReflectionException $e) { + } + } + } + + if (isset($attribute)) { + if (!$attribute || $attribute->isPublic()) { + return $object->$attributeName; + } + + $attribute->setAccessible(true); + $value = $attribute->getValue($object); + $attribute->setAccessible(false); + + return $value; + } + + throw new PHPUnit_Framework_Exception( + sprintf( + 'Attribute "%s" not found in object.', + $attributeName + ) + ); + } + + /** + * Mark the test as incomplete. + * + * @param string $message + * @throws PHPUnit_Framework_IncompleteTestError + * @since Method available since Release 3.0.0 + */ + public static function markTestIncomplete($message = '') + { + throw new PHPUnit_Framework_IncompleteTestError($message); + } + + /** + * Mark the test as skipped. + * + * @param string $message + * @throws PHPUnit_Framework_SkippedTestError + * @since Method available since Release 3.0.0 + */ + public static function markTestSkipped($message = '') + { + throw new PHPUnit_Framework_SkippedTestError($message); + } + + /** + * Return the current assertion count. + * + * @return integer + * @since Method available since Release 3.3.3 + */ + public static function getCount() + { + return self::$count; + } + + /** + * Reset the assertion counter. + * + * @since Method available since Release 3.3.3 + */ + public static function resetCount() + { + self::$count = 0; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * A marker interface for marking a unit test as being skipped. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 3.0.0 + */ +interface PHPUnit_Framework_SkippedTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A warning. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Framework_Warning extends PHPUnit_Framework_TestCase +{ + /** + * @var string + */ + protected $message = ''; + + /** + * @var boolean + */ + protected $backupGlobals = false; + + /** + * @var boolean + */ + protected $backupStaticAttributes = false; + + /** + * @var boolean + */ + protected $runTestInSeparateProcess = false; + + /** + * @var boolean + */ + protected $useErrorHandler = false; + + /** + * @param string $message + */ + public function __construct($message = '') + { + $this->message = $message; + parent::__construct('Warning'); + } + + /** + * @throws PHPUnit_Framework_Exception + */ + protected function runTest() + { + $this->fail($this->message); + } + + /** + * @return string + * @since Method available since Release 3.0.0 + */ + public function getMessage() + { + return $this->message; + } + + /** + * Returns a string representation of the test case. + * + * @return string + * @since Method available since Release 3.4.0 + */ + public function toString() + { + return 'Warning'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_TestSuite + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_TestSuite + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +class PHPUnit_Framework_TestSuite_DataProvider extends PHPUnit_Framework_TestSuite +{ + /** + * Sets the dependencies of a TestCase. + * + * @param array $dependencies + */ + public function setDependencies(array $dependencies) + { + foreach ($this->tests as $test) { + $test->setDependencies($dependencies); + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * A marker interface for marking any exception/error as result of an unit + * test as risky. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 4.0.0 + */ +interface PHPUnit_Framework_RiskyTest +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A TestCase defines the fixture to run multiple tests. + * + * To define a TestCase + * + * 1) Implement a subclass of PHPUnit_Framework_TestCase. + * 2) Define instance variables that store the state of the fixture. + * 3) Initialize the fixture state by overriding setUp(). + * 4) Clean-up after a test by overriding tearDown(). + * + * Each test runs in its own fixture so there can be no side effects + * among test runs. + * + * Here is an example: + * + * + * value1 = 2; + * $this->value2 = 3; + * } + * } + * ?> + * + * + * For each test implement a method which interacts with the fixture. + * Verify the expected results with assertions specified by calling + * assert with a boolean. + * + * + * assertTrue($this->value1 + $this->value2 == 5); + * } + * ?> + * + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +abstract class PHPUnit_Framework_TestCase extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing +{ + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * Overwrite this attribute in a child class of TestCase. + * Setting this attribute in setUp() has no effect! + * + * @var boolean + */ + protected $backupGlobals = null; + + /** + * @var array + */ + protected $backupGlobalsBlacklist = array(); + + /** + * Enable or disable the backup and restoration of static attributes. + * Overwrite this attribute in a child class of TestCase. + * Setting this attribute in setUp() has no effect! + * + * @var boolean + */ + protected $backupStaticAttributes = null; + + /** + * @var array + */ + protected $backupStaticAttributesBlacklist = array(); + + /** + * Whether or not this test is to be run in a separate PHP process. + * + * @var boolean + */ + protected $runTestInSeparateProcess = null; + + /** + * Whether or not this test should preserve the global state when + * running in a separate PHP process. + * + * @var boolean + */ + protected $preserveGlobalState = true; + + /** + * Whether or not this test is running in a separate PHP process. + * + * @var boolean + */ + private $inIsolation = false; + + /** + * @var array + */ + private $data = array(); + + /** + * @var string + */ + private $dataName = ''; + + /** + * @var boolean + */ + private $useErrorHandler = null; + + /** + * The name of the expected Exception. + * + * @var mixed + */ + private $expectedException = null; + + /** + * The message of the expected Exception. + * + * @var string + */ + private $expectedExceptionMessage = ''; + + /** + * The code of the expected Exception. + * + * @var integer + */ + private $expectedExceptionCode; + + /** + * The required preconditions for a test. + * + * @var array + */ + private $required = array( + 'PHP' => null, + 'PHPUnit' => null, + 'OS' => null, + 'functions' => array(), + 'extensions' => array() + ); + + /** + * The name of the test case. + * + * @var string + */ + private $name = null; + + /** + * @var array + */ + private $dependencies = array(); + + /** + * @var array + */ + private $dependencyInput = array(); + + /** + * @var array + */ + private $iniSettings = array(); + + /** + * @var array + */ + private $locale = array(); + + /** + * @var array + */ + private $mockObjects = array(); + + /** + * @var array + */ + private $mockObjectGenerator = null; + + /** + * @var integer + */ + private $status; + + /** + * @var string + */ + private $statusMessage = ''; + + /** + * @var integer + */ + private $numAssertions = 0; + + /** + * @var PHPUnit_Framework_TestResult + */ + private $result; + + /** + * @var mixed + */ + private $testResult; + + /** + * @var string + */ + private $output = ''; + + /** + * @var string + */ + private $outputExpectedRegex = null; + + /** + * @var string + */ + private $outputExpectedString = null; + + /** + * @var bool + */ + private $hasPerformedExpectationsOnOutput = false; + + /** + * @var mixed + */ + private $outputCallback = false; + + /** + * @var boolean + */ + private $outputBufferingActive = false; + + /** + * Constructs a test case with the given name. + * + * @param string $name + * @param array $data + * @param string $dataName + */ + public function __construct($name = null, array $data = array(), $dataName = '') + { + if ($name !== null) { + $this->setName($name); + } + + $this->data = $data; + $this->dataName = $dataName; + } + + /** + * Returns a string representation of the test case. + * + * @return string + */ + public function toString() + { + $class = new ReflectionClass($this); + + $buffer = sprintf( + '%s::%s', + + $class->name, + $this->getName(false) + ); + + return $buffer . $this->getDataSetAsString(); + } + + /** + * Counts the number of test cases executed by run(TestResult result). + * + * @return integer + */ + public function count() + { + return 1; + } + + /** + * Returns the annotations for this test. + * + * @return array + * @since Method available since Release 3.4.0 + */ + public function getAnnotations() + { + return PHPUnit_Util_Test::parseTestMethodAnnotations( + get_class($this), $this->name + ); + } + + /** + * Gets the name of a TestCase. + * + * @param boolean $withDataSet + * @return string + */ + public function getName($withDataSet = true) + { + if ($withDataSet) { + return $this->name . $this->getDataSetAsString(false); + } else { + return $this->name; + } + } + + /** + * Returns the size of the test. + * + * @return integer + * @since Method available since Release 3.6.0 + */ + public function getSize() + { + return PHPUnit_Util_Test::getSize( + get_class($this), $this->getName(false) + ); + } + + /** + * @return string + * @since Method available since Release 3.6.0 + */ + public function getActualOutput() + { + if (!$this->outputBufferingActive) { + return $this->output; + } else { + return ob_get_contents(); + } + } + + /** + * @return boolean + * @since Method available since Release 3.6.0 + */ + public function hasOutput() + { + if (strlen($this->output) === 0) { + return false; + } + + if ($this->outputExpectedString !== null || + $this->outputExpectedRegex !== null || + $this->hasPerformedExpectationsOnOutput) { + return false; + } + + return true; + } + + /** + * @param string $expectedRegex + * @since Method available since Release 3.6.0 + * @throws PHPUnit_Framework_Exception + */ + public function expectOutputRegex($expectedRegex) + { + if ($this->outputExpectedString !== null) { + throw new PHPUnit_Framework_Exception; + } + + if (is_string($expectedRegex) || is_null($expectedRegex)) { + $this->outputExpectedRegex = $expectedRegex; + } + } + + /** + * @param string $expectedString + * @since Method available since Release 3.6.0 + */ + public function expectOutputString($expectedString) + { + if ($this->outputExpectedRegex !== null) { + throw new PHPUnit_Framework_Exception; + } + + if (is_string($expectedString) || is_null($expectedString)) { + $this->outputExpectedString = $expectedString; + } + } + + /** + * @return bool + * @since Method available since Release 3.6.5 + */ + public function hasPerformedExpectationsOnOutput() + { + return $this->hasPerformedExpectationsOnOutput; + } + + /** + * @return string + * @since Method available since Release 3.2.0 + */ + public function getExpectedException() + { + return $this->expectedException; + } + + /** + * @param mixed $exceptionName + * @param string $exceptionMessage + * @param integer $exceptionCode + * @since Method available since Release 3.2.0 + */ + public function setExpectedException($exceptionName, $exceptionMessage = '', $exceptionCode = null) + { + $this->expectedException = $exceptionName; + $this->expectedExceptionMessage = $exceptionMessage; + $this->expectedExceptionCode = $exceptionCode; + } + + /** + * @since Method available since Release 3.4.0 + */ + protected function setExpectedExceptionFromAnnotation() + { + try { + $expectedException = PHPUnit_Util_Test::getExpectedException( + get_class($this), $this->name + ); + + if ($expectedException !== false) { + $this->setExpectedException( + $expectedException['class'], + $expectedException['message'], + $expectedException['code'] + ); + } + } catch (ReflectionException $e) { + } + } + + /** + * @param boolean $useErrorHandler + * @since Method available since Release 3.4.0 + */ + public function setUseErrorHandler($useErrorHandler) + { + $this->useErrorHandler = $useErrorHandler; + } + + /** + * @since Method available since Release 3.4.0 + */ + protected function setUseErrorHandlerFromAnnotation() + { + try { + $useErrorHandler = PHPUnit_Util_Test::getErrorHandlerSettings( + get_class($this), $this->name + ); + + if ($useErrorHandler !== null) { + $this->setUseErrorHandler($useErrorHandler); + } + } catch (ReflectionException $e) { + } + } + + /** + * @since Method available since Release 3.6.0 + */ + protected function setRequirementsFromAnnotation() + { + try { + $requirements = PHPUnit_Util_Test::getRequirements( + get_class($this), $this->name + ); + + if (isset($requirements['PHP'])) { + $this->required['PHP'] = $requirements['PHP']; + } + + if (isset($requirements['PHPUnit'])) { + $this->required['PHPUnit'] = $requirements['PHPUnit']; + } + + if (isset($requirements['OS'])) { + $this->required['OS'] = $requirements['OS']; + } + + if (isset($requirements['extensions'])) { + $this->required['extensions'] = $requirements['extensions']; + } + + if (isset($requirements['functions'])) { + $this->required['functions'] = $requirements['functions']; + } + } catch (ReflectionException $e) { + } + } + + /** + * @since Method available since Release 3.6.0 + */ + protected function checkRequirements() + { + $this->setRequirementsFromAnnotation(); + + $missingRequirements = array(); + + if ($this->required['PHP'] && + version_compare(PHP_VERSION, $this->required['PHP'], '<')) { + $missingRequirements[] = sprintf( + 'PHP %s (or later) is required.', + $this->required['PHP'] + ); + } + + $phpunitVersion = PHPUnit_Runner_Version::id(); + if ($this->required['PHPUnit'] && + version_compare($phpunitVersion, $this->required['PHPUnit'], '<')) { + $missingRequirements[] = sprintf( + 'PHPUnit %s (or later) is required.', + $this->required['PHPUnit'] + ); + } + + if ($this->required['OS'] && + !preg_match($this->required['OS'], PHP_OS)) { + $missingRequirements[] = sprintf( + 'Operating system matching %s is required.', + $this->required['OS'] + ); + } + + foreach ($this->required['functions'] as $requiredFunction) { + if (!function_exists($requiredFunction)) { + $missingRequirements[] = sprintf( + 'Function %s is required.', + $requiredFunction + ); + } + } + + foreach ($this->required['extensions'] as $requiredExtension) { + if (!extension_loaded($requiredExtension)) { + $missingRequirements[] = sprintf( + 'Extension %s is required.', + $requiredExtension + ); + } + } + + if ($missingRequirements) { + $this->markTestSkipped( + implode( + PHP_EOL, + $missingRequirements + ) + ); + } + } + + /** + * Returns the status of this test. + * + * @return integer + * @since Method available since Release 3.1.0 + */ + public function getStatus() + { + return $this->status; + } + + /** + * Returns the status message of this test. + * + * @return string + * @since Method available since Release 3.3.0 + */ + public function getStatusMessage() + { + return $this->statusMessage; + } + + /** + * Returns whether or not this test has failed. + * + * @return boolean + * @since Method available since Release 3.0.0 + */ + public function hasFailed() + { + $status = $this->getStatus(); + + return $status == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE || + $status == PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; + } + + /** + * Runs the test case and collects the results in a TestResult object. + * If no TestResult object is passed a new one will be created. + * + * @param PHPUnit_Framework_TestResult $result + * @return PHPUnit_Framework_TestResult + * @throws PHPUnit_Framework_Exception + */ + public function run(PHPUnit_Framework_TestResult $result = null) + { + if ($result === null) { + $result = $this->createResult(); + } + + if (!$this instanceof PHPUnit_Framework_Warning) { + $this->setTestResultObject($result); + $this->setUseErrorHandlerFromAnnotation(); + } + + if ($this->useErrorHandler !== null) { + $oldErrorHandlerSetting = $result->getConvertErrorsToExceptions(); + $result->convertErrorsToExceptions($this->useErrorHandler); + } + + if (!$this instanceof PHPUnit_Framework_Warning && !$this->handleDependencies()) { + return; + } + + if ($this->runTestInSeparateProcess === true && + $this->inIsolation !== true && + !$this instanceof PHPUnit_Extensions_SeleniumTestCase && + !$this instanceof PHPUnit_Extensions_PhptTestCase) { + $class = new ReflectionClass($this); + + $template = new Text_Template( + __DIR__ . '/../Util/PHP/Template/TestCaseMethod.tpl' + ); + + if ($this->preserveGlobalState) { + $constants = PHPUnit_Util_GlobalState::getConstantsAsString(); + $globals = PHPUnit_Util_GlobalState::getGlobalsAsString(); + $includedFiles = PHPUnit_Util_GlobalState::getIncludedFilesAsString(); + $iniSettings = PHPUnit_Util_GlobalState::getIniSettingsAsString(); + } else { + $constants = ''; + $globals = ''; + $includedFiles = ''; + $iniSettings = ''; + } + + $coverage = $result->getCollectCodeCoverageInformation() ? 'true' : 'false'; + $isStrictAboutTestsThatDoNotTestAnything = $result->isStrictAboutTestsThatDoNotTestAnything() ? 'true' : 'false'; + $isStrictAboutOutputDuringTests = $result->isStrictAboutOutputDuringTests() ? 'true' : 'false'; + $isStrictAboutTestSize = $result->isStrictAboutTestSize() ? 'true' : 'false'; + + if (defined('PHPUNIT_COMPOSER_INSTALL')) { + $composerAutoload = var_export(PHPUNIT_COMPOSER_INSTALL, true); + } else { + $composerAutoload = '\'\''; + } + + if (defined('__PHPUNIT_PHAR__')) { + $phar = var_export(__PHPUNIT_PHAR__, true); + } else { + $phar = '\'\''; + } + + $data = var_export(serialize($this->data), true); + $dependencyInput = var_export(serialize($this->dependencyInput), true); + $includePath = var_export(get_include_path(), true); + // must do these fixes because TestCaseMethod.tpl has unserialize('{data}') in it, and we can't break BC + // the lines above used to use addcslashes() rather than var_export(), which breaks null byte escape sequences + $data = "'." . $data . ".'"; + $dependencyInput = "'." . $dependencyInput . ".'"; + $includePath = "'." . $includePath . ".'"; + + $template->setVar( + array( + 'composerAutoload' => $composerAutoload, + 'phar' => $phar, + 'filename' => $class->getFileName(), + 'className' => $class->getName(), + 'methodName' => $this->name, + 'collectCodeCoverageInformation' => $coverage, + 'data' => $data, + 'dataName' => $this->dataName, + 'dependencyInput' => $dependencyInput, + 'constants' => $constants, + 'globals' => $globals, + 'include_path' => $includePath, + 'included_files' => $includedFiles, + 'iniSettings' => $iniSettings, + 'isStrictAboutTestsThatDoNotTestAnything' => $isStrictAboutTestsThatDoNotTestAnything, + 'isStrictAboutOutputDuringTests' => $isStrictAboutOutputDuringTests, + 'isStrictAboutTestSize' => $isStrictAboutTestSize + ) + ); + + $this->prepareTemplate($template); + + $php = PHPUnit_Util_PHP::factory(); + $php->runTestJob($template->render(), $this, $result); + } else { + $result->run($this); + } + + if ($this->useErrorHandler !== null) { + $result->convertErrorsToExceptions($oldErrorHandlerSetting); + } + + $this->result = null; + + return $result; + } + + /** + * Runs the bare test sequence. + */ + public function runBare() + { + $this->numAssertions = 0; + + // Backup the $GLOBALS array and static attributes. + if ($this->runTestInSeparateProcess !== true && + $this->inIsolation !== true) { + if ($this->backupGlobals === null || + $this->backupGlobals === true) { + PHPUnit_Util_GlobalState::backupGlobals( + $this->backupGlobalsBlacklist + ); + } + + if ($this->backupStaticAttributes === true) { + PHPUnit_Util_GlobalState::backupStaticAttributes( + $this->backupStaticAttributesBlacklist + ); + } + } + + // Start output buffering. + ob_start(); + $this->outputBufferingActive = true; + + // Clean up stat cache. + clearstatcache(); + + // Backup the cwd + $currentWorkingDirectory = getcwd(); + + $hookMethods = PHPUnit_Util_Test::getHookMethods(get_class($this)); + + try { + $this->checkRequirements(); + + if ($this->inIsolation) { + foreach ($hookMethods['beforeClass'] as $method) { + $this->$method(); + } + } + + $this->setExpectedExceptionFromAnnotation(); + + foreach ($hookMethods['before'] as $method) { + $this->$method(); + } + + $this->assertPreConditions(); + $this->testResult = $this->runTest(); + $this->verifyMockObjects(); + $this->assertPostConditions(); + $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED; + } catch (PHPUnit_Framework_IncompleteTest $e) { + $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE; + $this->statusMessage = $e->getMessage(); + } catch (PHPUnit_Framework_SkippedTest $e) { + $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED; + $this->statusMessage = $e->getMessage(); + } catch (PHPUnit_Framework_AssertionFailedError $e) { + $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE; + $this->statusMessage = $e->getMessage(); + } catch (Exception $e) { + $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; + $this->statusMessage = $e->getMessage(); + } + + // Clean up the mock objects. + $this->mockObjects = array(); + + // Tear down the fixture. An exception raised in tearDown() will be + // caught and passed on when no exception was raised before. + try { + foreach ($hookMethods['after'] as $method) { + $this->$method(); + } + + if ($this->inIsolation) { + foreach ($hookMethods['afterClass'] as $method) { + $this->$method(); + } + } + } catch (Exception $_e) { + if (!isset($e)) { + $e = $_e; + } + } + + // Stop output buffering. + if ($this->outputCallback === false) { + $this->output = ob_get_contents(); + } else { + $this->output = call_user_func_array( + $this->outputCallback, array(ob_get_contents()) + ); + } + + ob_end_clean(); + $this->outputBufferingActive = false; + + // Clean up stat cache. + clearstatcache(); + + // Restore the cwd if it was changed by the test + if ($currentWorkingDirectory != getcwd()) { + chdir($currentWorkingDirectory); + } + + // Restore the $GLOBALS array and static attributes. + if ($this->runTestInSeparateProcess !== true && + $this->inIsolation !== true) { + if ($this->backupGlobals === null || + $this->backupGlobals === true) { + PHPUnit_Util_GlobalState::restoreGlobals( + $this->backupGlobalsBlacklist + ); + } + + if ($this->backupStaticAttributes === true) { + PHPUnit_Util_GlobalState::restoreStaticAttributes(); + } + } + + // Clean up INI settings. + foreach ($this->iniSettings as $varName => $oldValue) { + ini_set($varName, $oldValue); + } + + $this->iniSettings = array(); + + // Clean up locale settings. + foreach ($this->locale as $category => $locale) { + setlocale($category, $locale); + } + + // Perform assertion on output. + if (!isset($e)) { + try { + if ($this->outputExpectedRegex !== null) { + $this->hasPerformedExpectationsOnOutput = true; + $this->assertRegExp($this->outputExpectedRegex, $this->output); + $this->outputExpectedRegex = null; + } elseif ($this->outputExpectedString !== null) { + $this->hasPerformedExpectationsOnOutput = true; + $this->assertEquals($this->outputExpectedString, $this->output); + $this->outputExpectedString = null; + } + } catch (Exception $_e) { + $e = $_e; + } + } + + // Workaround for missing "finally". + if (isset($e)) { + $this->onNotSuccessfulTest($e); + } + } + + /** + * Override to run the test and assert its state. + * + * @return mixed + * @throws Exception|PHPUnit_Framework_Exception + * @throws PHPUnit_Framework_Exception + */ + protected function runTest() + { + if ($this->name === null) { + throw new PHPUnit_Framework_Exception( + 'PHPUnit_Framework_TestCase::$name must not be null.' + ); + } + + try { + $class = new ReflectionClass($this); + $method = $class->getMethod($this->name); + } catch (ReflectionException $e) { + $this->fail($e->getMessage()); + } + + try { + $testResult = $method->invokeArgs( + $this, array_merge($this->data, $this->dependencyInput) + ); + } catch (Exception $e) { + $checkException = false; + + if (is_string($this->expectedException)) { + $checkException = true; + + if ($e instanceof PHPUnit_Framework_Exception) { + $checkException = false; + } + + $reflector = new ReflectionClass($this->expectedException); + + if ($this->expectedException == 'PHPUnit_Framework_Exception' || + $reflector->isSubclassOf('PHPUnit_Framework_Exception')) { + $checkException = true; + } + } + + if ($checkException) { + $this->assertThat( + $e, + new PHPUnit_Framework_Constraint_Exception( + $this->expectedException + ) + ); + + if (is_string($this->expectedExceptionMessage) && + !empty($this->expectedExceptionMessage)) { + $this->assertThat( + $e, + new PHPUnit_Framework_Constraint_ExceptionMessage( + $this->expectedExceptionMessage + ) + ); + } + + if ($this->expectedExceptionCode !== null) { + $this->assertThat( + $e, + new PHPUnit_Framework_Constraint_ExceptionCode( + $this->expectedExceptionCode + ) + ); + } + + return; + } else { + throw $e; + } + } + + if ($this->expectedException !== null) { + $this->assertThat( + null, + new PHPUnit_Framework_Constraint_Exception( + $this->expectedException + ) + ); + } + + return $testResult; + } + + /** + * Verifies the mock object expectations. + * + * @since Method available since Release 3.5.0 + */ + protected function verifyMockObjects() + { + foreach ($this->mockObjects as $mockObject) { + if ($mockObject->__phpunit_hasMatchers()) { + $this->numAssertions++; + } + + $mockObject->__phpunit_verify(); + } + } + + /** + * Sets the name of a TestCase. + * + * @param string + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Sets the dependencies of a TestCase. + * + * @param array $dependencies + * @since Method available since Release 3.4.0 + */ + public function setDependencies(array $dependencies) + { + $this->dependencies = $dependencies; + } + + /** + * Returns true if the tests has dependencies + * + * @return boolean + * @since Method available since Release 4.0.0 + */ + public function hasDependencies() + { + return count($this->dependencies) > 0; + } + + /** + * Sets + * + * @param array $dependencyInput + * @since Method available since Release 3.4.0 + */ + public function setDependencyInput(array $dependencyInput) + { + $this->dependencyInput = $dependencyInput; + } + + /** + * Calling this method in setUp() has no effect! + * + * @param boolean $backupGlobals + * @since Method available since Release 3.3.0 + */ + public function setBackupGlobals($backupGlobals) + { + if (is_null($this->backupGlobals) && is_bool($backupGlobals)) { + $this->backupGlobals = $backupGlobals; + } + } + + /** + * Calling this method in setUp() has no effect! + * + * @param boolean $backupStaticAttributes + * @since Method available since Release 3.4.0 + */ + public function setBackupStaticAttributes($backupStaticAttributes) + { + if (is_null($this->backupStaticAttributes) && + is_bool($backupStaticAttributes)) { + $this->backupStaticAttributes = $backupStaticAttributes; + } + } + + /** + * @param boolean $runTestInSeparateProcess + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.4.0 + */ + public function setRunTestInSeparateProcess($runTestInSeparateProcess) + { + if (is_bool($runTestInSeparateProcess)) { + if ($this->runTestInSeparateProcess === null) { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + } + + /** + * @param boolean $preserveGlobalState + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.4.0 + */ + public function setPreserveGlobalState($preserveGlobalState) + { + if (is_bool($preserveGlobalState)) { + $this->preserveGlobalState = $preserveGlobalState; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + } + + /** + * @param boolean $inIsolation + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.4.0 + */ + public function setInIsolation($inIsolation) + { + if (is_bool($inIsolation)) { + $this->inIsolation = $inIsolation; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + } + + /** + * @return mixed + * @since Method available since Release 3.4.0 + */ + public function getResult() + { + return $this->testResult; + } + + /** + * @param mixed $result + * @since Method available since Release 3.4.0 + */ + public function setResult($result) + { + $this->testResult = $result; + } + + /** + * @param callable $callback + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.6.0 + */ + public function setOutputCallback($callback) + { + if (!is_callable($callback)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'callback'); + } + + $this->outputCallback = $callback; + } + + /** + * @return PHPUnit_Framework_TestResult + * @since Method available since Release 3.5.7 + */ + public function getTestResultObject() + { + return $this->result; + } + + /** + * @param PHPUnit_Framework_TestResult $result + * @since Method available since Release 3.6.0 + */ + public function setTestResultObject(PHPUnit_Framework_TestResult $result) + { + $this->result = $result; + } + + /** + * This method is a wrapper for the ini_set() function that automatically + * resets the modified php.ini setting to its original value after the + * test is run. + * + * @param string $varName + * @param string $newValue + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.0.0 + */ + protected function iniSet($varName, $newValue) + { + if (!is_string($varName)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + $currentValue = ini_set($varName, $newValue); + + if ($currentValue !== false) { + $this->iniSettings[$varName] = $currentValue; + } else { + throw new PHPUnit_Framework_Exception( + sprintf( + 'INI setting "%s" could not be set to "%s".', + $varName, + $newValue + ) + ); + } + } + + /** + * This method is a wrapper for the setlocale() function that automatically + * resets the locale to its original value after the test is run. + * + * @param integer $category + * @param string $locale + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.1.0 + */ + protected function setLocale() + { + $args = func_get_args(); + + if (count($args) < 2) { + throw new PHPUnit_Framework_Exception; + } + + $category = $args[0]; + $locale = $args[1]; + + $categories = array( + LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME + ); + + if (defined('LC_MESSAGES')) { + $categories[] = LC_MESSAGES; + } + + if (!in_array($category, $categories)) { + throw new PHPUnit_Framework_Exception; + } + + if (!is_array($locale) && !is_string($locale)) { + throw new PHPUnit_Framework_Exception; + } + + $this->locale[$category] = setlocale($category, null); + + $result = call_user_func_array( 'setlocale', $args ); + + if ($result === false) { + throw new PHPUnit_Framework_Exception( + 'The locale functionality is not implemented on your platform, ' . + 'the specified locale does not exist or the category name is ' . + 'invalid.' + ); + } + } + + /** + * Returns a mock object for the specified class. + * + * @param string $originalClassName Name of the class to mock. + * @param array|null $methods When provided, only methods whose names are in the array + * are replaced with a configurable test double. The behavior + * of the other methods is not changed. + * Providing null means that no methods will be replaced. + * @param array $arguments Parameters to pass to the original class' constructor. + * @param string $mockClassName Class name for the generated test double class. + * @param boolean $callOriginalConstructor Can be used to disable the call to the original class' constructor. + * @param boolean $callOriginalClone Can be used to disable the call to the original class' clone constructor. + * @param boolean $callAutoload Can be used to disable __autoload() during the generation of the test double class. + * @param boolean $cloneArguments + * @param boolean $callOriginalMethods + * @return PHPUnit_Framework_MockObject_MockObject + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.0.0 + */ + public function getMock($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false) + { + $mockObject = $this->getMockObjectGenerator()->getMock( + $originalClassName, + $methods, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments, + $callOriginalMethods + ); + + $this->mockObjects[] = $mockObject; + + return $mockObject; + } + + /** + * Returns a builder object to create mock objects using a fluent interface. + * + * @param string $className + * @return PHPUnit_Framework_MockObject_MockBuilder + * @since Method available since Release 3.5.0 + */ + public function getMockBuilder($className) + { + return new PHPUnit_Framework_MockObject_MockBuilder( + $this, $className + ); + } + + /** + * Mocks the specified class and returns the name of the mocked class. + * + * @param string $originalClassName + * @param array $methods + * @param array $arguments + * @param string $mockClassName + * @param boolean $callOriginalConstructor + * @param boolean $callOriginalClone + * @param boolean $callAutoload + * @param boolean $cloneArguments + * @return string + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.5.0 + */ + protected function getMockClass($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = false, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false) + { + $mock = $this->getMock( + $originalClassName, + $methods, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments + ); + + return get_class($mock); + } + + /** + * Returns a mock object for the specified abstract class with all abstract + * methods of the class mocked. Concrete methods to mock can be specified with + * the last parameter + * + * @param string $originalClassName + * @param array $arguments + * @param string $mockClassName + * @param boolean $callOriginalConstructor + * @param boolean $callOriginalClone + * @param boolean $callAutoload + * @param array $mockedMethods + * @param boolean $cloneArguments + * @return PHPUnit_Framework_MockObject_MockObject + * @since Method available since Release 3.4.0 + * @throws PHPUnit_Framework_Exception + */ + public function getMockForAbstractClass($originalClassName, array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = array(), $cloneArguments = false) + { + $mockObject = $this->getMockObjectGenerator()->getMockForAbstractClass( + $originalClassName, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $mockedMethods, + $cloneArguments + ); + + $this->mockObjects[] = $mockObject; + + return $mockObject; + } + + /** + * Returns a mock object based on the given WSDL file. + * + * @param string $wsdlFile + * @param string $originalClassName + * @param string $mockClassName + * @param array $methods + * @param boolean $callOriginalConstructor + * @param array $options An array of options passed to SOAPClient::_construct + * @return PHPUnit_Framework_MockObject_MockObject + * @since Method available since Release 3.4.0 + */ + protected function getMockFromWsdl($wsdlFile, $originalClassName = '', $mockClassName = '', array $methods = array(), $callOriginalConstructor = true, array $options = array()) + { + if ($originalClassName === '') { + $originalClassName = str_replace( + '.wsdl', '', basename($wsdlFile) + ); + } + + if (!class_exists($originalClassName)) { + eval( + $this->getMockObjectGenerator()->generateClassFromWsdl( + $wsdlFile, $originalClassName, $methods, $options + ) + ); + } + + return $this->getMock( + $originalClassName, + $methods, + array('', $options), + $mockClassName, + $callOriginalConstructor, + false, + false + ); + } + + /** + * Returns a mock object for the specified trait with all abstract methods + * of the trait mocked. Concrete methods to mock can be specified with the + * `$mockedMethods` parameter. + * + * @param string $traitName + * @param array $arguments + * @param string $mockClassName + * @param boolean $callOriginalConstructor + * @param boolean $callOriginalClone + * @param boolean $callAutoload + * @param array $mockedMethods + * @param boolean $cloneArguments + * @return PHPUnit_Framework_MockObject_MockObject + * @since Method available since Release 4.0.0 + * @throws PHPUnit_Framework_Exception + */ + public function getMockForTrait($traitName, array $arguments = array(), $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $mockedMethods = array(), $cloneArguments = false) + { + $mockObject = $this->getMockObjectGenerator()->getMockForTrait( + $traitName, + $arguments, + $mockClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $mockedMethods, + $cloneArguments + ); + + $this->mockObjects[] = $mockObject; + + return $mockObject; + } + + /** + * Returns an object for the specified trait. + * + * @param string $traitName + * @param array $arguments + * @param string $traitClassName + * @param boolean $callOriginalConstructor + * @param boolean $callOriginalClone + * @param boolean $callAutoload + * @param boolean $cloneArguments + * @return object + * @since Method available since Release 3.6.0 + * @throws PHPUnit_Framework_Exception + */ + protected function getObjectForTrait($traitName, array $arguments = array(), $traitClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false) + { + return $this->getMockObjectGenerator()->getObjectForTrait( + $traitName, + $arguments, + $traitClassName, + $callOriginalConstructor, + $callOriginalClone, + $callAutoload, + $cloneArguments + ); + } + + /** + * Adds a value to the assertion counter. + * + * @param integer $count + * @since Method available since Release 3.3.3 + */ + public function addToAssertionCount($count) + { + $this->numAssertions += $count; + } + + /** + * Returns the number of assertions performed by this test. + * + * @return integer + * @since Method available since Release 3.3.0 + */ + public function getNumAssertions() + { + return $this->numAssertions; + } + + /** + * Returns a matcher that matches when the method it is evaluated for + * is executed zero or more times. + * + * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount + * @since Method available since Release 3.0.0 + */ + public static function any() + { + return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount; + } + + /** + * Returns a matcher that matches when the method it is evaluated for + * is never executed. + * + * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount + * @since Method available since Release 3.0.0 + */ + public static function never() + { + return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0); + } + + /** + * Returns a matcher that matches when the method it is evaluated for + * is executed at least once. + * + * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce + * @since Method available since Release 3.0.0 + */ + public static function atLeastOnce() + { + return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce; + } + + /** + * Returns a matcher that matches when the method it is evaluated for + * is executed exactly once. + * + * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount + * @since Method available since Release 3.0.0 + */ + public static function once() + { + return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1); + } + + /** + * Returns a matcher that matches when the method it is evaluated for + * is executed exactly $count times. + * + * @param integer $count + * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount + * @since Method available since Release 3.0.0 + */ + public static function exactly($count) + { + return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count); + } + + /** + * Returns a matcher that matches when the method it is evaluated for + * is invoked at the given $index. + * + * @param integer $index + * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex + * @since Method available since Release 3.0.0 + */ + public static function at($index) + { + return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index); + } + + /** + * + * + * @param mixed $value + * @return PHPUnit_Framework_MockObject_Stub_Return + * @since Method available since Release 3.0.0 + */ + public static function returnValue($value) + { + return new PHPUnit_Framework_MockObject_Stub_Return($value); + } + + /** + * + * + * @param array $valueMap + * @return PHPUnit_Framework_MockObject_Stub_ReturnValueMap + * @since Method available since Release 3.6.0 + */ + public static function returnValueMap(array $valueMap) + { + return new PHPUnit_Framework_MockObject_Stub_ReturnValueMap($valueMap); + } + + /** + * + * + * @param integer $argumentIndex + * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument + * @since Method available since Release 3.3.0 + */ + public static function returnArgument($argumentIndex) + { + return new PHPUnit_Framework_MockObject_Stub_ReturnArgument( + $argumentIndex + ); + } + + /** + * + * + * @param mixed $callback + * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback + * @since Method available since Release 3.3.0 + */ + public static function returnCallback($callback) + { + return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback); + } + + /** + * Returns the current object. + * + * This method is useful when mocking a fluent interface. + * + * @return PHPUnit_Framework_MockObject_Stub_ReturnSelf + * @since Method available since Release 3.6.0 + */ + public static function returnSelf() + { + return new PHPUnit_Framework_MockObject_Stub_ReturnSelf(); + } + + /** + * + * + * @param Exception $exception + * @return PHPUnit_Framework_MockObject_Stub_Exception + * @since Method available since Release 3.1.0 + */ + public static function throwException(Exception $exception) + { + return new PHPUnit_Framework_MockObject_Stub_Exception($exception); + } + + /** + * @param mixed $value, ... + * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls + * @since Method available since Release 3.0.0 + */ + public static function onConsecutiveCalls() + { + $args = func_get_args(); + + return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args); + } + + /** + * @param mixed $data + * @return string + * @since Method available since Release 3.2.1 + */ + protected function dataToString($data) + { + $result = array(); + + set_error_handler(function ($errno, $errstr, $errfile, $errline) { + throw new ErrorException($errstr, $errno, $errno, $errfile, $errline); + }, E_WARNING); + + foreach ($data as $key => $_data) { + try { + // Detect array-recursions by using count + // http://php.net/manual/en/function.count.php + $iRecursiveCheck = count($_data, COUNT_RECURSIVE); + + if (is_array($_data)) { + $result[] = 'array(' . $this->dataToString($_data) . ')'; + } elseif (is_object($_data)) { + $object = new ReflectionObject($_data); + + if ($object->hasMethod('__toString')) { + $result[] = (string) $_data; + } else { + $result[] = get_class($_data); + } + } elseif (is_resource($_data)) { + $result[] = ''; + } else { + $result[] = var_export($_data, true); + } + } catch (ErrorException $e) { + $result[] = '*RECURSION*'; + } + } + + restore_error_handler(); + + return join(', ', $result); + } + + /** + * Gets the data set description of a TestCase. + * + * @param boolean $includeData + * @return string + * @since Method available since Release 3.3.0 + */ + protected function getDataSetAsString($includeData = true) + { + $buffer = ''; + + if (!empty($this->data)) { + if (is_int($this->dataName)) { + $buffer .= sprintf(' with data set #%d', $this->dataName); + } else { + $buffer .= sprintf(' with data set "%s"', $this->dataName); + } + + if ($includeData) { + $buffer .= sprintf(' (%s)', $this->dataToString($this->data)); + } + } + + return $buffer; + } + + /** + * Creates a default TestResult object. + * + * @return PHPUnit_Framework_TestResult + */ + protected function createResult() + { + return new PHPUnit_Framework_TestResult; + } + + /** + * @since Method available since Release 3.5.4 + */ + protected function handleDependencies() + { + if (!empty($this->dependencies) && !$this->inIsolation) { + $className = get_class($this); + $passed = $this->result->passed(); + $passedKeys = array_keys($passed); + $numKeys = count($passedKeys); + + for ($i = 0; $i < $numKeys; $i++) { + $pos = strpos($passedKeys[$i], ' with data set'); + + if ($pos !== false) { + $passedKeys[$i] = substr($passedKeys[$i], 0, $pos); + } + } + + $passedKeys = array_flip(array_unique($passedKeys)); + + foreach ($this->dependencies as $dependency) { + if (strpos($dependency, '::') === false) { + $dependency = $className . '::' . $dependency; + } + + if (!isset($passedKeys[$dependency])) { + $this->result->addError( + $this, + new PHPUnit_Framework_SkippedTestError( + sprintf( + 'This test depends on "%s" to pass.', $dependency + ) + ), + 0 + ); + + return false; + } + + if (isset($passed[$dependency])) { + if ($passed[$dependency]['size'] > $this->getSize()) { + $this->result->addError( + $this, + new PHPUnit_Framework_SkippedTestError( + 'This test depends on a test that is larger than itself.' + ), + 0 + ); + + return false; + } + + $this->dependencyInput[] = $passed[$dependency]['result']; + } else { + $this->dependencyInput[] = null; + } + } + } + + return true; + } + + /** + * This method is called before the first test of this test class is run. + * + * @since Method available since Release 3.4.0 + */ + public static function setUpBeforeClass() + { + } + + /** + * Sets up the fixture, for example, open a network connection. + * This method is called before a test is executed. + * + */ + protected function setUp() + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called before the execution of a test starts + * and after setUp() is called. + * + * @since Method available since Release 3.2.8 + */ + protected function assertPreConditions() + { + } + + /** + * Performs assertions shared by all tests of a test case. + * + * This method is called before the execution of a test ends + * and before tearDown() is called. + * + * @since Method available since Release 3.2.8 + */ + protected function assertPostConditions() + { + } + + /** + * Tears down the fixture, for example, close a network connection. + * This method is called after a test is executed. + */ + protected function tearDown() + { + } + + /** + * This method is called after the last test of this test class is run. + * + * @since Method available since Release 3.4.0 + */ + public static function tearDownAfterClass() + { + } + + /** + * This method is called when a test method did not execute successfully. + * + * @param Exception $e + * @since Method available since Release 3.4.0 + * @throws Exception + */ + protected function onNotSuccessfulTest(Exception $e) + { + throw $e; + } + + /** + * Performs custom preparations on the process isolation template. + * + * @param Text_Template $template + * @since Method available since Release 3.4.0 + */ + protected function prepareTemplate(Text_Template $template) + { + } + + /** + * Get the mock object generator, creating it if it doesn't exist. + * + * @return PHPUnit_Framework_MockObject_Generator + */ + protected function getMockObjectGenerator() + { + if (null === $this->mockObjectGenerator) { + $this->mockObjectGenerator = new PHPUnit_Framework_MockObject_Generator; + } + + return $this->mockObjectGenerator; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A TestSuite is a composite of Tests. It runs a collection of test cases. + * + * Here is an example using the dynamic test definition. + * + * + * addTest(new MathTest('testPass')); + * ?> + * + * + * Alternatively, a TestSuite can extract the tests to be run automatically. + * To do so you pass a ReflectionClass instance for your + * PHPUnit_Framework_TestCase class to the PHPUnit_Framework_TestSuite + * constructor. + * + * + * + * + * + * This constructor creates a suite with all the methods starting with + * "test" that take no arguments. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Framework_TestSuite implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing, IteratorAggregate +{ + /** + * Enable or disable the backup and restoration of the $GLOBALS array. + * + * @var boolean + */ + protected $backupGlobals = null; + + /** + * Enable or disable the backup and restoration of static attributes. + * + * @var boolean + */ + protected $backupStaticAttributes = null; + + /** + * @var boolean + */ + protected $runTestInSeparateProcess = false; + + /** + * The name of the test suite. + * + * @var string + */ + protected $name = ''; + + /** + * The test groups of the test suite. + * + * @var array + */ + protected $groups = array(); + + /** + * The tests in the test suite. + * + * @var array + */ + protected $tests = array(); + + /** + * The number of tests in the test suite. + * + * @var integer + */ + protected $numTests = -1; + + /** + * @var boolean + */ + protected $testCase = false; + + /** + * @var PHPUnit_Runner_Filter_Factory + */ + private $iteratorFilter = null; + + /** + * Constructs a new TestSuite: + * + * - PHPUnit_Framework_TestSuite() constructs an empty TestSuite. + * + * - PHPUnit_Framework_TestSuite(ReflectionClass) constructs a + * TestSuite from the given class. + * + * - PHPUnit_Framework_TestSuite(ReflectionClass, String) + * constructs a TestSuite from the given class with the given + * name. + * + * - PHPUnit_Framework_TestSuite(String) either constructs a + * TestSuite from the given class (if the passed string is the + * name of an existing class) or constructs an empty TestSuite + * with the given name. + * + * @param mixed $theClass + * @param string $name + * @throws PHPUnit_Framework_Exception + */ + public function __construct($theClass = '', $name = '') + { + $argumentsValid = false; + + if (is_object($theClass) && + $theClass instanceof ReflectionClass) { + $argumentsValid = true; + } elseif (is_string($theClass) && + $theClass !== '' && + class_exists($theClass, false)) { + $argumentsValid = true; + + if ($name == '') { + $name = $theClass; + } + + $theClass = new ReflectionClass($theClass); + } elseif (is_string($theClass)) { + $this->setName($theClass); + + return; + } + + if (!$argumentsValid) { + throw new PHPUnit_Framework_Exception; + } + + if (!$theClass->isSubclassOf('PHPUnit_Framework_TestCase')) { + throw new PHPUnit_Framework_Exception( + 'Class "' . $theClass->name . '" does not extend PHPUnit_Framework_TestCase.' + ); + } + + if ($name != '') { + $this->setName($name); + } else { + $this->setName($theClass->getName()); + } + + $constructor = $theClass->getConstructor(); + + if ($constructor !== null && + !$constructor->isPublic()) { + $this->addTest( + self::warning( + sprintf( + 'Class "%s" has no public constructor.', + + $theClass->getName() + ) + ) + ); + + return; + } + + foreach ($theClass->getMethods() as $method) { + $this->addTestMethod($theClass, $method); + } + + if (empty($this->tests)) { + $this->addTest( + self::warning( + sprintf( + 'No tests found in class "%s".', + + $theClass->getName() + ) + ) + ); + } + + $this->testCase = true; + } + + /** + * Returns a string representation of the test suite. + * + * @return string + */ + public function toString() + { + return $this->getName(); + } + + /** + * Adds a test to the suite. + * + * @param PHPUnit_Framework_Test $test + * @param array $groups + */ + public function addTest(PHPUnit_Framework_Test $test, $groups = array()) + { + $class = new ReflectionClass($test); + + if (!$class->isAbstract()) { + $this->tests[] = $test; + $this->numTests = -1; + + if ($test instanceof PHPUnit_Framework_TestSuite && + empty($groups)) { + $groups = $test->getGroups(); + } + + if (empty($groups)) { + $groups = array('__nogroup__'); + } + + foreach ($groups as $group) { + if (!isset($this->groups[$group])) { + $this->groups[$group] = array($test); + } else { + $this->groups[$group][] = $test; + } + } + } + } + + /** + * Adds the tests from the given class to the suite. + * + * @param mixed $testClass + * @throws PHPUnit_Framework_Exception + */ + public function addTestSuite($testClass) + { + if (is_string($testClass) && class_exists($testClass)) { + $testClass = new ReflectionClass($testClass); + } + + if (!is_object($testClass)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'class name or object' + ); + } + + if ($testClass instanceof PHPUnit_Framework_TestSuite) { + $this->addTest($testClass); + } elseif ($testClass instanceof ReflectionClass) { + $suiteMethod = false; + + if (!$testClass->isAbstract()) { + if ($testClass->hasMethod(PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME)) { + $method = $testClass->getMethod( + PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME + ); + + if ($method->isStatic()) { + $this->addTest( + $method->invoke(null, $testClass->getName()) + ); + + $suiteMethod = true; + } + } + } + + if (!$suiteMethod && !$testClass->isAbstract()) { + $this->addTest(new PHPUnit_Framework_TestSuite($testClass)); + } + } else { + throw new PHPUnit_Framework_Exception; + } + } + + /** + * Wraps both addTest() and addTestSuite + * as well as the separate import statements for the user's convenience. + * + * If the named file cannot be read or there are no new tests that can be + * added, a PHPUnit_Framework_Warning will be created instead, + * leaving the current test run untouched. + * + * @param string $filename + * @param array $phptOptions Array with ini settings for the php instance + * run, key being the name if the setting, + * value the ini value. + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 2.3.0 + * @author Stefano F. Rausch + */ + public function addTestFile($filename, $phptOptions = array()) + { + if (!is_string($filename)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (file_exists($filename) && substr($filename, -5) == '.phpt') { + $this->addTest( + new PHPUnit_Extensions_PhptTestCase($filename, $phptOptions) + ); + + return; + } + + $classes = get_declared_classes(); + $filename = PHPUnit_Util_Fileloader::checkAndLoad($filename); + $newClasses = array_values(array_diff(get_declared_classes(), $classes)); + $baseName = str_replace('.php', '', basename($filename)); + + foreach ($newClasses as $className) { + if (substr($className, 0 - strlen($baseName)) == $baseName) { + $class = new ReflectionClass($className); + + if ($class->getFileName() == $filename) { + $newClasses = array($className); + break; + } + } + } + + foreach ($newClasses as $className) { + $class = new ReflectionClass($className); + + if (!$class->isAbstract()) { + if ($class->hasMethod(PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME)) { + $method = $class->getMethod( + PHPUnit_Runner_BaseTestRunner::SUITE_METHODNAME + ); + + if ($method->isStatic()) { + $this->addTest($method->invoke(null, $className)); + } + } elseif ($class->implementsInterface('PHPUnit_Framework_Test')) { + $this->addTestSuite($class); + } + } + } + + $this->numTests = -1; + } + + /** + * Wrapper for addTestFile() that adds multiple test files. + * + * @param array|Iterator $filenames + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 2.3.0 + */ + public function addTestFiles($filenames) + { + if (!(is_array($filenames) || + (is_object($filenames) && $filenames instanceof Iterator))) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'array or iterator' + ); + } + + foreach ($filenames as $filename) { + $this->addTestFile((string) $filename); + } + } + + /** + * Counts the number of test cases that will be run by this test. + * + * @return integer + */ + public function count() + { + $numTests = 0; + + foreach ($this as $test) { + $numTests += count($test); + } + + return $numTests; + } + + /** + * @param ReflectionClass $theClass + * @param string $name + * @return PHPUnit_Framework_Test + * @throws PHPUnit_Framework_Exception + */ + public static function createTest(ReflectionClass $theClass, $name) + { + $className = $theClass->getName(); + + if (!$theClass->isInstantiable()) { + return self::warning( + sprintf('Cannot instantiate class "%s".', $className) + ); + } + + $backupSettings = PHPUnit_Util_Test::getBackupSettings( + $className, $name + ); + $preserveGlobalState = PHPUnit_Util_Test::getPreserveGlobalStateSettings( + $className, $name + ); + $runTestInSeparateProcess = PHPUnit_Util_Test::getProcessIsolationSettings( + $className, $name + ); + + $constructor = $theClass->getConstructor(); + + if ($constructor !== null) { + $parameters = $constructor->getParameters(); + + // TestCase() or TestCase($name) + if (count($parameters) < 2) { + $test = new $className; + } + + // TestCase($name, $data) + else { + try { + $data = PHPUnit_Util_Test::getProvidedData( + $className, $name + ); + } catch (Exception $e) { + $message = sprintf( + 'The data provider specified for %s::%s is invalid.', + $className, + $name + ); + + $_message = $e->getMessage(); + + if (!empty($_message)) { + $message .= "\n" . $_message; + } + + $data = self::warning($message); + } + + // Test method with @dataProvider. + if (isset($data)) { + $test = new PHPUnit_Framework_TestSuite_DataProvider( + $className . '::' . $name + ); + + if (empty($data)) { + $data = self::warning( + sprintf( + 'No tests found in suite "%s".', + $test->getName() + ) + ); + } + + $groups = PHPUnit_Util_Test::getGroups($className, $name); + + if ($data instanceof PHPUnit_Framework_Warning) { + $test->addTest($data, $groups); + } else { + foreach ($data as $_dataName => $_data) { + $_test = new $className($name, $_data, $_dataName); + + if ($runTestInSeparateProcess) { + $_test->setRunTestInSeparateProcess(true); + + if ($preserveGlobalState !== null) { + $_test->setPreserveGlobalState($preserveGlobalState); + } + } + + if ($backupSettings['backupGlobals'] !== null) { + $_test->setBackupGlobals( + $backupSettings['backupGlobals'] + ); + } + + if ($backupSettings['backupStaticAttributes'] !== null) { + $_test->setBackupStaticAttributes( + $backupSettings['backupStaticAttributes'] + ); + } + + $test->addTest($_test, $groups); + } + } + } else { + $test = new $className; + } + } + } + + if (!isset($test)) { + throw new PHPUnit_Framework_Exception('No valid test provided.'); + } + + if ($test instanceof PHPUnit_Framework_TestCase) { + $test->setName($name); + + if ($runTestInSeparateProcess) { + $test->setRunTestInSeparateProcess(true); + + if ($preserveGlobalState !== null) { + $test->setPreserveGlobalState($preserveGlobalState); + } + } + + if ($backupSettings['backupGlobals'] !== null) { + $test->setBackupGlobals($backupSettings['backupGlobals']); + } + + if ($backupSettings['backupStaticAttributes'] !== null) { + $test->setBackupStaticAttributes( + $backupSettings['backupStaticAttributes'] + ); + } + } + + return $test; + } + + /** + * Creates a default TestResult object. + * + * @return PHPUnit_Framework_TestResult + */ + protected function createResult() + { + return new PHPUnit_Framework_TestResult; + } + + /** + * Returns the name of the suite. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Returns the test groups of the suite. + * + * @return array + * @since Method available since Release 3.2.0 + */ + public function getGroups() + { + return array_keys($this->groups); + } + + public function getGroupDetails() + { + return $this->groups; + } + + /** + * Set tests groups of the test case + * + * @param array $groups + * @since Method available since Release 4.0.0 + */ + public function setGroupDetails(array $groups) + { + $this->groups = $groups; + } + + /** + * Runs the tests and collects their result in a TestResult. + * + * @param PHPUnit_Framework_TestResult $result + * @return PHPUnit_Framework_TestResult + */ + public function run(PHPUnit_Framework_TestResult $result = null) + { + if ($result === null) { + $result = $this->createResult(); + } + + if (count($this) == 0) { + return $result; + } + + $hookMethods = PHPUnit_Util_Test::getHookMethods($this->name); + + $result->startTestSuite($this); + + try { + $this->setUp(); + + foreach ($hookMethods['beforeClass'] as $beforeClassMethod) { + if ($this->testCase === true && class_exists($this->name, false) && method_exists($this->name, $beforeClassMethod)) { + call_user_func(array($this->name, $beforeClassMethod)); + } + } + } catch (PHPUnit_Framework_SkippedTestSuiteError $e) { + $numTests = count($this); + + for ($i = 0; $i < $numTests; $i++) { + $result->addFailure($this, $e, 0); + } + + return $result; + } catch (Exception $e) { + $numTests = count($this); + + for ($i = 0; $i < $numTests; $i++) { + $result->addError($this, $e, 0); + } + + return $result; + } + + foreach ($this as $test) { + if ($result->shouldStop()) { + break; + } + + if ($test instanceof PHPUnit_Framework_TestCase || + $test instanceof PHPUnit_Framework_TestSuite) { + $test->setBackupGlobals($this->backupGlobals); + $test->setBackupStaticAttributes($this->backupStaticAttributes); + $test->setRunTestInSeparateProcess($this->runTestInSeparateProcess); + } + + $test->run($result); + } + + foreach ($hookMethods['afterClass'] as $afterClassMethod) { + if ($this->testCase === true && class_exists($this->name, false) && method_exists($this->name, $afterClassMethod)) { + call_user_func(array($this->name, $afterClassMethod)); + } + } + + $this->tearDown(); + + $result->endTestSuite($this); + + return $result; + } + + /** + * @param boolean $runTestInSeparateProcess + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.7.0 + */ + public function setRunTestInSeparateProcess($runTestInSeparateProcess) + { + if (is_bool($runTestInSeparateProcess)) { + $this->runTestInSeparateProcess = $runTestInSeparateProcess; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + } + + /** + * Runs a test. + * + * @deprecated + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_TestResult $result + */ + public function runTest(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result) + { + $test->run($result); + } + + /** + * Sets the name of the suite. + * + * @param string + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Returns the test at the given index. + * + * @param integer + * @return PHPUnit_Framework_Test + */ + public function testAt($index) + { + if (isset($this->tests[$index])) { + return $this->tests[$index]; + } else { + return false; + } + } + + /** + * Returns the tests as an enumeration. + * + * @return array + */ + public function tests() + { + return $this->tests; + } + + /** + * Set tests of the test suite + * + * @param array $tests + * @since Method available since Release 4.0.0 + */ + public function setTests(array $tests) + { + $this->tests = $tests; + } + + /** + * Mark the test suite as skipped. + * + * @param string $message + * @throws PHPUnit_Framework_SkippedTestSuiteError + * @since Method available since Release 3.0.0 + */ + public function markTestSuiteSkipped($message = '') + { + throw new PHPUnit_Framework_SkippedTestSuiteError($message); + } + + /** + * @param ReflectionClass $class + * @param ReflectionMethod $method + */ + protected function addTestMethod(ReflectionClass $class, ReflectionMethod $method) + { + if (!$this->isTestMethod($method)) + return; + + $name = $method->getName(); + + if (!$method->isPublic()) { + $this->addTest( + self::warning( + sprintf( + 'Test method "%s" in test class "%s" is not public.', + $name, + $class->getName() + ) + ) + ); + + return; + } + + $test = self::createTest($class, $name); + + if ($test instanceof PHPUnit_Framework_TestCase || + $test instanceof PHPUnit_Framework_TestSuite_DataProvider) { + $test->setDependencies( + PHPUnit_Util_Test::getDependencies($class->getName(), $name) + ); + } + + $this->addTest( + $test, + PHPUnit_Util_Test::getGroups($class->getName(), $name) + ); + } + + /** + * @param ReflectionMethod $method + * @return boolean + */ + public static function isTestMethod(ReflectionMethod $method) + { + if (strpos($method->name, 'test') === 0) { + return true; + } + + // @scenario on TestCase::testMethod() + // @test on TestCase::testMethod() + $doc_comment = $method->getDocComment(); + + return strpos($doc_comment, '@test') !== false || + strpos($doc_comment, '@scenario') !== false; + } + + /** + * @param string $message + * @return PHPUnit_Framework_Warning + */ + protected static function warning($message) + { + return new PHPUnit_Framework_Warning($message); + } + + /** + * @param boolean $backupGlobals + * @since Method available since Release 3.3.0 + */ + public function setBackupGlobals($backupGlobals) + { + if (is_null($this->backupGlobals) && is_bool($backupGlobals)) { + $this->backupGlobals = $backupGlobals; + } + } + + /** + * @param boolean $backupStaticAttributes + * @since Method available since Release 3.4.0 + */ + public function setBackupStaticAttributes($backupStaticAttributes) + { + if (is_null($this->backupStaticAttributes) && + is_bool($backupStaticAttributes)) { + $this->backupStaticAttributes = $backupStaticAttributes; + } + } + + /** + * Returns an iterator for this test suite. + * + * @return RecursiveIteratorIterator + * @since Method available since Release 3.1.0 + */ + public function getIterator() + { + $iterator = new PHPUnit_Util_TestSuiteIterator($this); + + if ($this->iteratorFilter !== null) { + $iterator = $this->iteratorFilter->factory($iterator, $this); + } + + return $iterator; + } + + public function injectFilter(PHPUnit_Runner_Filter_Factory $filter) + { + $this->iteratorFilter = $filter; + foreach ($this as $test) { + if ($test instanceof PHPUnit_Framework_TestSuite) { + $test->injectFilter($filter); + } + } + } + + /** + * Template Method that is called before the tests + * of this test suite are run. + * + * @since Method available since Release 3.1.0 + */ + protected function setUp() + { + } + + /** + * Template Method that is called after the tests + * of this test suite have finished running. + * + * @since Method available since Release 3.1.0 + */ + protected function tearDown() + { + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * Thrown when an assertion failed. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Framework_AssertionFailedError extends PHPUnit_Framework_Exception implements PHPUnit_Framework_SelfDescribing +{ + /** + * Wrapper for getMessage() which is declared as final. + * + * @return string + */ + public function toString() + { + return $this->getMessage(); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A Test can be run and collect its results. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 2.0.0 + */ +interface PHPUnit_Framework_Test extends Countable +{ + /** + * Runs a test and collects its result in a TestResult instance. + * + * @param PHPUnit_Framework_TestResult $result + * @return PHPUnit_Framework_TestResult + */ + public function run(PHPUnit_Framework_TestResult $result = null); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of a test that printed output. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.0 + */ +class PHPUnit_Framework_OutputError extends PHPUnit_Framework_AssertionFailedError +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.2.0 + */ + +/** + * Wrapper for PHP errors. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.2.0 + */ +class PHPUnit_Framework_Error extends Exception +{ + /** + * Constructor. + * + * @param string $message + * @param integer $code + * @param string $file + * @param integer $line + * @param Exception $previous + */ + public function __construct($message, $code, $file, $line, Exception $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->file = $file; + $this->line = $line; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Logical XOR. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_Xor extends PHPUnit_Framework_Constraint +{ + /** + * @var PHPUnit_Framework_Constraint[] + */ + protected $constraints = array(); + + /** + * @param PHPUnit_Framework_Constraint[] $constraints + */ + public function setConstraints(array $constraints) + { + $this->constraints = array(); + + foreach ($constraints as $constraint) { + if (!($constraint instanceof PHPUnit_Framework_Constraint)) { + $constraint = new PHPUnit_Framework_Constraint_IsEqual( + $constraint + ); + } + + $this->constraints[] = $constraint; + } + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = true; + $lastResult = null; + $constraint = null; + + foreach ($this->constraints as $constraint) { + $result = $constraint->evaluate($other, $description, true); + + if ($result === $lastResult) { + $success = false; + break; + } + + $lastResult = $result; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + if ($key > 0) { + $text .= ' xor '; + } + + $text .= $constraint->toString(); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + * + * @return integer + * @since Method available since Release 3.4.0 + */ + public function count() + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += count($constraint); + } + + return $count; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.0 + */ + +/** + * Constraint that asserts that the class it is evaluated for has a given + * attribute. + * + * The attribute name is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.0 + */ +class PHPUnit_Framework_Constraint_ClassHasAttribute extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $attributeName; + + /** + * @param string $attributeName + */ + public function __construct($attributeName) + { + parent::__construct(); + $this->attributeName = $attributeName; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + $class = new ReflectionClass($other); + + return $class->hasProperty($this->attributeName); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return sprintf( + 'has attribute "%s"', + + $this->attributeName + ); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + '%sclass "%s" %s', + + is_object($other) ? 'object of ' : '', + is_object($other) ? get_class($other) : $other, + $this->toString() + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.0 + */ + +/** + * Constraint that checks whether a variable is empty(). + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.5.0 + */ +class PHPUnit_Framework_Constraint_IsEmpty extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + if ($other instanceof Countable) { + return count($other) === 0; + } + + return empty($other); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is empty'; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + $type = gettype($other); + + return sprintf( + '%s %s %s', + + $type[0] == 'a' || $type[0] == 'o' ? 'an' : 'a', + $type, + $this->toString() + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.0 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.0 + */ +class PHPUnit_Framework_Constraint_Count extends PHPUnit_Framework_Constraint +{ + /** + * @var integer + */ + protected $expectedCount = 0; + + /** + * @param integer $expected + */ + public function __construct($expected) + { + parent::__construct(); + $this->expectedCount = $expected; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other + * @return boolean + */ + protected function matches($other) + { + return $this->expectedCount === $this->getCountOf($other); + } + + /** + * @param mixed $other + * @return boolean + */ + protected function getCountOf($other) + { + if ($other instanceof Countable || is_array($other)) { + return count($other); + } + + else if ($other instanceof Traversable) { + if ($other instanceof IteratorAggregate) { + $iterator = $other->getIterator(); + } else { + $iterator = $other; + } + + $key = $iterator->key(); + $count = iterator_count($iterator); + + // manually rewind $iterator to previous key, since iterator_count + // moves pointer + if ($key !== null) { + $iterator->rewind(); + while ($key !== $iterator->key()) { + $iterator->next(); + } + } + + return $count; + } + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + 'actual size %d matches expected size %d', + + $this->getCountOf($other), + $this->expectedCount + ); + } + + /** + * @return string + */ + public function toString() + { + return 'count matches '; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * Constraint that asserts that the string it is evaluated for begins with a + * given prefix. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +class PHPUnit_Framework_Constraint_StringStartsWith extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $prefix; + + /** + * @param string $prefix + */ + public function __construct($prefix) + { + parent::__construct(); + $this->prefix = $prefix; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return strpos($other, $this->prefix) === 0; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'starts with "' . $this->prefix . '"'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.0 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.0 + */ +class PHPUnit_Framework_Constraint_SameSize extends PHPUnit_Framework_Constraint_Count +{ + /** + * @var integer + */ + protected $expectedCount; + + /** + * @param integer $expected + */ + public function __construct($expected) + { + parent::__construct($this->getCountOf($expected)); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Kore Nordmann + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that checks if one value is equal to another. + * + * Equality is checked with PHP's == operator, the operator is explained in + * detail at {@url http://www.php.net/manual/en/types.comparisons.php}. + * Two values are equal if they have the same value disregarding type. + * + * The expected value is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Kore Nordmann + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_IsEqual extends PHPUnit_Framework_Constraint +{ + /** + * @var mixed + */ + protected $value; + + /** + * @var float + */ + protected $delta = 0.0; + + /** + * @var integer + */ + protected $maxDepth = 10; + + /** + * @var boolean + */ + protected $canonicalize = false; + + /** + * @var boolean + */ + protected $ignoreCase = false; + + /** + * @var SebastianBergmann\Comparator\ComparisonFailure + */ + protected $lastFailure; + + /** + * @param mixed $value + * @param float $delta + * @param integer $maxDepth + * @param boolean $canonicalize + * @param boolean $ignoreCase + * @throws PHPUnit_Framework_Exception + */ + public function __construct($value, $delta = 0.0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) + { + parent::__construct(); + + if (!is_numeric($delta)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'numeric'); + } + + if (!is_int($maxDepth)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'integer'); + } + + if (!is_bool($canonicalize)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'boolean'); + } + + if (!is_bool($ignoreCase)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(5, 'boolean'); + } + + $this->value = $value; + $this->delta = $delta; + $this->maxDepth = $maxDepth; + $this->canonicalize = $canonicalize; + $this->ignoreCase = $ignoreCase; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $comparatorFactory = new SebastianBergmann\Comparator\Factory; + + try { + $comparator = $comparatorFactory->getComparatorFor( + $other, $this->value + ); + + $comparator->assertEquals( + $this->value, + $other, + $this->delta, + $this->canonicalize, + $this->ignoreCase + ); + } catch (SebastianBergmann\Comparator\ComparisonFailure $f) { + if ($returnResult) { + return false; + } + + throw new PHPUnit_Framework_ExpectationFailedException( + trim($description . "\n" . $f->getMessage()), + $f + ); + } + + return true; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + $delta = ''; + + if (is_string($this->value)) { + if (strpos($this->value, "\n") !== false) { + return 'is equal to '; + } else { + return sprintf( + 'is equal to ', + + $this->value + ); + } + } else { + if ($this->delta != 0) { + $delta = sprintf( + ' with delta <%F>', + + $this->delta + ); + } + + return sprintf( + 'is equal to %s%s', + + $this->exporter->export($this->value), + $delta + ); + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Logical OR. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_Or extends PHPUnit_Framework_Constraint +{ + /** + * @var PHPUnit_Framework_Constraint[] + */ + protected $constraints = array(); + + /** + * @param PHPUnit_Framework_Constraint[] $constraints + */ + public function setConstraints(array $constraints) + { + $this->constraints = array(); + + foreach ($constraints as $constraint) { + if (!($constraint instanceof PHPUnit_Framework_Constraint)) { + $constraint = new PHPUnit_Framework_Constraint_IsEqual( + $constraint + ); + } + + $this->constraints[] = $constraint; + } + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = false; + $constraint = null; + + foreach ($this->constraints as $constraint) { + if ($constraint->evaluate($other, $description, true)) { + $success = true; + break; + } + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + if ($key > 0) { + $text .= ' or '; + } + + $text .= $constraint->toString(); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + * + * @return integer + * @since Method available since Release 3.4.0 + */ + public function count() + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += count($constraint); + } + + return $count; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the string it is evaluated for contains + * a given string. + * + * Uses strpos() to find the position of the string in the input, if not found + * the evaluation fails. + * + * The sub-string is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_StringContains extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $string; + + /** + * @var boolean + */ + protected $ignoreCase; + + /** + * @param string $string + * @param boolean $ignoreCase + */ + public function __construct($string, $ignoreCase = false) + { + parent::__construct(); + + $this->string = $string; + $this->ignoreCase = $ignoreCase; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + if ($this->ignoreCase) { + return stripos($other, $this->string) !== false; + } else { + return strpos($other, $this->string) !== false; + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + if ($this->ignoreCase) { + $string = strtolower($this->string); + } else { + $string = $this->string; + } + + return sprintf( + 'contains "%s"', + + $string + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.0 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.0 + */ + +abstract class PHPUnit_Framework_Constraint_Composite extends PHPUnit_Framework_Constraint +{ + /** + * @var PHPUnit_Framework_Constraint + */ + protected $innerConstraint; + + /** + * @param PHPUnit_Framework_Constraint $innerConstraint + * @param string $attributeName + */ + public function __construct(PHPUnit_Framework_Constraint $innerConstraint) + { + parent::__construct(); + $this->innerConstraint = $innerConstraint; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + try { + return $this->innerConstraint->evaluate( + $other, + $description, + $returnResult + ); + } catch (PHPUnit_Framework_ExpectationFailedException $e) { + $this->fail($other, $description); + } + } + + /** + * Counts the number of constraint elements. + * + * @return integer + */ + public function count() + { + return count($this->innerConstraint); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.6 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.6 + */ +class PHPUnit_Framework_Constraint_ExceptionMessage extends PHPUnit_Framework_Constraint +{ + /** + * @var integer + */ + protected $expectedMessage; + + /** + * @param string $expected + */ + public function __construct($expected) + { + parent::__construct(); + $this->expectedMessage = $expected; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param Exception $other + * @return boolean + */ + protected function matches($other) + { + return strpos($other->getMessage(), $this->expectedMessage) !== false; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + "exception message '%s' contains '%s'", + $other->getMessage(), + $this->expectedMessage + ); + } + + /** + * @return string + */ + public function toString() + { + return 'exception message contains '; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * Constraint that accepts null. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Framework_Constraint_IsNull extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return $other === null; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is null'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.0 + */ + +use SebastianBergmann\Diff\Differ; + +/** + * ... + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.5.0 + */ +class PHPUnit_Framework_Constraint_StringMatches extends PHPUnit_Framework_Constraint_PCREMatch +{ + /** + * @var string + */ + protected $string; + + /** + * @param string $string + */ + public function __construct($string) + { + parent::__construct($string); + + $this->pattern = $this->createPatternFromFormat( + preg_replace('/\r\n/', "\n", $string) + ); + + $this->string = $string; + } + + protected function failureDescription($other) + { + return "format description matches text"; + } + + protected function additionalFailureDescription($other) + { + $from = preg_split('(\r\n|\r|\n)', $this->string); + $to = preg_split('(\r\n|\r|\n)', $other); + + foreach ($from as $index => $line) { + if (isset($to[$index]) && $line !== $to[$index]) { + $line = $this->createPatternFromFormat($line); + + if (preg_match($line, $to[$index]) > 0) { + $from[$index] = $to[$index]; + } + } + } + + $this->string = join("\n", $from); + $other = join("\n", $to); + + $differ = new Differ("--- Expected\n+++ Actual\n"); + + return $differ->diff($this->string, $other); + } + + protected function createPatternFromFormat($string) + { + $string = str_replace( + array( + '%e', + '%s', + '%S', + '%a', + '%A', + '%w', + '%i', + '%d', + '%x', + '%f', + '%c' + ), + array( + '\\' . DIRECTORY_SEPARATOR, + '[^\r\n]+', + '[^\r\n]*', + '.+', + '.*', + '\s*', + '[+-]?\d+', + '\d+', + '[0-9a-fA-F]+', + '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', + '.' + ), + preg_quote($string, '/') + ); + + return '/^' . $string . '$/s'; + } + +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the value it is evaluated for is of a + * specified type. + * + * The expected value is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_IsType extends PHPUnit_Framework_Constraint +{ + const TYPE_ARRAY = 'array'; + const TYPE_BOOL = 'bool'; + const TYPE_FLOAT = 'float'; + const TYPE_INT = 'int'; + const TYPE_null = 'null'; + const TYPE_NUMERIC = 'numeric'; + const TYPE_OBJECT = 'object'; + const TYPE_RESOURCE = 'resource'; + const TYPE_STRING = 'string'; + const TYPE_SCALAR = 'scalar'; + const TYPE_CALLABLE = 'callable'; + + /** + * @var array + */ + protected $types = array( + 'array' => true, + 'boolean' => true, + 'bool' => true, + 'float' => true, + 'integer' => true, + 'int' => true, + 'null' => true, + 'numeric' => true, + 'object' => true, + 'resource' => true, + 'string' => true, + 'scalar' => true, + 'callable' => true + ); + + /** + * @var string + */ + protected $type; + + /** + * @param string $type + * @throws PHPUnit_Framework_Exception + */ + public function __construct($type) + { + parent::__construct(); + + if (!isset($this->types[$type])) { + throw new PHPUnit_Framework_Exception( + sprintf( + 'Type specified for PHPUnit_Framework_Constraint_IsType <%s> ' . + 'is not a valid type.', + $type + ) + ); + } + + $this->type = $type; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + switch ($this->type) { + case 'numeric': { + return is_numeric($other); + } + + case 'integer': + case 'int': { + return is_integer($other); + } + + case 'float': { + return is_float($other); + } + + case 'string': { + return is_string($other); + } + + case 'boolean': + case 'bool': { + return is_bool($other); + } + + case 'null': { + return is_null($other); + } + + case 'array': { + return is_array($other); + } + + case 'object': { + return is_object($other); + } + + case 'resource': { + return is_resource($other); + } + + case 'scalar': { + return is_scalar($other); + } + + case 'callable': { + return is_callable($other); + } + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return sprintf( + 'is of type "%s"', + + $this->type + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the object it is evaluated for is an instance + * of a given class. + * + * The expected class name is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_IsInstanceOf extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $className; + + /** + * @param string $className + */ + public function __construct($className) + { + parent::__construct(); + $this->className = $className; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return ($other instanceof $this->className); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + '%s is an instance of %s "%s"', + $this->exporter->shortenedExport($other), + $this->getType(), + $this->className + ); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return sprintf( + 'is instance of %s "%s"', + $this->getType(), + $this->className + ); + } + + private function getType() + { + try { + $reflection = new ReflectionClass($this->className); + if ($reflection->isInterface()) { + return 'interface'; + } + } catch (ReflectionException $e) { + } + + return 'class'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * Constraint that accepts true. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Framework_Constraint_IsTrue extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return $other === true; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is true'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * Constraint that accepts false. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Framework_Constraint_IsFalse extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return $other === false; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is false'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.6 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.6 + */ +class PHPUnit_Framework_Constraint_ExceptionCode extends PHPUnit_Framework_Constraint +{ + /** + * @var integer + */ + protected $expectedCode; + + /** + * @param integer $expected + */ + public function __construct($expected) + { + parent::__construct(); + $this->expectedCode = $expected; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param Exception $other + * @return boolean + */ + protected function matches($other) + { + return (string) $other->getCode() == (string) $this->expectedCode; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + '%s is equal to expected exception code %s', + $this->exporter->export($other->getCode()), + $this->exporter->export($this->expectedCode) + ); + } + + /** + * @return string + */ + public function toString() + { + return 'exception code is '; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.7.20 + */ + +/** + * Constraint that asserts that a string is valid JSON. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.7.20 + */ +class PHPUnit_Framework_Constraint_IsJson extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + json_decode($other); + if (json_last_error()) { + return false; + } + + return true; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + json_decode($other); + $error = PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider::determineJsonError( + json_last_error() + ); + + return sprintf( + '%s is valid JSON (%s)', + + $this->exporter->shortenedExport($other), + $error + ); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is valid JSON'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Logical NOT. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ + +class PHPUnit_Framework_Constraint_Not extends PHPUnit_Framework_Constraint +{ + /** + * @var PHPUnit_Framework_Constraint + */ + protected $constraint; + + /** + * @param PHPUnit_Framework_Constraint $constraint + */ + public function __construct($constraint) + { + parent::__construct(); + + if (!($constraint instanceof PHPUnit_Framework_Constraint)) { + $constraint = new PHPUnit_Framework_Constraint_IsEqual($constraint); + } + + $this->constraint = $constraint; + } + + /** + * @param string $string + * @return string + */ + public static function negate($string) + { + return str_replace( + array( + 'contains ', + 'exists', + 'has ', + 'is ', + 'are ', + 'matches ', + 'starts with ', + 'ends with ', + 'reference ', + 'not not ' + ), + array( + 'does not contain ', + 'does not exist', + 'does not have ', + 'is not ', + 'are not ', + 'does not match ', + 'starts not with ', + 'ends not with ', + 'don\'t reference ', + 'not ' + ), + $string + ); + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = !$this->constraint->evaluate($other, $description, true); + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + switch (get_class($this->constraint)) { + case 'PHPUnit_Framework_Constraint_And': + case 'PHPUnit_Framework_Constraint_Not': + case 'PHPUnit_Framework_Constraint_Or': { + return 'not( ' . $this->constraint->failureDescription($other) . ' )'; + } + break; + + default: { + return self::negate( + $this->constraint->failureDescription($other) + ); + } + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + switch (get_class($this->constraint)) { + case 'PHPUnit_Framework_Constraint_And': + case 'PHPUnit_Framework_Constraint_Not': + case 'PHPUnit_Framework_Constraint_Or': { + return 'not( ' . $this->constraint->toString() . ' )'; + } + break; + + default: { + return self::negate( + $this->constraint->toString() + ); + } + } + } + + /** + * Counts the number of constraint elements. + * + * @return integer + * @since Method available since Release 3.4.0 + */ + public function count() + { + return count($this->constraint); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the array it is evaluated for has a given key. + * + * Uses array_key_exists() to check if the key is found in the input array, if + * not found the evaluation fails. + * + * The array key is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_ArrayHasKey extends PHPUnit_Framework_Constraint +{ + /** + * @var integer|string + */ + protected $key; + + /** + * @param integer|string $key + */ + public function __construct($key) + { + parent::__construct(); + $this->key = $key; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + if (is_array($other)) { + return array_key_exists($this->key, $other); + } + + if ($other instanceof ArrayAccess) { + return $other->offsetExists($this->key); + } + + return false; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'has the key ' . $this->exporter->export($this->key); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return 'an array ' . $this->toString(); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the string it is evaluated for matches + * a regular expression. + * + * Checks a given value using the Perl Compatible Regular Expression extension + * in PHP. The pattern is matched by executing preg_match(). + * + * The pattern string passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_PCREMatch extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $pattern; + + /** + * @param string $pattern + */ + public function __construct($pattern) + { + parent::__construct(); + $this->pattern = $pattern; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return preg_match($this->pattern, $other) > 0; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return sprintf( + 'matches PCRE pattern "%s"', + + $this->pattern + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Logical AND. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_And extends PHPUnit_Framework_Constraint +{ + /** + * @var PHPUnit_Framework_Constraint[] + */ + protected $constraints = array(); + + /** + * @var PHPUnit_Framework_Constraint + */ + protected $lastConstraint = null; + + /** + * @param PHPUnit_Framework_Constraint[] $constraints + * @throws PHPUnit_Framework_Exception + */ + public function setConstraints(array $constraints) + { + $this->constraints = array(); + + foreach ($constraints as $constraint) { + if (!($constraint instanceof PHPUnit_Framework_Constraint)) { + throw new PHPUnit_Framework_Exception( + 'All parameters to ' . __CLASS__ . + ' must be a constraint object.' + ); + } + + $this->constraints[] = $constraint; + } + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = true; + $constraint = null; + + foreach ($this->constraints as $constraint) { + if (!$constraint->evaluate($other, $description, true)) { + $success = false; + break; + } + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + $text = ''; + + foreach ($this->constraints as $key => $constraint) { + if ($key > 0) { + $text .= ' and '; + } + + $text .= $constraint->toString(); + } + + return $text; + } + + /** + * Counts the number of constraint elements. + * + * @return integer + * @since Method available since Release 3.4.0 + */ + public function count() + { + $count = 0; + + foreach ($this->constraints as $constraint) { + $count += count($constraint); + } + + return $count; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + */ + +/** + * Constraint that evaluates against a specified closure. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Timon Rapp + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + */ +class PHPUnit_Framework_Constraint_Callback extends PHPUnit_Framework_Constraint +{ + private $callback; + + /** + * @param callable $callback + * @throws PHPUnit_Framework_Exception + */ + public function __construct($callback) + { + if (!is_callable($callback)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 1, 'callable' + ); + } + + parent::__construct(); + + $this->callback = $callback; + } + + /** + * Evaluates the constraint for parameter $value. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return call_user_func($this->callback, $other); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is accepted by specified callback'; + } + + private function callbackToString($callback) + { + if (!is_array($callback)) { + return $callback; + } + if (empty($callback)) { + return "empty array"; + } + if (!isset($callback[0]) || !isset($callback[1])) { + return "array without indexes 0 and 1 set"; + } + if (is_object($callback[0])) { + $callback[0] = get_class($callback[0]); + } + + return $callback[0] . '::' . $callback[1]; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.4 + */ + +/** + * Constraint that asserts that the Traversable it is applied to contains + * only values of a given type. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.4 + */ +class PHPUnit_Framework_Constraint_TraversableContainsOnly extends PHPUnit_Framework_Constraint +{ + /** + * @var PHPUnit_Framework_Constraint + */ + protected $constraint; + + /** + * @var string + */ + protected $type; + + /** + * @param string $type + * @param boolean $isNativeType + */ + public function __construct($type, $isNativeType = true) + { + parent::__construct(); + + if ($isNativeType) { + $this->constraint = new PHPUnit_Framework_Constraint_IsType($type); + } else { + $this->constraint = new PHPUnit_Framework_Constraint_IsInstanceOf( + $type + ); + } + + $this->type = $type; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + $success = true; + + foreach ($other as $item) { + if (!$this->constraint->evaluate($item, '', true)) { + $success = false; + break; + } + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $this->fail($other, $description); + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'contains only values of type "' . $this->type . '"'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.0 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.0 + */ + +class PHPUnit_Framework_Constraint_Attribute extends PHPUnit_Framework_Constraint_Composite +{ + /** + * @var string + */ + protected $attributeName; + + /** + * @param PHPUnit_Framework_Constraint $constraint + * @param string $attributeName + */ + public function __construct(PHPUnit_Framework_Constraint $constraint, $attributeName) + { + parent::__construct($constraint); + + $this->attributeName = $attributeName; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + return parent::evaluate( + PHPUnit_Framework_Assert::readAttribute( + $other, $this->attributeName + ), + $description, + $returnResult + ); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'attribute "' . $this->attributeName . '" ' . + $this->innerConstraint->toString(); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return $this->toString(); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the value it is evaluated for is less than + * a given value. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_LessThan extends PHPUnit_Framework_Constraint +{ + /** + * @var numeric + */ + protected $value; + + /** + * @param numeric $value + */ + public function __construct($value) + { + parent::__construct(); + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return $this->value > $other; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is less than ' . $this->exporter->export($this->value); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Bastian Feder + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause + * @link http://www.phpunit.de/ + * @since File available since Release 3.7.0 + */ + +/** + * Asserts whether or not two JSON objects are equal. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Bastian Feder + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause + * @link http://www.phpunit.de/ + * @since Class available since Release 3.7.0 + */ +class PHPUnit_Framework_Constraint_JsonMatches extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $value; + + /** + * Creates a new constraint. + * + * @param string $value + */ + public function __construct($value) + { + parent::__construct(); + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * This method can be overridden to implement the evaluation algorithm. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + $decodedOther = json_decode($other); + if (json_last_error()) { + return false; + } + + $decodedValue = json_decode($this->value); + if (json_last_error()) { + return false; + } + + return $decodedOther == $decodedValue; + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return sprintf( + 'matches JSON string "%s"', + $this->value + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the value it is evaluated for is greater + * than a given value. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_GreaterThan extends PHPUnit_Framework_Constraint +{ + /** + * @var numeric + */ + protected $value; + + /** + * @param numeric $value + */ + public function __construct($value) + { + parent::__construct(); + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return $this->value < $other; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is greater than ' . $this->exporter->export($this->value); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the Traversable it is applied to contains + * a given value. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_TraversableContains extends PHPUnit_Framework_Constraint +{ + /** + * @var boolean + */ + protected $checkForObjectIdentity; + + /** + * @var boolean + */ + protected $checkForNonObjectIdentity; + + /** + * @var mixed + */ + protected $value; + + /** + * @param mixed $value + * @param boolean $checkForObjectIdentity + * @param boolean $checkForNonObjectIdentity + * @throws PHPUnit_Framework_Exception + */ + public function __construct($value, $checkForObjectIdentity = true, $checkForNonObjectIdentity = false) + { + parent::__construct(); + + if (!is_bool($checkForObjectIdentity)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'boolean'); + } + + if (!is_bool($checkForNonObjectIdentity)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'boolean'); + } + + $this->checkForObjectIdentity = $checkForObjectIdentity; + $this->checkForNonObjectIdentity = $checkForNonObjectIdentity; + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + if ($other instanceof SplObjectStorage) { + return $other->contains($this->value); + } + + if (is_object($this->value)) { + foreach ($other as $element) { + if (($this->checkForObjectIdentity && + $element === $this->value) || + (!$this->checkForObjectIdentity && + $element == $this->value)) { + return true; + } + } + } else { + foreach ($other as $element) { + if (($this->checkForNonObjectIdentity && + $element === $this->value) || + (!$this->checkForNonObjectIdentity && + $element == $this->value)) { + return true; + } + } + } + + return false; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + if (is_string($this->value) && strpos($this->value, "\n") !== false) { + return 'contains "' . $this->value . '"'; + } else { + return 'contains ' . $this->exporter->export($this->value); + } + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + '%s %s', + + is_array($other) ? 'an array' : 'a traversable', + $this->toString() + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that checks if the file(name) that it is evaluated for exists. + * + * The file path to check is passed as $other in evaluate(). + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_FileExists extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return file_exists($other); + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + return sprintf( + 'file "%s" exists', + + $other + ); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'file exists'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that accepts any input value. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_IsAnything extends PHPUnit_Framework_Constraint +{ + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + return $returnResult ? true : null; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'is anything'; + } + + /** + * Counts the number of constraint elements. + * + * @return integer + * @since Method available since Release 3.5.0 + */ + public function count() + { + return 0; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that the object it is evaluated for has a given + * attribute. + * + * The attribute name is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_ObjectHasAttribute extends PHPUnit_Framework_Constraint_ClassHasAttribute +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + $object = new ReflectionObject($other); + + return $object->hasProperty($this->attributeName); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Bastian Feder + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause + * @link http://www.phpunit.de/ + * @since File available since Release 3.7.0 + */ + +/** + * Provides human readable messages for each JSON error. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Bastian Feder + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause + * @link http://www.phpunit.de/ + * @since Class available since Release 3.7.0 + */ +class PHPUnit_Framework_Constraint_JsonMatches_ErrorMessageProvider +{ + /** + * Translates JSON error to a human readable string. + * + * @param string $error + * @return string + */ + public static function determineJsonError($error, $prefix = '') + { + switch ($error) { + case JSON_ERROR_NONE: + return; + case JSON_ERROR_DEPTH: + return $prefix . 'Maximum stack depth exceeded'; + case JSON_ERROR_STATE_MISMATCH: + return $prefix . 'Underflow or the modes mismatch'; + case JSON_ERROR_CTRL_CHAR: + return $prefix . 'Unexpected control character found'; + case JSON_ERROR_SYNTAX: + return $prefix . 'Syntax error, malformed JSON'; + case JSON_ERROR_UTF8: + return $prefix . 'Malformed UTF-8 characters, possibly incorrectly encoded'; + default: + return $prefix . 'Unknown error'; + } + } + + /** + * Translates a given type to a human readable message prefix. + * + * @param string $type + * @return string + */ + public static function translateTypeToPrefix($type) + { + switch (strtolower($type)) { + case 'expected': + $prefix = 'Expected value JSON decode error - '; + break; + case 'actual': + $prefix = 'Actual value JSON decode error - '; + break; + default: + $prefix = ''; + break; + } + + return $prefix; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.0 + */ + +/** + * Constraint that asserts that the class it is evaluated for has a given + * static attribute. + * + * The attribute name is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.0 + */ +class PHPUnit_Framework_Constraint_ClassHasStaticAttribute extends PHPUnit_Framework_Constraint_ClassHasAttribute +{ + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + $class = new ReflectionClass($other); + + if ($class->hasProperty($this->attributeName)) { + $attribute = $class->getProperty($this->attributeName); + + return $attribute->isStatic(); + } else { + return false; + } + } + + /** + * Returns a string representation of the constraint. + * + * @return string + * @since Method available since Release 3.3.0 + */ + public function toString() + { + return sprintf( + 'has static attribute "%s"', + + $this->attributeName + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.6 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.6 + */ +class PHPUnit_Framework_Constraint_Exception extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $className; + + /** + * @param string $className + */ + public function __construct($className) + { + parent::__construct(); + $this->className = $className; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return $other instanceof $this->className; + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + if ($other !== null) { + $message = ''; + if ($other instanceof Exception) { + $message = '. Message was: "' . $other->getMessage() . '" at' + . "\n" . $other->getTraceAsString(); + } + + return sprintf( + 'exception of type "%s" matches expected exception "%s"%s', + + get_class($other), + $this->className, + $message + ); + } + + return sprintf( + 'exception of type "%s" is thrown', + + $this->className + ); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return sprintf( + 'exception of type "%s"', + + $this->className + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * Constraint that asserts that the string it is evaluated for ends with a given + * suffix. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +class PHPUnit_Framework_Constraint_StringEndsWith extends PHPUnit_Framework_Constraint +{ + /** + * @var string + */ + protected $suffix; + + /** + * @param string $suffix + */ + public function __construct($suffix) + { + parent::__construct(); + $this->suffix = $suffix; + } + + /** + * Evaluates the constraint for parameter $other. Returns true if the + * constraint is met, false otherwise. + * + * @param mixed $other Value or object to evaluate. + * @return bool + */ + protected function matches($other) + { + return substr($other, 0 - strlen($this->suffix)) == $this->suffix; + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + return 'ends with "' . $this->suffix . '"'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Constraint that asserts that one value is identical to another. + * + * Identical check is performed with PHP's === operator, the operator is + * explained in detail at + * {@url http://www.php.net/manual/en/types.comparisons.php}. + * Two values are identical if they have the same value and are of the same + * type. + * + * The expected value is passed in the constructor. + * + * @package PHPUnit + * @subpackage Framework_Constraint + * @author Sebastian Bergmann + * @author Bernhard Schussek + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Framework_Constraint_IsIdentical extends PHPUnit_Framework_Constraint +{ + /** + * @var float + */ + const EPSILON = 0.0000000001; + + /** + * @var mixed + */ + protected $value; + + /** + * @param mixed $value + */ + public function __construct($value) + { + parent::__construct(); + $this->value = $value; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $returnResult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $returnResult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $returnResult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $returnResult = false) + { + if (is_double($this->value) && is_double($other) && + !is_infinite($this->value) && !is_infinite($other) && + !is_nan($this->value) && !is_nan($other)) { + $success = abs($this->value - $other) < self::EPSILON; + } else { + $success = $this->value === $other; + } + + if ($returnResult) { + return $success; + } + + if (!$success) { + $f = null; + + // if both values are strings, make sure a diff is generated + if (is_string($this->value) && is_string($other)) { + $f = new SebastianBergmann\Comparator\ComparisonFailure( + $this->value, + $other, + $this->value, + $other + ); + } + + $this->fail($other, $description, $f); + } + } + + /** + * Returns the description of the failure + * + * The beginning of failure messages is "Failed asserting that" in most + * cases. This method should return the second part of that sentence. + * + * @param mixed $other Evaluated value or object. + * @return string + */ + protected function failureDescription($other) + { + if (is_object($this->value) && is_object($other)) { + return 'two variables reference the same object'; + } + + if (is_string($this->value) && is_string($other)) { + return 'two strings are identical'; + } + + return parent::failureDescription($other); + } + + /** + * Returns a string representation of the constraint. + * + * @return string + */ + public function toString() + { + if (is_object($this->value)) { + return 'is identical to an object of class "' . + get_class($this->value) . '"'; + } else { + return 'is identical to ' . + $this->exporter->export($this->value); + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Error + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * Wrapper for PHP deprecated errors. + * You can disable deprecated-to-exception conversion by setting + * + * + * PHPUnit_Framework_Error_Deprecated::$enabled = false; + * + * + * @package PHPUnit + * @subpackage Framework_Error + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Framework_Error_Deprecated extends PHPUnit_Framework_Error +{ + public static $enabled = true; +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Error + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * Wrapper for PHP notices. + * You can disable notice-to-exception conversion by setting + * + * + * PHPUnit_Framework_Error_Notice::$enabled = false; + * + * + * @package PHPUnit + * @subpackage Framework_Error + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Framework_Error_Notice extends PHPUnit_Framework_Error +{ + public static $enabled = true; +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework_Error + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * Wrapper for PHP warnings. + * You can disable notice-to-exception conversion by setting + * + * + * PHPUnit_Framework_Error_Warning::$enabled = false; + * + * + * @package PHPUnit + * @subpackage Framework_Error + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Framework_Error_Warning extends PHPUnit_Framework_Error +{ + public static $enabled = true; +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +class PHPUnit_Framework_Exception extends RuntimeException implements PHPUnit_Exception +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Giorgio Sironi + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * An empty Listener that can be extended to implement TestListener + * with just a few lines of code. + * @see PHPUnit_Framework_TestListener for documentation on the API methods. + * + * @package PHPUnit + * @subpackage Framework + * @author Giorgio Sironi + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +abstract class PHPUnit_Framework_BaseTestListener implements PHPUnit_Framework_TestListener +{ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {} + + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {} + + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) {} + + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) {} + + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) {} + + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) {} + + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) {} + + public function startTest(PHPUnit_Framework_Test $test) {} + + public function endTest(PHPUnit_Framework_Test $test, $time) {} +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * Extension to PHPUnit_Framework_AssertionFailedError to mark the special + * case of a test test that unintentionally covers code. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Framework_UnintentionallyCoveredCodeError extends PHPUnit_Framework_RiskyTestError +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_Log + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * A TestListener that generates a logfile of the + * test execution using the Test Anything Protocol (TAP). + * + * @package PHPUnit + * @subpackage Util_Log + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Util_Log_TAP extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener +{ + /** + * @var integer + */ + protected $testNumber = 0; + + /** + * @var integer + */ + protected $testSuiteLevel = 0; + + /** + * @var boolean + */ + protected $testSuccessful = true; + + /** + * Constructor. + * + * @param mixed $out + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.3.4 + */ + public function __construct($out = null) + { + parent::__construct($out); + $this->write("TAP version 13\n"); + } + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeNotOk($test, 'Error'); + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + $this->writeNotOk($test, 'Failure'); + + $message = explode( + "\n", PHPUnit_Framework_TestFailure::exceptionToString($e) + ); + + $diagnostic = array( + 'message' => $message[0], + 'severity' => 'fail' + ); + + if ($e instanceof PHPUnit_Framework_ExpectationFailedException) { + $cf = $e->getComparisonFailure(); + + if ($cf !== null) { + $diagnostic['data'] = array( + 'got' => $cf->getActual(), + 'expected' => $cf->getExpected() + ); + } + } + + $yaml = new Symfony\Component\Yaml\Dumper; + + $this->write( + sprintf( + " ---\n%s ...\n", + $yaml->dump($diagnostic, 2, 2) + ) + ); + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeNotOk($test, '', 'TODO Incomplete Test'); + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->write( + sprintf( + "ok %d - # RISKY%s\n", + + $this->testNumber, + $e->getMessage() != '' ? ' ' . $e->getMessage() : '' + ) + ); + + $this->testSuccessful = false; + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->write( + sprintf( + "ok %d - # SKIP%s\n", + + $this->testNumber, + $e->getMessage() != '' ? ' ' . $e->getMessage() : '' + ) + ); + + $this->testSuccessful = false; + } + + /** + * A testsuite started. + * + * @param PHPUnit_Framework_TestSuite $suite + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $this->testSuiteLevel++; + } + + /** + * A testsuite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $this->testSuiteLevel--; + + if ($this->testSuiteLevel == 0) { + $this->write(sprintf("1..%d\n", $this->testNumber)); + } + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + $this->testNumber++; + $this->testSuccessful = true; + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + if ($this->testSuccessful === true) { + $this->write( + sprintf( + "ok %d - %s\n", + + $this->testNumber, + PHPUnit_Util_Test::describe($test) + ) + ); + } + } + + /** + * @param PHPUnit_Framework_Test $test + * @param string $prefix + * @param string $directive + */ + protected function writeNotOk(PHPUnit_Framework_Test $test, $prefix = '', $directive = '') + { + $this->write( + sprintf( + "not ok %d - %s%s%s\n", + + $this->testNumber, + $prefix != '' ? $prefix . ': ' : '', + PHPUnit_Util_Test::describe($test), + $directive != '' ? ' # ' . $directive : '' + ) + ); + + $this->testSuccessful = false; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_Log + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +if (!defined('JSON_PRETTY_PRINT')) { + define('JSON_PRETTY_PRINT', 128); +} + +/** + * A TestListener that generates JSON messages. + * + * @package PHPUnit + * @subpackage Util_Log + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Util_Log_JSON extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener +{ + /** + * @var string + */ + protected $currentTestSuiteName = ''; + + /** + * @var string + */ + protected $currentTestName = ''; + + /** + * @var boolean + * @access private + */ + protected $currentTestPass = true; + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeCase( + 'error', + $time, + PHPUnit_Util_Filter::getFilteredStacktrace($e, false), + $e->getMessage(), + $test + ); + + $this->currentTestPass = false; + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + $this->writeCase( + 'fail', + $time, + PHPUnit_Util_Filter::getFilteredStacktrace($e, false), + $e->getMessage(), + $test + ); + + $this->currentTestPass = false; + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeCase( + 'error', + $time, + PHPUnit_Util_Filter::getFilteredStacktrace($e, false), + 'Incomplete Test: ' . $e->getMessage(), + $test + ); + + $this->currentTestPass = false; + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeCase( + 'error', + $time, + PHPUnit_Util_Filter::getFilteredStacktrace($e, false), + 'Risky Test: ' . $e->getMessage(), + $test + ); + + $this->currentTestPass = false; + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeCase( + 'error', + $time, + PHPUnit_Util_Filter::getFilteredStacktrace($e, false), + 'Skipped Test: ' . $e->getMessage(), + $test + ); + + $this->currentTestPass = false; + } + + /** + * A testsuite started. + * + * @param PHPUnit_Framework_TestSuite $suite + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $this->currentTestSuiteName = $suite->getName(); + $this->currentTestName = ''; + + $this->write( + array( + 'event' => 'suiteStart', + 'suite' => $this->currentTestSuiteName, + 'tests' => count($suite) + ) + ); + } + + /** + * A testsuite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $this->currentTestSuiteName = ''; + $this->currentTestName = ''; + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + $this->currentTestName = PHPUnit_Util_Test::describe($test); + $this->currentTestPass = true; + + $this->write( + array( + 'event' => 'testStart', + 'suite' => $this->currentTestSuiteName, + 'test' => $this->currentTestName + ) + ); + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + if ($this->currentTestPass) { + $this->writeCase('pass', $time, array(), '', $test); + } + } + + /** + * @param string $status + * @param float $time + * @param array $trace + * @param string $message + */ + protected function writeCase($status, $time, array $trace = array(), $message = '', $test = null) + { + $output = ''; + // take care of TestSuite producing error (e.g. by running into exception) as TestSuite doesn't have hasOutput + if ($test !== null && method_exists($test, 'hasOutput') && $test->hasOutput()) { + $output = $test->getActualOutput(); + } + $this->write( + array( + 'event' => 'test', + 'suite' => $this->currentTestSuiteName, + 'test' => $this->currentTestName, + 'status' => $status, + 'time' => $time, + 'trace' => $trace, + 'message' => PHPUnit_Util_String::convertToUtf8($message), + 'output' => $output, + ) + ); + } + + /** + * @param string $buffer + */ + public function write($buffer) + { + array_walk_recursive($buffer, function (&$input) { + if (is_string($input)) { + $input = PHPUnit_Util_String::convertToUtf8($input); + } + }); + + parent::write(json_encode($buffer, JSON_PRETTY_PRINT)); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_Log + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +/** + * A TestListener that generates a logfile of the test execution in XML markup. + * + * The XML markup used is the same as the one that is used by the JUnit Ant task. + * + * @package PHPUnit + * @subpackage Util_Log + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.1.0 + */ +class PHPUnit_Util_Log_JUnit extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener +{ + /** + * @var DOMDocument + */ + protected $document; + + /** + * @var DOMElement + */ + protected $root; + + /** + * @var boolean + */ + protected $logIncompleteSkipped = false; + + /** + * @var boolean + */ + protected $writeDocument = true; + + /** + * @var DOMElement[] + */ + protected $testSuites = array(); + + /** + * @var integer[] + */ + protected $testSuiteTests = array(0); + + /** + * @var integer[] + */ + protected $testSuiteAssertions = array(0); + + /** + * @var integer[] + */ + protected $testSuiteErrors = array(0); + + /** + * @var integer[] + */ + protected $testSuiteFailures = array(0); + + /** + * @var integer[] + */ + protected $testSuiteTimes = array(0); + + /** + * @var integer + */ + protected $testSuiteLevel = 0; + + /** + * @var DOMElement + */ + protected $currentTestCase = null; + + /** + * @var boolean + */ + protected $attachCurrentTestCase = true; + + /** + * Constructor. + * + * @param mixed $out + * @param boolean $logIncompleteSkipped + */ + public function __construct($out = null, $logIncompleteSkipped = false) + { + $this->document = new DOMDocument('1.0', 'UTF-8'); + $this->document->formatOutput = true; + + $this->root = $this->document->createElement('testsuites'); + $this->document->appendChild($this->root); + + parent::__construct($out); + + $this->logIncompleteSkipped = $logIncompleteSkipped; + } + + /** + * Flush buffer and close output. + * + */ + public function flush() + { + if ($this->writeDocument === true) { + $this->write($this->getXML()); + } + + parent::flush(); + } + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($this->currentTestCase !== null) { + if ($test instanceof PHPUnit_Framework_SelfDescribing) { + $buffer = $test->toString() . "\n"; + } else { + $buffer = ''; + } + + $buffer .= PHPUnit_Framework_TestFailure::exceptionToString($e) . + "\n" . + PHPUnit_Util_Filter::getFilteredStacktrace($e); + + $error = $this->document->createElement( + 'error', PHPUnit_Util_XML::prepareString($buffer) + ); + + $error->setAttribute('type', get_class($e)); + + $this->currentTestCase->appendChild($error); + + $this->testSuiteErrors[$this->testSuiteLevel]++; + } + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + if ($this->currentTestCase !== null) { + if (!$test instanceof PHPUnit_Framework_Warning) { + if ($test instanceof PHPUnit_Framework_SelfDescribing) { + $buffer = $test->toString() . "\n"; + } else { + $buffer = ''; + } + + $buffer .= PHPUnit_Framework_TestFailure::exceptionToString($e) . + "\n" . + PHPUnit_Util_Filter::getFilteredStacktrace($e); + + $failure = $this->document->createElement( + 'failure', PHPUnit_Util_XML::prepareString($buffer) + ); + + $failure->setAttribute('type', get_class($e)); + + $this->currentTestCase->appendChild($failure); + + $this->testSuiteFailures[$this->testSuiteLevel]++; + } + } + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($this->logIncompleteSkipped && $this->currentTestCase !== null) { + $error = $this->document->createElement( + 'error', + PHPUnit_Util_XML::prepareString( + "Incomplete Test\n" . + PHPUnit_Util_Filter::getFilteredStacktrace($e) + ) + ); + + $error->setAttribute('type', get_class($e)); + + $this->currentTestCase->appendChild($error); + + $this->testSuiteErrors[$this->testSuiteLevel]++; + } else { + $this->attachCurrentTestCase = false; + } + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($this->logIncompleteSkipped && $this->currentTestCase !== null) { + $error = $this->document->createElement( + 'error', + PHPUnit_Util_XML::prepareString( + "Risky Test\n" . + PHPUnit_Util_Filter::getFilteredStacktrace($e) + ) + ); + + $error->setAttribute('type', get_class($e)); + + $this->currentTestCase->appendChild($error); + + $this->testSuiteErrors[$this->testSuiteLevel]++; + } else { + $this->attachCurrentTestCase = false; + } + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($this->logIncompleteSkipped && $this->currentTestCase !== null) { + $error = $this->document->createElement( + 'error', + PHPUnit_Util_XML::prepareString( + "Skipped Test\n" . + PHPUnit_Util_Filter::getFilteredStacktrace($e) + ) + ); + + $error->setAttribute('type', get_class($e)); + + $this->currentTestCase->appendChild($error); + + $this->testSuiteErrors[$this->testSuiteLevel]++; + } else { + $this->attachCurrentTestCase = false; + } + } + + /** + * A testsuite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $testSuite = $this->document->createElement('testsuite'); + $testSuite->setAttribute('name', $suite->getName()); + + if (class_exists($suite->getName(), false)) { + try { + $class = new ReflectionClass($suite->getName()); + + $testSuite->setAttribute('file', $class->getFileName()); + } catch (ReflectionException $e) { + } + } + + if ($this->testSuiteLevel > 0) { + $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite); + } else { + $this->root->appendChild($testSuite); + } + + $this->testSuiteLevel++; + $this->testSuites[$this->testSuiteLevel] = $testSuite; + $this->testSuiteTests[$this->testSuiteLevel] = 0; + $this->testSuiteAssertions[$this->testSuiteLevel] = 0; + $this->testSuiteErrors[$this->testSuiteLevel] = 0; + $this->testSuiteFailures[$this->testSuiteLevel] = 0; + $this->testSuiteTimes[$this->testSuiteLevel] = 0; + } + + /** + * A testsuite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'tests', $this->testSuiteTests[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'assertions', $this->testSuiteAssertions[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'failures', $this->testSuiteFailures[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'errors', $this->testSuiteErrors[$this->testSuiteLevel] + ); + + $this->testSuites[$this->testSuiteLevel]->setAttribute( + 'time', sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]) + ); + + if ($this->testSuiteLevel > 1) { + $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel]; + $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel]; + $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel]; + $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel]; + $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel]; + } + + $this->testSuiteLevel--; + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + if (!$test instanceof PHPUnit_Framework_Warning) { + $testCase = $this->document->createElement('testcase'); + $testCase->setAttribute('name', $test->getName()); + + if ($test instanceof PHPUnit_Framework_TestCase) { + $class = new ReflectionClass($test); + $methodName = $test->getName(); + + if ($class->hasMethod($methodName)) { + $method = $class->getMethod($test->getName()); + + $testCase->setAttribute('class', $class->getName()); + $testCase->setAttribute('file', $class->getFileName()); + $testCase->setAttribute('line', $method->getStartLine()); + } + } + + $this->currentTestCase = $testCase; + } + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + if (!$test instanceof PHPUnit_Framework_Warning) { + if ($this->attachCurrentTestCase) { + if ($test instanceof PHPUnit_Framework_TestCase) { + $numAssertions = $test->getNumAssertions(); + $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions; + + $this->currentTestCase->setAttribute( + 'assertions', $numAssertions + ); + } + + $this->currentTestCase->setAttribute( + 'time', sprintf('%F', $time) + ); + + $this->testSuites[$this->testSuiteLevel]->appendChild( + $this->currentTestCase + ); + + $this->testSuiteTests[$this->testSuiteLevel]++; + $this->testSuiteTimes[$this->testSuiteLevel] += $time; + + if (method_exists($test, 'hasOutput') && $test->hasOutput()) { + $systemOut = $this->document->createElement('system-out'); + $systemOut->appendChild( + $this->document->createTextNode($test->getActualOutput()) + ); + $this->currentTestCase->appendChild($systemOut); + } + } + } + + $this->attachCurrentTestCase = true; + $this->currentTestCase = null; + } + + /** + * Returns the XML as a string. + * + * @return string + * @since Method available since Release 2.2.0 + */ + public function getXML() + { + return $this->document->saveXML(); + } + + /** + * Enables or disables the writing of the document + * in flush(). + * + * This is a "hack" needed for the integration of + * PHPUnit with Phing. + * + * @return string + * @since Method available since Release 2.2.0 + */ + public function setWriteDocument($flag) + { + if (is_bool($flag)) { + $this->writeDocument = $flag; + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * Utility methods for PHP sub-processes. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +abstract class PHPUnit_Util_PHP +{ + /** + * @return PHPUnit_Util_PHP + * @since Method available since Release 3.5.12 + */ + public static function factory() + { + if (DIRECTORY_SEPARATOR == '\\') { + return new PHPUnit_Util_PHP_Windows; + } + + return new PHPUnit_Util_PHP_Default; + } + + /** + * Runs a single test in a separate PHP process. + * + * @param string $job + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_TestResult $result + * @throws PHPUnit_Framework_Exception + */ + public function runTestJob($job, PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result) + { + $result->startTest($test); + + $_result = $this->runJob($job); + + $this->processChildResult( + $test, $result, $_result['stdout'], $_result['stderr'] + ); + } + + /** + * Runs a single job (PHP code) using a separate PHP process. + * + * @param string $job + * @param array $settings + * @return array + * @throws PHPUnit_Framework_Exception + */ + abstract public function runJob($job, array $settings = array()); + + /** + * @param array $settings + * @return string + * @since Method available since Release 4.0.0 + */ + protected function settingsToParameters(array $settings) + { + $buffer = ''; + + foreach ($settings as $setting) { + $buffer .= ' -d ' . $setting; + } + + return $buffer; + } + + /** + * Processes the TestResult object from an isolated process. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_TestResult $result + * @param string $stdout + * @param string $stderr + * @since Method available since Release 3.5.0 + */ + private function processChildResult(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result, $stdout, $stderr) + { + $time = 0; + + if (!empty($stderr)) { + $result->addError( + $test, + new PHPUnit_Framework_Exception(trim($stderr)), $time + ); + } else { + set_error_handler(function ($errno, $errstr, $errfile, $errline) { + throw new ErrorException($errstr, $errno, $errno, $errfile, $errline); + }); + try { + if (strpos($stdout, "#!/usr/bin/env php\n") === 0) { + $stdout = substr($stdout, 19); + } + + $childResult = unserialize(str_replace("#!/usr/bin/env php\n", '', $stdout)); + restore_error_handler(); + } catch (ErrorException $e) { + restore_error_handler(); + $childResult = false; + + $result->addError( + $test, new PHPUnit_Framework_Exception(trim($stdout), 0, $e), $time + ); + } + + if ($childResult !== false) { + if (!empty($childResult['output'])) { + print $childResult['output']; + } + + $test->setResult($childResult['testResult']); + $test->addToAssertionCount($childResult['numAssertions']); + + $childResult = $childResult['result']; + + if ($result->getCollectCodeCoverageInformation()) { + $result->getCodeCoverage()->merge( + $childResult->getCodeCoverage() + ); + } + + $time = $childResult->time(); + $notImplemented = $childResult->notImplemented(); + $risky = $childResult->risky(); + $skipped = $childResult->skipped(); + $errors = $childResult->errors(); + $failures = $childResult->failures(); + + if (!empty($notImplemented)) { + $result->addError( + $test, $this->getException($notImplemented[0]), $time + ); + } elseif (!empty($risky)) { + $result->addError( + $test, $this->getException($risky[0]), $time + ); + } elseif (!empty($skipped)) { + $result->addError( + $test, $this->getException($skipped[0]), $time + ); + } elseif (!empty($errors)) { + $result->addError( + $test, $this->getException($errors[0]), $time + ); + } elseif (!empty($failures)) { + $result->addFailure( + $test, $this->getException($failures[0]), $time + ); + } + } + } + + $result->endTest($test, $time); + } + + /** + * Gets the thrown exception from a PHPUnit_Framework_TestFailure. + * + * @param PHPUnit_Framework_TestFailure $error + * @return Exception + * @since Method available since Release 3.6.0 + * @see https://github.com/sebastianbergmann/phpunit/issues/74 + */ + private function getException(PHPUnit_Framework_TestFailure $error) + { + $exception = $error->thrownException(); + + if ($exception instanceof __PHP_Incomplete_Class) { + $exceptionArray = array(); + foreach ((array) $exception as $key => $value) { + $key = substr($key, strrpos($key, "\0") + 1); + $exceptionArray[$key] = $value; + } + + $exception = new PHPUnit_Framework_SyntheticError( + sprintf( + '%s: %s', + $exceptionArray['_PHP_Incomplete_Class_Name'], + $exceptionArray['message'] + ), + $exceptionArray['code'], + $exceptionArray['file'], + $exceptionArray['line'], + $exceptionArray['trace'] + ); + } + + return $exception; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.2.0 + */ + +/** + * XML helpers. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.2.0 + */ +class PHPUnit_Util_XML +{ + /** + * Escapes a string for the use in XML documents + * Any Unicode character is allowed, excluding the surrogate blocks, FFFE, + * and FFFF (not even as character reference). + * See http://www.w3.org/TR/xml/#charsets + * + * @param string $string + * @return string + * @author Kore Nordmann + * @since Method available since Release 3.4.6 + */ + public static function prepareString($string) + { + return preg_replace( + '/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/', + '', + htmlspecialchars( + PHPUnit_Util_String::convertToUtf8($string), ENT_QUOTES, 'UTF-8' + ) + ); + } + + /** + * Loads an XML (or HTML) file into a DOMDocument object. + * + * @param string $filename + * @param boolean $isHtml + * @param boolean $xinclude + * @return DOMDocument + * @since Method available since Release 3.3.0 + */ + public static function loadFile($filename, $isHtml = false, $xinclude = false) + { + $reporting = error_reporting(0); + $contents = file_get_contents($filename); + error_reporting($reporting); + + if ($contents === false) { + throw new PHPUnit_Framework_Exception( + sprintf( + 'Could not read "%s".', + $filename + ) + ); + } + + return self::load($contents, $isHtml, $filename, $xinclude); + } + + /** + * Load an $actual document into a DOMDocument. This is called + * from the selector assertions. + * + * If $actual is already a DOMDocument, it is returned with + * no changes. Otherwise, $actual is loaded into a new DOMDocument + * as either HTML or XML, depending on the value of $isHtml. If $isHtml is + * false and $xinclude is true, xinclude is performed on the loaded + * DOMDocument. + * + * Note: prior to PHPUnit 3.3.0, this method loaded a file and + * not a string as it currently does. To load a file into a + * DOMDocument, use loadFile() instead. + * + * @param string|DOMDocument $actual + * @param boolean $isHtml + * @param string $filename + * @param boolean $xinclude + * @return DOMDocument + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + * @author Tobias Schlitt + */ + public static function load($actual, $isHtml = false, $filename = '', $xinclude = false) + { + if ($actual instanceof DOMDocument) { + return $actual; + } + + $document = new DOMDocument; + + $internal = libxml_use_internal_errors(true); + $message = ''; + $reporting = error_reporting(0); + + if ($isHtml) { + $loaded = $document->loadHTML($actual); + } else { + $loaded = $document->loadXML($actual); + } + + if ('' !== $filename) { + // Necessary for xinclude + $document->documentURI = $filename; + } + + if (!$isHtml && $xinclude) { + $document->xinclude(); + } + + foreach (libxml_get_errors() as $error) { + $message .= $error->message; + } + + libxml_use_internal_errors($internal); + error_reporting($reporting); + + if ($loaded === false) { + if ($filename != '') { + throw new PHPUnit_Framework_Exception( + sprintf( + 'Could not load "%s".%s', + + $filename, + $message != '' ? "\n" . $message : '' + ) + ); + } else { + throw new PHPUnit_Framework_Exception($message); + } + } + + return $document; + } + + /** + * + * + * @param DOMNode $node + * @return string + * @since Method available since Release 3.4.0 + */ + public static function nodeToText(DOMNode $node) + { + if ($node->childNodes->length == 1) { + return $node->nodeValue; + } + + $result = ''; + + foreach ($node->childNodes as $childNode) { + $result .= $node->ownerDocument->saveXML($childNode); + } + + return $result; + } + + /** + * + * + * @param DOMNode $node + * @since Method available since Release 3.3.0 + * @author Mattis Stordalen Flister + */ + public static function removeCharacterDataNodes(DOMNode $node) + { + if ($node->hasChildNodes()) { + for ($i = $node->childNodes->length - 1; $i >= 0; $i--) { + if (($child = $node->childNodes->item($i)) instanceof DOMCharacterData) { + $node->removeChild($child); + } + } + } + } + + /** + * "Convert" a DOMElement object into a PHP variable. + * + * @param DOMElement $element + * @return mixed + * @since Method available since Release 3.4.0 + */ + public static function xmlToVariable(DOMElement $element) + { + $variable = null; + + switch ($element->tagName) { + case 'array': { + $variable = array(); + + foreach ($element->getElementsByTagName('element') as $element) { + $value = self::xmlToVariable($element->childNodes->item(1)); + + if ($element->hasAttribute('key')) { + $variable[(string) $element->getAttribute('key')] = $value; + } else { + $variable[] = $value; + } + } + } + break; + + case 'object': { + $className = $element->getAttribute('class'); + + if ($element->hasChildNodes()) { + $arguments = $element->childNodes->item(1)->childNodes; + $constructorArgs = array(); + + foreach ($arguments as $argument) { + if ($argument instanceof DOMElement) { + $constructorArgs[] = self::xmlToVariable($argument); + } + } + + $class = new ReflectionClass($className); + $variable = $class->newInstanceArgs($constructorArgs); + } else { + $variable = new $className; + } + } + break; + + case 'boolean': { + $variable = $element->nodeValue == 'true' ? true : false; + } + break; + + case 'integer': + case 'double': + case 'string': { + $variable = $element->nodeValue; + + settype($variable, $element->tagName); + } + break; + } + + return $variable; + } + + /** + * Validate list of keys in the associative array. + * + * @param array $hash + * @param array $validKeys + * @return array + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function assertValidKeys(array $hash, array $validKeys) + { + $valids = array(); + + // Normalize validation keys so that we can use both indexed and + // associative arrays. + foreach ($validKeys as $key => $val) { + is_int($key) ? $valids[$val] = null : $valids[$key] = $val; + } + + $validKeys = array_keys($valids); + + // Check for invalid keys. + foreach ($hash as $key => $value) { + if (!in_array($key, $validKeys)) { + $unknown[] = $key; + } + } + + if (!empty($unknown)) { + throw new PHPUnit_Framework_Exception( + 'Unknown key(s): ' . implode(', ', $unknown) + ); + } + + // Add default values for any valid keys that are empty. + foreach ($valids as $key => $value) { + if (!isset($hash[$key])) { + $hash[$key] = $value; + } + } + + return $hash; + } + + /** + * Parse a CSS selector into an associative array suitable for + * use with findNodes(). + * + * @param string $selector + * @param mixed $content + * @return array + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + public static function convertSelectToTag($selector, $content = true) + { + $selector = trim(preg_replace("/\s+/", " ", $selector)); + + // substitute spaces within attribute value + while (preg_match('/\[[^\]]+"[^"]+\s[^"]+"\]/', $selector)) { + $selector = preg_replace( + '/(\[[^\]]+"[^"]+)\s([^"]+"\])/', "$1__SPACE__$2", $selector + ); + } + + if (strstr($selector, ' ')) { + $elements = explode(' ', $selector); + } else { + $elements = array($selector); + } + + $previousTag = array(); + + foreach (array_reverse($elements) as $element) { + $element = str_replace('__SPACE__', ' ', $element); + + // child selector + if ($element == '>') { + $previousTag = array('child' => $previousTag['descendant']); + continue; + } + + // adjacent-sibling selector + if ($element == '+') { + $previousTag = array('adjacent-sibling' => $previousTag['descendant']); + continue; + } + + $tag = array(); + + // match element tag + preg_match("/^([^\.#\[]*)/", $element, $eltMatches); + + if (!empty($eltMatches[1])) { + $tag['tag'] = $eltMatches[1]; + } + + // match attributes (\[[^\]]*\]*), ids (#[^\.#\[]*), + // and classes (\.[^\.#\[]*)) + preg_match_all( + "/(\[[^\]]*\]*|#[^\.#\[]*|\.[^\.#\[]*)/", $element, $matches + ); + + if (!empty($matches[1])) { + $classes = array(); + $attrs = array(); + + foreach ($matches[1] as $match) { + // id matched + if (substr($match, 0, 1) == '#') { + $tag['id'] = substr($match, 1); + } + + // class matched + else if (substr($match, 0, 1) == '.') { + $classes[] = substr($match, 1); + } + + // attribute matched + else if (substr($match, 0, 1) == '[' && + substr($match, -1, 1) == ']') { + $attribute = substr($match, 1, strlen($match) - 2); + $attribute = str_replace('"', '', $attribute); + + // match single word + if (strstr($attribute, '~=')) { + list($key, $value) = explode('~=', $attribute); + $value = "regexp:/.*\b$value\b.*/"; + } + + // match substring + else if (strstr($attribute, '*=')) { + list($key, $value) = explode('*=', $attribute); + $value = "regexp:/.*$value.*/"; + } + + // exact match + else { + list($key, $value) = explode('=', $attribute); + } + + $attrs[$key] = $value; + } + } + + if ($classes) { + $tag['class'] = join(' ', $classes); + } + + if ($attrs) { + $tag['attributes'] = $attrs; + } + } + + // tag content + if (is_string($content)) { + $tag['content'] = $content; + } + + // determine previous child/descendants + if (!empty($previousTag['descendant'])) { + $tag['descendant'] = $previousTag['descendant']; + } elseif (!empty($previousTag['child'])) { + $tag['child'] = $previousTag['child']; + } elseif (!empty($previousTag['adjacent-sibling'])) { + $tag['adjacent-sibling'] = $previousTag['adjacent-sibling']; + unset($tag['content']); + } + + $previousTag = array('descendant' => $tag); + } + + return $tag; + } + + /** + * Parse an $actual document and return an array of DOMNodes + * matching the CSS $selector. If an error occurs, it will + * return false. + * + * To only return nodes containing a certain content, give + * the $content to match as a string. Otherwise, setting + * $content to true will return all nodes matching $selector. + * + * The $actual document may be a DOMDocument or a string + * containing XML or HTML, identified by $isHtml. + * + * @param array $selector + * @param string $content + * @param mixed $actual + * @param boolean $isHtml + * @return boolean|array + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + * @author Tobias Schlitt + */ + public static function cssSelect($selector, $content, $actual, $isHtml = true) + { + $matcher = self::convertSelectToTag($selector, $content); + $dom = self::load($actual, $isHtml); + $tags = self::findNodes($dom, $matcher, $isHtml); + + return $tags; + } + + /** + * Parse out the options from the tag using DOM object tree. + * + * @param DOMDocument $dom + * @param array $options + * @param boolean $isHtml + * @return array + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + * @author Tobias Schlitt + */ + public static function findNodes(DOMDocument $dom, array $options, $isHtml = true) + { + $valid = array( + 'id', 'class', 'tag', 'content', 'attributes', 'parent', + 'child', 'ancestor', 'descendant', 'children', 'adjacent-sibling' + ); + + $filtered = array(); + $options = self::assertValidKeys($options, $valid); + + // find the element by id + if ($options['id']) { + $options['attributes']['id'] = $options['id']; + } + + if ($options['class']) { + $options['attributes']['class'] = $options['class']; + } + + // find the element by a tag type + if ($options['tag']) { + if ($isHtml) { + $elements = self::getElementsByCaseInsensitiveTagName( + $dom, $options['tag'] + ); + } else { + $elements = $dom->getElementsByTagName($options['tag']); + } + + foreach ($elements as $element) { + $nodes[] = $element; + } + + if (empty($nodes)) { + return false; + } + } + + // no tag selected, get them all + else { + $tags = array( + 'a', 'abbr', 'acronym', 'address', 'area', 'b', 'base', 'bdo', + 'big', 'blockquote', 'body', 'br', 'button', 'caption', 'cite', + 'code', 'col', 'colgroup', 'dd', 'del', 'div', 'dfn', 'dl', + 'dt', 'em', 'fieldset', 'form', 'frame', 'frameset', 'h1', 'h2', + 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', 'i', 'iframe', + 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link', + 'map', 'meta', 'noframes', 'noscript', 'object', 'ol', 'optgroup', + 'option', 'p', 'param', 'pre', 'q', 'samp', 'script', 'select', + 'small', 'span', 'strong', 'style', 'sub', 'sup', 'table', + 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title', + 'tr', 'tt', 'ul', 'var', + // HTML5 + 'article', 'aside', 'audio', 'bdi', 'canvas', 'command', + 'datalist', 'details', 'dialog', 'embed', 'figure', 'figcaption', + 'footer', 'header', 'hgroup', 'keygen', 'mark', 'meter', 'nav', + 'output', 'progress', 'ruby', 'rt', 'rp', 'track', 'section', + 'source', 'summary', 'time', 'video', 'wbr' + ); + + foreach ($tags as $tag) { + if ($isHtml) { + $elements = self::getElementsByCaseInsensitiveTagName( + $dom, $tag + ); + } else { + $elements = $dom->getElementsByTagName($tag); + } + + foreach ($elements as $element) { + $nodes[] = $element; + } + } + + if (empty($nodes)) { + return false; + } + } + + // filter by attributes + if ($options['attributes']) { + foreach ($nodes as $node) { + $invalid = false; + + foreach ($options['attributes'] as $name => $value) { + // match by regexp if like "regexp:/foo/i" + if (preg_match('/^regexp\s*:\s*(.*)/i', $value, $matches)) { + if (!preg_match($matches[1], $node->getAttribute($name))) { + $invalid = true; + } + } + + // class can match only a part + else if ($name == 'class') { + // split to individual classes + $findClasses = explode( + ' ', preg_replace("/\s+/", " ", $value) + ); + + $allClasses = explode( + ' ', + preg_replace("/\s+/", " ", $node->getAttribute($name)) + ); + + // make sure each class given is in the actual node + foreach ($findClasses as $findClass) { + if (!in_array($findClass, $allClasses)) { + $invalid = true; + } + } + } + + // match by exact string + else { + if ($node->getAttribute($name) != $value) { + $invalid = true; + } + } + } + + // if every attribute given matched + if (!$invalid) { + $filtered[] = $node; + } + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by content + if ($options['content'] !== null) { + foreach ($nodes as $node) { + $invalid = false; + + // match by regexp if like "regexp:/foo/i" + if (preg_match('/^regexp\s*:\s*(.*)/i', $options['content'], $matches)) { + if (!preg_match($matches[1], self::getNodeText($node))) { + $invalid = true; + } + } + + // match empty string + else if ($options['content'] === '') { + if (self::getNodeText($node) !== '') { + $invalid = true; + } + } + + // match by exact string + else if (strstr(self::getNodeText($node), $options['content']) === false) { + $invalid = true; + } + + if (!$invalid) { + $filtered[] = $node; + } + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by parent node + if ($options['parent']) { + $parentNodes = self::findNodes($dom, $options['parent'], $isHtml); + $parentNode = isset($parentNodes[0]) ? $parentNodes[0] : null; + + foreach ($nodes as $node) { + if ($parentNode !== $node->parentNode) { + continue; + } + + $filtered[] = $node; + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by child node + if ($options['child']) { + $childNodes = self::findNodes($dom, $options['child'], $isHtml); + $childNodes = !empty($childNodes) ? $childNodes : array(); + + foreach ($nodes as $node) { + foreach ($node->childNodes as $child) { + foreach ($childNodes as $childNode) { + if ($childNode === $child) { + $filtered[] = $node; + } + } + } + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by adjacent-sibling + if ($options['adjacent-sibling']) { + $adjacentSiblingNodes = self::findNodes($dom, $options['adjacent-sibling'], $isHtml); + $adjacentSiblingNodes = !empty($adjacentSiblingNodes) ? $adjacentSiblingNodes : array(); + + foreach ($nodes as $node) { + $sibling = $node; + + while ($sibling = $sibling->nextSibling) { + if ($sibling->nodeType !== XML_ELEMENT_NODE) { + continue; + } + + foreach ($adjacentSiblingNodes as $adjacentSiblingNode) { + if ($sibling === $adjacentSiblingNode) { + $filtered[] = $node; + break; + } + } + + break; + } + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by ancestor + if ($options['ancestor']) { + $ancestorNodes = self::findNodes($dom, $options['ancestor'], $isHtml); + $ancestorNode = isset($ancestorNodes[0]) ? $ancestorNodes[0] : null; + + foreach ($nodes as $node) { + $parent = $node->parentNode; + + while ($parent && $parent->nodeType != XML_HTML_DOCUMENT_NODE) { + if ($parent === $ancestorNode) { + $filtered[] = $node; + } + + $parent = $parent->parentNode; + } + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by descendant + if ($options['descendant']) { + $descendantNodes = self::findNodes($dom, $options['descendant'], $isHtml); + $descendantNodes = !empty($descendantNodes) ? $descendantNodes : array(); + + foreach ($nodes as $node) { + foreach (self::getDescendants($node) as $descendant) { + foreach ($descendantNodes as $descendantNode) { + if ($descendantNode === $descendant) { + $filtered[] = $node; + } + } + } + } + + $nodes = $filtered; + $filtered = array(); + + if (empty($nodes)) { + return false; + } + } + + // filter by children + if ($options['children']) { + $validChild = array('count', 'greater_than', 'less_than', 'only'); + $childOptions = self::assertValidKeys( + $options['children'], $validChild + ); + + foreach ($nodes as $node) { + $childNodes = $node->childNodes; + + foreach ($childNodes as $childNode) { + if ($childNode->nodeType !== XML_CDATA_SECTION_NODE && + $childNode->nodeType !== XML_TEXT_NODE) { + $children[] = $childNode; + } + } + + // we must have children to pass this filter + if (!empty($children)) { + // exact count of children + if ($childOptions['count'] !== null) { + if (count($children) !== $childOptions['count']) { + break; + } + } + + // range count of children + else if ($childOptions['less_than'] !== null && + $childOptions['greater_than'] !== null) { + if (count($children) >= $childOptions['less_than'] || + count($children) <= $childOptions['greater_than']) { + break; + } + } + + // less than a given count + else if ($childOptions['less_than'] !== null) { + if (count($children) >= $childOptions['less_than']) { + break; + } + } + + // more than a given count + else if ($childOptions['greater_than'] !== null) { + if (count($children) <= $childOptions['greater_than']) { + break; + } + } + + // match each child against a specific tag + if ($childOptions['only']) { + $onlyNodes = self::findNodes( + $dom, $childOptions['only'], $isHtml + ); + + // try to match each child to one of the 'only' nodes + foreach ($children as $child) { + $matched = false; + + foreach ($onlyNodes as $onlyNode) { + if ($onlyNode === $child) { + $matched = true; + } + } + + if (!$matched) { + break 2; + } + } + } + + $filtered[] = $node; + } + } + + $nodes = $filtered; + + if (empty($nodes)) { + return; + } + } + + // return the first node that matches all criteria + return !empty($nodes) ? $nodes : array(); + } + + /** + * Recursively get flat array of all descendants of this node. + * + * @param DOMNode $node + * @return array + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + protected static function getDescendants(DOMNode $node) + { + $allChildren = array(); + $childNodes = $node->childNodes ? $node->childNodes : array(); + + foreach ($childNodes as $child) { + if ($child->nodeType === XML_CDATA_SECTION_NODE || + $child->nodeType === XML_TEXT_NODE) { + continue; + } + + $children = self::getDescendants($child); + $allChildren = array_merge($allChildren, $children, array($child)); + } + + return isset($allChildren) ? $allChildren : array(); + } + + /** + * Gets elements by case insensitive tagname. + * + * @param DOMDocument $dom + * @param string $tag + * @return DOMNodeList + * @since Method available since Release 3.4.0 + */ + protected static function getElementsByCaseInsensitiveTagName(DOMDocument $dom, $tag) + { + $elements = $dom->getElementsByTagName(strtolower($tag)); + + if ($elements->length == 0) { + $elements = $dom->getElementsByTagName(strtoupper($tag)); + } + + return $elements; + } + + /** + * Get the text value of this node's child text node. + * + * @param DOMNode $node + * @return string + * @since Method available since Release 3.3.0 + * @author Mike Naberezny + * @author Derek DeVries + */ + protected static function getNodeText(DOMNode $node) + { + if (!$node->childNodes instanceof DOMNodeList) { + return ''; + } + + $result = ''; + + foreach ($node->childNodes as $childNode) { + if ($childNode->nodeType === XML_TEXT_NODE || + $childNode->nodeType === XML_CDATA_SECTION_NODE) { + $result .= trim($childNode->data) . ' '; + } else { + $result .= self::getNodeText($childNode); + } + } + + return str_replace(' ', ' ', $result); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Command-line options parsing class. + * + * @package PHPUnit + * @subpackage Util + * @author Andrei Zmievski + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Util_Getopt +{ + public static function getopt(array $args, $short_options, $long_options = null) + { + if (empty($args)) { + return array(array(), array()); + } + + $opts = array(); + $non_opts = array(); + + if ($long_options) { + sort($long_options); + } + + if (isset($args[0][0]) && $args[0][0] != '-') { + array_shift($args); + } + + reset($args); + array_map('trim', $args); + + while (list($i, $arg) = each($args)) { + if ($arg == '') { + continue; + } + + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg[0] != '-' || + (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg[1] == '-') { + self::parseLongOption( + substr($arg, 2), $long_options, $opts, $args + ); + } else { + self::parseShortOption( + substr($arg, 1), $short_options, $opts, $args + ); + } + } + + return array($opts, $non_opts); + } + + protected static function parseShortOption($arg, $short_options, &$opts, &$args) + { + $argLen = strlen($arg); + + for ($i = 0; $i < $argLen; $i++) { + $opt = $arg[$i]; + $opt_arg = null; + + if (($spec = strstr($short_options, $opt)) === false || + $arg[$i] == ':') { + throw new PHPUnit_Framework_Exception( + "unrecognized option -- $opt" + ); + } + + if (strlen($spec) > 1 && $spec[1] == ':') { + if (strlen($spec) > 2 && $spec[2] == ':') { + if ($i + 1 < $argLen) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + if ($i + 1 < $argLen) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } elseif (list(, $opt_arg) = each($args)) { + } else { + throw new PHPUnit_Framework_Exception( + "option requires an argument -- $opt" + ); + } + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + protected static function parseLongOption($arg, $long_options, &$opts, &$args) + { + $count = count($long_options); + $list = explode('=', $arg); + $opt = $list[0]; + $opt_arg = null; + + if (count($list) > 1) { + $opt_arg = $list[1]; + } + + $opt_len = strlen($opt); + + for ($i = 0; $i < $count; $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + + if ($opt_start != $opt) { + continue; + } + + $opt_rest = substr($long_opt, $opt_len); + + if ($opt_rest != '' && $opt[0] != '=' && $i + 1 < $count && + $opt == substr($long_options[$i+1], 0, $opt_len)) { + throw new PHPUnit_Framework_Exception( + "option --$opt is ambiguous" + ); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + if (!strlen($opt_arg) && + !(list(, $opt_arg) = each($args))) { + throw new PHPUnit_Framework_Exception( + "option --$opt requires an argument" + ); + } + } + } elseif ($opt_arg) { + throw new PHPUnit_Framework_Exception( + "option --$opt doesn't allow an argument" + ); + } + + $opts[] = array('--' . $opt, $opt_arg); + + return; + } + + throw new PHPUnit_Framework_Exception("unrecognized option --$opt"); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.12 + */ + +/** + * Windows utility for PHP sub-processes. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.5.12 + */ +class PHPUnit_Util_PHP_Windows extends PHPUnit_Util_PHP_Default +{ + /** + * @var string + */ + private $tempFile; + + /** + * @param resource $pipe + * @param string $job + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.5.12 + */ + protected function process($pipe, $job) + { + if (!($this->tempFile = tempnam(sys_get_temp_dir(), 'PHPUnit')) || + file_put_contents($this->tempFile, $job) === false) { + throw new PHPUnit_Framework_Exception( + 'Unable to write temporary file' + ); + } + + fwrite( + $pipe, + "tempFile, true) . "; ?>" + ); + } + + /** + * @since Method available since Release 3.5.12 + */ + protected function cleanup() + { + unlink($this->tempFile); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.12 + */ + +use SebastianBergmann\Environment\Runtime; + +/** + * Default utility for PHP sub-processes. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.5.12 + */ +class PHPUnit_Util_PHP_Default extends PHPUnit_Util_PHP +{ + /** + * Runs a single job (PHP code) using a separate PHP process. + * + * @param string $job + * @param array $settings + * @return array + * @throws PHPUnit_Framework_Exception + */ + public function runJob($job, array $settings = array()) + { + $runtime = new Runtime; + + $process = proc_open( + $runtime->getBinary() . $this->settingsToParameters($settings), + array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ), + $pipes + ); + + if (!is_resource($process)) { + throw new PHPUnit_Framework_Exception( + 'Unable to spawn worker process' + ); + } + + $this->process($pipes[0], $job); + fclose($pipes[0]); + + $stdout = stream_get_contents($pipes[1]); + fclose($pipes[1]); + + $stderr = stream_get_contents($pipes[2]); + fclose($pipes[2]); + + proc_close($process); + $this->cleanup(); + + return array('stdout' => $stdout, 'stderr' => $stderr); + } + + /** + * @param resource $pipe + * @param string $job + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.5.12 + */ + protected function process($pipe, $job) + { + fwrite($pipe, $job); + } + + /** + * @since Method available since Release 3.5.12 + */ + protected function cleanup() + { + } +} +setCodeCoverage(new PHP_CodeCoverage); + } + + $result->beStrictAboutTestsThatDoNotTestAnything({isStrictAboutTestsThatDoNotTestAnything}); + $result->beStrictAboutOutputDuringTests({isStrictAboutOutputDuringTests}); + $result->beStrictAboutTestSize({isStrictAboutTestSize}); + + $test = new {className}('{methodName}', unserialize('{data}'), '{dataName}'); + $test->setDependencyInput(unserialize('{dependencyInput}')); + $test->setInIsolation(TRUE); + + ob_end_clean(); + ob_start(); + $test->run($result); + $output = ob_get_clean(); + + print serialize( + array( + 'testResult' => $test->getResult(), + 'numAssertions' => $test->getNumAssertions(), + 'result' => $result, + 'output' => $output + ) + ); + + ob_start(); +} + +{constants} +{included_files} +{globals} + +if (isset($GLOBALS['__PHPUNIT_BOOTSTRAP'])) { + require_once $GLOBALS['__PHPUNIT_BOOTSTRAP']; + unset($GLOBALS['__PHPUNIT_BOOTSTRAP']); +} + +__phpunit_run_isolated_test(); +ob_end_clean(); +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Filesystem helpers. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Util_Filesystem +{ + /** + * @var array + */ + protected static $buffer = array(); + + /** + * Maps class names to source file names: + * - PEAR CS: Foo_Bar_Baz -> Foo/Bar/Baz.php + * - Namespace: Foo\Bar\Baz -> Foo/Bar/Baz.php + * + * @param string $className + * @return string + * @since Method available since Release 3.4.0 + */ + public static function classNameToFilename($className) + { + return str_replace( + array('_', '\\'), + DIRECTORY_SEPARATOR, + $className + ) . '.php'; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * Utility class for textual type (and value) representation. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Util_Type +{ + public static function isType($type) + { + return in_array( + $type, + array( + 'numeric', + 'integer', + 'int', + 'float', + 'string', + 'boolean', + 'bool', + 'null', + 'array', + 'object', + 'resource', + 'scalar' + ) + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Ralph Schindler + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.7 + */ + +/** + * Class to hold the information about a deprecated feature that was used + * + * @package PHPUnit + * @subpackage Framework + * @author Ralph Schindler + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 3.5.7 + */ +class PHPUnit_Util_DeprecatedFeature +{ + /** + * @var array + */ + protected $traceInfo = array(); + + /** + * @var string + */ + protected $message = null; + + /** + * @param string $message + * @param array $traceInfo + */ + public function __construct($message, array $traceInfo = array()) + { + $this->message = $message; + $this->traceInfo = $traceInfo; + } + + /** + * @return string + * @since Method available since Release 4.0.0 + */ + public function getMessage() + { + return $this->message; + } + + /** + * @return string + * @since Method available since Release 4.0.0 + */ + public function getSource() + { + $source = ''; + + if (isset($this->traceInfo['file'])) { + $source .= $this->traceInfo['file']; + + if (isset($this->traceInfo['line'])) { + $source .= ':' . $this->traceInfo['line']; + } + } + + return $source; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * Utility class for code filtering. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Util_Filter +{ + /** + * Filters stack frames from PHPUnit classes. + * + * @param Exception $e + * @param boolean $asString + * @return string + */ + public static function getFilteredStacktrace(Exception $e, $asString = true) + { + $prefix = false; + $script = realpath($GLOBALS['_SERVER']['SCRIPT_NAME']); + + if (defined('__PHPUNIT_PHAR_ROOT__')) { + $prefix = __PHPUNIT_PHAR_ROOT__; + } + + if ($asString === true) { + $filteredStacktrace = ''; + } else { + $filteredStacktrace = array(); + } + + if ($e instanceof PHPUnit_Framework_SyntheticError) { + $eTrace = $e->getSyntheticTrace(); + $eFile = $e->getSyntheticFile(); + $eLine = $e->getSyntheticLine(); + } else { + if ($e->getPrevious()) { + $eTrace = $e->getPrevious()->getTrace(); + } else { + $eTrace = $e->getTrace(); + } + $eFile = $e->getFile(); + $eLine = $e->getLine(); + } + + if (!self::frameExists($eTrace, $eFile, $eLine)) { + array_unshift( + $eTrace, array('file' => $eFile, 'line' => $eLine) + ); + } + + $blacklist = new PHPUnit_Util_Blacklist; + + foreach ($eTrace as $frame) { + if (isset($frame['file']) && is_file($frame['file']) && + !$blacklist->isBlacklisted($frame['file']) && + ($prefix === false || strpos($frame['file'], $prefix) !== 0) && + $frame['file'] !== $script) { + if ($asString === true) { + $filteredStacktrace .= sprintf( + "%s:%s\n", + + $frame['file'], + isset($frame['line']) ? $frame['line'] : '?' + ); + } else { + $filteredStacktrace[] = $frame; + } + } + } + + return $filteredStacktrace; + } + + /** + * @param array $trace + * @param string $file + * @param int $line + * @return boolean + * @since Method available since Release 3.3.2 + */ + private static function frameExists(array $trace, $file, $line) + { + foreach ($trace as $frame) { + if (isset($frame['file']) && $frame['file'] == $file && + isset($frame['line']) && $frame['line'] == $line) { + return true; + } + } + + return false; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Ralph Schindler + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.5.7 + */ + +/** + * Test Listener that tracks the usage of deprecated features. + * + * @package PHPUnit + * @subpackage Framework + * @author Ralph Schindler + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.5.7 + */ +class PHPUnit_Util_DeprecatedFeature_Logger implements PHPUnit_Framework_TestListener +{ + /** + * @var PHPUnit_Framework_TestCase + */ + protected static $currentTest = null; + + /** + * This is the publicly accessible API for notifying the system that a + * deprecated feature has been used. + * + * If it is run via a TestRunner and the test extends + * PHPUnit_Framework_TestCase, then this will inject the result into the + * test runner for display, if not, it will throw the notice to STDERR. + * + * @param string $message + * @param int|bool $backtraceDepth + */ + public static function log($message, $backtraceDepth = 2) + { + if ($backtraceDepth !== false) { + $trace = debug_backtrace(false); + + if (is_int($backtraceDepth)) { + $traceItem = $trace[$backtraceDepth]; + } + + if (!isset($traceItem['file'])) { + $reflectionClass = new ReflectionClass($traceItem['class']); + $traceItem['file'] = $reflectionClass->getFileName(); + } + + if (!isset($traceItem['line']) && + isset($traceItem['class']) && + isset($traceItem['function'])) { + if (!isset($reflectionClass)) { + $reflectionClass = new ReflectionClass($traceItem['class']); + } + + $method = $reflectionClass->getMethod($traceItem['function']); + $traceItem['line'] = $method->getStartLine() . '-' . $method->getEndLine(); + } + } + + $deprecatedFeature = new PHPUnit_Util_DeprecatedFeature( + $message, $traceItem + ); + + if (self::$currentTest instanceof PHPUnit_Framework_TestCase) { + $result = self::$currentTest->getTestResultObject(); + $result->addDeprecatedFeature($deprecatedFeature); + } else { + file_put_contents('php://stderr', $deprecatedFeature); + } + } + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * A test suite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test suite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + self::$currentTest = $test; + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + self::$currentTest = null; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.6.0 + */ + +/** + * String helpers. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.6.0 + */ +class PHPUnit_Util_String +{ + /** + * Converts a string to UTF-8 encoding. + * + * @param string $string + * @return string + */ + public static function convertToUtf8($string) + { + if (!self::isUtf8($string)) { + if (function_exists('mb_convert_encoding')) { + $string = mb_convert_encoding($string, 'UTF-8'); + } else { + $string = utf8_encode($string); + } + } + + return $string; + } + + /** + * Checks a string for UTF-8 encoding. + * + * @param string $string + * @return boolean + */ + protected static function isUtf8($string) + { + $length = strlen($string); + + for ($i = 0; $i < $length; $i++) { + if (ord($string[$i]) < 0x80) { + $n = 0; + } elseif ((ord($string[$i]) & 0xE0) == 0xC0) { + $n = 1; + } elseif ((ord($string[$i]) & 0xF0) == 0xE0) { + $n = 2; + } elseif ((ord($string[$i]) & 0xF0) == 0xF0) { + $n = 3; + } else { + return false; + } + + for ($j = 0; $j < $n; $j++) { + if ((++$i == $length) || ((ord($string[$i]) & 0xC0) != 0x80)) { + return false; + } + } + } + + return true; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.0 + */ + +/** + * Iterator for test suites. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.0 + */ +class PHPUnit_Util_TestSuiteIterator implements RecursiveIterator +{ + /** + * @var integer + */ + protected $position; + + /** + * @var PHPUnit_Framework_Test[] + */ + protected $tests; + + /** + * Constructor. + * + * @param PHPUnit_Framework_TestSuite $suite + */ + public function __construct(PHPUnit_Framework_TestSuite $testSuite) + { + $this->tests = $testSuite->tests(); + } + + /** + * Rewinds the Iterator to the first element. + * + */ + public function rewind() + { + $this->position = 0; + } + + /** + * Checks if there is a current element after calls to rewind() or next(). + * + * @return boolean + */ + public function valid() + { + return $this->position < count($this->tests); + } + + /** + * Returns the key of the current element. + * + * @return integer + */ + public function key() + { + return $this->position; + } + + /** + * Returns the current element. + * + * @return PHPUnit_Framework_Test + */ + public function current() + { + return $this->valid() ? $this->tests[$this->position] : null; + } + + /** + * Moves forward to next element. + * + */ + public function next() + { + $this->position++; + } + + /** + * Returns the sub iterator for the current element. + * + * @return PHPUnit_Util_TestSuiteIterator + */ + public function getChildren() + { + return new PHPUnit_Util_TestSuiteIterator( + $this->tests[$this->position] + ); + } + + /** + * Checks whether the current element has children. + * + * @return boolean + */ + public function hasChildren() + { + return $this->tests[$this->position] instanceof PHPUnit_Framework_TestSuite; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +class PHPUnit_Util_GlobalState +{ + /** + * @var array + */ + protected static $globals = array(); + + /** + * @var array + */ + protected static $staticAttributes = array(); + + /** + * @var array + */ + protected static $superGlobalArrays = array( + '_ENV', + '_POST', + '_GET', + '_COOKIE', + '_SERVER', + '_FILES', + '_REQUEST' + ); + + /** + * @var array + */ + protected static $superGlobalArraysLong = array( + 'HTTP_ENV_VARS', + 'HTTP_POST_VARS', + 'HTTP_GET_VARS', + 'HTTP_COOKIE_VARS', + 'HTTP_SERVER_VARS', + 'HTTP_POST_FILES' + ); + + public static function backupGlobals(array $blacklist) + { + self::$globals = array(); + $superGlobalArrays = self::getSuperGlobalArrays(); + + foreach ($superGlobalArrays as $superGlobalArray) { + if (!in_array($superGlobalArray, $blacklist)) { + self::backupSuperGlobalArray($superGlobalArray); + } + } + + foreach (array_keys($GLOBALS) as $key) { + if ($key != 'GLOBALS' && + !in_array($key, $superGlobalArrays) && + !in_array($key, $blacklist) && + !$GLOBALS[$key] instanceof Closure) { + self::$globals['GLOBALS'][$key] = serialize($GLOBALS[$key]); + } + } + } + + public static function restoreGlobals(array $blacklist) + { + if (ini_get('register_long_arrays') == '1') { + $superGlobalArrays = array_merge( + self::$superGlobalArrays, self::$superGlobalArraysLong + ); + } else { + $superGlobalArrays = self::$superGlobalArrays; + } + + foreach ($superGlobalArrays as $superGlobalArray) { + if (!in_array($superGlobalArray, $blacklist)) { + self::restoreSuperGlobalArray($superGlobalArray); + } + } + + foreach (array_keys($GLOBALS) as $key) { + if ($key != 'GLOBALS' && + !in_array($key, $superGlobalArrays) && + !in_array($key, $blacklist)) { + if (isset(self::$globals['GLOBALS'][$key])) { + $GLOBALS[$key] = unserialize( + self::$globals['GLOBALS'][$key] + ); + } else { + unset($GLOBALS[$key]); + } + } + } + + self::$globals = array(); + } + + protected static function backupSuperGlobalArray($superGlobalArray) + { + self::$globals[$superGlobalArray] = array(); + + if (isset($GLOBALS[$superGlobalArray]) && + is_array($GLOBALS[$superGlobalArray])) { + foreach ($GLOBALS[$superGlobalArray] as $key => $value) { + self::$globals[$superGlobalArray][$key] = serialize($value); + } + } + } + + protected static function restoreSuperGlobalArray($superGlobalArray) + { + if (isset($GLOBALS[$superGlobalArray]) && + is_array($GLOBALS[$superGlobalArray]) && + isset(self::$globals[$superGlobalArray])) { + $keys = array_keys( + array_merge( + $GLOBALS[$superGlobalArray], self::$globals[$superGlobalArray] + ) + ); + + foreach ($keys as $key) { + if (isset(self::$globals[$superGlobalArray][$key])) { + $GLOBALS[$superGlobalArray][$key] = unserialize( + self::$globals[$superGlobalArray][$key] + ); + } else { + unset($GLOBALS[$superGlobalArray][$key]); + } + } + } + + self::$globals[$superGlobalArray] = array(); + } + + public static function getIncludedFilesAsString() + { + $blacklist = new PHPUnit_Util_Blacklist; + $files = get_included_files(); + $prefix = false; + $result = ''; + + if (defined('__PHPUNIT_PHAR__')) { + $prefix = 'phar://' . __PHPUNIT_PHAR__ . '/'; + } + + for ($i = count($files) - 1; $i > 0; $i--) { + $file = $files[$i]; + + if ($prefix !== false && strpos($file, $prefix) === 0) { + continue; + } + + if (!$blacklist->isBlacklisted($file) && is_file($file)) { + $result = 'require_once \'' . $file . "';\n" . $result; + } + } + + return $result; + } + + public static function getIniSettingsAsString() + { + $result = ''; + $iniSettings = ini_get_all(null, false); + + foreach ($iniSettings as $key => $value) { + $result .= sprintf( + '@ini_set(%s, %s);' . "\n", + self::exportVariable($key), + self::exportVariable($value) + ); + } + + return $result; + } + + public static function getConstantsAsString() + { + $constants = get_defined_constants(true); + $result = ''; + + if (isset($constants['user'])) { + foreach ($constants['user'] as $name => $value) { + $result .= sprintf( + 'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n", + $name, + $name, + self::exportVariable($value) + ); + } + } + + return $result; + } + + public static function getGlobalsAsString() + { + $result = ''; + $superGlobalArrays = self::getSuperGlobalArrays(); + + foreach ($superGlobalArrays as $superGlobalArray) { + if (isset($GLOBALS[$superGlobalArray]) && + is_array($GLOBALS[$superGlobalArray])) { + foreach (array_keys($GLOBALS[$superGlobalArray]) as $key) { + if ($GLOBALS[$superGlobalArray][$key] instanceof Closure) { + continue; + } + + $result .= sprintf( + '$GLOBALS[\'%s\'][\'%s\'] = %s;' . "\n", + $superGlobalArray, + $key, + self::exportVariable($GLOBALS[$superGlobalArray][$key]) + ); + } + } + } + + $blacklist = $superGlobalArrays; + $blacklist[] = 'GLOBALS'; + + foreach (array_keys($GLOBALS) as $key) { + if (!in_array($key, $blacklist) && !$GLOBALS[$key] instanceof Closure) { + $result .= sprintf( + '$GLOBALS[\'%s\'] = %s;' . "\n", + $key, + self::exportVariable($GLOBALS[$key]) + ); + } + } + + return $result; + } + + protected static function getSuperGlobalArrays() + { + if (ini_get('register_long_arrays') == '1') { + return array_merge( + self::$superGlobalArrays, self::$superGlobalArraysLong + ); + } else { + return self::$superGlobalArrays; + } + } + + public static function backupStaticAttributes(array $blacklist) + { + self::$staticAttributes = array(); + $declaredClasses = get_declared_classes(); + $declaredClassesNum = count($declaredClasses); + + for ($i = $declaredClassesNum - 1; $i >= 0; $i--) { + if (strpos($declaredClasses[$i], 'PHPUnit') !== 0 && + strpos($declaredClasses[$i], 'File_Iterator') !== 0 && + strpos($declaredClasses[$i], 'PHP_CodeCoverage') !== 0 && + strpos($declaredClasses[$i], 'PHP_Invoker') !== 0 && + strpos($declaredClasses[$i], 'PHP_Timer') !== 0 && + strpos($declaredClasses[$i], 'PHP_Token_Stream') !== 0 && + strpos($declaredClasses[$i], 'Symfony') !== 0 && + strpos($declaredClasses[$i], 'Text_Template') !== 0) { + $class = new ReflectionClass($declaredClasses[$i]); + + if ($class->isSubclassOf('PHPUnit_Framework_Test')) { + continue; + } + + if (!$class->isUserDefined()) { + break; + } + + $backup = array(); + + foreach ($class->getProperties() as $attribute) { + if ($attribute->isStatic()) { + $name = $attribute->getName(); + + if (!isset($blacklist[$declaredClasses[$i]]) || + !in_array($name, $blacklist[$declaredClasses[$i]])) { + $attribute->setAccessible(true); + $value = $attribute->getValue(); + + if (!$value instanceof Closure) { + $backup[$name] = serialize($value); + } + } + } + } + + if (!empty($backup)) { + self::$staticAttributes[$declaredClasses[$i]] = $backup; + } + } + } + } + + public static function restoreStaticAttributes() + { + foreach (self::$staticAttributes as $className => $staticAttributes) { + foreach ($staticAttributes as $name => $value) { + $reflector = new ReflectionProperty($className, $name); + $reflector->setAccessible(true); + $reflector->setValue(unserialize($value)); + } + } + + self::$staticAttributes = array(); + } + + protected static function exportVariable($variable) + { + if (is_scalar($variable) || is_null($variable) || + (is_array($variable) && self::arrayOnlyContainsScalars($variable))) { + return var_export($variable, true); + } + + return 'unserialize(\'' . + str_replace("'", "\'", serialize($variable)) . + '\')'; + } + + protected static function arrayOnlyContainsScalars(array $array) + { + $result = true; + + foreach ($array as $element) { + if (is_array($element)) { + $result = self::arrayOnlyContainsScalars($element); + } elseif (!is_scalar($element) && !is_null($element)) { + $result = false; + } + + if ($result === false) { + break; + } + } + + return $result; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +/** + * Utility methods to load PHP sourcefiles. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.3.0 + */ +class PHPUnit_Util_Fileloader +{ + /** + * Checks if a PHP sourcefile is readable. + * The sourcefile is loaded through the load() method. + * + * @param string $filename + * @return string + * @throws PHPUnit_Framework_Exception + */ + public static function checkAndLoad($filename) + { + $includePathFilename = stream_resolve_include_path($filename); + + if (!$includePathFilename || !is_readable($includePathFilename)) { + throw new PHPUnit_Framework_Exception( + sprintf('Cannot open file "%s".' . "\n", $filename) + ); + } + + self::load($includePathFilename); + + return $includePathFilename; + } + + /** + * Loads a PHP sourcefile. + * + * @param string $filename + * @return mixed + * @since Method available since Release 3.0.0 + */ + public static function load($filename) + { + $oldVariableNames = array_keys(get_defined_vars()); + + include_once $filename; + + $newVariables = get_defined_vars(); + $newVariableNames = array_diff( + array_keys($newVariables), $oldVariableNames + ); + + foreach ($newVariableNames as $variableName) { + if ($variableName != 'oldVariableNames') { + $GLOBALS[$variableName] = $newVariables[$variableName]; + } + } + + return $filename; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +if (!function_exists('trait_exists')) { + function trait_exists($traitname, $autoload = true) + { + return false; + } +} + +/** + * Test helpers. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_Util_Test +{ + const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\\x7f-\xff]+)/'; + const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\\x7f-\xff]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m'; + const REGEX_REQUIRES_VERSION = '/@requires\s+(?PPHP(?:Unit)?)\s+(?P[\d\.-]+(dev|(RC|alpha|beta)[\d\.])?)[ \t]*\r?$/m'; + const REGEX_REQUIRES_OS = '/@requires\s+OS\s+(?P.+?)[ \t]*\r?$/m'; + const REGEX_REQUIRES = '/@requires\s+(?Pfunction|extension)\s+(?P([^ ]+?))[ \t]*\r?$/m'; + + const SMALL = 0; + const MEDIUM = 1; + const LARGE = 2; + + private static $annotationCache = array(); + + private static $templateMethods = array( + 'setUp', 'assertPreConditions', 'assertPostConditions', 'tearDown' + ); + + private static $hookMethods = array(); + + /** + * @param PHPUnit_Framework_Test $test + * @param boolean $asString + * @return mixed + */ + public static function describe(PHPUnit_Framework_Test $test, $asString = true) + { + if ($asString) { + if ($test instanceof PHPUnit_Framework_SelfDescribing) { + return $test->toString(); + } else { + return get_class($test); + } + } else { + if ($test instanceof PHPUnit_Framework_TestCase) { + return array( + get_class($test), $test->getName() + ); + } elseif ($test instanceof PHPUnit_Framework_SelfDescribing) { + return array('', $test->toString()); + } else { + return array('', get_class($test)); + } + } + } + + /** + * @param string $className + * @param string $methodName + * @return array|bool + * @throws PHPUnit_Framework_CodeCoverageException + * @since Method available since Release 4.0.0 + */ + public static function getLinesToBeCovered($className, $methodName) + { + $codeToCoverList = array(); + + $class = new ReflectionClass($className); + + try { + $method = new ReflectionMethod($className, $methodName); + } catch (ReflectionException $e) { + return array(); + } + + $docComment = self::getDocCommentsOfTestClassAndTestMethodAndTemplateMethods($class, $method); + + if (strpos($docComment, '@coversNothing') !== false) { + return false; + } + + $classShortcut = preg_match_all( + '(@coversDefaultClass\s+(?P[^\s]++)\s*$)m', + $class->getDocComment(), + $matches + ); + + if ($classShortcut) { + if ($classShortcut > 1) { + throw new PHPUnit_Framework_CodeCoverageException( + sprintf( + 'More than one @coversClass annotation in class or interface "%s".', + $className + ) + ); + } + + $classShortcut = $matches['coveredClass'][0]; + } + + $match = preg_match_all( + '(@covers\s+(?P[^\s()]++)[\s()]*$)m', + $docComment, + $matches + ); + + if ($match) { + foreach ($matches['coveredElement'] as $coveredElement) { + if ($classShortcut && strncmp($coveredElement, '::', 2) === 0) { + $coveredElement = $classShortcut . $coveredElement; + } + + $codeToCoverList = array_merge( + $codeToCoverList, + self::resolveElementToReflectionObjects($coveredElement) + ); + } + } + + return self::resolveReflectionObjectsToLines($codeToCoverList); + } + + /** + * Returns lines of code specified with the @uses annotation. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 4.0.0 + */ + public static function getLinesToBeUsed($className, $methodName) + { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + $uses = array(); + + if (isset($annotations['class']['uses'])) { + $uses = $annotations['class']['uses']; + } + + if (isset($annotations['method']['uses'])) { + $uses = array_merge($uses, $annotations['method']['uses']); + } + + $uses = array_unique($uses); + $codeToUseList = array(); + + foreach (array_unique($uses) as $element) { + $codeToUseList = array_merge( + $codeToUseList, + self::resolveElementToReflectionObjects($element) + ); + } + + return self::resolveReflectionObjectsToLines($codeToUseList); + } + + /** + * Returns the requirements for a test. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 3.6.0 + */ + public static function getRequirements($className, $methodName) + { + $reflector = new ReflectionClass($className); + $docComment = $reflector->getDocComment(); + $reflector = new ReflectionMethod($className, $methodName); + $docComment .= "\n" . $reflector->getDocComment(); + $requires = array(); + + if ($count = preg_match_all(self::REGEX_REQUIRES_OS, $docComment, $matches)) { + $requires['OS'] = sprintf( + '/%s/i', + addcslashes($matches['value'][$count - 1], '/') + ); + } + if ($count = preg_match_all(self::REGEX_REQUIRES_VERSION, $docComment, $matches)) { + for ($i = 0; $i < $count; $i++) { + $requires[$matches['name'][$i]] = $matches['value'][$i]; + } + } + + // https://bugs.php.net/bug.php?id=63055 + $matches = array(); + + if ($count = preg_match_all(self::REGEX_REQUIRES, $docComment, $matches)) { + for ($i = 0; $i < $count; $i++) { + $name = $matches['name'][$i] . 's'; + if (!isset($requires[$name])) { + $requires[$name] = array(); + } + $requires[$name][] = $matches['value'][$i]; + } + } + + return $requires; + } + + /** + * Returns the expected exception for a test. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 3.3.6 + */ + public static function getExpectedException($className, $methodName) + { + $reflector = new ReflectionMethod($className, $methodName); + $docComment = $reflector->getDocComment(); + $docComment = substr($docComment, 3, -2); + + if (preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + $class = $matches[1]; + $code = null; + $message = ''; + + if (isset($matches[2])) { + $message = trim($matches[2]); + } elseif (isset($annotations['method']['expectedExceptionMessage'])) { + $message = self::parseAnnotationContent( + $annotations['method']['expectedExceptionMessage'][0] + ); + } + + if (isset($matches[3])) { + $code = $matches[3]; + } elseif (isset($annotations['method']['expectedExceptionCode'])) { + $code = self::parseAnnotationContent( + $annotations['method']['expectedExceptionCode'][0] + ); + } + + if (is_numeric($code)) { + $code = (int) $code; + } elseif (is_string($code) && defined($code)) { + $code = (int) constant($code); + } + + return array( + 'class' => $class, 'code' => $code, 'message' => $message + ); + } + + return false; + } + + /** + * Parse annotation content to use constant/class constant values + * + * Constants are specified using a starting '@'. For example: @ClassName::CONST_NAME + * + * If the constant is not found the string is used as is to ensure maximum BC. + * + * @param string $message + * @return string + */ + private static function parseAnnotationContent($message) + { + if (strpos($message, '::') !== false && count(explode('::', $message) == 2)) { + if (defined($message)) { + $message = constant($message); + } + } + + return $message; + } + + /** + * Returns the provided data for a method. + * + * @param string $className + * @param string $methodName + * @return array|Iterator when a data provider is specified and exists + * false when a data provider is specified but does not exist + * null when no data provider is specified + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.2.0 + */ + public static function getProvidedData($className, $methodName) + { + $reflector = new ReflectionMethod($className, $methodName); + $docComment = $reflector->getDocComment(); + $data = null; + + if (preg_match(self::REGEX_DATA_PROVIDER, $docComment, $matches)) { + $dataProviderMethodNameNamespace = explode('\\', $matches[1]); + $leaf = explode('::', array_pop($dataProviderMethodNameNamespace)); + $dataProviderMethodName = array_pop($leaf); + + if (!empty($dataProviderMethodNameNamespace)) { + $dataProviderMethodNameNamespace = join('\\', $dataProviderMethodNameNamespace) . '\\'; + } else { + $dataProviderMethodNameNamespace = ''; + } + + if (!empty($leaf)) { + $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf); + } else { + $dataProviderClassName = $className; + } + + $dataProviderClass = new ReflectionClass($dataProviderClassName); + $dataProviderMethod = $dataProviderClass->getMethod( + $dataProviderMethodName + ); + + if ($dataProviderMethod->isStatic()) { + $object = null; + } else { + $object = $dataProviderClass->newInstance(); + } + + if ($dataProviderMethod->getNumberOfParameters() == 0) { + $data = $dataProviderMethod->invoke($object); + } else { + $data = $dataProviderMethod->invoke($object, $methodName); + } + } + + if ($data !== null) { + if (is_object($data)) { + $data = iterator_to_array($data); + } + + foreach ($data as $key => $value) { + if (!is_array($value)) { + throw new PHPUnit_Framework_Exception( + sprintf( + 'Data set %s is invalid.', + is_int($key) ? '#' . $key : '"' . $key . '"' + ) + ); + } + } + } + + return $data; + } + + /** + * @param string $className + * @param string $methodName + * @return array + * @throws ReflectionException + * @since Method available since Release 3.4.0 + */ + public static function parseTestMethodAnnotations($className, $methodName = '') + { + if (!isset(self::$annotationCache[$className])) { + $class = new ReflectionClass($className); + self::$annotationCache[$className] = self::parseAnnotations($class->getDocComment()); + } + + if (!empty($methodName) && !isset(self::$annotationCache[$className . '::' . $methodName])) { + try { + $method = new ReflectionMethod($className, $methodName); + $annotations = self::parseAnnotations($method->getDocComment()); + } catch (ReflectionException $e) { + $annotations = array(); + } + self::$annotationCache[$className . '::' . $methodName] = $annotations; + } + + return array( + 'class' => self::$annotationCache[$className], + 'method' => !empty($methodName) ? self::$annotationCache[$className . '::' . $methodName] : array() + ); + } + + /** + * @param string $docblock + * @return array + * @since Method available since Release 3.4.0 + */ + private static function parseAnnotations($docblock) + { + $annotations = array(); + // Strip away the docblock header and footer to ease parsing of one line annotations + $docblock = substr($docblock, 3, -2); + + if (preg_match_all('/@(?P[A-Za-z_-]+)(?:[ \t]+(?P.*?))?[ \t]*\r?$/m', $docblock, $matches)) { + $numMatches = count($matches[0]); + + for ($i = 0; $i < $numMatches; ++$i) { + $annotations[$matches['name'][$i]][] = $matches['value'][$i]; + } + } + + return $annotations; + } + + /** + * Returns the backup settings for a test. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 3.4.0 + */ + public static function getBackupSettings($className, $methodName) + { + return array( + 'backupGlobals' => self::getBooleanAnnotationSetting( + $className, $methodName, 'backupGlobals' + ), + 'backupStaticAttributes' => self::getBooleanAnnotationSetting( + $className, $methodName, 'backupStaticAttributes' + ) + ); + } + + /** + * Returns the dependencies for a test class or method. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 3.4.0 + */ + public static function getDependencies($className, $methodName) + { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + $dependencies = array(); + + if (isset($annotations['class']['depends'])) { + $dependencies = $annotations['class']['depends']; + } + + if (isset($annotations['method']['depends'])) { + $dependencies = array_merge( + $dependencies, $annotations['method']['depends'] + ); + } + + return array_unique($dependencies); + } + + /** + * Returns the error handler settings for a test. + * + * @param string $className + * @param string $methodName + * @return boolean + * @since Method available since Release 3.4.0 + */ + public static function getErrorHandlerSettings($className, $methodName) + { + return self::getBooleanAnnotationSetting( + $className, $methodName, 'errorHandler' + ); + } + + /** + * Returns the groups for a test class or method. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 3.2.0 + */ + public static function getGroups($className, $methodName = '') + { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + $groups = array(); + + if (isset($annotations['method']['author'])) { + $groups = $annotations['method']['author']; + } elseif (isset($annotations['class']['author'])) { + $groups = $annotations['class']['author']; + } + + if (isset($annotations['class']['group'])) { + $groups = array_merge($groups, $annotations['class']['group']); + } + + if (isset($annotations['method']['group'])) { + $groups = array_merge($groups, $annotations['method']['group']); + } + + if (isset($annotations['class']['ticket'])) { + $groups = array_merge($groups, $annotations['class']['ticket']); + } + + if (isset($annotations['method']['ticket'])) { + $groups = array_merge($groups, $annotations['method']['ticket']); + } + + foreach (array('small', 'medium', 'large') as $size) { + if (isset($annotations['method'][$size])) { + $groups[] = $size; + } elseif (isset($annotations['class'][$size])) { + $groups[] = $size; + } + } + + return array_unique($groups); + } + + /** + * Returns the size of the test. + * + * @param string $className + * @param string $methodName + * @return integer + * @since Method available since Release 3.6.0 + */ + public static function getSize($className, $methodName) + { + $groups = array_flip(self::getGroups($className, $methodName)); + $size = self::SMALL; + $class = new ReflectionClass($className); + + if ((class_exists('PHPUnit_Extensions_Database_TestCase', false) && + $class->isSubclassOf('PHPUnit_Extensions_Database_TestCase')) || + (class_exists('PHPUnit_Extensions_SeleniumTestCase', false) && + $class->isSubclassOf('PHPUnit_Extensions_SeleniumTestCase'))) { + $size = self::LARGE; + } elseif (isset($groups['medium'])) { + $size = self::MEDIUM; + } elseif (isset($groups['large'])) { + $size = self::LARGE; + } + + return $size; + } + + /** + * Returns the tickets for a test class or method. + * + * @param string $className + * @param string $methodName + * @return array + * @since Method available since Release 3.4.0 + */ + public static function getTickets($className, $methodName) + { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + $tickets = array(); + + if (isset($annotations['class']['ticket'])) { + $tickets = $annotations['class']['ticket']; + } + + if (isset($annotations['method']['ticket'])) { + $tickets = array_merge($tickets, $annotations['method']['ticket']); + } + + return array_unique($tickets); + } + + /** + * Returns the process isolation settings for a test. + * + * @param string $className + * @param string $methodName + * @return boolean + * @since Method available since Release 3.4.1 + */ + public static function getProcessIsolationSettings($className, $methodName) + { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + if (isset($annotations['class']['runTestsInSeparateProcesses']) || + isset($annotations['method']['runInSeparateProcess'])) { + return true; + } else { + return false; + } + } + + /** + * Returns the preserve global state settings for a test. + * + * @param string $className + * @param string $methodName + * @return boolean + * @since Method available since Release 3.4.0 + */ + public static function getPreserveGlobalStateSettings($className, $methodName) + { + return self::getBooleanAnnotationSetting( + $className, $methodName, 'preserveGlobalState' + ); + } + + /** + * @param string $className + * @return array + * @since Method available since Release 4.0.8 + */ + public static function getHookMethods($className) + { + if (!class_exists($className, false)) { + return self::emptyHookMethodsArray(); + } + + if (!isset(self::$hookMethods[$className])) { + self::$hookMethods[$className] = self::emptyHookMethodsArray(); + + try { + $class = new ReflectionClass($className); + + foreach ($class->getMethods() as $method) { + if ($method->getDeclaringClass()->getName() != $className) { + continue; + } + + if (self::isBeforeClassMethod($method)) { + self::$hookMethods[$className]['beforeClass'][] = $method->getName(); + } + + if (self::isBeforeMethod($method)) { + self::$hookMethods[$className]['before'][] = $method->getName(); + } + + if (self::isAfterMethod($method)) { + self::$hookMethods[$className]['after'][] = $method->getName(); + } + + if (self::isAfterClassMethod($method)) { + self::$hookMethods[$className]['afterClass'][] = $method->getName(); + } + } + } catch (ReflectionException $e) { + } + } + + return self::$hookMethods[$className]; + } + + /** + * @return array + * @since Method available since Release 4.0.9 + */ + private static function emptyHookMethodsArray() + { + return array( + 'beforeClass' => array('setUpBeforeClass'), + 'before' => array('setUp'), + 'after' => array('tearDown'), + 'afterClass' => array('tearDownAfterClass') + ); + } + + /** + * @param string $className + * @param string $methodName + * @param string $settingName + * @return boolean + * @since Method available since Release 3.4.0 + */ + private static function getBooleanAnnotationSetting($className, $methodName, $settingName) + { + $annotations = self::parseTestMethodAnnotations( + $className, $methodName + ); + + $result = null; + + if (isset($annotations['class'][$settingName])) { + if ($annotations['class'][$settingName][0] == 'enabled') { + $result = true; + } elseif ($annotations['class'][$settingName][0] == 'disabled') { + $result = false; + } + } + + if (isset($annotations['method'][$settingName])) { + if ($annotations['method'][$settingName][0] == 'enabled') { + $result = true; + } elseif ($annotations['method'][$settingName][0] == 'disabled') { + $result = false; + } + } + + return $result; + } + + /** + * @param string $element + * @return array + * @throws PHPUnit_Framework_InvalidCoversTargetException + * @since Method available since Release 4.0.0 + */ + private static function resolveElementToReflectionObjects($element) + { + $codeToCoverList = array(); + + if (strpos($element, '::') !== false) { + list($className, $methodName) = explode('::', $element); + + if (isset($methodName[0]) && $methodName[0] == '<') { + $classes = array($className); + + foreach ($classes as $className) { + if (!class_exists($className) && + !interface_exists($className)) { + throw new PHPUnit_Framework_InvalidCoversTargetException( + sprintf( + 'Trying to @cover or @use not existing class or ' . + 'interface "%s".', + $className + ) + ); + } + + $class = new ReflectionClass($className); + $methods = $class->getMethods(); + $inverse = isset($methodName[1]) && $methodName[1] == '!'; + + if (strpos($methodName, 'protected')) { + $visibility = 'isProtected'; + } elseif (strpos($methodName, 'private')) { + $visibility = 'isPrivate'; + } elseif (strpos($methodName, 'public')) { + $visibility = 'isPublic'; + } + + foreach ($methods as $method) { + if ($inverse && !$method->$visibility()) { + $codeToCoverList[] = $method; + } elseif (!$inverse && $method->$visibility()) { + $codeToCoverList[] = $method; + } + } + } + } else { + $classes = array($className); + + foreach ($classes as $className) { + if ($className == '' && function_exists($methodName)) { + $codeToCoverList[] = new ReflectionFunction( + $methodName + ); + } else { + if (!((class_exists($className) || + interface_exists($className) || + trait_exists($className)) && + method_exists($className, $methodName))) { + throw new PHPUnit_Framework_InvalidCoversTargetException( + sprintf( + 'Trying to @cover or @use not existing method "%s::%s".', + $className, + $methodName + ) + ); + } + + $codeToCoverList[] = new ReflectionMethod( + $className, $methodName + ); + } + } + } + } else { + $extended = false; + + if (strpos($element, '') !== false) { + $element = str_replace( + '', '', $element + ); + + $extended = true; + } + + $classes = array($element); + + if ($extended) { + $classes = array_merge( + $classes, + class_implements($element), + class_parents($element) + ); + } + + foreach ($classes as $className) { + if (!class_exists($className) && + !interface_exists($className) && + !trait_exists($className)) { + throw new PHPUnit_Framework_InvalidCoversTargetException( + sprintf( + 'Trying to @cover or @use not existing class or ' . + 'interface "%s".', + $className + ) + ); + } + + $codeToCoverList[] = new ReflectionClass($className); + } + } + + return $codeToCoverList; + } + + /** + * @param array $reflectors + * @return array + */ + private static function resolveReflectionObjectsToLines(array $reflectors) + { + $result = array(); + + foreach ($reflectors as $reflector) { + $filename = $reflector->getFileName(); + + if (!isset($result[$filename])) { + $result[$filename] = array(); + } + + $result[$filename] = array_unique( + array_merge( + $result[$filename], + range( + $reflector->getStartLine(), $reflector->getEndLine() + ) + ) + ); + } + + return $result; + } + + /** + * @param ReflectionClass $class + * @param ReflectionMethod $method + * @return string + */ + private static function getDocCommentsOfTestClassAndTestMethodAndTemplateMethods(ReflectionClass $class, ReflectionMethod $method) + { + $buffer = substr($class->getDocComment(), 3, -2) . PHP_EOL . + substr($method->getDocComment(), 3, -2); + + foreach (self::$templateMethods as $templateMethod) { + if ($class->hasMethod($templateMethod)) { + $_method = $class->getMethod($templateMethod); + $buffer .= PHP_EOL . substr($_method->getDocComment(), 3, -2); + } + } + + return $buffer; + } + + /** + * @param ReflectionMethod $method + * @return boolean + * @since Method available since Release 4.0.8 + */ + private static function isBeforeClassMethod(ReflectionMethod $method) + { + return $method->isStatic() && strpos($method->getDocComment(), '@beforeClass') !== false; + } + + /** + * @param ReflectionMethod $method + * @return boolean + * @since Method available since Release 4.0.8 + */ + private static function isBeforeMethod(ReflectionMethod $method) + { + return preg_match('/@before\b/', $method->getDocComment()); + } + + /** + * @param ReflectionMethod $method + * @return boolean + * @since Method available since Release 4.0.8 + */ + private static function isAfterClassMethod(ReflectionMethod $method) + { + return $method->isStatic() && strpos($method->getDocComment(), '@afterClass') !== false; + } + + /** + * @param ReflectionMethod $method + * @return boolean + * @since Method available since Release 4.0.8 + */ + private static function isAfterMethod(ReflectionMethod $method) + { + return preg_match('/@after\b/', $method->getDocComment()); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * Utility class that can print to STDOUT or write to a file. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Util_Printer +{ + /** + * If true, flush output after every write. + * + * @var boolean + */ + protected $autoFlush = false; + + /** + * @var resource + */ + protected $out; + + /** + * @var string + */ + protected $outTarget; + + /** + * @var boolean + */ + protected $printsHTML = false; + + /** + * Constructor. + * + * @param mixed $out + * @throws PHPUnit_Framework_Exception + */ + public function __construct($out = null) + { + if ($out !== null) { + if (is_string($out)) { + if (strpos($out, 'socket://') === 0) { + $out = explode(':', str_replace('socket://', '', $out)); + + if (sizeof($out) != 2) { + throw new PHPUnit_Framework_Exception; + } + + $this->out = fsockopen($out[0], $out[1]); + } else { + if (strpos($out, 'php://') === false && + !is_dir(dirname($out))) { + mkdir(dirname($out), 0777, true); + } + + $this->out = fopen($out, 'wt'); + } + + $this->outTarget = $out; + } else { + $this->out = $out; + } + } + } + + /** + * Flush buffer, optionally tidy up HTML, and close output if it's not to a php stream + */ + public function flush() + { + if ($this->out && strncmp($this->outTarget, 'php://', 6) !== 0) { + fclose($this->out); + } + + if ($this->printsHTML === true && + $this->outTarget !== null && + strpos($this->outTarget, 'php://') !== 0 && + strpos($this->outTarget, 'socket://') !== 0 && + extension_loaded('tidy')) { + file_put_contents( + $this->outTarget, + tidy_repair_file( + $this->outTarget, array('indent' => true, 'wrap' => 0), 'utf8' + ) + ); + } + } + + /** + * Performs a safe, incremental flush. + * + * Do not confuse this function with the flush() function of this class, + * since the flush() function may close the file being written to, rendering + * the current object no longer usable. + * + * @since Method available since Release 3.3.0 + */ + public function incrementalFlush() + { + if ($this->out) { + fflush($this->out); + } else { + flush(); + } + } + + /** + * @param string $buffer + */ + public function write($buffer) + { + if ($this->out) { + fwrite($this->out, $buffer); + + if ($this->autoFlush) { + $this->incrementalFlush(); + } + } else { + if (PHP_SAPI != 'cli') { + $buffer = htmlspecialchars($buffer); + } + + print $buffer; + + if ($this->autoFlush) { + $this->incrementalFlush(); + } + } + } + + /** + * Check auto-flush mode. + * + * @return boolean + * @since Method available since Release 3.3.0 + */ + public function getAutoFlush() + { + return $this->autoFlush; + } + + /** + * Set auto-flushing mode. + * + * If set, *incremental* flushes will be done after each write. This should + * not be confused with the different effects of this class' flush() method. + * + * @param boolean $autoFlush + * @since Method available since Release 3.3.0 + */ + public function setAutoFlush($autoFlush) + { + if (is_bool($autoFlush)) { + $this->autoFlush = $autoFlush; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean'); + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.2.0 + */ + +/** + * Wrapper for the PHPUnit XML configuration file. + * + * Example XML configuration file: + * + * + * + * + * + * + * /path/to/files + * /path/to/MyTest.php + * /path/to/files/exclude + * + * + * + * + * + * name + * + * + * name + * + * + * + * + * + * /path/to/files + * /path/to/file + * + * /path/to/files + * /path/to/file + * + * + * + * /path/to/files + * /path/to/file + * + * /path/to/files + * /path/to/file + * + * + * + * + * + * + * + * + * + * Sebastian + * + * + * 22 + * April + * 19.78 + * + * + * MyRelativeFile.php + * MyRelativeDir + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * . + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.2.0 + */ +class PHPUnit_Util_Configuration +{ + private static $instances = array(); + + protected $document; + protected $xpath; + protected $filename; + + /** + * Loads a PHPUnit configuration file. + * + * @param string $filename + */ + protected function __construct($filename) + { + $this->filename = $filename; + $this->document = PHPUnit_Util_XML::loadFile($filename, false, true); + $this->xpath = new DOMXPath($this->document); + } + + /** + * @since Method available since Release 3.4.0 + */ + final private function __clone() + { + } + + /** + * Returns a PHPUnit configuration object. + * + * @param string $filename + * @return PHPUnit_Util_Configuration + * @since Method available since Release 3.4.0 + */ + public static function getInstance($filename) + { + $realpath = realpath($filename); + + if ($realpath === false) { + throw new PHPUnit_Framework_Exception( + sprintf( + 'Could not read "%s".', + $filename + ) + ); + } + + if (!isset(self::$instances[$realpath])) { + self::$instances[$realpath] = new PHPUnit_Util_Configuration($realpath); + } + + return self::$instances[$realpath]; + } + + /** + * Returns the realpath to the configuration file. + * + * @return string + * @since Method available since Release 3.6.0 + */ + public function getFilename() + { + return $this->filename; + } + + /** + * Returns the configuration for SUT filtering. + * + * @return array + * @since Method available since Release 3.2.1 + */ + public function getFilterConfiguration() + { + $addUncoveredFilesFromWhitelist = true; + $processUncoveredFilesFromWhitelist = false; + + $tmp = $this->xpath->query('filter/whitelist'); + + if ($tmp->length == 1) { + if ($tmp->item(0)->hasAttribute('addUncoveredFilesFromWhitelist')) { + $addUncoveredFilesFromWhitelist = $this->getBoolean( + (string) $tmp->item(0)->getAttribute( + 'addUncoveredFilesFromWhitelist' + ), + true + ); + } + + if ($tmp->item(0)->hasAttribute('processUncoveredFilesFromWhitelist')) { + $processUncoveredFilesFromWhitelist = $this->getBoolean( + (string) $tmp->item(0)->getAttribute( + 'processUncoveredFilesFromWhitelist' + ), + false + ); + } + } + + return array( + 'blacklist' => array( + 'include' => array( + 'directory' => $this->readFilterDirectories( + 'filter/blacklist/directory' + ), + 'file' => $this->readFilterFiles( + 'filter/blacklist/file' + ) + ), + 'exclude' => array( + 'directory' => $this->readFilterDirectories( + 'filter/blacklist/exclude/directory' + ), + 'file' => $this->readFilterFiles( + 'filter/blacklist/exclude/file' + ) + ) + ), + 'whitelist' => array( + 'addUncoveredFilesFromWhitelist' => $addUncoveredFilesFromWhitelist, + 'processUncoveredFilesFromWhitelist' => $processUncoveredFilesFromWhitelist, + 'include' => array( + 'directory' => $this->readFilterDirectories( + 'filter/whitelist/directory' + ), + 'file' => $this->readFilterFiles( + 'filter/whitelist/file' + ) + ), + 'exclude' => array( + 'directory' => $this->readFilterDirectories( + 'filter/whitelist/exclude/directory' + ), + 'file' => $this->readFilterFiles( + 'filter/whitelist/exclude/file' + ) + ) + ) + ); + } + + /** + * Returns the configuration for groups. + * + * @return array + * @since Method available since Release 3.2.1 + */ + public function getGroupConfiguration() + { + $groups = array( + 'include' => array(), + 'exclude' => array() + ); + + foreach ($this->xpath->query('groups/include/group') as $group) { + $groups['include'][] = (string) $group->nodeValue; + } + + foreach ($this->xpath->query('groups/exclude/group') as $group) { + $groups['exclude'][] = (string) $group->nodeValue; + } + + return $groups; + } + + /** + * Returns the configuration for listeners. + * + * @return array + * @since Method available since Release 3.4.0 + */ + public function getListenerConfiguration() + { + $result = array(); + + foreach ($this->xpath->query('listeners/listener') as $listener) { + $class = (string) $listener->getAttribute('class'); + $file = ''; + $arguments = array(); + + if ($listener->hasAttribute('file')) { + $file = $this->toAbsolutePath( + (string) $listener->getAttribute('file'), true + ); + } + + foreach ($listener->childNodes as $node) { + if ($node instanceof DOMElement && $node->tagName == 'arguments') { + foreach ($node->childNodes as $argument) { + if ($argument instanceof DOMElement) { + if ($argument->tagName == 'file' || + $argument->tagName == 'directory') { + $arguments[] = $this->toAbsolutePath((string) $argument->nodeValue); + } else { + $arguments[] = PHPUnit_Util_XML::xmlToVariable($argument); + } + } + } + } + } + + $result[] = array( + 'class' => $class, + 'file' => $file, + 'arguments' => $arguments + ); + } + + return $result; + } + + /** + * Returns the logging configuration. + * + * @return array + */ + public function getLoggingConfiguration() + { + $result = array(); + + foreach ($this->xpath->query('logging/log') as $log) { + $type = (string) $log->getAttribute('type'); + + $target = $this->toAbsolutePath( + (string) $log->getAttribute('target') + ); + + if ($type == 'coverage-html') { + if ($log->hasAttribute('lowUpperBound')) { + $result['lowUpperBound'] = (string) $log->getAttribute('lowUpperBound'); + } + + if ($log->hasAttribute('highLowerBound')) { + $result['highLowerBound'] = (string) $log->getAttribute('highLowerBound'); + } + } elseif ($type == 'junit') { + if ($log->hasAttribute('logIncompleteSkipped')) { + $result['logIncompleteSkipped'] = $this->getBoolean( + (string) $log->getAttribute('logIncompleteSkipped'), + false + ); + } + } elseif ($type == 'coverage-text') { + if ($log->hasAttribute('showUncoveredFiles')) { + $result['coverageTextShowUncoveredFiles'] = $this->getBoolean( + (string) $log->getAttribute('showUncoveredFiles'), + false + ); + } + if ($log->hasAttribute('showOnlySummary')) { + $result['coverageTextShowOnlySummary'] = $this->getBoolean( + (string) $log->getAttribute('showOnlySummary'), + false + ); + } + } + + $result[$type] = $target; + } + + return $result; + } + + /** + * Returns the PHP configuration. + * + * @return array + * @since Method available since Release 3.2.1 + */ + public function getPHPConfiguration() + { + $result = array( + 'include_path' => array(), + 'ini' => array(), + 'const' => array(), + 'var' => array(), + 'env' => array(), + 'post' => array(), + 'get' => array(), + 'cookie' => array(), + 'server' => array(), + 'files' => array(), + 'request' => array() + ); + + foreach ($this->xpath->query('php/includePath') as $includePath) { + $path = (string) $includePath->nodeValue; + + $result['include_path'][] = $this->toAbsolutePath($path); + } + + foreach ($this->xpath->query('php/ini') as $ini) { + $name = (string) $ini->getAttribute('name'); + $value = (string) $ini->getAttribute('value'); + + $result['ini'][$name] = $value; + } + + foreach ($this->xpath->query('php/const') as $const) { + $name = (string) $const->getAttribute('name'); + $value = (string) $const->getAttribute('value'); + + $result['const'][$name] = $this->getBoolean($value, $value); + } + + foreach (array('var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request') as $array) { + foreach ($this->xpath->query('php/' . $array) as $var) { + $name = (string) $var->getAttribute('name'); + $value = (string) $var->getAttribute('value'); + + $result[$array][$name] = $this->getBoolean($value, $value); + } + } + + return $result; + } + + /** + * Handles the PHP configuration. + * + * @since Method available since Release 3.2.20 + */ + public function handlePHPConfiguration() + { + $configuration = $this->getPHPConfiguration(); + + if (! empty($configuration['include_path'])) { + ini_set( + 'include_path', + implode(PATH_SEPARATOR, $configuration['include_path']) . + PATH_SEPARATOR . + ini_get('include_path') + ); + } + + foreach ($configuration['ini'] as $name => $value) { + if (defined($value)) { + $value = constant($value); + } + + ini_set($name, $value); + } + + foreach ($configuration['const'] as $name => $value) { + if (!defined($name)) { + define($name, $value); + } + } + + foreach (array('var', 'post', 'get', 'cookie', 'server', 'files', 'request') as $array) { + // See https://github.com/sebastianbergmann/phpunit/issues/277 + switch ($array) { + case 'var': + $target = &$GLOBALS; + break; + + case 'server': + $target = &$_SERVER; + break; + + default: + $target = &$GLOBALS['_' . strtoupper($array)]; + break; + } + + foreach ($configuration[$array] as $name => $value) { + $target[$name] = $value; + } + } + + foreach ($configuration['env'] as $name => $value) { + if (false === getenv($name)) { + putenv("{$name}={$value}"); + } + if (!isset($_ENV[$name])) { + $_ENV[$name] = $value; + } + } + } + + /** + * Returns the PHPUnit configuration. + * + * @return array + * @since Method available since Release 3.2.14 + */ + public function getPHPUnitConfiguration() + { + $result = array(); + $root = $this->document->documentElement; + + if ($root->hasAttribute('cacheTokens')) { + $result['cacheTokens'] = $this->getBoolean( + (string) $root->getAttribute('cacheTokens'), false + ); + } + + if ($root->hasAttribute('colors')) { + $result['colors'] = $this->getBoolean( + (string) $root->getAttribute('colors'), false + ); + } + + /** + * Issue #657 + */ + if ($root->hasAttribute('stderr')) { + $result['stderr'] = $this->getBoolean( + (string)$root->getAttribute('stderr'), FALSE + ); + } + + if ($root->hasAttribute('backupGlobals')) { + $result['backupGlobals'] = $this->getBoolean( + (string) $root->getAttribute('backupGlobals'), true + ); + } + + if ($root->hasAttribute('backupStaticAttributes')) { + $result['backupStaticAttributes'] = $this->getBoolean( + (string) $root->getAttribute('backupStaticAttributes'), false + ); + } + + if ($root->hasAttribute('bootstrap')) { + $result['bootstrap'] = $this->toAbsolutePath( + (string) $root->getAttribute('bootstrap') + ); + } + + if ($root->hasAttribute('convertErrorsToExceptions')) { + $result['convertErrorsToExceptions'] = $this->getBoolean( + (string) $root->getAttribute('convertErrorsToExceptions'), true + ); + } + + if ($root->hasAttribute('convertNoticesToExceptions')) { + $result['convertNoticesToExceptions'] = $this->getBoolean( + (string) $root->getAttribute('convertNoticesToExceptions'), true + ); + } + + if ($root->hasAttribute('convertWarningsToExceptions')) { + $result['convertWarningsToExceptions'] = $this->getBoolean( + (string) $root->getAttribute('convertWarningsToExceptions'), true + ); + } + + if ($root->hasAttribute('forceCoversAnnotation')) { + $result['forceCoversAnnotation'] = $this->getBoolean( + (string) $root->getAttribute('forceCoversAnnotation'), false + ); + } + + if ($root->hasAttribute('mapTestClassNameToCoveredClassName')) { + $result['mapTestClassNameToCoveredClassName'] = $this->getBoolean( + (string) $root->getAttribute('mapTestClassNameToCoveredClassName'), + false + ); + } + + if ($root->hasAttribute('processIsolation')) { + $result['processIsolation'] = $this->getBoolean( + (string) $root->getAttribute('processIsolation'), false + ); + } + + if ($root->hasAttribute('stopOnError')) { + $result['stopOnError'] = $this->getBoolean( + (string) $root->getAttribute('stopOnError'), false + ); + } + + if ($root->hasAttribute('stopOnFailure')) { + $result['stopOnFailure'] = $this->getBoolean( + (string) $root->getAttribute('stopOnFailure'), false + ); + } + + if ($root->hasAttribute('stopOnIncomplete')) { + $result['stopOnIncomplete'] = $this->getBoolean( + (string) $root->getAttribute('stopOnIncomplete'), false + ); + } + + if ($root->hasAttribute('stopOnRisky')) { + $result['stopOnRisky'] = $this->getBoolean( + (string) $root->getAttribute('stopOnRisky'), false + ); + } + + if ($root->hasAttribute('stopOnSkipped')) { + $result['stopOnSkipped'] = $this->getBoolean( + (string) $root->getAttribute('stopOnSkipped'), false + ); + } + + if ($root->hasAttribute('testSuiteLoaderClass')) { + $result['testSuiteLoaderClass'] = (string) $root->getAttribute( + 'testSuiteLoaderClass' + ); + } + + if ($root->hasAttribute('testSuiteLoaderFile')) { + $result['testSuiteLoaderFile'] = $this->toAbsolutePath( + (string) $root->getAttribute('testSuiteLoaderFile') + ); + } + + if ($root->hasAttribute('printerClass')) { + $result['printerClass'] = (string) $root->getAttribute( + 'printerClass' + ); + } + + if ($root->hasAttribute('printerFile')) { + $result['printerFile'] = $this->toAbsolutePath( + (string) $root->getAttribute('printerFile') + ); + } + + if ($root->hasAttribute('timeoutForSmallTests')) { + $result['timeoutForSmallTests'] = $this->getInteger( + (string) $root->getAttribute('timeoutForSmallTests'), 1 + ); + } + + if ($root->hasAttribute('timeoutForMediumTests')) { + $result['timeoutForMediumTests'] = $this->getInteger( + (string) $root->getAttribute('timeoutForMediumTests'), 10 + ); + } + + if ($root->hasAttribute('timeoutForLargeTests')) { + $result['timeoutForLargeTests'] = $this->getInteger( + (string) $root->getAttribute('timeoutForLargeTests'), 60 + ); + } + + if ($root->hasAttribute('beStrictAboutTestsThatDoNotTestAnything')) { + $result['reportUselessTests'] = $this->getBoolean( + (string) $root->getAttribute('beStrictAboutTestsThatDoNotTestAnything'), false + ); + } + + if ($root->hasAttribute('checkForUnintentionallyCoveredCode')) { + $result['strictCoverage'] = $this->getBoolean( + (string) $root->getAttribute('checkForUnintentionallyCoveredCode'), false + ); + } + + if ($root->hasAttribute('beStrictAboutOutputDuringTests')) { + $result['disallowTestOutput'] = $this->getBoolean( + (string) $root->getAttribute('beStrictAboutOutputDuringTests'), false + ); + } + + if ($root->hasAttribute('beStrictAboutTestSize')) { + $result['enforceTimeLimit'] = $this->getBoolean( + (string) $root->getAttribute('beStrictAboutTestSize'), false + ); + } + + if ($root->hasAttribute('strict')) { + $flag = $this->getBoolean( + (string) $root->getAttribute('strict'), false + ); + + $result['reportUselessTests'] = $flag; + $result['strictCoverage'] = $flag; + $result['disallowTestOutput'] = $flag; + $result['enforceTimeLimit'] = $flag; + } + + if ($root->hasAttribute('verbose')) { + $result['verbose'] = $this->getBoolean( + (string) $root->getAttribute('verbose'), false + ); + } + + return $result; + } + + /** + * Returns the SeleniumTestCase browser configuration. + * + * @return array + * @since Method available since Release 3.2.9 + */ + public function getSeleniumBrowserConfiguration() + { + $result = array(); + + foreach ($this->xpath->query('selenium/browser') as $config) { + $name = (string) $config->getAttribute('name'); + $browser = (string) $config->getAttribute('browser'); + + if ($config->hasAttribute('host')) { + $host = (string) $config->getAttribute('host'); + } else { + $host = 'localhost'; + } + + if ($config->hasAttribute('port')) { + $port = $this->getInteger( + (string) $config->getAttribute('port'), 4444 + ); + } else { + $port = 4444; + } + + if ($config->hasAttribute('timeout')) { + $timeout = $this->getInteger( + (string) $config->getAttribute('timeout'), 30000 + ); + } else { + $timeout = 30000; + } + + $result[] = array( + 'name' => $name, + 'browser' => $browser, + 'host' => $host, + 'port' => $port, + 'timeout' => $timeout + ); + } + + return $result; + } + + /** + * Returns the test suite configuration. + * + * @return PHPUnit_Framework_TestSuite + * @since Method available since Release 3.2.1 + */ + public function getTestSuiteConfiguration($testSuiteFilter=null) + { + $testSuiteNodes = $this->xpath->query('testsuites/testsuite'); + + if ($testSuiteNodes->length == 0) { + $testSuiteNodes = $this->xpath->query('testsuite'); + } + + if ($testSuiteNodes->length == 1) { + return $this->getTestSuite($testSuiteNodes->item(0), $testSuiteFilter); + } + + if ($testSuiteNodes->length > 1) { + $suite = new PHPUnit_Framework_TestSuite; + + foreach ($testSuiteNodes as $testSuiteNode) { + $suite->addTestSuite( + $this->getTestSuite($testSuiteNode, $testSuiteFilter) + ); + } + + return $suite; + } + } + + /** + * @param DOMElement $testSuiteNode + * @return PHPUnit_Framework_TestSuite + * @since Method available since Release 3.4.0 + */ + protected function getTestSuite(DOMElement $testSuiteNode, $testSuiteFilter=null) + { + if ($testSuiteNode->hasAttribute('name')) { + $suite = new PHPUnit_Framework_TestSuite( + (string) $testSuiteNode->getAttribute('name') + ); + } else { + $suite = new PHPUnit_Framework_TestSuite; + } + + $exclude = array(); + + foreach ($testSuiteNode->getElementsByTagName('exclude') as $excludeNode) { + $exclude[] = $this->toAbsolutePath( + (string) $excludeNode->nodeValue + ); + } + + $fileIteratorFacade = new File_Iterator_Facade; + + foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) { + if ($testSuiteFilter && $directoryNode->parentNode->getAttribute('name') != $testSuiteFilter) { + continue; + } + + $directory = (string) $directoryNode->nodeValue; + + if (empty($directory)) { + continue; + } + + if ($directoryNode->hasAttribute('phpVersion')) { + $phpVersion = (string) $directoryNode->getAttribute('phpVersion'); + } else { + $phpVersion = PHP_VERSION; + } + + if ($directoryNode->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = (string) $directoryNode->getAttribute('phpVersionOperator'); + } else { + $phpVersionOperator = '>='; + } + + if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) { + continue; + } + + if ($directoryNode->hasAttribute('prefix')) { + $prefix = (string) $directoryNode->getAttribute('prefix'); + } else { + $prefix = ''; + } + + if ($directoryNode->hasAttribute('suffix')) { + $suffix = (string) $directoryNode->getAttribute('suffix'); + } else { + $suffix = 'Test.php'; + } + + $files = $fileIteratorFacade->getFilesAsArray( + $this->toAbsolutePath($directory), + $suffix, + $prefix, + $exclude + ); + $suite->addTestFiles($files); + } + + foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) { + if ($testSuiteFilter && $fileNode->parentNode->getAttribute('name') != $testSuiteFilter) { + continue; + } + + $file = (string) $fileNode->nodeValue; + + if (empty($file)) { + continue; + } + + // Get the absolute path to the file + $file = $fileIteratorFacade->getFilesAsArray( + $this->toAbsolutePath($file) + ); + + if (!isset($file[0])) { + continue; + } + + $file = $file[0]; + + if ($fileNode->hasAttribute('phpVersion')) { + $phpVersion = (string) $fileNode->getAttribute('phpVersion'); + } else { + $phpVersion = PHP_VERSION; + } + + if ($fileNode->hasAttribute('phpVersionOperator')) { + $phpVersionOperator = (string) $fileNode->getAttribute('phpVersionOperator'); + } else { + $phpVersionOperator = '>='; + } + + if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) { + continue; + } + + $suite->addTestFile($file); + } + + return $suite; + } + + /** + * @param string $value + * @param boolean $default + * @return boolean + * @since Method available since Release 3.2.3 + */ + protected function getBoolean($value, $default) + { + if (strtolower($value) == 'false') { + return false; + } elseif (strtolower($value) == 'true') { + return true; + } + + return $default; + } + + /** + * @param string $value + * @param boolean $default + * @return boolean + * @since Method available since Release 3.6.0 + */ + protected function getInteger($value, $default) + { + if (is_numeric($value)) { + return (int) $value; + } + + return $default; + } + + /** + * @param string $query + * @return array + * @since Method available since Release 3.2.3 + */ + protected function readFilterDirectories($query) + { + $directories = array(); + + foreach ($this->xpath->query($query) as $directory) { + if ($directory->hasAttribute('prefix')) { + $prefix = (string) $directory->getAttribute('prefix'); + } else { + $prefix = ''; + } + + if ($directory->hasAttribute('suffix')) { + $suffix = (string) $directory->getAttribute('suffix'); + } else { + $suffix = '.php'; + } + + if ($directory->hasAttribute('group')) { + $group = (string) $directory->getAttribute('group'); + } else { + $group = 'DEFAULT'; + } + + $directories[] = array( + 'path' => $this->toAbsolutePath((string) $directory->nodeValue), + 'prefix' => $prefix, + 'suffix' => $suffix, + 'group' => $group + ); + } + + return $directories; + } + + /** + * @param string $query + * @return array + * @since Method available since Release 3.2.3 + */ + protected function readFilterFiles($query) + { + $files = array(); + + foreach ($this->xpath->query($query) as $file) { + $files[] = $this->toAbsolutePath((string) $file->nodeValue); + } + + return $files; + } + + /** + * @param string $path + * @param boolean $useIncludePath + * @return string + * @since Method available since Release 3.5.0 + */ + protected function toAbsolutePath($path, $useIncludePath = false) + { + if ($path[0] === '/') { + return $path; + } + + // Matches the following on Windows: + // - \\NetworkComputer\Path + // - \\.\D: + // - \\.\c: + // - C:\Windows + // - C:\windows + // - C:/windows + // - c:/windows + if (defined('PHP_WINDOWS_VERSION_BUILD') && + ($path[0] === '\\' || + (strlen($path) >= 3 && preg_match('#^[A-Z]\:[/\\\]#i', substr($path, 0, 3))))) { + return $path; + } + + // Stream + if (strpos($path, '://') !== false) { + return $path; + } + + $file = dirname($this->filename) . DIRECTORY_SEPARATOR . $path; + + if ($useIncludePath && !file_exists($file)) { + $includePathFile = stream_resolve_include_path($path); + + if ($includePathFile) { + $file = $includePathFile; + } + } + + return $file; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * Factory for PHPUnit_Framework_Exception objects that are used to describe + * invalid arguments passed to a function or method. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +class PHPUnit_Util_InvalidArgumentHelper +{ + /** + * @param integer $argument + * @param string $type + * @param mixed $value + * @return PHPUnit_Framework_Exception + */ + public static function factory($argument, $type, $value = null) + { + $stack = debug_backtrace(false); + + return new PHPUnit_Framework_Exception( + sprintf( + 'Argument #%d%sof %s::%s() must be a %s', + $argument, + $value !== null ? ' (' . gettype($value) . '#' . $value . ')' : ' (No Value) ', + $stack[1]['class'], + $stack[1]['function'], + $type + ) + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * Utility class for blacklisting PHPUnit's own source code files. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Util_Blacklist +{ + /** + * @var array + */ + public static $blacklistedClassNames = array( + 'File_Iterator' => 1, + 'PHP_CodeCoverage' => 1, + 'PHP_Invoker' => 1, + 'PHP_Timer' => 1, + 'PHP_Token' => 1, + 'PHPUnit_Framework_TestCase' => 2, + 'PHPUnit_Extensions_Database_TestCase' => 2, + 'PHPUnit_Framework_MockObject_Generator' => 2, + 'PHPUnit_Extensions_SeleniumTestCase' => 2, + 'PHPUnit_Extensions_Story_TestCase' => 2, + 'Text_Template' => 1, + 'Symfony\Component\Yaml\Yaml' => 1, + 'SebastianBergmann\Diff\Diff' => 1, + 'SebastianBergmann\Environment\Runtime' => 1, + 'SebastianBergmann\Comparator\Comparator' => 1, + 'SebastianBergmann\Exporter\Exporter' => 1, + 'SebastianBergmann\Version' => 1, + 'Composer\Autoload\ClassLoader' => 1 + ); + + /** + * @var array + */ + private static $directories; + + /** + * @return array + * @since Method available since Release 4.1.0 + */ + public function getBlacklistedDirectories() + { + $this->initialize(); + + return self::$directories; + } + + /** + * @param string $file + * @return boolean + */ + public function isBlacklisted($file) + { + if (defined('PHPUNIT_TESTSUITE')) { + return false; + } + + $this->initialize(); + + foreach (self::$directories as $directory) { + if (strpos($file, $directory) === 0) { + return true; + } + } + + return false; + } + + private function initialize() + { + if (self::$directories === null) { + self::$directories = array(); + + foreach (self::$blacklistedClassNames as $className => $parent) { + if (!class_exists($className)) { + continue; + } + + $reflector = new ReflectionClass($className); + $directory = $reflector->getFileName(); + + for ($i = 0; $i < $parent; $i++) { + $directory = dirname($directory); + } + + self::$directories[] = $directory; + } + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +/** + * Prettifies class and method names for use in TestDox documentation. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.1.0 + */ +class PHPUnit_Util_TestDox_NamePrettifier +{ + /** + * @var string + */ + protected $prefix = 'Test'; + + /** + * @var string + */ + protected $suffix = 'Test'; + + /** + * @var array + */ + protected $strings = array(); + + /** + * Prettifies the name of a test class. + * + * @param string $name + * @return string + */ + public function prettifyTestClass($name) + { + $title = $name; + + if ($this->suffix !== null && + $this->suffix == substr($name, -1 * strlen($this->suffix))) { + $title = substr($title, 0, strripos($title, $this->suffix)); + } + + if ($this->prefix !== null && + $this->prefix == substr($name, 0, strlen($this->prefix))) { + $title = substr($title, strlen($this->prefix)); + } + + if (substr($title, 0, 1) == '\\') { + $title = substr($title, 1); + } + + return $title; + } + + /** + * Prettifies the name of a test method. + * + * @param string $name + * @return string + */ + public function prettifyTestMethod($name) + { + $buffer = ''; + + if (!is_string($name) || strlen($name) == 0) { + return $buffer; + } + + $string = preg_replace('#\d+$#', '', $name, -1, $count); + + if (in_array($string, $this->strings)) { + $name = $string; + } elseif ($count == 0) { + $this->strings[] = $string; + } + + if (strpos($name, '_') !== false) { + return str_replace('_', ' ', $name); + } + + $max = strlen($name); + + if (substr($name, 0, 4) == 'test') { + $offset = 4; + } else { + $offset = 0; + $name[0] = strtoupper($name[0]); + } + + $wasNumeric = false; + + for ($i = $offset; $i < $max; $i++) { + if ($i > $offset && + ord($name[$i]) >= 65 && + ord($name[$i]) <= 90) { + $buffer .= ' ' . strtolower($name[$i]); + } else { + $isNumeric = is_numeric($name[$i]); + + if (!$wasNumeric && $isNumeric) { + $buffer .= ' '; + $wasNumeric = true; + } + + if ($wasNumeric && !$isNumeric) { + $wasNumeric = false; + } + + $buffer .= $name[$i]; + } + } + + return $buffer; + } + + /** + * Sets the prefix of test names. + * + * @param string $prefix + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + } + + /** + * Sets the suffix of test names. + * + * @param string $suffix + */ + public function setSuffix($suffix) + { + $this->suffix = $suffix; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +/** + * Base class for printers of TestDox documentation. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.1.0 + */ +abstract class PHPUnit_Util_TestDox_ResultPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener +{ + /** + * @var PHPUnit_Util_TestDox_NamePrettifier + */ + protected $prettifier; + + /** + * @var string + */ + protected $testClass = ''; + + /** + * @var integer + */ + protected $testStatus = false; + + /** + * @var array + */ + protected $tests = array(); + + /** + * @var integer + */ + protected $successful = 0; + + /** + * @var integer + */ + protected $failed = 0; + + /** + * @var integer + */ + protected $risky = 0; + + /** + * @var integer + */ + protected $skipped = 0; + + /** + * @var integer + */ + protected $incomplete = 0; + + /** + * @var string + */ + protected $testTypeOfInterest = 'PHPUnit_Framework_TestCase'; + + /** + * @var string + */ + protected $currentTestClassPrettified; + + /** + * @var string + */ + protected $currentTestMethodPrettified; + + /** + * Constructor. + * + * @param resource $out + */ + public function __construct($out = null) + { + parent::__construct($out); + + $this->prettifier = new PHPUnit_Util_TestDox_NamePrettifier; + $this->startRun(); + } + + /** + * Flush buffer and close output. + * + */ + public function flush() + { + $this->doEndClass(); + $this->endRun(); + + parent::flush(); + } + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($test instanceof $this->testTypeOfInterest) { + $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; + $this->failed++; + } + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + if ($test instanceof $this->testTypeOfInterest) { + $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE; + $this->failed++; + } + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($test instanceof $this->testTypeOfInterest) { + $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE; + $this->incomplete++; + } + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($test instanceof $this->testTypeOfInterest) { + $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_RISKY; + $this->risky++; + } + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + if ($test instanceof $this->testTypeOfInterest) { + $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED; + $this->skipped++; + } + } + + /** + * A testsuite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A testsuite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + if ($test instanceof $this->testTypeOfInterest) { + $class = get_class($test); + + if ($this->testClass != $class) { + if ($this->testClass != '') { + $this->doEndClass(); + } + + $this->currentTestClassPrettified = $this->prettifier->prettifyTestClass($class); + $this->startClass($class); + + $this->testClass = $class; + $this->tests = array(); + } + + $prettified = false; + + if ($test instanceof PHPUnit_Framework_TestCase && + !$test instanceof PHPUnit_Framework_Warning) { + $annotations = $test->getAnnotations(); + + if (isset($annotations['method']['testdox'][0])) { + $this->currentTestMethodPrettified = $annotations['method']['testdox'][0]; + $prettified = true; + } + } + + if (!$prettified) { + $this->currentTestMethodPrettified = $this->prettifier->prettifyTestMethod($test->getName(false)); + } + + $this->testStatus = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED; + } + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + if ($test instanceof $this->testTypeOfInterest) { + if (!isset($this->tests[$this->currentTestMethodPrettified])) { + if ($this->testStatus == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) { + $this->tests[$this->currentTestMethodPrettified]['success'] = 1; + $this->tests[$this->currentTestMethodPrettified]['failure'] = 0; + } else { + $this->tests[$this->currentTestMethodPrettified]['success'] = 0; + $this->tests[$this->currentTestMethodPrettified]['failure'] = 1; + } + } else { + if ($this->testStatus == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) { + $this->tests[$this->currentTestMethodPrettified]['success']++; + } else { + $this->tests[$this->currentTestMethodPrettified]['failure']++; + } + } + + $this->currentTestClassPrettified = null; + $this->currentTestMethodPrettified = null; + } + } + + /** + * @since Method available since Release 2.3.0 + */ + protected function doEndClass() + { + foreach ($this->tests as $name => $data) { + $this->onTest($name, $data['failure'] == 0); + } + + $this->endClass($this->testClass); + } + + /** + * Handler for 'start run' event. + * + */ + protected function startRun() + { + } + + /** + * Handler for 'start class' event. + * + * @param string $name + */ + protected function startClass($name) + { + } + + /** + * Handler for 'on test' event. + * + * @param string $name + * @param boolean $success + */ + protected function onTest($name, $success = true) + { + } + + /** + * Handler for 'end class' event. + * + * @param string $name + */ + protected function endClass($name) + { + } + + /** + * Handler for 'end run' event. + * + */ + protected function endRun() + { + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +/** + * Prints TestDox documentation in HTML format. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.1.0 + */ +class PHPUnit_Util_TestDox_ResultPrinter_HTML extends PHPUnit_Util_TestDox_ResultPrinter +{ + /** + * @var boolean + */ + protected $printsHTML = true; + + /** + * Handler for 'start run' event. + * + */ + protected function startRun() + { + $this->write(''); + } + + /** + * Handler for 'start class' event. + * + * @param string $name + */ + protected function startClass($name) + { + $this->write( + '

' . $this->currentTestClassPrettified . + '

    ' + ); + } + + /** + * Handler for 'on test' event. + * + * @param string $name + * @param boolean $success + */ + protected function onTest($name, $success = true) + { + if (!$success) { + $strikeOpen = ''; + $strikeClose = ''; + } else { + $strikeOpen = ''; + $strikeClose = ''; + } + + $this->write('
  • ' . $strikeOpen . $name . $strikeClose . '
  • '); + } + + /** + * Handler for 'end class' event. + * + * @param string $name + */ + protected function endClass($name) + { + $this->write('
'); + } + + /** + * Handler for 'end run' event. + * + */ + protected function endRun() + { + $this->write(''); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +/** + * Prints TestDox documentation in text format. + * + * @package PHPUnit + * @subpackage Util_TestDox + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.1.0 + */ +class PHPUnit_Util_TestDox_ResultPrinter_Text extends PHPUnit_Util_TestDox_ResultPrinter +{ + /** + * Handler for 'start class' event. + * + * @param string $name + */ + protected function startClass($name) + { + $this->write($this->currentTestClassPrettified . "\n"); + } + + /** + * Handler for 'on test' event. + * + * @param string $name + * @param boolean $success + */ + protected function onTest($name, $success = true) + { + if ($success) { + $this->write(' [x] '); + } else { + $this->write(' [ ] '); + } + + $this->write($name . "\n"); + } + + /** + * Handler for 'end class' event. + * + * @param string $name + */ + protected function endClass($name) + { + $this->write("\n"); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.3.0 + */ + +// Workaround for http://bugs.php.net/bug.php?id=47987, +// see https://github.com/sebastianbergmann/phpunit/issues#issue/125 for details +require_once __DIR__ . '/../Framework/Error.php'; +require_once __DIR__ . '/../Framework/Error/Notice.php'; +require_once __DIR__ . '/../Framework/Error/Warning.php'; +require_once __DIR__ . '/../Framework/Error/Deprecated.php'; + +/** + * Error handler that converts PHP errors and warnings to exceptions. + * + * @package PHPUnit + * @subpackage Util + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Util_ErrorHandler +{ + protected static $errorStack = array(); + + /** + * Returns the error stack. + * + * @return array + */ + public static function getErrorStack() + { + return self::$errorStack; + } + + /** + * @param integer $errno + * @param string $errstr + * @param string $errfile + * @param integer $errline + * @throws PHPUnit_Framework_Error + */ + public static function handleError($errno, $errstr, $errfile, $errline) + { + if (!($errno & error_reporting())) { + return false; + } + + self::$errorStack[] = array($errno, $errstr, $errfile, $errline); + + $trace = debug_backtrace(false); + array_shift($trace); + + foreach ($trace as $frame) { + if ($frame['function'] == '__toString') { + return false; + } + } + + if ($errno == E_NOTICE || $errno == E_USER_NOTICE || $errno == E_STRICT) { + if (PHPUnit_Framework_Error_Notice::$enabled !== true) { + return false; + } + + $exception = 'PHPUnit_Framework_Error_Notice'; + } elseif ($errno == E_WARNING || $errno == E_USER_WARNING) { + if (PHPUnit_Framework_Error_Warning::$enabled !== true) { + return false; + } + + $exception = 'PHPUnit_Framework_Error_Warning'; + } elseif ($errno == E_DEPRECATED || $errno == E_USER_DEPRECATED) { + if (PHPUnit_Framework_Error_Deprecated::$enabled !== true) { + return false; + } + + $exception = 'PHPUnit_Framework_Error_Deprecated'; + } else { + $exception = 'PHPUnit_Framework_Error'; + } + + throw new $exception($errstr, $errno, $errfile, $errline); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage TextUI + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.0.0 + */ + +/** + * A TestRunner for the Command Line Interface (CLI) + * PHP SAPI Module. + * + * @package PHPUnit + * @subpackage TextUI + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.0.0 + */ +class PHPUnit_TextUI_Command +{ + /** + * @var array + */ + protected $arguments = array( + 'listGroups' => false, + 'loader' => null, + 'useDefaultConfiguration' => true + ); + + /** + * @var array + */ + protected $options = array(); + + /** + * @var array + */ + protected $longOptions = array( + 'colors' => null, + 'bootstrap=' => null, + 'configuration=' => null, + 'coverage-clover=' => null, + 'coverage-crap4j=' => null, + 'coverage-html=' => null, + 'coverage-php=' => null, + 'coverage-text==' => null, + 'coverage-xml=' => null, + 'debug' => null, + 'exclude-group=' => null, + 'filter=' => null, + 'testsuite=' => null, + 'group=' => null, + 'help' => null, + 'include-path=' => null, + 'list-groups' => null, + 'loader=' => null, + 'log-json=' => null, + 'log-junit=' => null, + 'log-tap=' => null, + 'process-isolation' => null, + 'repeat=' => null, + 'stderr' => null, + 'stop-on-error' => null, + 'stop-on-failure' => null, + 'stop-on-incomplete' => null, + 'stop-on-risky' => null, + 'stop-on-skipped' => null, + 'report-useless-tests' => null, + 'strict-coverage' => null, + 'disallow-test-output' => null, + 'enforce-time-limit' => null, + 'strict' => null, + 'tap' => null, + 'testdox' => null, + 'testdox-html=' => null, + 'testdox-text=' => null, + 'test-suffix=' => null, + 'no-configuration' => null, + 'no-globals-backup' => null, + 'printer=' => null, + 'static-backup' => null, + 'verbose' => null, + 'version' => null + ); + + /** + * @param boolean $exit + */ + public static function main($exit = true) + { + $command = new static; + + return $command->run($_SERVER['argv'], $exit); + } + + /** + * @param array $argv + * @param boolean $exit + */ + public function run(array $argv, $exit = true) + { + $this->handleArguments($argv); + + $runner = $this->createRunner(); + + if (is_object($this->arguments['test']) && + $this->arguments['test'] instanceof PHPUnit_Framework_Test) { + $suite = $this->arguments['test']; + } else { + $suite = $runner->getTest( + $this->arguments['test'], + $this->arguments['testFile'], + $this->arguments['testSuffixes'] + ); + } + + if ($this->arguments['listGroups']) { + PHPUnit_TextUI_TestRunner::printVersionString(); + + print "Available test group(s):\n"; + + $groups = $suite->getGroups(); + sort($groups); + + foreach ($groups as $group) { + print " - $group\n"; + } + + if ($exit) { + exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); + } else { + return PHPUnit_TextUI_TestRunner::SUCCESS_EXIT; + } + } + + unset($this->arguments['test']); + unset($this->arguments['testFile']); + + try { + $result = $runner->doRun($suite, $this->arguments); + } catch (PHPUnit_Framework_Exception $e) { + print $e->getMessage() . "\n"; + } + + $ret = PHPUnit_TextUI_TestRunner::FAILURE_EXIT; + + if (isset($result) && $result->wasSuccessful()) { + $ret = PHPUnit_TextUI_TestRunner::SUCCESS_EXIT; + } elseif (!isset($result) || $result->errorCount() > 0) { + $ret = PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT; + } + + if ($exit) { + exit($ret); + } else { + return $ret; + } + } + + /** + * Create a TestRunner, override in subclasses. + * + * @return PHPUnit_TextUI_TestRunner + * @since Method available since Release 3.6.0 + */ + protected function createRunner() + { + return new PHPUnit_TextUI_TestRunner($this->arguments['loader']); + } + + /** + * Handles the command-line arguments. + * + * A child class of PHPUnit_TextUI_Command can hook into the argument + * parsing by adding the switch(es) to the $longOptions array and point to a + * callback method that handles the switch(es) in the child class like this + * + * + * longOptions['my-switch'] = 'myHandler'; + * // my-secondswitch will accept a value - note the equals sign + * $this->longOptions['my-secondswitch='] = 'myOtherHandler'; + * } + * + * // --my-switch -> myHandler() + * protected function myHandler() + * { + * } + * + * // --my-secondswitch foo -> myOtherHandler('foo') + * protected function myOtherHandler ($value) + * { + * } + * + * // You will also need this - the static keyword in the + * // PHPUnit_TextUI_Command will mean that it'll be + * // PHPUnit_TextUI_Command that gets instantiated, + * // not MyCommand + * public static function main($exit = true) + * { + * $command = new static; + * + * return $command->run($_SERVER['argv'], $exit); + * } + * + * } + * + * + * @param array $argv + */ + protected function handleArguments(array $argv) + { + if (defined('__PHPUNIT_PHAR__')) { + $this->longOptions['selfupdate'] = null; + $this->longOptions['self-update'] = null; + } + + try { + $this->options = PHPUnit_Util_Getopt::getopt( + $argv, + 'd:c:hv', + array_keys($this->longOptions) + ); + } catch (PHPUnit_Framework_Exception $e) { + PHPUnit_TextUI_TestRunner::showError($e->getMessage()); + } + + foreach ($this->options[0] as $option) { + switch ($option[0]) { + case '--colors': { + $this->arguments['colors'] = true; + } + break; + + case '--bootstrap': { + $this->arguments['bootstrap'] = $option[1]; + } + break; + + case 'c': + case '--configuration': { + $this->arguments['configuration'] = $option[1]; + } + break; + + case '--coverage-clover': { + $this->arguments['coverageClover'] = $option[1]; + } + break; + + case '--coverage-crap4j': { + $this->arguments['coverageCrap4J'] = $option[1]; + } + break; + + case '--coverage-html': { + $this->arguments['coverageHtml'] = $option[1]; + } + break; + + case '--coverage-php': { + $this->arguments['coveragePHP'] = $option[1]; + } + break; + + case '--coverage-text': { + if ($option[1] === null) { + $option[1] = 'php://stdout'; + } + + $this->arguments['coverageText'] = $option[1]; + $this->arguments['coverageTextShowUncoveredFiles'] = false; + $this->arguments['coverageTextShowOnlySummary'] = false; + } + break; + + case '--coverage-xml': { + $this->arguments['coverageXml'] = $option[1]; + } + break; + + case 'd': { + $ini = explode('=', $option[1]); + + if (isset($ini[0])) { + if (isset($ini[1])) { + ini_set($ini[0], $ini[1]); + } else { + ini_set($ini[0], true); + } + } + } + break; + + case '--debug': { + $this->arguments['debug'] = true; + } + break; + + case 'h': + case '--help': { + $this->showHelp(); + exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); + } + break; + + case '--filter': { + $this->arguments['filter'] = $option[1]; + } + break; + + case '--testsuite': { + $this->arguments['testsuite'] = $option[1]; + } + break; + + case '--group': { + $this->arguments['groups'] = explode(',', $option[1]); + } + break; + + case '--exclude-group': { + $this->arguments['excludeGroups'] = explode( + ',', $option[1] + ); + } + break; + + case '--test-suffix': { + $this->arguments['testSuffixes'] = explode( + ',', $option[1] + ); + } + break; + + case '--include-path': { + $includePath = $option[1]; + } + break; + + case '--list-groups': { + $this->arguments['listGroups'] = true; + } + break; + + case '--printer': { + $this->arguments['printer'] = $option[1]; + } + break; + + case '--loader': { + $this->arguments['loader'] = $option[1]; + } + break; + + case '--log-json': { + $this->arguments['jsonLogfile'] = $option[1]; + } + break; + + case '--log-junit': { + $this->arguments['junitLogfile'] = $option[1]; + } + break; + + case '--log-tap': { + $this->arguments['tapLogfile'] = $option[1]; + } + break; + + case '--process-isolation': { + $this->arguments['processIsolation'] = true; + } + break; + + case '--repeat': { + $this->arguments['repeat'] = (int) $option[1]; + } + break; + + case '--stderr': { + $this->arguments['stderr'] = true; + } + break; + + case '--stop-on-error': { + $this->arguments['stopOnError'] = true; + } + break; + + case '--stop-on-failure': { + $this->arguments['stopOnFailure'] = true; + } + break; + + case '--stop-on-incomplete': { + $this->arguments['stopOnIncomplete'] = true; + } + break; + + case '--stop-on-risky': { + $this->arguments['stopOnRisky'] = true; + } + break; + + case '--stop-on-skipped': { + $this->arguments['stopOnSkipped'] = true; + } + break; + + case '--tap': { + $this->arguments['printer'] = new PHPUnit_Util_Log_TAP; + } + break; + + case '--testdox': { + $this->arguments['printer'] = new PHPUnit_Util_TestDox_ResultPrinter_Text; + } + break; + + case '--testdox-html': { + $this->arguments['testdoxHTMLFile'] = $option[1]; + } + break; + + case '--testdox-text': { + $this->arguments['testdoxTextFile'] = $option[1]; + } + break; + + case '--no-configuration': { + $this->arguments['useDefaultConfiguration'] = false; + } + break; + + case '--no-globals-backup': { + $this->arguments['backupGlobals'] = false; + } + break; + + case '--static-backup': { + $this->arguments['backupStaticAttributes'] = true; + } + break; + + case 'v': + case '--verbose': { + $this->arguments['verbose'] = true; + } + break; + + case '--version': { + PHPUnit_TextUI_TestRunner::printVersionString(); + exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); + } + break; + + case '--report-useless-tests': { + $this->arguments['reportUselessTests'] = true; + } + break; + + case '--strict-coverage': { + $this->arguments['strictCoverage'] = true; + } + break; + + case '--disallow-test-output': { + $this->arguments['disallowTestOutput'] = true; + } + break; + + case '--enforce-time-limit': { + $this->arguments['enforceTimeLimit'] = true; + } + break; + + case '--strict': { + $this->arguments['reportUselessTests'] = true; + $this->arguments['strictCoverage'] = true; + $this->arguments['disallowTestOutput'] = true; + $this->arguments['enforceTimeLimit'] = true; + } + break; + + case '--selfupdate': + case '--self-update': { + $this->handleSelfUpdate(); + } + break; + + default: { + $optionName = str_replace('--', '', $option[0]); + + if (isset($this->longOptions[$optionName])) { + $handler = $this->longOptions[$optionName]; + } elseif (isset($this->longOptions[$optionName . '='])) { + $handler = $this->longOptions[$optionName . '=']; + } + + if (isset($handler) && is_callable(array($this, $handler))) { + $this->$handler($option[1]); + } + } + } + } + + $this->handleCustomTestSuite(); + + if (!isset($this->arguments['test'])) { + + if (isset($this->options[1][0])) { + $this->arguments['test'] = $this->options[1][0]; + } + + if (isset($this->options[1][1])) { + $this->arguments['testFile'] = realpath($this->options[1][1]); + } else { + $this->arguments['testFile'] = ''; + } + + if (isset($this->arguments['test']) && + is_file($this->arguments['test']) && + substr($this->arguments['test'], -5, 5) != '.phpt') { + $this->arguments['testFile'] = realpath($this->arguments['test']); + $this->arguments['test'] = substr($this->arguments['test'], 0, strrpos($this->arguments['test'], '.')); + } + } + + if (!isset($this->arguments['testSuffixes'])) { + $this->arguments['testSuffixes'] = array('Test.php', '.phpt'); + } + + if (isset($includePath)) { + ini_set( + 'include_path', + $includePath . PATH_SEPARATOR . ini_get('include_path') + ); + } + + if (isset($this->arguments['bootstrap'])) { + $this->handleBootstrap($this->arguments['bootstrap']); + } + + if (isset($this->arguments['printer']) && + is_string($this->arguments['printer'])) { + $this->arguments['printer'] = $this->handlePrinter($this->arguments['printer']); + } + + if ($this->arguments['loader'] !== null) { + $this->arguments['loader'] = $this->handleLoader($this->arguments['loader']); + } + + if (isset($this->arguments['configuration']) && + is_dir($this->arguments['configuration'])) { + $configurationFile = $this->arguments['configuration'] . + '/phpunit.xml'; + + if (file_exists($configurationFile)) { + $this->arguments['configuration'] = realpath( + $configurationFile + ); + } elseif (file_exists($configurationFile . '.dist')) { + $this->arguments['configuration'] = realpath( + $configurationFile . '.dist' + ); + } + } elseif (!isset($this->arguments['configuration']) && + $this->arguments['useDefaultConfiguration']) { + if (file_exists('phpunit.xml')) { + $this->arguments['configuration'] = realpath('phpunit.xml'); + } elseif (file_exists('phpunit.xml.dist')) { + $this->arguments['configuration'] = realpath( + 'phpunit.xml.dist' + ); + } + } + + if (isset($this->arguments['configuration'])) { + try { + $configuration = PHPUnit_Util_Configuration::getInstance( + $this->arguments['configuration'] + ); + } catch (Exception $e) { + print $e->getMessage() . "\n"; + exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT); + } + + $phpunit = $configuration->getPHPUnitConfiguration(); + + $configuration->handlePHPConfiguration(); + + if (!isset($this->arguments['bootstrap']) && isset($phpunit['bootstrap'])) { + $this->handleBootstrap($phpunit['bootstrap']); + } + + /** + * Issue #657 + */ + if (isset($phpunit['stderr']) && $phpunit['stderr'] == true) { + $this->arguments['printer'] = new PHPUnit_TextUI_ResultPrinter( + 'php://stderr', + isset($this->arguments['verbose']) ? $this->arguments['verbose'] : FALSE + ); + } + + if (isset($phpunit['printerClass'])) { + if (isset($phpunit['printerFile'])) { + $file = $phpunit['printerFile']; + } else { + $file = ''; + } + + $this->arguments['printer'] = $this->handlePrinter( + $phpunit['printerClass'], $file + ); + } + + if (isset($phpunit['testSuiteLoaderClass'])) { + if (isset($phpunit['testSuiteLoaderFile'])) { + $file = $phpunit['testSuiteLoaderFile']; + } else { + $file = ''; + } + + $this->arguments['loader'] = $this->handleLoader( + $phpunit['testSuiteLoaderClass'], $file + ); + } + + $browsers = $configuration->getSeleniumBrowserConfiguration(); + + if (!empty($browsers) && + class_exists('PHPUnit_Extensions_SeleniumTestCase')) { + PHPUnit_Extensions_SeleniumTestCase::$browsers = $browsers; + } + + if (!isset($this->arguments['test'])) { + $testSuite = $configuration->getTestSuiteConfiguration(isset($this->arguments['testsuite']) ? $this->arguments['testsuite'] : null); + + if ($testSuite !== null) { + $this->arguments['test'] = $testSuite; + } + } + } + + if (isset($this->arguments['test']) && is_string($this->arguments['test']) && substr($this->arguments['test'], -5, 5) == '.phpt') { + $test = new PHPUnit_Extensions_PhptTestCase($this->arguments['test']); + + $this->arguments['test'] = new PHPUnit_Framework_TestSuite; + $this->arguments['test']->addTest($test); + } + + if (!isset($this->arguments['test']) || + (isset($this->arguments['testDatabaseLogRevision']) && !isset($this->arguments['testDatabaseDSN']))) { + $this->showHelp(); + exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT); + } + } + + /** + * Handles the loading of the PHPUnit_Runner_TestSuiteLoader implementation. + * + * @param string $loaderClass + * @param string $loaderFile + * @return PHPUnit_Runner_TestSuiteLoader + */ + protected function handleLoader($loaderClass, $loaderFile = '') + { + if (!class_exists($loaderClass, false)) { + if ($loaderFile == '') { + $loaderFile = PHPUnit_Util_Filesystem::classNameToFilename( + $loaderClass + ); + } + + $loaderFile = stream_resolve_include_path($loaderFile); + + if ($loaderFile) { + require $loaderFile; + } + } + + if (class_exists($loaderClass, false)) { + $class = new ReflectionClass($loaderClass); + + if ($class->implementsInterface('PHPUnit_Runner_TestSuiteLoader') && + $class->isInstantiable()) { + $loader = $class->newInstance(); + } + } + + if (!isset($loader)) { + PHPUnit_TextUI_TestRunner::showError( + sprintf( + 'Could not use "%s" as loader.', + + $loaderClass + ) + ); + } + + return $loader; + } + + /** + * Handles the loading of the PHPUnit_Util_Printer implementation. + * + * @param string $printerClass + * @param string $printerFile + * @return PHPUnit_Util_Printer + */ + protected function handlePrinter($printerClass, $printerFile = '') + { + if (!class_exists($printerClass, false)) { + if ($printerFile == '') { + $printerFile = PHPUnit_Util_Filesystem::classNameToFilename( + $printerClass + ); + } + + $printerFile = stream_resolve_include_path($printerFile); + + if ($printerFile) { + require $printerFile; + } + } + + if (class_exists($printerClass)) { + $class = new ReflectionClass($printerClass); + + if ($class->implementsInterface('PHPUnit_Framework_TestListener') && + $class->isSubclassOf('PHPUnit_Util_Printer') && + $class->isInstantiable()) { + if ($class->isSubclassOf('PHPUnit_TextUI_ResultPrinter')) { + return $printerClass; + } + + $printer = $class->newInstance(); + } + } + + if (!isset($printer)) { + PHPUnit_TextUI_TestRunner::showError( + sprintf( + 'Could not use "%s" as printer.', + + $printerClass + ) + ); + } + + return $printer; + } + + /** + * Loads a bootstrap file. + * + * @param string $filename + */ + protected function handleBootstrap($filename) + { + try { + PHPUnit_Util_Fileloader::checkAndLoad($filename); + } catch (PHPUnit_Framework_Exception $e) { + PHPUnit_TextUI_TestRunner::showError($e->getMessage()); + } + } + + /** + * @since Method available since Release 4.0.0 + */ + protected function handleSelfUpdate() + { + PHPUnit_TextUI_TestRunner::printVersionString(); + + if (!extension_loaded('openssl')) { + print "The OpenSSL extension is not loaded.\n"; + exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT); + } + + $remoteFilename = sprintf( + 'https://phar.phpunit.de/phpunit%s.phar', + PHPUnit_Runner_Version::getReleaseChannel() + ); + + $localFilename = realpath($_SERVER['argv'][0]); + $tempFilename = basename($localFilename, '.phar') . '-temp.phar'; + + // Workaround for https://bugs.php.net/bug.php?id=65538 + $caFile = dirname($tempFilename) . '/ca.pem'; + copy(__PHPUNIT_PHAR_ROOT__ . '/ca.pem', $caFile); + + print 'Updating the PHPUnit PHAR ... '; + + $options = array( + 'ssl' => array( + 'allow_self_signed' => false, + 'cafile' => $caFile, + 'verify_peer' => true + ) + ); + + if (PHP_VERSION_ID < 50600) { + $options['ssl']['CN_match'] = 'phar.phpunit.de'; + $options['ssl']['SNI_server_name'] = 'phar.phpunit.de'; + } + + file_put_contents( + $tempFilename, + file_get_contents( + $remoteFilename, + false, + stream_context_create($options) + ) + ); + + chmod($tempFilename, 0777 & ~umask()); + + try { + $phar = new Phar($tempFilename); + unset($phar); + rename($tempFilename, $localFilename); + unlink($caFile); + } catch (Exception $e) { + unlink($caFile); + unlink($tempFilename); + print " done\n\n" . $e->getMessage() . "\n"; + exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT); + } + + print " done\n"; + exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); + } + + /** + * Show the help message. + */ + protected function showHelp() + { + PHPUnit_TextUI_TestRunner::printVersionString(); + + print << + +Code Coverage Options: + + --coverage-clover Generate code coverage report in Clover XML format. + --coverage-crap4j Generate code coverage report in Crap4J XML format. + --coverage-html Generate code coverage report in HTML format. + --coverage-php Export PHP_CodeCoverage object to file. + --coverage-text= Generate code coverage report in text format. + Default: Standard output. + --coverage-xml Generate code coverage report in PHPUnit XML format. + +Logging Options: + + --log-junit Log test execution in JUnit XML format to file. + --log-tap Log test execution in TAP format to file. + --log-json Log test execution in JSON format. + --testdox-html Write agile documentation in HTML format to file. + --testdox-text Write agile documentation in Text format to file. + +Test Selection Options: + + --filter Filter which tests to run. + --testsuite Filter which testsuite to run. + --group ... Only runs tests from the specified group(s). + --exclude-group ... Exclude tests from the specified group(s). + --list-groups List available test groups. + --test-suffix ... Only search for test in files with specified + suffix(es). Default: Test.php,.phpt + +Test Execution Options: + + --report-useless-tests Be strict about tests that do not test anything. + --strict-coverage Be strict about unintentionally covered code. + --disallow-test-output Be strict about output during tests. + --enforce-time-limit Enforce time limit based on test size. + --strict Run tests in strict mode (enables all of the above). + + --process-isolation Run each test in a separate PHP process. + --no-globals-backup Do not backup and restore \$GLOBALS for each test. + --static-backup Backup and restore static attributes for each test. + + --colors Use colors in output. + --stderr Write to STDERR instead of STDOUT. + --stop-on-error Stop execution upon first error. + --stop-on-failure Stop execution upon first error or failure. + --stop-on-risky Stop execution upon first risky test. + --stop-on-skipped Stop execution upon first skipped test. + --stop-on-incomplete Stop execution upon first incomplete test. + -v|--verbose Output more verbose information. + --debug Display debugging information during test execution. + + --loader TestSuiteLoader implementation to use. + --repeat Runs the test(s) repeatedly. + --tap Report test execution progress in TAP format. + --testdox Report test execution progress in TestDox format. + --printer TestSuiteListener implementation to use. + +Configuration Options: + + --bootstrap A "bootstrap" PHP file that is run before the tests. + -c|--configuration Read configuration from XML file. + --no-configuration Ignore default configuration file (phpunit.xml). + --include-path Prepend PHP's include_path with given path(s). + -d key[=value] Sets a php.ini value. + +Miscellaneous Options: + + -h|--help Prints this usage information. + --version Prints the version and exits. + +EOT; + + if (defined('__PHPUNIT_PHAR__')) { + print "\n --self-update Update PHPUnit to the latest version.\n"; + } + } + + /** + * Custom callback for test suite discovery. + */ + protected function handleCustomTestSuite() + { + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage TextUI + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * Prints the result of a TextUI TestRunner run. + * + * @package PHPUnit + * @subpackage TextUI + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_TextUI_ResultPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener +{ + const EVENT_TEST_START = 0; + const EVENT_TEST_END = 1; + const EVENT_TESTSUITE_START = 2; + const EVENT_TESTSUITE_END = 3; + + /** + * @var array + */ + private static $ansiCodes = array( + 'bold' => 1, + 'fg-black' => 30, + 'fg-red' => 31, + 'fg-yellow' => 33, + 'fg-cyan' => 36, + 'fg-white' => 37, + 'bg-red' => 41, + 'bg-green' => 42, + 'bg-yellow' => 43 + ); + + /** + * @var integer + */ + protected $column = 0; + + /** + * @var integer + */ + protected $maxColumn; + + /** + * @var boolean + */ + protected $lastTestFailed = false; + + /** + * @var integer + */ + protected $numAssertions = 0; + + /** + * @var integer + */ + protected $numTests = -1; + + /** + * @var integer + */ + protected $numTestsRun = 0; + + /** + * @var integer + */ + protected $numTestsWidth; + + /** + * @var boolean + */ + protected $colors = false; + + /** + * @var boolean + */ + protected $debug = false; + + /** + * @var boolean + */ + protected $verbose = false; + + /** + * Constructor. + * + * @param mixed $out + * @param boolean $verbose + * @param boolean $colors + * @param boolean $debug + * @throws PHPUnit_Framework_Exception + * @since Method available since Release 3.0.0 + */ + public function __construct($out = null, $verbose = false, $colors = false, $debug = false) + { + parent::__construct($out); + + if (is_bool($verbose)) { + $this->verbose = $verbose; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'boolean'); + } + + if (is_bool($colors)) { + $this->colors = $colors; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(3, 'boolean'); + } + + if (is_bool($debug)) { + $this->debug = $debug; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'boolean'); + } + } + + /** + * @param PHPUnit_Framework_TestResult $result + */ + public function printResult(PHPUnit_Framework_TestResult $result) + { + $this->printHeader(); + + $this->printErrors($result); + $printSeparator = $result->errorCount() > 0; + + if ($printSeparator && $result->failureCount() > 0) { + $this->write("\n--\n\n"); + } + + $printSeparator = $printSeparator || $result->failureCount() > 0; + $this->printFailures($result); + + if ($this->verbose) { + if ($printSeparator && $result->deprecatedFeaturesCount() > 0) { + $this->write("\n--\n\n"); + } + + $printSeparator = $printSeparator || + $result->deprecatedFeaturesCount() > 0; + + $this->printDeprecated($result); + + if ($printSeparator && $result->riskyCount() > 0) { + $this->write("\n--\n\n"); + } + + $printSeparator = $printSeparator || + $result->riskyCount() > 0; + + $this->printRisky($result); + + if ($printSeparator && $result->notImplementedCount() > 0) { + $this->write("\n--\n\n"); + } + + $printSeparator = $printSeparator || + $result->notImplementedCount() > 0; + + $this->printIncompletes($result); + + if ($printSeparator && $result->skippedCount() > 0) { + $this->write("\n--\n\n"); + } + + $this->printSkipped($result); + } + + $this->printFooter($result); + } + + /** + * @param array $defects + * @param string $type + */ + protected function printDefects(array $defects, $type) + { + $count = count($defects); + + if ($count == 0) { + return; + } + + $this->write( + sprintf( + "There %s %d %s%s:\n", + + ($count == 1) ? 'was' : 'were', + $count, + $type, + ($count == 1) ? '' : 's' + ) + ); + + $i = 1; + + foreach ($defects as $defect) { + $this->printDefect($defect, $i++); + } + } + + /** + * @param PHPUnit_Framework_TestFailure $defect + * @param integer $count + */ + protected function printDefect(PHPUnit_Framework_TestFailure $defect, $count) + { + $this->printDefectHeader($defect, $count); + $this->printDefectTrace($defect); + } + + /** + * @param PHPUnit_Framework_TestFailure $defect + * @param integer $count + */ + protected function printDefectHeader(PHPUnit_Framework_TestFailure $defect, $count) + { + $failedTest = $defect->failedTest(); + + if ($failedTest instanceof PHPUnit_Framework_SelfDescribing) { + $testName = $failedTest->toString(); + } else { + $testName = get_class($failedTest); + } + + $this->write( + sprintf( + "\n%d) %s\n", + + $count, + $testName + ) + ); + } + + /** + * @param PHPUnit_Framework_TestFailure $defect + */ + protected function printDefectTrace(PHPUnit_Framework_TestFailure $defect) + { + $this->write($defect->getExceptionAsString()); + + $trace = PHPUnit_Util_Filter::getFilteredStacktrace( + $defect->thrownException() + ); + + if (!empty($trace)) { + $this->write("\n" . $trace); + } + + $e = $defect->thrownException()->getPrevious(); + + while ($e) { + $this->write( + "\nCaused by\n" . + PHPUnit_Framework_TestFailure::exceptionToString($e). "\n" . + PHPUnit_Util_Filter::getFilteredStacktrace($e) + ); + + $e = $e->getPrevious(); + } + } + + /** + * @param PHPUnit_Framework_TestResult $result + */ + protected function printErrors(PHPUnit_Framework_TestResult $result) + { + $this->printDefects($result->errors(), 'error'); + } + + /** + * @param PHPUnit_Framework_TestResult $result + */ + protected function printFailures(PHPUnit_Framework_TestResult $result) + { + $this->printDefects($result->failures(), 'failure'); + } + + /** + * @param PHPUnit_Framework_TestResult $result + */ + protected function printIncompletes(PHPUnit_Framework_TestResult $result) + { + $this->printDefects($result->notImplemented(), 'incomplete test'); + } + + /** + * @param PHPUnit_Framework_TestResult $result + * @since Method available since Release 4.0.0 + */ + protected function printRisky(PHPUnit_Framework_TestResult $result) + { + $this->printDefects($result->risky(), 'risky test'); + } + + /** + * @param PHPUnit_Framework_TestResult $result + * @since Method available since Release 3.0.0 + */ + protected function printSkipped(PHPUnit_Framework_TestResult $result) + { + $this->printDefects($result->skipped(), 'skipped test'); + } + + /** + * @param PHPUnit_Framework_TestResult $result + * @since Method available since Release 4.0.0 + */ + protected function printDeprecated(PHPUnit_Framework_TestResult $result) + { + $deprecatedFeatures = $result->deprecatedFeatures(); + $count = count($deprecatedFeatures); + + if ($count == 0) { + return; + } + + $this->write( + sprintf( + "There %s %d tests that use%s deprecated features:\n", + + ($count == 1) ? 'was' : 'were', + $count, + ($count != 1) ? '' : 's' + ) + ); + + $i = 1; + + foreach ($result->deprecatedFeatures() as $deprecatedFeature) { + $this->write( + sprintf( + "\n%d) %s\n\n%s\n", + + $i++, + $deprecatedFeature->getMessage(), + $deprecatedFeature->getSource() + ) + ); + } + } + + protected function printHeader() + { + $this->write("\n\n" . PHP_Timer::resourceUsage() . "\n\n"); + } + + /** + * @param PHPUnit_Framework_TestResult $result + */ + protected function printFooter(PHPUnit_Framework_TestResult $result) + { + if (count($result) === 0) { + $this->writeWithColor( + 'fg-black, bg-yellow', + 'No tests executed!' + ); + } elseif ($result->wasSuccessful() && + $result->allHarmless() && + $result->allCompletelyImplemented() && + $result->noneSkipped()) { + + $this->writeWithColor( + 'fg-black, bg-green', + sprintf( + 'OK (%d test%s, %d assertion%s)', + + count($result), + (count($result) == 1) ? '' : 's', + $this->numAssertions, + ($this->numAssertions == 1) ? '' : 's' + ) + ); + } elseif ((!$result->allCompletelyImplemented() || + !$result->allHarmless() || + !$result->noneSkipped()) && + $result->wasSuccessful()) { + $this->writeWithColor( + 'fg-black, bg-yellow', + sprintf( + "%sOK, but incomplete, skipped, or risky tests!\n" . + 'Tests: %d, Assertions: %d%s%s%s.', + + $this->verbose ? "\n" : '', + count($result), + $this->numAssertions, + $this->getCountString( + $result->notImplementedCount(), 'Incomplete' + ), + $this->getCountString( + $result->skippedCount(), 'Skipped' + ), + $this->getCountString( + $result->riskyCount(), 'Risky' + ) + ) + ); + } else { + $this->writeWithColor( + 'fg-white, bg-red', + sprintf( + "\nFAILURES!\n" . + 'Tests: %d, Assertions: %s%s%s%s%s.', + + count($result), + $this->numAssertions, + $this->getCountString($result->failureCount(), 'Failures'), + $this->getCountString($result->errorCount(), 'Errors'), + $this->getCountString( + $result->notImplementedCount(), 'Incomplete' + ), + $this->getCountString($result->skippedCount(), 'Skipped') + ) + ); + } + + if (!$this->verbose && + $result->deprecatedFeaturesCount() > 0) { + $this->write("\n"); + + $this->writeWithColor( + 'fg-white, bg-red', + sprintf( + "Warning: Deprecated PHPUnit features are being used %s times!\n" . + 'Use --verbose for more information.', + + $result->deprecatedFeaturesCount() + ) + ); + } + } + + /** + * @param integer $count + * @param string $name + * @return string + * @since Method available since Release 3.0.0 + */ + protected function getCountString($count, $name) + { + $string = ''; + + if ($count > 0) { + $string = sprintf( + ', %s: %d', + + $name, + $count + ); + } + + return $string; + } + + /** + */ + public function printWaitPrompt() + { + $this->write("\n to continue\n"); + } + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeProgressWithColor('fg-red, bold', 'E'); + $this->lastTestFailed = true; + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + $this->writeProgressWithColor('bg-red, fg-white', 'F'); + $this->lastTestFailed = true; + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeProgressWithColor('fg-yellow, bold', 'I'); + $this->lastTestFailed = true; + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeProgressWithColor('fg-yellow, bold', 'R'); + $this->lastTestFailed = true; + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + $this->writeProgressWithColor('fg-cyan, bold', 'S'); + $this->lastTestFailed = true; + } + + /** + * A testsuite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + if ($this->numTests == -1) { + $this->numTests = count($suite); + $this->numTestsWidth = strlen((string) $this->numTests); + $this->maxColumn = 69 - (2 * $this->numTestsWidth); + } + } + + /** + * A testsuite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + if ($this->debug) { + $this->write( + sprintf( + "\nStarting test '%s'.\n", PHPUnit_Util_Test::describe($test) + ) + ); + } + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + if (!$this->lastTestFailed) { + $this->writeProgress('.'); + } + + if ($test instanceof PHPUnit_Framework_TestCase) { + $this->numAssertions += $test->getNumAssertions(); + } elseif ($test instanceof PHPUnit_Extensions_PhptTestCase) { + $this->numAssertions++; + } + + $this->lastTestFailed = false; + + if ($test instanceof PHPUnit_Framework_TestCase) { + if (!$test->hasPerformedExpectationsOnOutput()) { + $this->write($test->getActualOutput()); + } + } + } + + /** + * @param string $progress + */ + protected function writeProgress($progress) + { + $this->write($progress); + $this->column++; + $this->numTestsRun++; + + if ($this->column == $this->maxColumn) { + $this->write( + sprintf( + ' %' . $this->numTestsWidth . 'd / %' . + $this->numTestsWidth . 'd (%3s%%)', + + $this->numTestsRun, + $this->numTests, + floor(($this->numTestsRun / $this->numTests) * 100) + ) + ); + + $this->writeNewLine(); + } + } + + protected function writeNewLine() + { + $this->column = 0; + $this->write("\n"); + } + + /** + * Formats a buffer with a specified ANSI color sequence if colors are + * enabled. + * + * @param string $color + * @param string $buffer + * @return string + * @since Method available since Release 4.0.0 + */ + protected function formatWithColor($color, $buffer) + { + if (!$this->colors) { + return $buffer; + } + + $codes = array_map('trim', explode(',', $color)); + $lines = explode("\n", $buffer); + $padding = max(array_map('strlen', $lines)); + + $styles = array(); + foreach ($codes as $code) { + $styles[] = self::$ansiCodes[$code]; + } + $style = sprintf("\x1b[%sm", implode(';', $styles)); + + $styledLines = array(); + foreach ($lines as $line) { + $styledLines[] = $style . str_pad($line, $padding) . "\x1b[0m"; + } + + return implode("\n", $styledLines); + } + + /** + * Writes a buffer out with a color sequence if colors are enabled. + * + * @param string $color + * @param string $buffer + * @since Method available since Release 4.0.0 + */ + protected function writeWithColor($color, $buffer) + { + $buffer = $this->formatWithColor($color, $buffer); + $this->write($buffer . "\n"); + } + + /** + * Writes progress with a color sequence if colors are enabled. + * + * @param string $color + * @param string $buffer + * @since Method available since Release 4.0.0 + */ + protected function writeProgressWithColor($color, $buffer) + { + $buffer = $this->formatWithColor($color, $buffer); + $this->writeProgress($buffer); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage TextUI + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +use SebastianBergmann\Environment\Runtime; + +/** + * A TestRunner for the Command Line Interface (CLI) + * PHP SAPI Module. + * + * @package PHPUnit + * @subpackage TextUI + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_TextUI_TestRunner extends PHPUnit_Runner_BaseTestRunner +{ + const SUCCESS_EXIT = 0; + const FAILURE_EXIT = 1; + const EXCEPTION_EXIT = 2; + + /** + * @var PHP_CodeCoverage_Filter + */ + protected $codeCoverageFilter; + + /** + * @var PHPUnit_Runner_TestSuiteLoader + */ + protected $loader = null; + + /** + * @var PHPUnit_TextUI_ResultPrinter + */ + protected $printer = null; + + /** + * @var boolean + */ + protected static $versionStringPrinted = false; + + /** + * @var array + */ + private $missingExtensions = array(); + + /** + * @var boolean + */ + private $canCollectCodeCoverage; + + /** + * @param PHPUnit_Runner_TestSuiteLoader $loader + * @param PHP_CodeCoverage_Filter $filter + * @since Method available since Release 3.4.0 + */ + public function __construct(PHPUnit_Runner_TestSuiteLoader $loader = null, PHP_CodeCoverage_Filter $filter = null) + { + if ($filter === null) { + $filter = new PHP_CodeCoverage_Filter; + } + + $this->codeCoverageFilter = $filter; + $this->loader = $loader; + + $runtime = new Runtime; + $this->canCollectCodeCoverage = $runtime->canCollectCodeCoverage(); + } + + /** + * @param PHPUnit_Framework_Test|ReflectionClass $test + * @param array $arguments + * @return PHPUnit_Framework_TestResult + * @throws PHPUnit_Framework_Exception + */ + public static function run($test, array $arguments = array()) + { + if ($test instanceof ReflectionClass) { + $test = new PHPUnit_Framework_TestSuite($test); + } + + if ($test instanceof PHPUnit_Framework_Test) { + $aTestRunner = new PHPUnit_TextUI_TestRunner; + + return $aTestRunner->doRun( + $test, + $arguments + ); + } else { + throw new PHPUnit_Framework_Exception( + 'No test case or test suite found.' + ); + } + } + + /** + * @return PHPUnit_Framework_TestResult + */ + protected function createTestResult() + { + return new PHPUnit_Framework_TestResult; + } + + private function processSuiteFilters(PHPUnit_Framework_TestSuite $suite, array $arguments) + { + if (!$arguments['filter'] && + empty($arguments['groups']) && + empty($arguments['excludeGroups'])) { + return; + } + + $filterFactory = new PHPUnit_Runner_Filter_Factory(); + + if (!empty($arguments['excludeGroups'])) { + $filterFactory->addFilter( + new ReflectionClass('PHPUnit_Runner_Filter_Group_Exclude'), + $arguments['excludeGroups'] + ); + } + + if (!empty($arguments['groups'])) { + $filterFactory->addFilter( + new ReflectionClass('PHPUnit_Runner_Filter_Group_Include'), + $arguments['groups'] + ); + } + + if ($arguments['filter']) { + $filterFactory->addFilter( + new ReflectionClass('PHPUnit_Runner_Filter_Test'), + $arguments['filter'] + ); + } + $suite->injectFilter($filterFactory); + } + + /** + * @param PHPUnit_Framework_Test $suite + * @param array $arguments + * @return PHPUnit_Framework_TestResult + */ + public function doRun(PHPUnit_Framework_Test $suite, array $arguments = array()) + { + $this->handleConfiguration($arguments); + + $this->processSuiteFilters($suite, $arguments); + + if (isset($arguments['bootstrap'])) { + $GLOBALS['__PHPUNIT_BOOTSTRAP'] = $arguments['bootstrap']; + } + + if ($arguments['backupGlobals'] === false) { + $suite->setBackupGlobals(false); + } + + if ($arguments['backupStaticAttributes'] === true) { + $suite->setBackupStaticAttributes(true); + } + + if (is_integer($arguments['repeat'])) { + $test = new PHPUnit_Extensions_RepeatedTest( + $suite, + $arguments['repeat'], + $arguments['processIsolation'] + ); + + $suite = new PHPUnit_Framework_TestSuite(); + $suite->addTest($test); + } + + $result = $this->createTestResult(); + + if (!$arguments['convertErrorsToExceptions']) { + $result->convertErrorsToExceptions(false); + } + + if (!$arguments['convertNoticesToExceptions']) { + PHPUnit_Framework_Error_Notice::$enabled = false; + } + + if (!$arguments['convertWarningsToExceptions']) { + PHPUnit_Framework_Error_Warning::$enabled = false; + } + + if ($arguments['stopOnError']) { + $result->stopOnError(true); + } + + if ($arguments['stopOnFailure']) { + $result->stopOnFailure(true); + } + + if ($arguments['stopOnIncomplete']) { + $result->stopOnIncomplete(true); + } + + if ($arguments['stopOnRisky']) { + $result->stopOnRisky(true); + } + + if ($arguments['stopOnSkipped']) { + $result->stopOnSkipped(true); + } + + if ($this->printer === null) { + if (isset($arguments['printer']) && + $arguments['printer'] instanceof PHPUnit_Util_Printer) { + $this->printer = $arguments['printer']; + } else { + $printerClass = 'PHPUnit_TextUI_ResultPrinter'; + if (isset($arguments['printer']) && + is_string($arguments['printer']) && + class_exists($arguments['printer'], false)) { + $class = new ReflectionClass($arguments['printer']); + + if ($class->isSubclassOf('PHPUnit_TextUI_ResultPrinter')) { + $printerClass = $arguments['printer']; + } + } + + $this->printer = new $printerClass( + isset($arguments['stderr']) ? 'php://stderr' : null, + $arguments['verbose'], + $arguments['colors'], + $arguments['debug'] + ); + } + } + + if (!$this->printer instanceof PHPUnit_Util_Log_TAP) { + $this->printer->write( + PHPUnit_Runner_Version::getVersionString() . "\n\n" + ); + + self::$versionStringPrinted = true; + + if (isset($arguments['configuration'])) { + $this->printer->write( + sprintf( + "Configuration read from %s\n\n", + $arguments['configuration']->getFilename() + ) + ); + } + } + + foreach ($arguments['listeners'] as $listener) { + $result->addListener($listener); + } + + $result->addListener($this->printer); + + if ($this->printer instanceof PHPUnit_TextUI_ResultPrinter) { + $result->addListener(new PHPUnit_Util_DeprecatedFeature_Logger); + } + + if (isset($arguments['testdoxHTMLFile'])) { + $result->addListener( + new PHPUnit_Util_TestDox_ResultPrinter_HTML( + $arguments['testdoxHTMLFile'] + ) + ); + } + + if (isset($arguments['testdoxTextFile'])) { + $result->addListener( + new PHPUnit_Util_TestDox_ResultPrinter_Text( + $arguments['testdoxTextFile'] + ) + ); + } + + $codeCoverageReports = 0; + + if (isset($arguments['coverageClover'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageCrap4J'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageHtml'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coveragePHP'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageText'])) { + $codeCoverageReports++; + } + + if (isset($arguments['coverageXml'])) { + $codeCoverageReports++; + } + + if ($codeCoverageReports > 0 && (!extension_loaded('tokenizer') || !$this->canCollectCodeCoverage)) { + if (!extension_loaded('tokenizer')) { + $this->showExtensionNotLoadedMessage( + 'tokenizer', 'No code coverage will be generated.' + ); + } elseif (!extension_loaded('Xdebug')) { + $this->showExtensionNotLoadedMessage( + 'Xdebug', 'No code coverage will be generated.' + ); + } + + $codeCoverageReports = 0; + } + + if ($codeCoverageReports > 0) { + $codeCoverage = new PHP_CodeCoverage( + null, $this->codeCoverageFilter + ); + + $codeCoverage->setAddUncoveredFilesFromWhitelist( + $arguments['addUncoveredFilesFromWhitelist'] + ); + + $codeCoverage->setCheckForUnintentionallyCoveredCode( + $arguments['strictCoverage'] + ); + + $codeCoverage->setProcessUncoveredFilesFromWhitelist( + $arguments['processUncoveredFilesFromWhitelist'] + ); + + if (isset($arguments['forceCoversAnnotation'])) { + $codeCoverage->setForceCoversAnnotation( + $arguments['forceCoversAnnotation'] + ); + } + + if (isset($arguments['mapTestClassNameToCoveredClassName'])) { + $codeCoverage->setMapTestClassNameToCoveredClassName( + $arguments['mapTestClassNameToCoveredClassName'] + ); + } + + $result->setCodeCoverage($codeCoverage); + } + + if ($codeCoverageReports > 1) { + if (isset($arguments['cacheTokens'])) { + $codeCoverage->setCacheTokens($arguments['cacheTokens']); + } + } + + if (isset($arguments['jsonLogfile'])) { + $result->addListener( + new PHPUnit_Util_Log_JSON($arguments['jsonLogfile']) + ); + } + + if (isset($arguments['tapLogfile'])) { + $result->addListener( + new PHPUnit_Util_Log_TAP($arguments['tapLogfile']) + ); + } + + if (isset($arguments['junitLogfile'])) { + $result->addListener( + new PHPUnit_Util_Log_JUnit( + $arguments['junitLogfile'], $arguments['logIncompleteSkipped'] + ) + ); + } + + $result->beStrictAboutTestsThatDoNotTestAnything($arguments['reportUselessTests']); + $result->beStrictAboutOutputDuringTests($arguments['disallowTestOutput']); + $result->beStrictAboutTestSize($arguments['enforceTimeLimit']); + $result->setTimeoutForSmallTests($arguments['timeoutForSmallTests']); + $result->setTimeoutForMediumTests($arguments['timeoutForMediumTests']); + $result->setTimeoutForLargeTests($arguments['timeoutForLargeTests']); + + if ($suite instanceof PHPUnit_Framework_TestSuite) { + $suite->setRunTestInSeparateProcess($arguments['processIsolation']); + } + + $suite->run($result); + + unset($suite); + $result->flushListeners(); + + if ($this->printer instanceof PHPUnit_TextUI_ResultPrinter) { + $this->printer->printResult($result); + } + + if (isset($codeCoverage)) { + if (isset($arguments['coverageClover'])) { + $this->printer->write( + "\nGenerating code coverage report in Clover XML format ..." + ); + + $writer = new PHP_CodeCoverage_Report_Clover; + $writer->process($codeCoverage, $arguments['coverageClover']); + + $this->printer->write(" done\n"); + unset($writer); + } + + if (isset($arguments['coverageCrap4J'])) { + $this->printer->write( + "\nGenerating Crap4J report XML file ..." + ); + + $writer = new PHP_CodeCoverage_Report_Crap4j; + $writer->process($codeCoverage, $arguments['coverageCrap4J']); + + $this->printer->write(" done\n"); + unset($writer); + } + + if (isset($arguments['coverageHtml'])) { + $this->printer->write( + "\nGenerating code coverage report in HTML format ..." + ); + + $writer = new PHP_CodeCoverage_Report_HTML( + $arguments['reportLowUpperBound'], + $arguments['reportHighLowerBound'], + sprintf( + ' and PHPUnit %s', + PHPUnit_Runner_Version::id() + ) + ); + + $writer->process($codeCoverage, $arguments['coverageHtml']); + + $this->printer->write(" done\n"); + unset($writer); + } + + if (isset($arguments['coveragePHP'])) { + $this->printer->write( + "\nGenerating code coverage report in PHP format ..." + ); + + $writer = new PHP_CodeCoverage_Report_PHP; + $writer->process($codeCoverage, $arguments['coveragePHP']); + + $this->printer->write(" done\n"); + unset($writer); + } + + if (isset($arguments['coverageText'])) { + if ($arguments['coverageText'] == 'php://stdout') { + $outputStream = $this->printer; + $colors = (bool) $arguments['colors']; + } else { + $outputStream = new PHPUnit_Util_Printer($arguments['coverageText']); + $colors = false; + } + + $processor = new PHP_CodeCoverage_Report_Text( + $arguments['reportLowUpperBound'], + $arguments['reportHighLowerBound'], + $arguments['coverageTextShowUncoveredFiles'], + $arguments['coverageTextShowOnlySummary'] + ); + + $outputStream->write( + $processor->process($codeCoverage, $colors) + ); + } + + if (isset($arguments['coverageXml'])) { + $this->printer->write( + "\nGenerating code coverage report in PHPUnit XML format ..." + ); + + $writer = new PHP_CodeCoverage_Report_XML; + $writer->process($codeCoverage, $arguments['coverageXml']); + + $this->printer->write(" done\n"); + unset($writer); + } + } + + return $result; + } + + /** + * @param PHPUnit_TextUI_ResultPrinter $resultPrinter + */ + public function setPrinter(PHPUnit_TextUI_ResultPrinter $resultPrinter) + { + $this->printer = $resultPrinter; + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + * + * @param string $message + */ + protected function runFailed($message) + { + self::printVersionString(); + self::write($message . PHP_EOL); + exit(self::FAILURE_EXIT); + } + + /** + * @param string $buffer + * @since Method available since Release 3.1.0 + */ + protected static function write($buffer) + { + if (PHP_SAPI != 'cli') { + $buffer = htmlspecialchars($buffer); + } + + print $buffer; + } + + /** + * Returns the loader to be used. + * + * @return PHPUnit_Runner_TestSuiteLoader + * @since Method available since Release 2.2.0 + */ + public function getLoader() + { + if ($this->loader === null) { + $this->loader = new PHPUnit_Runner_StandardTestSuiteLoader; + } + + return $this->loader; + } + + /** + */ + public static function showError($message) + { + self::printVersionString(); + self::write($message . "\n"); + + exit(self::FAILURE_EXIT); + } + + /** + */ + public static function printVersionString() + { + if (!self::$versionStringPrinted) { + self::write(PHPUnit_Runner_Version::getVersionString() . "\n\n"); + self::$versionStringPrinted = true; + } + } + + /** + * @param array $arguments + * @since Method available since Release 3.2.1 + */ + protected function handleConfiguration(array &$arguments) + { + if (isset($arguments['configuration']) && + !$arguments['configuration'] instanceof PHPUnit_Util_Configuration) { + $arguments['configuration'] = PHPUnit_Util_Configuration::getInstance( + $arguments['configuration'] + ); + } + + $arguments['debug'] = isset($arguments['debug']) ? $arguments['debug'] : false; + $arguments['filter'] = isset($arguments['filter']) ? $arguments['filter'] : false; + $arguments['listeners'] = isset($arguments['listeners']) ? $arguments['listeners'] : array(); + + if (isset($arguments['configuration'])) { + $arguments['configuration']->handlePHPConfiguration(); + + $phpunitConfiguration = $arguments['configuration']->getPHPUnitConfiguration(); + + if (isset($phpunitConfiguration['backupGlobals']) && + !isset($arguments['backupGlobals'])) { + $arguments['backupGlobals'] = $phpunitConfiguration['backupGlobals']; + } + + if (isset($phpunitConfiguration['backupStaticAttributes']) && + !isset($arguments['backupStaticAttributes'])) { + $arguments['backupStaticAttributes'] = $phpunitConfiguration['backupStaticAttributes']; + } + + if (isset($phpunitConfiguration['bootstrap']) && + !isset($arguments['bootstrap'])) { + $arguments['bootstrap'] = $phpunitConfiguration['bootstrap']; + } + + if (isset($phpunitConfiguration['cacheTokens']) && + !isset($arguments['cacheTokens'])) { + $arguments['cacheTokens'] = $phpunitConfiguration['cacheTokens']; + } + + if (isset($phpunitConfiguration['colors']) && + !isset($arguments['colors'])) { + $arguments['colors'] = $phpunitConfiguration['colors']; + } + + if (isset($phpunitConfiguration['convertErrorsToExceptions']) && + !isset($arguments['convertErrorsToExceptions'])) { + $arguments['convertErrorsToExceptions'] = $phpunitConfiguration['convertErrorsToExceptions']; + } + + if (isset($phpunitConfiguration['convertNoticesToExceptions']) && + !isset($arguments['convertNoticesToExceptions'])) { + $arguments['convertNoticesToExceptions'] = $phpunitConfiguration['convertNoticesToExceptions']; + } + + if (isset($phpunitConfiguration['convertWarningsToExceptions']) && + !isset($arguments['convertWarningsToExceptions'])) { + $arguments['convertWarningsToExceptions'] = $phpunitConfiguration['convertWarningsToExceptions']; + } + + if (isset($phpunitConfiguration['processIsolation']) && + !isset($arguments['processIsolation'])) { + $arguments['processIsolation'] = $phpunitConfiguration['processIsolation']; + } + + if (isset($phpunitConfiguration['stopOnFailure']) && + !isset($arguments['stopOnFailure'])) { + $arguments['stopOnFailure'] = $phpunitConfiguration['stopOnFailure']; + } + + if (isset($phpunitConfiguration['timeoutForSmallTests']) && + !isset($arguments['timeoutForSmallTests'])) { + $arguments['timeoutForSmallTests'] = $phpunitConfiguration['timeoutForSmallTests']; + } + + if (isset($phpunitConfiguration['timeoutForMediumTests']) && + !isset($arguments['timeoutForMediumTests'])) { + $arguments['timeoutForMediumTests'] = $phpunitConfiguration['timeoutForMediumTests']; + } + + if (isset($phpunitConfiguration['timeoutForLargeTests']) && + !isset($arguments['timeoutForLargeTests'])) { + $arguments['timeoutForLargeTests'] = $phpunitConfiguration['timeoutForLargeTests']; + } + + if (isset($phpunitConfiguration['reportUselessTests']) && + !isset($arguments['reportUselessTests'])) { + $arguments['reportUselessTests'] = $phpunitConfiguration['reportUselessTests']; + } + + if (isset($phpunitConfiguration['strictCoverage']) && + !isset($arguments['strictCoverage'])) { + $arguments['strictCoverage'] = $phpunitConfiguration['strictCoverage']; + } + + if (isset($phpunitConfiguration['disallowTestOutput']) && + !isset($arguments['disallowTestOutput'])) { + $arguments['disallowTestOutput'] = $phpunitConfiguration['disallowTestOutput']; + } + + if (isset($phpunitConfiguration['enforceTimeLimit']) && + !isset($arguments['enforceTimeLimit'])) { + $arguments['enforceTimeLimit'] = $phpunitConfiguration['enforceTimeLimit']; + } + + if (isset($phpunitConfiguration['verbose']) && + !isset($arguments['verbose'])) { + $arguments['verbose'] = $phpunitConfiguration['verbose']; + } + + if (isset($phpunitConfiguration['forceCoversAnnotation']) && + !isset($arguments['forceCoversAnnotation'])) { + $arguments['forceCoversAnnotation'] = $phpunitConfiguration['forceCoversAnnotation']; + } + + if (isset($phpunitConfiguration['mapTestClassNameToCoveredClassName']) && + !isset($arguments['mapTestClassNameToCoveredClassName'])) { + $arguments['mapTestClassNameToCoveredClassName'] = $phpunitConfiguration['mapTestClassNameToCoveredClassName']; + } + + $groupCliArgs = array(); + if (!empty($arguments['groups'])) { + $groupCliArgs = $arguments['groups']; + } + + $groupConfiguration = $arguments['configuration']->getGroupConfiguration(); + + if (!empty($groupConfiguration['include']) && + !isset($arguments['groups'])) { + $arguments['groups'] = $groupConfiguration['include']; + } + + if (!empty($groupConfiguration['exclude']) && + !isset($arguments['excludeGroups'])) { + $arguments['excludeGroups'] = array_diff($groupConfiguration['exclude'], $groupCliArgs); + } + + foreach ($arguments['configuration']->getListenerConfiguration() as $listener) { + if (!class_exists($listener['class'], false) && + $listener['file'] !== '') { + require_once $listener['file']; + } + + if (class_exists($listener['class'])) { + if (count($listener['arguments']) == 0) { + $listener = new $listener['class']; + } else { + $listenerClass = new ReflectionClass( + $listener['class'] + ); + $listener = $listenerClass->newInstanceArgs( + $listener['arguments'] + ); + } + + if ($listener instanceof PHPUnit_Framework_TestListener) { + $arguments['listeners'][] = $listener; + } + } + } + + $loggingConfiguration = $arguments['configuration']->getLoggingConfiguration(); + + if (isset($loggingConfiguration['coverage-clover']) && + !isset($arguments['coverageClover'])) { + $arguments['coverageClover'] = $loggingConfiguration['coverage-clover']; + } + + if (isset($loggingConfiguration['coverage-crap4j']) && + !isset($arguments['coverageCrap4J'])) { + $arguments['coverageCrap4J'] = $loggingConfiguration['coverage-crap4j']; + } + + if (isset($loggingConfiguration['coverage-html']) && + !isset($arguments['coverageHtml'])) { + if (isset($loggingConfiguration['lowUpperBound']) && + !isset($arguments['reportLowUpperBound'])) { + $arguments['reportLowUpperBound'] = $loggingConfiguration['lowUpperBound']; + } + + if (isset($loggingConfiguration['highLowerBound']) && + !isset($arguments['reportHighLowerBound'])) { + $arguments['reportHighLowerBound'] = $loggingConfiguration['highLowerBound']; + } + + $arguments['coverageHtml'] = $loggingConfiguration['coverage-html']; + } + + if (isset($loggingConfiguration['coverage-php']) && + !isset($arguments['coveragePHP'])) { + $arguments['coveragePHP'] = $loggingConfiguration['coverage-php']; + } + + if (isset($loggingConfiguration['coverage-text']) && + !isset($arguments['coverageText'])) { + $arguments['coverageText'] = $loggingConfiguration['coverage-text']; + if (isset($loggingConfiguration['coverageTextShowUncoveredFiles'])) { + $arguments['coverageTextShowUncoveredFiles'] = $loggingConfiguration['coverageTextShowUncoveredFiles']; + } else { + $arguments['coverageTextShowUncoveredFiles'] = false; + } + if (isset($loggingConfiguration['coverageTextShowOnlySummary'])) { + $arguments['coverageTextShowOnlySummary'] = $loggingConfiguration['coverageTextShowOnlySummary']; + } else { + $arguments['coverageTextShowOnlySummary'] = false; + } + } + + if (isset($loggingConfiguration['coverage-xml']) && + !isset($arguments['coverageXml'])) { + $arguments['coverageXml'] = $loggingConfiguration['coverage-xml']; + } + + if (isset($loggingConfiguration['json']) && + !isset($arguments['jsonLogfile'])) { + $arguments['jsonLogfile'] = $loggingConfiguration['json']; + } + + if (isset($loggingConfiguration['plain'])) { + $arguments['listeners'][] = new PHPUnit_TextUI_ResultPrinter( + $loggingConfiguration['plain'], true + ); + } + + if (isset($loggingConfiguration['tap']) && + !isset($arguments['tapLogfile'])) { + $arguments['tapLogfile'] = $loggingConfiguration['tap']; + } + + if (isset($loggingConfiguration['junit']) && + !isset($arguments['junitLogfile'])) { + $arguments['junitLogfile'] = $loggingConfiguration['junit']; + + if (isset($loggingConfiguration['logIncompleteSkipped']) && + !isset($arguments['logIncompleteSkipped'])) { + $arguments['logIncompleteSkipped'] = $loggingConfiguration['logIncompleteSkipped']; + } + } + + if (isset($loggingConfiguration['testdox-html']) && + !isset($arguments['testdoxHTMLFile'])) { + $arguments['testdoxHTMLFile'] = $loggingConfiguration['testdox-html']; + } + + if (isset($loggingConfiguration['testdox-text']) && + !isset($arguments['testdoxTextFile'])) { + $arguments['testdoxTextFile'] = $loggingConfiguration['testdox-text']; + } + + if ((isset($arguments['coverageClover']) || + isset($arguments['coverageCrap4J']) || + isset($arguments['coverageHtml']) || + isset($arguments['coveragePHP'])) || + isset($arguments['coverageText']) && + $this->canCollectCodeCoverage) { + + $filterConfiguration = $arguments['configuration']->getFilterConfiguration(); + $arguments['addUncoveredFilesFromWhitelist'] = $filterConfiguration['whitelist']['addUncoveredFilesFromWhitelist']; + $arguments['processUncoveredFilesFromWhitelist'] = $filterConfiguration['whitelist']['processUncoveredFilesFromWhitelist']; + + if (empty($filterConfiguration['whitelist']['include']['directory']) && + empty($filterConfiguration['whitelist']['include']['file'])) { + if (defined('__PHPUNIT_PHAR__')) { + $this->codeCoverageFilter->addFileToBlacklist(__PHPUNIT_PHAR__); + } + + $blacklist = new PHPUnit_Util_Blacklist; + + foreach ($blacklist->getBlacklistedDirectories() as $directory) { + $this->codeCoverageFilter->addDirectoryToBlacklist($directory); + } + + foreach ($filterConfiguration['blacklist']['include']['directory'] as $dir) { + $this->codeCoverageFilter->addDirectoryToBlacklist( + $dir['path'], $dir['suffix'], $dir['prefix'], $dir['group'] + ); + } + + foreach ($filterConfiguration['blacklist']['include']['file'] as $file) { + $this->codeCoverageFilter->addFileToBlacklist($file); + } + + foreach ($filterConfiguration['blacklist']['exclude']['directory'] as $dir) { + $this->codeCoverageFilter->removeDirectoryFromBlacklist( + $dir['path'], $dir['suffix'], $dir['prefix'], $dir['group'] + ); + } + + foreach ($filterConfiguration['blacklist']['exclude']['file'] as $file) { + $this->codeCoverageFilter->removeFileFromBlacklist($file); + } + } + + foreach ($filterConfiguration['whitelist']['include']['directory'] as $dir) { + $this->codeCoverageFilter->addDirectoryToWhitelist( + $dir['path'], $dir['suffix'], $dir['prefix'] + ); + } + + foreach ($filterConfiguration['whitelist']['include']['file'] as $file) { + $this->codeCoverageFilter->addFileToWhitelist($file); + } + + foreach ($filterConfiguration['whitelist']['exclude']['directory'] as $dir) { + $this->codeCoverageFilter->removeDirectoryFromWhitelist( + $dir['path'], $dir['suffix'], $dir['prefix'] + ); + } + + foreach ($filterConfiguration['whitelist']['exclude']['file'] as $file) { + $this->codeCoverageFilter->removeFileFromWhitelist($file); + } + } + } + + $arguments['addUncoveredFilesFromWhitelist'] = isset($arguments['addUncoveredFilesFromWhitelist']) ? $arguments['addUncoveredFilesFromWhitelist'] : true; + $arguments['processUncoveredFilesFromWhitelist'] = isset($arguments['processUncoveredFilesFromWhitelist']) ? $arguments['processUncoveredFilesFromWhitelist'] : false; + $arguments['backupGlobals'] = isset($arguments['backupGlobals']) ? $arguments['backupGlobals'] : null; + $arguments['backupStaticAttributes'] = isset($arguments['backupStaticAttributes']) ? $arguments['backupStaticAttributes'] : null; + $arguments['cacheTokens'] = isset($arguments['cacheTokens']) ? $arguments['cacheTokens'] : false; + $arguments['colors'] = isset($arguments['colors']) ? $arguments['colors'] : false; + $arguments['convertErrorsToExceptions'] = isset($arguments['convertErrorsToExceptions']) ? $arguments['convertErrorsToExceptions'] : true; + $arguments['convertNoticesToExceptions'] = isset($arguments['convertNoticesToExceptions']) ? $arguments['convertNoticesToExceptions'] : true; + $arguments['convertWarningsToExceptions'] = isset($arguments['convertWarningsToExceptions']) ? $arguments['convertWarningsToExceptions'] : true; + $arguments['excludeGroups'] = isset($arguments['excludeGroups']) ? $arguments['excludeGroups'] : array(); + $arguments['groups'] = isset($arguments['groups']) ? $arguments['groups'] : array(); + $arguments['logIncompleteSkipped'] = isset($arguments['logIncompleteSkipped']) ? $arguments['logIncompleteSkipped'] : false; + $arguments['processIsolation'] = isset($arguments['processIsolation']) ? $arguments['processIsolation'] : false; + $arguments['repeat'] = isset($arguments['repeat']) ? $arguments['repeat'] : false; + $arguments['reportHighLowerBound'] = isset($arguments['reportHighLowerBound']) ? $arguments['reportHighLowerBound'] : 90; + $arguments['reportLowUpperBound'] = isset($arguments['reportLowUpperBound']) ? $arguments['reportLowUpperBound'] : 50; + $arguments['stopOnError'] = isset($arguments['stopOnError']) ? $arguments['stopOnError'] : false; + $arguments['stopOnFailure'] = isset($arguments['stopOnFailure']) ? $arguments['stopOnFailure'] : false; + $arguments['stopOnIncomplete'] = isset($arguments['stopOnIncomplete']) ? $arguments['stopOnIncomplete'] : false; + $arguments['stopOnRisky'] = isset($arguments['stopOnRisky']) ? $arguments['stopOnRisky'] : false; + $arguments['stopOnSkipped'] = isset($arguments['stopOnSkipped']) ? $arguments['stopOnSkipped'] : false; + $arguments['timeoutForSmallTests'] = isset($arguments['timeoutForSmallTests']) ? $arguments['timeoutForSmallTests'] : 1; + $arguments['timeoutForMediumTests'] = isset($arguments['timeoutForMediumTests']) ? $arguments['timeoutForMediumTests'] : 10; + $arguments['timeoutForLargeTests'] = isset($arguments['timeoutForLargeTests']) ? $arguments['timeoutForLargeTests'] : 60; + $arguments['reportUselessTests'] = isset($arguments['reportUselessTests']) ? $arguments['reportUselessTests'] : false; + $arguments['strictCoverage'] = isset($arguments['strictCoverage']) ? $arguments['strictCoverage'] : false; + $arguments['disallowTestOutput'] = isset($arguments['disallowTestOutput']) ? $arguments['disallowTestOutput'] : false; + $arguments['enforceTimeLimit'] = isset($arguments['enforceTimeLimit']) ? $arguments['enforceTimeLimit'] : false; + $arguments['verbose'] = isset($arguments['verbose']) ? $arguments['verbose'] : false; + } + + /** + * @param string $message + * @since Method available since Release 4.0.0 + */ + private function showExtensionNotLoadedMessage($extension, $message = '') + { + if (isset($this->missingExtensions[$extension])) { + return; + } + + if (!empty($message)) { + $message = ' ' . $message; + } + + $this->showMessage( + 'The ' . $extension . ' extension is not loaded.' . $message . "\n" + ); + + $this->missingExtensions[$extension] = true; + } + + /** + * Shows a message. + * + * @param string $message + * @param boolean $exit + * @since Method available since Release 4.0.0 + */ + private function showMessage($message, $exit = false) + { + $this->printVersionString(); + $this->write($message . "\n"); + + if ($exit) { + exit(self::EXCEPTION_EXIT); + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * Base class for all test runners. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +abstract class PHPUnit_Runner_BaseTestRunner +{ + const STATUS_PASSED = 0; + const STATUS_SKIPPED = 1; + const STATUS_INCOMPLETE = 2; + const STATUS_FAILURE = 3; + const STATUS_ERROR = 4; + const STATUS_RISKY = 5; + const SUITE_METHODNAME = 'suite'; + + /** + * Returns the loader to be used. + * + * @return PHPUnit_Runner_TestSuiteLoader + */ + public function getLoader() + { + return new PHPUnit_Runner_StandardTestSuiteLoader; + } + + /** + * Returns the Test corresponding to the given suite. + * This is a template method, subclasses override + * the runFailed() and clearStatus() methods. + * + * @param string $suiteClassName + * @param string $suiteClassFile + * @param mixed $suffixes + * @return PHPUnit_Framework_Test + */ + public function getTest($suiteClassName, $suiteClassFile = '', $suffixes = '') + { + if (is_dir($suiteClassName) && + !is_file($suiteClassName . '.php') && empty($suiteClassFile)) { + $facade = new File_Iterator_Facade; + $files = $facade->getFilesAsArray( + $suiteClassName, $suffixes + ); + + $suite = new PHPUnit_Framework_TestSuite($suiteClassName); + $suite->addTestFiles($files); + + return $suite; + } + + try { + $testClass = $this->loadSuiteClass( + $suiteClassName, $suiteClassFile + ); + } catch (PHPUnit_Framework_Exception $e) { + $this->runFailed($e->getMessage()); + + return null; + } + + try { + $suiteMethod = $testClass->getMethod(self::SUITE_METHODNAME); + + if (!$suiteMethod->isStatic()) { + $this->runFailed( + 'suite() method must be static.' + ); + + return null; + } + + try { + $test = $suiteMethod->invoke(null, $testClass->getName()); + } catch (ReflectionException $e) { + $this->runFailed( + sprintf( + "Failed to invoke suite() method.\n%s", + + $e->getMessage() + ) + ); + + return null; + } + } catch (ReflectionException $e) { + try { + $test = new PHPUnit_Framework_TestSuite($testClass); + } catch (PHPUnit_Framework_Exception $e) { + $test = new PHPUnit_Framework_TestSuite; + $test->setName($suiteClassName); + } + } + + $this->clearStatus(); + + return $test; + } + + /** + * Returns the loaded ReflectionClass for a suite name. + * + * @param string $suiteClassName + * @param string $suiteClassFile + * @return ReflectionClass + */ + protected function loadSuiteClass($suiteClassName, $suiteClassFile = '') + { + $loader = $this->getLoader(); + + if ($loader instanceof PHPUnit_Runner_StandardTestSuiteLoader) { + return $loader->load($suiteClassName, $suiteClassFile); + } else { + return $loader->load($suiteClassName, $suiteClassFile); + } + } + + /** + * Clears the status message. + * + */ + protected function clearStatus() + { + } + + /** + * Override to define how to handle a failed loading of + * a test suite. + * + * @param string $message + */ + abstract protected function runFailed($message); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * An interface to define how a test suite should be loaded. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 2.0.0 + */ +interface PHPUnit_Runner_TestSuiteLoader +{ + /** + * @param string $suiteClassName + * @param string $suiteClassFile + * @return ReflectionClass + */ + public function load($suiteClassName, $suiteClassFile = ''); + + /** + * @param ReflectionClass $aClass + * @return ReflectionClass + */ + public function reload(ReflectionClass $aClass); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Runner_Filter_Group_Exclude extends PHPUnit_Runner_Filter_GroupFilterIterator +{ + protected function doAccept($hash) + { + return !in_array($hash, $this->groupTests); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Runner_Filter_Group_Include extends PHPUnit_Runner_Filter_GroupFilterIterator +{ + protected function doAccept($hash) + { + return in_array($hash, $this->groupTests); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Runner_Filter_Factory +{ + /** + * @var array + */ + private $filters = array(); + + /** + * @param ReflectionClass $filter + * @param mixed $args + */ + public function addFilter(ReflectionClass $filter, $args) + { + if (!$filter->isSubclassOf('RecursiveFilterIterator')) { + throw new InvalidArgumentException( + sprintf( + 'Class "%s" does not extend RecursiveFilterIterator', + $filter->name + ) + ); + } + + $this->filters[] = array($filter, $args); + } + + /** + * @return FilterIterator + */ + public function factory(Iterator $iterator, PHPUnit_Framework_TestSuite $suite) + { + foreach ($this->filters as $filter) { + list($class, $args) = $filter; + $iterator = $class->newInstance($iterator, $args, $suite); + } + + return $iterator; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +abstract class PHPUnit_Runner_Filter_GroupFilterIterator extends RecursiveFilterIterator +{ + /** + * @var array + */ + protected $groupTests = array(); + + /** + * @param RecursiveIterator $iterator + * @param array $groups + * @param PHPUnit_Framework_TestSuite $suite + */ + public function __construct(RecursiveIterator $iterator, array $groups, PHPUnit_Framework_TestSuite $suite) + { + parent::__construct($iterator); + + foreach ($suite->getGroupDetails() as $group => $tests) { + if (in_array($group, $groups)) { + $testHashes = array_map( + function ($test) { return spl_object_hash($test); }, + $tests + ); + + $this->groupTests = array_merge($this->groupTests, $testHashes); + } + } + } + + /** + * @return boolean + */ + public function accept() + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof PHPUnit_Framework_TestSuite) { + return true; + } + + return $this->doAccept(spl_object_hash($test)); + } + + abstract protected function doAccept($hash); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Runner_Filter_Test extends RecursiveFilterIterator +{ + /** + * @var string + */ + protected $filter = null; + + /** + * @var integer + */ + protected $filterMin; + /** + * @var integer + */ + protected $filterMax; + + /** + * @param RecursiveIterator $iterator + * @param string $filter + */ + public function __construct(RecursiveIterator $iterator, $filter) + { + parent::__construct($iterator); + $this->setFilter($filter); + } + + /** + * @param string $filter + */ + protected function setFilter($filter) + { + if ($filter[0] != substr($filter, -1) || + preg_match('/^[a-zA-Z0-9_]/', $filter)) { + + // Handles: + // * testAssertEqualsSucceeds#4 + // * testAssertEqualsSucceeds#4-8 + if (preg_match('/^(.*?)#(\d+)(?:-(\d+))?$/', $filter, $matches)) { + if (isset($matches[3]) && $matches[2] < $matches[3]) { + $filter = sprintf( + '%s.*with data set #(\d+)$', + $matches[1] + ); + + $this->filterMin = $matches[2]; + $this->filterMax = $matches[3]; + } else { + $filter = sprintf( + '%s.*with data set #%s$', + $matches[1], + $matches[2] + ); + } + } + + // Handles: + // * testDetermineJsonError@JSON_ERROR_NONE + // * testDetermineJsonError@JSON.* + elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) { + $filter = sprintf( + '%s.*with data set "%s"$', + $matches[1], + $matches[2] + ); + } + + // Escape delimiters in regular expression. Do NOT use preg_quote, + // to keep magic characters. + $filter = sprintf('/%s/', str_replace( + '/', '\\/', $filter + )); + } + + $this->filter = $filter; + } + + /** + * @return boolean + */ + public function accept() + { + $test = $this->getInnerIterator()->current(); + + if ($test instanceof PHPUnit_Framework_TestSuite) { + return true; + } + + $tmp = PHPUnit_Util_Test::describe($test, false); + + if ($tmp[0] != '') { + $name = join('::', $tmp); + } else { + $name = $tmp[1]; + } + + $accepted = preg_match($this->filter, $name, $matches); + + if ($accepted && isset($this->filterMax)) { + $set = end($matches); + $accepted = $set >= $this->filterMin && $set <= $this->filterMax; + } + + return $accepted; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * The standard test suite loader. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Runner_StandardTestSuiteLoader implements PHPUnit_Runner_TestSuiteLoader +{ + /** + * @param string $suiteClassName + * @param string $suiteClassFile + * @return ReflectionClass + * @throws PHPUnit_Framework_Exception + */ + public function load($suiteClassName, $suiteClassFile = '') + { + $suiteClassName = str_replace('.php', '', $suiteClassName); + + if (empty($suiteClassFile)) { + $suiteClassFile = PHPUnit_Util_Filesystem::classNameToFilename( + $suiteClassName + ); + } + + if (!class_exists($suiteClassName, false)) { + $loadedClasses = get_declared_classes(); + + $filename = PHPUnit_Util_Fileloader::checkAndLoad($suiteClassFile); + + $loadedClasses = array_values( + array_diff(get_declared_classes(), $loadedClasses) + ); + } + + if (!class_exists($suiteClassName, false) && !empty($loadedClasses)) { + $offset = 0 - strlen($suiteClassName); + + foreach ($loadedClasses as $loadedClass) { + $class = new ReflectionClass($loadedClass); + if (substr($loadedClass, $offset) === $suiteClassName && + $class->getFileName() == $filename) { + $suiteClassName = $loadedClass; + break; + } + } + } + + if (!class_exists($suiteClassName, false) && !empty($loadedClasses)) { + $testCaseClass = 'PHPUnit_Framework_TestCase'; + + foreach ($loadedClasses as $loadedClass) { + $class = new ReflectionClass($loadedClass); + $classFile = $class->getFileName(); + + if ($class->isSubclassOf($testCaseClass) && + !$class->isAbstract()) { + $suiteClassName = $loadedClass; + $testCaseClass = $loadedClass; + + if ($classFile == realpath($suiteClassFile)) { + break; + } + } + + if ($class->hasMethod('suite')) { + $method = $class->getMethod('suite'); + + if (!$method->isAbstract() && + $method->isPublic() && + $method->isStatic()) { + $suiteClassName = $loadedClass; + + if ($classFile == realpath($suiteClassFile)) { + break; + } + } + } + } + } + + if (class_exists($suiteClassName, false)) { + $class = new ReflectionClass($suiteClassName); + + if ($class->getFileName() == realpath($suiteClassFile)) { + return $class; + } + } + + throw new PHPUnit_Framework_Exception( + sprintf( + "Class '%s' could not be found in '%s'.", + + $suiteClassName, + $suiteClassFile + ) + ); + } + + /** + * @param ReflectionClass $aClass + * @return ReflectionClass + */ + public function reload(ReflectionClass $aClass) + { + return $aClass; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 4.0.0 + */ +class PHPUnit_Runner_Exception extends RuntimeException implements PHPUnit_Exception +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * This class defines the current version of PHPUnit. + * + * @package PHPUnit + * @subpackage Runner + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Runner_Version +{ + private static $pharVersion = "4.1.1"; + private static $version; + + /** + * Returns the current version of PHPUnit. + * + * @return string + */ + public static function id() + { + if (self::$pharVersion !== null) { + return self::$pharVersion; + } + + if (self::$version === null) { + $version = new SebastianBergmann\Version('4.1.1', dirname(dirname(__DIR__))); + self::$version = $version->getVersion(); + } + + return self::$version; + } + + /** + * @return string + */ + public static function getVersionString() + { + return 'PHPUnit ' . self::id() . ' by Sebastian Bergmann.'; + } + + /** + * @return string + * @since Method available since Release 4.0.0 + */ + public static function getReleaseChannel() + { + if (strpos(self::$pharVersion, 'alpha') !== false) { + return '-alpha'; + } + + if (strpos(self::$pharVersion, 'beta') !== false) { + return '-beta'; + } + + return ''; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Extensions_PhptTestCase + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.4 + */ + +/** + * Runner for PHPT test cases. + * + * @package PHPUnit + * @subpackage Extensions_PhptTestCase + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.4 + */ +class PHPUnit_Extensions_PhptTestCase implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing +{ + /** + * @var string + */ + private $filename; + + /** + * @var array + */ + private $settings = array( + 'allow_url_fopen=1', + 'auto_append_file=', + 'auto_prepend_file=', + 'disable_functions=', + 'display_errors=1', + 'docref_root=', + 'docref_ext=.html', + 'error_append_string=', + 'error_prepend_string=', + 'error_reporting=-1', + 'html_errors=0', + 'log_errors=0', + 'magic_quotes_runtime=0', + 'output_handler=', + 'open_basedir=', + 'output_buffering=Off', + 'report_memleaks=0', + 'report_zend_debug=0', + 'safe_mode=0', + 'track_errors=1', + 'xdebug.default_enable=0' + ); + + /** + * Constructs a test case with the given filename. + * + * @param string $filename + * @throws PHPUnit_Framework_Exception + */ + public function __construct($filename) + { + if (!is_string($filename)) { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'string'); + } + + if (!is_file($filename)) { + throw new PHPUnit_Framework_Exception( + sprintf( + 'File "%s" does not exist.', + $filename + ) + ); + } + + $this->filename = $filename; + } + + /** + * Counts the number of test cases executed by run(TestResult result). + * + * @return integer + */ + public function count() + { + return 1; + } + + /** + * Runs a test and collects its result in a TestResult instance. + * + * @param PHPUnit_Framework_TestResult $result + * @return PHPUnit_Framework_TestResult + */ + public function run(PHPUnit_Framework_TestResult $result = null) + { + $sections = $this->parse(); + $code = $this->render($sections['FILE']); + + if ($result === null) { + $result = new PHPUnit_Framework_TestResult; + } + + $php = PHPUnit_Util_PHP::factory(); + $skip = false; + $time = 0; + + $result->startTest($this); + + if (isset($sections['SKIPIF'])) { + $jobResult = $php->runJob($sections['SKIPIF'], $this->settings); + + if (!strncasecmp('skip', ltrim($jobResult['stdout']), 4)) { + if (preg_match('/^\s*skip\s*(.+)\s*/i', $jobResult['stdout'], $message)) { + $message = substr($message[1], 2); + } else { + $message = ''; + } + + $result->addFailure($this, new PHPUnit_Framework_SkippedTestError($message), 0); + + $skip = true; + } + } + + if (!$skip) { + PHP_Timer::start(); + $jobResult = $php->runJob($code, $this->settings); + $time = PHP_Timer::stop(); + + if (isset($sections['EXPECT'])) { + $assertion = 'assertEquals'; + $expected = preg_replace('/\r\n/', "\n", trim($sections['EXPECT'])); + } else { + $assertion = 'assertStringMatchesFormat'; + $expected = trim($sections['EXPECTF']); + } + + try { + PHPUnit_Framework_Assert::$assertion($expected, trim($jobResult['stdout'])); + } catch (PHPUnit_Framework_AssertionFailedError $e) { + $result->addFailure($this, $e, $time); + } catch (Exception $e) { + $result->addError($this, $e, $time); + } + } + + $result->endTest($this, $time); + + return $result; + } + + /** + * Returns the name of the test case. + * + * @return string + */ + public function getName() + { + return $this->toString(); + } + + /** + * Returns a string representation of the test case. + * + * @return string + */ + public function toString() + { + return $this->filename; + } + + /** + * @return array + * @throws PHPUnit_Framework_Exception + */ + private function parse() + { + $sections = array(); + $section = ''; + + foreach (file($this->filename) as $line) { + if (preg_match('/^--([_A-Z]+)--/', $line, $result)) { + $section = $result[1]; + $sections[$section] = ''; + continue; + } elseif (empty($section)) { + throw new PHPUnit_Framework_Exception('Invalid PHPT file'); + } + + $sections[$section] .= $line; + } + + if (!isset($sections['FILE']) || + (!isset($sections['EXPECT']) && !isset($sections['EXPECTF']))) { + throw new PHPUnit_Framework_Exception('Invalid PHPT file'); + } + + return $sections; + } + + /** + * @param string $code + * @return string + */ + private function render($code) + { + return str_replace( + array( + '__DIR__', + '__FILE__' + ), + array( + "'" . dirname($this->filename) . "'", + "'" . $this->filename . "'" + ), + $code + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A Decorator that runs a test repeatedly. + * + * @package PHPUnit + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Extensions_RepeatedTest extends PHPUnit_Extensions_TestDecorator +{ + /** + * @var mixed + */ + protected $filter = false; + + /** + * @var array + */ + protected $groups = array(); + + /** + * @var array + */ + protected $excludeGroups = array(); + + /** + * @var boolean + */ + protected $processIsolation = false; + + /** + * @var integer + */ + protected $timesRepeat = 1; + + /** + * Constructor. + * + * @param PHPUnit_Framework_Test $test + * @param integer $timesRepeat + * @param mixed $filter + * @param array $groups + * @param array $excludeGroups + * @param boolean $processIsolation + * @throws PHPUnit_Framework_Exception + */ + public function __construct(PHPUnit_Framework_Test $test, $timesRepeat = 1, $processIsolation = false) + { + parent::__construct($test); + + if (is_integer($timesRepeat) && + $timesRepeat >= 0) { + $this->timesRepeat = $timesRepeat; + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory( + 2, 'positive integer' + ); + } + + $this->processIsolation = $processIsolation; + } + + /** + * Counts the number of test cases that + * will be run by this test. + * + * @return integer + */ + public function count() + { + return $this->timesRepeat * count($this->test); + } + + /** + * Runs the decorated test and collects the + * result in a TestResult. + * + * @param PHPUnit_Framework_TestResult $result + * @return PHPUnit_Framework_TestResult + * @throws PHPUnit_Framework_Exception + */ + public function run(PHPUnit_Framework_TestResult $result = null) + { + if ($result === null) { + $result = $this->createResult(); + } + + //@codingStandardsIgnoreStart + for ($i = 0; $i < $this->timesRepeat && !$result->shouldStop(); $i++) { + //@codingStandardsIgnoreEnd + if ($this->test instanceof PHPUnit_Framework_TestSuite) { + $this->test->setRunTestInSeparateProcess($this->processIsolation); + } + $this->test->run($result); + } + + return $result; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Extensions + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 2.0.0 + */ + +/** + * A Decorator for Tests. + * + * Use TestDecorator as the base class for defining new + * test decorators. Test decorator subclasses can be introduced + * to add behaviour before or after a test is run. + * + * @package PHPUnit + * @subpackage Extensions + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 2.0.0 + */ +class PHPUnit_Extensions_TestDecorator extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing +{ + /** + * The Test to be decorated. + * + * @var object + */ + protected $test = null; + + /** + * Constructor. + * + * @param PHPUnit_Framework_Test $test + */ + public function __construct(PHPUnit_Framework_Test $test) + { + $this->test = $test; + } + + /** + * Returns a string representation of the test. + * + * @return string + */ + public function toString() + { + return $this->test->toString(); + } + + /** + * Runs the test and collects the + * result in a TestResult. + * + * @param PHPUnit_Framework_TestResult $result + */ + public function basicRun(PHPUnit_Framework_TestResult $result) + { + $this->test->run($result); + } + + /** + * Counts the number of test cases that + * will be run by this test. + * + * @return integer + */ + public function count() + { + return count($this->test); + } + + /** + * Creates a default TestResult object. + * + * @return PHPUnit_Framework_TestResult + */ + protected function createResult() + { + return new PHPUnit_Framework_TestResult; + } + + /** + * Returns the test to be run. + * + * @return PHPUnit_Framework_Test + */ + public function getTest() + { + return $this->test; + } + + /** + * Runs the decorated test and collects the + * result in a TestResult. + * + * @param PHPUnit_Framework_TestResult $result + * @return PHPUnit_Framework_TestResult + */ + public function run(PHPUnit_Framework_TestResult $result = null) + { + if ($result === null) { + $result = $this->createResult(); + } + + $this->basicRun($result); + + return $result; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Extensions + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.3.0 + */ + +/** + * We have a TestSuite object A. + * In TestSuite object A we have Tests tagged with @group. + * We want a TestSuite object B that contains TestSuite objects C, D, ... + * for the Tests tagged with @group C, @group D, ... + * Running the Tests from TestSuite object B results in Tests tagged with both + * @group C and @group D in TestSuite object A to be run twice . + * + * + * $suite = new PHPUnit_Extensions_GroupTestSuite($A, array('C', 'D')); + * + * + * @package PHPUnit + * @subpackage Extensions + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.3.0 + */ +class PHPUnit_Extensions_GroupTestSuite extends PHPUnit_Framework_TestSuite +{ + public function __construct(PHPUnit_Framework_TestSuite $suite, array $groups) + { + $groupSuites = array(); + $name = $suite->getName(); + + foreach ($groups as $group) { + $groupSuites[$group] = new PHPUnit_Framework_TestSuite($name . ' - ' . $group); + $this->addTest($groupSuites[$group]); + } + + $tests = new RecursiveIteratorIterator( + new PHPUnit_Util_TestSuiteIterator($suite), + RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($tests as $test) { + if ($test instanceof PHPUnit_Framework_TestCase) { + $testGroups = PHPUnit_Util_Test::getGroups( + get_class($test), $test->getName(false) + ); + + foreach ($groups as $group) { + foreach ($testGroups as $testGroup) { + if ($group == $testGroup) { + $groupSuites[$group]->addTest($test); + } + } + } + } + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Extensions_TicketListener + * @author Sean Coates + * @author Raphael Stolt + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.4.0 + */ + +/** + * Base class for test listeners that interact with an issue tracker. + * + * @package PHPUnit + * @subpackage Extensions_TicketListener + * @author Sean Coates + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.4.0 + */ +abstract class PHPUnit_Extensions_TicketListener implements PHPUnit_Framework_TestListener +{ + /** + * @var array + */ + protected $ticketCounts = array(); + + /** + * @var boolean + */ + protected $ran = false; + + /** + * An error occurred. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * A failure occurred. + * + * @param PHPUnit_Framework_Test $test + * @param PHPUnit_Framework_AssertionFailedError $e + * @param float $time + */ + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + { + } + + /** + * Incomplete test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + */ + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * Risky test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 4.0.0 + */ + public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * Skipped test. + * + * @param PHPUnit_Framework_Test $test + * @param Exception $e + * @param float $time + * @since Method available since Release 3.0.0 + */ + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + { + } + + /** + * A test suite started. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test suite ended. + * + * @param PHPUnit_Framework_TestSuite $suite + * @since Method available since Release 2.2.0 + */ + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + { + } + + /** + * A test started. + * + * @param PHPUnit_Framework_Test $test + */ + public function startTest(PHPUnit_Framework_Test $test) + { + if (!$test instanceof PHPUnit_Framework_Warning) { + if ($this->ran) { + return; + } + + $name = $test->getName(false); + $tickets = PHPUnit_Util_Test::getTickets(get_class($test), $name); + + foreach ($tickets as $ticket) { + $this->ticketCounts[$ticket][$name] = 1; + } + + $this->ran = true; + } + } + + /** + * A test ended. + * + * @param PHPUnit_Framework_Test $test + * @param float $time + */ + public function endTest(PHPUnit_Framework_Test $test, $time) + { + if (!$test instanceof PHPUnit_Framework_Warning) { + if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) { + $ifStatus = array('assigned', 'new', 'reopened'); + $newStatus = 'closed'; + $message = 'Automatically closed by PHPUnit (test passed).'; + $resolution = 'fixed'; + $cumulative = true; + } elseif ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE) { + $ifStatus = array('closed'); + $newStatus = 'reopened'; + $message = 'Automatically reopened by PHPUnit (test failed).'; + $resolution = ''; + $cumulative = false; + } else { + return; + } + + $name = $test->getName(false); + $tickets = PHPUnit_Util_Test::getTickets(get_class($test), $name); + + foreach ($tickets as $ticket) { + // Remove this test from the totals (if it passed). + if ($test->getStatus() == PHPUnit_Runner_BaseTestRunner::STATUS_PASSED) { + unset($this->ticketCounts[$ticket][$name]); + } + + // Only close tickets if ALL referenced cases pass + // but reopen tickets if a single test fails. + if ($cumulative) { + // Determine number of to-pass tests: + if (count($this->ticketCounts[$ticket]) > 0) { + // There exist remaining test cases with this reference. + $adjustTicket = false; + } else { + // No remaining tickets, go ahead and adjust. + $adjustTicket = true; + } + } else { + $adjustTicket = true; + } + + $ticketInfo = $this->getTicketInfo($ticket); + + if ($adjustTicket && in_array($ticketInfo['status'], $ifStatus)) { + $this->updateTicket($ticket, $newStatus, $message, $resolution); + } + } + } + } + + abstract protected function getTicketInfo($ticketId = null); + abstract protected function updateTicket($ticketId, $newStatus, $message, $resolution); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Extensions_PhptTestCase + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 3.1.4 + */ + +/** + * Suite for .phpt test cases. + * + * @package PHPUnit + * @subpackage Extensions_PhptTestCase + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Class available since Release 3.1.4 + */ +class PHPUnit_Extensions_PhptTestSuite extends PHPUnit_Framework_TestSuite +{ + /** + * Constructs a new TestSuite for .phpt test cases. + * + * @param string $directory + * @param array $options Array with ini settings for the php instance run, + * key being the name if the setting, value the ini value. + * @throws PHPUnit_Framework_Exception + */ + public function __construct($directory, array $options = array()) + { + if (is_string($directory) && is_dir($directory)) { + $this->setName($directory); + + $facade = new File_Iterator_Facade; + $files = $facade->getFilesAsArray($directory, '.phpt'); + + foreach ($files as $file) { + $this->addTestFile($file, $options); + } + } else { + throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'directory name'); + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since File available since Release 4.0.0 + */ + +/** + * Marker interface for PHPUnit exceptions. + * + * @package PHPUnit + * @subpackage Framework + * @author Sebastian Bergmann + * @copyright 2001-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://www.phpunit.de/ + * @since Interface available since Release 4.0.0 + */ +interface PHPUnit_Exception +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.0.0 + */ + +/** + * Interface for code coverage drivers. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.0.0 + */ +interface PHP_CodeCoverage_Driver +{ + /** + * Start collection of code coverage information. + */ + public function start(); + + /** + * Stop collection of code coverage information. + * + * @return array + */ + public function stop(); +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.2.0 + */ + +/** + * Factory for PHP_CodeCoverage_Exception objects that are used to describe + * invalid arguments passed to a function or method. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.2.0 + */ +class PHP_CodeCoverage_Util_InvalidArgumentHelper +{ + /** + * @param integer $argument + * @param string $type + * @param mixed $value + */ + public static function factory($argument, $type, $value = null) + { + $stack = debug_backtrace(false); + + return new PHP_CodeCoverage_Exception( + sprintf( + 'Argument #%d%sof %s::%s() must be a %s', + $argument, + $value !== null ? ' (' . gettype($value) . '#' . $value . ')' : ' (No Value) ', + $stack[1]['class'], + $stack[1]['function'], + $type + ) + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.0.0 + */ + +/** + * Filter for blacklisting and whitelisting of code coverage information. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.0.0 + */ +class PHP_CodeCoverage_Filter +{ + /** + * Source files that are blacklisted. + * + * @var array + */ + private $blacklistedFiles = array(); + + /** + * Source files that are whitelisted. + * + * @var array + */ + private $whitelistedFiles = array(); + + /** + * @var boolean + */ + private $blacklistPrefilled = false; + + /** + * A list of classes which are always blacklisted + * + * @var array + */ + public static $blacklistClassNames = array( + 'File_Iterator' => 1, + 'PHP_CodeCoverage' => 1, + 'PHP_Invoker' => 1, + 'PHP_Timer' => 1, + 'PHP_Token' => 1, + 'PHPUnit_Framework_TestCase' => 2, + 'PHPUnit_Extensions_Database_TestCase' => 2, + 'PHPUnit_Framework_MockObject_Generator' => 2, + 'PHPUnit_Extensions_SeleniumTestCase' => 2, + 'PHPUnit_Extensions_Story_TestCase' => 2, + 'Text_Template' => 1, + 'Symfony\Component\Yaml\Yaml' => 1, + 'SebastianBergmann\Diff\Diff' => 1, + 'SebastianBergmann\Environment\Runtime' => 1, + 'SebastianBergmann\Exporter\Exporter' => 1, + 'SebastianBergmann\Version' => 1, + 'Composer\Autoload\ClassLoader' => 1 + ); + + /** + * Adds a directory to the blacklist (recursively). + * + * @param string $directory + * @param string $suffix + * @param string $prefix + */ + public function addDirectoryToBlacklist($directory, $suffix = '.php', $prefix = '') + { + $facade = new File_Iterator_Facade; + $files = $facade->getFilesAsArray($directory, $suffix, $prefix); + + foreach ($files as $file) { + $this->addFileToBlacklist($file); + } + } + + /** + * Adds a file to the blacklist. + * + * @param string $filename + */ + public function addFileToBlacklist($filename) + { + $this->blacklistedFiles[realpath($filename)] = true; + } + + /** + * Adds files to the blacklist. + * + * @param array $files + */ + public function addFilesToBlacklist(array $files) + { + foreach ($files as $file) { + $this->addFileToBlacklist($file); + } + } + + /** + * Removes a directory from the blacklist (recursively). + * + * @param string $directory + * @param string $suffix + * @param string $prefix + */ + public function removeDirectoryFromBlacklist($directory, $suffix = '.php', $prefix = '') + { + $facade = new File_Iterator_Facade; + $files = $facade->getFilesAsArray($directory, $suffix, $prefix); + + foreach ($files as $file) { + $this->removeFileFromBlacklist($file); + } + } + + /** + * Removes a file from the blacklist. + * + * @param string $filename + */ + public function removeFileFromBlacklist($filename) + { + $filename = realpath($filename); + + if (isset($this->blacklistedFiles[$filename])) { + unset($this->blacklistedFiles[$filename]); + } + } + + /** + * Adds a directory to the whitelist (recursively). + * + * @param string $directory + * @param string $suffix + * @param string $prefix + */ + public function addDirectoryToWhitelist($directory, $suffix = '.php', $prefix = '') + { + $facade = new File_Iterator_Facade; + $files = $facade->getFilesAsArray($directory, $suffix, $prefix); + + foreach ($files as $file) { + $this->addFileToWhitelist($file); + } + } + + /** + * Adds a file to the whitelist. + * + * @param string $filename + */ + public function addFileToWhitelist($filename) + { + $this->whitelistedFiles[realpath($filename)] = true; + } + + /** + * Adds files to the whitelist. + * + * @param array $files + */ + public function addFilesToWhitelist(array $files) + { + foreach ($files as $file) { + $this->addFileToWhitelist($file); + } + } + + /** + * Removes a directory from the whitelist (recursively). + * + * @param string $directory + * @param string $suffix + * @param string $prefix + */ + public function removeDirectoryFromWhitelist($directory, $suffix = '.php', $prefix = '') + { + $facade = new File_Iterator_Facade; + $files = $facade->getFilesAsArray($directory, $suffix, $prefix); + + foreach ($files as $file) { + $this->removeFileFromWhitelist($file); + } + } + + /** + * Removes a file from the whitelist. + * + * @param string $filename + */ + public function removeFileFromWhitelist($filename) + { + $filename = realpath($filename); + + if (isset($this->whitelistedFiles[$filename])) { + unset($this->whitelistedFiles[$filename]); + } + } + + /** + * Checks whether a filename is a real filename. + * + * @param string $filename + */ + public function isFile($filename) + { + if ($filename == '-' || + strpos($filename, 'eval()\'d code') !== false || + strpos($filename, 'runtime-created function') !== false || + strpos($filename, 'runkit created function') !== false || + strpos($filename, 'assert code') !== false || + strpos($filename, 'regexp code') !== false) { + return false; + } + + return true; + } + + /** + * Checks whether or not a file is filtered. + * + * When the whitelist is empty (default), blacklisting is used. + * When the whitelist is not empty, whitelisting is used. + * + * @param string $filename + * @param boolean $ignoreWhitelist + * @return boolean + * @throws PHP_CodeCoverage_Exception + */ + public function isFiltered($filename) + { + if (!$this->isFile($filename)) { + return true; + } + + $filename = realpath($filename); + + if (!empty($this->whitelistedFiles)) { + return !isset($this->whitelistedFiles[$filename]); + } + + if (!$this->blacklistPrefilled) { + $this->prefillBlacklist(); + } + + return isset($this->blacklistedFiles[$filename]); + } + + /** + * Returns the list of blacklisted files. + * + * @return array + */ + public function getBlacklist() + { + return array_keys($this->blacklistedFiles); + } + + /** + * Returns the list of whitelisted files. + * + * @return array + */ + public function getWhitelist() + { + return array_keys($this->whitelistedFiles); + } + + /** + * Returns whether this filter has a whitelist. + * + * @return boolean + * @since Method available since Release 1.1.0 + */ + public function hasWhitelist() + { + return !empty($this->whitelistedFiles); + } + + /** + * @since Method available since Release 1.2.3 + */ + private function prefillBlacklist() + { + if (defined('__PHPUNIT_PHAR__')) { + $this->addFileToBlacklist(__PHPUNIT_PHAR__); + } + + foreach (self::$blacklistClassNames as $className => $parent) { + $this->addDirectoryContainingClassToBlacklist($className, $parent); + } + + $this->blacklistPrefilled = true; + } + + /** + * @param string $className + * @param integer $parent + * @since Method available since Release 1.2.3 + */ + private function addDirectoryContainingClassToBlacklist($className, $parent = 1) + { + if (!class_exists($className)) { + return; + } + + $reflector = new ReflectionClass($className); + $directory = $reflector->getFileName(); + + for ($i = 0; $i < $parent; $i++) { + $directory = dirname($directory); + } + + $this->addDirectoryToBlacklist($directory); + } + + /** + * Returns the blacklisted files. + * + * @return array + * @since Method available since Release 2.0.0 + */ + public function getBlacklistedFiles() + { + return $this->blacklistedFiles; + } + + /** + * Sets the blacklisted files. + * + * @param array $blacklistedFiles + * @since Method available since Release 2.0.0 + */ + public function setBlacklistedFiles($blacklistedFiles) + { + $this->blacklistedFiles = $blacklistedFiles; + } + + /** + * Returns the whitelisted files. + * + * @return array + * @since Method available since Release 2.0.0 + */ + public function getWhitelistedFiles() + { + return $this->whitelistedFiles; + } + + /** + * Sets the whitelisted files. + * + * @param array $whitelistedFiles + * @since Method available since Release 2.0.0 + */ + public function setWhitelistedFiles($whitelistedFiles) + { + $this->whitelistedFiles = $whitelistedFiles; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.0.0 + */ + +/** + * Driver for Xdebug's code coverage functionality. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.0.0 + * @codeCoverageIgnore + */ +class PHP_CodeCoverage_Driver_Xdebug implements PHP_CodeCoverage_Driver +{ + /** + * Constructor. + */ + public function __construct() + { + if (!extension_loaded('xdebug')) { + throw new PHP_CodeCoverage_Exception('This driver requires Xdebug'); + } + + if (version_compare(phpversion('xdebug'), '2.2.0-dev', '>=') && + !ini_get('xdebug.coverage_enable')) { + throw new PHP_CodeCoverage_Exception( + 'xdebug.coverage_enable=On has to be set in php.ini' + ); + } + } + + /** + * Start collection of code coverage information. + */ + public function start() + { + xdebug_start_code_coverage(XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE); + } + + /** + * Stop collection of code coverage information. + * + * @return array + */ + public function stop() + { + $data = xdebug_get_code_coverage(); + xdebug_stop_code_coverage(); + + return $this->cleanup($data); + } + + /** + * @param array $data + * @return array + * @since Method available since Release 2.0.0 + */ + private function cleanup(array $data) + { + foreach (array_keys($data) as $file) { + if (isset($data[$file][0])) { + unset($data[$file][0]); + } + + if (file_exists($file)) { + $numLines = $this->getNumberOfLinesInFile($file); + + foreach (array_keys($data[$file]) as $line) { + if (isset($data[$file][$line]) && $line > $numLines) { + unset($data[$file][$line]); + } + } + } + } + + return $data; + } + + /** + * @param string $file + * @return integer + * @since Method available since Release 2.0.0 + */ + private function getNumberOfLinesInFile($file) + { + $buffer = file_get_contents($file); + $lines = substr_count($buffer, "\n"); + + if (substr($buffer, -1) !== "\n") { + $lines++; + } + + return $lines; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.3.0 + */ + +/** + * Driver for HHVM's code coverage functionality. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.3.0 + * @codeCoverageIgnore + */ +class PHP_CodeCoverage_Driver_HHVM implements PHP_CodeCoverage_Driver +{ + /** + * Constructor. + */ + public function __construct() + { + if (!defined('HHVM_VERSION')) { + throw new PHP_CodeCoverage_Exception('This driver requires HHVM'); + } + } + + /** + * Start collection of code coverage information. + */ + public function start() + { + fb_enable_code_coverage(); + } + + /** + * Stop collection of code coverage information. + * + * @return array + */ + public function stop() + { + $codeCoverage = fb_get_code_coverage(TRUE); + + fb_disable_code_coverage(); + + return $codeCoverage; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 2.0.0 + */ + +/** + * Exception that is raised when code is unintentionally covered. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 2.0.0 + */ +class PHP_CodeCoverage_Exception_UnintentionallyCoveredCode extends PHP_CodeCoverage_Exception +{ +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.0.0 + */ + +/** + * Utility methods. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.0.0 + */ +class PHP_CodeCoverage_Util +{ + /** + * @param float $a + * @param float $b + * @return float ($a / $b) * 100 + */ + public static function percent($a, $b, $asString = false, $fixedWidth = false) + { + if ($asString && $b == 0) { + return ''; + } + + if ($b > 0) { + $percent = ($a / $b) * 100; + } else { + $percent = 100; + } + + if ($asString) { + if ($fixedWidth) { + return sprintf('%6.2F%%', $percent); + } + + return sprintf('%01.2F%%', $percent); + } else { + return $percent; + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.1.0 + */ + +/** + * Uses var_export() to write a PHP_CodeCoverage object to a file. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @author uyga + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.1.0 + */ +class PHP_CodeCoverage_Report_PHP +{ + /** + * @param PHP_CodeCoverage $coverage + * @param string $target + * @return string + */ + public function process(PHP_CodeCoverage $coverage, $target = null) + { + $filter = $coverage->filter(); + + $output = sprintf( + 'setData(%s); +$coverage->setTests(%s); + +$filter = $coverage->filter(); +$filter->setBlacklistedFiles(%s); +$filter->setWhitelistedFiles(%s); + +return $coverage;', + var_export($coverage->getData(true), 1), + var_export($coverage->getTests(), 1), + var_export($filter->getBlacklistedFiles(), 1), + var_export($filter->getWhitelistedFiles(), 1) + ); + + if ($target !== null) { + return file_put_contents($target, $output); + } else { + return $output; + } + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Arne Blankerts + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 2.0.0 + */ + +/** + * @category PHP + * @package CodeCoverage + * @author Arne Blankerts + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 2.0.0 + */ +class PHP_CodeCoverage_Report_XML +{ + /** + * @var string + */ + private $target; + + /** + * @var PHP_CodeCoverage_Report_XML_Project + */ + private $project; + + public function process(PHP_CodeCoverage $coverage, $target) + { + if (substr($target, -1, 1) != DIRECTORY_SEPARATOR) { + $target .= DIRECTORY_SEPARATOR; + } + + $this->target = $target; + $this->initTargetDirectory($target); + + $report = $coverage->getReport(); + + $this->project = new PHP_CodeCoverage_Report_XML_Project( + $coverage->getReport()->getName() + ); + + $this->processTests($coverage->getTests()); + $this->processDirectory($report, $this->project); + + $index = $this->project->asDom(); + $index->formatOutput = true; + $index->preserveWhiteSpace = false; + $index->save($target . '/index.xml'); + } + + private function initTargetDirectory($dir) + { + if (file_exists($dir)) { + if (!is_dir($dir)) { + throw new PHP_CodeCoverage_Exception( + "'$dir' exists but is not a directory." + ); + } + + if (!is_writable($dir)) { + throw new PHP_CodeCoverage_Exception( + "'$dir' exists but is not writable." + ); + } + } elseif (!@mkdir($dir, 0777, true)) { + throw new PHP_CodeCoverage_Exception( + "'$dir' could not be created." + ); + } + } + + private function processDirectory(PHP_CodeCoverage_Report_Node_Directory $directory, PHP_CodeCoverage_Report_XML_Node $context) + { + $dirObject = $context->addDirectory($directory->getName()); + + $this->setTotals($directory, $dirObject->getTotals()); + + foreach ($directory as $node) { + if ($node instanceof PHP_CodeCoverage_Report_Node_Directory) { + $this->processDirectory($node, $dirObject); + continue; + } + + if ($node instanceof PHP_CodeCoverage_Report_Node_File) { + $this->processFile($node, $dirObject); + continue; + } + + throw new PHP_CodeCoverage_Exception( + 'Unknown node type for XML report' + ); + } + } + + private function processFile(PHP_CodeCoverage_Report_Node_File $file, PHP_CodeCoverage_Report_XML_Directory $context) + { + $fileObject = $context->addFile( + $file->getName(), + $file->getId() . '.xml' + ); + + $this->setTotals($file, $fileObject->getTotals()); + + $fileReport = new PHP_CodeCoverage_Report_XML_File_Report( + $file->getName() + ); + + $this->setTotals($file, $fileReport->getTotals()); + + foreach ($file->getClassesAndTraits() as $unit) { + $this->processUnit($unit, $fileReport); + } + + foreach ($file->getFunctions() as $function) { + $this->processFunction($function, $fileReport); + } + + foreach ($file->getCoverageData() as $line => $tests) { + if (!is_array($tests) || count($tests) == 0) { + continue; + } + + $coverage = $fileReport->getLineCoverage($line); + + foreach ($tests as $test) { + $coverage->addTest($test); + } + + $coverage->finalize(); + } + + $this->initTargetDirectory( + $this->target . dirname($file->getId()) . '/' + ); + + $fileDom = $fileReport->asDom(); + $fileDom->formatOutput = true; + $fileDom->preserveWhiteSpace = false; + $fileDom->save($this->target . $file->getId() . '.xml'); + } + + private function processUnit($unit, PHP_CodeCoverage_Report_XML_File_Report $report) + { + if (isset($unit['className'])) { + $unitObject = $report->getClassObject($unit['className']); + } else { + $unitObject = $report->getTraitObject($unit['traitName']); + } + + $unitObject->setLines( + $unit['startLine'], + $unit['executableLines'], + $unit['executedLines'] + ); + + $unitObject->setCrap($unit['crap']); + + $unitObject->setPackage( + $unit['package']['fullPackage'], + $unit['package']['package'], + $unit['package']['subpackage'], + $unit['package']['category'] + ); + + $unitObject->setNamespace($unit['package']['namespace']); + + foreach ($unit['methods'] as $method) { + $methodObject = $unitObject->addMethod($method['methodName']); + $methodObject->setSignature($method['signature']); + $methodObject->setLines($method['startLine'], $method['endLine']); + $methodObject->setCrap($method['crap']); + $methodObject->setTotals( + $method['executableLines'], + $method['executedLines'], + $method['coverage'] + ); + } + } + + private function processFunction($function, PHP_CodeCoverage_Report_XML_File_Report $report) + { + $functionObject = $report->getFunctionObject($function['functionName']); + + $functionObject->setSignature($function['signature']); + $functionObject->setLines($function['startLine']); + $functionObject->setCrap($function['crap']); + $functionObject->setTotals($function['executableLines'], $function['executedLines'], $function['coverage']); + } + + private function processTests(array $tests) + { + $testsObject = $this->project->getTests(); + + foreach ($tests as $test => $result) { + if ($test == 'UNCOVERED_FILES_FROM_WHITELIST') { + continue; + } + + $testsObject->addTest($test, $result); + } + } + + private function setTotals(PHP_CodeCoverage_Report_Node $node, PHP_CodeCoverage_Report_XML_Totals $totals) + { + $loc = $node->getLinesOfCode(); + + $totals->setNumLines( + $loc['loc'], + $loc['cloc'], + $loc['ncloc'], + $node->getNumExecutableLines(), + $node->getNumExecutedLines() + ); + + $totals->setNumClasses( + $node->getNumClasses(), + $node->getNumTestedClasses() + ); + + $totals->setNumTraits( + $node->getNumTraits(), + $node->getNumTestedTraits() + ); + + $totals->setNumMethods( + $node->getNumMethods(), + $node->getNumTestedMethods() + ); + + $totals->setNumFunctions( + $node->getNumFunctions(), + $node->getNumTestedFunctions() + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.1.0 + */ + +// @codeCoverageIgnoreStart +if (!defined('T_TRAIT')) { + define('T_TRAIT', 1001); +} + +if (!defined('T_INSTEADOF')) { + define('T_INSTEADOF', 1002); +} + +if (!defined('T_CALLABLE')) { + define('T_CALLABLE', 1003); +} + +if (!defined('T_FINALLY')) { + define('T_FINALLY', 1004); +} + +if (!defined('T_YIELD')) { + define('T_YIELD', 1005); +} +// @codeCoverageIgnoreEnd + +/** + * Renders a PHP_CodeCoverage_Report_Node_File node. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.1.0 + */ +class PHP_CodeCoverage_Report_HTML_Renderer_File extends PHP_CodeCoverage_Report_HTML_Renderer +{ + /** + * Constructor. + * + * @param string $templatePath + * @param string $generator + * @param string $date + * @param integer $lowUpperBound + * @param integer $highLowerBound + */ + public function __construct($templatePath, $generator, $date, $lowUpperBound, $highLowerBound) + { + parent::__construct( + $templatePath, + $generator, + $date, + $lowUpperBound, + $highLowerBound + ); + } + + /** + * @param PHP_CodeCoverage_Report_Node_File $node + * @param string $file + */ + public function render(PHP_CodeCoverage_Report_Node_File $node, $file) + { + $template = new Text_Template($this->templatePath . 'file.html', '{{', '}}'); + + $template->setVar( + array( + 'items' => $this->renderItems($node), + 'lines' => $this->renderSource($node) + ) + ); + + $this->setCommonTemplateVariables($template, $node); + + $template->renderTo($file); + } + + /** + * @param PHP_CodeCoverage_Report_Node_File $node + * @return string + */ + protected function renderItems(PHP_CodeCoverage_Report_Node_File $node) + { + $template = new Text_Template($this->templatePath . 'file_item.html', '{{', '}}'); + + $methodItemTemplate = new Text_Template( + $this->templatePath . 'method_item.html', '{{', '}}' + ); + + $items = $this->renderItemTemplate( + $template, + array( + 'name' => 'Total', + 'numClasses' => $node->getNumClassesAndTraits(), + 'numTestedClasses' => $node->getNumTestedClassesAndTraits(), + 'numMethods' => $node->getNumMethods(), + 'numTestedMethods' => $node->getNumTestedMethods(), + 'linesExecutedPercent' => $node->getLineExecutedPercent(false), + 'linesExecutedPercentAsString' => $node->getLineExecutedPercent(), + 'numExecutedLines' => $node->getNumExecutedLines(), + 'numExecutableLines' => $node->getNumExecutableLines(), + 'testedMethodsPercent' => $node->getTestedMethodsPercent(false), + 'testedMethodsPercentAsString' => $node->getTestedMethodsPercent(), + 'testedClassesPercent' => $node->getTestedClassesAndTraitsPercent(false), + 'testedClassesPercentAsString' => $node->getTestedClassesAndTraitsPercent(), + 'crap' => 'CRAP' + ) + ); + + $items .= $this->renderFunctionItems( + $node->getFunctions(), + $methodItemTemplate + ); + + $items .= $this->renderTraitOrClassItems( + $node->getTraits(), + $template, + $methodItemTemplate + ); + + $items .= $this->renderTraitOrClassItems( + $node->getClasses(), + $template, + $methodItemTemplate + ); + + return $items; + } + + /** + * @param array $items + * @param Text_Template $template + * @param Text_Template $methodItemTemplate + * @return string + */ + protected function renderTraitOrClassItems(array $items, Text_Template $template, Text_Template $methodItemTemplate) + { + if (empty($items)) { + return ''; + } + + $buffer = ''; + + foreach ($items as $name => $item) { + $numMethods = count($item['methods']); + $numTestedMethods = 0; + + foreach ($item['methods'] as $method) { + if ($method['executedLines'] == $method['executableLines']) { + $numTestedMethods++; + } + } + + $buffer .= $this->renderItemTemplate( + $template, + array( + 'name' => $name, + 'numClasses' => 1, + 'numTestedClasses' => $numTestedMethods == $numMethods ? 1 : 0, + 'numMethods' => $numMethods, + 'numTestedMethods' => $numTestedMethods, + 'linesExecutedPercent' => PHP_CodeCoverage_Util::percent( + $item['executedLines'], + $item['executableLines'], + false + ), + 'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent( + $item['executedLines'], + $item['executableLines'], + true + ), + 'numExecutedLines' => $item['executedLines'], + 'numExecutableLines' => $item['executableLines'], + 'testedMethodsPercent' => PHP_CodeCoverage_Util::percent( + $numTestedMethods, + $numMethods, + false + ), + 'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent( + $numTestedMethods, + $numMethods, + true + ), + 'testedClassesPercent' => PHP_CodeCoverage_Util::percent( + $numTestedMethods == $numMethods ? 1 : 0, + 1, + false + ), + 'testedClassesPercentAsString' => PHP_CodeCoverage_Util::percent( + $numTestedMethods == $numMethods ? 1 : 0, + 1, + true + ), + 'crap' => $item['crap'] + ) + ); + + foreach ($item['methods'] as $method) { + $buffer .= $this->renderFunctionOrMethodItem( + $methodItemTemplate, $method, ' ' + ); + } + } + + return $buffer; + } + + /** + * @param array $functions + * @param Text_Template $template + * @return string + */ + protected function renderFunctionItems(array $functions, Text_Template $template) + { + if (empty($functions)) { + return ''; + } + + $buffer = ''; + + foreach ($functions as $function) { + $buffer .= $this->renderFunctionOrMethodItem( + $template, $function + ); + } + + return $buffer; + } + + /** + * @param Text_Template $template + * @return string + */ + protected function renderFunctionOrMethodItem(Text_Template $template, array $item, $indent = '') + { + $numTestedItems = $item['executedLines'] == $item['executableLines'] ? 1 : 0; + + return $this->renderItemTemplate( + $template, + array( + 'name' => sprintf( + '%s%s', + $indent, + $item['startLine'], + htmlspecialchars($item['signature']) + ), + 'numMethods' => 1, + 'numTestedMethods' => $numTestedItems, + 'linesExecutedPercent' => PHP_CodeCoverage_Util::percent( + $item['executedLines'], + $item['executableLines'], + false + ), + 'linesExecutedPercentAsString' => PHP_CodeCoverage_Util::percent( + $item['executedLines'], + $item['executableLines'], + true + ), + 'numExecutedLines' => $item['executedLines'], + 'numExecutableLines' => $item['executableLines'], + 'testedMethodsPercent' => PHP_CodeCoverage_Util::percent( + $numTestedItems, + 1, + false + ), + 'testedMethodsPercentAsString' => PHP_CodeCoverage_Util::percent( + $numTestedItems, + 1, + true + ), + 'crap' => $item['crap'] + ) + ); + } + + /** + * @param PHP_CodeCoverage_Report_Node_File $node + * @return string + */ + protected function renderSource(PHP_CodeCoverage_Report_Node_File $node) + { + $coverageData = $node->getCoverageData(); + $testData = $node->getTestData(); + $codeLines = $this->loadFile($node->getPath()); + $lines = ''; + $i = 1; + + foreach ($codeLines as $line) { + $numTests = ''; + $trClass = ''; + $popoverContent = ''; + $popoverTitle = ''; + + if (array_key_exists($i, $coverageData)) { + $numTests = count($coverageData[$i]); + + if ($coverageData[$i] === null) { + $trClass = ' class="warning"'; + } elseif ($numTests == 0) { + $trClass = ' class="danger"'; + } else { + $trClass = ' class="success popin"'; + $popoverContent = '
    '; + + if ($numTests > 1) { + $popoverTitle = $numTests . ' tests cover line ' . $i; + } else { + $popoverTitle = '1 test covers line ' . $i; + } + + foreach ($coverageData[$i] as $test) { + switch ($testData[$test]) { + case 0: { + $testCSS = ' class="success"'; + } + break; + + case 1: + case 2: { + $testCSS = ' class="warning"'; + } + break; + + case 3: { + $testCSS = ' class="danger"'; + } + break; + + case 4: { + $testCSS = ' class="danger"'; + } + break; + + default: { + $testCSS = ''; + } + } + + $popoverContent .= sprintf( + '%s', + + $testCSS, + htmlspecialchars($test) + ); + } + + $popoverContent .= '
'; + } + } + + if (!empty($popoverTitle)) { + $popover = sprintf( + ' data-title="%s" data-content="%s" data-placement="bottom" data-html="true"', + $popoverTitle, + htmlspecialchars($popoverContent) + ); + } else { + $popover = ''; + } + + $lines .= sprintf( + ' %s' . "\n", + $trClass, + $popover, + $i, + $i, + $i, + $line + ); + + $i++; + } + + return $lines; + } + + /** + * @param string $file + * @return array + */ + protected function loadFile($file) + { + $buffer = file_get_contents($file); + $tokens = token_get_all($buffer); + $result = array(''); + $i = 0; + $stringFlag = false; + $fileEndsWithNewLine = substr($buffer, -1) == "\n"; + + unset($buffer); + + foreach ($tokens as $j => $token) { + if (is_string($token)) { + if ($token === '"' && $tokens[$j - 1] !== '\\') { + $result[$i] .= sprintf( + '%s', + + htmlspecialchars($token) + ); + + $stringFlag = !$stringFlag; + } else { + $result[$i] .= sprintf( + '%s', + + htmlspecialchars($token) + ); + } + + continue; + } + + list ($token, $value) = $token; + + $value = str_replace( + array("\t", ' '), + array('    ', ' '), + htmlspecialchars($value) + ); + + if ($value === "\n") { + $result[++$i] = ''; + } else { + $lines = explode("\n", $value); + + foreach ($lines as $jj => $line) { + $line = trim($line); + + if ($line !== '') { + if ($stringFlag) { + $colour = 'string'; + } else { + switch ($token) { + case T_INLINE_HTML: { + $colour = 'html'; + } + break; + + case T_COMMENT: + case T_DOC_COMMENT: { + $colour = 'comment'; + } + break; + + case T_ABSTRACT: + case T_ARRAY: + case T_AS: + case T_BREAK: + case T_CALLABLE: + case T_CASE: + case T_CATCH: + case T_CLASS: + case T_CLONE: + case T_CONTINUE: + case T_DEFAULT: + case T_ECHO: + case T_ELSE: + case T_ELSEIF: + case T_EMPTY: + case T_ENDDECLARE: + case T_ENDFOR: + case T_ENDFOREACH: + case T_ENDIF: + case T_ENDSWITCH: + case T_ENDWHILE: + case T_EXIT: + case T_EXTENDS: + case T_FINAL: + case T_FINALLY: + case T_FOREACH: + case T_FUNCTION: + case T_GLOBAL: + case T_IF: + case T_IMPLEMENTS: + case T_INCLUDE: + case T_INCLUDE_ONCE: + case T_INSTANCEOF: + case T_INSTEADOF: + case T_INTERFACE: + case T_ISSET: + case T_LOGICAL_AND: + case T_LOGICAL_OR: + case T_LOGICAL_XOR: + case T_NAMESPACE: + case T_NEW: + case T_PRIVATE: + case T_PROTECTED: + case T_PUBLIC: + case T_REQUIRE: + case T_REQUIRE_ONCE: + case T_RETURN: + case T_STATIC: + case T_THROW: + case T_TRAIT: + case T_TRY: + case T_UNSET: + case T_USE: + case T_VAR: + case T_WHILE: + case T_YIELD: { + $colour = 'keyword'; + } + break; + + default: { + $colour = 'default'; + } + } + } + + $result[$i] .= sprintf( + '%s', + + $colour, + $line + ); + } + + if (isset($lines[$jj + 1])) { + $result[++$i] = ''; + } + } + } + } + + if ($fileEndsWithNewLine) { + unset($result[count($result)-1]); + } + + return $result; + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.1.0 + */ + +/** + * Renders a PHP_CodeCoverage_Report_Node_Directory node. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.1.0 + */ +class PHP_CodeCoverage_Report_HTML_Renderer_Directory extends PHP_CodeCoverage_Report_HTML_Renderer +{ + /** + * @param PHP_CodeCoverage_Report_Node_Directory $node + * @param string $file + */ + public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) + { + $template = new Text_Template($this->templatePath . 'directory.html', '{{', '}}'); + + $this->setCommonTemplateVariables($template, $node); + + $items = $this->renderItem($node, true); + + foreach ($node->getDirectories() as $item) { + $items .= $this->renderItem($item); + } + + foreach ($node->getFiles() as $item) { + $items .= $this->renderItem($item); + } + + $template->setVar( + array( + 'id' => $node->getId(), + 'items' => $items + ) + ); + + $template->renderTo($file); + } + + /** + * @param PHP_CodeCoverage_Report_Node $item + * @param boolean $total + * @return string + */ + protected function renderItem(PHP_CodeCoverage_Report_Node $item, $total = false) + { + $data = array( + 'numClasses' => $item->getNumClassesAndTraits(), + 'numTestedClasses' => $item->getNumTestedClassesAndTraits(), + 'numMethods' => $item->getNumMethods(), + 'numTestedMethods' => $item->getNumTestedMethods(), + 'linesExecutedPercent' => $item->getLineExecutedPercent(false), + 'linesExecutedPercentAsString' => $item->getLineExecutedPercent(), + 'numExecutedLines' => $item->getNumExecutedLines(), + 'numExecutableLines' => $item->getNumExecutableLines(), + 'testedMethodsPercent' => $item->getTestedMethodsPercent(false), + 'testedMethodsPercentAsString' => $item->getTestedMethodsPercent(), + 'testedClassesPercent' => $item->getTestedClassesAndTraitsPercent(false), + 'testedClassesPercentAsString' => $item->getTestedClassesAndTraitsPercent() + ); + + if ($total) { + $data['name'] = 'Total'; + } else { + if ($item instanceof PHP_CodeCoverage_Report_Node_Directory) { + $data['name'] = sprintf( + '%s', + $item->getName(), + $item->getName() + ); + + $data['icon'] = ' '; + } else { + $data['name'] = sprintf( + '%s', + $item->getName(), + $item->getName() + ); + + $data['icon'] = ' '; + } + } + + return $this->renderItemTemplate( + new Text_Template($this->templatePath . 'directory_item.html', '{{', '}}'), + $data + ); + } +} +. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Sebastian Bergmann nor the names of his + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since File available since Release 1.1.0 + */ + +/** + * Renders the dashboard for a PHP_CodeCoverage_Report_Node_Directory node. + * + * @category PHP + * @package CodeCoverage + * @author Sebastian Bergmann + * @copyright 2009-2014 Sebastian Bergmann + * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License + * @link http://github.com/sebastianbergmann/php-code-coverage + * @since Class available since Release 1.1.0 + */ +class PHP_CodeCoverage_Report_HTML_Renderer_Dashboard extends PHP_CodeCoverage_Report_HTML_Renderer +{ + /** + * @param PHP_CodeCoverage_Report_Node_Directory $node + * @param string $file + */ + public function render(PHP_CodeCoverage_Report_Node_Directory $node, $file) + { + $classes = $node->getClassesAndTraits(); + $template = new Text_Template( + $this->templatePath . 'dashboard.html', '{{', '}}' + ); + + $this->setCommonTemplateVariables($template, $node); + + $complexity = $this->complexity($classes); + $coverageDistribution = $this->coverageDistribution($classes); + $insufficientCoverage = $this->insufficientCoverage($classes); + $projectRisks = $this->projectRisks($classes); + + $template->setVar( + array( + 'insufficient_coverage_classes' => $insufficientCoverage['class'], + 'insufficient_coverage_methods' => $insufficientCoverage['method'], + 'project_risks_classes' => $projectRisks['class'], + 'project_risks_methods' => $projectRisks['method'], + 'complexity_class' => $complexity['class'], + 'complexity_method' => $complexity['method'], + 'class_coverage_distribution' => $coverageDistribution['class'], + 'method_coverage_distribution' => $coverageDistribution['method'] + ) + ); + + $template->renderTo($file); + } + + /** + * Returns the data for the Class/Method Complexity charts. + * + * @param array $classes + * @return array + */ + protected function complexity(array $classes) + { + $result = array('class' => array(), 'method' => array()); + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($className != '*') { + $methodName = $className . '::' . $methodName; + } + + $result['method'][] = array( + $method['coverage'], + $method['ccn'], + sprintf( + '%s', + $method['link'], + $methodName + ) + ); + } + + $result['class'][] = array( + $class['coverage'], + $class['ccn'], + sprintf( + '%s', + $class['link'], + $className + ) + ); + } + + return array( + 'class' => json_encode($result['class']), + 'method' => json_encode($result['method']) + ); + } + + /** + * Returns the data for the Class / Method Coverage Distribution chart. + * + * @param array $classes + * @return array + */ + protected function coverageDistribution(array $classes) + { + $result = array( + 'class' => array( + '0%' => 0, + '0-10%' => 0, + '10-20%' => 0, + '20-30%' => 0, + '30-40%' => 0, + '40-50%' => 0, + '50-60%' => 0, + '60-70%' => 0, + '70-80%' => 0, + '80-90%' => 0, + '90-100%' => 0, + '100%' => 0 + ), + 'method' => array( + '0%' => 0, + '0-10%' => 0, + '10-20%' => 0, + '20-30%' => 0, + '30-40%' => 0, + '40-50%' => 0, + '50-60%' => 0, + '60-70%' => 0, + '70-80%' => 0, + '80-90%' => 0, + '90-100%' => 0, + '100%' => 0 + ) + ); + + foreach ($classes as $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] == 0) { + $result['method']['0%']++; + } elseif ($method['coverage'] == 100) { + $result['method']['100%']++; + } else { + $key = floor($method['coverage'] / 10) * 10; + $key = $key . '-' . ($key + 10) . '%'; + $result['method'][$key]++; + } + } + + if ($class['coverage'] == 0) { + $result['class']['0%']++; + } elseif ($class['coverage'] == 100) { + $result['class']['100%']++; + } else { + $key = floor($class['coverage'] / 10) * 10; + $key = $key . '-' . ($key + 10) . '%'; + $result['class'][$key]++; + } + } + + return array( + 'class' => json_encode(array_values($result['class'])), + 'method' => json_encode(array_values($result['method'])) + ); + } + + /** + * Returns the classes / methods with insufficient coverage. + * + * @param array $classes + * @return array + */ + protected function insufficientCoverage(array $classes) + { + $leastTestedClasses = array(); + $leastTestedMethods = array(); + $result = array('class' => '', 'method' => ''); + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] < $this->highLowerBound) { + if ($className != '*') { + $key = $className . '::' . $methodName; + } else { + $key = $methodName; + } + + $leastTestedMethods[$key] = $method['coverage']; + } + } + + if ($class['coverage'] < $this->highLowerBound) { + $leastTestedClasses[$className] = $class['coverage']; + } + } + + asort($leastTestedClasses); + asort($leastTestedMethods); + + foreach ($leastTestedClasses as $className => $coverage) { + $result['class'] .= sprintf( + ' %s%d%%' . "\n", + $classes[$className]['link'], + $className, + $coverage + ); + } + + foreach ($leastTestedMethods as $methodName => $coverage) { + list($class, $method) = explode('::', $methodName); + + $result['method'] .= sprintf( + ' %s%d%%' . "\n", + $classes[$class]['methods'][$method]['link'], + $methodName, + $coverage + ); + } + + return $result; + } + + /** + * Returns the project risks according to the CRAP index. + * + * @param array $classes + * @return array + */ + protected function projectRisks(array $classes) + { + $classRisks = array(); + $methodRisks = array(); + $result = array('class' => '', 'method' => ''); + + foreach ($classes as $className => $class) { + foreach ($class['methods'] as $methodName => $method) { + if ($method['coverage'] < $this->highLowerBound && + $method['ccn'] > 1) { + if ($className != '*') { + $key = $className . '::' . $methodName; + } else { + $key = $methodName; + } + + $methodRisks[$key] = $method['crap']; + } + } + + if ($class['coverage'] < $this->highLowerBound && + $class['ccn'] > count($class['methods'])) { + $classRisks[$className] = $class['crap']; + } + } + + arsort($classRisks); + arsort($methodRisks); + + foreach ($classRisks as $className => $crap) { + $result['class'] .= sprintf( + ' %s%d' . "\n", + $classes[$className]['link'], + $className, + $crap + ); + } + + foreach ($methodRisks as $methodName => $crap) { + list($class, $method) = explode('::', $methodName); + + $result['method'] .= sprintf( + ' %s%d' . "\n", + $classes[$class]['methods'][$method]['link'], + $methodName, + $crap + ); + } + + return $result; + } + + protected function getActiveBreadcrumb(PHP_CodeCoverage_Report_Node $node) + { + return sprintf( + '
  • %s
  • ' . "\n" . + '
  • (Dashboard)
  • ' . "\n", + $node->getName() + ); + } +} + + + + + Code Coverage for {{full_path}} + + + + + + +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + + + + + + + + + + +{{items}} + +
     
    Code Coverage
     
    Lines
    Functions and Methods
    Classes and Traits
    + +
    + + + + + + + {{name}} + {{classes_bar}} +
    {{classes_tested_percent}}
    +
    {{classes_number}}
    + {{methods_bar}} +
    {{methods_tested_percent}}
    +
    {{methods_number}}
    + {{crap}} + {{lines_bar}} +
    {{lines_executed_percent}}
    +
    {{lines_number}}
    + + +/*! + +Holder - 2.3.1 - client side image placeholders +(c) 2012-2014 Ivan Malopinsky / http://imsky.co + +Provided under the MIT License. +Commercial use requires attribution. + +*/ +var Holder = Holder || {}; +(function (app, win) { +var system_config = { + use_svg: false, + use_canvas: false, + use_fallback: false +}; +var instance_config = {}; +var preempted = false; +canvas = document.createElement('canvas'); +var dpr = 1, bsr = 1; +var resizable_images = []; + +if (!canvas.getContext) { + system_config.use_fallback = true; +} else { + if (canvas.toDataURL("image/png") + .indexOf("data:image/png") < 0) { + //Android doesn't support data URI + system_config.use_fallback = true; + } else { + var ctx = canvas.getContext("2d"); + } +} + +if(!!document.createElementNS && !!document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect){ + system_config.use_svg = true; + system_config.use_canvas = false; +} + +if(!system_config.use_fallback){ + dpr = window.devicePixelRatio || 1, + bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; +} + +var ratio = dpr / bsr; + +var settings = { + domain: "holder.js", + images: "img", + bgnodes: ".holderjs", + themes: { + "gray": { + background: "#eee", + foreground: "#aaa", + size: 12 + }, + "social": { + background: "#3a5a97", + foreground: "#fff", + size: 12 + }, + "industrial": { + background: "#434A52", + foreground: "#C2F200", + size: 12 + }, + "sky": { + background: "#0D8FDB", + foreground: "#fff", + size: 12 + }, + "vine": { + background: "#39DBAC", + foreground: "#1E292C", + size: 12 + }, + "lava": { + background: "#F8591A", + foreground: "#1C2846", + size: 12 + } + }, + stylesheet: "" +}; +app.flags = { + dimensions: { + regex: /^(\d+)x(\d+)$/, + output: function (val) { + var exec = this.regex.exec(val); + return { + width: +exec[1], + height: +exec[2] + } + } + }, + fluid: { + regex: /^([0-9%]+)x([0-9%]+)$/, + output: function (val) { + var exec = this.regex.exec(val); + return { + width: exec[1], + height: exec[2] + } + } + }, + colors: { + regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i, + output: function (val) { + var exec = this.regex.exec(val); + return { + size: settings.themes.gray.size, + foreground: "#" + exec[2], + background: "#" + exec[1] + } + } + }, + text: { + regex: /text\:(.*)/, + output: function (val) { + return this.regex.exec(val)[1]; + } + }, + font: { + regex: /font\:(.*)/, + output: function (val) { + return this.regex.exec(val)[1]; + } + }, + auto: { + regex: /^auto$/ + }, + textmode: { + regex: /textmode\:(.*)/, + output: function(val){ + return this.regex.exec(val)[1]; + } + } +} + +function text_size(width, height, template) { + height = parseInt(height, 10); + width = parseInt(width, 10); + var bigSide = Math.max(height, width) + var smallSide = Math.min(height, width) + var scale = 1 / 12; + var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale); + return { + height: Math.round(Math.max(template.size, newHeight)) + } +} + +var svg_el = (function(){ + //Prevent IE <9 from initializing SVG renderer + if(!window.XMLSerializer) return; + var serializer = new XMLSerializer(); + var svg_ns = "http://www.w3.org/2000/svg" + var svg = document.createElementNS(svg_ns, "svg"); + //IE throws an exception if this is set and Chrome requires it to be set + if(svg.webkitMatchesSelector){ + svg.setAttribute("xmlns", "http://www.w3.org/2000/svg") + } + var bg_el = document.createElementNS(svg_ns, "rect") + var text_el = document.createElementNS(svg_ns, "text") + var textnode_el = document.createTextNode(null) + text_el.setAttribute("text-anchor", "middle") + text_el.appendChild(textnode_el) + svg.appendChild(bg_el) + svg.appendChild(text_el) + + return function(props){ + svg.setAttribute("width",props.width); + svg.setAttribute("height", props.height); + bg_el.setAttribute("width", props.width); + bg_el.setAttribute("height", props.height); + bg_el.setAttribute("fill", props.template.background); + text_el.setAttribute("x", props.width/2) + text_el.setAttribute("y", props.height/2) + textnode_el.nodeValue=props.text + text_el.setAttribute("style", css_properties({ + "fill": props.template.foreground, + "font-weight": "bold", + "font-size": props.text_height+"px", + "font-family":props.font, + "dominant-baseline":"central" + })) + return serializer.serializeToString(svg) + } +})() + +function css_properties(props){ + var ret = []; + for(p in props){ + if(props.hasOwnProperty(p)){ + ret.push(p+":"+props[p]) + } + } + return ret.join(";") +} + +function draw_canvas(args) { + var ctx = args.ctx, + dimensions = args.dimensions, + template = args.template, + ratio = args.ratio, + holder = args.holder, + literal = holder.textmode == "literal", + exact = holder.textmode == "exact"; + + var ts = text_size(dimensions.width, dimensions.height, template); + var text_height = ts.height; + var width = dimensions.width * ratio, + height = dimensions.height * ratio; + var font = template.font ? template.font : "Arial,Helvetica,sans-serif"; + canvas.width = width; + canvas.height = height; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillStyle = template.background; + ctx.fillRect(0, 0, width, height); + ctx.fillStyle = template.foreground; + ctx.font = "bold " + text_height + "px " + font; + var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); + if (literal) { + var dimensions = holder.dimensions; + text = dimensions.width + "x" + dimensions.height; + } + else if(exact && holder.exact_dimensions){ + var dimensions = holder.exact_dimensions; + text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); + } + var text_width = ctx.measureText(text).width; + if (text_width / width >= 0.75) { + text_height = Math.floor(text_height * 0.75 * (width / text_width)); + } + //Resetting font size if necessary + ctx.font = "bold " + (text_height * ratio) + "px " + font; + ctx.fillText(text, (width / 2), (height / 2), width); + return canvas.toDataURL("image/png"); +} + +function draw_svg(args){ + var dimensions = args.dimensions, + template = args.template, + holder = args.holder, + literal = holder.textmode == "literal", + exact = holder.textmode == "exact"; + + var ts = text_size(dimensions.width, dimensions.height, template); + var text_height = ts.height; + var width = dimensions.width, + height = dimensions.height; + + var font = template.font ? template.font : "Arial,Helvetica,sans-serif"; + var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); + + if (literal) { + var dimensions = holder.dimensions; + text = dimensions.width + "x" + dimensions.height; + } + else if(exact && holder.exact_dimensions){ + var dimensions = holder.exact_dimensions; + text = (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); + } + var string = svg_el({ + text: text, + width:width, + height:height, + text_height:text_height, + font:font, + template:template + }) + return "data:image/svg+xml;base64,"+btoa(string); +} + +function draw(args) { + if(instance_config.use_canvas && !instance_config.use_svg){ + return draw_canvas(args); + } + else{ + return draw_svg(args); + } +} + +function render(mode, el, holder, src) { + var dimensions = holder.dimensions, + theme = holder.theme, + text = holder.text ? decodeURIComponent(holder.text) : holder.text; + var dimensions_caption = dimensions.width + "x" + dimensions.height; + theme = (text ? extend(theme, { + text: text + }) : theme); + theme = (holder.font ? extend(theme, { + font: holder.font + }) : theme); + el.setAttribute("data-src", src); + holder.theme = theme; + el.holder_data = holder; + + if (mode == "image") { + el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); + if (instance_config.use_fallback || !holder.auto) { + el.style.width = dimensions.width + "px"; + el.style.height = dimensions.height + "px"; + } + if (instance_config.use_fallback) { + el.style.backgroundColor = theme.background; + } else { + el.setAttribute("src", draw({ctx: ctx, dimensions: dimensions, template: theme, ratio:ratio, holder: holder})); + + if(holder.textmode && holder.textmode == "exact"){ + resizable_images.push(el); + resizable_update(el); + } + + } + } else if (mode == "background") { + if (!instance_config.use_fallback) { + el.style.backgroundImage = "url(" + draw({ctx:ctx, dimensions: dimensions, template: theme, ratio: ratio, holder: holder}) + ")"; + el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px"; + } + } else if (mode == "fluid") { + el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); + if (dimensions.height.slice(-1) == "%") { + el.style.height = dimensions.height + } else if(holder.auto == null || !holder.auto){ + el.style.height = dimensions.height + "px" + } + if (dimensions.width.slice(-1) == "%") { + el.style.width = dimensions.width + } else if(holder.auto == null || !holder.auto){ + el.style.width = dimensions.width + "px" + } + if (el.style.display == "inline" || el.style.display === "" || el.style.display == "none") { + el.style.display = "block"; + } + + set_initial_dimensions(el) + + if (instance_config.use_fallback) { + el.style.backgroundColor = theme.background; + } else { + resizable_images.push(el); + resizable_update(el); + } + } +} + +function dimension_check(el, callback) { + var dimensions = { + height: el.clientHeight, + width: el.clientWidth + }; + if (!dimensions.height && !dimensions.width) { + el.setAttribute("data-holder-invisible", true) + callback.call(this, el) + } + else{ + el.removeAttribute("data-holder-invisible") + return dimensions; + } +} + +function set_initial_dimensions(el){ + if(el.holder_data){ + var dimensions = dimension_check(el, app.invisible_error_fn( set_initial_dimensions)) + if(dimensions){ + var holder = el.holder_data; + holder.initial_dimensions = dimensions; + holder.fluid_data = { + fluid_height: holder.dimensions.height.slice(-1) == "%", + fluid_width: holder.dimensions.width.slice(-1) == "%", + mode: null + } + if(holder.fluid_data.fluid_width && !holder.fluid_data.fluid_height){ + holder.fluid_data.mode = "width" + holder.fluid_data.ratio = holder.initial_dimensions.width / parseFloat(holder.dimensions.height) + } + else if(!holder.fluid_data.fluid_width && holder.fluid_data.fluid_height){ + holder.fluid_data.mode = "height"; + holder.fluid_data.ratio = parseFloat(holder.dimensions.width) / holder.initial_dimensions.height + } + } + } +} + +function resizable_update(element) { + var images; + if (element.nodeType == null) { + images = resizable_images; + } else { + images = [element] + } + for (var i in images) { + if (!images.hasOwnProperty(i)) { + continue; + } + var el = images[i] + if (el.holder_data) { + var holder = el.holder_data; + var dimensions = dimension_check(el, app.invisible_error_fn( resizable_update)) + if(dimensions){ + if(holder.fluid){ + if(holder.auto){ + switch(holder.fluid_data.mode){ + case "width": + dimensions.height = dimensions.width / holder.fluid_data.ratio; + break; + case "height": + dimensions.width = dimensions.height * holder.fluid_data.ratio; + break; + } + } + el.setAttribute("src", draw({ + ctx: ctx, + dimensions: dimensions, + template: holder.theme, + ratio: ratio, + holder: holder + })) + } + if(holder.textmode && holder.textmode == "exact"){ + holder.exact_dimensions = dimensions; + el.setAttribute("src", draw({ + ctx: ctx, + dimensions: holder.dimensions, + template: holder.theme, + ratio: ratio, + holder: holder + })) + } + } + } + } +} + +function parse_flags(flags, options) { + var ret = { + theme: extend(settings.themes.gray, {}) + }; + var render = false; + for (var fl = flags.length, j = 0; j < fl; j++) { + var flag = flags[j]; + if (app.flags.dimensions.match(flag)) { + render = true; + ret.dimensions = app.flags.dimensions.output(flag); + } else if (app.flags.fluid.match(flag)) { + render = true; + ret.dimensions = app.flags.fluid.output(flag); + ret.fluid = true; + } else if (app.flags.textmode.match(flag)) { + ret.textmode = app.flags.textmode.output(flag) + } else if (app.flags.colors.match(flag)) { + ret.theme = app.flags.colors.output(flag); + } else if (options.themes[flag]) { + //If a theme is specified, it will override custom colors + if(options.themes.hasOwnProperty(flag)){ + ret.theme = extend(options.themes[flag], {}); + } + } else if (app.flags.font.match(flag)) { + ret.font = app.flags.font.output(flag); + } else if (app.flags.auto.match(flag)) { + ret.auto = true; + } else if (app.flags.text.match(flag)) { + ret.text = app.flags.text.output(flag); + } + } + return render ? ret : false; +} + +for (var flag in app.flags) { + if (!app.flags.hasOwnProperty(flag)) continue; + app.flags[flag].match = function (val) { + return val.match(this.regex) + } +} + +app.invisible_error_fn = function(fn){ + return function(el){ + if(el.hasAttribute("data-holder-invisible")){ + throw new Error("Holder: invisible placeholder") + } + } +} + +app.add_theme = function (name, theme) { + name != null && theme != null && (settings.themes[name] = theme); + return app; +}; + +app.add_image = function (src, el) { + var node = selector(el); + if (node.length) { + for (var i = 0, l = node.length; i < l; i++) { + var img = document.createElement("img") + img.setAttribute("data-src", src); + node[i].appendChild(img); + } + } + return app; +}; + +app.run = function (o) { + instance_config = extend({}, system_config) + preempted = true; + + var options = extend(settings, o), + images = [], + imageNodes = [], + bgnodes = []; + + if(options.use_canvas != null && options.use_canvas){ + instance_config.use_canvas = true; + instance_config.use_svg = false; + } + + if (typeof (options.images) == "string") { + imageNodes = selector(options.images); + } else if (window.NodeList && options.images instanceof window.NodeList) { + imageNodes = options.images; + } else if (window.Node && options.images instanceof window.Node) { + imageNodes = [options.images]; + } else if(window.HTMLCollection && options.images instanceof window.HTMLCollection){ + imageNodes = options.images + } + + if (typeof (options.bgnodes) == "string") { + bgnodes = selector(options.bgnodes); + } else if (window.NodeList && options.elements instanceof window.NodeList) { + bgnodes = options.bgnodes; + } else if (window.Node && options.bgnodes instanceof window.Node) { + bgnodes = [options.bgnodes]; + } + for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]); + var holdercss = document.getElementById("holderjs-style"); + if (!holdercss) { + holdercss = document.createElement("style"); + holdercss.setAttribute("id", "holderjs-style"); + holdercss.type = "text/css"; + document.getElementsByTagName("head")[0].appendChild(holdercss); + } + if (!options.nocss) { + if (holdercss.styleSheet) { + holdercss.styleSheet.cssText += options.stylesheet; + } else { + holdercss.appendChild(document.createTextNode(options.stylesheet)); + } + } + var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)"); + for (var l = bgnodes.length, i = 0; i < l; i++) { + var src = window.getComputedStyle(bgnodes[i], null) + .getPropertyValue("background-image"); + var flags = src.match(cssregex); + var bgsrc = bgnodes[i].getAttribute("data-background-src"); + if (flags) { + var holder = parse_flags(flags[1].split("/"), options); + if (holder) { + render("background", bgnodes[i], holder, src); + } + } else if (bgsrc != null) { + var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1) + .split("/"), options); + if (holder) { + render("background", bgnodes[i], holder, src); + } + } + } + for (l = images.length, i = 0; i < l; i++) { + var attr_data_src, attr_src; + attr_src = attr_data_src = src = null; + try { + attr_src = images[i].getAttribute("src"); + attr_datasrc = images[i].getAttribute("data-src"); + } catch (e) {} + if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) { + src = attr_src; + } else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) { + src = attr_datasrc; + } + if (src) { + var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1).split("/"), options); + if (holder) { + if (holder.fluid) { + render("fluid", images[i], holder, src) + } else { + render("image", images[i], holder, src); + } + } + } + } + return app; +}; + +contentLoaded(win, function () { + if (window.addEventListener) { + window.addEventListener("resize", resizable_update, false); + window.addEventListener("orientationchange", resizable_update, false); + } else { + window.attachEvent("onresize", resizable_update) + } + preempted || app.run({}); +}); +if (typeof define === "function" && define.amd) { + define([], function () { + return app; + }); +} + +//github.com/davidchambers/Base64.js +(function(){function t(t){this.message=t}var e="undefined"!=typeof exports?exports:this,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";t.prototype=Error(),t.prototype.name="InvalidCharacterError",e.btoa||(e.btoa=function(e){for(var o,n,a=0,i=r,c="";e.charAt(0|a)||(i="=",a%1);c+=i.charAt(63&o>>8-8*(a%1))){if(n=e.charCodeAt(a+=.75),n>255)throw new t("'btoa' failed");o=o<<8|n}return c}),e.atob||(e.atob=function(e){if(e=e.replace(/=+$/,""),1==e.length%4)throw new t("'atob' failed");for(var o,n,a=0,i=0,c="";n=e.charAt(i++);~n&&(o=a%4?64*o+n:n,a++%4)?c+=String.fromCharCode(255&o>>(6&-2*a)):0)n=r.indexOf(n);return c})})(); + +//getElementsByClassName polyfill +document.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll("."+e);if(t.evaluate){r=".//*[contains(concat(' ', @class, ' '), ' "+e+" ')]",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName("*"),r=new RegExp("(^|\\s)"+e+"(\\s|$)");for(i=0;i #mq-test-1 { width: 42px; }',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;barticle,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}"; +c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| +"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f); +if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d1)while(op||r>d||d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined||a){if(l&&d3.event.relatedTarget&&d3.event.relatedTarget.ownerSVGElement===undefined&&d3.event.relatedTarget.className.match(t.nvPointerEventsClass))return;u.elementMouseout({mouseX:n,mouseY:r}),c.renderGuideLine(null);return}var f=s.invert(n);u.elementMousemove({mouseX:n,mouseY:r,pointXValue:f}),d3.event.type==="dblclick"&&u.elementDblclick({mouseX:n,mouseY:r,pointXValue:f})}var h=d3.select(this),p=n||960,d=r||400,v=h.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([o]),m=v.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");m.append("g").attr("class","nv-interactiveGuideLine");if(!f)return;f.on("mousemove",g,!0).on("mouseout",g,!0).on("dblclick",g),c.renderGuideLine=function(t){if(!a)return;var n=v.select(".nv-interactiveGuideLine").selectAll("line").data(t!=null?[e.utils.NaNtoZero(t)]:[],String);n.enter().append("line").attr("class","nv-guideline").attr("x1",function(e){return e}).attr("x2",function(e){return e}).attr("y1",d).attr("y2",0),n.exit().remove()}})}var t=e.models.tooltip(),n=null,r=null,i={left:0,top:0},s=d3.scale.linear(),o=d3.scale.linear(),u=d3.dispatch("elementMousemove","elementMouseout","elementDblclick"),a=!0,f=null,l=navigator.userAgent.indexOf("MSIE")!==-1;return c.dispatch=u,c.tooltip=t,c.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.left=typeof e.left!="undefined"?e.left:i.left,c):i},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.xScale=function(e){return arguments.length?(s=e,c):s},c.showGuideLine=function(e){return arguments.length?(a=e,c):a},c.svgContainer=function(e){return arguments.length?(f=e,c):f},c},e.interactiveBisect=function(e,t,n){"use strict";if(!e instanceof Array)return null;typeof n!="function"&&(n=function(e,t){return e.x});var r=d3.bisector(n).left,i=d3.max([0,r(e,t)-1]),s=n(e[i],i);typeof s=="undefined"&&(s=i);if(s===t)return i;var o=d3.min([i+1,e.length-1]),u=n(e[o],o);return typeof u=="undefined"&&(u=o),Math.abs(u-t)>=Math.abs(s-t)?i:o},e.nearestValueIndex=function(e,t,n){"use strict";var r=Infinity,i=null;return e.forEach(function(e,s){var o=Math.abs(t-e);o<=r&&oT.height?0:x}v.top=Math.abs(x-S.top),v.left=Math.abs(E.left-S.left)}t+=a.offsetLeft+v.left-2*a.scrollLeft,u+=a.offsetTop+v.top-2*a.scrollTop}return s&&s>0&&(u=Math.floor(u/s)*s),e.tooltip.calcTooltipPosition([t,u],r,i,h),w}var t=null,n=null,r="w",i=50,s=25,o=null,u=null,a=null,f=null,l={left:null,top:null},c=!0,h="nvtooltip-"+Math.floor(Math.random()*1e5),p="nv-pointer-events-none",d=function(e,t){return e},v=function(e){return e},m=function(e){if(t!=null)return t;if(e==null)return"";var n=d3.select(document.createElement("table")),r=n.selectAll("thead").data([e]).enter().append("thead");r.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(v(e.value));var i=n.selectAll("tbody").data([e]).enter().append("tbody"),s=i.selectAll("tr").data(function(e){return e.series}).enter().append("tr").classed("highlight",function(e){return e.highlight});s.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(e){return e.color}),s.append("td").classed("key",!0).html(function(e){return e.key}),s.append("td").classed("value",!0).html(function(e,t){return d(e.value,t)}),s.selectAll("td").each(function(e){if(e.highlight){var t=d3.scale.linear().domain([0,1]).range(["#fff",e.color]),n=.6;d3.select(this).style("border-bottom-color",t(n)).style("border-top-color",t(n))}});var o=n.node().outerHTML;return e.footer!==undefined&&(o+=""),o},g=function(e){return e&&e.series&&e.series.length>0?!0:!1};return w.nvPointerEventsClass=p,w.content=function(e){return arguments.length?(t=e,w):t},w.tooltipElem=function(){return f},w.contentGenerator=function(e){return arguments.length?(typeof e=="function"&&(m=e),w):m},w.data=function(e){return arguments.length?(n=e,w):n},w.gravity=function(e){return arguments.length?(r=e,w):r},w.distance=function(e){return arguments.length?(i=e,w):i},w.snapDistance=function(e){return arguments.length?(s=e,w):s},w.classes=function(e){return arguments.length?(u=e,w):u},w.chartContainer=function(e){return arguments.length?(a=e,w):a},w.position=function(e){return arguments.length?(l.left=typeof e.left!="undefined"?e.left:l.left,l.top=typeof e.top!="undefined"?e.top:l.top,w):l},w.fixedTop=function(e){return arguments.length?(o=e,w):o},w.enabled=function(e){return arguments.length?(c=e,w):c},w.valueFormatter=function(e){return arguments.length?(typeof e=="function"&&(d=e),w):d},w.headerFormatter=function(e){return arguments.length?(typeof e=="function"&&(v=e),w):v},w.id=function(){return h},w},e.tooltip.show=function(t,n,r,i,s,o){var u=document.createElement("div");u.className="nvtooltip "+(o?o:"xy-tooltip");var a=s;if(!s||s.tagName.match(/g|svg/i))a=document.getElementsByTagName("body")[0];u.style.left=0,u.style.top=0,u.style.opacity=0,u.innerHTML=n,a.appendChild(u),s&&(t[0]=t[0]-s.scrollLeft,t[1]=t[1]-s.scrollTop),e.tooltip.calcTooltipPosition(t,r,i,u)},e.tooltip.findFirstNonSVGParent=function(e){while(e.tagName.match(/^g|svg$/i)!==null)e=e.parentNode;return e},e.tooltip.findTotalOffsetTop=function(e,t){var n=t;do isNaN(e.offsetTop)||(n+=e.offsetTop);while(e=e.offsetParent);return n},e.tooltip.findTotalOffsetLeft=function(e,t){var n=t;do isNaN(e.offsetLeft)||(n+=e.offsetLeft);while(e=e.offsetParent);return n},e.tooltip.calcTooltipPosition=function(t,n,r,i){var s=parseInt(i.offsetHeight),o=parseInt(i.offsetWidth),u=e.utils.windowSize().width,a=e.utils.windowSize().height,f=window.pageYOffset,l=window.pageXOffset,c,h;a=window.innerWidth>=document.body.scrollWidth?a:a-16,u=window.innerHeight>=document.body.scrollHeight?u:u-16,n=n||"s",r=r||20;var p=function(t){return e.tooltip.findTotalOffsetTop(t,h)},d=function(t){return e.tooltip.findTotalOffsetLeft(t,c)};switch(n){case"e":c=t[0]-o-r,h=t[1]-s/2;var v=d(i),m=p(i);vl?t[0]+r:l-v+c),mf+a&&(h=f+a-m+h-s);break;case"w":c=t[0]+r,h=t[1]-s/2;var v=d(i),m=p(i);v+o>u&&(c=t[0]-o-r),mf+a&&(h=f+a-m+h-s);break;case"n":c=t[0]-o/2-5,h=t[1]+r;var v=d(i),m=p(i);vu&&(c=c-o/2+5),m+s>f+a&&(h=f+a-m+h-s);break;case"s":c=t[0]-o/2,h=t[1]-s-r;var v=d(i),m=p(i);vu&&(c=c-o/2+5),f>m&&(h=f);break;case"none":c=t[0],h=t[1]-r;var v=d(i),m=p(i)}return i.style.left=c+"px",i.style.top=h+"px",i.style.opacity=1,i.style.position="absolute",i},e.tooltip.cleanup=function(){var e=document.getElementsByClassName("nvtooltip"),t=[];while(e.length)t.push(e[0]),e[0].style.transitionDelay="0 !important",e[0].style.opacity=0,e[0].className="nvtooltip-pending-removal";setTimeout(function(){while(t.length){var e=t.pop();e.parentNode.removeChild(e)}},500)}}(),e.utils.windowSize=function(){var e={width:640,height:480};return document.body&&document.body.offsetWidth&&(e.width=document.body.offsetWidth,e.height=document.body.offsetHeight),document.compatMode=="CSS1Compat"&&document.documentElement&&document.documentElement.offsetWidth&&(e.width=document.documentElement.offsetWidth,e.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(e.width=window.innerWidth,e.height=window.innerHeight),e},e.utils.windowResize=function(e){if(e===undefined)return;var t=window.onresize;window.onresize=function(n){typeof t=="function"&&t(n),e(n)}},e.utils.getColor=function(t){return arguments.length?Object.prototype.toString.call(t)==="[object Array]"?function(e,n){return e.color||t[n%t.length]}:t:e.utils.defaultColor()},e.utils.defaultColor=function(){var e=d3.scale.category20().range();return function(t,n){return t.color||e[n%e.length]}},e.utils.customTheme=function(e,t,n){t=t||function(e){return e.key},n=n||d3.scale.category20().range();var r=n.length;return function(i,s){var o=t(i);return r||(r=n.length),typeof e[o]!="undefined"?typeof e[o]=="function"?e[o]():e[o]:n[--r]}},e.utils.pjax=function(t,n){function r(r){d3.html(r,function(r){var i=d3.select(n).node();i.parentNode.replaceChild(d3.select(r).select(n).node(),i),e.utils.pjax(t,n)})}d3.selectAll(t).on("click",function(){history.pushState(this.href,this.textContent,this.href),r(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&r(d3.event.state)})},e.utils.calcApproxTextWidth=function(e){if(typeof e.style=="function"&&typeof e.text=="function"){var t=parseInt(e.style("font-size").replace("px","")),n=e.text().length;return n*t*.5}return 0},e.utils.NaNtoZero=function(e){return typeof e!="number"||isNaN(e)||e===null||e===Infinity?0:e},e.utils.optionsFunc=function(e){return e&&d3.map(e).forEach(function(e,t){typeof this[e]=="function"&&this[e](t)}.bind(this)),this},e.models.axis=function(){"use strict";function m(e){return e.each(function(e){var i=d3.select(this),m=i.selectAll("g.nv-wrap.nv-axis").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),y=g.append("g"),b=m.select("g");p!==null?t.ticks(p):(t.orient()=="top"||t.orient()=="bottom")&&t.ticks(Math.abs(s.range()[1]-s.range()[0])/100),b.transition().call(t),v=v||t.scale();var w=t.tickFormat();w==null&&(w=v.tickFormat());var E=b.selectAll("text.nv-axislabel").data([o||null]);E.exit().remove();switch(t.orient()){case"top":E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",0).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+s(e)+",0)"}).select("text").attr("dy","-0.5em").attr("y",-t.tickPadding()).attr("text-anchor","middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.transition().attr("transform",function(e,t){return"translate("+s.range()[t]+",0)"})}break;case"bottom":var T=36,N=30,C=b.selectAll("g").select("text");if(f%360){C.each(function(e,t){var n=this.getBBox().width;n>N&&(N=n)});var k=Math.abs(Math.sin(f*Math.PI/180)),T=(k?k*N:N)+30;C.attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f%360>0?"start":"end")}E.enter().append("text").attr("class","nv-axislabel");var S=s.range().length==2?s.range()[1]:s.range()[s.range().length-1]+(s.range()[1]-s.range()[0]);E.attr("text-anchor","middle").attr("y",T).attr("x",S/2);if(u){var x=m.selectAll("g.nv-axisMaxMin").data([s.domain()[0],s.domain()[s.domain().length-1]]);x.enter().append("g").attr("class","nv-axisMaxMin").append("text"),x.exit().remove(),x.attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",t.tickPadding()).attr("transform",function(e,t,n){return"rotate("+f+" 0,0)"}).style("text-anchor",f?f%360>0?"start":"end":"middle").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.transition().attr("transform",function(e,t){return"translate("+(s(e)+(h?s.rangeBand()/2:0))+",0)"})}c&&C.attr("transform",function(e,t){return"translate(0,"+(t%2==0?"0":"12")+")"});break;case"right":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(n.right,r)+12:-10).attr("x",l?s.range()[0]/2:t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+s(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",t.tickPadding()).style("text-anchor","start").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.transition().attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}break;case"left":E.enter().append("text").attr("class","nv-axislabel"),E.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(n.left,r)+d:-10).attr("x",l?-s.range()[0]/2:-t.tickPadding());if(u){var x=m.selectAll("g.nv-axisMaxMin").data(s.domain());x.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(e,t){return"translate(0,"+v(e)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-t.tickPadding()).attr("text-anchor","end").text(function(e,t){var n=w(e);return(""+n).match("NaN")?"":n}),x.transition().attr("transform",function(e,t){return"translate(0,"+s.range()[t]+")"}).select("text").style("opacity",1)}}E.text(function(e){return e}),u&&(t.orient()==="left"||t.orient()==="right")&&(b.selectAll("g").each(function(e,t){d3.select(this).select("text").attr("opacity",1);if(s(e)s.range()[0]-10)(e>1e-10||e<-1e-10)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0)}),s.domain()[0]==s.domain()[1]&&s.domain()[0]==0&&m.selectAll("g.nv-axisMaxMin").style("opacity",function(e,t){return t?0:1}));if(u&&(t.orient()==="top"||t.orient()==="bottom")){var L=[];m.selectAll("g.nv-axisMaxMin").each(function(e,t){try{t?L.push(s(e)-this.getBBox().width-4):L.push(s(e)+this.getBBox().width+4)}catch(n){t?L.push(s(e)-4):L.push(s(e)+4)}}),b.selectAll("g").each(function(e,t){if(s(e)L[1])e>1e-10||e<-1e-10?d3.select(this).remove():d3.select(this).select("text").remove()})}a&&b.selectAll(".tick").filter(function(e){return!parseFloat(Math.round(e.__data__*1e5)/1e6)&&e.__data__!==undefined}).classed("zero",!0),v=s.copy()}),m}var t=d3.svg.axis(),n={top:0,right:0,bottom:0,left:0},r=75,i=60,s=d3.scale.linear(),o=null,u=!0,a=!0,f=0,l=!0,c=!1,h=!1,p=null,d=12;t.scale(s).orient("bottom").tickFormat(function(e){return e});var v;return m.axis=t,d3.rebind(m,t,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.ticks=function(e){return arguments.length?(p=e,m):p},m.height=function(e){return arguments.length?(i=e,m):i},m.axisLabel=function(e){return arguments.length?(o=e,m):o},m.showMaxMin=function(e){return arguments.length?(u=e,m):u},m.highlightZero=function(e){return arguments.length?(a=e,m):a},m.scale=function(e){return arguments.length?(s=e,t.scale(s),h=typeof s.rangeBands=="function",d3.rebind(m,s,"domain","range","rangeBand","rangeBands"),m):s},m.rotateYLabel=function(e){return arguments.length?(l=e,m):l},m.rotateLabels=function(e){return arguments.length?(f=e,m):f},m.staggerLabels=function(e){return arguments.length?(c=e,m):c},m.axisLabelDistance=function(e){return arguments.length?(d=e,m):d},m},e.models.bullet=function(){"use strict";function m(e){return e.each(function(e,n){var p=c-t.left-t.right,m=h-t.top-t.bottom,g=d3.select(this),y=i.call(this,e,n).slice().sort(d3.descending),b=s.call(this,e,n).slice().sort(d3.descending),w=o.call(this,e,n).slice().sort(d3.descending),E=u.call(this,e,n).slice(),S=a.call(this,e,n).slice(),x=f.call(this,e,n).slice(),T=d3.scale.linear().domain(d3.extent(d3.merge([l,y]))).range(r?[p,0]:[0,p]),N=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(T.range());this.__chart__=T;var C=d3.min(y),k=d3.max(y),L=y[1],A=g.selectAll("g.nv-wrap.nv-bullet").data([e]),O=A.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),M=O.append("g"),_=A.select("g");M.append("rect").attr("class","nv-range nv-rangeMax"),M.append("rect").attr("class","nv-range nv-rangeAvg"),M.append("rect").attr("class","nv-range nv-rangeMin"),M.append("rect").attr("class","nv-measure"),M.append("path").attr("class","nv-markerTriangle"),A.attr("transform","translate("+t.left+","+t.top+")");var D=function(e){return Math.abs(N(e)-N(0))},P=function(e){return Math.abs(T(e)-T(0))},H=function(e){return e<0?N(e):N(0)},B=function(e){return e<0?T(e):T(0)};_.select("rect.nv-rangeMax").attr("height",m).attr("width",P(k>0?k:C)).attr("x",B(k>0?k:C)).datum(k>0?k:C),_.select("rect.nv-rangeAvg").attr("height",m).attr("width",P(L)).attr("x",B(L)).datum(L),_.select("rect.nv-rangeMin").attr("height",m).attr("width",P(k)).attr("x",B(k)).attr("width",P(k>0?C:k)).attr("x",B(k>0?C:k)).datum(k>0?C:k),_.select("rect.nv-measure").style("fill",d).attr("height",m/3).attr("y",m/3).attr("width",w<0?T(0)-T(w[0]):T(w[0])-T(0)).attr("x",B(w)).on("mouseover",function(){v.elementMouseover({value:w[0],label:x[0]||"Current",pos:[T(w[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:w[0],label:x[0]||"Current"})});var j=m/6;b[0]?_.selectAll("path.nv-markerTriangle").attr("transform",function(e){return"translate("+T(b[0])+","+m/2+")"}).attr("d","M0,"+j+"L"+j+","+ -j+" "+ -j+","+ -j+"Z").on("mouseover",function(){v.elementMouseover({value:b[0],label:S[0]||"Previous",pos:[T(b[0]),m/2]})}).on("mouseout",function(){v.elementMouseout({value:b[0],label:S[0]||"Previous"})}):_.selectAll("path.nv-markerTriangle").remove(),A.selectAll(".nv-range").on("mouseover",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseover({value:e,label:n,pos:[T(e),m/2]})}).on("mouseout",function(e,t){var n=E[t]||(t?t==1?"Mean":"Minimum":"Maximum");v.elementMouseout({value:e,label:n})})}),m}var t={top:0,right:0,bottom:0,left:0},n="left",r=!1,i=function(e){return e.ranges},s=function(e){return e.markers},o=function(e){return e.measures},u=function(e){return e.rangeLabels?e.rangeLabels:[]},a=function(e){return e.markerLabels?e.markerLabels:[]},f=function(e){return e.measureLabels?e.measureLabels:[]},l=[0],c=380,h=30,p=null,d=e.utils.getColor(["#1f77b4"]),v=d3.dispatch("elementMouseover","elementMouseout");return m.dispatch=v,m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(i=e,m):i},m.markers=function(e){return arguments.length?(s=e,m):s},m.measures=function(e){return arguments.length?(o=e,m):o},m.forceX=function(e){return arguments.length?(l=e,m):l},m.width=function(e){return arguments.length?(c=e,m):c},m.height=function(e){return arguments.length?(h=e,m):h},m.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,m):t},m.tickFormat=function(e){return arguments.length?(p=e,m):p},m.color=function(t){return arguments.length?(d=e.utils.getColor(t),m):d},m},e.models.bulletChart=function(){"use strict";function m(e){return e.each(function(n,h){var g=d3.select(this),y=(a||parseInt(g.style("width"))||960)-i.left-i.right,b=f-i.top-i.bottom,w=this;m.update=function(){m(e)},m.container=this;if(!n||!s.call(this,n,h)){var E=g.selectAll(".nv-noData").data([p]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",i.left+y/2).attr("y",18+i.top+b/2).text(function(e){return e}),m}g.selectAll(".nv-noData").remove();var S=s.call(this,n,h).slice().sort(d3.descending),x=o.call(this,n,h).slice().sort(d3.descending),T=u.call(this,n,h).slice().sort(d3.descending),N=g.selectAll("g.nv-wrap.nv-bulletChart").data([n]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-bulletWrap"),k.append("g").attr("class","nv-titles"),N.attr("transform","translate("+i.left+","+i.top+")");var A=d3.scale.linear().domain([0,Math.max(S[0],x[0],T[0])]).range(r?[y,0]:[0,y]),O=this.__chart__||d3.scale.linear().domain([0,Infinity]).range(A.range());this.__chart__=A;var M=function(e){return Math.abs(O(e)-O(0))},_=function(e){return Math.abs(A(e)-A(0))},D=k.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(f-i.top-i.bottom)/2+")");D.append("text").attr("class","nv-title").text(function(e){return e.title}),D.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(e){return e.subtitle}),t.width(y).height(b);var P=L.select(".nv-bulletWrap");d3.transition(P).call(t);var H=l||A.tickFormat(y/100),B=L.selectAll("g.nv-tick").data(A.ticks(y/50),function(e){return this.textContent||H(e)}),j=B.enter().append("g").attr("class","nv-tick").attr("transform",function(e){return"translate("+O(e)+",0)"}).style("opacity",1e-6);j.append("line").attr("y1",b).attr("y2",b*7/6),j.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",b*7/6).text(H);var F=d3.transition(B).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1);F.select("line").attr("y1",b).attr("y2",b*7/6),F.select("text").attr("y",b*7/6),d3.transition(B.exit()).attr("transform",function(e){return"translate("+A(e)+",0)"}).style("opacity",1e-6).remove(),d.on("tooltipShow",function(e){e.key=n.title,c&&v(e,w.parentNode)})}),d3.timer.flush(),m}var t=e.models.bullet(),n="left",r=!1,i={top:5,right:40,bottom:20,left:120},s=function(e){return e.ranges},o=function(e){return e.markers},u=function(e){return e.measures},a=null,f=55,l=null,c=!0,h=function(e,t,n,r,i){return"

    "+t+"

    "+"

    "+n+"

    "},p="No Data Available.",d=d3.dispatch("tooltipShow","tooltipHide"),v=function(t,n){var r=t.pos[0]+(n.offsetLeft||0)+i.left,s=t.pos[1]+(n.offsetTop||0)+i.top,o=h(t.key,t.label,t.value,t,m);e.tooltip.show([r,s],o,t.value<0?"e":"w",null,n)};return t.dispatch.on("elementMouseover.tooltip",function(e){d.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){d.tooltipHide(e)}),d.on("tooltipHide",function(){c&&e.tooltip.cleanup()}),m.dispatch=d,m.bullet=t,d3.rebind(m,t,"color"),m.options=e.utils.optionsFunc.bind(m),m.orient=function(e){return arguments.length?(n=e,r=n=="right"||n=="bottom",m):n},m.ranges=function(e){return arguments.length?(s=e,m):s},m.markers=function(e){return arguments.length?(o=e,m):o},m.measures=function(e){return arguments.length?(u=e,m):u},m.width=function(e){return arguments.length?(a=e,m):a},m.height=function(e){return arguments.length?(f=e,m):f},m.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,m):i},m.tickFormat=function(e){return arguments.length?(l=e,m):l},m.tooltips=function(e){return arguments.length?(c=e,m):c},m.tooltipContent=function(e){return arguments.length?(h=e,m):h},m.noData=function(e){return arguments.length?(p=e,m):p},m},e.models.cumulativeLineChart=function(){"use strict";function D(b){return b.each(function(b){function q(e,t){d3.select(D.container).style("cursor","ew-resize")}function R(e,t){M.x=d3.event.x,M.i=Math.round(O.invert(M.x)),rt()}function U(e,t){d3.select(D.container).style("cursor","auto"),x.index=M.i,k.stateChange(x)}function rt(){nt.data([M]);var e=D.transitionDuration();D.transitionDuration(0),D.update(),D.transitionDuration(e)}var A=d3.select(this).classed("nv-chart-"+S,!0),H=this,B=(f||parseInt(A.style("width"))||960)-u.left-u.right,j=(l||parseInt(A.style("height"))||400)-u.top-u.bottom;D.update=function(){A.transition().duration(L).call(D)},D.container=this,x.disabled=b.map(function(e){return!!e.disabled});if(!T){var F;T={};for(F in x)x[F]instanceof Array?T[F]=x[F].slice(0):T[F]=x[F]}var I=d3.behavior.drag().on("dragstart",q).on("drag",R).on("dragend",U);if(!b||!b.length||!b.filter(function(e){return e.values.length}).length){var z=A.selectAll(".nv-noData").data([N]);return z.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),z.attr("x",u.left+B/2).attr("y",u.top+j/2).text(function(e){return e}),D}A.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();if(!y){var W=b.filter(function(e){return!e.disabled}).map(function(e,n){var r=d3.extent(e.values,t.y());return r[0]<-0.95&&(r[0]=-0.95),[(r[0]-r[1])/(1+r[1]),(r[1]-r[0])/(1+r[0])]}),X=[d3.min(W,function(e){return e[0]}),d3.max(W,function(e){return e[1]})];t.yDomain(X)}else t.yDomain(null);O.domain([0,b[0].values.length-1]).range([0,B]).clamp(!0);var b=P(M.i,b),V=g?"none":"all",$=A.selectAll("g.nv-wrap.nv-cumulativeLine").data([b]),J=$.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),K=$.select("g");J.append("g").attr("class","nv-interactive"),J.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),J.append("g").attr("class","nv-y nv-axis"),J.append("g").attr("class","nv-background"),J.append("g").attr("class","nv-linesWrap").style("pointer-events",V),J.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),J.append("g").attr("class","nv-legendWrap"),J.append("g").attr("class","nv-controlsWrap"),c&&(i.width(B),K.select(".nv-legendWrap").datum(b).call(i),u.top!=i.height()&&(u.top=i.height(),j=(l||parseInt(A.style("height"))||400)-u.top-u.bottom),K.select(".nv-legendWrap").attr("transform","translate(0,"+ -u.top+")"));if(m){var Q=[{key:"Re-scale y-axis",disabled:!y}];s.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),K.select(".nv-controlsWrap").datum(Q).attr("transform","translate(0,"+ -u.top+")").call(s)}$.attr("transform","translate("+u.left+","+u.top+")"),d&&K.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)");var G=b.filter(function(e){return e.tempDisabled});$.select(".tempDisabled").remove(),G.length&&$.append("text").attr("class","tempDisabled").attr("x",B/2).attr("y","-.71em").style("text-anchor","end").text(G.map(function(e){return e.key}).join(", ")+" values cannot be calculated for this time period."),g&&(o.width(B).height(j).margin({left:u.left,top:u.top}).svgContainer(A).xScale(w),$.select(".nv-interactive").call(o)),J.select(".nv-background").append("rect"),K.select(".nv-background rect").attr("width",B).attr("height",j),t.y(function(e){return e.display.y}).width(B).height(j).color(b.map(function(e,t){return e.color||a(e,t)}).filter(function(e,t){return!b[t].disabled&&!b[t].tempDisabled}));var Y=K.select(".nv-linesWrap").datum(b.filter(function(e){return!e.disabled&&!e.tempDisabled}));Y.call(t),b.forEach(function(e,t){e.seriesIndex=t});var Z=b.filter(function(e){return!e.disabled&&!!C(e)}),et=K.select(".nv-avgLinesWrap").selectAll("line").data(Z,function(e){return e.key}),tt=function(e){var t=E(C(e));return t<0?0:t>j?j:t};et.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(e,n){return t.color()(e,e.seriesIndex)}).attr("x1",0).attr("x2",B).attr("y1",tt).attr("y2",tt),et.style("stroke-opacity",function(e){var t=E(C(e));return t<0||t>j?0:1}).attr("x1",0).attr("x2",B).attr("y1",tt).attr("y2",tt),et.exit().remove();var nt=Y.selectAll(".nv-indexLine").data([M]);nt.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(I),nt.attr("transform",function(e){return"translate("+O(e.i)+",0)"}).attr("height",j),h&&(n.scale(w).ticks(Math.min(b[0].values.length,B/70)).tickSize(-j,0),K.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),d3.transition(K.select(".nv-x.nv-axis")).call(n)),p&&(r.scale(E).ticks(j/36).tickSize(-B,0),d3.transition(K.select(".nv-y.nv-axis")).call(r)),K.select(".nv-background rect").on("click",function(){M.x=d3.mouse(this)[0],M.i=Math.round(O.invert(M.x)),x.index=M.i,k.stateChange(x),rt()}),t.dispatch.on("elementClick",function(e){M.i=e.pointIndex,M.x=O(M.i),x.index=M.i,k.stateChange(x),rt()}),s.dispatch.on("legendClick",function(e,t){e.disabled=!e.disabled,y=!e.disabled,x.rescaleY=y,k.stateChange(x),D.update()}),i.dispatch.on("stateChange",function(e){x.disabled=e.disabled,k.stateChange(x),D.update()}),o.dispatch.on("elementMousemove",function(i){t.clearHighlights();var s,f,l,c=[];b.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,D.x()),t.highlightPoint(r,f,!0);var o=n.values[f];if(typeof o=="undefined")return;typeof s=="undefined"&&(s=o),typeof l=="undefined"&&(l=D.xScale()(D.x()(o,f))),c.push({key:n.key,value:D.y()(o,f),color:a(n,n.seriesIndex)})});if(c.length>2){var h=D.yScale().invert(i.mouseY),p=Math.abs(D.yScale().domain()[0]-D.yScale().domain()[1]),d=.03*p,m=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);m!==null&&(c[m].highlight=!0)}var g=n.tickFormat()(D.x()(s,f),f);o.tooltip.position({left:l+u.left,top:i.mouseY+u.top}).chartContainer(H.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:g,series:c})(),o.renderGuideLine(l)}),o.dispatch.on("elementMouseout",function(e){k.tooltipHide(),t.clearHighlights()}),k.on("tooltipShow",function(e){v&&_(e,H.parentNode)}),k.on("changeState",function(e){typeof e.disabled!="undefined"&&(b.forEach(function(t,n){t.disabled=e.disabled[n]}),x.disabled=e.disabled),typeof e.index!="undefined"&&(M.i=e.index,M.x=O(M.i),x.index=e.index,nt.data([M])),typeof e.rescaleY!="undefined"&&(y=e.rescaleY),D.update()})}),D}function P(e,n){return n.map(function(n,r){if(!n.values)return n;var i=t.y()(n.values[e],e);return i<-0.95&&!A?(n.tempDisabled=!0,n):(n.tempDisabled=!1,n.values= +n.values.map(function(e,n){return e.display={y:(t.y()(e,n)-i)/(1+i)},e}),n)})}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:30,bottom:50,left:60},a=e.utils.defaultColor(),f=null,l=null,c=!0,h=!0,p=!0,d=!1,v=!0,m=!0,g=!1,y=!0,b=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},w,E,S=t.id(),x={index:0,rescaleY:y},T=null,N="No Data Available.",C=function(e){return e.average},k=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),L=250,A=!1;n.orient("bottom").tickPadding(7),r.orient(d?"right":"left"),s.updateState(!1);var O=d3.scale.linear(),M={i:0,x:0},_=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,D);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],k.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){k.tooltipHide(e)}),k.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),D.dispatch=k,D.lines=t,D.legend=i,D.xAxis=n,D.yAxis=r,D.interactiveLayer=o,d3.rebind(D,t,"defined","isArea","x","y","xScale","yScale","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id"),D.options=e.utils.optionsFunc.bind(D),D.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,D):u},D.width=function(e){return arguments.length?(f=e,D):f},D.height=function(e){return arguments.length?(l=e,D):l},D.color=function(t){return arguments.length?(a=e.utils.getColor(t),i.color(a),D):a},D.rescaleY=function(e){return arguments.length?(y=e,D):y},D.showControls=function(e){return arguments.length?(m=e,D):m},D.useInteractiveGuideline=function(e){return arguments.length?(g=e,e===!0&&(D.interactive(!1),D.useVoronoi(!1)),D):g},D.showLegend=function(e){return arguments.length?(c=e,D):c},D.showXAxis=function(e){return arguments.length?(h=e,D):h},D.showYAxis=function(e){return arguments.length?(p=e,D):p},D.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),D):d},D.tooltips=function(e){return arguments.length?(v=e,D):v},D.tooltipContent=function(e){return arguments.length?(b=e,D):b},D.state=function(e){return arguments.length?(x=e,D):x},D.defaultState=function(e){return arguments.length?(T=e,D):T},D.noData=function(e){return arguments.length?(N=e,D):N},D.average=function(e){return arguments.length?(C=e,D):C},D.transitionDuration=function(e){return arguments.length?(L=e,D):L},D.noErrorCheck=function(e){return arguments.length?(A=e,D):A},D},e.models.discreteBar=function(){"use strict";function E(e){return e.each(function(e){var i=n-t.left-t.right,E=r-t.top-t.bottom,S=d3.select(this);e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var T=p&&d?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0}})});s.domain(p||d3.merge(T).map(function(e){return e.x})).rangeBands(v||[0,i],.1),o.domain(d||d3.extent(d3.merge(T).map(function(e){return e.y}).concat(f))),c?o.range(m||[E-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]):o.range(m||[E,0]),b=b||s,w=w||o.copy().range([o(0),o(0)]);var N=S.selectAll("g.nv-wrap.nv-discretebar").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-groups"),N.attr("transform","translate("+t.left+","+t.top+")");var A=N.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),A.exit().transition().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),A.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),A.transition().style("stroke-opacity",1).style("fill-opacity",.75);var O=A.selectAll("g.nv-bar").data(function(e){return e.values});O.exit().remove();var M=O.enter().append("g").attr("transform",function(e,t,n){return"translate("+(s(u(e,t))+s.rangeBand()*.05)+", "+o(0)+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),g.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),g.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){g.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){g.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(t.series+.5)/e.length,o(a(t,n))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()});M.append("rect").attr("height",0).attr("width",s.rangeBand()*.9/e.length),c?(M.append("text").attr("text-anchor","middle"),O.select("text").text(function(e,t){return h(a(e,t))}).transition().attr("x",s.rangeBand()*.9/2).attr("y",function(e,t){return a(e,t)<0?o(a(e,t))-o(0)+12:-4})):O.selectAll("text").remove(),O.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(e,t){return e.color||l(e,t)}).style("stroke",function(e,t){return e.color||l(e,t)}).select("rect").attr("class",y).transition().attr("width",s.rangeBand()*.9/e.length),O.transition().attr("transform",function(e,t){var n=s(u(e,t))+s.rangeBand()*.05,r=a(e,t)<0?o(0):o(0)-o(a(e,t))<1?o(0)-1:o(a(e,t));return"translate("+n+", "+r+")"}).select("rect").attr("height",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(d&&d[0]||0))||1)}),b=s.copy(),w=o.copy()}),E}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=!1,h=d3.format(",.2f"),p,d,v,m,g=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),y="discreteBar",b,w;return E.dispatch=g,E.options=e.utils.optionsFunc.bind(E),E.x=function(e){return arguments.length?(u=e,E):u},E.y=function(e){return arguments.length?(a=e,E):a},E.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,E):t},E.width=function(e){return arguments.length?(n=e,E):n},E.height=function(e){return arguments.length?(r=e,E):r},E.xScale=function(e){return arguments.length?(s=e,E):s},E.yScale=function(e){return arguments.length?(o=e,E):o},E.xDomain=function(e){return arguments.length?(p=e,E):p},E.yDomain=function(e){return arguments.length?(d=e,E):d},E.xRange=function(e){return arguments.length?(v=e,E):v},E.yRange=function(e){return arguments.length?(m=e,E):m},E.forceY=function(e){return arguments.length?(f=e,E):f},E.color=function(t){return arguments.length?(l=e.utils.getColor(t),E):l},E.id=function(e){return arguments.length?(i=e,E):i},E.showValues=function(e){return arguments.length?(c=e,E):c},E.valueFormat=function(e){return arguments.length?(h=e,E):h},E.rectClass=function(e){return arguments.length?(y=e,E):y},E},e.models.discreteBarChart=function(){"use strict";function w(e){return e.each(function(e){var u=d3.select(this),p=this,E=(s||parseInt(u.style("width"))||960)-i.left-i.right,S=(o||parseInt(u.style("height"))||400)-i.top-i.bottom;w.update=function(){g.beforeUpdate(),u.transition().duration(y).call(w)},w.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var T=u.selectAll(".nv-noData").data([m]);return T.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),T.attr("x",i.left+E/2).attr("y",i.top+S/2).text(function(e){return e}),w}u.selectAll(".nv-noData").remove(),d=t.xScale(),v=t.yScale().clamp(!0);var N=u.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([e]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),k=C.append("defs"),L=N.select("g");C.append("g").attr("class","nv-x nv-axis"),C.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),C.append("g").attr("class","nv-barsWrap"),L.attr("transform","translate("+i.left+","+i.top+")"),l&&L.select(".nv-y.nv-axis").attr("transform","translate("+E+",0)"),t.width(E).height(S);var A=L.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));A.transition().call(t),k.append("clipPath").attr("id","nv-x-label-clip-"+t.id()).append("rect"),L.select("#nv-x-label-clip-"+t.id()+" rect").attr("width",d.rangeBand()*(c?2:1)).attr("height",16).attr("x",-d.rangeBand()/(c?1:2));if(a){n.scale(d).ticks(E/100).tickSize(-S,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+(v.range()[0]+(t.showValues()&&v.domain()[0]<0?16:0))+")"),L.select(".nv-x.nv-axis").transition().call(n);var O=L.select(".nv-x.nv-axis").selectAll("g");c&&O.selectAll("text").attr("transform",function(e,t,n){return"translate(0,"+(n%2==0?"5":"17")+")"})}f&&(r.scale(v).ticks(S/36).tickSize(-E,0),L.select(".nv-y.nv-axis").transition().call(r)),L.select(".nv-zeroLine line").attr("x1",0).attr("x2",E).attr("y1",v(0)).attr("y2",v(0)),g.on("tooltipShow",function(e){h&&b(e,p.parentNode)})}),w}var t=e.models.discreteBar(),n=e.models.axis(),r=e.models.axis(),i={top:15,right:10,bottom:50,left:60},s=null,o=null,u=e.utils.getColor(),a=!0,f=!0,l=!1,c=!1,h=!0,p=function(e,t,n,r,i){return"

    "+t+"

    "+"

    "+n+"

    "},d,v,m="No Data Available.",g=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate"),y=250;n.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(l?"right":"left").tickFormat(d3.format(",.1f"));var b=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=p(i.series.key,a,f,i,w);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+i.left,e.pos[1]+i.top],g.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){g.tooltipHide(e)}),g.on("tooltipHide",function(){h&&e.tooltip.cleanup()}),w.dispatch=g,w.discretebar=t,w.xAxis=n,w.yAxis=r,d3.rebind(w,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","id","showValues","valueFormat"),w.options=e.utils.optionsFunc.bind(w),w.margin=function(e){return arguments.length?(i.top=typeof e.top!="undefined"?e.top:i.top,i.right=typeof e.right!="undefined"?e.right:i.right,i.bottom=typeof e.bottom!="undefined"?e.bottom:i.bottom,i.left=typeof e.left!="undefined"?e.left:i.left,w):i},w.width=function(e){return arguments.length?(s=e,w):s},w.height=function(e){return arguments.length?(o=e,w):o},w.color=function(n){return arguments.length?(u=e.utils.getColor(n),t.color(u),w):u},w.showXAxis=function(e){return arguments.length?(a=e,w):a},w.showYAxis=function(e){return arguments.length?(f=e,w):f},w.rightAlignYAxis=function(e){return arguments.length?(l=e,r.orient(e?"right":"left"),w):l},w.staggerLabels=function(e){return arguments.length?(c=e,w):c},w.tooltips=function(e){return arguments.length?(h=e,w):h},w.tooltipContent=function(e){return arguments.length?(p=e,w):p},w.noData=function(e){return arguments.length?(m=e,w):m},w.transitionDuration=function(e){return arguments.length?(y=e,w):y},w},e.models.distribution=function(){"use strict";function l(e){return e.each(function(e){var a=n-(i==="x"?t.left+t.right:t.top+t.bottom),l=i=="x"?"y":"x",c=d3.select(this);f=f||u;var h=c.selectAll("g.nv-distribution").data([e]),p=h.enter().append("g").attr("class","nvd3 nv-distribution"),d=p.append("g"),v=h.select("g");h.attr("transform","translate("+t.left+","+t.top+")");var m=v.selectAll("g.nv-dist").data(function(e){return e},function(e){return e.key});m.enter().append("g"),m.attr("class",function(e,t){return"nv-dist nv-series-"+t}).style("stroke",function(e,t){return o(e,t)});var g=m.selectAll("line.nv-dist"+i).data(function(e){return e.values});g.enter().append("line").attr(i+"1",function(e,t){return f(s(e,t))}).attr(i+"2",function(e,t){return f(s(e,t))}),m.exit().selectAll("line.nv-dist"+i).transition().attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}).style("stroke-opacity",0).remove(),g.attr("class",function(e,t){return"nv-dist"+i+" nv-dist"+i+"-"+t}).attr(l+"1",0).attr(l+"2",r),g.transition().attr(i+"1",function(e,t){return u(s(e,t))}).attr(i+"2",function(e,t){return u(s(e,t))}),f=u.copy()}),l}var t={top:0,right:0,bottom:0,left:0},n=400,r=8,i="x",s=function(e){return e[i]},o=e.utils.defaultColor(),u=d3.scale.linear(),a,f;return l.options=e.utils.optionsFunc.bind(l),l.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,l):t},l.width=function(e){return arguments.length?(n=e,l):n},l.axis=function(e){return arguments.length?(i=e,l):i},l.size=function(e){return arguments.length?(r=e,l):r},l.getData=function(e){return arguments.length?(s=d3.functor(e),l):s},l.scale=function(e){return arguments.length?(u=e,l):u},l.color=function(t){return arguments.length?(o=e.utils.getColor(t),l):o},l},e.models.historicalBar=function(){"use strict";function w(E){return E.each(function(w){var E=n-t.left-t.right,S=r-t.top-t.bottom,T=d3.select(this);s.domain(d||d3.extent(w[0].values.map(u).concat(f))),c?s.range(m||[E*.5/w[0].values.length,E*(w[0].values.length-.5)/w[0].values.length]):s.range(m||[0,E]),o.domain(v||d3.extent(w[0].values.map(a).concat(l))).range(g||[S,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=T.selectAll("g.nv-wrap.nv-historicalBar-"+i).data([w[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+i),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-bars"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){y.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",E).attr("height",S),A.attr("clip-path",h?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-bars").selectAll(".nv-bar").data(function(e){return e},function(e,t){return u(e,t)});O.exit().remove();var M=O.enter().append("rect").attr("x",0).attr("y",function(t,n){return e.utils.NaNtoZero(o(Math.max(0,a(t,n))))}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.abs(o(a(t,n))-o(0)))}).attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).on("mouseover",function(e,t){if(!b)return;d3.select(this).classed("hover",!0),y.elementMouseover({point:e,series:w[0],pos:[s(u(e,t)),o(a(e,t))],pointIndex:t,seriesIndex:0,e:d3.event})}).on("mouseout",function(e,t){if(!b)return;d3.select(this).classed("hover",!1),y.elementMouseout({point:e,series:w[0],pointIndex:t,seriesIndex:0,e:d3.event})}).on("click",function(e,t){if(!b)return;y.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){if(!b)return;y.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("fill",function(e,t){return p(e,t)}).attr("class",function(e,t,n){return(a(e,t)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+n+"-"+t}).transition().attr("transform",function(e,t){return"translate("+(s(u(e,t))-E/w[0].values.length*.45)+",0)"}).attr("width",E/w[0].values.length*.9),O.transition().attr("y",function(t,n){var r=a(t,n)<0?o(0):o(0)-o(a(t,n))<1?o(0)-1:o(a(t,n));return e.utils.NaNtoZero(r)}).attr("height",function(t,n){return e.utils.NaNtoZero(Math.max(Math.abs(o(a(t,n))-o(0)),1))})}),w}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[],l=[0],c=!1,h=!0,p=e.utils.defaultColor(),d,v,m,g,y=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),b=!0;return w.highlightPoint=function(e,t){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar-0-"+e).classed("hover",t)},w.clearHighlights=function(){d3.select(".nv-historicalBar-"+i).select(".nv-bars .nv-bar.hover").classed("hover",!1)},w.dispatch=y,w.options=e.utils.optionsFunc.bind(w),w.x=function(e){return arguments.length?(u=e,w):u},w.y=function(e){return arguments.length?(a=e,w):a},w.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,w):t},w.width=function(e){return arguments.length?(n=e,w):n},w.height=function(e){return arguments.length?(r=e,w):r},w.xScale=function(e){return arguments.length?(s=e,w):s},w.yScale=function(e){return arguments.length?(o=e,w):o},w.xDomain=function(e){return arguments.length?(d=e,w):d},w.yDomain=function(e){return arguments.length?(v=e,w):v},w.xRange=function(e){return arguments.length?(m=e,w):m},w.yRange=function(e){return arguments.length?(g=e,w):g},w.forceX=function(e){return arguments.length?(f=e,w):f},w.forceY=function(e){return arguments.length?(l=e,w):l},w.padData=function(e){return arguments.length?(c=e,w):c},w.clipEdge=function(e){return arguments.length?(h=e,w):h},w.color=function(t){return arguments.length?(p=e.utils.getColor(t),w):p},w.id=function(e){return arguments.length?(i=e,w):i},w.interactive=function(e){return arguments.length?(b=!1,w):b},w},e.models.historicalBarChart=function(){"use strict";function x(e){return e.each(function(d){var T=d3.select(this),N=this,C=(u||parseInt(T.style("width"))||960)-s.left-s.right,k=(a||parseInt(T.style("height"))||400)-s.top-s.bottom;x.update=function(){T.transition().duration(E).call(x)},x.container=this,g.disabled=d.map(function(e){return!!e.disabled});if(!y){var L;y={};for(L in g)g[L]instanceof Array?y[L]=g[L].slice(0):y[L]=g[L]}if(!d||!d.length||!d.filter(function(e){return e.values.length}).length){var A=T.selectAll(".nv-noData").data([b]);return A.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),A.attr("x",s.left+C/2).attr("y",s.top+k/2).text(function(e){return e}),x}T.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale();var O=T.selectAll("g.nv-wrap.nv-historicalBarChart").data([d]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y nv-axis"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-legendWrap"),f&&(i.width(C),_.select(".nv-legendWrap").datum(d).call(i),s.top!=i.height()&&(s.top=i.height(),k=(a||parseInt(T.style("height"))||400)-s.top-s.bottom),O.select(".nv-legendWrap").attr("transform","translate(0,"+ -s.top+")")),O.attr("transform","translate("+s.left+","+s.top+")"),h&&_.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),t.width(C).height(k).color(d.map(function(e,t){return e.color||o(e,t)}).filter(function(e,t){return!d[t].disabled}));var D=_.select(".nv-barsWrap").datum(d.filter(function(e){return!e.disabled}));D.transition().call(t),l&&(n.scale(v).tickSize(-k,0),_.select(".nv-x.nv-axis").attr("transform","translate(0,"+m.range()[0]+")"),_.select(".nv-x.nv-axis").transition().call(n)),c&&(r.scale(m).ticks(k/36).tickSize(-C,0),_.select(".nv-y.nv-axis").transition().call(r)),i.dispatch.on("legendClick",function(t,n){t.disabled=!t.disabled,d.filter(function(e){return!e.disabled}).length||d.map(function(e){return e.disabled=!1,O.selectAll(".nv-series").classed("disabled",!1),e}),g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),e.transition().call(x)}),i.dispatch.on("legendDblclick",function(e){d.forEach(function(e){e.disabled=!0}),e.disabled=!1,g.disabled=d.map(function(e){return!!e.disabled}),w.stateChange(g),x.update()}),w.on("tooltipShow",function(e){p&&S(e,N.parentNode)}),w.on("changeState",function(e){typeof e.disabled!="undefined"&&(d.forEach(function(t,n){t.disabled=e.disabled[n]}),g.disabled=e.disabled),x.update()})}),x}var t=e.models.historicalBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s={top:30,right:90,bottom:50,left:90},o=e.utils.defaultColor(),u=null,a=null,f=!1,l=!0,c=!0,h=!1,p=!0,d=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},v,m,g={},y=null,b="No Data Available.",w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=250;n.orient("bottom").tickPadding(7),r.orient(h?"right":"left");var S=function(i,s){if(s){var o=d3.select(s).select("svg"),u=o.node()?o.attr("viewBox"):null;if(u){u=u.split(" ");var a=parseInt(o.style("width"))/u[2];i.pos[0]=i.pos[0]*a,i.pos[1]=i.pos[1]*a}}var f=i.pos[0]+(s.offsetLeft||0),l=i.pos[1]+(s.offsetTop||0),c=n.tickFormat()(t.x()(i.point,i.pointIndex)),h=r.tickFormat()(t.y()(i.point,i.pointIndex)),p=d(i.series.key,c,h,i,x);e.tooltip.show([f,l],p,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+s.left,e.pos[1]+s.top],w.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){w.tooltipHide(e)}),w.on("tooltipHide",function(){p&&e.tooltip.cleanup()}),x.dispatch=w,x.bars=t,x.legend=i,x.xAxis=n,x.yAxis=r,d3.rebind(x,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate","highlightPoint","clearHighlights","interactive"),x.options=e.utils.optionsFunc.bind(x),x.margin=function(e){return arguments.length?(s.top=typeof e.top!="undefined"?e.top:s.top,s.right=typeof e.right!="undefined"?e.right:s.right,s.bottom=typeof e.bottom!="undefined"?e.bottom:s.bottom,s.left=typeof e.left!="undefined"?e.left:s.left,x):s},x.width=function(e){return arguments.length?(u=e,x):u},x.height=function(e){return arguments.length?(a=e,x):a},x.color=function(t){return arguments.length?(o=e.utils.getColor(t),i.color(o),x):o},x.showLegend=function(e){return arguments.length?(f=e,x):f},x.showXAxis=function(e){return arguments.length?(l=e,x):l},x.showYAxis=function(e){return arguments.length?(c=e,x):c},x.rightAlignYAxis=function(e){return arguments.length?(h=e,r.orient(e?"right":"left"),x):h},x.tooltips=function(e){return arguments.length?(p=e,x):p},x.tooltipContent=function(e){return arguments.length?(d=e,x):d},x.state=function(e){return arguments.length?(g=e,x):g},x.defaultState=function(e){return arguments.length?(y=e,x):y},x.noData=function(e){return arguments.length?(b=e,x):b},x.transitionDuration=function(e){return arguments.length?(E=e,x):E},x},e.models.indentedTree=function(){"use strict";function g(e){return e.each(function(e){function k(e,t,n){d3.event.stopPropagation();if(d3.event.shiftKey&&!n)return d3.event.shiftKey=!1,e.values&&e.values.forEach(function(e){(e.values||e._values)&&k(e,0,!0)}),!0;if(!O(e))return!0;e.values?(e._values=e.values,e.values=null):(e.values=e._values,e._values=null),g.update()}function L(e){return e._values&&e._values.length?h:e.values&&e.values.length?p:""}function A(e){return e._values&&e._values.length}function O(e){var t=e.values||e._values;return t&&t.length}var t=1,n=d3.select(this),i=d3.layout.tree().children(function(e){return e.values}).size([r,f]);g.update=function(){n.transition().duration(600).call(g)},e[0]||(e[0]={key:a});var s=i.nodes(e[0]),y=d3.select(this).selectAll("div").data([[s]]),b=y.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),w=b.append("table"),E=y.select("table").attr("width","100%").attr("class",c);if(o){var S=w.append("thead"),x=S.append("tr");l.forEach(function(e){x.append("th").attr("width",e.width?e.width:"10%").style("text-align",e.type=="numeric"?"right":"left").append("span").text(e.label)})}var T=E.selectAll("tbody").data(function(e){return e});T.enter().append("tbody"),t=d3.max(s,function(e){return e.depth}),i.size([r,t*f]);var N=T.selectAll("tr").data(function(e){return e.filter(function(e){return u&&!e.children?u(e):!0})},function(e,t){return e.id||e.id||++m});N.exit().remove(),N.select("img.nv-treeicon").attr("src",L).classed("folded",A);var C=N.enter().append("tr");l.forEach(function(e,t){var n=C.append("td").style("padding-left",function(e){return(t?0:e.depth*f+12+(L(e)?0:16))+"px"},"important").style("text-align",e.type=="numeric"?"right":"left");t==0&&n.append("img").classed("nv-treeicon",!0).classed("nv-folded",A).attr("src",L).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(e){return L(e)?"inline-block":"none"}).on("click",k),n.each(function(n){!t&&v(n)?d3.select(this).append("a").attr("href",v).attr("class",d3.functor(e.classes)).append("span"):d3.select(this).append("span"),d3.select(this).select("span").attr("class",d3.functor(e.classes)).text(function(t){return e.format?e.format(t):t[e.key]||"-"})}),e.showCount&&(n.append("span").attr("class","nv-childrenCount"),N.selectAll("span.nv-childrenCount").text(function(e){return e.values&&e.values.length||e._values&&e._values.length?"("+(e.values&&e.values.filter(function(e){return u?u(e):!0}).length||e._values&&e._values.filter(function(e){return u?u(e):!0}).length||0)+")":""}))}),N.order().on("click",function(e){d.elementClick({row:this,data:e,pos:[e.x,e.y]})}).on("dblclick",function(e){d.elementDblclick({row:this,data:e,pos:[e.x,e.y]})}).on("mouseover",function(e){d.elementMouseover({row:this,data:e,pos:[e.x,e.y]})}).on("mouseout",function(e){d.elementMouseout({row:this,data:e,pos:[e.x,e.y]})})}),g}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e4),o=!0,u=!1,a="No Data Available.",f=20,l=[{key:"key",label:"Name",type:"text"}],c=null,h="images/grey-plus.png",p="images/grey-minus.png",d=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),v=function(e){return e.url},m=0;return g.options=e.utils.optionsFunc.bind(g),g.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,g):t},g.width=function(e){return arguments.length?(n=e,g):n},g.height=function(e){return arguments.length?(r=e,g):r},g.color=function(t){return arguments.length?(i=e.utils.getColor(t),scatter.color(i),g):i},g.id=function(e){return arguments.length?(s=e,g):s},g.header=function(e){return arguments.length?(o=e,g):o},g.noData=function(e){return arguments.length?(a=e,g):a},g.filterZero=function(e){return arguments.length?(u=e,g):u},g.columns=function(e){return arguments.length?(l=e,g):l},g.tableClass=function(e){return arguments.length?(c=e,g):c},g.iconOpen=function(e){return arguments.length?(h=e,g):h},g.iconClose=function(e){return arguments.length?(p=e,g):p},g.getUrl=function(e){return arguments.length?(v=e,g):v},g},e.models.legend=function(){"use strict";function c(h){return h.each(function(c){var h=n-t.left-t.right,p=d3.select(this),d=p.selectAll("g.nv-legend").data([c]),v=d.enter().append("g").attr("class","nvd3 nv-legend").append("g"),m=d.select("g");d.attr("transform","translate("+t.left+","+t.top+")");var g=m.selectAll(".nv-series").data(function(e){return e}),y=g.enter().append("g").attr("class","nv-series").on("mouseover",function(e,t){l.legendMouseover(e,t)}).on("mouseout",function(e,t){l.legendMouseout(e,t)}).on("click",function(e,t){l.legendClick(e,t),a&&(f?(c.forEach(function(e){e.disabled=!0}),e.disabled=!1):(e.disabled=!e.disabled,c.every(function(e){return e.disabled})&&c.forEach(function(e){e.disabled=!1})),l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))}).on("dblclick",function(e,t){l.legendDblclick(e,t),a&&(c.forEach(function(e){e.disabled=!0}),e.disabled=!1,l.stateChange({disabled:c.map(function(e){return!!e.disabled})}))});y.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),y.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8"),g.classed("disabled",function(e){return e.disabled}),g.exit().remove(),g.select("circle").style("fill",function(e,t){return e.color||s(e,t)}).style("stroke",function(e,t){return e.color||s(e,t)}),g.select("text").text(i);if(o){var b=[];g.each(function(t,n){var r=d3.select(this).select("text"),i;try{i=r.getComputedTextLength();if(i<=0)throw Error()}catch(s){i=e.utils.calcApproxTextWidth(r)}b.push(i+28)});var w=0,E=0,S=[];while(Eh&&w>1){S=[],w--;for(var x=0;x(S[x%w]||0)&&(S[x%w]=b[x]);E=S.reduce(function(e,t,n,r){return e+t})}var T=[];for(var N=0,C=0;NA&&(A=L),"translate("+O+","+k+")"}),m.attr("transform","translate("+(n-t.right-A)+","+t.top+")"),r=t.top+t.bottom+k+15}}),c}var t={top:5,right:0,bottom:5,left:0},n=400,r=20,i=function(e){return e.key},s=e.utils.defaultColor(),o=!0,u=!0,a=!0,f=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return c.dispatch=l,c.options=e.utils.optionsFunc.bind(c),c.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,c):t},c.width=function(e){return arguments.length?(n=e,c):n},c.height=function(e){return arguments.length?(r=e,c):r},c.key=function(e){return arguments.length?(i=e,c):i},c.color=function(t){return arguments.length?(s=e.utils.getColor(t),c):s},c.align=function(e){return arguments.length?(o=e,c):o},c.rightAlign=function(e){return arguments.length?(u=e,c):u},c.updateState=function(e){return arguments.length?(a=e,c):a},c.radioButtonMode=function(e){return arguments.length?(f=e,c):f},c},e.models.line=function(){"use strict";function m(g){return g.each(function(m){var g=r-n.left-n.right,b=i-n.top-n.bottom,w=d3.select(this);c=t.xScale(),h=t.yScale(),d=d||c,v=v||h;var E=w.selectAll("g.nv-wrap.nv-line").data([m]),S=E.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),T=S.append("defs"),N=S.append("g"),C=E.select("g");N.append("g").attr("class","nv-groups"),N.append("g").attr("class","nv-scatterWrap"),E.attr("transform","translate("+n.left+","+n.top+")"),t.width(g).height(b);var k=E.select(".nv-scatterWrap");k.transition().call(t),T.append("clipPath").attr("id","nv-edge-clip-"+t.id()).append("rect"),E.select("#nv-edge-clip-"+t.id()+" rect").attr("width",g).attr("height",b),C.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":""),k.attr("clip-path",l?"url(#nv-edge-clip-"+t.id()+")":"");var L=E.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});L.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),L.exit().remove(),L.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return s(e,t)}).style("stroke",function(e,t){return s(e,t)}),L.transition().style("stroke-opacity",1).style("fill-opacity",.5);var A=L.selectAll("path.nv-area").data(function(e){return f(e)?[e]:[]});A.enter().append("path").attr("class","nv-area").attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e. +utils.NaNtoZero(d(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))}).y1(function(e,t){return v(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])}),L.exit().selectAll("path.nv-area").remove(),A.transition().attr("d",function(t){return d3.svg.area().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y0(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))}).y1(function(e,t){return h(h.domain()[0]<=0?h.domain()[1]>=0?0:h.domain()[1]:h.domain()[0])}).apply(this,[t.values])});var O=L.selectAll("path.nv-line").data(function(e){return[e.values]});O.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(d(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(v(u(t,n)))})),O.transition().attr("d",d3.svg.line().interpolate(p).defined(a).x(function(t,n){return e.utils.NaNtoZero(c(o(t,n)))}).y(function(t,n){return e.utils.NaNtoZero(h(u(t,n)))})),d=c.copy(),v=h.copy()}),m}var t=e.models.scatter(),n={top:0,right:0,bottom:0,left:0},r=960,i=500,s=e.utils.defaultColor(),o=function(e){return e.x},u=function(e){return e.y},a=function(e,t){return!isNaN(u(e,t))&&u(e,t)!==null},f=function(e){return e.area},l=!1,c,h,p="linear";t.size(16).sizeDomain([16,256]);var d,v;return m.dispatch=t.dispatch,m.scatter=t,d3.rebind(m,t,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","padData","highlightPoint","clearHighlights"),m.options=e.utils.optionsFunc.bind(m),m.margin=function(e){return arguments.length?(n.top=typeof e.top!="undefined"?e.top:n.top,n.right=typeof e.right!="undefined"?e.right:n.right,n.bottom=typeof e.bottom!="undefined"?e.bottom:n.bottom,n.left=typeof e.left!="undefined"?e.left:n.left,m):n},m.width=function(e){return arguments.length?(r=e,m):r},m.height=function(e){return arguments.length?(i=e,m):i},m.x=function(e){return arguments.length?(o=e,t.x(e),m):o},m.y=function(e){return arguments.length?(u=e,t.y(e),m):u},m.clipEdge=function(e){return arguments.length?(l=e,m):l},m.color=function(n){return arguments.length?(s=e.utils.getColor(n),t.color(s),m):s},m.interpolate=function(e){return arguments.length?(p=e,m):p},m.defined=function(e){return arguments.length?(a=e,m):a},m.isArea=function(e){return arguments.length?(f=d3.functor(e),m):f},m},e.models.lineChart=function(){"use strict";function N(m){return m.each(function(m){var C=d3.select(this),k=this,L=(a||parseInt(C.style("width"))||960)-o.left-o.right,A=(f||parseInt(C.style("height"))||400)-o.top-o.bottom;N.update=function(){C.transition().duration(x).call(N)},N.container=this,b.disabled=m.map(function(e){return!!e.disabled});if(!w){var O;w={};for(O in b)b[O]instanceof Array?w[O]=b[O].slice(0):w[O]=b[O]}if(!m||!m.length||!m.filter(function(e){return e.values.length}).length){var M=C.selectAll(".nv-noData").data([E]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",o.left+L/2).attr("y",o.top+A/2).text(function(e){return e}),N}C.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var _=C.selectAll("g.nv-wrap.nv-lineChart").data([m]),D=_.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),P=_.select("g");D.append("rect").style("opacity",0),D.append("g").attr("class","nv-x nv-axis"),D.append("g").attr("class","nv-y nv-axis"),D.append("g").attr("class","nv-linesWrap"),D.append("g").attr("class","nv-legendWrap"),D.append("g").attr("class","nv-interactive"),P.select("rect").attr("width",L).attr("height",A>0?A:0),l&&(i.width(L),P.select(".nv-legendWrap").datum(m).call(i),o.top!=i.height()&&(o.top=i.height(),A=(f||parseInt(C.style("height"))||400)-o.top-o.bottom),_.select(".nv-legendWrap").attr("transform","translate(0,"+ -o.top+")")),_.attr("transform","translate("+o.left+","+o.top+")"),p&&P.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),d&&(s.width(L).height(A).margin({left:o.left,top:o.top}).svgContainer(C).xScale(g),_.select(".nv-interactive").call(s)),t.width(L).height(A).color(m.map(function(e,t){return e.color||u(e,t)}).filter(function(e,t){return!m[t].disabled}));var H=P.select(".nv-linesWrap").datum(m.filter(function(e){return!e.disabled}));H.transition().call(t),c&&(n.scale(g).ticks(L/100).tickSize(-A,0),P.select(".nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),P.select(".nv-x.nv-axis").transition().call(n)),h&&(r.scale(y).ticks(A/36).tickSize(-L,0),P.select(".nv-y.nv-axis").transition().call(r)),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),N.update()}),s.dispatch.on("elementMousemove",function(i){t.clearHighlights();var a,f,l,c=[];m.filter(function(e,t){return e.seriesIndex=t,!e.disabled}).forEach(function(n,r){f=e.interactiveBisect(n.values,i.pointXValue,N.x()),t.highlightPoint(r,f,!0);var s=n.values[f];if(typeof s=="undefined")return;typeof a=="undefined"&&(a=s),typeof l=="undefined"&&(l=N.xScale()(N.x()(s,f))),c.push({key:n.key,value:N.y()(s,f),color:u(n,n.seriesIndex)})});if(c.length>2){var h=N.yScale().invert(i.mouseY),p=Math.abs(N.yScale().domain()[0]-N.yScale().domain()[1]),d=.03*p,g=e.nearestValueIndex(c.map(function(e){return e.value}),h,d);g!==null&&(c[g].highlight=!0)}var y=n.tickFormat()(N.x()(a,f));s.tooltip.position({left:l+o.left,top:i.mouseY+o.top}).chartContainer(k.parentNode).enabled(v).valueFormatter(function(e,t){return r.tickFormat()(e)}).data({value:y,series:c})(),s.renderGuideLine(l)}),s.dispatch.on("elementMouseout",function(e){S.tooltipHide(),t.clearHighlights()}),S.on("tooltipShow",function(e){v&&T(e,k.parentNode)}),S.on("changeState",function(e){typeof e.disabled!="undefined"&&m.length===e.disabled.length&&(m.forEach(function(t,n){t.disabled=e.disabled[n]}),b.disabled=e.disabled),N.update()})}),N}var t=e.models.line(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.interactiveGuideline(),o={top:30,right:20,bottom:50,left:60},u=e.utils.defaultColor(),a=null,f=null,l=!0,c=!0,h=!0,p=!1,d=!1,v=!0,m=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=250;n.orient("bottom").tickPadding(7),r.orient(p?"right":"left");var T=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,N);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),N.dispatch=S,N.lines=t,N.legend=i,N.xAxis=n,N.yAxis=r,N.interactiveLayer=s,d3.rebind(N,t,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id","interpolate"),N.options=e.utils.optionsFunc.bind(N),N.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,N):o},N.width=function(e){return arguments.length?(a=e,N):a},N.height=function(e){return arguments.length?(f=e,N):f},N.color=function(t){return arguments.length?(u=e.utils.getColor(t),i.color(u),N):u},N.showLegend=function(e){return arguments.length?(l=e,N):l},N.showXAxis=function(e){return arguments.length?(c=e,N):c},N.showYAxis=function(e){return arguments.length?(h=e,N):h},N.rightAlignYAxis=function(e){return arguments.length?(p=e,r.orient(e?"right":"left"),N):p},N.useInteractiveGuideline=function(e){return arguments.length?(d=e,e===!0&&(N.interactive(!1),N.useVoronoi(!1)),N):d},N.tooltips=function(e){return arguments.length?(v=e,N):v},N.tooltipContent=function(e){return arguments.length?(m=e,N):m},N.state=function(e){return arguments.length?(b=e,N):b},N.defaultState=function(e){return arguments.length?(w=e,N):w},N.noData=function(e){return arguments.length?(E=e,N):E},N.transitionDuration=function(e){return arguments.length?(x=e,N):x},N},e.models.linePlusBarChart=function(){"use strict";function T(e){return e.each(function(e){var l=d3.select(this),c=this,v=(a||parseInt(l.style("width"))||960)-u.left-u.right,N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom;T.update=function(){l.transition().call(T)},b.disabled=e.map(function(e){return!!e.disabled});if(!w){var C;w={};for(C in b)b[C]instanceof Array?w[C]=b[C].slice(0):w[C]=b[C]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var k=l.selectAll(".nv-noData").data([E]);return k.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),k.attr("x",u.left+v/2).attr("y",u.top+N/2).text(function(e){return e}),T}l.selectAll(".nv-noData").remove();var L=e.filter(function(e){return!e.disabled&&e.bar}),A=e.filter(function(e){return!e.bar});m=A.filter(function(e){return!e.disabled}).length&&A.filter(function(e){return!e.disabled})[0].values.length?t.xScale():n.xScale(),g=n.yScale(),y=t.yScale();var O=d3.select(this).selectAll("g.nv-wrap.nv-linePlusBar").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),_=O.select("g");M.append("g").attr("class","nv-x nv-axis"),M.append("g").attr("class","nv-y1 nv-axis"),M.append("g").attr("class","nv-y2 nv-axis"),M.append("g").attr("class","nv-barsWrap"),M.append("g").attr("class","nv-linesWrap"),M.append("g").attr("class","nv-legendWrap"),p&&(o.width(v/2),_.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(o),u.top!=o.height()&&(u.top=o.height(),N=(f||parseInt(l.style("height"))||400)-u.top-u.bottom),_.select(".nv-legendWrap").attr("transform","translate("+v/2+","+ -u.top+")")),O.attr("transform","translate("+u.left+","+u.top+")"),t.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar})),n.width(v).height(N).color(e.map(function(e,t){return e.color||h(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar}));var D=_.select(".nv-barsWrap").datum(L.length?L:[{values:[]}]),P=_.select(".nv-linesWrap").datum(A[0]&&!A[0].disabled?A:[{values:[]}]);d3.transition(D).call(n),d3.transition(P).call(t),r.scale(m).ticks(v/100).tickSize(-N,0),_.select(".nv-x.nv-axis").attr("transform","translate(0,"+g.range()[0]+")"),d3.transition(_.select(".nv-x.nv-axis")).call(r),i.scale(g).ticks(N/36).tickSize(-v,0),d3.transition(_.select(".nv-y1.nv-axis")).style("opacity",L.length?1:0).call(i),s.scale(y).ticks(N/36).tickSize(L.length?0:-v,0),_.select(".nv-y2.nv-axis").style("opacity",A.length?1:0).attr("transform","translate("+v+",0)"),d3.transition(_.select(".nv-y2.nv-axis")).call(s),o.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),T.update()}),S.on("tooltipShow",function(e){d&&x(e,c.parentNode)}),S.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),b.disabled=t.disabled),T.update()})}),T}var t=e.models.line(),n=e.models.historicalBar(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.legend(),u={top:30,right:60,bottom:50,left:60},a=null,f=null,l=function(e){return e.x},c=function(e){return e.y},h=e.utils.defaultColor(),p=!0,d=!0,v=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},m,g,y,b={},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");n.padData(!0),t.clipEdge(!1).padData(!0),r.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),s.orient("right");var x=function(n,o){var u=n.pos[0]+(o.offsetLeft||0),a=n.pos[1]+(o.offsetTop||0),f=r.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?i:s).tickFormat()(t.y()(n.point,n.pointIndex)),c=v(n.series.key,f,l,n,T);e.tooltip.show([u,a],c,n.value<0?"n":"s",null,o)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),n.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],S.tooltipShow(e)}),n.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){d&&e.tooltip.cleanup()}),T.dispatch=S,T.legend=o,T.lines=t,T.bars=n,T.xAxis=r,T.y1Axis=i,T.y2Axis=s,d3.rebind(T,t,"defined","size","clipVoronoi","interpolate"),T.options=e.utils.optionsFunc.bind(T),T.x=function(e){return arguments.length?(l=e,t.x(e),n.x(e),T):l},T.y=function(e){return arguments.length?(c=e,t.y(e),n.y(e),T):c},T.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,T):u},T.width=function(e){return arguments.length?(a=e,T):a},T.height=function(e){return arguments.length?(f=e,T):f},T.color=function(t){return arguments.length?(h=e.utils.getColor(t),o.color(h),T):h},T.showLegend=function(e){return arguments.length?(p=e,T):p},T.tooltips=function(e){return arguments.length?(d=e,T):d},T.tooltipContent=function(e){return arguments.length?(v=e,T):v},T.state=function(e){return arguments.length?(b=e,T):b},T.defaultState=function(e){return arguments.length?(w=e,T):w},T.noData=function(e){return arguments.length?(E=e,T):E},T},e.models.lineWithFocusChart=function(){"use strict";function k(e){return e.each(function(e){function U(e){var t=+(e=="e"),n=t?1:-1,r=M/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function z(){a.empty()||a.extent(w),I.data([a.empty()?g.domain():w]).each(function(e,t){var n=g(e[0])-v.range()[0],r=v.range()[1]-g(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",g(e[1])).attr("width",r<0?0:r)})}function W(){w=a.empty()?null:a.extent();var n=a.empty()?g.domain():a.extent();if(Math.abs(n[0]-n[1])<=1)return;T.brush({extent:n,brush:a}),z();var s=H.select(".nv-focus .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}).map(function(e,r){return{key:e.key,values:e.values.filter(function(e,r){return t.x()(e,r)>=n[0]&&t.x()(e,r)<=n[1]})}}));s.transition().duration(N).call(t),H.select(".nv-focus .nv-x.nv-axis").transition().duration(N).call(r),H.select(".nv-focus .nv-y.nv-axis").transition().duration(N).call(i)}var S=d3.select(this),L=this,A=(h||parseInt(S.style("width"))||960)-f.left-f.right,O=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d,M=d-l.top-l.bottom;k.update=function(){S.transition().duration(N).call(k)},k.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var _=S.selectAll(".nv-noData").data([x]);return _.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),_.attr("x",f.left+A/2).attr("y",f.top+O/2).text(function(e){return e}),k}S.selectAll(".nv-noData").remove(),v=t.xScale(),m=t.yScale(),g=n.xScale(),y=n.yScale();var D=S.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([e]),P=D.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),H=D.select("g");P.append("g").attr("class","nv-legendWrap");var B=P.append("g").attr("class","nv-focus");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-linesWrap");var j=P.append("g").attr("class","nv-context");j.append("g").attr("class","nv-x nv-axis"),j.append("g").attr("class","nv-y nv-axis"),j.append("g").attr("class","nv-linesWrap"),j.append("g").attr("class","nv-brushBackground"),j.append("g").attr("class","nv-x nv-brush"),b&&(u.width(A),H.select(".nv-legendWrap").datum(e).call(u),f.top!=u.height()&&(f.top=u.height(),O=(p||parseInt(S.style("height"))||400)-f.top-f.bottom-d),H.select(".nv-legendWrap").attr("transform","translate(0,"+ -f.top+")")),D.attr("transform","translate("+f.left+","+f.top+")"),t.width(A).height(O).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),n.defined(t.defined()).width(A).height(M).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),H.select(".nv-context").attr("transform","translate(0,"+(O+f.bottom+l.top)+")");var F=H.select(".nv-context .nv-linesWrap").datum(e.filter(function(e){return!e.disabled}));d3.transition(F).call(n),r.scale(v).ticks(A/100).tickSize(-O,0),i.scale(m).ticks(O/36).tickSize(-A,0),H.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+O+")"),a.x(g).on("brush",function(){var e=k.transitionDuration();k.transitionDuration(0),W(),k.transitionDuration(e)}),w&&a.extent(w);var I=H.select(".nv-brushBackground").selectAll("g").data([w||a.extent()]),q=I.enter().append("g");q.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),q.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var R=H.select(".nv-x.nv-brush").call(a);R.selectAll("rect").attr("height",M),R.selectAll(".resize").append("path").attr("d",U),W(),s.scale(g).ticks(A/100).tickSize(-M,0),H.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),d3.transition(H.select(".nv-context .nv-x.nv-axis")).call(s),o.scale(y).ticks(M/36).tickSize(-A,0),d3.transition(H.select(".nv-context .nv-y.nv-axis")).call(o),H.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+y.range()[0]+")"),u.dispatch.on("stateChange",function(e){k.update()}),T.on("tooltipShow",function(e){E&&C(e,L.parentNode)})}),k}var t=e.models.line(),n=e.models.line(),r=e.models.axis(),i=e.models.axis(),s=e.models.axis(),o=e.models.axis(),u=e.models.legend(),a=d3.svg.brush(),f={top:30,right:30,bottom:30,left:60},l={top:0,right:30,bottom:20,left:60},c=e.utils.defaultColor(),h=null,p=null,d=100,v,m,g,y,b=!0,w=null,E=!0,S=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},x="No Data Available.",T=d3.dispatch("tooltipShow","tooltipHide","brush"),N=250;t.clipEdge(!0),n.interactive(!1),r.orient("bottom").tickPadding(5),i.orient("left"),s.orient("bottom").tickPadding(5),o.orient("left");var C=function(n,s){var o=n.pos[0]+(s.offsetLeft||0),u=n.pos[1]+(s.offsetTop||0),a=r.tickFormat()(t.x()(n.point,n.pointIndex)),f=i.tickFormat()(t.y()(n.point,n.pointIndex)),l=S(n.series.key,a,f,n,k);e.tooltip.show([o,u],l,null,null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+f.left,e.pos[1]+f.top],T.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){E&&e.tooltip.cleanup()}),k.dispatch=T,k.legend=u,k.lines=t,k.lines2=n,k.xAxis=r,k.yAxis=i,k.x2Axis=s,k.y2Axis=o,d3.rebind(k,t,"defined","isArea","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),k.options=e.utils.optionsFunc.bind(k),k.x=function(e){return arguments.length?(t.x(e),n.x(e),k):t.x},k.y=function(e){return arguments.length?(t.y(e),n.y(e),k):t.y},k.margin=function(e){return arguments.length?(f.top=typeof e.top!="undefined"?e.top:f.top,f.right=typeof e.right!="undefined"?e.right:f.right,f.bottom=typeof e.bottom!="undefined"?e.bottom:f.bottom,f.left=typeof e.left!="undefined"?e.left:f.left,k):f},k.margin2=function(e){return arguments.length?(l=e,k):l},k.width=function(e){return arguments.length?(h=e,k):h},k.height=function(e){return arguments.length?(p=e,k):p},k.height2=function(e){return arguments.length?(d=e,k):d},k.color=function(t){return arguments.length?(c=e.utils.getColor(t),u.color(c),k):c},k.showLegend=function(e){return arguments.length?(b=e,k):b},k.tooltips=function(e){return arguments.length?(E=e,k):E},k.tooltipContent=function(e){return arguments.length?(S=e,k):S},k.interpolate=function(e){return arguments.length?(t.interpolate(e),n.interpolate(e),k):t.interpolate()},k.noData=function(e){return arguments.length?(x=e,k):x},k.xTickFormat=function(e){return arguments.length?(r.tickFormat(e),s.tickFormat(e),k):r.tickFormat()},k.yTickFormat=function(e){return arguments.length?(i.tickFormat(e),o.tickFormat(e),k):i.tickFormat()},k.brushExtent=function(e){return arguments.length?(w=e,k):w},k.transitionDuration=function(e){return arguments.length?(N=e,k):N},k},e.models.linePlusBarWithFocusChart=function(){"use strict";function B(e){return e.each(function(e){function nt(e){var t=+(e=="e"),n=t?1:-1,r=q/3;return"M"+.5*n+","+r+"A6,6 0 0 "+t+" "+6.5*n+","+(r+6)+"V"+(2*r-6)+"A6,6 0 0 "+t+" "+.5*n+","+2*r+"Z"+"M"+2.5*n+","+(r+8)+"V"+(2*r-8)+"M"+4.5*n+","+(r+8)+"V"+(2*r-8)}function rt(){h.empty()||h.extent(x),Z.data([h.empty()?k.domain():x]).each(function(e,t){var n=k(e[0])-k.range()[0],r=k.range()[1]-k(e[1]);d3.select(this).select(".left").attr("width",n<0?0:n),d3.select(this).select(".right").attr("x",k(e[1])).attr("width",r<0?0:r)})}function it(){x=h.empty()?null:h.extent(),S=h.empty()?k.domain():h.extent(),D.brush({extent:S,brush:h}),rt(),r.width(F).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),t.width(F).height(I).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var n=J.select(".nv-focus .nv-barsWrap").datum(U.length?U.map(function(e,t){return{key:e.key,values:e.values.filter(function(e,t){return r.x()(e,t)>=S[0]&&r.x()(e,t)<=S[1]})}}):[{values:[]}]),i=J.select(".nv-focus .nv-linesWrap").datum(z[0].disabled?[{values:[]}]:z.map(function(e,n){return{key:e.key,values:e.values.filter(function(e,n){return t.x()(e,n)>=S[0]&&t.x()(e,n)<=S[1]})}}));U.length?C=r.xScale():C=t.xScale(),s.scale(C).ticks(F/100).tickSize(-I,0),s.domain([Math.ceil(S[0]),Math.floor(S[1])]),J.select(".nv-x.nv-axis").transition().duration(P).call(s),n.transition().duration(P).call(r),i.transition().duration(P).call(t),J.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L.range()[0]+")"),u.scale(L).ticks(I/36).tickSize(-F,0),J.select(".nv-focus .nv-y1.nv-axis").style("opacity",U.length?1:0),a.scale(A).ticks(I/36).tickSize(U.length?0:-F,0),J.select(".nv-focus .nv-y2.nv-axis").style("opacity",z.length?1:0).attr("transform","translate("+C.range()[1]+",0)"),J.select(".nv-focus .nv-y1.nv-axis").transition().duration(P).call(u),J.select(".nv-focus .nv-y2.nv-axis").transition().duration(P).call(a)}var N=d3.select(this),j=this,F=(v||parseInt(N.style("width"))||960)-p.left-p.right,I=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g,q=g-d.top-d.bottom;B.update=function(){N.transition().duration(P).call(B)},B.container=this;if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var R=N.selectAll(".nv-noData").data([_]);return R.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),R.attr("x",p.left+F/2).attr("y",p.top+I/2).text(function(e){return e}),B}N.selectAll(".nv-noData").remove();var U=e.filter(function(e){return!e.disabled&&e.bar}),z=e.filter(function(e){return!e.bar});C=r.xScale(),k=o.scale(),L=r.yScale(),A=t.yScale(),O=i.yScale(),M=n.yScale();var W=e.filter(function(e){return!e.disabled&&e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})}),X=e.filter(function(e){return!e.disabled&&!e.bar}).map(function(e){return e.values.map(function(e,t){return{x:y(e,t),y:b(e,t)}})});C.range([0,F]),k.domain(d3.extent(d3.merge(W.concat(X)),function(e){return e.x})).range([0,F]);var V=N.selectAll("g.nv-wrap.nv-linePlusBar").data([e]),$=V.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),J=V.select("g");$.append("g").attr("class","nv-legendWrap");var K=$.append("g").attr("class","nv-focus");K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y1 nv-axis"),K.append("g").attr("class","nv-y2 nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-linesWrap");var Q=$.append("g").attr("class","nv-context");Q.append("g").attr("class","nv-x nv-axis"),Q.append("g").attr("class","nv-y1 nv-axis"),Q.append("g").attr("class","nv-y2 nv-axis"),Q.append("g").attr("class","nv-barsWrap"),Q.append("g").attr("class","nv-linesWrap"),Q.append("g").attr("class","nv-brushBackground"),Q.append("g").attr("class","nv-x nv-brush"),E&&(c.width(F/2),J.select(".nv-legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.bar?" (left axis)":" (right axis)"),e})).call(c),p.top!=c.height()&&(p.top=c.height(),I=(m||parseInt(N.style("height"))||400)-p.top-p.bottom-g),J.select(".nv-legendWrap").attr("transform","translate("+F/2+","+ -p.top+")")),V.attr("transform","translate("+p.left+","+p.top+")"),i.width(F).height(q).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&e[n].bar})),n.width(F).height(q).color(e.map(function(e,t){return e.color||w(e,t)}).filter(function(t,n){return!e[n].disabled&&!e[n].bar}));var G=J.select(".nv-context .nv-barsWrap").datum(U.length?U:[{values:[]}]),Y=J.select(".nv-context .nv-linesWrap").datum(z[0].disabled?[{values:[]}]:z);J.select(".nv-context").attr("transform","translate(0,"+(I+p.bottom+d.top)+")"),G.transition().call(i),Y.transition().call(n),h.x(k).on("brush",it),x&&h.extent(x);var Z=J.select(".nv-brushBackground").selectAll("g").data([x||h.extent()]),et=Z.enter().append("g");et.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",q),et.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",q);var tt=J.select(".nv-x.nv-brush").call(h);tt.selectAll("rect").attr("height",q),tt.selectAll(".resize").append("path").attr("d",nt),o.ticks(F/100).tickSize(-q,0),J.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+O.range()[0]+")"),J.select(".nv-context .nv-x.nv-axis").transition().call(o),f.scale(O).ticks(q/36).tickSize(-F,0),J.select(".nv-context .nv-y1.nv-axis").style("opacity",U.length?1:0).attr("transform","translate(0,"+k.range()[0]+")"),J.select(".nv-context .nv-y1.nv-axis").transition().call(f),l.scale(M).ticks(q/36).tickSize(U.length?0:-F,0),J.select(".nv-context .nv-y2.nv-axis").style("opacity",z.length?1:0).attr("transform","translate("+k.range()[1]+",0)"),J.select(".nv-context .nv-y2.nv-axis").transition().call(l),c.dispatch.on("stateChange",function(e){B.update()}),D.on("tooltipShow",function(e){T&&H(e,j.parentNode)}),it()}),B}var t=e.models.line(),n=e.models.line(),r=e.models.historicalBar(),i=e.models.historicalBar(),s=e.models.axis(),o=e.models.axis(),u=e.models.axis(),a=e.models.axis(),f=e.models.axis(),l=e.models.axis(),c=e.models.legend(),h=d3.svg.brush(),p={top:30,right:30,bottom:30,left:60},d={top:0,right:30,bottom:20,left:60},v=null,m=null,g=100,y=function(e){return e.x},b=function(e){return e.y},w=e.utils.defaultColor(),E=!0,S,x=null,T=!0,N=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},C,k,L,A,O,M,_="No Data Available.",D=d3.dispatch("tooltipShow","tooltipHide","brush"),P=0;t.clipEdge(!0),n.interactive(!1),s.orient("bottom").tickPadding(5),u.orient("left"),a.orient("right"),o.orient("bottom").tickPadding(5),f.orient("left"),l.orient("right");var H=function(n,r){S&&(n.pointIndex+=Math.ceil(S[0]));var i=n.pos[0]+(r.offsetLeft||0),o=n.pos[1]+(r.offsetTop||0),f=s.tickFormat()(t.x()(n.point,n.pointIndex)),l=(n.series.bar?u:a).tickFormat()(t.y()(n.point,n.pointIndex)),c=N(n.series.key,f,l,n,B);e.tooltip.show([i,o],c,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),r.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+p.left,e.pos[1]+p.top],D.tooltipShow(e)}),r.dispatch.on("elementMouseout.tooltip",function(e){D.tooltipHide(e)}),D.on("tooltipHide",function(){T&&e.tooltip.cleanup()}),B.dispatch=D,B.legend=c,B.lines=t,B.lines2=n,B.bars=r,B.bars2=i,B.xAxis=s,B.x2Axis=o,B.y1Axis=u,B.y2Axis=a,B.y3Axis=f,B.y4Axis=l,d3.rebind(B,t,"defined","size","clipVoronoi","interpolate"),B.options=e.utils.optionsFunc.bind(B),B.x=function(e){return arguments.length?(y=e,t.x(e),r.x(e),B):y},B.y=function(e){return arguments.length?(b=e,t.y(e),r.y(e),B):b},B.margin=function(e){return arguments.length?(p.top=typeof e.top!="undefined"?e.top:p.top,p.right=typeof e.right!="undefined"?e.right:p.right,p.bottom=typeof e.bottom!="undefined"?e.bottom:p.bottom,p.left=typeof e.left!="undefined"?e.left:p.left,B):p},B.width=function(e){return arguments.length?(v=e,B):v},B.height=function(e){return arguments.length?(m=e,B):m},B.color=function(t){return arguments.length?(w=e.utils.getColor(t),c.color(w),B):w},B.showLegend=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(T=e,B):T},B.tooltipContent=function(e){return arguments.length?(N=e,B):N},B.noData=function(e){return arguments.length?(_=e,B):_},B.brushExtent=function(e){return arguments.length?(x=e,B):x},B},e.models.multiBar=function(){"use strict";function C(e){return e.each(function(e){var C=n-t.left-t.right,k=r-t.top-t.bottom,L=d3.select(this);d&&e.length&&(d=[{values:e[0].values.map(function(e){return{x:e.x,y:0,series:e.series,size:.01}})}]),c&&(e=d3.layout.stack().offset(h).values(function(e){return e.values}).y(a)(!e.length&&d?d:e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),c&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i,i-=t.size):(t.y1=t.size+r,r+=t.size)})});var A=y&&b?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});i.domain(y||d3.merge(A).map(function(e){return e.x})).rangeBands(w||[0,C],S),s.domain(b||d3.extent(d3.merge(A).map(function(e){return c?e.y>0?e.y1:e.y1+e.y:e.y}).concat(f))).range(E||[k,0]),i.domain()[0]===i.domain()[1]&&(i.domain()[0]?i.domain([i.domain()[0]-i.domain()[0]*.01,i.domain()[1]+i.domain()[1]*.01]):i.domain([-1,1])),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]+s.domain()[0]*.01,s.domain()[1]-s.domain()[1]*.01]):s.domain([-1,1])),T=T||i,N=N||s;var O=L.selectAll("g.nv-wrap.nv-multibar").data([e]),M=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),_=M.append("defs"),D=M.append("g"),P=O.select("g");D.append("g").attr("class","nv-groups"),O.attr("transform","translate("+t.left+","+t.top+")"),_.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),O.select("#nv-edge-clip-"+o+" rect").attr("width",C).attr("height",k),P.attr("clip-path",l?"url(#nv-edge-clip-"+o+")":"");var H=O.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});H.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),H.exit().transition().selectAll("rect.nv-bar").delay(function(t,n){return n*g/e[0].values.length}).attr("y",function(e){return c?N(e.y0):N(0)}).attr("height",0).remove(),H.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return p(e,t)}).style("stroke",function(e,t){return p(e,t)}),H.transition().style("stroke-opacity",1).style("fill-opacity",.75);var B=H.selectAll("rect.nv-bar").data(function(t){return d&&!e.length?d.values:t.values});B.exit().remove();var j=B.enter().append("rect").attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(t,n,r){return c?0:r*i.rangeBand()/e.length}).attr("y",function(e){return N(c?e.y0:0)}).attr("height",0).attr("width",i.rangeBand()/(c?1:e.length)).attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"});B.style("fill",function(e,t,n){return p(e,n,t)}).style("stroke",function(e,t,n){return p(e,n,t)}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length +,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[i(u(t,n))+i.rangeBand()*(c?e.length/2:t.series+.5)/e.length,s(a(t,n)+(c?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),B.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}).transition().attr("transform",function(e,t){return"translate("+i(u(e,t))+",0)"}),v&&(m||(m=e.map(function(){return!0})),B.style("fill",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(v(e,t)).darker(m.map(function(e,t){return t}).filter(function(e,t){return!m[t]})[n]).toString()})),c?B.transition().delay(function(t,n){return n*g/e[0].values.length}).attr("y",function(e,t){return s(c?e.y1:0)}).attr("height",function(e,t){return Math.max(Math.abs(s(e.y+(c?e.y0:0))-s(c?e.y0:0)),1)}).attr("x",function(t,n){return c?0:t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/(c?1:e.length)):B.transition().delay(function(t,n){return n*g/e[0].values.length}).attr("x",function(t,n){return t.series*i.rangeBand()/e.length}).attr("width",i.rangeBand()/e.length).attr("y",function(e,t){return a(e,t)<0?s(0):s(0)-s(a(e,t))<1?s(0)-1:s(a(e,t))||0}).attr("height",function(e,t){return Math.max(Math.abs(s(a(e,t))-s(0)),1)||0}),T=i.copy(),N=s.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=d3.scale.ordinal(),s=d3.scale.linear(),o=Math.floor(Math.random()*1e4),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=!0,c=!1,h="zero",p=e.utils.defaultColor(),d=!1,v=null,m,g=1200,y,b,w,E,S=.1,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(i=e,C):i},C.yScale=function(e){return arguments.length?(s=e,C):s},C.xDomain=function(e){return arguments.length?(y=e,C):y},C.yDomain=function(e){return arguments.length?(b=e,C):b},C.xRange=function(e){return arguments.length?(w=e,C):w},C.yRange=function(e){return arguments.length?(E=e,C):E},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(c=e,C):c},C.stackOffset=function(e){return arguments.length?(h=e,C):h},C.clipEdge=function(e){return arguments.length?(l=e,C):l},C.color=function(t){return arguments.length?(p=e.utils.getColor(t),C):p},C.barColor=function(t){return arguments.length?(v=e.utils.getColor(t),C):v},C.disabled=function(e){return arguments.length?(m=e,C):m},C.id=function(e){return arguments.length?(o=e,C):o},C.hideable=function(e){return arguments.length?(d=e,C):d},C.delay=function(e){return arguments.length?(g=e,C):g},C.groupSpacing=function(e){return arguments.length?(S=e,C):S},C},e.models.multiBarChart=function(){"use strict";function A(e){return e.each(function(e){var b=d3.select(this),O=this,M=(u||parseInt(b.style("width"))||960)-o.left-o.right,_=(a||parseInt(b.style("height"))||400)-o.top-o.bottom;A.update=function(){b.transition().duration(k).call(A)},A.container=this,S.disabled=e.map(function(e){return!!e.disabled});if(!x){var D;x={};for(D in S)S[D]instanceof Array?x[D]=S[D].slice(0):x[D]=S[D]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var P=b.selectAll(".nv-noData").data([T]);return P.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),P.attr("x",o.left+M/2).attr("y",o.top+_/2).text(function(e){return e}),A}b.selectAll(".nv-noData").remove(),w=t.xScale(),E=t.yScale();var H=b.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([e]),B=H.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),j=H.select("g");B.append("g").attr("class","nv-x nv-axis"),B.append("g").attr("class","nv-y nv-axis"),B.append("g").attr("class","nv-barsWrap"),B.append("g").attr("class","nv-legendWrap"),B.append("g").attr("class","nv-controlsWrap"),c&&(i.width(M-C()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),j.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),_=(a||parseInt(b.style("height"))||400)-o.top-o.bottom),j.select(".nv-legendWrap").attr("transform","translate("+C()+","+ -o.top+")"));if(l){var F=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(C()).color(["#444","#444","#444"]),j.select(".nv-controlsWrap").datum(F).attr("transform","translate(0,"+ -o.top+")").call(s)}H.attr("transform","translate("+o.left+","+o.top+")"),d&&j.select(".nv-y.nv-axis").attr("transform","translate("+M+",0)"),t.disabled(e.map(function(e){return e.disabled})).width(M).height(_).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var I=j.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));I.transition().call(t);if(h){n.scale(w).ticks(M/100).tickSize(-_,0),j.select(".nv-x.nv-axis").attr("transform","translate(0,"+E.range()[0]+")"),j.select(".nv-x.nv-axis").transition().call(n);var q=j.select(".nv-x.nv-axis > g").selectAll("g");q.selectAll("line, text").style("opacity",1);if(m){var R=function(e,t){return"translate("+e+","+t+")"},U=5,z=17;q.selectAll("text").attr("transform",function(e,t,n){return R(0,n%2==0?U:z)});var W=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;j.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(e,t){return R(0,t===0||W%2!==0?z:U)})}v&&q.filter(function(t,n){return n%Math.ceil(e[0].values.length/(M/100))!==0}).selectAll("text, line").style("opacity",0),g&&q.selectAll(".tick text").attr("transform","rotate("+g+" 0,0)").style("text-anchor",g>0?"start":"end"),j.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}p&&(r.scale(E).ticks(_/36).tickSize(-M,0),j.select(".nv-y.nv-axis").transition().call(r)),i.dispatch.on("stateChange",function(e){S=e,N.stateChange(S),A.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;F=F.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}S.stacked=t.stacked(),N.stateChange(S),A.update()}),N.on("tooltipShow",function(e){y&&L(e,O.parentNode)}),N.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),S.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),S.stacked=n.stacked),A.update()})}),A}var t=e.models.multiBar(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=!1,g=0,y=!0,b=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" on "+t+"

    "},w,E,S={stacked:!1},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=function(){return l?180:0},k=250;t.stacked(!1),n.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(e){return e}),r.orient(d?"right":"left").tickFormat(d3.format(",.1f")),s.updateState(!1);var L=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=b(i.series.key,a,f,i,A);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],N.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){y&&e.tooltip.cleanup()}),A.dispatch=N,A.multibar=t,A.legend=i,A.xAxis=n,A.yAxis=r,d3.rebind(A,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","stacked","stackOffset","delay","barColor","groupSpacing"),A.options=e.utils.optionsFunc.bind(A),A.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,A):o},A.width=function(e){return arguments.length?(u=e,A):u},A.height=function(e){return arguments.length?(a=e,A):a},A.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),A):f},A.showControls=function(e){return arguments.length?(l=e,A):l},A.showLegend=function(e){return arguments.length?(c=e,A):c},A.showXAxis=function(e){return arguments.length?(h=e,A):h},A.showYAxis=function(e){return arguments.length?(p=e,A):p},A.rightAlignYAxis=function(e){return arguments.length?(d=e,r.orient(e?"right":"left"),A):d},A.reduceXTicks=function(e){return arguments.length?(v=e,A):v},A.rotateLabels=function(e){return arguments.length?(g=e,A):g},A.staggerLabels=function(e){return arguments.length?(m=e,A):m},A.tooltip=function(e){return arguments.length?(b=e,A):b},A.tooltips=function(e){return arguments.length?(y=e,A):y},A.tooltipContent=function(e){return arguments.length?(b=e,A):b},A.state=function(e){return arguments.length?(S=e,A):S},A.defaultState=function(e){return arguments.length?(x=e,A):x},A.noData=function(e){return arguments.length?(T=e,A):T},A.transitionDuration=function(e){return arguments.length?(k=e,A):k},A},e.models.multiBarHorizontal=function(){"use strict";function C(e){return e.each(function(e){var i=n-t.left-t.right,y=r-t.top-t.bottom,C=d3.select(this);p&&(e=d3.layout.stack().offset("zero").values(function(e){return e.values}).y(a)(e)),e.forEach(function(e,t){e.values.forEach(function(e){e.series=t})}),p&&e[0].values.map(function(t,n){var r=0,i=0;e.map(function(e){var t=e.values[n];t.size=Math.abs(t.y),t.y<0?(t.y1=i-t.size,i-=t.size):(t.y1=r,r+=t.size)})});var k=b&&w?[]:e.map(function(e){return e.values.map(function(e,t){return{x:u(e,t),y:a(e,t),y0:e.y0,y1:e.y1}})});s.domain(b||d3.merge(k).map(function(e){return e.x})).rangeBands(E||[0,y],.1),o.domain(w||d3.extent(d3.merge(k).map(function(e){return p?e.y>0?e.y1+e.y:e.y1:e.y}).concat(f))),d&&!p?o.range(S||[o.domain()[0]<0?m:0,i-(o.domain()[1]>0?m:0)]):o.range(S||[0,i]),T=T||s,N=N||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);var L=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([e]),A=L.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),O=A.append("defs"),M=A.append("g"),_=L.select("g");M.append("g").attr("class","nv-groups"),L.attr("transform","translate("+t.left+","+t.top+")");var D=L.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e,t){return t});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().transition().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}).style("fill",function(e,t){return l(e,t)}).style("stroke",function(e,t){return l(e,t)}),D.transition().style("stroke-opacity",1).style("fill-opacity",.75);var P=D.selectAll("g.nv-bar").data(function(e){return e.values});P.exit().remove();var H=P.enter().append("g").attr("transform",function(t,n,r){return"translate("+N(p?t.y0:0)+","+(p?0:r*s.rangeBand()/e.length+s(u(t,n)))+")"});H.append("rect").attr("width",0).attr("height",s.rangeBand()/(p?1:e.length)),P.on("mouseover",function(t,n){d3.select(this).classed("hover",!0),x.elementMouseover({value:a(t,n),point:t,series:e[t.series],pos:[o(a(t,n)+(p?t.y0:0)),s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),x.elementMouseout({value:a(t,n),point:t,series:e[t.series],pointIndex:n,seriesIndex:t.series,e:d3.event})}).on("click",function(t,n){x.elementClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(t,n){x.elementDblClick({value:a(t,n),point:t,series:e[t.series],pos:[s(u(t,n))+s.rangeBand()*(p?e.length/2:t.series+.5)/e.length,o(a(t,n)+(p?t.y0:0))],pointIndex:n,seriesIndex:t.series,e:d3.event}),d3.event.stopPropagation()}),H.append("text"),d&&!p?(P.select("text").attr("text-anchor",function(e,t){return a(e,t)<0?"end":"start"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return g(a(e,t))}),P.transition().select("text").attr("x",function(e,t){return a(e,t)<0?-4:o(a(e,t))-o(0)+4})):P.selectAll("text").text(""),v&&!p?(H.append("text").classed("nv-bar-label",!0),P.select("text.nv-bar-label").attr("text-anchor",function(e,t){return a(e,t)<0?"start":"end"}).attr("y",s.rangeBand()/(e.length*2)).attr("dy",".32em").text(function(e,t){return u(e,t)}),P.transition().select("text.nv-bar-label").attr("x",function(e,t){return a(e,t)<0?o(0)-o(a(e,t))+4:-4})):P.selectAll("text.nv-bar-label").text(""),P.attr("class",function(e,t){return a(e,t)<0?"nv-bar negative":"nv-bar positive"}),c&&(h||(h=e.map(function(){return!0})),P.style("fill",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()}).style("stroke",function(e,t,n){return d3.rgb(c(e,t)).darker(h.map(function(e,t){return t}).filter(function(e,t){return!h[t]})[n]).toString()})),p?P.transition().attr("transform",function(e,t){return"translate("+o(e.y1)+","+s(u(e,t))+")"}).select("rect").attr("width",function(e,t){return Math.abs(o(a(e,t)+e.y0)-o(e.y0))}).attr("height",s.rangeBand()):P.transition().attr("transform",function(t,n){return"translate("+(a(t,n)<0?o(a(t,n)):o(0))+","+(t.series*s.rangeBand()/e.length+s(u(t,n)))+")"}).select("rect").attr("height",s.rangeBand()/e.length).attr("width",function(e,t){return Math.max(Math.abs(o(a(e,t))-o(0)),1)}),T=s.copy(),N=o.copy()}),C}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.ordinal(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=[0],l=e.utils.defaultColor(),c=null,h,p=!1,d=!1,v=!1,m=60,g=d3.format(",.2f"),y=1200,b,w,E,S,x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),T,N;return C.dispatch=x,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(u=e,C):u},C.y=function(e){return arguments.length?(a=e,C):a},C.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,C):t},C.width=function(e){return arguments.length?(n=e,C):n},C.height=function(e){return arguments.length?(r=e,C):r},C.xScale=function(e){return arguments.length?(s=e,C):s},C.yScale=function(e){return arguments.length?(o=e,C):o},C.xDomain=function(e){return arguments.length?(b=e,C):b},C.yDomain=function(e){return arguments.length?(w=e,C):w},C.xRange=function(e){return arguments.length?(E=e,C):E},C.yRange=function(e){return arguments.length?(S=e,C):S},C.forceY=function(e){return arguments.length?(f=e,C):f},C.stacked=function(e){return arguments.length?(p=e,C):p},C.color=function(t){return arguments.length?(l=e.utils.getColor(t),C):l},C.barColor=function(t){return arguments.length?(c=e.utils.getColor(t),C):c},C.disabled=function(e){return arguments.length?(h=e,C):h},C.id=function(e){return arguments.length?(i=e,C):i},C.delay=function(e){return arguments.length?(y=e,C):y},C.showValues=function(e){return arguments.length?(d=e,C):d},C.showBarLabels=function(e){return arguments.length?(v=e,C):v},C.valueFormat=function(e){return arguments.length?(g=e,C):g},C.valuePadding=function(e){return arguments.length?(m=e,C):m},C},e.models.multiBarHorizontalChart=function(){"use strict";function C(e){return e.each(function(e){var d=d3.select(this),m=this,k=(u||parseInt(d.style("width"))||960)-o.left-o.right,L=(a||parseInt(d.style("height"))||400)-o.top-o.bottom;C.update=function(){d.transition().duration(T).call(C)},C.container=this,b.disabled=e.map(function(e){return!!e.disabled});if(!w){var A;w={};for(A in b)b[A]instanceof Array?w[A]=b[A].slice(0):w[A]=b[A]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var O=d.selectAll(".nv-noData").data([E]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",o.left+k/2).attr("y",o.top+L/2).text(function(e){return e}),C}d.selectAll(".nv-noData").remove(),g=t.xScale(),y=t.yScale();var M=d.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([e]),_=M.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),D=M.select("g");_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),_.append("g").attr("class","nv-barsWrap"),_.append("g").attr("class","nv-legendWrap"),_.append("g").attr("class","nv-controlsWrap"),c&&(i.width(k-x()),t.barColor()&&e.forEach(function(e,t){e.color=d3.rgb("#ccc").darker(t*1.5).toString()}),D.select(".nv-legendWrap").datum(e).call(i),o.top!=i.height()&&(o.top=i.height(),L=(a||parseInt(d.style("height"))||400)-o.top-o.bottom),D.select(".nv-legendWrap").attr("transform","translate("+x()+","+ -o.top+")"));if(l){var P=[{key:"Grouped",disabled:t.stacked()},{key:"Stacked",disabled:!t.stacked()}];s.width(x()).color(["#444","#444","#444"]),D.select(".nv-controlsWrap").datum(P).attr("transform","translate(0,"+ -o.top+")").call(s)}M.attr("transform","translate("+o.left+","+o.top+")"),t.disabled(e.map(function(e){return e.disabled})).width(k).height(L).color(e.map(function(e,t){return e.color||f(e,t)}).filter(function(t,n){return!e[n].disabled}));var H=D.select(".nv-barsWrap").datum(e.filter(function(e){return!e.disabled}));H.transition().call(t);if(h){n.scale(g).ticks(L/24).tickSize(-k,0),D.select(".nv-x.nv-axis").transition().call(n);var B=D.select(".nv-x.nv-axis").selectAll("g");B.selectAll("line, text")}p&&(r.scale(y).ticks(k/100).tickSize(-L,0),D.select(".nv-y.nv-axis").attr("transform","translate(0,"+L+")"),D.select(".nv-y.nv-axis").transition().call(r)),D.select(".nv-zeroLine line").attr("x1",y(0)).attr("x2",y(0)).attr("y1",0).attr("y2",-L),i.dispatch.on("stateChange",function(e){b=e,S.stateChange(b),C.update()}),s.dispatch.on("legendClick",function(e,n){if(!e.disabled)return;P=P.map(function(e){return e.disabled=!0,e}),e.disabled=!1;switch(e.key){case"Grouped":t.stacked(!1);break;case"Stacked":t.stacked(!0)}b.stacked=t.stacked(),S.stateChange(b),C.update()}),S.on("tooltipShow",function(e){v&&N(e,m.parentNode)}),S.on("changeState",function(n){typeof n.disabled!="undefined"&&(e.forEach(function(e,t){e.disabled=n.disabled[t]}),b.disabled=n.disabled),typeof n.stacked!="undefined"&&(t.stacked(n.stacked),b.stacked=n.stacked),C.update()})}),C}var t=e.models.multiBarHorizontal(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend().height(30),s=e.models.legend().height(30),o={top:30,right:20,bottom:50,left:60},u=null,a=null,f=e.utils.defaultColor(),l=!0,c=!0,h=!0,p=!0,d=!1,v=!0,m=function(e,t,n,r,i){return"

    "+e+" - "+t+"

    "+"

    "+n+"

    "},g,y,b={stacked:d},w=null,E="No Data Available.",S=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),x=function(){return l?180:0},T=250;t.stacked(d),n.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(e){return e}),r.orient("bottom").tickFormat(d3.format(",.1f")),s.updateState(!1);var N=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=m(i.series.key,a,f,i,C);e.tooltip.show([o,u],l,i.value<0?"e":"w",null,s)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+o.left,e.pos[1]+o.top],S.tooltipShow(e)}),t.dispatch.on("elementMouseout.tooltip",function(e){S.tooltipHide(e)}),S.on("tooltipHide",function(){v&&e.tooltip.cleanup()}),C.dispatch=S,C.multibar=t,C.legend=i,C.xAxis=n,C.yAxis=r,d3.rebind(C,t,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","delay","showValues","showBarLabels","valueFormat","stacked","barColor"),C.options=e.utils.optionsFunc.bind(C),C.margin=function(e){return arguments.length?(o.top=typeof e.top!="undefined"?e.top:o.top,o.right=typeof e.right!="undefined"?e.right:o.right,o.bottom=typeof e.bottom!="undefined"?e.bottom:o.bottom,o.left=typeof e.left!="undefined"?e.left:o.left,C):o},C.width=function(e){return arguments.length?(u=e,C):u},C.height=function(e){return arguments.length?(a=e,C):a},C.color=function(t){return arguments.length?(f=e.utils.getColor(t),i.color(f),C):f},C.showControls=function(e){return arguments.length?(l=e,C):l},C.showLegend=function(e){return arguments.length?(c=e,C):c},C.showXAxis=function(e){return arguments.length?(h=e,C):h},C.showYAxis=function(e){return arguments.length?(p=e,C):p},C.tooltip=function(e){return arguments.length?(m=e,C):m},C.tooltips=function(e){return arguments.length?(v=e,C):v},C.tooltipContent=function(e){return arguments.length?(m=e,C):m},C.state=function(e){return arguments.length?(b=e,C):b},C.defaultState=function(e){return arguments.length?(w=e,C):w},C.noData=function(e){return arguments.length?(E=e,C):E},C.transitionDuration=function(e){return arguments.length?(T=e,C):T},C},e.models.multiChart=function(){"use strict";function C(e){return e.each(function(e){var u=d3.select(this),f=this;C.update=function(){u.transition().call(C)},C.container=this;var k=(r||parseInt(u.style("width"))||960)-t.left-t.right,L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom,A=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==1}),O=e.filter(function(e){return!e.disabled&&e.type=="line"&&e.yAxis==2}),M=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==1}),_=e.filter(function(e){return!e.disabled&&e.type=="bar"&&e.yAxis==2}),D=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==1}),P=e.filter(function(e){return!e.disabled&&e.type=="area"&&e.yAxis==2}),H=e.filter(function(e){return!e.disabled&&e.yAxis==1}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})}),B=e.filter(function(e){return!e.disabled&&e.yAxis==2}).map(function(e){return e.values.map(function(e,t){return{x:e.x,y:e.y}})});a.domain(d3.extent(d3.merge(H.concat(B)),function(e){return e.x})).range([0,k]);var j=u.selectAll("g.wrap.multiChart").data([e]),F=j.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");F.append("g").attr("class","x axis"),F.append("g").attr("class","y1 axis"),F.append("g").attr("class","y2 axis"),F.append("g").attr("class","lines1Wrap"),F.append("g").attr("class","lines2Wrap"),F.append("g").attr("class","bars1Wrap"),F.append("g").attr("class","bars2Wrap"),F.append("g").attr("class","stack1Wrap"),F.append("g").attr("class","stack2Wrap"),F.append("g").attr("class","legendWrap");var I=j.select("g");s&&(x.width(k/2),I.select(".legendWrap").datum(e.map(function(e){return e.originalKey=e.originalKey===undefined?e.key:e.originalKey,e.key=e.originalKey+(e.yAxis==1?"":" (right axis)"),e})).call(x),t.top!=x.height()&&(t.top=x.height(),L=(i||parseInt(u.style("height"))||400)-t.top-t.bottom),I.select(".legendWrap").attr("transform","translate("+k/2+","+ -t.top+")")),d.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="line"})),v.width(k).height(L).interpolate("monotone").color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="line"})),m.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="bar"})),g.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="bar"})),y.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==1&&e[n].type=="area"})),b.width(k).height(L).color(e.map(function(e,t){return e.color||n[t%n.length]}).filter(function(t,n){return!e[n].disabled&&e[n].yAxis==2&&e[n].type=="area"})),I.attr("transform","translate("+t.left+","+t.top+")");var q=I.select(".lines1Wrap").datum(A),R=I.select(".bars1Wrap").datum(M),U=I.select(".stack1Wrap").datum(D),z=I.select(".lines2Wrap").datum(O),W=I.select(".bars2Wrap").datum(_),X=I.select(".stack2Wrap").datum(P),V=D.length?D.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[],$=P.length?P.map(function(e){return e.values}).reduce(function(e,t){return e.map(function(e,n){return{x:e.x,y:e.y+t[n].y}})}).concat([{x:0,y:0}]):[];h.domain(l||d3.extent(d3.merge(H).concat(V),function(e){return e.y})).range([0,L]),p.domain(c||d3.extent(d3.merge(B).concat($),function(e){return e.y})).range([0,L]),d.yDomain(h.domain()),m.yDomain(h.domain()),y.yDomain(h.domain()),v.yDomain(p.domain()),g.yDomain(p.domain()),b.yDomain(p.domain()),D.length&&d3.transition(U).call(y),P.length&&d3.transition(X).call(b),M.length&&d3.transition(R).call(m),_.length&&d3.transition(W).call(g),A.length&&d3.transition(q).call(d),O.length&&d3.transition(z).call(v),w.ticks(k/100).tickSize(-L,0),I.select(".x.axis").attr("transform","translate(0,"+L+")"),d3.transition(I.select(".x.axis")).call(w),E.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y1.axis")).call(E),S.ticks(L/36).tickSize(-k,0),d3.transition(I.select(".y2.axis")).call(S),I.select(".y2.axis").style("opacity",B.length?1:0).attr("transform","translate("+a.range()[1]+",0)"),x.dispatch.on("stateChange",function(e){C.update()}),T.on("tooltipShow",function(e){o&&N(e,f.parentNode)})}),C}var t={top:30,right:20,bottom:50,left:60},n=d3.scale.category20().range(),r=null,i=null,s=!0,o=!0,u=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" at "+t+"

    "},a,f,l,c,a=d3.scale.linear(),h=d3.scale.linear(),p=d3.scale.linear(),d=e.models.line().yScale(h),v=e.models.line().yScale(p),m=e.models.multiBar().stacked(!1).yScale(h),g=e.models.multiBar().stacked(!1).yScale(p),y=e.models.stackedArea().yScale(h),b=e.models.stackedArea().yScale(p),w=e.models.axis().scale(a).orient("bottom").tickPadding(5),E=e.models.axis().scale(h).orient("left"),S=e.models.axis().scale(p).orient("right"),x=e.models.legend().height(30),T=d3.dispatch("tooltipShow","tooltipHide"),N=function(t,n){var r=t.pos[0]+(n.offsetLeft||0),i=t.pos[1]+(n.offsetTop||0),s=w.tickFormat()(d.x()(t.point,t.pointIndex)),o=(t.series.yAxis==2?S:E).tickFormat()(d.y()(t.point,t.pointIndex)),a=u(t.series.key,s,o,t,C);e.tooltip.show([r,i],a,undefined,undefined,n.offsetParent)};return d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),m.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),m.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),g.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),g.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),y.dispatch.on("tooltipShow",function(e){if(!Math.round(y.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),y.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),b.dispatch.on("tooltipShow",function(e){if(!Math.round(b.y()(e.point)*100))return setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1;e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),b.dispatch.on("tooltipHide",function(e){T.tooltipHide(e)}),d.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),d.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),v.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+t.left,e.pos[1]+t.top],T.tooltipShow(e)}),v.dispatch.on("elementMouseout.tooltip",function(e){T.tooltipHide(e)}),T.on("tooltipHide",function(){o&&e.tooltip.cleanup()}),C.dispatch=T,C.lines1=d,C.lines2=v,C.bars1=m,C.bars2=g,C.stack1=y,C.stack2=b,C.xAxis=w,C.yAxis1=E,C.yAxis2=S,C.options=e.utils.optionsFunc.bind(C),C.x=function(e){return arguments.length?(getX=e,d.x(e),m.x(e),C):getX},C.y=function(e){return arguments.length?(getY=e,d.y(e),m.y(e),C):getY},C.yDomain1=function(e){return arguments.length?(l=e,C):l},C.yDomain2=function(e){return arguments.length?(c=e,C):c},C.margin=function(e){return arguments.length?(t=e,C):t},C.width=function(e){return arguments.length?(r=e,C):r},C.height=function(e){return arguments.length?(i=e,C):i},C.color=function(e){return arguments.length?(n=e,x.color(e),C):n},C.showLegend=function(e){return arguments.length?(s=e,C):s},C.tooltips=function(e){return arguments.length?(o=e,C):o},C.tooltipContent=function(e){return arguments.length?(u=e,C):u},C},e.models.ohlcBar=function(){"use strict";function x(e){return e.each(function(e){var g=n-t.left-t.right,x=r-t.top-t.bottom,T=d3.select(this);s.domain(y||d3.extent(e[0].values.map(u).concat(p))),v?s.range(w||[g*.5/e[0].values.length,g*(e[0].values.length-.5)/e[0].values.length]):s.range(w||[0,g]),o.domain(b||[d3.min(e[0].values.map(h).concat(d)),d3.max(e[0].values.map(c).concat(d))]).range(E||[x,0]),s.domain()[0]===s.domain()[1]&&(s.domain()[0]?s.domain([s.domain()[0]-s.domain()[0]*.01,s.domain()[1]+s.domain()[1]*.01]):s.domain([-1,1])),o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]+o.domain()[0]*.01,o.domain()[1]-o.domain()[1]*.01]):o.domain([-1,1]));var N=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([e[0].values]),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),k=C.append("defs"),L=C.append("g"),A=N.select("g");L.append("g").attr("class","nv-ticks"),N.attr("transform","translate("+t.left+","+t.top+")"),T.on("click",function(e,t){S.chartClick({data:e,index:t,pos:d3.event,id:i})}),k.append("clipPath").attr("id","nv-chart-clip-path-"+i).append("rect"),N.select("#nv-chart-clip-path-"+i+" rect").attr("width",g).attr("height",x),A.attr("clip-path",m?"url(#nv-chart-clip-path-"+i+")":"");var O=N.select(".nv-ticks").selectAll(".nv-tick").data(function(e){return e});O.exit().remove();var M=O.enter().append("path").attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"}).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).on("mouseover",function(t,n){d3.select(this).classed("hover",!0),S.elementMouseover({point:t,series:e[0],pos:[s(u(t,n)),o(a(t,n))],pointIndex:n,seriesIndex:0,e:d3.event})}).on("mouseout",function(t,n){d3.select(this).classed("hover",!1),S.elementMouseout({point:t,series:e[0],pointIndex:n,seriesIndex:0,e:d3.event})}).on("click",function(e,t){S.elementClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()}).on("dblclick",function(e,t){S.elementDblClick({value:a(e,t),data:e,index:t,pos:[s(u(e,t)),o(a(e,t))],e:d3.event,id:i}),d3.event.stopPropagation()});O.attr("class",function(e,t,n){return(f(e,t)>l(e,t)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+n+"-"+t}),d3.transition(O).attr("transform",function(e,t){return"translate("+s(u(e,t))+","+o(c(e,t))+")"}).attr("d",function(t,n){var r=g/e[0].values.length*.9;return"m0,0l0,"+(o(f(t,n))-o(c(t,n)))+"l"+ -r/2+",0l"+r/2+",0l0,"+(o(h(t,n))-o(f(t,n)))+"l0,"+(o(l(t,n))-o(h(t,n)))+"l"+r/2+",0l"+ -r/2+",0z"})}),x}var t={top:0 +,right:0,bottom:0,left:0},n=960,r=500,i=Math.floor(Math.random()*1e4),s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=function(e){return e.open},l=function(e){return e.close},c=function(e){return e.high},h=function(e){return e.low},p=[],d=[],v=!1,m=!0,g=e.utils.defaultColor(),y,b,w,E,S=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return x.dispatch=S,x.options=e.utils.optionsFunc.bind(x),x.x=function(e){return arguments.length?(u=e,x):u},x.y=function(e){return arguments.length?(a=e,x):a},x.open=function(e){return arguments.length?(f=e,x):f},x.close=function(e){return arguments.length?(l=e,x):l},x.high=function(e){return arguments.length?(c=e,x):c},x.low=function(e){return arguments.length?(h=e,x):h},x.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,x):t},x.width=function(e){return arguments.length?(n=e,x):n},x.height=function(e){return arguments.length?(r=e,x):r},x.xScale=function(e){return arguments.length?(s=e,x):s},x.yScale=function(e){return arguments.length?(o=e,x):o},x.xDomain=function(e){return arguments.length?(y=e,x):y},x.yDomain=function(e){return arguments.length?(b=e,x):b},x.xRange=function(e){return arguments.length?(w=e,x):w},x.yRange=function(e){return arguments.length?(E=e,x):E},x.forceX=function(e){return arguments.length?(p=e,x):p},x.forceY=function(e){return arguments.length?(d=e,x):d},x.padData=function(e){return arguments.length?(v=e,x):v},x.clipEdge=function(e){return arguments.length?(m=e,x):m},x.color=function(t){return arguments.length?(g=e.utils.getColor(t),x):g},x.id=function(e){return arguments.length?(i=e,x):i},x},e.models.pie=function(){"use strict";function S(e){return e.each(function(e){function q(e){var t=(e.startAngle+e.endAngle)*90/Math.PI-90;return t>90?t-180:t}function R(e){e.endAngle=isNaN(e.endAngle)?0:e.endAngle,e.startAngle=isNaN(e.startAngle)?0:e.startAngle,m||(e.innerRadius=0);var t=d3.interpolate(this._current,e);return this._current=t(0),function(e){return A(t(e))}}function U(e){e.innerRadius=0;var t=d3.interpolate({startAngle:0,endAngle:0},e);return function(e){return A(t(e))}}var o=n-t.left-t.right,f=r-t.top-t.bottom,S=Math.min(o,f)/2,x=S-S/5,T=d3.select(this),N=T.selectAll(".nv-wrap.nv-pie").data(e),C=N.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+u),k=C.append("g"),L=N.select("g");k.append("g").attr("class","nv-pie"),k.append("g").attr("class","nv-pieLabels"),N.attr("transform","translate("+t.left+","+t.top+")"),L.select(".nv-pie").attr("transform","translate("+o/2+","+f/2+")"),L.select(".nv-pieLabels").attr("transform","translate("+o/2+","+f/2+")"),T.on("click",function(e,t){E.chartClick({data:e,index:t,pos:d3.event,id:u})});var A=d3.svg.arc().outerRadius(x);y&&A.startAngle(y),b&&A.endAngle(b),m&&A.innerRadius(S*w);var O=d3.layout.pie().sort(null).value(function(e){return e.disabled?0:s(e)}),M=N.select(".nv-pie").selectAll(".nv-slice").data(O),_=N.select(".nv-pieLabels").selectAll(".nv-label").data(O);M.exit().remove(),_.exit().remove();var D=M.enter().append("g").attr("class","nv-slice").on("mouseover",function(e,t){d3.select(this).classed("hover",!0),E.elementMouseover({label:i(e.data),value:s(e.data),point:e.data,pointIndex:t,pos:[d3.event.pageX,d3.event.pageY],id:u})}).on("mouseout",function(e,t){d3.select(this).classed("hover",!1),E.elementMouseout({label:i(e.data),value:s(e.data),point:e.data,index:t,id:u})}).on("click",function(e,t){E.elementClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()}).on("dblclick",function(e,t){E.elementDblClick({label:i(e.data),value:s(e.data),point:e.data,index:t,pos:d3.event,id:u}),d3.event.stopPropagation()});M.attr("fill",function(e,t){return a(e,t)}).attr("stroke",function(e,t){return a(e,t)});var P=D.append("path").each(function(e){this._current=e});M.select("path").transition().attr("d",A).attrTween("d",R);if(l){var H=d3.svg.arc().innerRadius(0);c&&(H=A),h&&(H=d3.svg.arc().outerRadius(A.outerRadius())),_.enter().append("g").classed("nv-label",!0).each(function(e,t){var n=d3.select(this);n.attr("transform",function(e){if(g){e.outerRadius=x+10,e.innerRadius=x+15;var t=(e.startAngle+e.endAngle)/2*(180/Math.PI);return(e.startAngle+e.endAngle)/2v?r[p]:""})}}),S}var t={top:0,right:0,bottom:0,left:0},n=500,r=500,i=function(e){return e.x},s=function(e){return e.y},o=function(e){return e.description},u=Math.floor(Math.random()*1e4),a=e.utils.defaultColor(),f=d3.format(",.2f"),l=!0,c=!0,h=!1,p="key",v=.02,m=!1,g=!1,y=!1,b=!1,w=.5,E=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return S.dispatch=E,S.options=e.utils.optionsFunc.bind(S),S.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,S):t},S.width=function(e){return arguments.length?(n=e,S):n},S.height=function(e){return arguments.length?(r=e,S):r},S.values=function(t){return e.log("pie.values() is no longer supported."),S},S.x=function(e){return arguments.length?(i=e,S):i},S.y=function(e){return arguments.length?(s=d3.functor(e),S):s},S.description=function(e){return arguments.length?(o=e,S):o},S.showLabels=function(e){return arguments.length?(l=e,S):l},S.labelSunbeamLayout=function(e){return arguments.length?(g=e,S):g},S.donutLabelsOutside=function(e){return arguments.length?(h=e,S):h},S.pieLabelsOutside=function(e){return arguments.length?(c=e,S):c},S.labelType=function(e){return arguments.length?(p=e,p=p||"key",S):p},S.donut=function(e){return arguments.length?(m=e,S):m},S.donutRatio=function(e){return arguments.length?(w=e,S):w},S.startAngle=function(e){return arguments.length?(y=e,S):y},S.endAngle=function(e){return arguments.length?(b=e,S):b},S.id=function(e){return arguments.length?(u=e,S):u},S.color=function(t){return arguments.length?(a=e.utils.getColor(t),S):a},S.valueFormat=function(e){return arguments.length?(f=e,S):f},S.labelThreshold=function(e){return arguments.length?(v=e,S):v},S},e.models.pieChart=function(){"use strict";function v(e){return e.each(function(e){var u=d3.select(this),a=this,f=(i||parseInt(u.style("width"))||960)-r.left-r.right,d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom;v.update=function(){u.transition().call(v)},v.container=this,l.disabled=e.map(function(e){return!!e.disabled});if(!c){var m;c={};for(m in l)l[m]instanceof Array?c[m]=l[m].slice(0):c[m]=l[m]}if(!e||!e.length){var g=u.selectAll(".nv-noData").data([h]);return g.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),g.attr("x",r.left+f/2).attr("y",r.top+d/2).text(function(e){return e}),v}u.selectAll(".nv-noData").remove();var y=u.selectAll("g.nv-wrap.nv-pieChart").data([e]),b=y.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=y.select("g");b.append("g").attr("class","nv-pieWrap"),b.append("g").attr("class","nv-legendWrap"),o&&(n.width(f).key(t.x()),y.select(".nv-legendWrap").datum(e).call(n),r.top!=n.height()&&(r.top=n.height(),d=(s||parseInt(u.style("height"))||400)-r.top-r.bottom),y.select(".nv-legendWrap").attr("transform","translate(0,"+ -r.top+")")),y.attr("transform","translate("+r.left+","+r.top+")"),t.width(f).height(d);var E=w.select(".nv-pieWrap").datum([e]);d3.transition(E).call(t),n.dispatch.on("stateChange",function(e){l=e,p.stateChange(l),v.update()}),t.dispatch.on("elementMouseout.tooltip",function(e){p.tooltipHide(e)}),p.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),l.disabled=t.disabled),v.update()})}),v}var t=e.models.pie(),n=e.models.legend(),r={top:30,right:20,bottom:20,left:20},i=null,s=null,o=!0,u=e.utils.defaultColor(),a=!0,f=function(e,t,n,r){return"

    "+e+"

    "+"

    "+t+"

    "},l={},c=null,h="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),d=function(n,r){var i=t.description()(n.point)||t.x()(n.point),s=n.pos[0]+(r&&r.offsetLeft||0),o=n.pos[1]+(r&&r.offsetTop||0),u=t.valueFormat()(t.y()(n.point)),a=f(i,u,n,v);e.tooltip.show([s,o],a,n.value<0?"n":"s",null,r)};return t.dispatch.on("elementMouseover.tooltip",function(e){e.pos=[e.pos[0]+r.left,e.pos[1]+r.top],p.tooltipShow(e)}),p.on("tooltipShow",function(e){a&&d(e)}),p.on("tooltipHide",function(){a&&e.tooltip.cleanup()}),v.legend=n,v.dispatch=p,v.pie=t,d3.rebind(v,t,"valueFormat","values","x","y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","labelType","donut","donutRatio","labelThreshold"),v.options=e.utils.optionsFunc.bind(v),v.margin=function(e){return arguments.length?(r.top=typeof e.top!="undefined"?e.top:r.top,r.right=typeof e.right!="undefined"?e.right:r.right,r.bottom=typeof e.bottom!="undefined"?e.bottom:r.bottom,r.left=typeof e.left!="undefined"?e.left:r.left,v):r},v.width=function(e){return arguments.length?(i=e,v):i},v.height=function(e){return arguments.length?(s=e,v):s},v.color=function(r){return arguments.length?(u=e.utils.getColor(r),n.color(u),t.color(u),v):u},v.showLegend=function(e){return arguments.length?(o=e,v):o},v.tooltips=function(e){return arguments.length?(a=e,v):a},v.tooltipContent=function(e){return arguments.length?(f=e,v):f},v.state=function(e){return arguments.length?(l=e,v):l},v.defaultState=function(e){return arguments.length?(c=e,v):c},v.noData=function(e){return arguments.length?(h=e,v):h},v},e.models.scatter=function(){"use strict";function I(q){return q.each(function(I){function Q(){if(!g)return!1;var e,i=d3.merge(I.map(function(e,t){return e.values.map(function(e,n){var r=f(e,n),i=l(e,n);return[o(r)+Math.random()*1e-7,u(i)+Math.random()*1e-7,t,n,e]}).filter(function(e,t){return b(e[4],t)})}));if(D===!0){if(x){var a=X.select("defs").selectAll(".nv-point-clips").data([s]).enter();a.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+s);var c=X.select("#nv-points-clip-"+s).selectAll("circle").data(i);c.enter().append("circle").attr("r",T),c.exit().remove(),c.attr("cx",function(e){return e[0]}).attr("cy",function(e){return e[1]}),X.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+s+")")}i.length&&(i.push([o.range()[0]-20,u.range()[0]-20,null,null]),i.push([o.range()[1]+20,u.range()[1]+20,null,null]),i.push([o.range()[0]-20,u.range()[0]+20,null,null]),i.push([o.range()[1]+20,u.range()[1]-20,null,null]));var h=d3.geom.polygon([[-10,-10],[-10,r+10],[n+10,r+10],[n+10,-10]]),p=d3.geom.voronoi(i).map(function(e,t){return{data:h.clip(e),series:i[t][2],point:i[t][3]}}),d=X.select(".nv-point-paths").selectAll("path").data(p);d.enter().append("path").attr("class",function(e,t){return"nv-path-"+t}),d.exit().remove(),d.attr("d",function(e){return e.data.length===0?"M 0 0":"M"+e.data.join("L")+"Z"});var v=function(e,n){if(F)return 0;var r=I[e.series];if(typeof r=="undefined")return;var i=r.values[e.point];n({point:i,series:r,pos:[o(f(i,e.point))+t.left,u(l(i,e.point))+t.top],seriesIndex:e.series,pointIndex:e.point})};d.on("click",function(e){v(e,_.elementClick)}).on("mouseover",function(e){v(e,_.elementMouseover)}).on("mouseout",function(e,t){v(e,_.elementMouseout)})}else X.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementClick({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseover",function(e,n){if(F||!I[e.series])return 0;var r=I[e.series],i=r.values[n];_.elementMouseover({point:i,series:r,pos:[o(f(i,n))+t.left,u(l(i,n))+t.top],seriesIndex:e.series,pointIndex:n})}).on("mouseout",function(e,t){if(F||!I[e.series])return 0;var n=I[e.series],r=n.values[t];_.elementMouseout({point:r,series:n,seriesIndex:e.series,pointIndex:t})});F=!1}var q=n-t.left-t.right,R=r-t.top-t.bottom,U=d3.select(this);I.forEach(function(e,t){e.values.forEach(function(e){e.series=t})});var W=N&&C&&A?[]:d3.merge(I.map(function(e){return e.values.map(function(e,t){return{x:f(e,t),y:l(e,t),size:c(e,t)}})}));o.domain(N||d3.extent(W.map(function(e){return e.x}).concat(d))),w&&I[0]?o.range(k||[(q*E+q)/(2*I[0].values.length),q-q*(1+E)/(2*I[0].values.length)]):o.range(k||[0,q]),u.domain(C||d3.extent(W.map(function(e){return e.y}).concat(v))).range(L||[R,0]),a.domain(A||d3.extent(W.map(function(e){return e.size}).concat(m))).range(O||[16,256]);if(o.domain()[0]===o.domain()[1]||u.domain()[0]===u.domain()[1])M=!0;o.domain()[0]===o.domain()[1]&&(o.domain()[0]?o.domain([o.domain()[0]-o.domain()[0]*.01,o.domain()[1]+o.domain()[1]*.01]):o.domain([-1,1])),u.domain()[0]===u.domain()[1]&&(u.domain()[0]?u.domain([u.domain()[0]-u.domain()[0]*.01,u.domain()[1]+u.domain()[1]*.01]):u.domain([-1,1])),isNaN(o.domain()[0])&&o.domain([-1,1]),isNaN(u.domain()[0])&&u.domain([-1,1]),P=P||o,H=H||u,B=B||a;var X=U.selectAll("g.nv-wrap.nv-scatter").data([I]),V=X.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+s+(M?" nv-single-point":"")),$=V.append("defs"),J=V.append("g"),K=X.select("g");J.append("g").attr("class","nv-groups"),J.append("g").attr("class","nv-point-paths"),X.attr("transform","translate("+t.left+","+t.top+")"),$.append("clipPath").attr("id","nv-edge-clip-"+s).append("rect"),X.select("#nv-edge-clip-"+s+" rect").attr("width",q).attr("height",R>0?R:0),K.attr("clip-path",S?"url(#nv-edge-clip-"+s+")":""),F=!0;var G=X.select(".nv-groups").selectAll(".nv-group").data(function(e){return e},function(e){return e.key});G.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),G.exit().remove(),G.attr("class",function(e,t){return"nv-group nv-series-"+t}).classed("hover",function(e){return e.hover}),G.transition().style("fill",function(e,t){return i(e,t)}).style("stroke",function(e,t){return i(e,t)}).style("stroke-opacity",1).style("fill-opacity",.5);if(p){var Y=G.selectAll("circle.nv-point").data(function(e){return e.values},y);Y.enter().append("circle").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("cx",function(t,n){return e.utils.NaNtoZero(P(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(H(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)}),Y.exit().remove(),G.exit().selectAll("path.nv-point").transition().attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.transition().attr("cx",function(t,n){return e.utils.NaNtoZero(o(f(t,n)))}).attr("cy",function(t,n){return e.utils.NaNtoZero(u(l(t,n)))}).attr("r",function(e,t){return Math.sqrt(a(c(e,t))/Math.PI)})}else{var Y=G.selectAll("path.nv-point").data(function(e){return e.values});Y.enter().append("path").style("fill",function(e,t){return e.color}).style("stroke",function(e,t){return e.color}).attr("transform",function(e,t){return"translate("+P(f(e,t))+","+H(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))})),Y.exit().remove(),G.exit().selectAll("path.nv-point").transition().attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).remove(),Y.each(function(e,t){d3.select(this).classed("nv-point",!0).classed("nv-point-"+t,!0).classed("hover",!1)}),Y.transition().attr("transform",function(e,t){return"translate("+o(f(e,t))+","+u(l(e,t))+")"}).attr("d",d3.svg.symbol().type(h).size(function(e,t){return a(c(e,t))}))}clearTimeout(j),j=setTimeout(Q,300),P=o.copy(),H=u.copy(),B=a.copy()}),I}var t={top:0,right:0,bottom:0,left:0},n=960,r=500,i=e.utils.defaultColor(),s=Math.floor(Math.random()*1e5),o=d3.scale.linear(),u=d3.scale.linear(),a=d3.scale.linear(),f=function(e){return e.x},l=function(e){return e.y},c=function(e){return e.size||1},h=function(e){return e.shape||"circle"},p=!0,d=[],v=[],m=[],g=!0,y=null,b=function(e){return!e.notActive},w=!1,E=.1,S=!1,x=!0,T=function(){return 25},N=null,C=null,k=null,L=null,A=null,O=null,M=!1,_=d3.dispatch("elementClick","elementMouseover","elementMouseout"),D=!0,P,H,B,j,F=!1;return I.clearHighlights=function(){d3.selectAll(".nv-chart-"+s+" .nv-point.hover").classed("hover",!1)},I.highlightPoint=function(e,t,n){d3.select(".nv-chart-"+s+" .nv-series-"+e+" .nv-point-"+t).classed("hover",n)},_.on("elementMouseover.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!0)}),_.on("elementMouseout.point",function(e){g&&I.highlightPoint(e.seriesIndex,e.pointIndex,!1)}),I.dispatch=_,I.options=e.utils.optionsFunc.bind(I),I.x=function(e){return arguments.length?(f=d3.functor(e),I):f},I.y=function(e){return arguments.length?(l=d3.functor(e),I):l},I.size=function(e){return arguments.length?(c=d3.functor(e),I):c},I.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,I):t},I.width=function(e){return arguments.length?(n=e,I):n},I.height=function(e){return arguments.length?(r=e,I):r},I.xScale=function(e){return arguments.length?(o=e,I):o},I.yScale=function(e){return arguments.length?(u=e,I):u},I.zScale=function(e){return arguments.length?(a=e,I):a},I.xDomain=function(e){return arguments.length?(N=e,I):N},I.yDomain=function(e){return arguments.length?(C=e,I):C},I.sizeDomain=function(e){return arguments.length?(A=e,I):A},I.xRange=function(e){return arguments.length?(k=e,I):k},I.yRange=function(e){return arguments.length?(L=e,I):L},I.sizeRange=function(e){return arguments.length?(O=e,I):O},I.forceX=function(e){return arguments.length?(d=e,I):d},I.forceY=function(e){return arguments.length?(v=e,I):v},I.forceSize=function(e){return arguments.length?(m=e,I):m},I.interactive=function(e){return arguments.length?(g=e,I):g},I.pointKey=function(e){return arguments.length?(y=e,I):y},I.pointActive=function(e){return arguments.length?(b=e,I):b},I.padData=function(e){return arguments.length?(w=e,I):w},I.padDataOuter=function(e){return arguments.length?(E=e,I):E},I.clipEdge=function(e){return arguments.length?(S=e,I):S},I.clipVoronoi=function(e){return arguments.length?(x=e,I):x},I.useVoronoi=function(e){return arguments.length?(D=e,D===!1&&(x=!1),I):D},I.clipRadius=function(e){return arguments.length?(T=e,I):T},I.color=function(t){return arguments.length?(i=e.utils.getColor(t),I):i},I.shape=function(e){return arguments.length?(h=e,I):h},I.onlyCircles=function(e){return arguments.length?(p=e,I):p},I.id=function(e){return arguments.length?(s=e,I):s},I.singlePoint=function(e){return arguments.length?(M=e,I):M},I},e.models.scatterChart=function(){"use strict";function F(e){return e.each(function(e){function K(){if(T)return X.select(".nv-point-paths").style("pointer-events","all"),!1;X.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(x).focus(i[0]),p.distortion(x).focus(i[1]),X.select(".nv-scatterWrap").call(t),b&&X.select(".nv-x.nv-axis").call(n),w&&X.select(".nv-y.nv-axis").call(r),X.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),X.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var C=d3.select(this),k=this,L=(f||parseInt(C.style("width"))||960)-a.left-a.right,I=(l||parseInt(C.style("height"))||400)-a.top-a.bottom;F.update=function(){C.transition().duration(D).call(F)},F.container=this,A.disabled=e.map(function(e){return!!e.disabled});if(!O){var q;O={};for(q in A)A[q]instanceof Array?O[q]=A[q].slice(0):O[q]=A[q]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var R=C.selectAll(".nv-noData").data([_]);return R.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),R.attr("x",a.left+L/2).attr("y",a.top+I/2).text(function(e){return e}),F}C.selectAll(".nv-noData").remove(),P=P||h,H=H||p;var U=C.selectAll("g.nv-wrap.nv-scatterChart").data([e]),z=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),W=z.append("g"),X=U.select("g");W.append("rect").attr("class","nvd3 nv-background"),W.append("g").attr("class","nv-x nv-axis"),W.append("g").attr("class","nv-y nv-axis"),W.append("g").attr("class","nv-scatterWrap"),W.append("g").attr("class","nv-distWrap"),W.append("g").attr("class","nv-legendWrap"),W.append("g").attr("class","nv-controlsWrap");if(y){var V=S?L/2:L;i.width(V),U.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),I=(l||parseInt(C.style("height"))||400)-a.top-a.bottom),U.select(".nv-legendWrap").attr("transform","translate("+(L-V)+","+ -a.top+")")}S&&(s.width(180).color(["#444"]),X.select(".nv-controlsWrap").datum(j).attr("transform","translate(0,"+ -a.top+")").call(s)),U.attr("transform","translate("+a.left+","+a.top+")"),E&&X.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),t.width(L).height(I).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),d!==0&&t.xDomain(null),v!==0&&t.yDomain(null),U.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t);if(d!==0){var $=h.domain()[1]-h.domain()[0];t.xDomain([h.domain()[0]-d*$,h.domain()[1]+d*$])}if(v!==0){var J=p.domain()[1]-p.domain()[0];t.yDomain([p.domain()[0]-v*J,p.domain()[1]+v*J])}(v!==0||d!==0)&&U.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),b&&(n.scale(h).ticks(n.ticks()&&n.ticks().length?n.ticks():L/100).tickSize(-I,0),X.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),w&&(r.scale(p).ticks(r.ticks()&&r.ticks().length?r.ticks():I/36).tickSize(-L,0),X.select(".nv-y.nv-axis").call(r)),m&&(o.getData(t.x()).scale(h).width(L).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),W.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),X.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),g&&(u.getData(t.y()).scale(p).width(I).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),W.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),X.select(".nv-distributionY").attr("transform","translate("+(E?L:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(X.select(".nv-background").attr("width",L).attr("height",I),X.select(".nv-background").on("mousemove",K),X.select(".nv-background").on("click",function(){T=!T}),t.dispatch.on("elementClick.freezeFisheye",function(){T=!T})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,x=e.disabled?0:2.5,X.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),X.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(x).focus(0),p.distortion(x).focus(0),X.select(".nv-scatterWrap").call(t),X.select(".nv-x.nv-axis").call(n),X.select(".nv-y.nv-axis").call(r)):T=!1,F.update()}),i.dispatch.on("stateChange",function(e){A.disabled=e.disabled,M.stateChange(A),F.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",function(t,n){return e.pos[1]-I}),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],M.tooltipShow(e)}),M.on("tooltipShow",function(e){N&&B(e,k.parentNode)}),M.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),A.disabled=t.disabled),F.update()}),P=h.copy(),H=p.copy()}),F}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=0,v=0,m=!1,g=!1,y=!0,b=!0,w=!0,E=!1,S=!!d3.fisheye,x=0,T=!1,N=!0,C=function(e,t,n){return""+t+""},k=function(e,t,n){return""+n+""},L=null,A={},O=null,M=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),_="No Data Available.",D=250;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(E?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var P,H,B=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));C!=null&&e.tooltip.show([f,l],C(i.series.key,v,m,i,F),"n",1,s,"x-nvtooltip"),k!=null&&e.tooltip.show([c,d],k(i.series.key,v,m,i,F),"e",1,s,"y-nvtooltip"),L!=null&&e.tooltip.show([o,u],L(i.series.key,v,m,i,F),i.value<0?"n":"s",null,s)},j=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){M.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),M.on("tooltipHide",function(){N&&e.tooltip.cleanup()}),F.dispatch=M,F.scatter=t,F.legend=i,F.controls=s,F.xAxis=n,F.yAxis=r,F.distX=o,F.distY=u,d3.rebind(F,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),F.options=e.utils.optionsFunc.bind(F),F.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,F):a},F.width=function(e){return arguments.length?(f=e,F):f},F.height=function(e){return arguments.length?(l=e,F):l},F.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),F):c},F.showDistX=function(e){return arguments.length?(m=e,F):m},F.showDistY=function(e){return arguments.length?(g=e,F):g},F.showControls=function(e){return arguments.length?(S=e,F):S},F.showLegend=function(e){return arguments.length?(y=e,F):y},F.showXAxis=function(e){return arguments.length?(b=e,F):b},F.showYAxis=function(e){return arguments.length?(w=e,F):w},F.rightAlignYAxis=function(e){return arguments.length?(E=e,r.orient(e?"right":"left"),F):E},F.fisheye=function(e){return arguments.length?(x=e,F):x},F.xPadding=function(e){return arguments.length?(d=e,F):d},F.yPadding=function(e){return arguments.length?(v=e,F):v},F.tooltips=function(e){return arguments.length?(N=e,F):N},F.tooltipContent=function(e){return arguments.length?(L=e,F):L},F.tooltipXContent=function(e){return arguments.length?(C=e,F):C},F.tooltipYContent=function(e){return arguments.length?(k=e,F):k},F.state=function(e){return arguments.length?(A=e,F):A},F.defaultState=function(e){return arguments.length?(O=e,F):O},F.noData=function(e){return arguments.length?(_=e,F):_},F.transitionDuration=function(e){return arguments.length?(D=e,F):D},F},e.models.scatterPlusLineChart=function(){"use strict";function B(e){return e.each(function(e){function $(){if(S)return z.select(".nv-point-paths").style("pointer-events","all"),!1;z.select(".nv-point-paths").style("pointer-events","none");var i=d3.mouse(this);h.distortion(E).focus(i[0]),p.distortion(E).focus(i[1]),z.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),g&&z.select(".nv-x.nv-axis").call(n),y&&z.select(".nv-y.nv-axis").call(r),z.select(".nv-distributionX").datum(e.filter(function(e){return!e.disabled})).call(o),z.select(".nv-distributionY").datum(e.filter(function(e){return!e.disabled})).call(u)}var T=d3.select(this),N=this,C=(f||parseInt(T.style("width"))||960)-a.left-a.right,j=(l||parseInt(T.style("height"))||400)-a.top-a.bottom;B.update=function(){T.transition().duration(M).call(B)},B.container=this,k.disabled=e.map(function(e){return!!e.disabled});if(!L){var F;L={};for(F in k)k[F]instanceof Array?L[F]=k[F].slice(0):L[F]=k[F]}if(!e||!e.length||!e.filter(function(e){return e.values.length}).length){var I=T.selectAll(".nv-noData").data([O]);return I.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),I.attr("x",a.left+C/2).attr("y",a.top+j/2).text(function(e){return e}),B}T.selectAll(".nv-noData").remove(),h=t.xScale(),p=t.yScale(),_=_||h,D=D||p;var q=T.selectAll("g.nv-wrap.nv-scatterChart").data([e]),R=q.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+t.id()),U=R.append("g"),z=q.select("g");U.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),U.append("g").attr("class","nv-x nv-axis"),U.append("g").attr("class","nv-y nv-axis"),U.append("g").attr("class","nv-scatterWrap"),U.append("g").attr("class","nv-regressionLinesWrap"),U.append("g").attr("class","nv-distWrap"),U.append("g").attr("class","nv-legendWrap"),U.append("g").attr("class","nv-controlsWrap"),q.attr("transform","translate("+a.left+","+a.top+")"),b&&z.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),m&&(i.width(C/2),q.select(".nv-legendWrap").datum(e).call(i),a.top!=i.height()&&(a.top=i.height(),j=(l||parseInt(T.style("height"))||400)-a.top-a.bottom),q.select(".nv-legendWrap").attr("transform","translate("+C/2+","+ -a.top+")")),w&&(s.width(180).color(["#444"]),z.select(".nv-controlsWrap").datum(H).attr("transform","translate(0,"+ -a.top+")").call(s)),t.width(C).height(j).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),q.select(".nv-scatterWrap").datum(e.filter(function(e){return!e.disabled})).call(t),q.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+t.id()+")");var W=q.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(e){return e});W.enter().append("g").attr("class","nv-regLines");var X=W.selectAll(".nv-regLine").data(function(e){return[e]}),V=X.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0);X.transition().attr("x1",h.range()[0]).attr("x2",h.range()[1]).attr("y1",function(e,t){return p(h.domain()[0]*e.slope+e.intercept)}).attr("y2",function(e,t){return p(h.domain()[1]*e.slope+e.intercept)}).style("stroke",function(e,t,n){return c(e,n)}).style("stroke-opacity",function(e,t){return e.disabled||typeof e.slope=="undefined"||typeof e.intercept=="undefined"?0:1}),g&&(n.scale(h).ticks(n.ticks()?n.ticks():C/100).tickSize(-j,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(n)),y&&(r.scale(p).ticks(r.ticks()?r.ticks():j/36).tickSize(-C,0),z.select(".nv-y.nv-axis").call(r)),d&&(o.getData(t.x()).scale(h).width(C).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),U.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),z.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(e.filter(function(e){return!e.disabled})).call(o)),v&&(u.getData(t.y()).scale(p).width( +j).color(e.map(function(e,t){return e.color||c(e,t)}).filter(function(t,n){return!e[n].disabled})),U.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),z.select(".nv-distributionY").attr("transform","translate("+(b?C:-u.size())+",0)").datum(e.filter(function(e){return!e.disabled})).call(u)),d3.fisheye&&(z.select(".nv-background").attr("width",C).attr("height",j),z.select(".nv-background").on("mousemove",$),z.select(".nv-background").on("click",function(){S=!S}),t.dispatch.on("elementClick.freezeFisheye",function(){S=!S})),s.dispatch.on("legendClick",function(e,i){e.disabled=!e.disabled,E=e.disabled?0:2.5,z.select(".nv-background").style("pointer-events",e.disabled?"none":"all"),z.select(".nv-point-paths").style("pointer-events",e.disabled?"all":"none"),e.disabled?(h.distortion(E).focus(0),p.distortion(E).focus(0),z.select(".nv-scatterWrap").call(t),z.select(".nv-x.nv-axis").call(n),z.select(".nv-y.nv-axis").call(r)):S=!1,B.update()}),i.dispatch.on("stateChange",function(e){k=e,A.stateChange(k),B.update()}),t.dispatch.on("elementMouseover.tooltip",function(e){d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",e.pos[1]-j),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",e.pos[0]+o.size()),e.pos=[e.pos[0]+a.left,e.pos[1]+a.top],A.tooltipShow(e)}),A.on("tooltipShow",function(e){x&&P(e,N.parentNode)}),A.on("changeState",function(t){typeof t.disabled!="undefined"&&(e.forEach(function(e,n){e.disabled=t.disabled[n]}),k.disabled=t.disabled),B.update()}),_=h.copy(),D=p.copy()}),B}var t=e.models.scatter(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.models.distribution(),u=e.models.distribution(),a={top:30,right:20,bottom:50,left:75},f=null,l=null,c=e.utils.defaultColor(),h=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.xScale(),p=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):t.yScale(),d=!1,v=!1,m=!0,g=!0,y=!0,b=!1,w=!!d3.fisheye,E=0,S=!1,x=!0,T=function(e,t,n){return""+t+""},N=function(e,t,n){return""+n+""},C=function(e,t,n,r){return"

    "+e+"

    "+"

    "+r+"

    "},k={},L=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),O="No Data Available.",M=250;t.xScale(h).yScale(p),n.orient("bottom").tickPadding(10),r.orient(b?"right":"left").tickPadding(10),o.axis("x"),u.axis("y"),s.updateState(!1);var _,D,P=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),f=i.pos[0]+(s.offsetLeft||0),l=p.range()[0]+a.top+(s.offsetTop||0),c=h.range()[0]+a.left+(s.offsetLeft||0),d=i.pos[1]+(s.offsetTop||0),v=n.tickFormat()(t.x()(i.point,i.pointIndex)),m=r.tickFormat()(t.y()(i.point,i.pointIndex));T!=null&&e.tooltip.show([f,l],T(i.series.key,v,m,i,B),"n",1,s,"x-nvtooltip"),N!=null&&e.tooltip.show([c,d],N(i.series.key,v,m,i,B),"e",1,s,"y-nvtooltip"),C!=null&&e.tooltip.show([o,u],C(i.series.key,v,m,i.point.tooltip,i,B),i.value<0?"n":"s",null,s)},H=[{key:"Magnify",disabled:!0}];return t.dispatch.on("elementMouseout.tooltip",function(e){A.tooltipHide(e),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-distx-"+e.pointIndex).attr("y1",0),d3.select(".nv-chart-"+t.id()+" .nv-series-"+e.seriesIndex+" .nv-disty-"+e.pointIndex).attr("x2",u.size())}),A.on("tooltipHide",function(){x&&e.tooltip.cleanup()}),B.dispatch=A,B.scatter=t,B.legend=i,B.controls=s,B.xAxis=n,B.yAxis=r,B.distX=o,B.distY=u,d3.rebind(B,t,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),B.options=e.utils.optionsFunc.bind(B),B.margin=function(e){return arguments.length?(a.top=typeof e.top!="undefined"?e.top:a.top,a.right=typeof e.right!="undefined"?e.right:a.right,a.bottom=typeof e.bottom!="undefined"?e.bottom:a.bottom,a.left=typeof e.left!="undefined"?e.left:a.left,B):a},B.width=function(e){return arguments.length?(f=e,B):f},B.height=function(e){return arguments.length?(l=e,B):l},B.color=function(t){return arguments.length?(c=e.utils.getColor(t),i.color(c),o.color(c),u.color(c),B):c},B.showDistX=function(e){return arguments.length?(d=e,B):d},B.showDistY=function(e){return arguments.length?(v=e,B):v},B.showControls=function(e){return arguments.length?(w=e,B):w},B.showLegend=function(e){return arguments.length?(m=e,B):m},B.showXAxis=function(e){return arguments.length?(g=e,B):g},B.showYAxis=function(e){return arguments.length?(y=e,B):y},B.rightAlignYAxis=function(e){return arguments.length?(b=e,r.orient(e?"right":"left"),B):b},B.fisheye=function(e){return arguments.length?(E=e,B):E},B.tooltips=function(e){return arguments.length?(x=e,B):x},B.tooltipContent=function(e){return arguments.length?(C=e,B):C},B.tooltipXContent=function(e){return arguments.length?(T=e,B):T},B.tooltipYContent=function(e){return arguments.length?(N=e,B):N},B.state=function(e){return arguments.length?(k=e,B):k},B.defaultState=function(e){return arguments.length?(L=e,B):L},B.noData=function(e){return arguments.length?(O=e,B):O},B.transitionDuration=function(e){return arguments.length?(M=e,B):M},B},e.models.sparkline=function(){"use strict";function d(e){return e.each(function(e){var i=n-t.left-t.right,d=r-t.top-t.bottom,v=d3.select(this);s.domain(l||d3.extent(e,u)).range(h||[0,i]),o.domain(c||d3.extent(e,a)).range(p||[d,0]);var m=v.selectAll("g.nv-wrap.nv-sparkline").data([e]),g=m.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline"),b=g.append("g"),w=m.select("g");m.attr("transform","translate("+t.left+","+t.top+")");var E=m.selectAll("path").data(function(e){return[e]});E.enter().append("path"),E.exit().remove(),E.style("stroke",function(e,t){return e.color||f(e,t)}).attr("d",d3.svg.line().x(function(e,t){return s(u(e,t))}).y(function(e,t){return o(a(e,t))}));var S=m.selectAll("circle.nv-point").data(function(e){function n(t){if(t!=-1){var n=e[t];return n.pointIndex=t,n}return null}var t=e.map(function(e,t){return a(e,t)}),r=n(t.lastIndexOf(o.domain()[1])),i=n(t.indexOf(o.domain()[0])),s=n(t.length-1);return[i,r,s].filter(function(e){return e!=null})});S.enter().append("circle"),S.exit().remove(),S.attr("cx",function(e,t){return s(u(e,e.pointIndex))}).attr("cy",function(e,t){return o(a(e,e.pointIndex))}).attr("r",2).attr("class",function(e,t){return u(e,e.pointIndex)==s.domain()[1]?"nv-point nv-currentValue":a(e,e.pointIndex)==o.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),d}var t={top:2,right:0,bottom:2,left:0},n=400,r=32,i=!0,s=d3.scale.linear(),o=d3.scale.linear(),u=function(e){return e.x},a=function(e){return e.y},f=e.utils.getColor(["#000"]),l,c,h,p;return d.options=e.utils.optionsFunc.bind(d),d.margin=function(e){return arguments.length?(t.top=typeof e.top!="undefined"?e.top:t.top,t.right=typeof e.right!="undefined"?e.right:t.right,t.bottom=typeof e.bottom!="undefined"?e.bottom:t.bottom,t.left=typeof e.left!="undefined"?e.left:t.left,d):t},d.width=function(e){return arguments.length?(n=e,d):n},d.height=function(e){return arguments.length?(r=e,d):r},d.x=function(e){return arguments.length?(u=d3.functor(e),d):u},d.y=function(e){return arguments.length?(a=d3.functor(e),d):a},d.xScale=function(e){return arguments.length?(s=e,d):s},d.yScale=function(e){return arguments.length?(o=e,d):o},d.xDomain=function(e){return arguments.length?(l=e,d):l},d.yDomain=function(e){return arguments.length?(c=e,d):c},d.xRange=function(e){return arguments.length?(h=e,d):h},d.yRange=function(e){return arguments.length?(p=e,d):p},d.animate=function(e){return arguments.length?(i=e,d):i},d.color=function(t){return arguments.length?(f=e.utils.getColor(t),d):f},d},e.models.sparklinePlus=function(){"use strict";function v(e){return e.each(function(c){function O(){if(a)return;var e=C.selectAll(".nv-hoverValue").data(u),r=e.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);e.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),e.attr("transform",function(e){return"translate("+s(t.x()(c[e],e))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1);if(!u.length)return;r.append("line").attr("x1",0).attr("y1",-n.top).attr("x2",0).attr("y2",b),r.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-n.top).attr("text-anchor","end").attr("dy",".9em"),C.select(".nv-hoverValue .nv-xValue").text(f(t.x()(c[u[0]],u[0]))),r.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-n.top).attr("text-anchor","start").attr("dy",".9em"),C.select(".nv-hoverValue .nv-yValue").text(l(t.y()(c[u[0]],u[0])))}function M(){function r(e,n){var r=Math.abs(t.x()(e[0],0)-n),i=0;for(var s=0;s2){var h=M.yScale().invert(i.mouseY),p=Infinity,d=null;c.forEach(function(e,t){h=Math.abs(h);var n=Math.abs(e.stackedValue.y0),r=Math.abs(e.stackedValue.y);if(h>=n&&h<=r+n){d=t;return}}),d!=null&&(c[d].highlight=!0)}var v=n.tickFormat()(M.x()(s,a)),m=t.style()=="expand"?function(e,t){return d3.format(".1%")(e)}:function(e,t){return r.tickFormat()(e)};o.tooltip.position({left:f+u.left,top:i.mouseY+u.top}).chartContainer(D.parentNode).enabled(g).valueFormatter(m).data({value:v,series:c})(),o.renderGuideLine(f)}),o.dispatch.on("elementMouseout",function(e){N.tooltipHide(),t.clearHighlights()}),N.on("tooltipShow",function(e){g&&O(e,D.parentNode)}),N.on("changeState",function(e){typeof e.disabled!="undefined"&&y.length===e.disabled.length&&(y.forEach(function(t,n){t.disabled=e.disabled[n]}),S.disabled=e.disabled),typeof e.style!="undefined"&&t.style(e.style),M.update()})}),M}var t=e.models.stackedArea(),n=e.models.axis(),r=e.models.axis(),i=e.models.legend(),s=e.models.legend(),o=e.interactiveGuideline(),u={top:30,right:25,bottom:50,left:60},a=null,f=null,l=e.utils.defaultColor(),c=!0,h=!0,p=!0,d=!0,v=!1,m=!1,g=!0,y=function(e,t,n,r,i){return"

    "+e+"

    "+"

    "+n+" on "+t+"

    "},b,w,E=d3.format(",.2f"),S={style:t.style()},x=null,T="No Data Available.",N=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),C=250,k=["Stacked","Stream","Expanded"],L={},A=250;n.orient("bottom").tickPadding(7),r.orient(v?"right":"left"),s.updateState(!1);var O=function(i,s){var o=i.pos[0]+(s.offsetLeft||0),u=i.pos[1]+(s.offsetTop||0),a=n.tickFormat()(t.x()(i.point,i.pointIndex)),f=r.tickFormat()(t.y()(i.point,i.pointIndex)),l=y(i.series.key,a,f,i,M);e.tooltip.show([o,u],l,i.value<0?"n":"s",null,s)};return t.dispatch.on("tooltipShow",function(e){e.pos=[e.pos[0]+u.left,e.pos[1]+u.top],N.tooltipShow(e)}),t.dispatch.on("tooltipHide",function(e){N.tooltipHide(e)}),N.on("tooltipHide",function(){g&&e.tooltip.cleanup()}),M.dispatch=N,M.stacked=t,M.legend=i,M.controls=s,M.xAxis=n,M.yAxis=r,M.interactiveLayer=o,d3.rebind(M,t,"x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","sizeDomain","interactive","useVoronoi","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),M.options=e.utils.optionsFunc.bind(M),M.margin=function(e){return arguments.length?(u.top=typeof e.top!="undefined"?e.top:u.top,u.right=typeof e.right!="undefined"?e.right:u.right,u.bottom=typeof e.bottom!="undefined"?e.bottom:u.bottom,u.left=typeof e.left!="undefined"?e.left:u.left,M):u},M.width=function(e){return arguments.length?(a=e,M):a},M.height=function(e){return arguments.length?(f=e,M):f},M.color=function(n){return arguments.length?(l=e.utils.getColor(n),i.color(l),t.color(l),M):l},M.showControls=function(e){return arguments.length?(c=e,M):c},M.showLegend=function(e){return arguments.length?(h=e,M):h},M.showXAxis=function(e){return arguments.length?(p=e,M):p},M.showYAxis=function(e){return arguments.length?(d=e,M):d},M.rightAlignYAxis=function(e){return arguments.length?(v=e,r.orient(e?"right":"left"),M):v},M.useInteractiveGuideline=function(e){return arguments.length?(m=e,e===!0&&(M.interactive(!1),M.useVoronoi(!1)),M):m},M.tooltip=function(e){return arguments.length?(y=e,M):y},M.tooltips=function(e){return arguments.length?(g=e,M):g},M.tooltipContent=function(e){return arguments.length?(y=e,M):y},M.state=function(e){return arguments.length?(S=e,M):S},M.defaultState=function(e){return arguments.length?(x=e,M):x},M.noData=function(e){return arguments.length?(T=e,M):T},M.transitionDuration=function(e){return arguments.length?(A=e,M):A},M.controlsData=function(e){return arguments.length?(k=e,M):k},M.controlLabels=function(e){return arguments.length?typeof e!="object"?L:(L=e,M):L},r.setTickFormat=r.tickFormat,r.tickFormat=function(e){return arguments.length?(E=e,r):E},M}})();!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(Mt(u[0]),Mt(u[1]),Mt(u[2]))}return(i=Va.get(n))?t(i.r,i.g,i.b):(null!=n&&"#"===n.charAt(0)&&(4===n.length?(o=n.charAt(1),o+=o,a=n.charAt(2),a+=a,c=n.charAt(3),c+=c):7===n.length&&(o=n.substring(1,3),a=n.substring(3,5),c=n.substring(5,7)),o=parseInt(o,16),a=parseInt(a,16),c=parseInt(c,16)),t(o,a,c))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function zt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){if(m&&n%1)return"";var e=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var u=Xo.formatPrefix(n,h);n=u.scale(n),d=u.symbol}else n*=p;n=g(n,h);var c=n.lastIndexOf("."),x=0>c?n:n.substring(0,c),M=0>c?"":t+n.substring(c+1);!s&&f&&(x=i(x));var _=v.length+x.length+M.length+(y?0:e.length),b=l>_?new Array(_=l-_+1).join(r):"";return y&&(x=i(b+x)),e+=v,n=x+M,("<"===o?e+n+b:">"===o?b+e+n:"^"===o?b.substring(0,_>>=1)+e+n+b.substring(_):e+(y?n:b+n))+d}}}function qt(n){return n+""}function Tt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=Tt;var r=new Tt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=Tt;var r=new Tt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=Tt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=Tt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++ea;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=oa(_)>Sa,w=p*x;if(hc.add(Math.atan2(w*Math.sin(_),v*M+w*Math.cos(_))),i+=b?_+(_>=0?ka:-ka):_,b^h>=e^m>=e){var S=fe(se(f),se(n));pe(S);var k=fe(u,S);pe(k);var E=(b^_>=0?-1:1)*X(k[2]);(r>E||r===E&&(S[0]||S[1]))&&(o+=b^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function ze(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Te(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)0?0:3:oa(r[0]-e)0?2:1:oa(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),zc>t&&(zc=t),t>Tc&&(Tc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)i||oa((y*L+x*z)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b +},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function zr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];zr(n);for(var c=i;c.circle&&oa(e-c.circle.x)l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function Tr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)Aa?{x:f,y:oa(t-f)Aa?{x:oa(e-p)Aa?{x:h,y:oa(t-h)Aa?{x:oa(e-g)=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xr;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=zu(t,e),i=qu(Tu(e,t,-u))||0;t[0]*e[1]180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++ie;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++iu&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Ti(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():Ti(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=Ti(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Ti(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++0;h--)o.push(i(s)*h);for(s=0;o[s]c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++ae?[0/0,0/0]:[e>0?u[e-1]:n[0],et?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++ue?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Ti(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.1"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ur&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ur&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=e);)e=void 0;for(;++ue&&(e=r)}else{for(;++u=e);)e=void 0;for(;++ue&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=e);)e=u=void 0;for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=e);)e=void 0;for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)r;){var i=r+u>>>1;er?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++ur){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++rr;++r)p[r]=z(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++oi;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=T.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++ar){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,za=Math.SQRT2,qa=2,Ta=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(za*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(za*t+v)]}return[r+n*s,u+n*l,i*Math.exp(za*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+Ta*f)/(2*i*qa*h),p=(c*c-i*i-Ta*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/za;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=z.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=z.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=z.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=z.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",z=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=z.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,z,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv(" ","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;Tt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:zt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nhc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h +}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,ze,Te,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,zc,qc,Tc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=Tc=-(Lc=zc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,zc],[qc,Tc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.xm&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++ea*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++at;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++fg;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++oe&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++ie.dx)&&(l=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[]) +},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(zo(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=To,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++oi;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),z.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),z=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?z.on("touchmove.brush",v).on("touchend.brush",y):z.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),T=+/^n/.test(k);M=[l[1-q]-L[0],f[1-T]-L[1]],L[0]=l[q],L[1]=f[T]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(+n,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}();/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery);/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
    ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f +}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="
    a",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/\s*$/g,sb={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:l.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?""!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("