#!perl

use strict;
use warnings;
use Test::More;
use Test::Fatal;
use Redis::Fast;
use lib 't/tlib';
use Test::SpawnRedisTimeoutServer;
use Errno qw(ETIMEDOUT EWOULDBLOCK);
use POSIX qw(strerror);
use Carp;
use IO::Socket::INET;
use Test::TCP;

subtest 'server replies quickly enough' => sub {
    my $server = Test::SpawnRedisTimeoutServer::create_server_with_timeout(0);
    my $redis = Redis::Fast->new(server => '127.0.0.1:' . $server->port, read_timeout => 1);
    ok($redis);
    my $res = $redis->get('foo');;
    is $res, 42;
};

subtest "server doesn't replies quickly enough" => sub {
    my $server = Test::SpawnRedisTimeoutServer::create_server_with_timeout(10);
    my $redis = Redis::Fast->new(server => '127.0.0.1:' . $server->port, read_timeout => 1);
    ok($redis);
    like(
         exception { $redis->get('foo'); },
         qr/Error while reading from Redis server: /,
         "the code died as expected",
        );
    ok($! == ETIMEDOUT || $! == EWOULDBLOCK);
};

subtest "server doesn't respond at connection (cnx_timeout)" => sub {
  SKIP: {
    skip "This subtest is failing on some platforms", 4;
	my $server = Test::TCP->new(code => sub {
			my $port = shift;
			my $sock = IO::Socket::INET->new(Listen => 1, LocalPort => $port, Proto => 'tcp', LocalAddr => '127.0.0.1') or croak "fail to listen on port $port";
			while(1) {
				sleep(1);
			};
	});

    my $redis;
    my $start_time = time;
    isnt(
         exception { $redis = Redis::Fast->new(server => '127.0.0.1:' . $server->port, cnx_timeout => 1); },
         undef,
         "the code died",
        );
    ok(time - $start_time >= 1, "gave up late enough");
    ok(time - $start_time < 5, "gave up soon enough");
    ok(!$redis, 'redis was not set');
  }
};

subtest "server doesn't respond at connection with unreachable server (cnx_timeout)" => sub {
    my $redis;
    my $start_time = time;

    # $server is one of example IP addresses.
    # it is reserved for documentation, so unreachable.
    my $server = "192.0.2.1:9998";

    isnt(
         exception { $redis = Redis::Fast->new(server => $server, cnx_timeout => 1); },
         undef,
         "the code died",
        );
    ok(time - $start_time >= 1, "gave up late enough");
    ok(time - $start_time < 5, "gave up soon enough");
    ok(!$redis, 'redis was not set');
};

done_testing;

