Skip to content

Commit

Permalink
API Move extension management into test state
Browse files Browse the repository at this point in the history
  • Loading branch information
Damian Mooyman committed Jun 20, 2017
1 parent c66d433 commit ca03395
Show file tree
Hide file tree
Showing 19 changed files with 185 additions and 130 deletions.
1 change: 1 addition & 0 deletions _config/tests.yml
Expand Up @@ -5,5 +5,6 @@ SilverStripe\Core\Injector\Injector:
SilverStripe\Dev\SapphireTestState:
properties:
States:
extensions: %$SilverStripe\Dev\ExtensionTestState
flushable: %$SilverStripe\Dev\FlushableTestState
requirements: %$SilverStripe\View\Dev\RequirementsTestState
16 changes: 5 additions & 11 deletions src/Core/Manifest/ClassManifest.php
Expand Up @@ -35,14 +35,6 @@ class ClassManifest
*/
protected $cacheFactory;

/**
* Set if including test classes
*
* @see TestOnly
* @var bool
*/
protected $tests;

/**
* Cache to use, if caching.
* Set to null if uncached.
Expand Down Expand Up @@ -161,7 +153,7 @@ public function init($includeTests = false, $forceRegen = false)
$this->implementors = $data['implementors'];
$this->traits = $data['traits'];
} else {
$this->regenerate();
$this->regenerate($includeTests);
}
}

Expand Down Expand Up @@ -356,8 +348,10 @@ public function getOwnerModule($class)

/**
* Completely regenerates the manifest file.
*
* @param bool $includeTests
*/
public function regenerate()
public function regenerate($includeTests)
{
$resets = array(
'classes', 'roots', 'children', 'descendants', 'interfaces',
Expand All @@ -373,7 +367,7 @@ public function regenerate()
$finder->setOptions(array(
'name_regex' => '/^[^_].*\\.php$/',
'ignore_files' => array('index.php', 'main.php', 'cli-script.php'),
'ignore_tests' => !$this->tests,
'ignore_tests' => !$includeTests,
'file_callback' => array($this, 'handleFile'),
));
$finder->find($this->base);
Expand Down
8 changes: 8 additions & 0 deletions src/Core/TestKernel.php
Expand Up @@ -23,6 +23,14 @@ public function reset()
$this->bootPHP();
}

protected function bootPHP()
{
parent::bootPHP();

// Set default timezone consistently to avoid NZ-specific dependencies
date_default_timezone_set('UTC');
}

protected function getIncludeTests()
{
return true;
Expand Down
122 changes: 122 additions & 0 deletions src/Dev/ExtensionTestState.php
@@ -0,0 +1,122 @@
<?php

namespace SilverStripe\Dev;

use LogicException;
use SilverStripe\Core\Extension;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\DataObject;

/**
* Manages illegal and required extensions for sapphiretest
*/
class ExtensionTestState implements TestState
{
/**
* @var array
*/
protected $extensionsToReapply = [];

/**
* @var array
*/
protected $extensionsToRemove = [];

/**
* Called on setup
*
* @param SapphireTest $test
*/
public function setUp(SapphireTest $test)
{
}

public function tearDown(SapphireTest $test)
{
}

public function setUpOnce($class)
{
$isAltered = false;
/** @var string|SapphireTest $class */
/** @var string|DataObject $dataClass */
// Remove any illegal extensions that are present
foreach ($class::getIllegalExtensions() as $dataClass => $extensions) {
if (!class_exists($dataClass)) {
continue;
}
if ($extensions === '*') {
$extensions = $dataClass::get_extensions();
}
foreach ($extensions as $extension) {
if (!class_exists($extension) || !$dataClass::has_extension($extension)) {
continue;
}
if (!isset($this->extensionsToReapply[$dataClass])) {
$this->extensionsToReapply[$dataClass] = array();
}
$this->extensionsToReapply[$dataClass][] = $extension;
$dataClass::remove_extension($extension);
$isAltered = true;
}
}

// Add any required extensions that aren't present
foreach ($class::getRequiredExtensions() as $dataClass => $extensions) {
if (!class_exists($dataClass)) {
throw new LogicException("Test {$class} requires dataClass {$dataClass} which doesn't exist");
}
$this->extensionsToRemove[$dataClass] = array();
foreach ($extensions as $extension) {
$dataClass = Extension::get_classname_without_arguments($extension);
if (!class_exists($dataClass)) {
$self = static::class;
throw new LogicException("Test {$self} requires extension {$extension} which doesn't exist");
}
if (!$dataClass::has_extension($extension)) {
if (!isset($this->extensionsToRemove[$dataClass])) {
$this->extensionsToReapply[$dataClass] = array();
}
$this->extensionsToRemove[$dataClass][] = $extension;
$dataClass::add_extension($extension);
$isAltered = true;
}
}
}

// If we have made changes to the extensions present, then migrate the database schema.
if ($isAltered || $this->extensionsToReapply || $this->extensionsToRemove || $class::getExtraDataObjects()) {
DataObject::reset();
if (!SapphireTest::using_temp_db()) {
SapphireTest::create_temp_db();
}
SapphireTest::resetDBSchema(true);
}

// clear singletons, they're caching old extension info
// which is used in DatabaseAdmin->doBuild()
Injector::inst()->unregisterObjects(DataObject::class);
}

public function tearDownOnce($class)
{
// @todo: This isn't strictly necessary to restore extensions, but only to ensure that
// Object::$extra_methods is properly flushed. This should be replaced with a simple
// flush mechanism for each $class.
/** @var string|DataObject $dataClass */

// Remove extensions added for testing
foreach ($this->extensionsToRemove as $dataClass => $extensions) {
foreach ($extensions as $extension) {
$dataClass::remove_extension($extension);
}
}

// Reapply ones removed
foreach ($this->extensionsToReapply as $dataClass => $extensions) {
foreach ($extensions as $extension) {
$dataClass::add_extension($extension);
}
}
}
}

0 comments on commit ca03395

Please sign in to comment.