getCommand(); $command->setArguments($actualArguments); $this->assertSameValues($expectedArguments, $command->getArguments()); } /** * @group disconnected */ public function testParseResponse(): void { $this->assertSame(1, $this->getCommand()->parseResponse(1)); } /** * @group disconnected * @dataProvider parseResponseProvider */ public function testParseResponsePassesThroughSingleAndMultipleAggregatorResults(array $response): void { $this->assertSame($response, $this->getCommand()->parseResponse($response)); } public function parseResponseProvider(): array { return [ 'single aggregator' => [ [[1000, '100'], [1020, '120']], ], 'multiple aggregators' => [ [[1000, '100', '200'], [1020, '120', '170']], ], ]; } /** * @group disconnected */ public function testPrefixKeys(): void { /** @var PrefixableCommand $command */ $command = $this->getCommand(); $actualArguments = ['arg1']; $prefix = 'prefix:'; $expectedArguments = ['prefix:arg1']; $command->setRawArguments($actualArguments); $command->prefixKeys($prefix); $this->assertSame($expectedArguments, $command->getArguments()); } /** * @group connected * @group relay-resp3 * @return void * @requiresRedisTimeSeriesVersion >= 1.0.0 */ public function testReturnsQueriedRangeInForwardDirectionFromGivenTimeSeries(): void { $redis = $this->getClient(); $createArguments = (new CreateArguments())->labels('type', 'temp', 'location', 'TLV'); $this->assertEquals('OK', $redis->tscreate('temp:TLV', $createArguments)); $this->assertSame( [1000, 1010, 1020, 1030], $redis->tsmadd('temp:TLV', 1000, 30, 'temp:TLV', 1010, 35, 'temp:TLV', 1020, 9999, 'temp:TLV', 1030, 40) ); $rangeArguments = (new RangeArguments())->filterByValue(-100, 100); $this->assertEquals( [[1000, '30'], [1010, '35'], [1030, '40']], $redis->tsrange('temp:TLV', '-', '+', $rangeArguments) ); } /** * @group connected * @return void * @requiresRedisTimeSeriesVersion >= 1.0.0 */ public function testReturnsQueriedRangeInForwardDirectionFromGivenTimeSeriesResp3(): void { $redis = $this->getResp3Client(); $createArguments = (new CreateArguments())->labels('type', 'temp', 'location', 'TLV'); $this->assertEquals('OK', $redis->tscreate('temp:TLV', $createArguments)); $this->assertSame( [1000, 1010, 1020, 1030], $redis->tsmadd('temp:TLV', 1000, 30, 'temp:TLV', 1010, 35, 'temp:TLV', 1020, 9999, 'temp:TLV', 1030, 40) ); $rangeArguments = (new RangeArguments())->filterByValue(-100, 100); $this->assertEquals( [[1000, '30'], [1010, '35'], [1030, '40']], $redis->tsrange('temp:TLV', '-', '+', $rangeArguments) ); } /** * @group connected * @group relay-resp3 * @return void * @requiresRedisVersion >= 8.5.0 */ public function testAddSampleIntoTimeSeriesWithNaNValues(): void { $redis = $this->getClient(); $createArguments = (new CreateArguments()) ->retentionMsecs(31536000000) ->duplicatePolicy(CommonArguments::POLICY_LAST) ->ignore(10, 10); $this->assertEquals('OK', $redis->tscreate('temperature:2:32', $createArguments)); // Add NaN value samples $this->assertEquals( 1000, $redis->tsadd('temperature:2:32', 1000, 'NaN') ); $this->assertEquals( 1003, $redis->tsadd('temperature:2:32', 1003, 25) ); $this->assertEquals( 1005, $redis->tsadd('temperature:2:32', 1005, 'NaN') ); $this->assertEquals( 1006, $redis->tsadd('temperature:2:32', 1006, 'NaN') ); // Ensure that we can count NaN values only $rangeArguments = (new RangeArguments()) ->aggregation(RangeArguments::AGG_COUNT_NAN, 1000); $this->assertEquals( [[1000, 3]], $redis->tsrange('temperature:2:32', 1000, 1006, $rangeArguments) ); // Ensure that we can count all values (included NaN) $rangeArguments = (new RangeArguments()) ->aggregation(RangeArguments::AGG_COUNT_ALL, 1000); $this->assertEquals( [[1000, 4]], $redis->tsrange('temperature:2:32', 1000, 1006, $rangeArguments) ); } /** * @group connected * @group relay-resp3 * @return void * @requiresRedisVersion >= 8.7.2 */ public function testReturnsQueriedRangeWithMultipleAggregators(): void { $redis = $this->getClient(); $createArguments = (new CreateArguments())->labels('type', 'stock', 'name', 'A'); $this->assertEquals('OK', $redis->tscreate('stock:A', $createArguments)); $this->assertSame( [1000, 1010, 1020], $redis->tsmadd('stock:A', 1000, 100, 'stock:A', 1010, 110, 'stock:A', 1020, 120) ); $rangeArguments = (new RangeArguments()) ->aggregation([RangeArguments::AGG_MIN, RangeArguments::AGG_MAX], 1000); $response = $redis->tsrange('stock:A', '-', '+', $rangeArguments); $this->assertCount(1, $response); $this->assertCount(3, $response[0]); $this->assertSame(1000, $response[0][0]); } /** * @group connected * @group relay-resp3 * @return void * @requiresRedisTimeSeriesVersion >= 1.0.0 */ public function testThrowsExceptionOnNonExistingKey(): void { $redis = $this->getClient(); $this->expectException(ServerException::class); $this->expectExceptionMessage('ERR TSDB: the key does not exist'); $redis->tsrange('non_existing_key', 1000, 1000); } public function argumentsProvider(): array { return [ 'with default arguments' => [ ['key', 10000, 10001], ['key', 10000, 10001], ], 'with LATEST modifier' => [ ['key', 10000, 10001, (new RangeArguments())->latest()], ['key', 10000, 10001, 'LATEST'], ], 'with FILTER_BY_TS modifier' => [ ['key', 10000, 10001, (new RangeArguments())->filterByTs(1000, 1001)], ['key', 10000, 10001, 'FILTER_BY_TS', 1000, 1001], ], 'with FILTER_BY_VALUE modifier' => [ ['key', 10000, 10001, (new RangeArguments())->filterByValue(1000, 1001)], ['key', 10000, 10001, 'FILTER_BY_VALUE', 1000, 1001], ], 'with COUNT modifier' => [ ['key', 10000, 10001, (new RangeArguments())->count(100)], ['key', 10000, 10001, 'COUNT', 100], ], 'with AGGREGATION modifier - default arguments' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation('sum', 100)], ['key', 10000, 10001, 'AGGREGATION', 'sum', 100], ], 'with AGGREGATION modifier - with ALIGN' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation('sum', 100, 100)], ['key', 10000, 10001, 'ALIGN', 100, 'AGGREGATION', 'sum', 100], ], 'with AGGREGATION modifier - with BUCKETTIMESTAMP' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation('sum', 100, 0, 1000)], ['key', 10000, 10001, 'AGGREGATION', 'sum', 100, 'BUCKETTIMESTAMP', 1000], ], 'with AGGREGATION modifier - with EMPTY' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation('sum', 100, 0, 0, true)], ['key', 10000, 10001, 'AGGREGATION', 'sum', 100, 'EMPTY'], ], 'with AGGREGATION modifier - multiple aggregators as array' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation(['min', 'max'], 100)], ['key', 10000, 10001, 'AGGREGATION', 'min,max', 100], ], 'with AGGREGATION modifier - multiple aggregators as string' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation('min,max', 100)], ['key', 10000, 10001, 'AGGREGATION', 'min,max', 100], ], 'with AGGREGATION modifier - multiple aggregators with all options' => [ ['key', 10000, 10001, (new RangeArguments())->aggregation(['min', 'max', 'avg'], 100, 10, 1000, true)], ['key', 10000, 10001, 'ALIGN', 10, 'AGGREGATION', 'min,max,avg', 100, 'BUCKETTIMESTAMP', 1000, 'EMPTY'], ], 'with all modifiers' => [ ['key', 10000, 10001, (new RangeArguments())->latest()->filterByTs(1000, 1001)->filterByValue(1000, 1001)->count(100)->aggregation('sum', 100)], ['key', 10000, 10001, 'LATEST', 'FILTER_BY_TS', 1000, 1001, 'FILTER_BY_VALUE', 1000, 1001, 'COUNT', 100, 'AGGREGATION', 'sum', 100], ], ]; } }