mageekguy\atoum\test: lines coverage

60% of 4520

OPs

63% of 918

Lines

44% of 590

Branches

2% of 6934

Paths
Method OPs OPs % Lines Line % Branches Branches % Paths Path %
mageekguy\atoum\test::__construct() 345 84% 79 91% 48 54% 2352 0%
mageekguy\atoum\test::__toString() 9 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::__get() 12 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::__set() 11 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::__call() 14 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::setTestAdapterStorage() 16 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getTestAdapterStorage() 6 0% 3 67% 1 0% 1 0%
mageekguy\atoum\test::setMockControllerLinker() 16 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getMockControllerLinker() 6 0% 2 50% 1 0% 1 0%
mageekguy\atoum\test::setScore() 16 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getScore() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setLocale() 16 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getLocale() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setAdapter() 16 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getAdapter() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setPhpMocker() 16 100% 4 100% 1 100% 1 100%
mageekguy\atoum\test::getPhpMocker() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setMockGenerator() 28 100% 9 100% 5 100% 2 100%
mageekguy\atoum\test::getMockGenerator() 6 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::setMockAutoloader() 16 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getMockAutoloader() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setFactoryBuilder() 16 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getFactoryBuilder() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::setReflectionMethodFactory() 12 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::setPhpExtensionFactory() 12 100% 4 75% 1 100% 1 100%
mageekguy\atoum\test::setAsserterGenerator() 33 100% 8 100% 5 100% 2 100%
mageekguy\atoum\test::getAsserterGenerator() 12 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::setAssertionManager() 315 100% 65 98% 1 100% 1 100%
mageekguy\atoum\test::getAsserterCallManager() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setAsserterCallManager() 16 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::addClassPhpVersion() 13 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getClassPhpVersions() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::addMandatoryClassExtension() 10 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::addMethodPhpVersion() 22 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getMethodPhpVersions() 74 89% 20 100% 17 76% 6 33%
mageekguy\atoum\test::getMandatoryClassExtensions() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::addMandatoryMethodExtension() 19 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getMandatoryMethodExtensions() 74 80% 19 89% 17 65% 6 33%
mageekguy\atoum\test::skip() 12 0% 2 50% 1 0% 1 0%
mageekguy\atoum\test::getAssertionManager() 6 0% 3 67% 1 0% 1 0%
mageekguy\atoum\test::setClassEngine() 10 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::getClassEngine() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::classHasVoidMethods() 7 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::classHasNotVoidMethods() 7 0% 2 50% 1 0% 1 0%
mageekguy\atoum\test::setMethodVoid() 9 0% 3 33% 1 0% 1 0%
mageekguy\atoum\test::setMethodNotVoid() 9 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::methodIsNotVoid() 17 0% 2 50% 5 0% 2 0%
mageekguy\atoum\test::setMethodEngine() 13 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::getMethodEngine() 20 85% 3 100% 5 60% 2 50%
mageekguy\atoum\test::enableDebugMode() 9 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::disableDebugMode() 9 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::debugModeIsEnabled() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::setXdebugConfig() 9 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::getXdebugConfig() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::executeOnFailure() 10 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::codeCoverageIsEnabled() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::enableCodeCoverage() 14 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::disableCodeCoverage() 9 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::branchCoverageIsEnabled() 6 0% 1 0% 1 0% 1 0%
mageekguy\atoum\test::enableBranchCoverage() 19 0% 2 0% 4 0% 2 0%
mageekguy\atoum\test::disableBranchCoverage() 9 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::setMaxChildrenNumber() 24 96% 6 100% 4 75% 2 100%
mageekguy\atoum\test::setBootstrapFile() 9 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getBootstrapFile() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setTestNamespace() 28 96% 5 100% 4 75% 2 100%
mageekguy\atoum\test::getTestNamespace() 13 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setTestMethodPrefix() 24 96% 6 100% 4 75% 2 100%
mageekguy\atoum\test::getTestMethodPrefix() 13 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setPhpPath() 10 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getPhpPath() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::getAllTags() 45 44% 9 56% 9 22% 4 25%
mageekguy\atoum\test::setTags() 9 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getTags() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setMethodTags() 18 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getMethodTags() 59 69% 10 90% 18 44% 6 33%
mageekguy\atoum\test::getDataProviders() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::getTestedClassName() 30 100% 6 100% 4 100% 2 100%
mageekguy\atoum\test::getTestedClassNamespace() 24 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::getTestedClassPath() 31 100% 8 100% 4 75% 2 50%
mageekguy\atoum\test::setTestedClassName() 23 96% 6 100% 4 75% 2 100%
mageekguy\atoum\test::getClass() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getClassNamespace() 6 0% 1 0% 1 0% 1 0%
mageekguy\atoum\test::getPath() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getTaggedTestMethods() 24 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::getTestMethods() 37 68% 9 100% 9 67% 4 25%
mageekguy\atoum\test::getCurrentMethod() 6 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getMaxChildrenNumber() 6 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::getCoverage() 10 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::count() 11 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::addObserver() 13 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::removeObserver() 13 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::getObservers() 11 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::callObservers() 21 0% 5 60% 6 0% 3 0%
mageekguy\atoum\test::ignore() 20 100% 4 100% 1 100% 1 100%
mageekguy\atoum\test::isIgnored() 99 44% 12 58% 19 63% 48 4%
mageekguy\atoum\test::ignoreMethod() 29 100% 4 100% 1 100% 1 100%
mageekguy\atoum\test::methodIsIgnored() 68 100% 13 100% 16 94% 13 46%
mageekguy\atoum\test::runTestMethods() 185 66% 41 76% 31 45% 160 1%
mageekguy\atoum\test::runTestMethod() 861 13% 142 20% 95 2% 4096 0%
mageekguy\atoum\test::run() 67 25% 14 43% 11 27% 5 20%
mageekguy\atoum\test::startCase() 19 100% 4 100% 1 100% 1 100%
mageekguy\atoum\test::stopCase() 17 100% 3 100% 1 100% 1 100%
mageekguy\atoum\test::setDataProvider() 53 91% 10 80% 7 57% 4 50%
mageekguy\atoum\test::errorHandler() 68 100% 9 100% 7 100% 4 75%
mageekguy\atoum\test::setUp() 3 0% 1 0% 1 0% 1 0%
mageekguy\atoum\test::beforeTestMethod() 4 0% 1 0% 1 0% 1 0%
mageekguy\atoum\test::afterTestMethod() 4 0% 1 0% 1 0% 1 0%
mageekguy\atoum\test::tearDown() 3 0% 1 0% 1 0% 1 0%
mageekguy\atoum\test::setNamespace() 28 68% 6 83% 4 25% 2 50%
mageekguy\atoum\test::getNamespace() 11 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setMethodPrefix() 20 0% 5 0% 4 0% 2 0%
mageekguy\atoum\test::getMethodPrefix() 11 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::setDefaultEngine() 9 0% 2 0% 1 0% 1 0%
mageekguy\atoum\test::getDefaultEngine() 11 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::getTestedClassNameFromTestClass() 115 98% 17 100% 14 86% 8 75%
mageekguy\atoum\test::setClassAnnotations() 83 100% 40 38% 1 100% 1 100%
mageekguy\atoum\test::setMethodAnnotations() 70 100% 38 47% 1 100% 1 100%
mageekguy\atoum\test::getBacktrace() 68 47% 13 46% 25 40% 52 0%
mageekguy\atoum\test::checkMethod() 26 96% 4 100% 4 75% 2 100%
mageekguy\atoum\test::addExceptionToScore() 33 0% 3 0% 1 0% 1 0%
mageekguy\atoum\test::runEngines() 226 0% 52 2% 40 0% 19 0%
mageekguy\atoum\test::stopEngines() 36 0% 10 0% 13 0% 5 0%
mageekguy\atoum\test::runEngine() 74 0% 16 0% 10 0% 4 0%
mageekguy\atoum\test::canRunEngine() 22 0% 1 0% 7 0% 4 0%
mageekguy\atoum\test::doTearDown() 26 0% 4 0% 1 0% 1 0%
mageekguy\atoum\test::getExtensions() 11 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::removeExtension() 19 100% 2 100% 1 100% 1 100%
mageekguy\atoum\test::removeExtensions() 27 67% 5 100% 6 67% 3 33%
mageekguy\atoum\test::addExtension() 36 100% 7 100% 4 100% 2 100%
mageekguy\atoum\test::addExtensions() 19 0% 4 0% 6 0% 3 0%
mageekguy\atoum\test::cleanNamespace() 13 100% 1 100% 1 100% 1 100%
mageekguy\atoum\test::isRegex() 13 100% 1 100% 1 100% 1 100%
#
1
<?php
2

                    
3
namespace mageekguy\atoum;
4

                    
5
use
6
	mageekguy\atoum,
7
	mageekguy\atoum\test,
