1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\Stopwatch\Tests;
13
14use PHPUnit\Framework\TestCase;
15use Symfony\Component\Stopwatch\Stopwatch;
16
17/**
18 * StopwatchTest.
19 *
20 * @author Fabien Potencier <fabien@symfony.com>
21 *
22 * @group time-sensitive
23 */
24class StopwatchTest extends TestCase
25{
26    const DELTA = 20;
27
28    public function testStart()
29    {
30        $stopwatch = new Stopwatch();
31        $event = $stopwatch->start('foo', 'cat');
32
33        $this->assertInstanceOf('Symfony\Component\Stopwatch\StopwatchEvent', $event);
34        $this->assertEquals('cat', $event->getCategory());
35        $this->assertSame($event, $stopwatch->getEvent('foo'));
36    }
37
38    public function testStartWithoutCategory()
39    {
40        $stopwatch = new Stopwatch();
41        $stopwatchEvent = $stopwatch->start('bar');
42        $this->assertSame('default', $stopwatchEvent->getCategory());
43        $this->assertSame($stopwatchEvent, $stopwatch->getEvent('bar'));
44    }
45
46    public function testIsStarted()
47    {
48        $stopwatch = new Stopwatch();
49        $stopwatch->start('foo', 'cat');
50
51        $this->assertTrue($stopwatch->isStarted('foo'));
52    }
53
54    public function testIsNotStarted()
55    {
56        $stopwatch = new Stopwatch();
57
58        $this->assertFalse($stopwatch->isStarted('foo'));
59    }
60
61    public function testIsNotStartedEvent()
62    {
63        $stopwatch = new Stopwatch();
64
65        $sections = new \ReflectionProperty('Symfony\Component\Stopwatch\Stopwatch', 'sections');
66        $sections->setAccessible(true);
67        $section = $sections->getValue($stopwatch);
68
69        $events = new \ReflectionProperty('Symfony\Component\Stopwatch\Section', 'events');
70        $events->setAccessible(true);
71
72        $stopwatchMockEvent = $this->getMockBuilder('Symfony\Component\Stopwatch\StopwatchEvent')
73            ->setConstructorArgs([microtime(true) * 1000])
74            ->getMock()
75        ;
76
77        $events->setValue(end($section), ['foo' => $stopwatchMockEvent]);
78
79        $this->assertFalse($stopwatch->isStarted('foo'));
80    }
81
82    public function testStop()
83    {
84        $stopwatch = new Stopwatch();
85        $stopwatch->start('foo', 'cat');
86        usleep(200000);
87        $event = $stopwatch->stop('foo');
88
89        $this->assertInstanceOf('Symfony\Component\Stopwatch\StopwatchEvent', $event);
90        $this->assertEqualsWithDelta(200, $event->getDuration(), self::DELTA);
91    }
92
93    public function testUnknownEvent()
94    {
95        $this->expectException('LogicException');
96        $stopwatch = new Stopwatch();
97        $stopwatch->getEvent('foo');
98    }
99
100    public function testStopWithoutStart()
101    {
102        $this->expectException('LogicException');
103        $stopwatch = new Stopwatch();
104        $stopwatch->stop('foo');
105    }
106
107    public function testMorePrecision()
108    {
109        $stopwatch = new Stopwatch(true);
110
111        $stopwatch->start('foo');
112        $event = $stopwatch->stop('foo');
113
114        $this->assertIsFloat($event->getStartTime());
115        $this->assertIsFloat($event->getEndTime());
116        $this->assertIsFloat($event->getDuration());
117    }
118
119    public function testSection()
120    {
121        $stopwatch = new Stopwatch();
122
123        $stopwatch->openSection();
124        $stopwatch->start('foo', 'cat');
125        $stopwatch->stop('foo');
126        $stopwatch->start('bar', 'cat');
127        $stopwatch->stop('bar');
128        $stopwatch->stopSection('1');
129
130        $stopwatch->openSection();
131        $stopwatch->start('foobar', 'cat');
132        $stopwatch->stop('foobar');
133        $stopwatch->stopSection('2');
134
135        $stopwatch->openSection();
136        $stopwatch->start('foobar', 'cat');
137        $stopwatch->stop('foobar');
138        $stopwatch->stopSection('0');
139
140        // the section is an event by itself
141        $this->assertCount(3, $stopwatch->getSectionEvents('1'));
142        $this->assertCount(2, $stopwatch->getSectionEvents('2'));
143        $this->assertCount(2, $stopwatch->getSectionEvents('0'));
144    }
145
146    public function testReopenASection()
147    {
148        $stopwatch = new Stopwatch();
149
150        $stopwatch->openSection();
151        $stopwatch->start('foo', 'cat');
152        $stopwatch->stopSection('section');
153
154        $stopwatch->openSection('section');
155        $stopwatch->start('bar', 'cat');
156        $stopwatch->stopSection('section');
157
158        $events = $stopwatch->getSectionEvents('section');
159
160        $this->assertCount(3, $events);
161        $this->assertCount(2, $events['__section__']->getPeriods());
162    }
163
164    public function testReopenANewSectionShouldThrowAnException()
165    {
166        $this->expectException('LogicException');
167        $stopwatch = new Stopwatch();
168        $stopwatch->openSection('section');
169    }
170
171    public function testReset()
172    {
173        $stopwatch = new Stopwatch();
174
175        $stopwatch->openSection();
176        $stopwatch->start('foo', 'cat');
177
178        $stopwatch->reset();
179
180        $this->assertEquals(new Stopwatch(), $stopwatch);
181    }
182}
183