Passed
Push — master ( 8dceab...2d1996 )
by Benjamin
15:07 queued 12:31
created

TcpTransportTest   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 69
c 7
b 0
f 0
dl 0
loc 141
rs 10
wmc 11

10 Methods

Rating   Name   Duplication   Size   Complexity  
A testSslOptionsAreUsed() 0 15 1
A getTransport() 0 14 1
A testSafeEncoderSucceeds() 0 10 1
A setUp() 0 16 1
A testSend() 0 10 1
A testConstructor() 0 12 1
A testNonNullSafeEncoderFails() 0 4 1
A testConnectTimeout() 0 15 1
A validateTransport() 0 12 2
A testSetEncoder() 0 6 1
1
<?php
2
declare(strict_types=1);
3
4
/*
5
 * This file is part of the php-gelf package.
6
 *
7
 * (c) Benjamin Zikarsky <http://benjamin-zikarsky.de>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Gelf\Test\Transport;
14
15
use Gelf\Encoder\CompressedJsonEncoder;
16
use Gelf\Encoder\EncoderInterface;
17
use Gelf\Encoder\JsonEncoder;
18
use Gelf\Encoder\NoNullByteEncoderInterface;
19
use Gelf\MessageInterface;
20
use Gelf\Transport\StreamSocketClient;
21
use Gelf\Transport\TcpTransport;
22
use Gelf\Transport\SslOptions;
23
use InvalidArgumentException;
24
use PHPUnit\Framework\MockObject\MockObject;
25
use PHPUnit\Framework\TestCase;
26
use ReflectionObject;
27
28
class TcpTransportTest extends TestCase
29
{
30
    private MockObject|StreamSocketClient $socketClient;
31
    private MockObject|MessageInterface $message;
32
    private MockObject|EncoderInterface $encoder;
33
    private TcpTransport $transport;
34
    private string $testMessage;
35
36
    public function setUp(): void
37
    {
38
        $this->testMessage = str_repeat("0123456789", 30); // 300 char string
39
40
        $this->socketClient = $this->getMockBuilder(StreamSocketClient::class)
41
                ->disableOriginalConstructor()
42
                ->getMock();
43
        $this->message = $this->createMock(MessageInterface::class);
44
45
        // create an encoder always return $testMessage
46
        $this->encoder = $this->createMock(NoNullByteEncoderInterface::class);
47
        $this->encoder->expects($this->any())->method('encode')->will(
48
            $this->returnValue($this->testMessage)
49
        );
50
51
        $this->transport = $this->getTransport();
52
    }
53
54
    private function getTransport(): TcpTransport
55
    {
56
        // initialize transport with an unlimited packet-size
57
        // and the mocked message encoder
58
        $transport = new TcpTransport("", 0);
59
        $transport->setMessageEncoder($this->encoder);
60
61
        // replace internal stream socket client with our mock
62
        $reflectedTransport = new ReflectionObject($transport);
63
        $reflectedClient = $reflectedTransport->getProperty('socketClient');
64
        $reflectedClient->setAccessible(true);
65
        $reflectedClient->setValue($transport, $this->socketClient);
66
67
        return $transport;
68
    }
69
70
    public function testConstructor(): void
71
    {
72
        $transport = new TcpTransport();
73
        $this->validateTransport($transport, '127.0.0.1', 12201);
74
75
        $transport = new TcpTransport('test.local', 2202);
76
        $this->validateTransport($transport, 'test.local', 2202);
77
78
        // test defaults:
79
        //   port 12202 without explicit SSL options       => sslOptions: default
80
        $transport = new TcpTransport('localhost', 12202);
81
        $this->validateTransport($transport, 'localhost', 12202, new SslOptions());
82
    }
83
84
    public function validateTransport(
85
        TcpTransport $transport,
86
        $host,
87
        $port,
88
        $sslOptions = null
89
    ): void {
90
        $r = new ReflectionObject($transport);
91
92
        foreach (['host' => $host, 'port' => $port, 'sslOptions' => $sslOptions] as $test => $value) {
93
            $p = $r->getProperty($test);
94
            $p->setAccessible(true);
95
            self::assertEquals($value, $p->getValue($transport));
96
        }
97
    }
98
99
    public function testSslOptionsAreUsed(): void
100
    {
101
        $sslOptions = $this->createMock(SslOptions::class);
102
        $sslOptions->expects($this->exactly(2))
103
            ->method('toStreamContext')
104
            ->will($this->returnValue(['ssl' => null]));
105
106
        $transport = new TcpTransport("localhost", 12202, $sslOptions);
107
108
        $reflectedTransport = new ReflectionObject($transport);
109
        $reflectedGetContext = $reflectedTransport->getMethod('getContext');
110
        $reflectedGetContext->setAccessible(true);
111
        $context = $reflectedGetContext->invoke($transport);
112
113
        self::assertEquals(['ssl' => null], $context);
114
    }
115
116
    public function testSetEncoder(): void
117
    {
118
        $encoder = $this->createMock(NoNullByteEncoderInterface::class);
119
        $this->transport->setMessageEncoder($encoder);
120
121
        self::assertEquals($encoder, $this->transport->getMessageEncoder());
122
    }
123
124
    public function testSend(): void
125
    {
126
        $this->socketClient
127
            ->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects() does not exist on Gelf\Transport\StreamSocketClient. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

127
            ->/** @scrutinizer ignore-call */ 
128
              expects($this->once())

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
128
            ->method('write')
129
            // TCP protocol requires every message to be
130
            // terminated with \0
131
            ->with($this->testMessage . "\0");
132
133
        $this->transport->send($this->message);
134
    }
135
136
    public function testConnectTimeout(): void
137
    {
138
        $this->socketClient
139
            ->expects($this->once())
140
            ->method('getConnectTimeout')
141
            ->will($this->returnValue(123));
142
143
        self::assertEquals(123, $this->transport->getConnectTimeout());
144
145
        $this->socketClient
146
            ->expects($this->once())
147
            ->method('setConnectTimeout')
148
            ->with(123);
149
150
        $this->transport->setConnectTimeout(123);
151
    }
152
153
    public function testNonNullSafeEncoderFails(): void
154
    {
155
        self::expectException(InvalidArgumentException::class);
0 ignored issues
show
Bug Best Practice introduced by
The method PHPUnit\Framework\TestCase::expectException() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

155
        self::/** @scrutinizer ignore-call */ 
156
              expectException(InvalidArgumentException::class);
Loading history...
156
        $this->transport->setMessageEncoder(new CompressedJsonEncoder());
157
    }
158
159
    public function testSafeEncoderSucceeds(): void
160
    {
161
        $encoder = new JsonEncoder();
162
        self::assertInstanceOf(
163
            NoNullByteEncoderInterface::class,
164
            $encoder
165
        );
166
167
        $this->transport->setMessageEncoder($encoder);
168
        self::assertEquals($encoder, $this->transport->getMessageEncoder());
169
    }
170
}
171