Пример #1
0
 /**
  * Sets up test case - initializes directory in %TEMP
  *
  */
 public function setUp()
 {
     $this->temp = $this->normalize(realpath(System::tempDir())) . md5(uniqid()) . '.xp' . DIRECTORY_SEPARATOR;
     if (is_dir($this->temp) && !rmdir($this->temp)) {
         throw new \unittest\PrerequisitesNotMetError('Fixture directory exists, but cannot remove', null, $this->temp);
     }
 }
 /**
  * Sets up test case
  */
 public function setUp()
 {
     $this->emitter = new V54Emitter();
     $this->files = new FileManager();
     $this->files->addSourcePath(dirname(__FILE__) . '/src');
     // FIXME: ClassPathManager?
     $this->files->setOutput(new \io\Folder(\lang\System::tempDir()));
 }
 public function setUp()
 {
     $tempDir = realpath(System::tempDir());
     $this->fixture = new FilesystemPropertySource($tempDir);
     // Create a temporary ini file
     $this->tempFile = new File($tempDir, 'temp.ini');
     FileUtil::setContents($this->tempFile, "[section]\nkey=value\n");
 }
Пример #4
0
 /**
  * Create XML from a DBTable
  *
  * @param   rdbms.DBTable table
  * @param   string dbhost
  * @param   string database
  * @return  rdbms.util.DBXmlGenerator object
  */
 public static function createFromTable(DBTable $table, $dbhost, $database)
 {
     $g = new self();
     $g->doc->root()->setAttribute('created_at', date('r'));
     $g->doc->root()->setAttribute('created_by', System::getProperty('user.name'));
     $g->doc->root()->addChild(new \xml\Node('table', null, ['name' => $table->name, 'dbhost' => $dbhost, 'database' => $database]));
     $g->table = $table;
     return $g;
 }
 /**
  * Create XML map
  *
  * @param   rdbms.DBAdapter and adapter
  * @param   string database
  * @return  rdbms.util.DBConstraintXmlGenerator object
  */
 public static function createFromDatabase($adapter, $database)
 {
     $g = new self();
     $g->doc->root()->setAttribute('created_at', date('r'));
     $g->doc->root()->setAttribute('created_by', System::getProperty('user.name'));
     $g->doc->root()->addChild(new \xml\Node('database', null, ['database' => $database]));
     $g->tables = DBTable::getByDatabase($adapter, $database);
     return $g;
 }
Пример #6
0
 public static function createFiles()
 {
     self::$temp = new Folder(System::tempDir(), uniqid(microtime(true)));
     self::$temp->create();
     $partials = new Folder(self::$temp, 'partials');
     $partials->create();
     FileUtil::setContents(new File(self::$temp, 'test.mustache'), 'Mustache template {{id}}');
     FileUtil::setContents(new File($partials, 'navigation.mustache'), '{{#if nav}}nav{{/if}}');
 }
 public static function verifyTempDir()
 {
     self::$temp = System::tempDir();
     if (!is_writeable(self::$temp)) {
         throw new \unittest\PrerequisitesNotMetError('$TEMP is not writeable', null, array(self::$temp . ' +w'));
     }
     if (($df = disk_free_space(self::$temp)) < 10240) {
         throw new \unittest\PrerequisitesNotMetError('Not enough space available in $TEMP', null, array(sprintf('df %s = %.0fk > 10k', self::$temp, $df / 1024)));
     }
 }
Пример #8
0
 public static function makeConfigDirectory()
 {
     self::$dir = realpath(System::tempDir()) . DIRECTORY_SEPARATOR . md5(uniqid()) . '.xp' . DIRECTORY_SEPARATOR;
     if (is_dir(self::$dir) && !rmdir(self::$dir)) {
         throw new PrerequisitesNotMetError('Fixture directory exists, but cannot remove', null, self::$dir);
     }
     self::$file = self::$dir . 'web.ini';
     mkdir(self::$dir);
     file_put_contents(self::$file, '[app]');
 }
