testFailureRequestToUnknownHost()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 21
rs 9.8333
cc 2
nc 2
nop 0
1
<?php declare(strict_types=1);
2
3
use GuzzleHttp\Client;
4
use GuzzleHttp\Exception\ConnectException;
5
use GuzzleHttp\HandlerStack;
6
use LeoCarmo\CircuitBreaker\Adapters\SwooleTableAdapter;
7
use LeoCarmo\CircuitBreaker\CircuitBreaker;
8
use LeoCarmo\CircuitBreaker\CircuitBreakerException;
9
use LeoCarmo\CircuitBreaker\GuzzleMiddleware;
10
use PHPUnit\Framework\TestCase;
11
12
class GuzzleMiddlewareTest extends TestCase
13
{
14
    public function testSuccessRequest()
15
    {
16
        $circuit = new CircuitBreaker(new SwooleTableAdapter(), 'testSuccessRequest');
17
18
        // Set the first failure and the failure threshold
19
        $circuit->setSettings(['failureRateThreshold' => 2]);
20
        $circuit->failure();
21
22
        $handler = new GuzzleMiddleware($circuit);
23
        $handlers = HandlerStack::create();
24
        $handlers->push($handler);
25
26
        $client = new Client(['handler' => $handlers, 'verify' => false]);
27
        $response = $client->get('leocarmo.dev');
28
29
        // After a success response the failures must be reset and the circuit is available
30
        $this->assertEquals(200, $response->getStatusCode());
31
        $this->assertTrue($circuit->isAvailable());
32
33
        // Set another failure to ensure that the previous failure was reset and a new fail will not open the circuit
34
        $circuit->failure();
35
        $this->assertTrue($circuit->isAvailable());
36
    }
37
38
    public function testSuccessRequestWithCustomStatusCode()
39
    {
40
        $circuit = new CircuitBreaker(new SwooleTableAdapter(), 'testRequestWithCustomStatusCode');
41
42
        // Set the first failure and the failure threshold
43
        $circuit->setSettings(['failureRateThreshold' => 2]);
44
        $circuit->failure();
45
46
        $handler = new GuzzleMiddleware($circuit);
47
        $handler->setCustomSuccessCodes([403]);
48
49
        $handlers = HandlerStack::create();
50
        $handlers->push($handler);
51
52
        $client = new Client(['handler' => $handlers, 'verify' => false, 'http_errors' => false]);
53
54
        // After a success response the failures must be reset and the circuit is available
55
        $this->assertEquals(1, $circuit->getFailuresCounter());
56
        $response = $client->get('https://httpstat.us/403');
57
        $this->assertEquals(403, $response->getStatusCode());
58
        $this->assertEquals(0, $circuit->getFailuresCounter());
59
        $this->assertTrue($circuit->isAvailable());
60
61
        // Set another failure to ensure that the previous failure was reset and a new fail will not open the circuit
62
        $circuit->failure();
63
        $this->assertTrue($circuit->isAvailable());
64
    }
65
66
    public function testRequestWithIgnoredStatusCode()
67
    {
68
        $circuit = new CircuitBreaker(new SwooleTableAdapter(), 'testRequestWithCustomStatusCode');
69
70
        // Set the first failure and the failure threshold
71
        $circuit->setSettings(['failureRateThreshold' => 2]);
72
        $circuit->failure();
73
74
        $handler = new GuzzleMiddleware($circuit);
75
        $handler->setCustomIgnoreCodes([412]);
76
77
        $handlers = HandlerStack::create();
78
        $handlers->push($handler);
79
80
        $client = new Client(['handler' => $handlers, 'verify' => false, 'http_errors' => false]);
81
82
        // After an ignored status code, nothing will change on failure counter
83
        $this->assertEquals(1, $circuit->getFailuresCounter());
84
        $response = $client->get('https://httpstat.us/412');
85
        $this->assertEquals(412, $response->getStatusCode());
86
        $this->assertEquals(1, $circuit->getFailuresCounter());
87
        $this->assertTrue($circuit->isAvailable());
88
    }
89
90
    public function testCircuitIsNotAvailable()
91
    {
92
        $circuit = new CircuitBreaker(new SwooleTableAdapter(), 'testCircuitIsNotAvailable');
93
94
        $circuit->setSettings(['failureRateThreshold' => 2]);
95
        $circuit->failure();
96
        $circuit->failure();
97
98
        $this->assertEquals(2, $circuit->getFailuresCounter());
99
100
        $handler = new GuzzleMiddleware($circuit);
101
        $handlers = HandlerStack::create();
102
        $handlers->push($handler);
103
104
        $client = new Client(['handler' => $handlers, 'verify' => false]);
105
106
        $this->expectException(CircuitBreakerException::class);
107
108
        $client->get('leocarmo.dev');
109
    }
110
111
    public function testFailureRequest()
112
    {
113
        $circuit = new CircuitBreaker(new SwooleTableAdapter(), 'testFailureRequest');
114
115
        $circuit->setSettings(['failureRateThreshold' => 2]);
116
        $circuit->failure();
117
118
        $handler = new GuzzleMiddleware($circuit);
119
        $handlers = HandlerStack::create();
120
        $handlers->push($handler);
121
122
        $client = new Client(['handler' => $handlers, 'verify' => false]);
123
124
        $this->expectException(\GuzzleHttp\Exception\ClientException::class);
125
126
        $client->get('leocarmo.dev/undefined');
127
128
        $this->assertEquals(2, $circuit->getFailuresCounter());
129
        $this->assertFalse($circuit->isAvailable());
130
    }
131
132
    public function testFailureRequestToUnknownHost()
133
    {
134
        $circuit = new CircuitBreaker(new SwooleTableAdapter(), 'testFailureRequest');
135
136
        $circuit->setSettings(['failureRateThreshold' => 2]);
137
        $circuit->failure();
138
139
        $handler = new GuzzleMiddleware($circuit);
140
        $handlers = HandlerStack::create();
141
        $handlers->push($handler);
142
143
        $client = new Client(['handler' => $handlers, 'verify' => false]);
144
145
        try {
146
            $client->get('undefined_host.dev');
147
        } catch (\Throwable $exception) {
148
            $this->assertInstanceOf(ConnectException::class, $exception);
149
        }
150
151
        $this->assertEquals(2, $circuit->getFailuresCounter());
152
        $this->assertFalse($circuit->isAvailable());
153
    }
154
}