8
	mageekguy\atoum\mock,
9
	mageekguy\atoum\asserter,
10
	mageekguy\atoum\asserters,
11
	mageekguy\atoum\exceptions,
12
	mageekguy\atoum\annotations
13
;
14

                    
15
abstract class test implements observable, \countable
16
{
17
	const testMethodPrefix = 'test';
18
	const defaultNamespace = '#(?:^|\\\)tests?\\\units?\\\#i';
19
	const defaultMethodPrefix = '#^(?:test|_*[^_]+_should_)#i';
20
	const runStart = 'testRunStart';
21
	const beforeSetUp = 'beforeTestSetUp';
22
	const afterSetUp = 'afterTestSetUp';
23
	const beforeTestMethod = 'beforeTestMethod';
24
	const fail = 'testAssertionFail';
25
	const error = 'testError';
26
	const void = 'testVoid';
27
	const uncompleted = 'testUncompleted';
28
	const skipped = 'testSkipped';
29
	const exception = 'testException';
30
	const runtimeException = 'testRuntimeException';
31
	const success = 'testAssertionSuccess';
32
	const afterTestMethod = 'afterTestMethod';
33
	const beforeTearDown = 'beforeTestTearDown';
34
	const afterTearDown = 'afterTestTearDown';
35
	const runStop = 'testRunStop';
36
	const defaultEngine = 'concurrent';
37
	const enginesNamespace = '\mageekguy\atoum\test\engines';
38

                    
39
	private $score = null;
40
	private $locale = null;
41
	private $adapter = null;
42
	private $mockGenerator = null;
43
	private $mockAutoloader = null;
44
	private $factoryBuilder = null;
45
	private $reflectionMethodFactory = null;
46
	private $phpExtensionFactory;
47
	private $asserterGenerator = null;
48
	private $assertionManager = null;
49
	private $phpMocker = null;
50
	private $testAdapterStorage = null;
51
	private $asserterCallManager = null;
52
	private $mockControllerLinker = null;
53
	private $phpPath = null;
54
	private $testedClassName = null;
55
	private $testedClassPath = null;
56
	private $currentMethod = null;
57
	private $testNamespace = null;
58
	private $testMethodPrefix = null;
59
	private $classEngine = null;
60
	private $bootstrapFile = null;
61
	private $maxAsynchronousEngines = null;
62
	private $asynchronousEngines = 0;
63
	private $path = '';
64
	private $class = '';
65
	private $classNamespace = '';
66
	private $observers = null;
67
	private $tags = array();
68
	private $phpVersions = array();
69
	private $mandatoryExtensions = array();
70
	private $dataProviders = array();
71
	private $testMethods = array();
72
	private $runTestMethods = array();
73
	private $engines = array();
74
	private $methodEngines = array();
75
	private $methodsAreNotVoid = array();
76
	private $executeOnFailure = array();
77
	private $ignore = false;
78
	private $debugMode = false;
79
	private $xdebugConfig = null;
80
	private $codeCoverage = false;
81
	private $branchCoverage = false;
82
	private $classHasNotVoidMethods = false;
83
	private $extensions = null;
84

                    
85
	private static $namespace = null;
86
	private static $methodPrefix = null;
87
	private static $defaultEngine = self::defaultEngine;
88

                    
89
	public function __construct(adapter $adapter = null, annotations\extractor $annotationExtractor = null, asserter\generator $asserterGenerator = null, test\assertion\manager $assertionManager = null, \closure $reflectionClassFactory = null, \closure $phpExtensionFactory = null)91%
90
	{
91
		$this
92
			->setAdapter($adapter)
93
			->setPhpMocker()
94
			->setMockGenerator()
95
			->setMockAutoloader()
96
			->setAsserterGenerator($asserterGenerator)
97
			->setAssertionManager($assertionManager)
98
			->setTestAdapterStorage()
99
			->setMockControllerLinker()
100
			->setScore()
101
			->setLocale()
102
			->setFactoryBuilder()
103
			->setReflectionMethodFactory()
104
			->setAsserterCallManager()
105
			->enableCodeCoverage()
106
			->setPhpExtensionFactory($phpExtensionFactory);
107
		;
108

                    
109
		$this->observers = new \splObjectStorage();
110
		$this->extensions = new \splObjectStorage();
111

                    
112
		$class = ($reflectionClassFactory ? $reflectionClassFactory($this) : new \reflectionClass($this));
113

                    
114
		$this->path = $class->getFilename();
115
		$this->class = $class->getName();
116
		$this->classNamespace = $class->getNamespaceName();
117

                    
118
		if ($annotationExtractor === null)
119
		{
120
			$annotationExtractor = new annotations\extractor();
121
		}
122

                    
123
		$this->setClassAnnotations($annotationExtractor);
124

                    
125
		$annotationExtractor->extract($class->getDocComment());
126

                    
127
		if ($this->testNamespace === null || $this->testMethodPrefix === null)
128
		{
129
			$annotationExtractor
130
				->unsetHandler('ignore')
131
				->unsetHandler('tags')
132
				->unsetHandler('maxChildrenNumber')
133
			;
134

                    
135
			$parentClass = $class;
136

                    
137
			while (($this->testNamespace === null || $this->testMethodPrefix === null) && ($parentClass = $parentClass->getParentClass()) !== false)
138
			{
139
				$annotationExtractor->extract($parentClass->getDocComment());
140

                    
141
				if ($this->testNamespace !== null)
142
				{
143
					$annotationExtractor->unsetHandler('namespace');
144
				}
145

                    
146
				if ($this->testMethodPrefix !== null)
147
				{
148
					$annotationExtractor->unsetHandler('methodPrefix');
149
				}
150
			}
151
		}
152

                    
153
		$this->setMethodAnnotations($annotationExtractor, $methodName);
154

                    
155
		$testMethodPrefix = $this->getTestMethodPrefix();
156

                    
157
		if (self::isRegex($testMethodPrefix) === false)
158
		{
159
			$testMethodFilter = function($methodName) use ($testMethodPrefix) { return (stripos($methodName, $testMethodPrefix) === 0); };
160
		}
161
		else
162
		{
163
			$testMethodFilter = function($methodName) use ($testMethodPrefix) { return (preg_match($testMethodPrefix, $methodName) == true); };
164
		}
165

                    
166
		foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $publicMethod)
167
		{
168
			$methodName = $publicMethod->getName();
169

                    
170
			if ($testMethodFilter($methodName) == true)
171
			{
172
				$this->testMethods[$methodName] = array();
173

                    
174
				$annotationExtractor->extract($publicMethod->getDocComment());
175

                    
176
				if ($publicMethod->getNumberOfParameters() > 0 && isset($this->dataProviders[$methodName]) === false)
177
				{
178
					$this->setDataProvider($methodName);
179
				}
180
			}
181
		}
182

                    
183
		$this->runTestMethods($this->getTestMethods());
184
	}
185

                    
186
	public function __toString()100%
187
	{
188
		return $this->getClass();
189
	}
190

                    
191
	public function __get($property)
192
	{
193
		return $this->assertionManager->__get($property);
194
	}
195

                    
196
	public function __set($property, $handler)100%
197
	{
198
		$this->assertionManager->{$property} = $handler;
199

                    
200
		return $this;
201
	}
202

                    
203
	public function __call($method, array $arguments)
204
	{
205
		return $this->assertionManager->__call($method, $arguments);
206
	}
207

                    
208
	public function setTestAdapterStorage(test\adapter\storage $storage = null)100%
209
	{
210
		$this->testAdapterStorage = $storage ?: new test\adapter\storage();
211

                    
212
		return $this;
213
	}
214

                    
215
	public function getTestAdapterStorage()67%
216
	{
217
		return $this->testAdapterStorage;
218
	}
219

                    
220
	public function setMockControllerLinker(mock\controller\linker $linker = null)100%
221
	{
222
		$this->mockControllerLinker = $linker ?: new mock\controller\linker();
223

                    
224
		return $this;
225
	}
226

                    
227
	public function getMockControllerLinker()
228
	{
229
		return $this->mockControllerLinker;
230
	}
231

                    
232
	public function setScore(test\score $score = null)100%
233
	{
234
		$this->score = $score ?: new test\score();
235

                    
236
		return $this;
237
	}
238

                    
239
	public function getScore()100%
240
	{
241
		return $this->score;
242
	}
243

                    
244
	public function setLocale(locale $locale = null)100%
245
	{
246
		$this->locale = $locale ?: new locale();
247

                    
248
		return $this;
249
	}
250

                    
251
	public function getLocale()100%
252
	{
253
		return $this->locale;
254
	}
255

                    
256
	public function setAdapter(adapter $adapter = null)100%
257
	{
258
		$this->adapter = $adapter ?: new adapter();
259

                    
260
		return $this;
261
	}
262

                    
263
	public function getAdapter()100%
264
	{
265
		return $this->adapter;
266
	}