Пример #9
0
 /**
  * Setup the class instance. A dsn string must be given with the relevant information
  * about the server and script:
  *
  * Eg: nagios://nagios.xp_framework.net:5667/service_to_monitor
  *
  * @param   string dsn
  */
 public function setup($dsn)
 {
     $url = new URL($dsn);
     $this->server = $url->getHost();
     $this->port = $url->getPort(5667);
     $this->version = $url->getParam('version', NscaProtocol::VERSION_2);
     $this->service = trim($url->getPath(), '/');
     $this->host = $url->getParam('hostname', System::getProperty('host.name'));
     if (false !== $url->getParam('domain', false)) {
         $this->host .= '.' . ltrim($url->getParam('domain'), '.');
     }
 }
 /**
  * Constructor
  *
  * @param   string name
  * @param   string[] args
  * @param   [:string] env
  */
 public function __construct($name, $args, $env = array())
 {
     $class = \lang\XPClass::forName($name);
     if ($class->hasConstructor()) {
         $this->scriptlet = $class->getConstructor()->newInstance((array) $args);
     } else {
         $this->scriptlet = $class->newInstance();
     }
     $this->scriptlet->init();
     $this->request = $class->getMethod('_request')->setAccessible(true);
     $this->response = $class->getMethod('_response')->setAccessible(true);
     $this->env = $env;
     $this->serverName = \lang\System::getProperty('host.name');
 }
Пример #11
0
 /**
  * Constructor
  *
  * @param   string $prefix default "tmp"
  */
 public function __construct($prefix = 'tmp')
 {
     parent::__construct(tempnam(System::tempDir(), $prefix . uniqid((double) microtime())));
 }
Пример #12
0
 public function runningDirectory()
 {
     new Process(System::tempDir());
 }
Пример #13
0
 /**
  * Sets up test case - initializes temp directory in %TEMP%
  *
  * @return void
  */
 public function setUp()
 {
     $this->folder = new Folder(System::tempDir(), md5(uniqid()) . '.xp');
     $this->folder->exists() && $this->folder->unlink();
     $this->folder->create();
 }
