AdaptersTest::provideAdapters()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 4
c 2
b 0
f 1
dl 0
loc 6
rs 10
cc 1
nc 1
nop 0
1
<?php declare(strict_types=1);
2
3
use LeoCarmo\CircuitBreaker\Adapters\AdapterInterface;
4
use LeoCarmo\CircuitBreaker\Adapters\RedisClusterAdapter;
5
use LeoCarmo\CircuitBreaker\Adapters\SwooleTableAdapter;
6
use LeoCarmo\CircuitBreaker\CircuitBreaker;
7
use LeoCarmo\CircuitBreaker\Adapters\RedisAdapter;
8
use PHPUnit\Framework\TestCase;
9
10
class AdaptersTest extends TestCase
11
{
12
    public function testCreateRedisAdapter()
13
    {
14
        $redis = new \Redis();
15
        $redis->connect(getenv('REDIS_HOST'));
16
        $adapter = new RedisAdapter($redis, 'my-product');
17
18
        $this->assertInstanceOf(AdapterInterface::class, $adapter);
19
20
        return $adapter;
21
    }
22
23
    public function testCreateRedisClusterAdapter()
24
    {
25
        $redis = new \Redis();
26
        $redis->connect(getenv('REDIS_HOST'));
27
        $adapter = new RedisClusterAdapter($redis, 'my-product');
28
29
        $this->assertInstanceOf(AdapterInterface::class, $adapter);
30
31
        return $adapter;
32
    }
33
34
    public function testCreateSwooleTableAdapter()
35
    {
36
        $adapter = new SwooleTableAdapter();
37
        $this->assertInstanceOf(AdapterInterface::class, $adapter);
38
        return $adapter;
39
    }
40
41
    public function provideAdapters()
42
    {
43
        return [
44
            'redis' => [$this->testCreateRedisAdapter()],
45
            'redis-cluster' => [$this->testCreateRedisClusterAdapter()],
46
            'swoole-table' => [$this->testCreateSwooleTableAdapter()],
47
        ];
48
    }
49
50
    /**
51
     * @dataProvider provideAdapters
52
     */
53
    public function testSetAdapter(AdapterInterface $adapter)
54
    {
55
        $circuitBreaker = new CircuitBreaker($adapter, 'testSetAdapter');
56
57
        $this->assertInstanceOf(AdapterInterface::class, $circuitBreaker->getAdapter());
58
    }
59
60
    /**
61
     * @dataProvider provideAdapters
62
     */
63
    public function testOpenCircuit(AdapterInterface $adapter)
64
    {
65
        $circuitBreaker = new CircuitBreaker($adapter, 'testOpenCircuit');
66
67
        $circuitBreaker->setSettings([
68
            'timeWindow' => 20,
69
            'failureRateThreshold' => 5,
70
            'intervalToHalfOpen' => 10,
71
        ]);
72
73
        $circuitBreaker->failure();
74
        $circuitBreaker->failure();
75
        $circuitBreaker->failure();
76
        $circuitBreaker->failure();
77
        $circuitBreaker->failure();
78
79
        $this->assertFalse($circuitBreaker->isAvailable());
80
    }
81
82
    /**
83
     * @dataProvider provideAdapters
84
     */
85
    public function testReachFailureRateAfterTimeWindow(AdapterInterface $adapter)
86
    {
87
        $circuitBreaker = new CircuitBreaker($adapter, 'testReachFailureRateAfterTimeWindow');
88
89
        $circuitBreaker->setSettings([
90
            'timeWindow' => 2,
91
            'failureRateThreshold' => 2,
92
            'intervalToHalfOpen' => 10,
93
        ]);
94
95
        $circuitBreaker->failure();
96
        $circuitBreaker->failure();
97
        $circuitBreaker->failure();
98
99
        sleep(3);
100
101
        $this->assertTrue($circuitBreaker->isAvailable());
102
    }
103
104
    /**
105
     * @dataProvider provideAdapters
106
     */
107
    public function testCloseCircuitSuccess(AdapterInterface $adapter)
108
    {
109
        $circuitBreaker = new CircuitBreaker($adapter, 'testCloseCircuitSuccess');
110
111
        $circuitBreaker->setSettings([
112
            'timeWindow' => 20,
113
            'failureRateThreshold' => 1,
114
            'intervalToHalfOpen' => 10,
115
        ]);
116
117
        $circuitBreaker->failure();
118
        $circuitBreaker->failure();
119
120
        $this->assertFalse($circuitBreaker->isAvailable());
121
122
        $circuitBreaker->success();
123
124
        $this->assertTrue($circuitBreaker->isAvailable());
125
    }
126
127
    /**
128
     * @dataProvider provideAdapters
129
     */
130
    public function testHalfOpenFailAndOpenCircuit(AdapterInterface $adapter)
131
    {
132
        $circuitBreaker = new CircuitBreaker($adapter, 'testHalfOpenFailAndOpenCircuit');
133
134
        $circuitBreaker->setSettings([
135
            'timeWindow' => 1,
136
            'failureRateThreshold' => 3,
137
            'intervalToHalfOpen' => 15,
138
        ]);
139
140
        $circuitBreaker->failure();
141
        $circuitBreaker->failure();
142
        $circuitBreaker->failure();
143
144
        // Check if is available for open circuit
145
        $this->assertFalse($circuitBreaker->isAvailable());
146
147
        // Sleep for half open
148
        sleep(2);
149
150
        // Register new failure
151
        $circuitBreaker->failure();
152
153
        // Check if is open
154
        $this->assertFalse($circuitBreaker->isAvailable());
155
    }
156
}
157