Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 203
0.00% covered (danger)
0.00%
0 / 16
CRAP
0.00% covered (danger)
0.00%
0 / 1
AppStatsTest
0.00% covered (danger)
0.00%
0 / 202
0.00% covered (danger)
0.00%
0 / 16
552
0.00% covered (danger)
0.00%
0 / 1
 setUpBeforeClass
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
6
 tearDownAfterClass
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 testStatsDefaultValues
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 iterateObjectCheck0
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
42
 testAppstatsMinute0
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsMinute1
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsHour0
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsDay0
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsMonth0
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsLimit0
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsLimit1
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsPagination0
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsPagination1
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsPagination2
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 testAppstatsPagination3
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 testPaginationDefaults
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2namespace tests;
3use Ably\AblyRest;
4
5require_once __DIR__ . '/factories/TestApp.php';
6
7class AppStatsTest extends \PHPUnit_Framework_TestCase {
8
9    protected static $testApp;
10    protected static $defaultOptions;
11    protected static $ably;
12    protected static $timestamp;
13    protected static $timestampOlder;
14    protected static $timestampMs;
15    protected static $timestampOlderMs;
16
17    public static function setUpBeforeClass() {
18        self::$testApp = new TestApp();
19        self::$defaultOptions = self::$testApp->getOptions();
20        self::$ably = new AblyRest( array_merge( self::$defaultOptions, [
21            'key' => self::$testApp->getAppKeyDefault()->string,
22        ] ) );
23
24        self::$timestamp = strtotime( "first day of -1 month 14:00:00" );
25        self::$timestampOlder = strtotime( "first day of -2 month 14:00:00" );
26        self::$timestampMs = self::$timestamp * 1000;
27        self::$timestampOlderMs = self::$timestampOlder * 1000;
28
29        $fixtureEntries = [
30            '{
31                "intervalId": "' . gmdate( 'Y-m-d:H:i', self::$timestamp ) . '",
32                "inbound":  { "realtime": { "messages": { "count": 50, "data": 5000 } } },
33                "outbound": { "realtime": { "messages": { "count": 20, "data": 2000 } } }
34            }',
35            '{
36                "intervalId": "' . gmdate( 'Y-m-d:H:i', self::$timestamp + 60 ) . '",
37                "inbound":  { "realtime": { "messages": { "count": 60, "data": 6000 } } },
38                "outbound": { "realtime": { "messages": { "count": 10, "data": 1000 } } }
39            }',
40            '{
41                "intervalId": "' . gmdate( 'Y-m-d:H:i', self::$timestamp + 120 ) . '",
42                "inbound":       { "realtime": { "messages": { "count": 70, "data": 7000 } } },
43                "outbound":      { "realtime": { "messages": { "count": 40, "data": 4000 } } },
44                "persisted":     { "presence": { "count": 20, "data": 2000 } },
45                "connections":   { "tls":      { "peak": 20,  "opened": 10 } },
46                "channels":      { "peak": 50, "opened": 30 },
47                "apiRequests":   { "succeeded": 50, "failed": 10 },
48                "tokenRequests": { "succeeded": 60, "failed": 20 }
49            }',
50        ];
51
52        for ($i = 0; $i < 101; $i++) {
53            $fixtureEntries[] = '{
54                "intervalId": "' . gmdate( 'Y-m-d:H:i', self::$timestampOlder + $i * 60 ) . '",
55                "channels":      { "peak": ' . ($i + 1) . ', "opened": 1 }
56            }';
57        }
58
59        $fixtureJSON = "[\n" . implode( ",\n", $fixtureEntries ) . "\n]";
60
61        self::$ably->post( '/stats', [], $fixtureJSON );
62    }
63
64    public static function tearDownAfterClass() {
65        self::$testApp->release();
66    }
67
68    /**
69     * Check if stats are automatically populated by zeroes
70     */
71    public function testStatsDefaultValues() {
72        $stats = new \Ably\Models\Stats();
73        $this->assertTrue( $this->iterateObjectCheck0( $stats ), 'Expected newly created Stats to have zero values.' );
74    }
75
76    protected function iterateObjectCheck0($obj, $level = 0) {
77        $valid = true;
78
79        foreach ($obj as $key => $value) {
80            if (is_object($value)) {
81                if (!$this->iterateObjectCheck0($value, $level + 1)) $valid = false;
82            } else {
83                if ($level > 0 && $value !== 0) $valid = false;
84            }
85        }
86
87        return $valid;
88    }
89
90    /**
91     * Check minute-level stats exist (forwards)
92     */
93    public function testAppstatsMinute0() {
94        $oneMinuteMs = 60 * 1000;
95        $twoMinutesMs = 120 * 1000;
96        // get the stats for this channel 
97        // note that bounds are inclusive 
98        $stats = self::$ably->stats([
99            "direction" => "forwards",
100            "start" => self::$timestampMs,
101            "end" => self::$timestampMs
102        ]);
103        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
104        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
105
106        $stats = self::$ably->stats([
107            "direction" => "forwards",
108            "start" => self::$timestampMs + $oneMinuteMs,
109            "end" => self::$timestampMs + $oneMinuteMs
110        ]);
111        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
112        $this->assertEquals( 60, $stats->items[0]->inbound->all->all->count, "Expected 60 messages" );
113
114        $stats = self::$ably->stats([
115            "direction" => "forwards",
116            "start" => self::$timestampMs + $twoMinutesMs,
117            "end" => self::$timestampMs + $twoMinutesMs
118        ]);
119        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
120        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
121    }
122
123    /**
124     * Check minute-level stats exist (backwards)
125     */
126    public function testAppstatsMinute1() {
127        $oneMinuteMs = 60 * 1000;
128        $twoMinutesMs = 120 * 1000;
129        // get the stats for this channel 
130        // note that bounds are inclusive 
131        $stats = self::$ably->stats([
132            "direction" => "backwards",
133            "start" => self::$timestampMs,
134            "end" => self::$timestampMs
135        ]);
136        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
137        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
138
139        $stats = self::$ably->stats([
140            "direction" => "backwards",
141            "start" => self::$timestampMs + $oneMinuteMs,
142            "end" => self::$timestampMs + $oneMinuteMs
143        ]);
144        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
145        $this->assertEquals( 60, $stats->items[0]->inbound->all->all->count, "Expected 60 messages" );
146
147        $stats = self::$ably->stats([
148            "direction" => "backwards",
149            "start" => self::$timestampMs + $twoMinutesMs,
150            "end" => self::$timestampMs + $twoMinutesMs
151        ]);
152        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
153        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
154    }
155
156    /**
157     * Check hour-level stats exist (forwards)
158     */
159    public function testAppstatsHour0() {
160        $twoMinutesMs = 120 * 1000;
161        $stats = self::$ably->stats([
162            "direction" => "forwards",
163            "start" => self::$timestampMs,
164            "end" => self::$timestampMs + $twoMinutesMs,
165            "unit" => "hour"
166        ]);
167        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
168        $this->assertEquals( 180, $stats->items[0]->inbound->all->all->count, "Expected 180 messages" );
169    }
170
171    /**
172     * Check day-level stats exist (forwards)
173     */
174    public function testAppstatsDay0() {
175        $twoMinutesMs = 120 * 1000;
176        $stats = self::$ably->stats([
177            "direction" => "forwards",
178            "start" => self::$timestampMs,
179            "end" => self::$timestampMs + $twoMinutesMs,
180            "unit" => "day"
181        ]);
182        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
183        $this->assertEquals( 180, $stats->items[0]->inbound->all->all->count, "Expected 180 messages" );
184    }
185
186    /**
187     * Check month-level stats exist (forwards)
188     */
189    public function testAppstatsMonth0() {
190        $twoMinutesMs = 120 * 1000;
191        $stats = self::$ably->stats([
192            "direction" => "forwards",
193            "start" => self::$timestampMs,
194            "end" => self::$timestampMs + $twoMinutesMs,
195            "unit" => "month"
196        ]);
197
198        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
199        $this->assertEquals( 180, $stats->items[0]->inbound->all->all->count, "Expected 180 messages" );
200    }
201
202    /**
203     * Publish events and check limit query param (backwards)
204     */
205    public function testAppstatsLimit0() {
206        $twoMinutesMs = 120 * 1000;
207        $stats = self::$ably->stats([
208            "direction" => "backwards",
209            "start" => self::$timestampMs,
210            "end" => self::$timestampMs + $twoMinutesMs,
211            "limit" => 1
212        ]);
213        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
214        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
215    }
216
217    /**
218     * Check limit query param (forwards)
219     */
220    public function testAppstatsLimit1() {
221        $twoMinutesMs = 120 * 1000;
222        $stats = self::$ably->stats([
223            "direction" => "forwards",
224            "start" => self::$timestampMs,
225            "end" => self::$timestampMs + $twoMinutesMs,
226            "limit" => 1
227        ]);
228        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
229        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
230    }
231
232    /**
233     * Check query pagination (backwards)
234     */
235    public function testAppstatsPagination0() {
236        $twoMinutesMs = 120 * 1000;
237        $stats = self::$ably->stats([
238            "direction" => "backwards",
239            "start" => self::$timestampMs,
240            "end" => self::$timestampMs + $twoMinutesMs,
241            "limit" => 1
242        ]);
243        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
244        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
245        // get next page 
246        $stats = $stats->next();
247        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
248        $this->assertEquals( 60, $stats->items[0]->inbound->all->all->count, "Expected 60 messages" );
249        // get next page 
250        $stats = $stats->next();
251        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
252        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
253        // verify that there is no next page 
254        $this->assertFalse( $stats->hasNext(), "Expected not to have next page" );
255        $this->assertNull( $stats->next(), "Expected null next page" );
256    }
257
258    /**
259     * Check query pagination (forwards)
260     */
261    public function testAppstatsPagination1() {
262        $twoMinutesMs = 120 * 1000;
263        $stats = self::$ably->stats([
264            "direction" => "forwards",
265            "start" => self::$timestampMs,
266            "end" => self::$timestampMs + $twoMinutesMs,
267            "limit" => 1
268        ]);
269        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
270        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
271        // get next page 
272        $stats = $stats->next();
273        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
274        $this->assertEquals( 60, $stats->items[0]->inbound->all->all->count, "Expected 60 messages" );
275        // get next page 
276        $stats = $stats->next();
277        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
278        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
279        // verify that there is no next page 
280        $this->assertFalse( $stats->hasNext(), "Expected not to have next page" );
281        $this->assertNull( $stats->next(), "Expected null next page" );
282    }
283
284    /**
285     * Check query pagination rel="first" (backwards)
286     */
287    public function testAppstatsPagination2() {
288        $twoMinutesMs = 120 * 1000;
289        $stats = self::$ably->stats([
290            "direction" => "backwards",
291            "start" => self::$timestampMs,
292            "end" => self::$timestampMs + $twoMinutesMs,
293            "limit" => 1
294        ]);
295        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
296        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
297        // get next page 
298        $stats = $stats->next();
299        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
300        $this->assertEquals( 60, $stats->items[0]->inbound->all->all->count, "Expected 60 messages" );
301        // get first page 
302        $stats = $stats->first();
303        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
304        $this->assertEquals( 70, $stats->items[0]->inbound->all->all->count, "Expected 70 messages" );
305    }
306
307    /**
308     * Check query pagination rel="first" (forwards)
309     */
310    public function testAppstatsPagination3() {
311        $twoMinutesMs = 120 * 1000;
312        $stats = self::$ably->stats([
313            "direction" => "forwards",
314            "start" => self::$timestampMs,
315            "end" => self::$timestampMs + $twoMinutesMs,
316            "limit" => 1
317        ]);
318        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
319        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
320        // get next page 
321        $stats = $stats->next();
322        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
323        $this->assertEquals( 60, $stats->items[0]->inbound->all->all->count, "Expected 60 messages" );
324        // get first page 
325        $stats = $stats->first();
326        $this->assertEquals( 1, count( $stats->items ), "Expected 1 record" );
327        $this->assertEquals( 50, $stats->items[0]->inbound->all->all->count, "Expected 50 messages" );
328    }
329
330    /**
331     * Verify default pagination limit (100), direction (backwards) and unit (minute)
332     */
333    public function testPaginationDefaults () {
334        $twoHoursMs = 120 * 60 * 1000;
335        $stats = self::$ably->stats([
336            "start" => self::$timestampOlderMs,
337            "end" => self::$timestampOlderMs + $twoHoursMs,
338        ]);
339        $this->assertEquals( 100, count( $stats->items ), "Expected 100 records" );
340 
341        // verify order
342        $actualRecordsPeakData = [];
343        foreach ($stats->items as $minute) {
344            $actualRecordsPeakData[] = (int) $minute->channels->peak;
345        }
346        $expectedData = range( 101, 2, -1 );
347        $this->assertEquals( $expectedData, $actualRecordsPeakData, 'Expected records in backward order' );
348    }
349}