1<?php
2namespace GuzzleHttp\Tests\Ring\Future;
3
4use GuzzleHttp\Ring\Exception\CancelledFutureAccessException;
5use GuzzleHttp\Ring\Future\FutureValue;
6use React\Promise\Deferred;
7
8class FutureValueTest extends \PHPUnit_Framework_TestCase
9{
10    public function testDerefReturnsValue()
11    {
12        $called = 0;
13        $deferred = new Deferred();
14
15        $f = new FutureValue(
16            $deferred->promise(),
17            function () use ($deferred, &$called) {
18                $called++;
19                $deferred->resolve('foo');
20            }
21        );
22
23        $this->assertEquals('foo', $f->wait());
24        $this->assertEquals(1, $called);
25        $this->assertEquals('foo', $f->wait());
26        $this->assertEquals(1, $called);
27        $f->cancel();
28        $this->assertTrue($this->readAttribute($f, 'isRealized'));
29    }
30
31    /**
32     * @expectedException \GuzzleHttp\Ring\Exception\CancelledFutureAccessException
33     */
34    public function testThrowsWhenAccessingCancelled()
35    {
36        $f = new FutureValue(
37            (new Deferred())->promise(),
38            function () {},
39            function () { return true; }
40        );
41        $f->cancel();
42        $f->wait();
43    }
44
45    /**
46     * @expectedException \OutOfBoundsException
47     */
48    public function testThrowsWhenDerefFailure()
49    {
50        $called = false;
51        $deferred = new Deferred();
52        $f = new FutureValue(
53            $deferred->promise(),
54            function () use(&$called) {
55                $called = true;
56            }
57        );
58        $deferred->reject(new \OutOfBoundsException());
59        $f->wait();
60        $this->assertFalse($called);
61    }
62
63    /**
64     * @expectedException \GuzzleHttp\Ring\Exception\RingException
65     * @expectedExceptionMessage Waiting did not resolve future
66     */
67    public function testThrowsWhenDerefDoesNotResolve()
68    {
69        $deferred = new Deferred();
70        $f = new FutureValue(
71            $deferred->promise(),
72            function () use(&$called) {
73                $called = true;
74            }
75        );
76        $f->wait();
77    }
78
79    public function testThrowingCancelledFutureAccessExceptionCancels()
80    {
81        $deferred = new Deferred();
82        $f = new FutureValue(
83            $deferred->promise(),
84            function () use ($deferred) {
85                throw new CancelledFutureAccessException();
86            }
87        );
88        try {
89            $f->wait();
90            $this->fail('did not throw');
91        } catch (CancelledFutureAccessException $e) {}
92    }
93
94    /**
95     * @expectedException \Exception
96     * @expectedExceptionMessage foo
97     */
98    public function testThrowingExceptionInDerefMarksAsFailed()
99    {
100        $deferred = new Deferred();
101        $f = new FutureValue(
102            $deferred->promise(),
103            function () {
104                throw new \Exception('foo');
105            }
106        );
107        $f->wait();
108    }
109}
110