PHP Classes

File: test/RouterTest.php

Recommend this page to a friend!
  Packages of Igor Crevar   icRouter   test/RouterTest.php   Download  
File: test/RouterTest.php
Role: Unit test script
Content type: text/plain
Description: phpunit tests
Class: icRouter
Route accesses based on request parameters
Author: By
Last change: Update of test/RouterTest.php
Date: 2 days ago
Size: 8,459 bytes
 

Contents

Class file image Download
<?php

namespace PathForge\icRouter\test;

use
PathForge\icRouter\Router;
use
PathForge\icRouter\Route;
use
PathForge\icRouter\Interfaces\DefImpl\DefaultNodeBuilder;

class
RouterTest extends \PHPUnit\Framework\TestCase
{
    private
$router;
   
    protected function
setUp(): void
   
{
       
$this->router = new Router(new DefaultNodeBuilder());
       
       
$this->router->setRoutes([
            new
Route('simple', '/simple',
                      array(
'module' => 'simple')),
            new
Route('simple_param', '/param/:a',
                      array(
'module' => 'simple_param', 'a' => 10),
                      array(
'a' => '\d+')), ///^\d+$/')),
           
new Route('two_params', '/param/hello/:a/some/:b',
                      array(
'module' => 'two_params', 'a' => 10, 'onemore' => 'time')),
            new
Route('two_params_any', '/home/hello/:a/:b/*',
                      array(
'module' => 'two_params_any', 'a' => 10, 'b' => '10'),
                     
//array('b' => '/^[01]+$/')),
                     
array('b' => '[01]+')), ///^\d+$/')),
           
new Route('labud', '/labud/:a/*',
                      array(
'module' => 'labud', 'a' => 10, 'b' => 20)),
            new
Route('complex_param', '/complex/id_:id',
                array(
'module' => 'complex_param'),
                array(
'id' => '\d+')), ///^\d+$/')),
           
new Route('home', '/*',
                      array(
'module' => 'home')),
        ]);
       
       
// must build tree
       
$this->router->build();
    }
   
    public function
testHomeMatch()
    {
       
$result = $this->router->match('/a/b/c/d/e');
       
$this->assertEquals(
            array(
'module' => 'home', 'a' => 'b', 'c' => 'd'), $result);
       
       
$result = $this->router->match('/kobac/2');
       
$this->assertEquals(
            array(
'module' => 'home', 'kobac' => '2'), $result);
    }
   
    public function
testSimpleMatch()
    {
       
$result = $this->router->match('/simple');
       
$this->assertEquals(
            array(
'module' => 'simple'), $result);
    }
   
    public function
testSimpleParamMatch()
    {
       
$result = $this->router->match('/param/20');
       
$this->assertEquals(
            array(
'module' => 'simple_param', 'a' => '20'), $result);
       
$result = $this->router->match('/param/dzuvec');
       
$this->assertFalse($result);
    }
   
    public function
testComplexParamMatch() {
       
$result = $this->router->match('/complex/id_125');
       
$this->assertEquals(
            array(
'module' => 'complex_param', 'id' => '125'), $result);
       
$result = $this->router->match('/complex/ide_125');
       
$this->assertFalse($result);
       
$result = $this->router->match('/complex/125');
       
$this->assertFalse($result);
    }
   
    public function
testTwoParamsMatch()
    {
       
$result = $this->router->match('/param/hello/two/some/qw');
       
$this->assertEquals(
            array(
'module' => 'two_params', 'a' => 'two',
                 
'onemore' => 'time', 'b' => 'qw'), $result);
       
$result = $this->router->match('/param/hello/ko/some');
       
$this->assertFalse($result);
    }
   
    public function
testTwoParamsAnyMatch()
    {
       
$result = $this->router->match('/home/hello/1/01/c/3/d');
       
$this->assertEquals(
            array(
'module' => 'two_params_any', 'a' => '1', 'b' => '01', 'c' => '3'), $result);
       
// b is not [01]+
       
$result = $this->router->match('/home/hello/1/201/c/3/d');
       
$this->assertFalse($result);
       
       
$result = $this->router->match('/home/hello/1/01');
       
$this->assertEquals(
            array(
'module' => 'two_params_any', 'a' => '1', 'b' => '01'), $result);
       
    }
   
    public function
testGenerateTwoParamsAny()
    {
       
$result = $this->router->generate('two_params_any',
            array(
'a' => 20, 'c' => 1));
       
$this->assertEquals('/home/hello/20/10/c/1', $result);
       
       
$result = $this->router->generate('two_params_any', array('a' => 20));
       
$this->assertEquals('/home/hello/20/10', $result);
       
$result = $this->router->generate('two_params_any', array());
       
$this->assertEquals('/home/hello/10/10', $result);
    }
   
    public function
testGenerateHome()
    {
       
$result = $this->router->generate('home', array('a' => 20, 'c' => 1));
       
$this->assertEquals('/a/20/c/1', $result);
    }
   
    public function
testGenerateTwoParams()
    {
       
$result = $this->router->generate('two_params', array('b' => 'aabb'));
       
$this->assertEquals('/param/hello/10/some/aabb', $result);
       
$result = $this->router->generate('two_params',
                  array(
'b' => 'aabb', 'a' => 'bbaa'));
       
$this->assertEquals('/param/hello/bbaa/some/aabb', $result);
    }
   
   
/**
     * b is not set
     */
   
public function testGenerateExceptionParamNotSet()
    {
       
$this->expectException(\PathForge\icRouter\RouterException::class);
       
// b is not set
       
$this->router->generate('two_params');
    }
   
    public function
testGenerateComplexParam() {
       
$result = $this->router->generate('complex_param', array('id' => 1));
       
$this->assertEquals('/complex/id_1', $result);
    }
   
   
   
/**
     * additional params set and not end with *
     */
   
public function testGenerateExceptionAdditionalParamoOnNonStarRoute()
    {
       
$this->expectException(\PathForge\icRouter\RouterException::class);
       
// additional params set and not end with *
       
$this->router->generate('two_params', array('b' => 1, 'c' => 2));
    }

   
/**
     * Wildcard segments can legitimately overwrite defaults.
     */
   
public function testWildcardCanOverwriteDefaults()
    {
       
// The 'home' route has default module => 'home'
        // Wildcard segments should be able to override defaults
       
$result = $this->router->match('/module/other');
       
$this->assertIsArray($result);
       
$this->assertEquals('other', $result['module']);
    }

   
/**
     * Wildcard segments cannot overwrite previously matched named params.
     */
   
public function testWildcardCannotOverwriteNamedParams()
    {
       
// The 'two_params_any' route: /home/hello/:a/:b/*
        // URL tries to overwrite 'a' via the wildcard segments
       
$result = $this->router->match('/home/hello/1/01/a/overwritten');
       
$this->assertIsArray($result);
       
// 'a' should remain '1' from the :a param, not overwritten
       
$this->assertEquals('1', $result['a']);
    }

   
/**
     * ReDoS: a malicious regex pattern causes catastrophic backtracking.
     * After fix, this throws RouterException instead of silently returning false.
     */
   
public function testReDoSWithMaliciousPattern()
    {
       
$router = new Router(new DefaultNodeBuilder());
       
$router->setRoutes([
            new
Route('redos', '/redos/:input',
                      array(
'module' => 'redos'),
                      array(
'input' => '(a+)+')),
        ]);
       
$router->build();
       
       
$this->expectException(\PathForge\icRouter\RouterException::class);
       
$router->match('/redos/' . str_repeat('a', 25) . '!');
    }

   
/**
     * Missing use statement: DefaultNodeBuilder throws RouterException without importing it.
     * A route pattern with an invalid parameter syntax (colon but no valid identifier)
     * should throw RouterException, but instead causes a fatal "class not found" error.
     */
   
public function testMissingUseStatementInDefaultNodeBuilder()
    {
       
$router = new Router(new DefaultNodeBuilder());
       
$router->setRoutes([
           
// ':' with no valid identifier after it triggers the exception path
           
new Route('bad_param', '/bad/:',
                      array(
'module' => 'bad')),
        ]);
       
       
// This should throw RouterException but will fail with
        // "Class 'PathForge\icRouter\Interfaces\DefImpl\RouterException' not found"
       
$this->expectException(\PathForge\icRouter\RouterException::class);
       
$router->build();
    }
}
   
spl_autoload_register(function($className) {
    if (
strpos($className, 'PathForge\\icRouter\\') === 0) {
       
$path = dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR;
        include
str_replace('\\', DIRECTORY_SEPARATOR, $path.$className).'.php';
    }
});