267

                    
268
	public function setPhpMocker(php\mocker $phpMocker = null)
269
	{
270
		$this->phpMocker = $phpMocker ?: new php\mocker();
271

                    
272
		return $this;
273
	}
274

                    
275
	public function getPhpMocker()100%
276
	{
277
		return $this->phpMocker;
278
	}
279

                    
280
	public function setMockGenerator(test\mock\generator $generator = null)100%
281
	{
282
		if ($generator !== null)
283
		{
284
			$generator->setTest($this);
285
		}
286
		else
287
		{
288
			$generator = new test\mock\generator($this);
289
		}
290

                    
291
		$this->mockGenerator = $generator;
292

                    
293
		return $this;
294
	}
295

                    
296
	public function getMockGenerator()
297
	{
298
		return $this->mockGenerator;
299
	}
300

                    
301
	public function setMockAutoloader(atoum\autoloader\mock $autoloader = null)100%
302
	{
303
		$this->mockAutoloader = $autoloader ?: new atoum\autoloader\mock();
304

                    
305
		return $this;
306
	}
307

                    
308
	public function getMockAutoloader()100%
309
	{
310
		return $this->mockAutoloader;
311
	}
312

                    
313
	public function setFactoryBuilder(factory\builder $factoryBuilder = null)100%
314
	{
315
		$this->factoryBuilder = $factoryBuilder ?: new factory\builder\closure();
316

                    
317
		return $this;
318
	}
319

                    
320
	public function getFactoryBuilder()100%
321
	{
322
		return $this->factoryBuilder;
323
	}
324

                    
325
	public function setReflectionMethodFactory(\closure $factory = null)100%
326
	{
327
		$this->reflectionMethodFactory = $factory ?: function($class, $method) { return new \reflectionMethod($class, $method); };
328

                    
329
		return $this;
330
	}
331

                    
332
	public function setPhpExtensionFactory(\closure $factory = null)75%
333
	{
334
		$this->phpExtensionFactory = $factory ?: function($extensionName) {
335
			return new atoum\php\extension($extensionName);
336
		};
337

                    
338
		return $this;
339
	}
340

                    
341
	public function setAsserterGenerator(test\asserter\generator $generator = null)100%
342
	{
343
		if ($generator !== null)
344
		{
345
			$generator->setTest($this);
346
		}
347
		else
348
		{
349
			$generator = new test\asserter\generator($this);
350
		}
351

                    
352
		$this->asserterGenerator = $generator->setTest($this);
353

                    
354
		return $this;
355
	}
356

                    
357
	public function getAsserterGenerator()100%
358
	{
359
		$this->testAdapterStorage->resetCalls();
360

                    
361
		return $this->asserterGenerator;
362
	}
363

                    
364
	public function setAssertionManager(test\assertion\manager $assertionManager = null)98%
365
	{
366
		$this->assertionManager = $assertionManager ?: new test\assertion\manager();
367

                    
368
		$test = $this;
369

                    
370
		$this->assertionManager
371
			->setHandler('when', function($mixed) use ($test) { if ($mixed instanceof \closure) { $mixed($test); } return $test; })
372
			->setHandler('assert', function($case = null) use ($test) { $test->stopCase(); if ($case !== null) { $test->startCase($case); } return $test; })
373
			->setHandler('mockGenerator', function() use ($test) { return $test->getMockGenerator(); })
374
			->setHandler('mockClass', function($class, $mockNamespace = null, $mockClass = null) use ($test) { $test->getMockGenerator()->generate($class, $mockNamespace, $mockClass); return $test; })
375
			->setHandler('mockTestedClass', function($mockNamespace = null, $mockClass = null) use ($test) { $test->getMockGenerator()->generate($test->getTestedClassName(), $mockNamespace, $mockClass); return $test; })
376
			->setHandler('dump', function() use ($test) { if ($test->debugModeIsEnabled() === true) { call_user_func_array('var_dump', func_get_args()); } return $test; })
377
			->setHandler('stop', function() use ($test) { if ($test->debugModeIsEnabled() === true) { throw new test\exceptions\stop(); } return $test; })
378
			->setHandler('executeOnFailure', function($callback) use ($test) { if ($test->debugModeIsEnabled() === true) { $test->executeOnFailure($callback); } return $test; })
379
			->setHandler('dumpOnFailure', function($variable) use ($test) { if ($test->debugModeIsEnabled() === true) { $test->executeOnFailure(function() use ($variable) { var_dump($variable); }); } return $test; })
380
			->setPropertyHandler('function', function() use ($test) { return $test->getPhpMocker(); })
381
			->setPropertyHandler('exception', function() { return asserters\exception::getLastValue(); })
382
		;
383

                    
384
		$mockGenerator = $this->mockGenerator;
385

                    
386
		$this->assertionManager
387
			->setPropertyHandler('nextMockedMethod', function() use ($mockGenerator) { return $mockGenerator->getMethod(); })
388
		;
389

                    
390
		$returnTest = function() use ($test) { return $test; };
391

                    
392
		$this->assertionManager
393
			->setHandler('if', $returnTest)
394
			->setHandler('and', $returnTest)
395
			->setHandler('then', $returnTest)
396
			->setHandler('given', $returnTest)
397
			->setMethodHandler('define', $returnTest)
398
			->setMethodHandler('let', $returnTest)
399
		;
400

                    
401
		$returnMockController = function(mock\aggregator $mock) { return $mock->getMockController(); };
402

                    
403
		$this->assertionManager
404
			->setHandler('calling', $returnMockController)
405
			->setHandler('ƒ', $returnMockController)
406

                    
407
		;
408

                    
409
		$this->assertionManager
410
			->setHandler('resetMock', function(mock\aggregator $mock) { return $mock->getMockController()->resetCalls(); })
411
			->setHandler('resetAdapter', function(test\adapter $adapter) { return $adapter->resetCalls(); })
412
		;
413

                    
414
		$phpMocker = $this->phpMocker;
415

                    
416
		$this->assertionManager->setHandler('resetFunction', function(test\adapter\invoker $invoker) use ($phpMocker) { $phpMocker->resetCalls($invoker->getFunction()); return $invoker; });
417

                    
418
		$assertionAliaser = $this->assertionManager->getAliaser();
419

                    
420
		$this->assertionManager
421
			->setPropertyHandler('define', function() use ($assertionAliaser, $test) { return $assertionAliaser; })
422
			->setHandler('from', function($class) use ($assertionAliaser, $test) { $assertionAliaser->from($class); return $test; })
423
			->setHandler('use', function($target) use ($assertionAliaser, $test) { $assertionAliaser->alias($target); return $test; })
424
			->setHandler('as', function($alias) use ($assertionAliaser, $test) { $assertionAliaser->to($alias); return $test; })
425
		;
426

                    
427
		$asserterGenerator = $this->asserterGenerator;
428

                    
429
		$this->assertionManager->setDefaultHandler(function($keyword, $arguments) use ($asserterGenerator, $assertionAliaser, & $lastAsserter) {
430
				static $lastAsserter = null;
431

                    
432
				if ($lastAsserter !== null)
433
				{
434
					$realKeyword = $assertionAliaser->resolveAlias($keyword, get_class($lastAsserter));
435

                    
436
					if ($realKeyword !== $keyword)
437
					{
438
						return call_user_func_array(array($lastAsserter, $realKeyword), $arguments);
439
					}
440
				}
441

                    
442
				return ($lastAsserter = $asserterGenerator->getAsserterInstance($keyword, $arguments));
443
			}
444
		);
445

                    
446
		$this->assertionManager
447
			->use('phpArray')->as('array')
448
			->use('phpArray')->as('in')
449
			->use('phpClass')->as('class')
450
			->use('phpFunction')->as('function')
451
			->use('phpFloat')->as('float')
452
			->use('phpString')->as('string')
453
			->use('calling')->as('method')
454
		;
455

                    
456
		return $this;
457
	}
458

                    
459
	public function getAsserterCallManager()100%
460
	{
461
		return $this->asserterCallManager;
462
	}
463

                    
464
	public function setAsserterCallManager(asserters\adapter\call\manager $asserterCallManager = null)100%
465
	{
466
		$this->asserterCallManager = $asserterCallManager ?: new asserters\adapter\call\manager();
467

                    
468
		return $this;
469
	}
470

                    
471
	public function addClassPhpVersion($version, $operator = null)100%
472
	{
473
		$this->phpVersions[$version] = $operator ?: '>=';
474

                    
475
		return $this;
476
	}
477

                    
478
	public function getClassPhpVersions()100%
479
	{
480
		return $this->phpVersions;
481
	}
482

                    
483
	public function addMandatoryClassExtension($extension)100%
484
	{
485
		$this->mandatoryExtensions[] = $extension;
486

                    
487
		return $this;
488
	}
489

                    
490
	public function addMethodPhpVersion($testMethodName, $version, $operator = null)100%
