Completed
Push — add_bdd ( a2de90...b6b949 )
by Anatoliy
05:17
created

PidFileTestCase::newTempFileName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
declare(strict_types=1);
3
/**
4
 * Created by PhpStorm.
5
 * User: danchukas
6
 * Date: 2017-07-17 21:51
7
 */
8
9
namespace DanchukAS\Mock;
10
11
use DanchukAS\DenyMultiplyRun\Exception\ConvertPidFail;
12
use DanchukAS\DenyMultiplyRun\Exception\LockFileFail;
13
use DanchukAS\DenyMultiplyRun\Exception\ProcessExisted;
14
use DanchukAS\Mock\TypeList\NotStringList;
15
use PHPUnit\Framework\TestCase;
16
17
/**
18
 * Class PidFileTestCase
19
 * included shared test settings.
20
 * @package DanchukAS\DenyMultiplyRunTest
21
 */
22
abstract class PidFileTestCase extends TestCase
23
{
24
    protected static $noExistFileName;
25
26
    protected static $existFileName;
27
28
    private static $tempFileList = [];
29
30
    private static $saveUntilEnd = [];
31
32
    /**
33
     * @return bool|string
34
     */
35
    public static function generateTempFile()
36
    {
37
        $tmp_file_res = \tmpfile();
38
        self::$saveUntilEnd[] = $tmp_file_res;
39
        return \stream_get_meta_data($tmp_file_res)['uri'];
40
    }
41
42
    public function setUp()
43
    {
44
        self::$noExistFileName = self::getFileName();
45
        self::$existFileName = self::newTempFileName();
46
    }
47
48
    /**
49
     * @return string
50
     */
51
    private static function getFileName(): string
52
    {
53
        $file_name = sys_get_temp_dir() . '/' . uniqid('vd_', true);
54
        self::$tempFileList[] = $file_name;
55
        return $file_name;
56
    }
57
58
    /**
59
     * @return bool|string
60
     */
61
    private static function newTempFileName()
62
    {
63
        $file_name = self::generateTempFile();
64
        self::$tempFileList[] = $file_name;
65
        return $file_name;
66
    }
67
68
    public function tearDown()
69
    {
70
        foreach (self::$tempFileList as $file_name) {
71
            /** @noinspection PhpUsageOfSilenceOperatorInspection */
72
            @unlink($file_name);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

72
            /** @scrutinizer ignore-unhandled */ @unlink($file_name);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
73
        }
74
    }
75
76
    /**
77
     * @return array
78
     */
79
    public function notFileNameProvider()
80
    {
81
        static $not_file_name = null;
82
83
        if (null === $not_file_name) {
84
            $not_file_name = \array_merge($this->notStringProvider(), $this->noValidFileNameProvider());
85
        }
86
87
88
        return $not_file_name;
89
    }
90
91
    /**
92
     * @return array
93
     */
94
    public function notStringProvider()
95
    {
96
        static $not_string_list = null;
97
        if (null === $not_string_list) {
98
            $not_string_list = NotStringList::getList();
99
100
            foreach ($not_string_list as &$param) {
101
                $param['throw'] = 'TypeError';
102
            }
103
        }
104
105
106
        return $not_string_list;
107
    }
108
109
110
    /**
111
     * @return array
112
     */
113
    public function noValidFileNameProvider()
114
    {
115
        static $file_name_list = null;
116
117
        if (null === $file_name_list) {
118
            $file_name_list = [
119
                ['']
120
                , ['.']
121
                , ['/']
122
                , ['//']
123
            ];
124
125
            foreach ($file_name_list as &$param) {
126
                $param['throw'] = 'Exception';
127
            }
128
        }
129
130
        return $file_name_list;
131
    }
132
133
    /**
134
     * return array
135
     */
136
    public function deletePidFileParam()
137
    {
138
        static $param = null;
139
140
        if (null === $param) {
141
            // existed file without write access for current user.
142
            // for Ubuntu is /etc/hosts.
143
            $file_name = '/etc/hosts';
144
145
            $message = $this->adminOrNotUnix($file_name);
146
147
            $param = [
148
                'noExistFileName' => [self::getFileName()]
149
                , 'wrongParam' => [null]
150
                , 'accessDenied' => [$file_name, $message]
151
            ];
152
        }
153
154
        return $param;
155
    }
156
157
    /**
158
     * @param $file_name
159
     * @return null|string
160
     */
161
    private function adminOrNotUnix($file_name)
162
    {
163
        $message = null;
164
165
        if (!file_exists($file_name)) {
166
            $message = 'test only for *nix.';
167
        } elseif (is_writable($file_name)) {
168
            $message = 'test runned under super/admin user. Change user.';
169
        }
170
        return $message;
171
    }
172
173
    /**
174
     * return array
175
     */
176
    public function setPidFileParam()
177
    {
178
        static $param = null;
179
180
        if (null === $param) {
181
            $param = [
182
                'lockedPidFile' => [
183
                    self::lockedPidFile()
184
                    , LockFileFail::class
185
                ]
186
                , 'fileHasExistPid' => [
187
                    self::fileWithExistedPid()
188
                    , ProcessExisted::class
189
                ]
190
                , '' => [
191
                    self::noValidPidFile()
192
                    , ConvertPidFail::class
193
                ]
194
            ];
195
        }
196
197
        return $param;
198
    }
199
200
    /**
201
     *
202
     */
203
    private static function lockedPidFile()
204
    {
205
        while (true) {
206
            $file_name = self::newTempFileName();
207
            $file_resource = fopen($file_name, 'rb+');
208
            flock($file_resource, LOCK_EX);
209
210
            yield $file_name;
211
        }
212
    }
213
214
    /**
215
     *
216
     */
217
    private static function fileWithExistedPid()
218
    {
219
        while (true) {
220
            $file_name = self::newTempFileName();
221
            file_put_contents($file_name, getmypid());
222
223
            yield $file_name;
224
        }
225
    }
226
227
    /**
228
     *
229
     */
230
    private static function noValidPidFile()
231
    {
232
        while (true) {
233
            $file_name = self::newTempFileName();
234
            file_put_contents($file_name, '12as');
235
236
            yield $file_name;
237
        }
238
    }
239
240
    /**
241
     * @return int
242
     */
243
    protected function getNoExistPid()
244
    {
245
        $no_exist_pid = 1;
246
        while (++$no_exist_pid < PHP_INT_MAX) {
247
            if (false === posix_kill($no_exist_pid, 0)
248
                && 3 === posix_get_last_error()
249
            ) {
250
                break;
251
            }
252
        }
253
        return $no_exist_pid;
254
    }
255
}
256