1<?php 2 3use PHPUnit\Framework\MockObject\MockObject; 4 5/** 6 * @covers ExternalStoreAccess 7 */ 8class ExternalStoreAccessTest extends MediaWikiIntegrationTestCase { 9 10 use MediaWikiCoversValidator; 11 12 public function testBasic() { 13 $active = [ 'memory' ]; 14 $defaults = [ 'memory://cluster1', 'memory://cluster2' ]; 15 $esFactory = new ExternalStoreFactory( $active, $defaults, 'db-prefix' ); 16 $access = new ExternalStoreAccess( $esFactory ); 17 18 $this->assertFalse( $access->isReadOnly() ); 19 20 /** @var ExternalStoreMemory $store */ 21 $store = $esFactory->getStore( 'memory' ); 22 $this->assertInstanceOf( ExternalStoreMemory::class, $store ); 23 24 $location = $esFactory->getStoreLocationFromUrl( 'memory://cluster1' ); 25 $this->assertFalse( $store->isReadOnly( $location ) ); 26 } 27 28 /** 29 * @covers ExternalStoreAccess::isReadOnly 30 */ 31 public function testReadOnly() { 32 /** @var ExternalStoreMedium|MockObject $medium */ 33 $medium = $this->getMockBuilder( ExternalStoreMedium::class ) 34 ->disableOriginalConstructor() 35 ->getMock(); 36 37 $medium->method( 'isReadOnly' )->willReturn( true ); 38 39 /** @var ExternalStoreFactory|MockObject $esFactory */ 40 $esFactory = $this->getMockBuilder( ExternalStoreFactory::class ) 41 ->disableOriginalConstructor() 42 ->getMock(); 43 44 $esFactory->method( 'getWriteBaseUrls' )->willReturn( [ 'test:' ] ); 45 $esFactory->method( 'getStoreForUrl' )->willReturn( $medium ); 46 $esFactory->method( 'getStoreLocationFromUrl' )->willReturn( 'dummy' ); 47 48 $access = new ExternalStoreAccess( $esFactory ); 49 $this->assertTrue( $access->isReadOnly() ); 50 51 $this->expectExceptionObject( new ReadOnlyError() ); 52 $access->insert( 'Lorem Ipsum' ); 53 } 54 55 /** 56 * @covers ExternalStoreAccess::fetchFromURL 57 * @covers ExternalStoreAccess::fetchFromURLs 58 * @covers ExternalStoreAccess::insert 59 */ 60 public function testReadWrite() { 61 $active = [ 'memory' ]; // active store types 62 $defaults = [ 'memory://cluster1', 'memory://cluster2' ]; 63 $esFactory = new ExternalStoreFactory( $active, $defaults, 'db-prefix' ); 64 $access = new ExternalStoreAccess( $esFactory ); 65 66 /** @var ExternalStoreMemory $storeLocal */ 67 $storeLocal = $esFactory->getStore( 'memory' ); 68 /** @var ExternalStoreMemory $storeOther */ 69 $storeOther = $esFactory->getStore( 'memory', [ 'domain' => 'other' ] ); 70 $this->assertInstanceOf( ExternalStoreMemory::class, $storeLocal ); 71 $this->assertInstanceOf( ExternalStoreMemory::class, $storeOther ); 72 73 $v1 = wfRandomString(); 74 $v2 = wfRandomString(); 75 $v3 = wfRandomString(); 76 77 $this->assertFalse( $storeLocal->fetchFromURL( 'memory://cluster1/1' ) ); 78 79 $url1 = 'memory://cluster1/1'; 80 $this->assertEquals( 81 $url1, 82 $esFactory->getStoreForUrl( 'memory://cluster1' ) 83 ->store( $esFactory->getStoreLocationFromUrl( 'memory://cluster1' ), $v1 ) 84 ); 85 $this->assertEquals( 86 $v1, 87 $esFactory->getStoreForUrl( 'memory://cluster1/1' ) 88 ->fetchFromURL( 'memory://cluster1/1' ) 89 ); 90 $this->assertEquals( $v1, $storeLocal->fetchFromURL( 'memory://cluster1/1' ) ); 91 92 $url2 = $access->insert( $v2 ); 93 $url3 = $access->insert( $v3, [ 'domain' => 'other' ] ); 94 $this->assertNotFalse( $url2 ); 95 $this->assertNotFalse( $url3 ); 96 // There is only one active store type 97 $this->assertEquals( $v2, $storeLocal->fetchFromURL( $url2 ) ); 98 $this->assertEquals( $v3, $storeOther->fetchFromURL( $url3 ) ); 99 $this->assertFalse( $storeOther->fetchFromURL( $url2 ) ); 100 $this->assertFalse( $storeLocal->fetchFromURL( $url3 ) ); 101 102 $res = $access->fetchFromURLs( [ $url1, $url2, $url3 ] ); 103 $this->assertEquals( [ $url1 => $v1, $url2 => $v2, $url3 => false ], $res, "Local-only" ); 104 105 $storeLocal->clear(); 106 $storeOther->clear(); 107 } 108} 109