491
	{
492
		$this->checkMethod($testMethodName)->testMethods[$testMethodName]['php'][$version] = $operator ?: '>=';
493

                    
494
		return $this;
495
	}
496

                    
497
	public function getMethodPhpVersions($testMethodName = null)100%
498
	{
499
		$versions = array();
500

                    
501
		$classVersions = $this->getClassPhpVersions();
502

                    
503
		if ($testMethodName === null)
504
		{
505
			foreach ($this->testMethods as $testMethodName => $annotations)
506
			{
507
				if (isset($annotations['php']) === false)
508
				{
509
					$versions[$testMethodName] = $classVersions;
510
				}
511
				else
512
				{
513
					$versions[$testMethodName] = array_merge($classVersions, $annotations['php']);
514
				}
515
			}
516
		}
517
		else
518
		{
519
			if (isset($this->checkMethod($testMethodName)->testMethods[$testMethodName]['php']) === false)
520
			{
521
				$versions = $classVersions;
522
			}
523
			else
524
			{
525
				$versions = array_merge($classVersions, $this->testMethods[$testMethodName]['php']);
526
			}
527
		}
528

                    
529
		return $versions;
530
	}
531

                    
532
	public function getMandatoryClassExtensions()100%
533
	{
534
		return $this->mandatoryExtensions;
535
	}
536

                    
537
	public function addMandatoryMethodExtension($testMethodName, $extension)100%
538
	{
539
		$this->checkMethod($testMethodName)->testMethods[$testMethodName]['mandatoryExtensions'][] = $extension;
540

                    
541
		return $this;
542
	}
543

                    
544
	public function getMandatoryMethodExtensions($testMethodName = null)89%
545
	{
546
		$extensions = array();
547

                    
548
		$mandatoryClassExtensions = $this->getMandatoryClassExtensions();
549

                    
550
		if ($testMethodName === null)
551
		{
552
			foreach ($this->testMethods as $testMethodName => $annotations)
553
			{
554
				if (isset($annotations['mandatoryExtensions']) === false)
555
				{
556
					$extensions[$testMethodName] = $mandatoryClassExtensions;
557
				}
558
				else
559
				{
560
					$extensions[$testMethodName] = array_merge($mandatoryClassExtensions, $annotations['mandatoryExtensions']);
561
				}
562
			}
563
		}
564
		else
565
		{
566
			if (isset($this->checkMethod($testMethodName)->testMethods[$testMethodName]['mandatoryExtensions']) === false)
567
			{
568
				$extensions = $mandatoryClassExtensions;
569
			}
570
			else
571
			{
572
				$extensions = array_merge($mandatoryClassExtensions, $this->testMethods[$testMethodName]['mandatoryExtensions']);
573
			}
574
		}
575

                    
576
		return $extensions;
577
	}
578

                    
579
	public function skip($message)
580
	{
581
		throw new test\exceptions\skip($message);
582
	}
583

                    
584
	public function getAssertionManager()
585
	{
586
		return $this->assertionManager;
587
	}
588

                    
589
	public function setClassEngine($engine)0%
590
	{
591
		$this->classEngine = (string) $engine;
592

                    
593
		return $this;
594
	}
595

                    
596
	public function getClassEngine()100%
597
	{
598
		return $this->classEngine;
599
	}
600

                    
601
	public function classHasVoidMethods()0%
602
	{
603
		$this->classHasNotVoidMethods = false;
604
	}
605

                    
606
	public function classHasNotVoidMethods()50%
607
	{
608
		$this->classHasNotVoidMethods = true;
609
	}
610

                    
611
	public function setMethodVoid($method)33%
612
	{
613
		$this->methodsAreNotVoid[$method] = false;
614
	}
615

                    
616
	public function setMethodNotVoid($method)0%
617
	{
618
		$this->methodsAreNotVoid[$method] = true;
619
	}
620

                    
621
	public function methodIsNotVoid($method)
622
	{
623
		return (isset($this->methodsAreNotVoid[$method]) === false ? $this->classHasNotVoidMethods : $this->methodsAreNotVoid[$method]);
624
	}
625

                    
626
	public function setMethodEngine($method, $engine)0%
627
	{
628
		$this->methodEngines[(string) $method] = (string) $engine;
629

                    
630
		return $this;
631
	}
632

                    
633
	public function getMethodEngine($method)
634
	{
635
		$method = (string) $method;
636

                    
637
		return (isset($this->methodEngines[$method]) === false ? null : $this->methodEngines[$method]);
638
	}
639

                    
640
	public function enableDebugMode()100%
641
	{
642
		$this->debugMode = true;
643

                    
644
		return $this;
645
	}
646

                    
647
	public function disableDebugMode()100%
648
	{
649
		$this->debugMode = false;
650

                    
651
		return $this;
652
	}
653

                    
654
	public function debugModeIsEnabled()
655
	{
656
		return $this->debugMode;
657
	}
658

                    
659
	public function setXdebugConfig($value)0%
660
	{
661
		$this->xdebugConfig = $value;
662

                    
663
		return $this;
664
	}
665

                    
666
	public function getXdebugConfig()100%
667
	{
668
		return $this->xdebugConfig;
669
	}
670

                    
671
	public function executeOnFailure(\closure $closure)0%
672
	{
673
		$this->executeOnFailure[] = $closure;
674

                    
675
		return $this;
676
	}
677

                    
678
	public function codeCoverageIsEnabled()100%
679
	{
680
		return $this->codeCoverage;
681
	}
682

                    
683
	public function enableCodeCoverage()100%
684
	{
685
		$this->codeCoverage = $this->adapter->extension_loaded('xdebug');
686

                    
687
		return $this;
688
	}
689

                    
690
	public function disableCodeCoverage()100%
691
	{
692
		$this->codeCoverage = false;
693

                    
694
		return $this;
695
	}
696

                    
697
	public function branchCoverageIsEnabled()0%
698
	{
699
		return $this->branchCoverage;
700
	}
701

                    
702
	public function enableBranchCoverage()0%
703
	{
704
		$this->branchCoverage = $this->codeCoverageIsEnabled() && defined('XDEBUG_CC_BRANCH_CHECK');
705

                    
706
		return $this;
707
	}
708

                    
709
	public function disableBranchCoverage()0%
710
	{
711
		$this->branchCoverage = false;
712

                    
713
		return $this;
714
	}
715

                    
716
	public function setMaxChildrenNumber($number)100%
717
	{
718
		$number = (int) $number;
719

                    
720
		if ($number < 1)
721
		{
722
			throw new exceptions\logic\invalidArgument('Maximum number of children must be greater or equal to 1');
723
		}
724

                    
725
		$this->maxAsynchronousEngines = $number;
726

                    
727
		return $this;
728
	}
729

                    
730
	public function setBootstrapFile($path)100%
731
	{
732
		$this->bootstrapFile = $path;
733

                    
734
		return $this;
735
	}
736

                    
737
	public function getBootstrapFile()100%
738
	{
739
		return $this->bootstrapFile;
740
	}
741

                    
742
	public function setTestNamespace($testNamespace)100%
743
	{
744
		$this->testNamespace = self::cleanNamespace($testNamespace);
745

                    
746
		if ($this->testNamespace === '')
747
		{
748
			throw new exceptions\logic\invalidArgument('Test namespace must not be empty');
749
		}
750

                    
751
		return $this;
752
	}
753

                    
754
	public function getTestNamespace()100%
755
	{
756
		return $this->testNamespace ?: self::getNamespace();
757
	}
758

                    
759
	public function setTestMethodPrefix($methodPrefix)100%
760
	{
761
		$methodPrefix = (string) $methodPrefix;
762

                    
763
		if ($methodPrefix == '')
764
		{
765
			throw new exceptions\logic\invalidArgument('Test method prefix must not be empty');
766
		}
767

                    
768
		$this->testMethodPrefix = $methodPrefix;
769

                    
770
		return $this;
771
	}
772

                    
773
	public function getTestMethodPrefix()100%
774
	{
775
		return $this->testMethodPrefix ?: self::getMethodPrefix();
776
	}
777

                    
778
	public function setPhpPath($path)100%
779
	{
780
		$this->phpPath = (string) $path;
781

                    
782
		return $this;
783
	}
784

                    
785
	public function getPhpPath()100%
786
	{
787
		return $this->phpPath;
788
	}
789

                    
790
	public function getAllTags()56%
791
	{
792
		$tags = $this->getTags();
793

                    
794
		foreach ($this->testMethods as $annotations)
795
		{
796
			if (isset($annotations['tags']) === true)
797
			{
798
				$tags = array_merge($tags, array_diff($annotations['tags'], $tags));
799
			}
800
		}
801

                    
802
		return array_values($tags);
803
	}
804

                    
805
	public function setTags(array $tags)100%
806
	{
807
		$this->tags = $tags;
808

                    
809
		return $this;
810
	}
