1<?php
2namespace GuzzleHttp\Tests\Stream;
3
4use GuzzleHttp\Stream\StreamInterface;
5use GuzzleHttp\Stream\Stream;
6use GuzzleHttp\Stream\StreamDecoratorTrait;
7
8class Str implements StreamInterface
9{
10    use StreamDecoratorTrait;
11}
12
13/**
14 * @covers GuzzleHttp\Stream\StreamDecoratorTrait
15 */
16class StreamDecoratorTraitTest extends \PHPUnit_Framework_TestCase
17{
18    private $a;
19    private $b;
20    private $c;
21
22    public function setUp()
23    {
24        $this->c = fopen('php://temp', 'r+');
25        fwrite($this->c, 'foo');
26        fseek($this->c, 0);
27        $this->a = Stream::factory($this->c);
28        $this->b = new Str($this->a);
29    }
30
31    public function testCatchesExceptionsWhenCastingToString()
32    {
33        $s = $this->getMockBuilder('GuzzleHttp\Stream\StreamInterface')
34            ->setMethods(['read'])
35            ->getMockForAbstractClass();
36        $s->expects($this->once())
37            ->method('read')
38            ->will($this->throwException(new \Exception('foo')));
39        $msg = '';
40        set_error_handler(function ($errNo, $str) use (&$msg) { $msg = $str; });
41        echo new Str($s);
42        restore_error_handler();
43        $this->assertContains('foo', $msg);
44    }
45
46    public function testToString()
47    {
48        $this->assertEquals('foo', (string) $this->b);
49    }
50
51    public function testHasSize()
52    {
53        $this->assertEquals(3, $this->b->getSize());
54        $this->assertSame($this->b, $this->b->setSize(2));
55        $this->assertEquals(2, $this->b->getSize());
56    }
57
58    public function testReads()
59    {
60        $this->assertEquals('foo', $this->b->read(10));
61    }
62
63    public function testCheckMethods()
64    {
65        $this->assertEquals($this->a->isReadable(), $this->b->isReadable());
66        $this->assertEquals($this->a->isWritable(), $this->b->isWritable());
67        $this->assertEquals($this->a->isSeekable(), $this->b->isSeekable());
68    }
69
70    public function testSeeksAndTells()
71    {
72        $this->assertTrue($this->b->seek(1));
73        $this->assertEquals(1, $this->a->tell());
74        $this->assertEquals(1, $this->b->tell());
75        $this->assertTrue($this->b->seek(0));
76        $this->assertEquals(0, $this->a->tell());
77        $this->assertEquals(0, $this->b->tell());
78        $this->assertTrue($this->b->seek(0, SEEK_END));
79        $this->assertEquals(3, $this->a->tell());
80        $this->assertEquals(3, $this->b->tell());
81    }
82
83    public function testGetsContents()
84    {
85        $this->assertEquals('foo', $this->b->getContents());
86        $this->assertEquals('', $this->b->getContents());
87        $this->b->seek(1);
88        $this->assertEquals('oo', $this->b->getContents(1));
89    }
90
91    public function testCloses()
92    {
93        $this->b->close();
94        $this->assertFalse(is_resource($this->c));
95    }
96
97    public function testDetaches()
98    {
99        $this->b->detach();
100        $this->assertFalse($this->b->isReadable());
101    }
102
103    /**
104     * @expectedException \GuzzleHttp\Stream\Exception\CannotAttachException
105     */
106    public function testCannotAttachByDefault()
107    {
108        $this->b->attach('a');
109    }
110
111    public function testWrapsMetadata()
112    {
113        $this->assertSame($this->b->getMetadata(), $this->a->getMetadata());
114        $this->assertSame($this->b->getMetadata('uri'), $this->a->getMetadata('uri'));
115    }
116
117    public function testWrapsWrites()
118    {
119        $this->b->seek(0, SEEK_END);
120        $this->b->write('foo');
121        $this->assertEquals('foofoo', (string) $this->a);
122    }
123
124    /**
125     * @expectedException \UnexpectedValueException
126     */
127    public function testThrowsWithInvalidGetter()
128    {
129        $this->b->foo;
130    }
131
132    /**
133     * @expectedException \BadMethodCallException
134     */
135    public function testThrowsWhenGetterNotImplemented()
136    {
137        $s = new BadStream();
138        $s->stream;
139    }
140}
141
142class BadStream
143{
144    use StreamDecoratorTrait;
145
146    public function __construct() {}
147}
148