Made supported

This commit is contained in:
Christopher Pitt 2015-09-11 09:13:48 +12:00
parent 7e28448664
commit 53aafd97ba
32 changed files with 682 additions and 133 deletions

7
.gitattributes vendored Normal file
View File

@ -0,0 +1,7 @@
/tests export-ignore
/docs export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/.scrutinizer.yml export-ignore
/phpunit.xml export-ignore

13
.scrutinizer.yml Normal file
View File

@ -0,0 +1,13 @@
inherit: true
tools:
external_code_coverage:
timeout: 1800 # 30 minute delay to allow for coverage reporting taking ages!
checks:
php:
code_rating: true
duplication: true
filter:
paths: [code/*, tests/*]

35
.travis.yml Normal file
View File

@ -0,0 +1,35 @@
language: php
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
sudo: false
env:
- DB=MYSQL CORE_RELEASE=3.1
before_script:
- composer self-update || true
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
- php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss
- cd ~/builds/ss
- composer install
script:
- vendor/bin/phpunit --coverage-clover coverage.clover environmentcheck/tests
- wget https://scrutinizer-ci.com/ocular.phar
- git remote rm origin
- git remote add origin git@github.com:silverstripe-labs/silverstripe-environmentcheck.git
- php ocular.phar code-coverage:upload --format=php-clover coverage.clover
branches:
only:
- master
matrix:
allow_failures:
- php: 7.0

9
changelog.md Normal file
View File

@ -0,0 +1,9 @@
# Changelog
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [1.1.1]
Changelog added.

3
code-of-conduct.md Normal file
View File

@ -0,0 +1,3 @@
# Code of Conduct
https://docs.silverstripe.org/en/3.1/contributing/code_of_conduct/

View File

@ -1,20 +1,37 @@
<?php
class DevCheckController extends Controller {
/**
* @var array
*/
public static $allowed_actions = array(
'index'
);
/**
* @var string Permission code to check for access to this controller.
* Permission code to check for access to this controller.
*
* @var string
*/
private static $permission = 'ADMIN';
/**
* @param SS_HTTPRequest $request
*
* @return EnvironmentChecker
*
* @throws SS_HTTPResponse_Exception
*/
function index($request) {
$suiteName = $request->param('Suite') ? $request->param('Suite') : 'check';
$e = new EnvironmentChecker($suiteName, 'Environment status');
$e->init($this->config()->permission); //check for admin permissions before running this check
return $e;
$suite = 'check';
if ($name = $request->param('Suite')) {
$suite = $name;
}
$checker = new EnvironmentChecker($suite, 'Environment status');
$checker->init($this->config()->permission);
return $checker;
}
}

View File

@ -1,15 +1,25 @@
<?php
class DevHealthController extends Controller {
/**
* @var array
*/
public static $allowed_actions = array(
'index'
);
/**
* @return EnvironmentChecker
*
* @throws SS_HTTPResponse_Exception
*/
function index() {
$e = new EnvironmentChecker('health', 'Site health');
$e->init(''); //empty permission check, the "health" check does not require a permission check to run
$e->setErrorCode(404);
return $e;
// health check does not require permission to run
$checker = new EnvironmentChecker('health', 'Site health');
$checker->init('');
$checker->setErrorCode(404);
return $checker;
}
}

View File

@ -3,8 +3,9 @@
/**
* Interface for environment checks
*
* An environment check is a test that can be performed on a live environment. They differ from unit
* tests in that they are designed to check the state of the evnironment / server, rather than the code.
* An environment check is a test that can be performed on a live environment. They differ from
* unit tests in that they are designed to check the state of the environment/server, rather than
* the code.
*
* Environment checks should *never* alter production data.
*
@ -14,17 +15,25 @@
* - Are the file permissions correct?
*/
interface EnvironmentCheck {
/**
* @var int
*/
const ERROR = 3;
/**
* @var int
*/
const WARNING = 2;
/**
* @var int
*/
const OK = 1;
/**
* Perform this check
*
* @return 2 element array( $status, $message )
* $status is EnvironmentCheck::ERROR, EnvironmentCheck::WARNING, or EnvironmentCheck::OK
* @return array Result with 'status' and 'message' keys.
*
* Status is EnvironmentCheck::ERROR, EnvironmentCheck::WARNING, or EnvironmentCheck::OK.
*/
function check();
}