811

                    
812
	public function getTags()100%
813
	{
814
		return $this->tags;
815
	}
816

                    
817
	public function setMethodTags($testMethodName, array $tags)100%
818
	{
819
		$this->checkMethod($testMethodName)->testMethods[$testMethodName]['tags'] = $tags;
820

                    
821
		return $this;
822
	}
823

                    
824
	public function getMethodTags($testMethodName = null)90%
825
	{
826
		$tags = array();
827

                    
828
		$classTags = $this->getTags();
829

                    
830
		if ($testMethodName === null)
831
		{
832
			foreach ($this->testMethods as $testMethodName => $annotations)
833
			{
834
				$tags[$testMethodName] = isset($annotations['tags']) === false ? $classTags : $annotations['tags'];
835
			}
836
		}
837
		else
838
		{
839
			$tags = isset($this->checkMethod($testMethodName)->testMethods[$testMethodName]['tags']) === false ? $classTags : $this->testMethods[$testMethodName]['tags'];
840
		}
841

                    
842
		return $tags;
843
	}
844

                    
845
	public function getDataProviders()100%
846
	{
847
		return $this->dataProviders;
848
	}
849

                    
850
	public function getTestedClassName()100%
851
	{
852
		if ($this->testedClassName === null)
853
		{
854
			$this->testedClassName = self::getTestedClassNameFromTestClass($this->getClass(), $this->getTestNamespace());
855
		}
856

                    
857
		return $this->testedClassName;
858
	}
859

                    
860
	public function getTestedClassNamespace()0%
861
	{
862
		$testedClassName = $this->getTestedClassName();
863

                    
864
		return substr($testedClassName, 0, strrpos($testedClassName, '\\'));
865
	}
866

                    
867
	public function getTestedClassPath()100%
868
	{
869
		if ($this->testedClassPath === null)
870
		{
871
			$testedClass = new \reflectionClass($this->getTestedClassName());
872

                    
873
			$this->testedClassPath = $testedClass->getFilename();
874
		}
875

                    
876
		return $this->testedClassPath;
877
	}
878

                    
879
	public function setTestedClassName($className)100%
880
	{
881
		if ($this->testedClassName !== null)
882
		{
883
			throw new exceptions\runtime('Tested class name is already defined');
884
		}
885

                    
886
		$this->testedClassName = $className;
887

                    
888
		return $this;
889
	}
890

                    
891
	public function getClass()100%
892
	{
893
		return $this->class;
894
	}
895

                    
896
	public function getClassNamespace()0%
897
	{
898
		return $this->classNamespace;
899
	}
900

                    
901
	public function getPath()100%
902
	{
903
		return $this->path;
904
	}
905

                    
906
	public function getTaggedTestMethods(array $methods, array $tags = array())100%
907
	{
908
		return array_values(array_uintersect($methods, $this->getTestMethods($tags), 'strcasecmp'));
909
	}
910

                    
911
	public function getTestMethods(array $tags = array())100%
912
	{
913
		$testMethods = array();
914

                    
915
		foreach (array_keys($this->testMethods) as $methodName)
916
		{
917
			if ($this->methodIsIgnored($methodName, $tags) === false)
918
			{
919
				$testMethods[] = $methodName;
920
			}
921
		}
922

                    
923
		return $testMethods;
924
	}
925

                    
926
	public function getCurrentMethod()100%
927
	{
928
		return $this->currentMethod;
929
	}
930

                    
931
	public function getMaxChildrenNumber()100%
932
	{
933
		return $this->maxAsynchronousEngines;
934
	}
935

                    
936
	public function getCoverage()100%
937
	{
938
		return $this->score->getCoverage();
939
	}
940

                    
941
	public function count()100%
942
	{
943
		return sizeof($this->runTestMethods);
944
	}
945

                    
946
	public function addObserver(observer $observer)100%
947
	{
948
		$this->observers->attach($observer);
949

                    
950
		return $this;
951
	}
952

                    
953
	public function removeObserver(atoum\observer $observer)100%
954
	{
955
		$this->observers->detach($observer);
956

                    
957
		return $this;
958
	}
959

                    
960
	public function getObservers()100%
961
	{
962
		return iterator_to_array($this->observers);
963
	}
964

                    
965
	public function callObservers($event)60%
966
	{
967
		foreach ($this->observers as $observer)
968
		{
969
			$observer->handleEvent($event, $this);
970
		}
971

                    
972
		return $this;
973
	}
974

                    
975
	public function ignore($boolean)
976
	{
977
		$this->ignore = ($boolean == true);
978

                    
979
		return $this->runTestMethods($this->getTestMethods());
980
	}
981

                    
982
	public function isIgnored(array $namespaces = array(), array $tags = array())58%
983
	{
984
		$isIgnored = (sizeof($this) <= 0 || $this->ignore === true);
985

                    
986
		if ($isIgnored === false && sizeof($namespaces) > 0)
987
		{
988
			$classNamespace = strtolower($this->getClassNamespace());
989

                    
990
			$isIgnored = sizeof(array_filter($namespaces, function($value) use ($classNamespace) { return strpos($classNamespace, strtolower($value)) === 0; })) <= 0;
991
		}
992

                    
993
		if ($isIgnored === false && sizeof($tags) > 0)
994
		{
995
			$isIgnored = sizeof($testTags = $this->getAllTags()) <= 0 || sizeof(array_intersect($tags, $testTags)) == 0;
996
		}
997

                    
998
		return $isIgnored;
999
	}
1000

                    
1001
	public function ignoreMethod($methodName, $boolean)
1002
	{
1003
		$this->checkMethod($methodName)->testMethods[$methodName]['ignore'] = $boolean == true;
1004

                    
1005
		return $this->runTestMethods($this->getTestMethods());
1006
	}
1007

                    
1008
	public function methodIsIgnored($methodName, array $tags = array())100%
1009
	{
1010
		$isIgnored = $this->checkMethod($methodName)->ignore;
1011

                    
1012
		if ($isIgnored === false)
1013
		{
1014
			if (isset($this->testMethods[$methodName]['ignore']) === true)
1015
			{
1016
				$isIgnored = $this->testMethods[$methodName]['ignore'];
1017
			}
1018

                    
1019
			if ($isIgnored === false && $tags)
1020
			{
1021
				$isIgnored = sizeof($methodTags = $this->getMethodTags($methodName)) <= 0 || sizeof(array_intersect($tags, $methodTags)) <= 0;
1022
			}
1023
		}
1024

                    
1025
		return $isIgnored;
1026
	}
1027

                    
1028
	public function runTestMethods(array $methods, array $tags = array())76%
1029
	{
1030
		$this->runTestMethods = $runTestMethods = array();
1031

                    
1032
		if (isset($methods['*']) === true)
1033
		{
1034
			$runTestMethods = $methods['*'];
1035
		}
1036

                    
1037
		$testClass = $this->getClass();
1038

                    
1039
		if (isset($methods[$testClass]) === true)
1040
		{
1041
			$runTestMethods = $methods[$testClass];
1042
		}
1043

                    
1044
		if (in_array('*', $runTestMethods) === true)
1045
		{
1046
			$runTestMethods = array();
1047
		}
1048

                    
1049
		if (sizeof($runTestMethods) <= 0)
1050
		{
1051
			$runTestMethods = $this->getTestMethods($tags);
1052
		}
1053
		else
1054
		{
1055
			$runTestMethods = $this->getTaggedTestMethods($runTestMethods, $tags);
1056
		}
1057

                    
1058
		foreach ($runTestMethods as $method)
1059
		{
1060
			if ($this->xdebugConfig != null)
1061
			{
1062
				$engineClass = 'mageekguy\atoum\test\engines\concurrent';
1063
			}
1064
			else
1065
			{
1066
				$engineName = $engineClass = ($this->getMethodEngine($method) ?: $this->getClassEngine() ?: self::getDefaultEngine());
1067

                    
1068
				if (substr($engineClass, 0, 1) !== '\\')
1069
				{
1070
					$engineClass = self::enginesNamespace . '\\' . $engineClass;
1071
				}
1072

                    
1073
				if (class_exists($engineClass) === false)
1074
				{
1075
					throw new exceptions\runtime('Test engine \'' . $engineName . '\' does not exist for method \'' . $this->class . '::' . $method . '()\'');
1076
				}
1077
			}
1078

                    
1079
			$engine = new $engineClass();
1080

                    
1081
			if ($engine instanceof test\engine === false)
1082
			{
1083
				throw new exceptions\runtime('Test engine \'' . $engineName . '\' is invalid for method \'' . $this->class . '::' . $method . '()\'');
1084
			}
1085

                    
1086
			$this->runTestMethods[$method] = $engine;
1087
		}
1088

                    
1089
		return $this;
1090
	}
1091

                    
1092
	public function runTestMethod($testMethod, array $tags = array())20%
