1<?php
2namespace GuzzleHttp\Tests\Stream;
3
4use GuzzleHttp\Stream\FnStream;
5use GuzzleHttp\Stream\NoSeekStream;
6use GuzzleHttp\Stream\Stream;
7use GuzzleHttp\Stream\Utils;
8
9class UtilsTest extends \PHPUnit_Framework_TestCase
10{
11    public function testCopiesToString()
12    {
13        $s = Stream::factory('foobaz');
14        $this->assertEquals('foobaz', Utils::copyToString($s));
15        $s->seek(0);
16        $this->assertEquals('foo', Utils::copyToString($s, 3));
17        $this->assertEquals('baz', Utils::copyToString($s, 3));
18        $this->assertEquals('', Utils::copyToString($s));
19    }
20
21    public function testCopiesToStringStopsWhenReadFails()
22    {
23        $s1 = Stream::factory('foobaz');
24        $s1 = FnStream::decorate($s1, [
25            'read' => function () {
26                return false;
27            }
28        ]);
29        $result = Utils::copyToString($s1);
30        $this->assertEquals('', $result);
31    }
32
33    public function testCopiesToStream()
34    {
35        $s1 = Stream::factory('foobaz');
36        $s2 = Stream::factory('');
37        Utils::copyToStream($s1, $s2);
38        $this->assertEquals('foobaz', (string) $s2);
39        $s2 = Stream::factory('');
40        $s1->seek(0);
41        Utils::copyToStream($s1, $s2, 3);
42        $this->assertEquals('foo', (string) $s2);
43        Utils::copyToStream($s1, $s2, 3);
44        $this->assertEquals('foobaz', (string) $s2);
45    }
46
47    public function testStopsCopyToStreamWhenWriteFails()
48    {
49        $s1 = Stream::factory('foobaz');
50        $s2 = Stream::factory('');
51        $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
52        Utils::copyToStream($s1, $s2);
53        $this->assertEquals('', (string) $s2);
54    }
55
56    public function testStopsCopyToSteamWhenWriteFailsWithMaxLen()
57    {
58        $s1 = Stream::factory('foobaz');
59        $s2 = Stream::factory('');
60        $s2 = FnStream::decorate($s2, ['write' => function () { return 0; }]);
61        Utils::copyToStream($s1, $s2, 10);
62        $this->assertEquals('', (string) $s2);
63    }
64
65    public function testStopsCopyToSteamWhenReadFailsWithMaxLen()
66    {
67        $s1 = Stream::factory('foobaz');
68        $s1 = FnStream::decorate($s1, ['read' => function () { return ''; }]);
69        $s2 = Stream::factory('');
70        Utils::copyToStream($s1, $s2, 10);
71        $this->assertEquals('', (string) $s2);
72    }
73
74    public function testReadsLines()
75    {
76        $s = Stream::factory("foo" . PHP_EOL . "baz" . PHP_EOL . "bar");
77        $this->assertEquals("foo" . PHP_EOL, Utils::readline($s));
78        $this->assertEquals("baz" . PHP_EOL, Utils::readline($s));
79        $this->assertEquals("bar", Utils::readline($s));
80    }
81
82    public function testReadsLinesUpToMaxLength()
83    {
84        $s = Stream::factory("12345" . PHP_EOL);
85        $this->assertEquals("123", Utils::readline($s, 3));
86        $this->assertEquals("45" . PHP_EOL, Utils::readline($s));
87    }
88
89    public function testReadsLinesWithCustomEol()
90    {
91        $s = Stream::factory("foo\tbaz\t\tbar");
92        $this->assertEquals("foo\tbaz\t\t", Utils::readline($s, null, "\t\t"));
93        $this->assertEquals("bar", Utils::readline($s));
94    }
95
96    public function testReadsLineUntilFalseReturnedFromRead()
97    {
98        $s = $this->getMockBuilder('GuzzleHttp\Stream\Stream')
99            ->setMethods(['read', 'eof'])
100            ->disableOriginalConstructor()
101            ->getMock();
102        $s->expects($this->exactly(2))
103            ->method('read')
104            ->will($this->returnCallback(function () {
105                static $c = false;
106                if ($c) {
107                    return false;
108                }
109                $c = true;
110                return 'h';
111            }));
112        $s->expects($this->exactly(2))
113            ->method('eof')
114            ->will($this->returnValue(false));
115        $this->assertEquals("h", Utils::readline($s));
116    }
117
118    public function testCalculatesHash()
119    {
120        $s = Stream::factory('foobazbar');
121        $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
122    }
123
124    /**
125     * @expectedException \GuzzleHttp\Stream\Exception\SeekException
126     */
127    public function testCalculatesHashThrowsWhenSeekFails()
128    {
129        $s = new NoSeekStream(Stream::factory('foobazbar'));
130        $s->read(2);
131        Utils::hash($s, 'md5');
132    }
133
134    public function testCalculatesHashSeeksToOriginalPosition()
135    {
136        $s = Stream::factory('foobazbar');
137        $s->seek(4);
138        $this->assertEquals(md5('foobazbar'), Utils::hash($s, 'md5'));
139        $this->assertEquals(4, $s->tell());
140    }
141
142    public function testOpensFilesSuccessfully()
143    {
144        $r = Utils::open(__FILE__, 'r');
145        $this->assertInternalType('resource', $r);
146        fclose($r);
147    }
148
149    /**
150     * @expectedException \RuntimeException
151     * @expectedExceptionMessage Unable to open /path/to/does/not/exist using mode r
152     */
153    public function testThrowsExceptionNotWarning()
154    {
155        Utils::open('/path/to/does/not/exist', 'r');
156    }
157
158    public function testProxiesToFactory()
159    {
160        $this->assertEquals('foo', (string) Utils::create('foo'));
161    }
162}
163