--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Rest\PathTemplateMatcher;
+
+use MediaWiki\Rest\PathTemplateMatcher\PathConflict;
+use MediaWiki\Rest\PathTemplateMatcher\PathMatcher;
+use MediaWikiTestCase;
+
+/**
+ * @covers \MediaWiki\Rest\PathTemplateMatcher\PathMatcher
+ * @covers \MediaWiki\Rest\PathTemplateMatcher\PathConflict
+ */
+class PathMatcherTest extends MediaWikiTestCase {
+ private static $normalRoutes = [
+ '/a/b',
+ '/b/{x}',
+ '/c/{x}/d',
+ '/c/{x}/e',
+ '/c/{x}/{y}/d',
+ ];
+
+ public static function provideConflictingRoutes() {
+ return [
+ [ '/a/b', 0, '/a/b' ],
+ [ '/a/{x}', 0, '/a/b' ],
+ [ '/{x}/c', 1, '/b/{x}' ],
+ [ '/b/a', 1, '/b/{x}' ],
+ [ '/b/{x}', 1, '/b/{x}' ],
+ [ '/{x}/{y}/d', 2, '/c/{x}/d' ],
+ ];
+ }
+
+ public static function provideMatch() {
+ return [
+ [ '', false ],
+ [ '/a/b', [ 'params' => [], 'userData' => 0 ] ],
+ [ '/b', false ],
+ [ '/b/1', [ 'params' => [ 'x' => '1' ], 'userData' => 1 ] ],
+ [ '/c/1/d', [ 'params' => [ 'x' => '1' ], 'userData' => 2 ] ],
+ [ '/c/1/e', [ 'params' => [ 'x' => '1' ], 'userData' => 3 ] ],
+ [ '/c/000/e', [ 'params' => [ 'x' => '000' ], 'userData' => 3 ] ],
+ [ '/c/1/f', false ],
+ [ '/c//e', [ 'params' => [ 'x' => '' ], 'userData' => 3 ] ],
+ [ '/c///e', false ],
+ ];
+ }
+
+ public function createNormalRouter() {
+ $pm = new PathMatcher;
+ foreach ( self::$normalRoutes as $i => $route ) {
+ $pm->add( $route, $i );
+ }
+ return $pm;
+ }
+
+ /** @dataProvider provideConflictingRoutes */
+ public function testAddConflict( $attempt, $expectedUserData, $expectedTemplate ) {
+ $pm = $this->createNormalRouter();
+ $actualTemplate = null;
+ $actualUserData = null;
+ try {
+ $pm->add( $attempt, 'conflict' );
+ } catch ( PathConflict $pc ) {
+ $actualTemplate = $pc->existingTemplate;
+ $actualUserData = $pc->existingUserData;
+ }
+ $this->assertSame( $expectedUserData, $actualUserData );
+ $this->assertSame( $expectedTemplate, $actualTemplate );
+ }
+
+ /** @dataProvider provideMatch */
+ public function testMatch( $path, $expectedResult ) {
+ $pm = $this->createNormalRouter();
+ $result = $pm->match( $path );
+ $this->assertSame( $expectedResult, $result );
+ }
+}
--- /dev/null
+<?php
+
+namespace MediaWiki\Tests\Rest;
+
+use MediaWiki\Rest\StringStream;
+use MediaWikiTestCase;
+
+/** @covers \MediaWiki\Rest\StringStream */
+class StringStreamTest extends MediaWikiTestCase {
+ public static function provideSeekGetContents() {
+ return [
+ [ 'abcde', 0, SEEK_SET, 'abcde' ],
+ [ 'abcde', 1, SEEK_SET, 'bcde' ],
+ [ 'abcde', 5, SEEK_SET, '' ],
+ [ 'abcde', 1, SEEK_CUR, 'cde' ],
+ [ 'abcde', 0, SEEK_END, '' ],
+ ];
+ }
+
+ /** @dataProvider provideSeekGetContents */
+ public function testCopyToStream( $input, $offset, $whence, $expected ) {
+ $ss = new StringStream;
+ $ss->write( $input );
+ $ss->seek( 1 );
+ $ss->seek( $offset, $whence );
+ $destStream = fopen( 'php://memory', 'w+' );
+ $ss->copyToStream( $destStream );
+ fseek( $destStream, 0 );
+ $result = stream_get_contents( $destStream );
+ $this->assertSame( $expected, $result );
+ }
+
+ public function testGetSize() {
+ $ss = new StringStream;
+ $this->assertSame( 0, $ss->getSize() );
+ $ss->write( "hello" );
+ $this->assertSame( 5, $ss->getSize() );
+ $ss->rewind();
+ $this->assertSame( 5, $ss->getSize() );
+ }
+
+ public function testTell() {
+ $ss = new StringStream;
+ $this->assertSame( $ss->tell(), 0 );
+ $ss->write( "abc" );
+ $this->assertSame( $ss->tell(), 3 );
+ $ss->seek( 0 );
+ $ss->read( 1 );
+ $this->assertSame( $ss->tell(), 1 );
+ }
+
+ public function testEof() {
+ $ss = new StringStream( 'abc' );
+ $this->assertFalse( $ss->eof() );
+ $ss->read( 1 );
+ $this->assertFalse( $ss->eof() );
+ $ss->read( 1 );
+ $this->assertFalse( $ss->eof() );
+ $ss->read( 1 );
+ $this->assertTrue( $ss->eof() );
+ $ss->rewind();
+ $this->assertFalse( $ss->eof() );
+ }
+
+ public function testIsSeekable() {
+ $ss = new StringStream;
+ $this->assertTrue( $ss->isSeekable() );
+ }
+
+ public function testIsReadable() {
+ $ss = new StringStream;
+ $this->assertTrue( $ss->isReadable() );
+ }
+
+ public function testIsWritable() {
+ $ss = new StringStream;
+ $this->assertTrue( $ss->isWritable() );
+ }
+
+ public function testSeekWrite() {
+ $ss = new StringStream;
+ $this->assertSame( '', (string)$ss );
+ $ss->write( 'a' );
+ $this->assertSame( 'a', (string)$ss );
+ $ss->write( 'b' );
+ $this->assertSame( 'ab', (string)$ss );
+ $ss->seek( 1 );
+ $ss->write( 'c' );
+ $this->assertSame( 'ac', (string)$ss );
+ }
+
+ /** @dataProvider provideSeekGetContents */
+ public function testSeekGetContents( $input, $offset, $whence, $expected ) {
+ $ss = new StringStream( $input );
+ $ss->seek( 1 );
+ $ss->seek( $offset, $whence );
+ $this->assertSame( $expected, $ss->getContents() );
+ }
+
+ public static function provideSeekRead() {
+ return [
+ [ 'abcde', 0, SEEK_SET, 1, 'a' ],
+ [ 'abcde', 0, SEEK_SET, 2, 'ab' ],
+ [ 'abcde', 4, SEEK_SET, 2, 'e' ],
+ [ 'abcde', 5, SEEK_SET, 1, '' ],
+ [ 'abcde', 1, SEEK_CUR, 1, 'c' ],
+ [ 'abcde', 0, SEEK_END, 1, '' ],
+ [ 'abcde', -1, SEEK_END, 1, 'e' ],
+ ];
+ }
+
+ /** @dataProvider provideSeekRead */
+ public function testSeekRead( $input, $offset, $whence, $length, $expected ) {
+ $ss = new StringStream( $input );
+ $ss->seek( 1 );
+ $ss->seek( $offset, $whence );
+ $this->assertSame( $expected, $ss->read( $length ) );
+ }
+
+ /** @expectedException \InvalidArgumentException */
+ public function testReadBeyondEnd() {
+ $ss = new StringStream( 'abc' );
+ $ss->seek( 1, SEEK_END );
+ }
+
+ /** @expectedException \InvalidArgumentException */
+ public function testReadBeforeStart() {
+ $ss = new StringStream( 'abc' );
+ $ss->seek( -1 );
+ }
+}