1093
	{
1094
		if ($this->methodIsIgnored($testMethod, $tags) === false)
1095
		{
1096
			$this->mockAutoloader->setMockGenerator($this->mockGenerator)->register();
1097

                    
1098
			set_error_handler(array($this, 'errorHandler'));
1099

                    
1100
			ini_set('display_errors', 'stderr');
1101
			ini_set('log_errors', 'Off');
1102
			ini_set('log_errors_max_len', '0');
1103

                    
1104
			$this->currentMethod = $testMethod;
1105
			$this->executeOnFailure = array();
1106

                    
1107
			$this->phpMocker->setDefaultNamespace($this->getTestedClassNamespace());
1108

                    
1109
			try
1110
			{
1111
				foreach ($this->getMethodPhpVersions($testMethod) as $phpVersion => $operator)
1112
				{
1113
					if (version_compare(phpversion(), $phpVersion, $operator) === false)
1114
					{
1115
						throw new test\exceptions\skip('PHP version ' . PHP_VERSION . ' is not ' . $operator . ' to ' . $phpVersion);
1116
					}
1117
				}
1118

                    
1119
				foreach ($this->getMandatoryMethodExtensions($testMethod) as $mandatoryExtension)
1120
				{
1121
					try
1122
					{
1123
						call_user_func($this->phpExtensionFactory, $mandatoryExtension)->requireExtension();
1124
					}
1125
					catch (atoum\php\exception $exception)
1126
					{
1127
						throw new test\exceptions\skip($exception->getMessage());
1128
					}
1129
				}
1130

                    
1131
				try
1132
				{
1133
					ob_start();
1134

                    
1135
					test\adapter::setStorage($this->testAdapterStorage);
1136
					mock\controller::setLinker($this->mockControllerLinker);
1137

                    
1138
					$this->testAdapterStorage->add(php\mocker::getAdapter());
1139

                    
1140
					$this->beforeTestMethod($this->currentMethod);
1141

                    
1142
					$this->mockGenerator->testedClassIs($this->getTestedClassName());
1143

                    
1144
					try
1145
					{
1146
						$testedClass = new \reflectionClass($testedClassName = $this->getTestedClassName());
1147
					}
1148
					catch (\exception $exception)
1149
					{
1150
						throw new exceptions\runtime('Tested class \'' . $testedClassName . '\' does not exist for test class \'' . $this->getClass() . '\'');
1151
					}
1152

                    
1153
					if ($testedClass->isAbstract() === true)
1154
					{
1155
						$testedClass = new \reflectionClass($testedClassName = $this->mockGenerator->getDefaultNamespace() . '\\' . $testedClassName);
1156
					}
1157

                    
1158
					$this->factoryBuilder->build($testedClass, $instance)
1159
						->addToAssertionManager($this->assertionManager, 'newTestedInstance', function() use ($testedClass) {
1160
								throw new exceptions\runtime('Tested class ' . $testedClass->getName() . ' has no constructor or its constructor has at least one mandatory argument');
1161
							}
1162
						)
1163
					;
1164

                    
1165
					$this->factoryBuilder->build($testedClass)
1166
						->addToAssertionManager($this->assertionManager, 'newInstance', function() use ($testedClass) {
1167
								throw new exceptions\runtime('Tested class ' . $testedClass->getName() . ' has no constructor or its constructor has at least one mandatory argument');
1168
							}
1169
						)
1170
					;
1171

                    
1172
					$this->assertionManager->setPropertyHandler('testedInstance', function() use (& $instance) {
1173
							if ($instance === null)
1174
							{
1175
								throw new exceptions\runtime('Use $this->newTestedInstance before using $this->testedInstance');
1176
							}
1177

                    
1178
							return $instance;
1179
						}
1180
					);
1181

                    
1182
					if ($this->codeCoverageIsEnabled() === true)
1183
					{
1184
						$options = XDEBUG_CC_UNUSED | XDEBUG_CC_DEAD_CODE;
1185

                    
1186
						if ($this->branchCoverageIsEnabled() === true)
1187
						{
1188
							$options |= XDEBUG_CC_BRANCH_CHECK;
1189
						}
1190

                    
1191
						xdebug_start_code_coverage($options);
1192
					}
1193

                    
1194
					$assertionNumber = $this->score->getAssertionNumber();
1195
					$time = microtime(true);
1196
					$memory = memory_get_usage(true);
1197

                    
1198
					if (isset($this->dataProviders[$testMethod]) === false)
1199
					{
1200
						$this->{$testMethod}();
1201

                    
1202
						$this->asserterCallManager->check();
1203
					}
1204
					else
1205
					{
1206
						$data = $this->{$this->dataProviders[$testMethod]}();
1207

                    
1208
						if (is_array($data) === false && $data instanceof \traversable === false)
1209
						{
1210
							throw new test\exceptions\runtime('Data provider ' . $this->getClass() . '::' . $this->dataProviders[$testMethod] . '() must return an array or an iterator');
1211
						}
1212

                    
1213
						$reflectedTestMethod = call_user_func($this->reflectionMethodFactory, $this, $testMethod);
1214
						$numberOfArguments = $reflectedTestMethod->getNumberOfRequiredParameters();
1215

                    
1216
						foreach ($data as $key => $arguments)
1217
						{
1218
							if (is_array($arguments) === false)
1219
							{
1220
								$arguments = array($arguments);
1221
							}
1222

                    
1223
							if (sizeof($arguments) != $numberOfArguments)
1224
							{
1225
								throw new test\exceptions\runtime('Data provider ' . $this->getClass() . '::' . $this->dataProviders[$testMethod] . '() not provide enough arguments at key ' . $key . ' for test method ' . $this->getClass() . '::' . $testMethod . '()');
1226
							}
1227

                    
1228
							$this->score->setDataSet($key, $this->dataProviders[$testMethod]);
1229

                    
1230
							$reflectedTestMethod->invokeArgs($this, $arguments);
1231

                    
1232
							$this->asserterCallManager->check();
1233

                    
1234
							$this->score->unsetDataSet();
1235
						}
1236
					}
1237

                    
1238
					$this->mockControllerLinker->reset();
1239
					$this->testAdapterStorage->reset();
1240

                    
1241
					$memoryUsage = memory_get_usage(true) - $memory;
1242
					$duration = microtime(true) - $time;
1243

                    
1244
					$this->score
1245
						->addMemoryUsage($this->path, $this->class, $this->currentMethod, $memoryUsage)
1246
						->addDuration($this->path, $this->class, $this->currentMethod, $duration)
1247
						->addOutput($this->path, $this->class, $this->currentMethod, ob_get_clean())
1248
					;
1249

                    
1250
					if ($this->codeCoverageIsEnabled() === true)
1251
					{
1252
						$this->score->getCoverage()->addXdebugDataForTest($this, xdebug_get_code_coverage());
1253
						xdebug_stop_code_coverage();
1254
					}
1255

                    
1256
					if ($assertionNumber == $this->score->getAssertionNumber() && $this->methodIsNotVoid($this->currentMethod) === false)
1257
					{
1258
						$this->score->addVoidMethod($this->path, $this->class, $this->currentMethod);
1259
					}
1260
				}
1261
				catch (\exception $exception)
1262
				{
1263
					$this->score->addOutput($this->path, $this->class, $this->currentMethod, ob_get_clean());
1264

                    
1265
					throw $exception;
1266
				}
1267
			}
1268
			catch (asserter\exception $exception)
1269
			{
1270
				foreach ($this->executeOnFailure as $closure)
1271
				{
1272
					ob_start();
1273
					$closure();
1274
					$this->score->addOutput($this->path, $this->class, $this->currentMethod, ob_get_clean());
1275
				}
1276

                    
1277
				if ($this->score->failExists($exception) === false)
1278
				{
1279
					$this->addExceptionToScore($exception);
1280
				}
1281
			}
1282
			catch (test\exceptions\runtime $exception)
1283
			{
1284
				$this->score->addRuntimeException($this->path, $this->class, $this->currentMethod, $exception);
1285
			}
1286
			catch (test\exceptions\skip $exception)
1287
			{
1288
				list($file, $line) = $this->getBacktrace($exception->getTrace());
1289

                    
1290
				$this->score->addSkippedMethod($file, $this->class, $this->currentMethod, $line, $exception->getMessage());
1291
			}
1292
			catch (test\exceptions\stop $exception)
1293
			{
1294
			}
1295
			catch (exception $exception)
1296
			{
1297
				list($file, $line) = $this->getBacktrace($exception->getTrace());
1298

                    
1299
				$this->errorHandler(E_USER_ERROR, $exception->getMessage(), $file, $line);
1300
			}
1301
			catch (\exception $exception)
1302
			{
1303
				$this->addExceptionToScore($exception);
1304
			}
1305

                    
1306
			$this->afterTestMethod($this->currentMethod);
1307

                    
1308
			$this->currentMethod = null;
1309

                    
1310
			restore_error_handler();
1311

                    
1312
			ini_restore('display_errors');
1313
			ini_restore('log_errors');
1314
			ini_restore('log_errors_max_len');
1315

                    
1316
			$this->mockAutoloader->unregister();
1317
		}
1318

                    
1319
		return $this;
1320
	}