Пример #14
0
 /**
  * Main method
  *
  * @param   util.cmd.ParamString params
  * @return  int
  */
 public function run(ParamString $params)
 {
     // No arguments given - show our own usage
     if ($params->count < 1) {
         return self::usage();
     }
     // Configure properties
     $pm = PropertyManager::getInstance();
     // Separate runner options from class options
     for ($offset = 0, $i = 0; $i < $params->count; $i++) {
         switch ($params->list[$i]) {
             case '-c':
                 if (0 == strncmp('res://', $params->list[$i + 1], 6)) {
                     $pm->appendSource(new ResourcePropertySource(substr($params->list[$i + 1], 6)));
                 } else {
                     $pm->appendSource(new FilesystemPropertySource($params->list[$i + 1]));
                 }
                 $offset += 2;
                 $i++;
                 break;
             case '-cp':
                 \lang\ClassLoader::registerPath($params->list[$i + 1], null);
                 $offset += 2;
                 $i++;
                 break;
             case '-v':
                 $this->verbose = true;
                 $offset += 1;
                 $i++;
                 break;
             case '-?':
                 return self::usage();
             default:
                 break 2;
         }
     }
     // Sanity check
     if (!$params->exists($offset)) {
         self::$err->writeLine('*** Missing classname');
         return 1;
     }
     // Use default path for PropertyManager if no sources set
     if (!$pm->getSources()) {
         $pm->configure(self::DEFAULT_CONFIG_PATH);
     }
     unset($params->list[-1]);
     $classname = $params->value($offset);
     $classparams = new ParamString(array_slice($params->list, $offset + 1));
     // Class file or class name
     if (strstr($classname, \xp::CLASS_FILE_EXT)) {
         $file = new \io\File($classname);
         if (!$file->exists()) {
             self::$err->writeLine('*** Cannot load class from non-existant file ', $classname);
             return 1;
         }
         try {
             $class = \lang\ClassLoader::getDefault()->loadUri($file->getURI());
         } catch (\lang\ClassNotFoundException $e) {
             self::$err->writeLine('*** ', $this->verbose ? $e : $e->getMessage());
             return 1;
         }
     } else {
         try {
             $class = \lang\XPClass::forName($classname);
         } catch (\lang\ClassNotFoundException $e) {
             self::$err->writeLine('*** ', $this->verbose ? $e : $e->getMessage());
             return 1;
         }
     }
     // Check whether class is runnable
     if (!$class->isSubclassOf('lang.Runnable')) {
         self::$err->writeLine('*** ', $class->getName(), ' is not runnable');
         return 1;
     }
     // Usage
     if ($classparams->exists('help', '?')) {
         self::showUsage($class);
         return 0;
     }
     // Load, instantiate and initialize
     $l = Logger::getInstance();
     $pm->hasProperties('log') && $l->configure($pm->getProperties('log'));
     if (class_exists('rdbms\\DBConnection')) {
         // FIXME: Job of XPInjector?
         $cm = ConnectionManager::getInstance();
         $pm->hasProperties('database') && $cm->configure($pm->getProperties('database'));
     }
     // Setup logger context for all registered log categories
     foreach (Logger::getInstance()->getCategories() as $category) {
         if (null === ($context = $category->getContext()) || !$context instanceof EnvironmentAware) {
             continue;
         }
         $context->setHostname(\lang\System::getProperty('host.name'));
         $context->setRunner(nameof($this));
         $context->setInstance($class->getName());
         $context->setResource(null);
         $context->setParams($params->string);
     }
     $instance = $class->newInstance();
     $instance->in = self::$in;
     $instance->out = self::$out;
     $instance->err = self::$err;
     $methods = $class->getMethods();
     // Injection
     foreach ($methods as $method) {
         if (!$method->hasAnnotation('inject')) {
             continue;
         }
         $inject = $method->getAnnotation('inject');
         if (isset($inject['type'])) {
             $type = $inject['type'];
         } else {
             if ($restriction = $method->getParameter(0)->getTypeRestriction()) {
                 $type = $restriction->getName();
             } else {
                 $type = $method->getParameter(0)->getType()->getName();
             }
         }
         try {
             switch ($type) {
                 case 'rdbms.DBConnection':
                     $args = [$cm->getByHost($inject['name'], 0)];
                     break;
                 case 'util.Properties':
                     $p = $pm->getProperties($inject['name']);
                     // If a PropertyAccess is retrieved which is not a util.Properties,
                     // then, for BC sake, convert it into a util.Properties
                     if ($p instanceof \util\PropertyAccess && !$p instanceof \util\Properties) {
                         $convert = \util\Properties::fromString('');
                         $section = $p->getFirstSection();
                         while ($section) {
                             // HACK: Properties::writeSection() would first attempts to
                             // read the whole file, we cannot make use of it.
                             $convert->_data[$section] = $p->readSection($section);
                             $section = $p->getNextSection();
                         }
                         $args = [$convert];
                     } else {
                         $args = [$p];
                     }
                     break;
                 case 'util.log.LogCategory':
                     $args = [$l->getCategory($inject['name'])];
                     break;
                 default:
                     self::$err->writeLine('*** Unknown injection type "' . $type . '" at method "' . $method->getName() . '"');
                     return 2;
             }
             $method->invoke($instance, $args);
         } catch (\lang\reflect\TargetInvocationException $e) {
             self::$err->writeLine('*** Error injecting ' . $type . ' ' . $inject['name'] . ': ' . $e->getCause()->compoundMessage());
             return 2;
         } catch (\lang\Throwable $e) {
             self::$err->writeLine('*** Error injecting ' . $type . ' ' . $inject['name'] . ': ' . $e->compoundMessage());
             return 2;
         }
     }
     // Arguments
     foreach ($methods as $method) {
         if ($method->hasAnnotation('args')) {
             // Pass all arguments
             if (!$method->hasAnnotation('args', 'select')) {
                 $begin = 0;
                 $end = $classparams->count;
                 $pass = array_slice($classparams->list, 0, $end);
             } else {
                 $pass = [];
                 foreach (preg_split('/, ?/', $method->getAnnotation('args', 'select')) as $def) {
                     if (is_numeric($def) || '-' == $def[0]) {
                         $pass[] = $classparams->value((int) $def);
                     } else {
                         sscanf($def, '[%d..%d]', $begin, $end);
                         isset($begin) || ($begin = 0);
                         isset($end) || ($end = $classparams->count - 1);
                         while ($begin <= $end) {
                             $pass[] = $classparams->value($begin++);
                         }
                     }
                 }
             }
             try {
                 $method->invoke($instance, [$pass]);
             } catch (\lang\Throwable $e) {
                 self::$err->writeLine('*** Error for arguments ' . $begin . '..' . $end . ': ', $this->verbose ? $e : $e->getMessage());
                 return 2;
             }
         } else {
             if ($method->hasAnnotation('arg')) {
                 // Pass arguments
                 $arg = $method->getAnnotation('arg');
                 if (isset($arg['position'])) {
                     $name = '#' . ($arg['position'] + 1);
                     $select = intval($arg['position']);
                     $short = null;
                 } else {
                     if (isset($arg['name'])) {
                         $name = $select = $arg['name'];
                         $short = isset($arg['short']) ? $arg['short'] : null;
                     } else {
                         $name = $select = strtolower(preg_replace('/^set/', '', $method->getName()));
                         $short = isset($arg['short']) ? $arg['short'] : null;
                     }
                 }
                 if (0 == $method->numParameters()) {
                     if (!$classparams->exists($select, $short)) {
                         continue;
                     }
                     $args = [];
                 } else {
                     if (!$classparams->exists($select, $short)) {
                         list($first, ) = $method->getParameters();
                         if (!$first->isOptional()) {
                             self::$err->writeLine('*** Argument ' . $name . ' does not exist!');
                             return 2;
                         }
                         $args = [];
                     } else {
                         $args = [$classparams->value($select, $short)];
                     }
                 }
                 try {
                     $method->invoke($instance, $args);
                 } catch (\lang\reflect\TargetInvocationException $e) {
                     self::$err->writeLine('*** Error for argument ' . $name . ': ', $this->verbose ? $e->getCause() : $e->getCause()->compoundMessage());
                     return 2;
                 }
             }
         }
     }
     try {
         $instance->run();
     } catch (\lang\Throwable $t) {
         self::$err->writeLine('*** ', $t->toString());
         return 70;
         // EX_SOFTWARE according to sysexits.h
     }
     return 0;
 }
