storageCache = $this->createMock(StorageCache::class); $this->storage = $this->createMock(Temporary::class); $this->storage->expects($this->any()) ->method('getStorageCache') ->willReturn($this->storageCache); $this->wrapper = new Availability(['storage' => $this->storage]); } /** * Storage is available */ public function testAvailable(): void { $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => true, 'last_checked' => 0]); $this->storage->expects($this->never()) ->method('test'); $this->storage->expects($this->once()) ->method('mkdir'); $this->wrapper->mkdir('foobar'); } /** * Storage marked unavailable, TTL not expired * */ public function testUnavailable(): void { $this->expectException(\OCP\Files\StorageNotAvailableException::class); $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => false, 'last_checked' => time()]); $this->storage->expects($this->never()) ->method('test'); $this->storage->expects($this->never()) ->method('mkdir'); $this->wrapper->mkdir('foobar'); } /** * Storage marked unavailable, TTL expired */ public function testUnavailableRecheck(): void { $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => false, 'last_checked' => 0]); $this->storage->expects($this->once()) ->method('test') ->willReturn(true); $this->storage->expects($this->exactly(2)) ->method('setAvailability') ->withConsecutive( [$this->equalTo(false)], // prevents concurrent rechecks [$this->equalTo(true)] // sets correct availability ); $this->storage->expects($this->once()) ->method('mkdir'); $this->wrapper->mkdir('foobar'); } /** * Storage marked available, but throws StorageNotAvailableException * */ public function testAvailableThrowStorageNotAvailable(): void { $this->expectException(\OCP\Files\StorageNotAvailableException::class); $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => true, 'last_checked' => 0]); $this->storage->expects($this->never()) ->method('test'); $this->storage->expects($this->once()) ->method('mkdir') ->will($this->throwException(new StorageNotAvailableException())); $this->storageCache->expects($this->once()) ->method('setAvailability') ->with($this->equalTo(false)); $this->wrapper->mkdir('foobar'); } /** * Storage available, but call fails * Method failure does not indicate storage unavailability */ public function testAvailableFailure(): void { $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => true, 'last_checked' => 0]); $this->storage->expects($this->never()) ->method('test'); $this->storage->expects($this->once()) ->method('mkdir') ->willReturn(false); $this->storage->expects($this->never()) ->method('setAvailability'); $this->wrapper->mkdir('foobar'); } /** * Storage available, but throws exception * Standard exception does not indicate storage unavailability * */ public function testAvailableThrow(): void { $this->expectException(\Exception::class); $this->storage->expects($this->once()) ->method('getAvailability') ->willReturn(['available' => true, 'last_checked' => 0]); $this->storage->expects($this->never()) ->method('test'); $this->storage->expects($this->once()) ->method('mkdir') ->will($this->throwException(new \Exception())); $this->storage->expects($this->never()) ->method('setAvailability'); $this->wrapper->mkdir('foobar'); } }