1321

                    
1322
	public function run(array $runTestMethods = array(), array $tags = array())
1323
	{
1324
		if ($runTestMethods)
1325
		{
1326
			$this->runTestMethods(array_intersect($runTestMethods, $this->getTestMethods($tags)));
1327
		}
1328

                    
1329
		if ($this->isIgnored() === false)
1330
		{
1331
			$this->callObservers(self::runStart);
1332

                    
1333
			try
1334
			{
1335
				$this->runEngines();
1336
			}
1337
			catch (\exception $exception)
1338
			{
1339
				$this->stopEngines();
1340

                    
1341
				throw $exception;
1342
			}
1343

                    
1344
			$this->callObservers(self::runStop);
1345
		}
1346

                    
1347
		return $this;
1348
	}
1349

                    
1350
	public function startCase($case)100%
1351
	{
1352
		$this->testAdapterStorage->resetCalls();
1353
		$this->score->setCase($case);
1354

                    
1355
		return $this;
1356
	}
1357

                    
1358
	public function stopCase()100%
1359
	{
1360
		$this->testAdapterStorage->resetCalls();
1361
		$this->score->unsetCase();
1362

                    
1363
		return $this;
1364
	}
1365

                    
1366
	public function setDataProvider($testMethodName, $dataProvider = null)80%
1367
	{
1368
		if ($dataProvider === null)
1369
		{
1370
			$dataProvider = $testMethodName . 'DataProvider';
1371
		}
1372

                    
1373
		if (method_exists($this->checkMethod($testMethodName), $dataProvider) === false)
1374
		{
1375
			throw new exceptions\logic\invalidArgument('Data provider ' . $this->class . '::' . lcfirst($dataProvider) . '() is unknown');
1376
		}
1377

                    
1378
		$this->dataProviders[$testMethodName] = $dataProvider;
1379

                    
1380
		return $this;
1381
	}
1382

                    
1383
	public function errorHandler($errno, $errstr, $errfile, $errline)100%
1384
	{
1385
		$doNotCallDefaultErrorHandler = true;
1386
		$errorReporting = $this->adapter->error_reporting();
1387

                    
1388
		if ($errorReporting !== 0 && $errorReporting & $errno)
1389
		{
1390
			list($file, $line) = $this->getBacktrace();
1391

                    
1392
			$this->score->addError($file ?: ($errfile ?: $this->path), $this->class, $this->currentMethod, $line ?: $errline, $errno, trim($errstr), $errfile, $errline);
1393

                    
1394
			$doNotCallDefaultErrorHandler = !($errno & E_RECOVERABLE_ERROR);
1395
		}
1396

                    
1397
		return $doNotCallDefaultErrorHandler;
1398
	}
1399

                    
1400
	public function setUp() {}
1401

                    
1402
	public function beforeTestMethod($testMethod) {}
1403

                    
1404
	public function afterTestMethod($testMethod) {}
1405

                    
1406
	public function tearDown() {}
1407

                    
1408
	public static function setNamespace($namespace)83%
1409
	{
1410
		$namespace = self::cleanNamespace($namespace);
1411

                    
1412
		if ($namespace === '')
1413
		{
1414
			throw new exceptions\logic\invalidArgument('Namespace must not be empty');
1415
		}
1416

                    
1417
		self::$namespace = $namespace;
1418
	}
1419

                    
1420
	public static function getNamespace()100%
1421
	{
1422
		return self::$namespace ?: static::defaultNamespace;
1423
	}
1424

                    
1425
	public static function setMethodPrefix($methodPrefix)0%
1426
	{
1427
		if ($methodPrefix == '')
1428
		{
1429
			throw new exceptions\logic\invalidArgument('Method prefix must not be empty');
1430
		}
1431

                    
1432
		self::$methodPrefix = $methodPrefix;
1433
	}
1434

                    
1435
	public static function getMethodPrefix()100%
1436
	{
1437
		return self::$methodPrefix ?: static::defaultMethodPrefix;
1438
	}
1439

                    
1440
	public static function setDefaultEngine($defaultEngine)0%
1441
	{
1442
		self::$defaultEngine = (string) $defaultEngine;
1443
	}
1444

                    
1445
	public static function getDefaultEngine()100%
1446
	{
1447
		return self::$defaultEngine ?: self::defaultEngine;
1448
	}
1449

                    
1450
	public static function getTestedClassNameFromTestClass($fullyQualifiedClassName, $testNamespace = null)100%
1451
	{
1452
		if ($testNamespace === null)
1453
		{
1454
			$testNamespace = self::getNamespace();
1455
		}
1456

                    
1457
		if (self::isRegex($testNamespace) === true)
1458
		{
1459
			if (preg_match($testNamespace, $fullyQualifiedClassName) === 0)
1460
			{
1461
				throw new exceptions\runtime('Test class \'' . $fullyQualifiedClassName . '\' is not in a namespace which match pattern \'' . $testNamespace . '\'');
1462
			}
1463

                    
1464
			$testedClassName = preg_replace($testNamespace, '\\', $fullyQualifiedClassName);
1465
		}
1466
		else
1467
		{
1468
			$position = strpos($fullyQualifiedClassName, $testNamespace);
1469

                    
1470
			if ($position === false)
1471
			{
1472
				throw new exceptions\runtime('Test class \'' . $fullyQualifiedClassName . '\' is not in a namespace which contains \'' . $testNamespace . '\'');
1473
			}
1474

                    
1475
			$testedClassName = substr($fullyQualifiedClassName, 0, $position) . substr($fullyQualifiedClassName, $position + 1 + strlen($testNamespace));
1476
		}
1477

                    
1478
		return trim($testedClassName, '\\');
1479
	}
1480

                    
1481
	protected function setClassAnnotations(annotations\extractor $extractor)38%
1482
	{
1483
		$test = $this;
1484

                    
1485
		$extractor
1486
			->resetHandlers()
1487
			->setHandler('ignore', function($value) use ($test) { $test->ignore(annotations\extractor::toBoolean($value)); })
1488
			->setHandler('tags', function($value) use ($test) { $test->setTags(annotations\extractor::toArray($value)); })
1489
			->setHandler('namespace', function($value) use ($test) { $test->setTestNamespace($value === true ? static::defaultNamespace : $value); })
1490
			->setHandler('methodPrefix', function($value) use ($test) { $test->setTestMethodPrefix($value === true ? static::defaultMethodPrefix : $value); })
1491
			->setHandler('maxChildrenNumber', function($value) use ($test) { $test->setMaxChildrenNumber($value); })
1492
			->setHandler('engine', function($value) use ($test) { $test->setClassEngine($value); })
1493
			->setHandler('hasVoidMethods', function($value) use ($test) { $test->classHasVoidMethods(); })
1494
			->setHandler('hasNotVoidMethods', function($value) use ($test) { $test->classHasNotVoidMethods(); })
1495
			->setHandler('php', function($value) use ($test) {
1496
					$value = annotations\extractor::toArray($value);
1497

                    
1498
					if (isset($value[0]) === true)
1499
					{
1500
						$operator = null;
1501

                    
1502
						if (isset($value[1]) === false)
1503
						{
1504
							$version = $value[0];
1505
						}
1506
						else
1507
						{
1508
							$version = $value[1];
1509

                    
1510
							switch ($value[0])
1511
							{
1512
								case '<':
1513
								case '<=':
1514
								case '=':
1515
								case '==':
1516
								case '>=':
1517
								case '>':
1518
									$operator = $value[0];
1519
							}
1520
						}
1521

                    
1522
						$test->addClassPhpVersion($version, $operator);
1523
					}
1524
				}
1525
			)
1526
			->setHandler('extensions', function($value) use ($test) {
1527
					foreach (annotations\extractor::toArray($value) as $mandatoryExtension)
1528
					{
1529
						$test->addMandatoryClassExtension($mandatoryExtension);
1530
					}
1531
				}
1532
			)
1533
		;
1534

                    
1535
		return $this;
1536
	}
1537

                    
1538
	protected function setMethodAnnotations(annotations\extractor $extractor, & $methodName)47%
