diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 3b3eec7..96b2e9f 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -23,19 +23,18 @@ jobs: strategy: matrix: - php-version: [ "7.2", "7.3", "7.4", "8.0", "8.1" ] + php-version: [ "8.1", "8.2", "8.3" ] operating-system: [ "ubuntu-latest" ] composer-args: [ "" ] include: - - php-version: "7.2" + - php-version: "8.1" operating-system: "ubuntu-latest" composer-args: "--prefer-lowest" - - php-version: "8.0" + - php-version: "8.3" operating-system: "ubuntu-latest" composer-args: "" fail-fast: false - steps: - name: "Checkout" uses: "actions/checkout@v2" diff --git a/composer.json b/composer.json index e203efc..8981240 100644 --- a/composer.json +++ b/composer.json @@ -3,17 +3,19 @@ "type": "library", "license": "MIT", "require": { - "php": ">=7.1", - "nette/di": "^2.4.17 || ~3.0", - "nette/tester": "^2.3.1" + "php": ">=8.1", + "nette/bootstrap": "^3.2", + "nette/di": "~3.2", + "nette/tester": "^2.3.1", + "nette/utils": "^4.0" }, "require-dev": { "mockery/mockery": "^1.0", - "nette/bootstrap": "^3.0", - "nette/utils": "^3.0", - "ninjify/qa": "^0.13", + "contributte/qa": "^0.3", "phpstan/phpstan": "^1.0", - "tracy/tracy": "~2.6" + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "~2.10" }, "autoload": { "classmap": [ @@ -24,5 +26,10 @@ "classmap": [ "tests/src" ] + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } } } diff --git a/phpstan.neon b/phpstan.neon index 505b2cc..0ce0e4a 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,26 +1,18 @@ +includes: + - vendor/phpstan/phpstan-deprecation-rules/rules.neon + - vendor/phpstan/phpstan-nette/extension.neon + - vendor/phpstan/phpstan-nette/rules.neon + parameters: + level: 8 + treatPhpDocTypesAsCertain: false ignoreErrors: - - - message: "#^Call to an undefined method Nette\\\\DI\\\\Container\\:\\:initialize\\(\\)\\.$#" - count: 1 - path: src/InfrastructureConfigurator.php - - - - message: "#^Call to an undefined static method Nette\\\\DI\\\\Helpers\\:\\:autowireArguments\\(\\)\\.$#" - count: 1 - path: src/MethodArgumentsResolver.php - - message: "#^Call to function method_exists\\(\\) with 'Nette\\\\\\\\DI\\\\\\\\Helpers' and 'autowireArguments' will always evaluate to false\\.$#" count: 1 path: src/MethodArgumentsResolver.php - - - message: "#^Parameter \\#3 \\$getter of static method Nette\\\\DI\\\\Resolver\\:\\:autowireArguments\\(\\) expects callable\\(string, bool\\)\\: array\\\\|object\\|null, Nette\\\\DI\\\\Container given\\.$#" - count: 1 - path: src/MethodArgumentsResolver.php - - message: "#^Call to an undefined method Nette\\\\DI\\\\Container\\:\\:setAppContainer\\(\\)\\.$#" count: 1 diff --git a/ruleset.xml b/ruleset.xml index 58f7f4e..927da56 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -1,7 +1,7 @@ - + @@ -13,7 +13,10 @@ "/> - + + + + diff --git a/src/Bridges/Mockery/MockeryContainerHook.php b/src/Bridges/Mockery/MockeryContainerHook.php index 23763be..a7f7a84 100644 --- a/src/Bridges/Mockery/MockeryContainerHook.php +++ b/src/Bridges/Mockery/MockeryContainerHook.php @@ -14,8 +14,7 @@ class MockeryContainerHook extends AppContainerHook { - /** @var TestContext */ - private $testContext; + private TestContext $testContext; public function __construct(TestContext $testContext) { diff --git a/src/Container/AppContainerFactory.php b/src/Container/AppContainerFactory.php index 2a301a3..253f12a 100644 --- a/src/Container/AppContainerFactory.php +++ b/src/Container/AppContainerFactory.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure\Container; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Compiler; use Nette\DI\Container; use Nette\DI\ContainerBuilder; @@ -11,8 +11,7 @@ class AppContainerFactory { - /** @var IAppConfiguratorFactory */ - private $appConfiguratorFactory; + private IAppConfiguratorFactory $appConfiguratorFactory; public function __construct(IAppConfiguratorFactory $appConfiguratorFactory) { @@ -45,7 +44,7 @@ protected function setupConfigurator(Container $testContainer, Configurator $app $compiler->addExtension('mango.tester.beforeCompile', $compilerExtension); }; - $appConfigurator->addParameters([ + $appConfigurator->addStaticParameters([ 'hookHash' => $hook->getHash(), 'testContainerParameters' => $testContainer->getParameters(), ]); diff --git a/src/Container/AppContainerHook.php b/src/Container/AppContainerHook.php index 76c6fd9..57a160b 100644 --- a/src/Container/AppContainerHook.php +++ b/src/Container/AppContainerHook.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure\Container; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Container; use Nette\DI\ContainerBuilder; diff --git a/src/Container/AppContainerHookList.php b/src/Container/AppContainerHookList.php index bcb18c4..356f99c 100644 --- a/src/Container/AppContainerHookList.php +++ b/src/Container/AppContainerHookList.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure\Container; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Container; use Nette\DI\ContainerBuilder; @@ -10,7 +10,7 @@ class AppContainerHookList implements IAppContainerHook { /** @var IAppContainerHook[] */ - private $hooks; + private array $hooks; /** * @param IAppContainerHook[] $hooks @@ -23,9 +23,7 @@ public function __construct(array $hooks) public function getHash(): string { return md5(serialize(array_map( - static function (IAppContainerHook $hook): string { - return $hook->getHash(); - }, + static fn (IAppContainerHook $hook): string => $hook->getHash(), $this->hooks ))); } diff --git a/src/Container/CompilerHookExtension.php b/src/Container/CompilerHookExtension.php index 5559169..04a6ade 100644 --- a/src/Container/CompilerHookExtension.php +++ b/src/Container/CompilerHookExtension.php @@ -8,9 +8,9 @@ class CompilerHookExtension extends CompilerExtension { /** @var callable[] */ - public $onBeforeCompile = []; + public array $onBeforeCompile = []; - public function beforeCompile() + public function beforeCompile(): void { foreach ($this->onBeforeCompile as $fn) { call_user_func($fn, $this->getContainerBuilder()); diff --git a/src/Container/ConfigAppContainerHook.php b/src/Container/ConfigAppContainerHook.php index fc674ec..81faea9 100644 --- a/src/Container/ConfigAppContainerHook.php +++ b/src/Container/ConfigAppContainerHook.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure\Container; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Container; use Nette\DI\ContainerBuilder; @@ -10,12 +10,12 @@ class ConfigAppContainerHook implements IAppContainerHook { /** @var array|string */ - private $config; + private array|string $config; /** * @param array|string $config */ - public function __construct($config) + public function __construct(array|string $config) { $this->config = $config; } diff --git a/src/Container/IAppConfiguratorFactory.php b/src/Container/IAppConfiguratorFactory.php index 36f17cc..4f84140 100644 --- a/src/Container/IAppConfiguratorFactory.php +++ b/src/Container/IAppConfiguratorFactory.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure\Container; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Container; interface IAppConfiguratorFactory diff --git a/src/Container/IAppContainerHook.php b/src/Container/IAppContainerHook.php index 62f4962..c40ead4 100644 --- a/src/Container/IAppContainerHook.php +++ b/src/Container/IAppContainerHook.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure\Container; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Container; use Nette\DI\ContainerBuilder; diff --git a/src/DefaultAppConfiguratorFactory.php b/src/DefaultAppConfiguratorFactory.php index 4267e09..7905229 100644 --- a/src/DefaultAppConfiguratorFactory.php +++ b/src/DefaultAppConfiguratorFactory.php @@ -2,7 +2,7 @@ namespace Webnazakazku\MangoTester\Infrastructure; -use Nette\Configurator; +use Nette\Bootstrap\Configurator; use Nette\DI\Container; use Nette\DI\Extensions\ExtensionsExtension; use Webnazakazku\MangoTester\Infrastructure\Container\IAppConfiguratorFactory; @@ -19,13 +19,12 @@ class DefaultAppConfiguratorFactory implements IAppConfiguratorFactory ]; /** @var string[] */ - private $configFiles; + private array $configFiles; /** @var string[] */ - private $copiedParameters; + private array $copiedParameters; - /** @var bool */ - private $defaultExtensionsOverride = true; + private bool $defaultExtensionsOverride = true; /** * @param string[] $configFiles @@ -58,7 +57,7 @@ public function create(Container $testContainer): Configurator $parameters = array_intersect_key($params, array_fill_keys($this->copiedParameters, true)); - $configurator->addParameters($parameters); + $configurator->addStaticParameters($parameters); foreach ($this->configFiles as $file) { $configurator->addConfig($file); } diff --git a/src/InfrastructureConfigurator.php b/src/InfrastructureConfigurator.php index 52197a7..5064574 100644 --- a/src/InfrastructureConfigurator.php +++ b/src/InfrastructureConfigurator.php @@ -3,8 +3,13 @@ namespace Webnazakazku\MangoTester\Infrastructure; use Closure; -use Nette; -use Nette\DI; +use Nette\DI\Compiler; +use Nette\DI\Config\Loader; +use Nette\DI\Container; +use Nette\DI\ContainerLoader; +use Nette\DI\Extensions\ExtensionsExtension; +use Nette\Schema\Helpers; +use Nette\Utils\FileSystem; use Tester\Dumper; use Tester\Environment; @@ -12,10 +17,10 @@ class InfrastructureConfigurator { /** @var mixed[] */ - protected $parameters; + protected array $parameters; /** @var array */ - protected $configs = []; + protected array $configs = []; public function __construct(string $path) { @@ -46,7 +51,7 @@ public function setTimeZone(string $timezone): void */ public function addParameters(array $params): void { - $parameters = DI\Config\Helpers::merge($params, $this->parameters); + $parameters = Helpers::merge($params, $this->parameters); assert(is_array($parameters)); $this->parameters = $parameters; @@ -55,7 +60,7 @@ public function addParameters(array $params): void /** * @param mixed[]|string $config file or configuration itself */ - public function addConfig($config): void + public function addConfig(array|string $config): void { assert(is_string($config) || is_array($config)); $this->configs[] = $config; @@ -63,9 +68,9 @@ public function addConfig($config): void public function getContainerFactory(): Closure { - return function (): DI\Container { + return function (): Container { $class = $this->loadContainer(); - /** @var DI\Container $container */ + /** @var Container $container */ $container = new $class([]); $container->initialize(); @@ -78,23 +83,22 @@ public function getContainerFactory(): Closure */ protected function loadContainer(): string { - $loader = new DI\ContainerLoader( + $loader = new ContainerLoader( $this->getCacheDirectory() . '/Mango.Tester.Infrastructure', $this->parameters['debugMode'] ); + return $loader->load( - function (DI\Compiler $compiler) { - return $this->generateContainer($compiler); - }, + fn (Compiler $compiler) => $this->generateContainer($compiler), [$this->parameters, $this->configs, PHP_VERSION_ID - PHP_RELEASE_VERSION] ); } - protected function generateContainer(DI\Compiler $compiler): string + protected function generateContainer(Compiler $compiler): string { $compiler->addConfig(['parameters' => $this->parameters]); - $loader = new DI\Config\Loader(); + $loader = new Loader(); $fileInfo = []; foreach ($this->configs as $config) { if (is_string($config)) { @@ -107,17 +111,19 @@ protected function generateContainer(DI\Compiler $compiler): string $compiler->addDependencies($loader->getDependencies()); - $compiler->addExtension('extensions', new DI\Extensions\ExtensionsExtension()); + $compiler->addExtension('extensions', new ExtensionsExtension()); $compiler->addExtension('mango.tester', new MangoTesterExtension()); $classes = $compiler->compile(); + return implode("\n", $fileInfo) . "\n\n" . $classes; } protected function getCacheDirectory(): string { $dir = $this->parameters['tempDir'] . '/cache'; - Nette\Utils\FileSystem::createDir($dir); + FileSystem::createDir($dir); + return $dir; } diff --git a/src/MangoTesterExtension.php b/src/MangoTesterExtension.php index 8e24455..c70a39e 100644 --- a/src/MangoTesterExtension.php +++ b/src/MangoTesterExtension.php @@ -3,40 +3,46 @@ namespace Webnazakazku\MangoTester\Infrastructure; use Mockery; -use Nette; use Nette\DI\CompilerExtension; use Nette\DI\Container; +use Nette\DI\Definitions\ImportedDefinition; use Nette\DI\Definitions\ServiceDefinition; -use Nette\DI\Statement; +use Nette\DI\Definitions\Statement; +use Nette\PhpGenerator\ClassType; +use Nette\Schema\Expect; +use Nette\Schema\Schema; use Webnazakazku\MangoTester\Infrastructure\Bridges\Mockery\MockeryContainerHook; use Webnazakazku\MangoTester\Infrastructure\Container\AppContainerFactory; +/** + * @property mixed $config + */ class MangoTesterExtension extends CompilerExtension { public const TAG_REQUIRE = 'mango.tester.require'; public const TAG_HOOK = 'mango.tester.hook'; - /** @var mixed[] */ - public $defaults = [ - 'hooks' => [], - 'require' => [], - 'appContainer' => [], - 'mockery' => false, - ]; - - public function __construct() + public function getConfigSchema(): Schema { - $this->defaults['mockery'] = class_exists(Mockery::class); + return Expect::structure([ + 'hooks' => Expect::array(), + 'require' => Expect::array(), + 'appContainer' => Expect::array(), + 'mockery' => Expect::bool()->castTo('bool'), + ]); } - public function loadConfiguration() + public function loadConfiguration(): void { - $config = $this->validateConfig($this->defaults); + /** @var mixed $config */ + $config = $this->config; + + $config->mockery = class_exists(Mockery::class); - $this->registerRequiredServices($config['require']); - $this->registerHooks($config['hooks']); - $this->registerAppConfiguratorFactory($config['appContainer']); + $this->registerRequiredServices($config->require); + $this->registerHooks($config->hooks); + $this->registerAppConfiguratorFactory($config->appContainer); $builder = $this->getContainerBuilder(); @@ -44,21 +50,21 @@ public function loadConfiguration() ->setAutowired(false); $builder->addDefinition($this->prefix('containerFactory')) - ->setClass(AppContainerFactory::class); + ->setType(AppContainerFactory::class); $builder->addDefinition($this->prefix('methodArgumentResolver')) - ->setClass(MethodArgumentsResolver::class); + ->setType(MethodArgumentsResolver::class); $this->addDynamic($this->prefix('testContext'), TestContext::class); - if ($config['mockery'] !== false) { + if ($config->mockery !== false) { $builder->addDefinition($this->prefix('mockeryContainerHook')) - ->setClass(MockeryContainerHook::class) + ->setType(MockeryContainerHook::class) ->addTag(self::TAG_HOOK); } } - public function beforeCompile() + public function beforeCompile(): void { $builder = $this->getContainerBuilder(); @@ -70,7 +76,7 @@ public function beforeCompile() } elseif (is_string($attrs)) { $def->setFactory(new Statement([$this->prefix('@appContainer'), 'getByType'], [$attrs])); } else { - $type = $def->getClass(); + $type = $def->getType(); $def->setFactory(new Statement([$this->prefix('@appContainer'), 'getByType'], [$type])); } } @@ -87,7 +93,7 @@ protected function registerHooks(array $hooks): void $name = $i++ . preg_replace('#\W+#', '_', $hookClass); $builder->addDefinition($this->prefix($name)) - ->setClass($hookClass) + ->setType($hookClass) ->addTag(self::TAG_HOOK); } } @@ -108,7 +114,7 @@ private function requireService(string $class): void /** @var string $name */ $name = preg_replace('#\W+#', '_', $class); $builder->addDefinition($this->prefix($name)) - ->setClass($class) + ->setType($class) ->addTag(self::TAG_REQUIRE); } @@ -132,27 +138,21 @@ private function registerAppConfiguratorFactory(array $config): void } } - public function afterCompile(Nette\PhpGenerator\ClassType $class) + public function afterCompile(ClassType $class): void { parent::afterCompile($class); + $class->addMethod('setAppContainer') ->setBody('$this->addService(?, $container);', [$this->prefix('appContainer')]) ->addParameter('container'); } - /** - * @return Nette\DI\Definitions\ImportedDefinition|Nette\DI\ServiceDefinition - */ - private function addDynamic(string $name, string $className) + private function addDynamic(string $name, string $className): ImportedDefinition { $builder = $this->getContainerBuilder(); - if (class_exists(Nette\DI\Definitions\ImportedDefinition::class)) { - return $builder->addImportedDefinition($name)->setType($className); - } - $def = $builder->addDefinition($name); - $def->setClass($className); - $def->setDynamic(); + $def = $builder->addImportedDefinition($name); + $def->setType($className); return $def; } diff --git a/src/MethodArgumentsResolver.php b/src/MethodArgumentsResolver.php index aabe89c..8f2ac65 100644 --- a/src/MethodArgumentsResolver.php +++ b/src/MethodArgumentsResolver.php @@ -17,7 +17,7 @@ class MethodArgumentsResolver * @param array $args * @return array */ - public function resolve(ReflectionMethod $method, Container $appContainer, array $args) + public function resolve(ReflectionMethod $method, Container $appContainer, array $args): array { $fixedArgs = $this->prepareArguments($method, $appContainer); @@ -29,6 +29,7 @@ public function resolve(ReflectionMethod $method, Container $appContainer, array $params = $ref->getMethod('autowireArguments')->getParameters(); if ($params[2]->name === 'resolver') { + /** @phpstan-var mixed $appContainer */ return Resolver::autowireArguments($method, $args + $fixedArgs, $appContainer); } elseif ($params[2]->name === 'getter') { $getter = function (string $type, bool $single) use ($appContainer) { diff --git a/src/TestCase.php b/src/TestCase.php index 0172913..de9baee 100644 --- a/src/TestCase.php +++ b/src/TestCase.php @@ -16,17 +16,14 @@ class TestCase { - /** @var bool */ - private $handleErrors = false; + private bool $handleErrors = false; /** @var callable|FALSE|NULL */ private $prevErrorHandler = false; - /** @var Container */ - private $testContainer; + private Container $testContainer; - /** @var Container */ - private $applicationContainer; + private Container $applicationContainer; public static function run(callable $testContainerFactory): void { @@ -36,9 +33,8 @@ public static function run(callable $testContainerFactory): void /** * @param mixed[] $args - * @return mixed */ - public static function runMethod(callable $testContainerFactory, string $method, array $args) + public static function runMethod(callable $testContainerFactory, string $method, array $args): mixed { $testContainer = $testContainerFactory(); assert($testContainer instanceof Container); @@ -127,9 +123,8 @@ protected function executeTearDownListeners(): void /** * @param mixed[] $args - * @return mixed */ - protected function execute(ReflectionMethod $method, array $args) + protected function execute(ReflectionMethod $method, array $args): mixed { if ($this->prevErrorHandler === false) { $this->prevErrorHandler = set_error_handler(function ($severity) { @@ -154,6 +149,7 @@ protected function execute(ReflectionMethod $method, array $args) } catch (Throwable $e) { $this->handleErrors = false; $this->silentTearDown(); + throw $e; } @@ -174,9 +170,7 @@ protected function execute(ReflectionMethod $method, array $args) private function silentTearDown(): void { - set_error_handler(function (): bool { - return true; - }); + set_error_handler(fn (): bool => true); try { $this->tearDown(); } catch (Throwable $e) { // phpcs:ignore @@ -187,9 +181,8 @@ private function silentTearDown(): void /** * @param mixed[] $args - * @return mixed */ - protected function invoke(ReflectionMethod $method, array $args) + protected function invoke(ReflectionMethod $method, array $args): mixed { if (count($method->getParameters()) > 0) { $resolver = $this->testContainer->getByType(MethodArgumentsResolver::class); @@ -199,6 +192,7 @@ protected function invoke(ReflectionMethod $method, array $args) $callback = [$this, $method->getName()]; assert(is_callable($callback)); + return call_user_func_array($callback, $args); } diff --git a/src/TestCaseRunner.php b/src/TestCaseRunner.php index e2cc4db..98c1ba5 100644 --- a/src/TestCaseRunner.php +++ b/src/TestCaseRunner.php @@ -20,7 +20,7 @@ class TestCaseRunner private $testContainerFactory; /** @var class-string */ - private $testCaseClass; + private string $testCaseClass; /** * @param class-string $testCaseClass @@ -33,9 +33,7 @@ public function __construct(string $testCaseClass, callable $testContainerFactor public function run(): void { - $methods = preg_grep(self::METHOD_PATTERN, array_map(function (ReflectionMethod $rm) { - return $rm->getName(); - }, (new ReflectionClass($this->testCaseClass))->getMethods())); + $methods = preg_grep(self::METHOD_PATTERN, array_map(fn (ReflectionMethod $rm) => $rm->getName(), (new ReflectionClass($this->testCaseClass))->getMethods())); assert($methods !== false); $methods = array_values($methods); @@ -105,9 +103,8 @@ public function runMethod(string $method): void /** * @param mixed[] $args - * @return mixed */ - private function callTestMethod(string $method, array $args) + private function callTestMethod(string $method, array $args): mixed { return ($this->testCaseClass)::runMethod($this->testContainerFactory, $method, $args); } @@ -125,6 +122,7 @@ protected function getData(string $provider): iterable $fileName = $rc->getFileName(); assert($fileName !== false); [$file, $query] = DataProvider::parseAnnotation($provider, $fileName); + return DataProvider::load($file, $query); } diff --git a/src/TestContext.php b/src/TestContext.php index ef3240b..d24664f 100644 --- a/src/TestContext.php +++ b/src/TestContext.php @@ -6,10 +6,9 @@ class TestContext { /** @var class-string */ - private $testCaseClass; + private string $testCaseClass; - /** @var string */ - private $testMethod; + private string $testMethod; /** * @param class-string $testCaseClass diff --git a/tests/cases/TestRunTest.phpt b/tests/cases/TestRunTest.phpt index b4b0772..76b7912 100644 --- a/tests/cases/TestRunTest.phpt +++ b/tests/cases/TestRunTest.phpt @@ -14,7 +14,7 @@ require __DIR__ . '/../../vendor/autoload.php'; class TestRunTest extends TestCase { - public function testEcho(DateTimeImmutable $containerDependency) + public function testEcho(DateTimeImmutable $containerDependency): void { Assert::true(true); } diff --git a/tests/src/Bootstrap.php b/tests/src/Bootstrap.php index 009f666..6fc87a6 100644 --- a/tests/src/Bootstrap.php +++ b/tests/src/Bootstrap.php @@ -3,6 +3,7 @@ namespace Tests\Tester\Infrastructure; use Nette\Configurator; +use Nette\DI\Container; use Webnazakazku\MangoTester\Infrastructure\MangoTesterExtension; class Bootstrap @@ -10,7 +11,7 @@ class Bootstrap public const FACTORY = [self::class, 'createContainer']; - public static function createContainer() + public static function createContainer(): Container { $configurator = new Configurator(); $configurator->setTempDirectory(__DIR__ . '/../temp');