Пример #15
0
 public function links_resolved_in_realpath()
 {
     $temp = System::tempDir();
     $link = new Path($temp, 'link-to-temp');
     if (false === symlink($temp, $link)) {
         $this->skip('Cannot create ' . $link . ' -> ' . $temp);
     }
     $resolved = (new Path($link))->asRealpath()->toString();
     unlink($link);
     $this->assertEquals($temp, $resolved);
 }
Пример #16
0
 /** @param io.Path */
 private function tempName()
 {
     return Path::compose([System::tempDir(), md5(uniqid()) . '-xp.json']);
 }
Пример #17
0
 /**
  * Main runner method
  *
  * @param   string[] args
  */
 public static function main(array $args)
 {
     if (!$args) {
         self::usage();
     }
     // Parse arguments
     $output = '-';
     for ($i = 0, $s = sizeof($args); $i < $s; $i++) {
         if ('-O' == $args[$i]) {
             $output = $args[++$i];
         } else {
             if ('-?' == $args[$i] || '--help' == $args[$i]) {
                 self::usage();
             } else {
                 $package = $args[$i];
                 break;
             }
         }
     }
     // Load generator class
     try {
         $class = \lang\reflect\Package::forName('xp.codegen')->getPackage($package)->loadClass('Generator');
     } catch (\lang\ElementNotFoundException $e) {
         Console::$err->writeLine('*** No generator named "' . $package . '"');
         exit(2);
     }
     $params = new ParamString(array_slice($args, $i + 1));
     if ($params->exists('help', '?')) {
         Console::$err->writeLine(self::textOf($class->getComment()));
         exit(1);
     }
     // Instantiate generator
     $generator = $class->newInstance($params);
     $generator->storage = new FileSystemStorage(System::tempDir());
     // Output
     if ('-' === $output) {
         $generator->output = new ConsoleOutput(Console::$err);
     } else {
         if (strstr($output, '.xar')) {
             $generator->output = new ArchiveOutput($output);
         } else {
             $generator->output = new FileSystemOutput($output);
         }
     }
     $generator->output->addObserver(newinstance('util.Observer', array(), '{
   public function update($obs, $arg= NULL) { Console::writeLine("     >> ", $arg); }
 }'));
     Console::writeLine('===> Starting ', $generator);
     // Compile target chain
     $empty = new \lang\types\ArrayList();
     $targets = create('new util.collections.HashTable<lang.reflect.Method, util.collections.HashTable<string, lang.Generic>>()');
     foreach ($class->getMethods() as $method) {
         if (!$method->hasAnnotation('target')) {
             continue;
         }
         $target = create('new util.collections.HashTable<string, lang.Generic>()');
         // Fetch dependencies
         if ($method->hasAnnotation('target', 'depends')) {
             $depends = create('new util.collections.Vector<lang.reflect.Method>()');
             foreach ((array) $method->getAnnotation('target', 'depends') as $dependency) {
                 $depends[] = $class->getMethod($dependency);
             }
             $target['depends'] = $depends;
         }
         // Fetch input
         if ($method->hasAnnotation('target', 'input')) {
             $arguments = create('new util.collections.Vector<lang.reflect.Method>()');
             foreach ((array) $method->getAnnotation('target', 'input') as $input) {
                 $arguments[] = $class->getMethod($input);
             }
             $target['arguments'] = $arguments;
         }
         $targets->put($method, $target);
     }
     // Invoke
     try {
         foreach ($targets->keys() as $method) {
             self::invoke($generator, $method, $targets);
         }
     } catch (\lang\reflect\TargetInvocationException $e) {
         Console::$err->writeLine('*** ', $e->getCause());
         exit(3);
     }
     $generator->output->commit();
     Console::writeLine('===> Done');
 }
 public static function prepareTempDir()
 {
     self::$temp = new Folder(System::tempDir(), md5(uniqid()));
     self::$temp->create();
     session_save_path(self::$temp->getURI());
 }
Пример #19
0
 /**
  * Runs class
  *
  * @param  string $command
  * @param  util.cmd.ParamString $params
  * @param  util.cmd.Config $config
  * @return int
  */
 protected function runCommand($command, $params, $config)
 {
     try {
         $class = Commands::named($command);
     } catch (Throwable $e) {
         self::$err->writeLine('*** ', $this->verbose ? $e : $e->getMessage());
         return 1;
     }
     // Usage
     if ($params->exists('help', '?')) {
         $this->commandUsage($class);
         return 0;
     }
     // BC: PropertyManager, Logger, ConnectionManager instances
     $pm = PropertyManager::getInstance();
     $pm->setSources($config->sources());
     $l = Logger::getInstance();
     $pm->hasProperties('log') && $l->configure($pm->getProperties('log'));
     if (class_exists('rdbms\\DBConnection')) {
         // FIXME: Job of XPInjector?
         $cm = ConnectionManager::getInstance();
         $pm->hasProperties('database') && $cm->configure($pm->getProperties('database'));
     }
     // Setup logger context for all registered log categories
     foreach (Logger::getInstance()->getCategories() as $category) {
         if (null === ($context = $category->getContext()) || !$context instanceof EnvironmentAware) {
             continue;
         }
         $context->setHostname(System::getProperty('host.name'));
         $context->setRunner(nameof($this));
         $context->setInstance($class->getName());
         $context->setResource(null);
         $context->setParams($params->string);
     }
     if ($class->hasMethod('newInstance')) {
         $instance = $class->getMethod('newInstance')->invoke(null, [$config]);
     } else {
         if ($class->hasConstructor()) {
             $instance = $class->newInstance($config);
         } else {
             $instance = $class->newInstance();
         }
     }
     $instance->in = self::$in;
     $instance->out = self::$out;
     $instance->err = self::$err;
     $methods = $class->getMethods();
     // Injection
     foreach ($methods as $method) {
         if (!$method->hasAnnotation('inject')) {
             continue;
         }
         $inject = $method->getAnnotation('inject');
         if (isset($inject['type'])) {
             $type = $inject['type'];
         } else {
             if ($restriction = $method->getParameter(0)->getTypeRestriction()) {
                 $type = $restriction->getName();
             } else {
                 $type = $method->getParameter(0)->getType()->getName();
             }
         }
         try {
             switch ($type) {
                 case 'rdbms.DBConnection':
                     $args = [$cm->getByHost($inject['name'], 0)];
                     break;
                 case 'util.Properties':
                     $p = $pm->getProperties($inject['name']);
                     // If a PropertyAccess is retrieved which is not a util.Properties,
                     // then, for BC sake, convert it into a util.Properties
                     if ($p instanceof PropertyAccess && !$p instanceof Properties) {
                         $convert = new Properties(null);
                         $convert->load(new \io\streams\MemoryInputStream(''));
                         $section = $p->getFirstSection();
                         while ($section) {
                             // HACK: Properties::writeSection() would first attempts to
                             // read the whole file, we cannot make use of it.
                             $convert->_data[$section] = $p->readSection($section);
                             $section = $p->getNextSection();
                         }
                         $args = [$convert];
                     } else {
                         $args = [$p];
                     }
                     break;
                 case 'util.log.LogCategory':
                     $args = [$l->getCategory($inject['name'])];
                     break;
                 default:
                     self::$err->writeLine('*** Unknown injection type "' . $type . '" at method "' . $method->getName() . '"');
                     return 2;
             }
             $method->invoke($instance, $args);
         } catch (TargetInvocationException $e) {
             self::$err->writeLine('*** Error injecting ' . $type . ' ' . $inject['name'] . ': ' . $e->getCause()->compoundMessage());
             return 2;
         } catch (Throwable $e) {
             self::$err->writeLine('*** Error injecting ' . $type . ' ' . $inject['name'] . ': ' . $e->compoundMessage());
             return 2;
         }
     }
     // Arguments
     foreach ($methods as $method) {
         if ($method->hasAnnotation('args')) {
             // Pass all arguments
             if (!$method->hasAnnotation('args', 'select')) {
                 $begin = 0;
                 $end = $params->count;
                 $pass = array_slice($params->list, 0, $end);
             } else {
                 $pass = [];
                 foreach (preg_split('/, ?/', $method->getAnnotation('args', 'select')) as $def) {
                     if (is_numeric($def) || '-' == $def[0]) {
                         $pass[] = $params->value((int) $def);
                     } else {
                         sscanf($def, '[%d..%d]', $begin, $end);
                         isset($begin) || ($begin = 0);
                         isset($end) || ($end = $params->count - 1);
                         while ($begin <= $end) {
                             $pass[] = $params->value($begin++);
                         }
                     }
                 }
             }
             try {
                 $method->invoke($instance, [$pass]);
             } catch (Throwable $e) {
                 self::$err->writeLine('*** Error for arguments ' . $begin . '..' . $end . ': ', $this->verbose ? $e : $e->getMessage());
                 return 2;
             }
         } else {
             if ($method->hasAnnotation('arg')) {
                 // Pass arguments
                 $arg = $method->getAnnotation('arg');
                 if (isset($arg['position'])) {
                     $name = '#' . ($arg['position'] + 1);
                     $select = intval($arg['position']);
                     $short = null;
                 } else {
                     if (isset($arg['name'])) {
                         $name = $select = $arg['name'];
                         $short = isset($arg['short']) ? $arg['short'] : null;
                     } else {
                         $name = $select = strtolower(preg_replace('/^set/', '', $method->getName()));
                         $short = isset($arg['short']) ? $arg['short'] : null;
                     }
                 }
                 if (0 == $method->numParameters()) {
                     if (!$params->exists($select, $short)) {
                         continue;
                     }
                     $args = [];
                 } else {
                     if (!$params->exists($select, $short)) {
                         list($first, ) = $method->getParameters();
                         if (!$first->isOptional()) {
                             self::$err->writeLine('*** Argument ' . $name . ' does not exist!');
                             return 2;
                         }
                         $args = [];
                     } else {
                         $args = [$params->value($select, $short)];
                     }
                 }
                 try {
                     $method->invoke($instance, $args);
                 } catch (TargetInvocationException $e) {
                     self::$err->writeLine('*** Error for argument ' . $name . ': ', $this->verbose ? $e->getCause() : $e->getCause()->compoundMessage());
                     return 2;
                 }
             }
         }
     }
     try {
         return (int) $instance->run();
     } catch (Throwable $t) {
         self::$err->writeLine('*** ', $t->toString());
         return 70;
         // EX_SOFTWARE according to sysexits.h
     }
 }
Пример #20
0
 public function callingMain()
 {
     $temp = System::tempDir();
     // Create web.ini in system's temp dir
     $ini = new \io\File($temp, 'web.ini');
     $ini->open(FILE_MODE_WRITE);
     $ini->write("[app]\n" . "mappings=\"/:welcome\"\n" . "[app::welcome]\n" . "class=undefined\n" . "[app::welcome@dev]\n" . "class=\"" . self::$welcomeScriptlet->getName() . "\"\n");
     $ini->close();
     // Run
     ob_start();
     Runner::main(array($temp, $temp, 'dev', '/'));
     $content = ob_get_contents();
     ob_end_clean();
     $ini->unlink();
     // Assert
     $this->assertEquals('<h1>Welcome, we are open</h1>', $content);
 }