Completed
Push — master ( 8b8afe...5f2bbe )
by Greg
02:21
created

tests/cli/CollectionCest.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Robo;
3
4
use \CliGuy;
5
6
use Robo\Collection\Temporary;
7
8
class CollectionCest
9
{
10
    public function _before(CliGuy $I)
11
    {
12
        $I->amInPath(codecept_data_dir().'sandbox');
13
    }
14
15
    public function toRunMultipleTasksViaACollectionBuilder(CliGuy $I)
16
    {
17
        // This tests creating multiple tasks in a single builder,
18
        // which implicitly adds them to a collection.  To keep things
19
        // simple, we are only going to use taskFilesystemStack.  It
20
        // would be possible, of course, to do these operations with
21
        // a single FilesystemStack, but our goal is to test creating
22
        // multiple tasks with a builder, and ensure that a propper
23
        // collection is built.
24
        $collection = $I->collectionBuilder();
25
        $result = $collection->taskFilesystemStack()
26
                ->mkdir('a')
27
                ->touch('a/a.txt')
28
            ->rollback(
29
                $I->taskDeleteDir('a')
30
            )
31
            ->taskFilesystemStack()
32
                ->mkdir('a/b')
33
                ->touch('a/b/b.txt')
34
            ->taskFilesystemStack()
35
                ->mkdir('a/c')
36
                ->touch('a/c/c.txt')
37
            ->run();
38
39
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
40
41
        // All of the tasks created by the builder should be added
42
        // to a collection, and `run()` should run them all.
43
        $I->seeDirFound('a');
44
        $I->seeFileFound('a/a.txt');
45
        $I->seeDirFound('a/b');
46
        $I->seeFileFound('a/b/b.txt');
47
        $I->seeDirFound('a/c');
48
        $I->seeFileFound('a/c/c.txt');
49
    }
50
51
    public function toUseAWorkingDirWithACollectionBuilder(CliGuy $I)
52
    {
53
        // Run the same test with a working directory.  The working
54
        // directory path will point to a temporary directory which
55
        // will be moved into place once the tasks complete.
56
        $collection = $I->collectionBuilder();
57
        $workDirPath = $collection->workDir("build");
58
        $I->assertNotEquals("build", basename($workDirPath));
59
        $result = $collection->taskFilesystemStack()
60
                ->mkdir("{$workDirPath}/a")
61
                ->touch("{$workDirPath}/a/a.txt")
62
            ->taskFilesystemStack()
63
                ->mkdir("{$workDirPath}/a/b")
64
                ->touch("{$workDirPath}/a/b/b.txt")
65
            ->taskFilesystemStack()
66
                ->mkdir("{$workDirPath}/a/c")
67
                ->touch("{$workDirPath}/a/c/c.txt")
68
            ->run();
69
70
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
71
72
        // All of the tasks created by the builder should be added
73
        // to a collection, and `run()` should run them all.
74
        $I->seeDirFound('build/a');
75
        $I->seeFileFound('build/a/a.txt');
76
        $I->seeDirFound('build/a/b');
77
        $I->seeFileFound('build/a/b/b.txt');
78
        $I->seeDirFound('build/a/c');
79
        $I->seeFileFound('build/a/c/c.txt');
80
    }
81
82
    public function toRollbackAfterFailureViaACollectionBuilder(CliGuy $I)
83
    {
84
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
85
        // except we force an error at the end, and confirm that the
86
        // rollback function is called.
87
        $collection = $I->collectionBuilder();
88
        $result = $collection->taskFilesystemStack()
89
                ->mkdir('j')
90
                ->touch('j/j.txt')
91
            ->rollback(
92
                $I->taskDeleteDir('j')
93
            )
94
            ->taskFilesystemStack()
95
                ->mkdir('j/k')
96
                ->touch('j/k/k.txt')
97
            ->taskFilesystemStack()
98
                ->mkdir('j/k/m')
99
                ->touch('j/k/m/m.txt')
100
            ->taskCopyDir(['doesNotExist' => 'copied'])
101
            ->run();
102
103
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
104
105
        // All of the tasks created by the builder should be added
106
        // to a collection, and `run()` should run them all.
107
        $I->dontSeeFileFound('q/q.txt');
108
        $I->dontSeeFileFound('j/j.txt');
109
        $I->dontSeeFileFound('j/k/k.txt');
110
        $I->dontSeeFileFound('j/k/m/m.txt');
111
    }
112
113
    public function toRollbackAWorkingDir(CliGuy $I)
114
    {
115
        // Run the same test with a working directory.  The working
116
        // directory path will point to a temporary directory which
117
        // will be moved into place once the tasks complete.
118
        $collection = $I->collectionBuilder();
119
        $workDirPath = $collection->workDir("build");
120
        $I->assertNotEquals("build", basename($workDirPath));
121
        $result = $collection->taskFilesystemStack()
122
                ->mkdir("{$workDirPath}/a")
123
                ->touch("{$workDirPath}/a/a.txt")
124
            ->taskFilesystemStack()
125
                ->mkdir("{$workDirPath}/a/b")
126
                ->touch("{$workDirPath}/a/b/b.txt")
127
            ->taskFilesystemStack()
128
                ->mkdir("{$workDirPath}/a/c")
129
                ->touch("{$workDirPath}/a/c/c.txt")
130
            ->taskCopyDir(['doesNotExist' => 'copied'])
131
            ->run();
132
133
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
134
135
        // All of the tasks created by the builder should be added
136
        // to a collection, and `run()` should run them all.
137
        $I->dontSeeFileFound('build/a');
138
        $I->dontSeeFileFound($workDirPath);
139
    }
140
141
    public function toBuildFilesViaAddIterable(CliGuy $I)
142
    {
143
        $processList = ['cats', 'dogs', 'sheep', 'fish', 'horses', 'cows'];
144
145
        $collection = $I->collectionBuilder();
146
        $result = $collection
147
            ->taskFilesystemStack()
148
                ->mkdir('stuff')
149
            ->taskForEach($processList)
150
                ->withBuilder(
151
                    function ($builder, $key, $value) {
152
                        return $builder
153
                            ->taskFilesystemStack()
154
                                ->touch("stuff/{$value}.txt");
155
                    }
156
                )
157
            ->run();
158
159
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
160
161
        $I->seeFileFound('stuff/cats.txt');
162
        $I->seeFileFound('stuff/dogs.txt');
163
        $I->seeFileFound('stuff/sheep.txt');
164
        $I->seeFileFound('stuff/fish.txt');
165
        $I->seeFileFound('stuff/horses.txt');
166
        $I->seeFileFound('stuff/cows.txt');
167
    }
168
169
    public function toRollbackANestedCollection(CliGuy $I)
170
    {
171
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
172
        // except we force an error at the end, and confirm that the
173
        // rollback function is called.
174
        $collection = $I->collectionBuilder();
175
        $collection->taskFilesystemStack()
176
                ->mkdir('j')
177
                ->touch('j/j.txt')
178
            ->rollback(
179
                $I->taskDeleteDir('j')
180
            )
181
            ->taskFilesystemStack()
182
                ->mkdir('j/k')
183
                ->touch('j/k/k.txt')
184
            ->taskFilesystemStack()
185
                ->mkdir('j/k/m')
186
                ->touch('j/k/m/m.txt');
187
188
        $result = $I->collectionBuilder()
189
            ->taskFilesystemStack()
190
                ->mkdir('q')
191
                ->touch('q/q.txt')
192
            ->addTask($collection)
193
            ->taskCopyDir(['doesNotExist' => 'copied'])
194
            ->run();
195
196
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
197
198
        // All of the tasks created by the builder should be added
199
        // to a collection, and `run()` should run them all.
200
        $I->seeFileFound('q/q.txt');
201
        $I->dontSeeFileFound('j/j.txt');
202
        $I->dontSeeFileFound('j/k/k.txt');
203
        $I->dontSeeFileFound('j/k/m/m.txt');
204
    }
205
206
    public function toRollbackInCorrectOrder(CliGuy $I)
207
    {
208
        $expected_order = [6,5,4,3,2,1];
209
        $actual_order = [];
210
        $collection = $I->collectionBuilder();
211
        $collection->rollbackCode(function () use (&$actual_order) {
212
            $actual_order[] = 1;
213
        });
214
        $collection->rollbackCode(function () use (&$actual_order) {
215
            $actual_order[] = 2;
216
        });
217
        $collection->rollbackCode(function () use (&$actual_order) {
218
            $actual_order[] = 3;
219
        });
220
        // Add a nested collection with rollbacks.
221
        $nested_collection = $I->collectionBuilder();
222
        $nested_collection->rollbackCode(function () use (&$actual_order) {
223
            $actual_order[] = 4;
224
        });
225
        $nested_collection->rollbackCode(function () use (&$actual_order) {
226
            $actual_order[] = 5;
227
        });
228
        $collection->addTask($nested_collection);
229
230
        $collection->rollbackCode(function () use (&$actual_order) {
231
            $actual_order[] = 6;
232
        });
233
        $collection->addCode(function () {
234
            return Result::EXITCODE_ERROR;
235
        });
236
        $result = $collection->run();
0 ignored issues
show
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
237
        $I->assertEquals($expected_order, $actual_order);
238
    }
239
240 View Code Duplication
    public function toCreateDirViaCollection(CliGuy $I)
241
    {
242
        // Set up a collection to add tasks to
243
        $collection = $I->collectionBuilder();
244
245
        // Set up a filesystem stack
246
        $collection->taskFilesystemStack()
247
            ->mkdir('log')
248
            ->touch('log/error.txt');
249
250
        // FilesystemStack has not run yet, so file should not be found.
251
        $I->dontSeeFileFound('log/error.txt');
252
253
        // Run the task collection; now the files should be present
254
        $collection->run();
255
        $I->seeFileFound('log/error.txt');
256
        $I->seeDirFound('log');
257
    }
258
259
    public function toUseATmpDirAndConfirmItIsDeleted(CliGuy $I)
260
    {
261
        // Set up a collection to add tasks to
262
        $collection = $I->collectionBuilder();
263
264
        // Get a temporary directory to work in. Note that we get a
265
        // name back, but the directory is not created until the task
266
        // runs.  This technically is not thread-safe, but we create
267
        // a random name, so it is unlikely to conflict.
268
        $tmpPath = $collection->tmpDir();
269
270
        // Set up a filesystem stack, but use a collection to defer execution
271
        $collection->taskFilesystemStack()
272
            ->mkdir("$tmpPath/tmp")
273
            ->touch("$tmpPath/tmp/error.txt")
274
            ->rename("$tmpPath/tmp", "$tmpPath/log");
275
276
        // Copy our tmp directory to a location that is not transient
277
        $collection->taskCopyDir([$tmpPath => 'copied']);
278
279
        // FilesystemStack has not run yet, so no files should be found.
280
        $I->dontSeeFileFound("$tmpPath/tmp/error.txt");
281
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
282
        $I->dontSeeFileFound('copied/log/error.txt');
283
284
        // Run the task collection
285
        $result = $collection->run();
286
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
287
        $I->assertEquals($result['path'], $tmpPath, "Tmp dir result matches accessor.");
288
289
        // The file 'error.txt' should have been copied into the "copied" dir.
290
        // This also proves that the tmp directory was created.
291
        $I->seeFileFound('copied/log/error.txt');
292
        // $tmpPath should be deleted after $collection->run() completes.
293
        $I->dontSeeFileFound("$tmpPath/tmp/error.txt");
294
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
295
        $I->dontSeeFileFound("$tmpPath");
296
    }
297
298
    public function toUseATmpDirAndChangeWorkingDirectory(CliGuy $I)
299
    {
300
        // Set up a collection to add tasks to
301
        $collection = $I->collectionBuilder();
302
303
        $cwd = getcwd();
304
305
        $tmpPath = $collection->taskTmpDir()
306
            ->cwd()
307
            ->getPath();
308
309
        // Set up a filesystem stack, but use a collection to defer execution.
310
        // Note that since we used 'cwd()' above, the relative file paths
311
        // used below will be inside the temporary directory.
312
        $collection->taskFilesystemStack()
313
            ->mkdir("log")
314
            ->touch("log/error.txt");
315
316
        // Copy our tmp directory to a location that is not transient
317
        $collection->taskCopyDir(['log' => "$cwd/copied2"]);
318
319
        // FilesystemStack has not run yet, so no files should be found.
320
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
321
        $I->dontSeeFileFound('$cwd/copied2/log/error.txt');
322
323
        // Run the task collection
324
        $result = $collection->run();
325
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
326
327
        // The file 'error.txt' should have been copied into the "copied" dir
328
        $I->seeFileFound("$cwd/copied2/error.txt");
329
        // $tmpPath should be deleted after $collection->run() completes.
330
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
331
        // Make sure that 'log' was created in the temporary directory, not
332
        // at the current working directory.
333
        $I->dontSeeFileFound("$cwd/log/error.txt");
334
335
        // Make sure that our working directory was restored.
336
        $finalWorkingDir = getcwd();
337
        $I->assertEquals($cwd, $finalWorkingDir);
338
    }
339
340
    public function toCreateATmpFileAndConfirmItIsDeleted(CliGuy $I)
341
    {
342
        // Set up a collection to add tasks to
343
        $collection = $I->collectionBuilder();
344
345
        // Write to a temporary file. Note that we can get the path
346
        // to the tempoary file that will be created, even though the
347
        // the file is not created until the task collecction runs.
348
        $tmpPath = $collection->taskTmpFile('tmp', '.txt')
349
            ->line("This is a test file")
350
            ->getPath();
351
352
        // Copy our tmp directory to a location that is not transient
353
        $collection->taskFilesystemStack()
354
            ->copy($tmpPath, 'copied.txt');
355
356
        // FilesystemStack has not run yet, so no files should be found.
357
        $I->dontSeeFileFound("$tmpPath");
358
        $I->dontSeeFileFound('copied.txt');
359
360
        // Run the task collection
361
        $result = $collection->run();
362
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
363
364
        // The file 'copied.txt' should have been copied from the tmp file
365
        $I->seeFileFound('copied.txt');
366
        // $tmpPath should be deleted after $collection->run() completes.
367
        $I->dontSeeFileFound("$tmpPath");
368
    }
369
370
    public function toUseATmpDirWithAlternateSyntax(CliGuy $I)
371
    {
372
        $collection = $I->collectionBuilder();
373
374
        // This test is equivalent to toUseATmpDirAndConfirmItIsDeleted,
375
        // but uses a different technique to create a collection of tasks.
376
        $tmpPath = $collection->tmpDir();
377
378
        // Now, rather than creating the tasks with a collection builder,
379
        // which automatically adds the tasks to the collection as they are
380
        // created, we will instead create them individually and then add
381
        // them to the collection via the addTaskList() method.
382
        $result = $collection->addTaskList(
383
            [
384
                $I->taskFilesystemStack()->mkdir("$tmpPath/log")->touch("$tmpPath/log/error.txt"),
385
                $I->taskCopyDir([$tmpPath => 'copied3']),
386
            ]
387
        )->run();
388
389
        // The results of this operation should be the same.
390
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
391
        $I->seeFileFound('copied3/log/error.txt');
392
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
393
    }
394
395
    public function toCreateATmpDirWithoutACollection(CliGuy $I)
396
    {
397
        // Create a temporary directory, using our function name as
398
        // the prefix for the directory name.
399
        $tmpDirTask = $I->taskTmpDir(__FUNCTION__);
400
        $tmpPath = $tmpDirTask->getPath();
401
        $I->dontSeeFileFound($tmpPath);
402
        $tmpDirTask->run();
403
        $I->seeDirFound($tmpPath);
404
        // Creating a temporary directory without a task collection will
405
        // cause the temporary directory to be deleted when the program
406
        // terminates.  We can force it to clean up sooner by calling
407
        // TransientManager::complete(); note that this deletes ALL global tmp
408
        // directories, so this is not thread-safe!  Useful in tests, though.
409
        Temporary::complete();
410
        $I->dontSeeFileFound($tmpPath);
411
    }
412
413
    public function toCreateATmpDirUsingShortcut(CliGuy $I)
414
    {
415
        // Create a temporary directory, using our function name as
416
        // the prefix for the directory name.
417
        $tmpPath = $I->shortcutTmpDir(__FUNCTION__);
418
        $I->seeDirFound($tmpPath);
419
        // Creating a temporary directory without a task collection will
420
        // cause the temporary directory to be deleted when the program
421
        // terminates.  We can force it to clean up sooner by calling
422
        // TransientManager::complete(); note that this deletes ALL global tmp
423
        // directories, so this is not thread-safe!  Useful in tests, though.
424
        Temporary::complete();
425
        $I->dontSeeFileFound($tmpPath);
426
    }
427
428
    public function toThrowAnExceptionAndConfirmItIsCaught(CliGuy $I)
429
    {
430
        $collection = $I->getContainer()->get('collection');
431
432
        $collection->addCode(
433
            function () {
434
                throw new \RuntimeException('Error');
435
            }
436
        );
437
        $result = $collection->run();
438
        $I->assertEquals('Error', $result->getMessage());
439
        $I->assertEquals(1, $result->getExitCode());
440
    }
441
442
    public function toChainData(CliGuy $I)
443
    {
444
        $collection = $I->collectionBuilder();
445
446
        $result = $collection
447
            ->taskValueProvider()
448
                ->provideMessage('1st') // Sets Result's message to '1st'
449
                ->storeState('one') // Copy Result's message to $state['one']
450
            ->taskValueProvider()
451
                ->provideMessage('2nd')
452
                ->storeState('two')
453
            ->taskValueProvider()
454
                ->deferTaskConfiguration('provideItem', 'one') // Same as ->proivdeItem($state['one']), but runs immediately before this task's run() method.
455
                ->deferTaskConfiguration('provideMessage', 'two')
456
                ->storeState('final')
457
            ->run();
458
459
        $state = $collection->getState();
460
        $I->assertEquals('1st', $state['one']);
461
        $I->assertEquals('1st', $state['item']);
462
        $I->assertEquals('2nd', $state['final']);
463
    }
464
}
465