1539
	{
1540
		$test = $this;
1541

                    
1542
		$extractor
1543
			->resetHandlers()
1544
			->setHandler('ignore', function($value) use ($test, & $methodName) { $test->ignoreMethod($methodName, annotations\extractor::toBoolean($value)); })
1545
			->setHandler('tags', function($value) use ($test, & $methodName) { $test->setMethodTags($methodName, annotations\extractor::toArray($value)); })
1546
			->setHandler('dataProvider', function($value) use ($test, & $methodName) { $test->setDataProvider($methodName, $value === true ? null : $value); })
1547
			->setHandler('engine', function($value) use ($test, & $methodName) { $test->setMethodEngine($methodName, $value); })
1548
			->setHandler('isVoid', function($value) use ($test, & $methodName) { $test->setMethodVoid($methodName); })
1549
			->setHandler('isNotVoid', function($value) use ($test, & $methodName) { $test->setMethodNotVoid($methodName); })
1550
			->setHandler('php', function($value) use ($test, & $methodName) {
1551
					$value = annotations\extractor::toArray($value);
1552

                    
1553
					if (isset($value[0]) === true)
1554
					{
1555
						$operator = null;
1556

                    
1557
						if (isset($value[1]) === false)
1558
						{
1559
							$version = $value[0];
1560
						}
1561
						else
1562
						{
1563
							$version = $value[1];
1564

                    
1565
							switch ($value[0])
1566
							{
1567
								case '<':
1568
								case '<=':
1569
								case '=':
1570
								case '==':
1571
								case '>=':
1572
								case '>':
1573
									$operator = $value[0];
1574
							}
1575
						}
1576

                    
1577
						$test->addMethodPhpVersion($methodName, $version, $operator);
1578
					}
1579
				}
1580
			)
1581
			->setHandler('extensions', function($value) use ($test, & $methodName) {
1582
					foreach (annotations\extractor::toArray($value) as $mandatoryExtension)
1583
					{
1584
						$test->addMandatoryMethodExtension($methodName, $mandatoryExtension);
1585
					}
1586
				}
1587
			)
1588
		;
1589

                    
1590
		return $this;
1591
	}
1592

                    
1593
	protected function getBacktrace(array $trace = null)46%
1594
	{
1595
		$debugBacktrace = $trace === null ? debug_backtrace(false) : $trace;
1596

                    
1597
		foreach ($debugBacktrace as $key => $value)
1598
		{
1599
			if (isset($value['class']) === true && $value['class'] === $this->class && isset($value['function']) === true && $value['function'] === $this->currentMethod)
1600
			{
1601
				if (isset($debugBacktrace[$key - 1]) === true)
1602
				{
1603
					$key -= 1;
1604
				}
1605

                    
1606
				return array(
1607
					$debugBacktrace[$key]['file'],
1608
					$debugBacktrace[$key]['line']
1609
				);
1610
			}
1611
		}
1612

                    
1613
		return null;
1614
	}
1615

                    
1616
	private function checkMethod($methodName)100%
1617
	{
1618
		if (isset($this->testMethods[$methodName]) === false)
1619
		{
1620
			throw new exceptions\logic\invalidArgument('Test method ' . $this->class . '::' . $methodName . '() does not exist');
1621
		}
1622

                    
1623
		return $this;
1624
	}
1625

                    
1626
	private function addExceptionToScore(\exception $exception)0%
1627
	{
1628
		list($file, $line) = $this->getBacktrace($exception->getTrace());
1629

                    
1630
		$this->score->addException($file, $this->class, $this->currentMethod, $line, $exception);
1631

                    
1632
		return $this;
1633
	}
1634

                    
1635
	private function runEngines()2%
1636
	{
1637
		$this->callObservers(self::beforeSetUp);
1638
		$this->setUp();
1639
		$this->callObservers(self::afterSetUp);
1640

                    
1641
		while ($this->runEngine()->engines)
1642
		{
1643
			$engines = $this->engines;
1644

                    
1645
			foreach ($engines as $this->currentMethod => $engine)
1646
			{
1647
				$score = $engine->getScore();
1648

                    
1649
				if ($score !== null)
1650
				{
1651
					unset($this->engines[$this->currentMethod]);
1652

                    
1653
					$this
1654
						->callObservers(self::afterTestMethod)
1655
						->score
1656
							->merge($score)
1657
					;
1658

                    
1659
					$runtimeExceptions = $score->getRuntimeExceptions();
1660

                    
1661
					if (sizeof($runtimeExceptions) > 0)
1662
					{
1663
						$this->callObservers(self::runtimeException);
1664

                    
1665
						throw reset($runtimeExceptions);
1666
					}
1667
					else
1668
					{
1669
						switch (true)
1670
						{
1671
							case $score->getVoidMethodNumber():
1672
								$signal = self::void;
1673
								break;
1674

                    
1675
							case $score->getUncompletedMethodNumber():
1676
								$signal = self::uncompleted;
1677
								break;
1678

                    
1679
							case $score->getSkippedMethodNumber():
1680
								$signal = self::skipped;
1681
								break;
1682

                    
1683
							case $score->getFailNumber():
1684
								$signal = self::fail;
1685
								break;
1686

                    
1687
							case $score->getErrorNumber():
1688
								$signal = self::error;
1689
								break;
1690

                    
1691
							case $score->getExceptionNumber():
1692
								$signal = self::exception;
1693
								break;
1694

                    
1695
							default:
1696
								$signal = self::success;
1697
						}
1698

                    
1699
						$this->callObservers($signal);
1700
					}
1701

                    
1702
					if ($engine->isAsynchronous() === true)
1703
					{
1704
						$this->asynchronousEngines--;
1705
					}
1706
				}
1707
			}
1708

                    
1709
			$this->currentMethod = null;
1710
		}
1711

                    
1712
		return $this->doTearDown();
1713
	}
1714

                    
1715
	private function stopEngines()0%
1716
	{
1717
		while ($this->engines)
1718
		{
1719
			$engines = $this->engines;
1720

                    
1721
			foreach ($engines as $currentMethod => $engine)
1722
			{
1723
				if ($engine->getScore() !== null)
1724
				{
1725
					unset($this->engines[$currentMethod]);
1726
				}
1727
			}
1728
		}
1729

                    
1730
		return $this->doTearDown();
1731
	}
1732

                    
1733
	private function runEngine()0%
1734
	{
1735
		$engine = reset($this->runTestMethods);
1736

                    
1737
		if ($engine !== false)
1738
		{
1739
			$this->currentMethod = key($this->runTestMethods);
1740

                    
1741
			if ($this->canRunEngine($engine) === true)
1742
			{
1743
				unset($this->runTestMethods[$this->currentMethod]);
1744

                    
1745
				$this->engines[$this->currentMethod] = $engine->run($this->callObservers(self::beforeTestMethod));
1746

                    
1747
				if ($engine->isAsynchronous() === true)
1748
				{
1749
					$this->asynchronousEngines++;
1750
				}
1751
			}
1752

                    
1753
			$this->currentMethod = null;
1754
		}
1755

                    
1756
		return $this;
1757
	}
1758

                    
1759
	private function canRunEngine(test\engine $engine)0%
1760
	{
1761
		return ($engine->isAsynchronous() === false || $this->maxAsynchronousEngines === null || $this->asynchronousEngines < $this->maxAsynchronousEngines);
1762
	}
1763

                    
1764
	private function doTearDown()0%
1765
	{
1766
		$this->callObservers(self::beforeTearDown);
1767
		$this->tearDown();
1768
		$this->callObservers(self::afterTearDown);
1769

                    
1770
		return $this;
1771
	}
1772

                    
1773
	public function getExtensions()100%
1774
	{
1775
		return iterator_to_array($this->extensions);
1776
	}
1777

                    
1778
	public function removeExtension(atoum\extension $extension)100%
1779
	{
1780
		$this->extensions->detach($extension);
1781

                    
1782
		return $this->removeObserver($extension);;
1783
	}
1784

                    
1785
	public function removeExtensions()100%
1786
	{
1787
		foreach ($this->extensions as $extension)
1788
		{
1789
			$this->removeObserver($extension);
1790
		}
1791

                    
1792
		$this->extensions = new \splObjectStorage();
1793

                    
1794
		return $this;
1795
	}
1796

                    
1797

                    
1798
	public function addExtension(atoum\extension $extension)100%
1799
	{
1800
		if ($this->extensions->contains($extension) === false)
1801
		{
1802
			$extension->setTest($this);
1803

                    
1804
			$this->extensions->attach($extension);
1805

                    
1806
			$this->addObserver($extension);
1807
		}
1808

                    
1809
		return $this;
1810
	}
1811

                    
1812
	public function addExtensions(\traversable $extensions)0%
1813
	{
1814
		foreach ($extensions as $extension)
1815
		{
1816
			$this->addExtension($extension);
1817
		}
1818

                    
1819
		return $this;
1820
	}
1821

                    
1822
	private static function cleanNamespace($namespace)100%
1823
	{
1824
		return trim((string) $namespace, '\\');
1825
	}
1826

                    
1827
	private static function isRegex($namespace)100%
1828
	{
1829
		return preg_match('/^([^\\\[:alnum:][:space:]]).*\1.*$/', $namespace) === 1;
1830
	}
1831
}