View File

@ -1,4 +1,5 @@
<?php
/**
* Represents a suite of environment checks.
* Specific checks can be registered against a named instance of EnvironmentCheckSuite.
@ -19,12 +20,16 @@
* $result = EnvironmentCheckSuite::inst('health')->run();
*/
class EnvironmentCheckSuite extends Object {
/**
* Name of this suite.
*
* @var string
*/
protected $name;
/**
* @var array
*/
protected $checks = array();
/**
@ -32,14 +37,18 @@ class EnvironmentCheckSuite extends Object {
* - definition (e.g. 'MyHealthCheck("my param")')
* - title (e.g. 'Is my feature working?')
* - state (setting this to 'disabled' will cause suites to skip this check entirely.
*
* @var array
*/
private static $registered_checks;
private static $registered_checks = array();
/**
* Associative array of named suites registered via the config system. Each suite should enumerate
* named checks that have been configured in 'registered_checks'.
*
* @var array
*/
private static $registered_suites;
private static $registered_suites = array();
/**
* Load checks for this suite from the configuration system. This is an alternative to the
@ -48,6 +57,8 @@ class EnvironmentCheckSuite extends Object {
* @param string $suiteName The name of this suite.
*/
public function __construct($suiteName) {
parent::__construct();
if (empty($this->config()->registered_suites[$suiteName])) {
// Not registered via config system, but it still may be configured later via self::register.
return;
@ -72,13 +83,13 @@ class EnvironmentCheckSuite extends Object {
}
/**
* Run this test suite
* @return The result code of the worst result.
* Run this test suite and return the result code of the worst result.
*
* @return int
*/
public function run() {
$worstResult = 0;
$result = new EnvironmentCheckSuiteResult();
foreach($this->checkInstances() as $check) {
list($checkClass, $checkTitle) = $check;
try {
@ -95,7 +106,9 @@ class EnvironmentCheckSuite extends Object {
}
/**
* Get instances of all the environment checks
* Get instances of all the environment checks.
*
* @return array
*/
protected function checkInstances() {
$output = array();
@ -119,6 +132,9 @@ class EnvironmentCheckSuite extends Object {
/**
* Add a check to this suite.
*
* @param mixed $check
* @param string $title
*/
public function push($check, $title = null) {
if(!$title) {
@ -129,10 +145,17 @@ class EnvironmentCheckSuite extends Object {
/////////////////////////////////////////////////////////////////////////////////////////////
/**
* @var array
*/
protected static $instances = array();
/**
* Return a named instance of EnvironmentCheckSuite.
*
* @param string $name
*
* @return EnvironmentCheckSuite
*/
static function inst($name) {
if(!isset(self::$instances[$name])) self::$instances[$name] = new EnvironmentCheckSuite($name);
@ -142,7 +165,9 @@ class EnvironmentCheckSuite extends Object {
/**
* Register a check against the named check suite.
*
* @param String|Array
* @param string|array $names
* @param EnvironmentCheck $check
* @param string|array
*/
static function register($names, $check, $title = null) {
if(!is_array($names)) $names = array($names);
@ -154,13 +179,26 @@ class EnvironmentCheckSuite extends Object {
* A single set of results from running an EnvironmentCheckSuite
*/
class EnvironmentCheckSuiteResult extends ViewableData {
protected $details, $worst = 0;
/**
* @var ArrayList
*/
protected $details;
/**
* @var int
*/
protected $worst = 0;
function __construct() {
parent::__construct();
$this->details = new ArrayList();
}
/**
* @param int $status
* @param string $message
* @param string $checkIdentifier
*/
function addResult($status, $message, $checkIdentifier) {
$this->details->push(new ArrayData(array(
'Check' => $checkIdentifier,
@ -172,21 +210,27 @@ class EnvironmentCheckSuiteResult extends ViewableData {
}
/**
* Returns true if there are no ERRORs, only WARNINGs or OK
* Returns true if there are no errors.
*
* @return bool
*/
function ShouldPass() {
public function ShouldPass() {
return $this->worst <= EnvironmentCheck::WARNING;
}
/**
* Returns overall (i.e. worst) status as a string.
*
* @return string
*/
function Status() {
return $this->statusText($this->worst);
}
/**
* Returns detailed status information about each check
* Returns detailed status information about each check.
*
* @return ArrayList
*/
function Details() {
return $this->details;
@ -194,6 +238,7 @@ class EnvironmentCheckSuiteResult extends ViewableData {
/**
* Convert the final result status and details to JSON.
*
* @return string
*/
function toJSON() {
@ -209,7 +254,9 @@ class EnvironmentCheckSuiteResult extends ViewableData {
}
/**
* Return a text version of a status code
* Return a text version of a status code.
*
* @return string
*/
protected function statusText($status) {
switch($status) {

View File

@ -4,30 +4,59 @@
* Provides an interface for checking the given EnvironmentCheckSuite.
*/
class EnvironmentChecker extends RequestHandler {
static $url_handlers = array(
/**
* @var array
*/
private static $url_handlers = array(
'' => 'index',
);
/**
* @var string
*/
protected $checkSuiteName;
/**
* @var string
*/
protected $title;
/**
* @var int
*/
protected $errorCode = 500;
/**
* @var null|string
*/
public static $to_email_address = null;
/**
* @var null|string
*/
public static $from_email_address = null;
/**
* @var bool
*/
public static $email_results = false;
/**
* @param string $checkSuiteName
* @param string $title
*/
function __construct($checkSuiteName, $title) {
parent::__construct();
$this->checkSuiteName = $checkSuiteName;
$this->title = $title;
}
/**
* @param string $permission
*
* @throws SS_HTTPResponse_Exception
*/
function init($permission = 'ADMIN') {
// if the environment supports it, provide a basic auth challenge and see if it matches configured credentials
if(defined('ENVCHECK_BASICAUTH_USERNAME') && defined('ENVCHECK_BASICAUTH_PASSWORD')) {
@ -59,6 +88,14 @@ class EnvironmentChecker extends RequestHandler {
}
}
/**
* @param null|int|Member $member
* @param string $permission
*
* @return bool
*
* @throws SS_HTTPResponse_Exception
*/
function canAccess($member = null, $permission = "ADMIN") {
if(!$member) {
$member = Member::currentUser();
@ -90,7 +127,10 @@ class EnvironmentChecker extends RequestHandler {
return false;
}
/**
* @return SS_HTTPResponse
*/
function index() {
$response = new SS_HTTPResponse;
$result = EnvironmentCheckSuite::inst($this->checkSuiteName)->run();
@ -128,34 +168,52 @@ class EnvironmentChecker extends RequestHandler {
/**
* Set the HTTP status code that should be returned when there's an error.
* Defaults to 500
*
* @param int $errorCode
*/
function setErrorCode($errorCode) {
$this->errorCode = $errorCode;
}
/**
* @param string $from
*/
public static function set_from_email_address($from) {
self::$from_email_address = $from;
}
/**
* @return null|string
*/
public static function get_from_email_address() {
return self::$from_email_address;
}
/**
* @param string $to
*/
public static function set_to_email_address($to) {
self::$to_email_address = $to;
}
/**
* @return null|string
*/
public static function get_to_email_address() {
return self::$to_email_address;
}
/**
* @param bool $results
*/
public static function set_email_results($results) {
self::$email_results = $results;
}
/**
* @return bool
*/
public static function get_email_results() {
return self::$email_results;
}
}

View File

@ -1,25 +1,27 @@
<?php
/**
* This file contains a number of default environment checks that you can use.
*/
/**
* Check that the connection to the database is working, by ensuring that the table exists and that
* the table contain some records.
* By default, Member will be checked.
*
* @param $checkTable The table that will be checked.
* the table contains some records.
*/
class DatabaseCheck implements EnvironmentCheck {
protected $checkTable;
/**
* By default, Member will be checked.
*
* @param string $checkTable
*/
function __construct($checkTable = "Member") {
$this->checkTable = $checkTable;
}
function check() {
/**
* @inheritdoc
*
* @return array
*/
function check() {
if(!DB::getConn()->hasTable($this->checkTable)) {
return array(EnvironmentCheck::ERROR, "$this->checkTable not present in the database");
}
@ -32,4 +34,4 @@ class DatabaseCheck implements EnvironmentCheck {
return array(EnvironmentCheck::WARNING, "$this->checkTable queried ok but has no records");
}
}
}
}

View File

@ -1,4 +1,5 @@
<?php
/**
* Checks that one or more URLs are reachable via HTTP.
* Note that the HTTP connectivity can just be verified from the server to the remote URL,
@ -8,7 +9,6 @@
* <code>EnvironmentCheckSuite::register('check', 'HasFunctionCheck("curl_init")', "Does PHP have CURL support?");</code>
*/
class ExternalURLCheck implements EnvironmentCheck {
/**
* @var array
*/
@ -20,14 +20,19 @@ class ExternalURLCheck implements EnvironmentCheck {
protected $timeout;
/**
* @param String Space separated list of absolute URLs
* (can't be an array as we're using Object::create() with strings for the constructor signature)
* @param string $urls Space-separated list of absolute URLs.
* @param int $timeout
*/
function __construct($urls, $timeout = 15) {
if($urls) $this->urls = explode(' ', $urls);
$this->timeout = $timeout;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
$urls = $this->getURLs();
@ -90,7 +95,7 @@ class ExternalURLCheck implements EnvironmentCheck {
}
/**
* @return Array
* @return array
*/
protected function getCurlOpts($url) {
return array(
@ -103,9 +108,9 @@ class ExternalURLCheck implements EnvironmentCheck {
}
/**
* @return Array
* @return array
*/
protected function getURLs() {
return $this->urls;
}
}
}

View File

@ -1,50 +1,72 @@
<?php
/**
* Checks for the accessiblility and tiletype validation of one or more files or folders.
* Checks for the accessibility and file type validation of one or more files or folders.
*
* Examples:
* // Checks /assets/caluclator_files has .json files and all files are valid json files.
* EnvironmentCheckSuite::register('check', 'FileAccessibilityAndValidationCheck("' . BASE_PATH . '/assets/caluclator_files/*.json",
* // Checks /assets/calculator_files has .json files and all files are valid json files.
* EnvironmentCheckSuite::register('check', 'FileAccessibilityAndValidationCheck("' . BASE_PATH . '/assets/calculator_files/*.json",
* "jsonValidate", '.FileAccessibilityAndValidationCheck::CHECK_ALL.')', 'Check a json file exist and are all valid json files'
* );
*
* // Checks /assets/caluclator_files/calculator.json exists and is valid json file.
* EnvironmentCheckSuite::register('check', 'FileAccessibilityAndValidationCheck("' . BASE_PATH . '/assets/caluclator_files/calculator.json",
* // Checks /assets/calculator_files/calculator.json exists and is valid json file.
* EnvironmentCheckSuite::register('check', 'FileAccessibilityAndValidationCheck("' . BASE_PATH . '/assets/calculator_files/calculator.json",
* "jsonValidate", '.FileAccessibilityAndValidationCheck::CHECK_SINGLE.')', 'Check a calculator.json exists and is valid json file'
* );
*
* // Check only existence
* EnvironmentCheckSuite::register('check', 'FileAccessibilityAndValidationCheck("' . BASE_PATH . '/assets/caluclator_files/calculator.json")',
* EnvironmentCheckSuite::register('check', 'FileAccessibilityAndValidationCheck("' . BASE_PATH . '/assets/calculator_files/calculator.json")',
* 'Check a calculator.json exists only'
* );
*/
class FileAccessibilityAndValidationCheck implements EnvironmentCheck {
/**
* @var int
*/
const CHECK_SINGLE = 1;
/**
* @var int
*/
const CHECK_ALL = 2;
/**
* @var String Absolute path to a file or folder, compatible with glob().
* Absolute path to a file or folder, compatible with glob().
*
* @var string
*/
protected $path;
/**
* @var Int Constant, check for a single file to match age criteria, or all of them.
* Constant, check for a single file to match age criteria, or all of them.
*
* @var int
*/
protected $fileTypeValidateFunc;
/**
* @var Int Constant, check for a single file to match age criteria, or all of them.
/**
* Constant, check for a single file to match age criteria, or all of them.
*
* @var int
*/
protected $checkType;
/**
* @param string $path
* @param string $fileTypeValidateFunc
* @param null|int $checkType
*/
function __construct($path, $fileTypeValidateFunc = 'noVidation', $checkType = null) {
$this->path = $path;
$this->fileTypeValidateFunc = ($fileTypeValidateFunc)? $fileTypeValidateFunc:'noVidation';
$this->checkType = ($checkType) ? $checkType : self::CHECK_SINGLE;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
$origStage = Versioned::get_reading_mode();
Versioned::set_reading_mode('Live');
@ -122,6 +144,11 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck {
return $checkReturn;
}
/**
* @param string $file
*
* @return bool
*/
private function jsonValidate($file){
$json = json_decode(file_get_contents($file));
if(!$json) {
@ -131,15 +158,21 @@ class FileAccessibilityAndValidationCheck implements EnvironmentCheck {
}
}
/**
* @param string $file
*
* @return bool
*/
protected function noVidation($file) {
return true;
}
/**
* @return Array Of absolute file paths
* Gets a list of absolute file paths.
*
* @return array
*/
protected function getFiles() {
return glob($this->path);
}
}
}

View File

@ -1,4 +1,5 @@
<?php
/**
* Checks for the maximum age of one or more files or folders.
* Useful for files which should be frequently auto-generated,
@ -19,37 +20,58 @@
* );
*/
class FileAgeCheck implements EnvironmentCheck {
/**
* @var int
*/
const CHECK_SINGLE = 1;
/**
* @var int
*/
const CHECK_ALL = 2;
/**
* @var String Absolute path to a file or folder, compatible with glob().
* Absolute path to a file or folder, compatible with glob().
*
* @var string
*/
protected $path;
/**
* @var String strtotime() compatible relative date specification.
* Relative date specification, compatible with strtotime().
*
* @var string
*/
protected $relativeAge;
/**
* @var String The function to use for checking file age,
* so filemtime(), filectime() or fileatime().
* The function to use for checking file age: so filemtime(), filectime(), or fileatime().
*
* @var string
*/
protected $checkFn;
/**
* @var Int Constant, check for a single file to match age criteria, or all of them.
* Constant, check for a single file to match age criteria, or all of them.
*
* @var int
*/
protected $checkType;
/**
* @var String Either '>' or '<'.
* Type of comparison (either > or <).
*
* @var string
*/
protected $compareOperand;
/**
* @param string $path
* @param string $relativeAge
* @param string $compareOperand
* @param null|int $checkType
* @param string $checkFn
*/
function __construct($path, $relativeAge, $compareOperand = '>', $checkType = null, $checkFn = 'filemtime') {
$this->path = $path;
$this->relativeAge = $relativeAge;
@ -58,6 +80,11 @@ class FileAgeCheck implements EnvironmentCheck {
$this->compareOperand = $compareOperand;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
$cutoffTime = strtotime($this->relativeAge, SS_Datetime::now()->Format('U'));
$files = $this->getFiles();
@ -98,10 +125,11 @@ class FileAgeCheck implements EnvironmentCheck {
}
/**
* @return Array Of absolute file paths
* Gets a list of absolute file paths.
*
* @return array
*/
protected function getFiles() {
return glob($this->path);
}
}
}

View File

@ -1,16 +1,26 @@
<?php
/**
* Check that the given file is writeable.
* This can be used to check that the environment doesn't have permission set-up errors.
* @param $path The full path. If a relative path, it will relative to the BASE_PATH
* Check that the given file is writable.
*/
class FileWriteableCheck implements EnvironmentCheck {
/**
* @var string
*/
protected $path;
/**
* @param string $path The full path. If a relative path, it will relative to the BASE_PATH.
*/
function __construct($path) {
$this->path = $path;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
if($this->path[0] == '/') $filename = $this->path;
else $filename = BASE_PATH . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $this->path);
@ -55,4 +65,4 @@ class FileWriteableCheck implements EnvironmentCheck {
return array(EnvironmentCheck::OK,'');
}
}
}

View File

@ -1,18 +1,28 @@
<?php
/**
* Check that the given class exists.
* This can be used to check that PHP modules or features are installed.
* @param $className The name of the class to look for.
*/
class HasClassCheck implements EnvironmentCheck {
/**
* @var string
*/
protected $className;
/**
* @param string $className The name of the class to look for.
*/
function __construct($className) {
$this->className = $className;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
if(class_exists($this->className)) return array(EnvironmentCheck::OK, 'Class ' . $this->className.' exists');
else return array(EnvironmentCheck::ERROR, 'Class ' . $this->className.' doesn\'t exist');
}
}
}

View File

@ -1,18 +1,28 @@
<?php
/**
* Check that the given function exists.
* This can be used to check that PHP modules or features are installed.
* @param $functionName The name of the function to look for.
*/
class HasFunctionCheck implements EnvironmentCheck {
/**
* @var string
*/
protected $functionName;
/**
* @param string $functionName The name of the function to look for.
*/
function __construct($functionName) {
$this->functionName = $functionName;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
if(function_exists($this->functionName)) return array(EnvironmentCheck::OK, $this->functionName.'() exists');
else return array(EnvironmentCheck::ERROR, $this->functionName.'() doesn\'t exist');
}
}
}

View File

@ -1,28 +1,32 @@
<?php
/**
* Checks if the SMTP connection configured through PHP.ini works as expected.
*
* Only checks socket connection with HELO command, not actually sending the email.
*/
class SMTPConnectCheck implements EnvironmentCheck {
/**
* @var String
* @var string
*/
protected $host;
/**
* @var Int
* @var int
*/
protected $port;
/**
* @var Int In seconds
* Timeout (in seconds).
*
* @var int
*/
protected $timeout;
/**
* @param String
* @param Int
* @param null|string $host
* @param null|int $port
* @param int $timeout
*/
function __construct($host = null, $port = null, $timeout = 15) {
$this->host = ($host) ? $host : ini_get('SMTP');
@ -34,6 +38,11 @@ class SMTPConnectCheck implements EnvironmentCheck {
$this->timeout = $timeout;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
$f = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
if(!$f) {
@ -53,6 +62,5 @@ class SMTPConnectCheck implements EnvironmentCheck {
}
return array(EnvironmentCheck::OK, '');
}
}
}

View File

@ -1,18 +1,28 @@
<?php
/**
* Check the availability of all Solr indexes of given class.
* If there are no indexes of given class found, the returned status will still be "OK".
*
* @param $indexClass Limit the index checks to the specified class and all its subclasses.
* If there are no indexes of given class found, the returned status will still be "OK".
*/
class SolrIndexCheck implements EnvironmentCheck {
/**
* @var null|string
*/
protected $indexClass;
/**
* @param string $indexClass Limit the index checks to the specified class and all its subclasses.
*/
function __construct($indexClass = null) {
$this->indexClass = $indexClass;
}
/**
* @inheritdoc
*
* @return array
*/
function check() {
$brokenCores = array();
@ -40,5 +50,4 @@ class SolrIndexCheck implements EnvironmentCheck {
return array(EnvironmentCheck::OK, 'Expected indexes are available.');
}
}

View File

@ -1,22 +1,37 @@
<?php
/**
* Check that a given URL is functioning, by default, the homepage.
*
* Note that Director::test() will be used rather than a CURL check.
*/
class URLCheck implements EnvironmentCheck {
/**
* @var string
*/
protected $url;
/**
* @var string
*/
protected $testString;
/*
* @param $url The URL to check, relative to the site. "" is the homepage.
* @param $testString A piece of text to optionally search for in the homepage HTML. If omitted, no such check is made.
* @param string $url The URL to check, relative to the site (homepage is '').
* @param string $testString An optional piece of text to search for on the homepage.
*/
function __construct($url = "", $testString = "") {
function __construct($url = '', $testString = '') {
$this->url = $url;
$this->testString = $testString;
}
/**
* @inheritdoc
*
* @return array
*
* @throws SS_HTTPResponse_Exception
*/
function check() {
$response = Director::test($this->url);
@ -39,4 +54,4 @@ class URLCheck implements EnvironmentCheck {
);
}
}
}
}

View File

@ -2,16 +2,19 @@
"name": "silverstripe/environmentcheck",
"description": "Provides an API for building environment tests",
"type": "silverstripe-module",
"keywords": ["silverstripe", "testing", "environment", "environmentcheck"],
"keywords": ["silverstripe", "testing", "environment", "check"],
"authors": [
{
"name": "Sam Minnee",
"email": "sam@silverstripe.com"
}
{
"name": "Will Rossiter",
"email": "will@fullscreen.io"
},
{
"name": "Sam Minnee",
"email": "sam@silverstripe.com"
}
],
"require":
{
"silverstripe/framework": "3.*"
"silverstripe/framework": "~3.1"
}
}

3
contributing.md Normal file
View File

@ -0,0 +1,3 @@
# Contributing
Contributions are welcome! Create an issue, explaining a bug or proposal. Submit pull requests if you feel brave. Speak to me on [Twitter](https://twitter.com/assertchris).

16
license.md Normal file
View File

@ -0,0 +1,16 @@
Copyright (c) 2015, SilverStripe Limited
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 SilverStripe nor the names of its 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.

View File

@ -1,6 +1,10 @@
# SilverStripe Environment Checker Module
Initially developed by Sam Minnée, thanks to Will Rossiter.
[![Build Status](http://img.shields.io/travis/silverstripe-labs/silverstripe-environmentalcheck.svg?style=flat-square)](https://travis-ci.org/silverstripe-labs/silverstripe-environmentalcheck)
[![Code Quality](http://img.shields.io/scrutinizer/g/silverstripe-labs/silverstripe-environmentalcheck.svg?style=flat-square)](https://scrutinizer-ci.com/g/silverstripe-labs/silverstripe-environmentalcheck)
[![Code Coverage](http://img.shields.io/scrutinizer/coverage/g/silverstripe-labs/silverstripe-environmentalcheck.svg?style=flat-square)](https://scrutinizer-ci.com/g/silverstripe-labs/silverstripe-environmentalcheck)
[![Version](http://img.shields.io/packagist/v/silverstripe/environmentalcheck.svg?style=flat-square)](https://packagist.org/packages/silverstripe/silverstripe-environmentalcheck)
[![License](http://img.shields.io/packagist/l/silverstripe/environmentalcheck.svg?style=flat-square)](LICENSE.md)
This module adds an API for running environment checks to your API.
@ -17,9 +21,13 @@ Almost, but not really. Environment checks differ from unit tests in two importa
## Installation
There are two ways to register your checks, both can be used at the same time. The checks will be appended to the suite.
```sh
$ composer require silverstripe/environmentalcheck
```
### Direct method
You'll also need to run `/dev/build`.
### Activating Directly
Register checks in your own `_config.php` - see the `_config.php` in this module for some defaults.
@ -28,7 +36,7 @@ EnvironmentCheckSuite::register('health', 'DatabaseCheck', "Can we connect to th
EnvironmentCheckSuite::register('check', 'URLCheck("")', "Is the homepage accessible?");
```
### Config system method
### Activating Via Config
Register your checks on the `EnvironmentCheckSuite`. The same named check may be used multiple times.
@ -156,3 +164,13 @@ If you wish to embed an environment check suite in another, you can use the foll
* `$result->Details()`: A `DataObjectSet` of details about the result of each check in the suite.
See `EnvironmentChecker.ss` to see how these can be used to build a UI.
## Versioning
This library follows [Semver](http://semver.org). According to Semver, you will be able to upgrade to any minor or patch version of this library without any breaking changes to the public API. Semver also requires that we clearly define the public API for this library.
All methods, with `public` visibility, are part of the public API. All other methods are not part of the public API. Where possible, we'll try to keep `protected` methods backwards-compatible in minor/patch versions, but if you're overriding methods then please test your work before upgrading.
## Reporting Issues
Please [create an issue](http://github.com/silverstripe-labs/silverstripe-environmentalcheck/issues) for any bugs you've found, or features you're missing.

View File

@ -0,0 +1,14 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class DevCheckControllerTest extends SapphireTest {
public function testIndexCreatesChecker() {
$controller = new DevCheckController();
$request = new SS_HTTPRequest('GET', 'example.com');
$this->assertInstanceOf('EnvironmentChecker', $controller->index($request));
}
}

View File

@ -0,0 +1,23 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class DevHealthControllerTest extends SapphireTest {
public function testIndexCreatesChecker() {
$controller = new DevHealthController();
$request = new SS_HTTPRequest('GET', 'example.com');
// we need to fake authenticated access as BasicAuth::requireLogin doesn't like empty
// permission type strings, which is what health check uses.
define('ENVCHECK_BASICAUTH_USERNAME', 'foo');
define('ENVCHECK_BASICAUTH_PASSWORD', 'bar');
$_SERVER['PHP_AUTH_USER'] = 'foo';
$_SERVER['PHP_AUTH_PW'] = 'bar';
$this->assertInstanceOf('EnvironmentChecker', $controller->index($request));
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class DatabaseCheckTest extends SapphireTest {
public function testCheckReportsValidConnection() {
$check = new DatabaseCheck();
$expected = array(
EnvironmentCheck::OK,
'',
);
$this->assertEquals($expected, $check->check());
}
}

View File

@ -0,0 +1,19 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class ExternalURLCheckTest extends SapphireTest {
public function testCheckReportsMissingPages() {
$this->markTestSkipped('ExternalURLCheck seems faulty on some systems');
$check = new ExternalURLCheck('http://missing-site/');
$expected = array(
EnvironmentCheck::ERROR,
'Success retrieving "http://missing-site/" (Code: 404)',
);
$this->assertEquals($expected, $check->check());
}
}

View File

@ -0,0 +1,25 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class FileWritableCheckTest extends SapphireTest {
public function testCheckReportsWritablePaths() {
$check = new FileWriteableCheck(TEMP_FOLDER);
$expected = array(
EnvironmentCheck::OK,
'',
);
$this->assertEquals($expected, $check->check());
}
public function testCheckReportsNonWritablePaths() {
$check = new FileWriteableCheck('/var');
$result = $check->check();
$this->assertEquals(EnvironmentCheck::ERROR, $result[0]);
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class HasClassCheckTest extends SapphireTest {
public function testCheckReportsMissingClasses() {
$check = new HasClassCheck('foo');
$expected = array(
EnvironmentCheck::ERROR,
'Class foo doesn\'t exist',
);
$this->assertEquals($expected, $check->check());
}
public function testCheckReportsFoundClasses() {
$check = new HasClassCheck('stdClass');
$expected = array(
EnvironmentCheck::OK,
'Class stdClass exists',
);
$this->assertEquals($expected, $check->check());
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class HasFunctionCheckTest extends SapphireTest {
public function testCheckReportsMissingFunctions() {
$check = new HasFunctionCheck('foo');
$expected = array(
EnvironmentCheck::ERROR,
'foo() doesn\'t exist',
);
$this->assertEquals($expected, $check->check());
}
public function testCheckReportsFoundFunctions() {
$check = new HasFunctionCheck('class_exists');
$expected = array(
EnvironmentCheck::OK,
'class_exists() exists',
);
$this->assertEquals($expected, $check->check());
}
}

View File

@ -0,0 +1,17 @@
<?php
/**
* @mixin PHPUnit_Framework_TestCase
*/
class URLCheckTest extends SapphireTest {
public function testCheckReportsMissingPages() {
$check = new URLCheck('foo', 'bar');
$expected = array(
EnvironmentCheck::ERROR,
'Error retrieving "foo" (Code: 404)',
);
$this->assertEquals($expected, $check->check());
}
}