Completed
Push — master ( d3a073...5737c8 )
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
use Robo\Exception\AbortTasksException;
8
9
class CollectionCest
10
{
11
    public function _before(CliGuy $I)
12
    {
13
        $I->amInPath(codecept_data_dir().'sandbox');
14
    }
15
16
    public function toRunMultipleTasksViaACollectionBuilder(CliGuy $I)
17
    {
18
        // This tests creating multiple tasks in a single builder,
19
        // which implicitly adds them to a collection.  To keep things
20
        // simple, we are only going to use taskFilesystemStack.  It
21
        // would be possible, of course, to do these operations with
22
        // a single FilesystemStack, but our goal is to test creating
23
        // multiple tasks with a builder, and ensure that a propper
24
        // collection is built.
25
        $collection = $I->collectionBuilder();
26
        $result = $collection->taskFilesystemStack()
27
                ->mkdir('a')
28
                ->touch('a/a.txt')
29
            ->rollback(
30
                $I->taskDeleteDir('a')
31
            )
32
            ->taskFilesystemStack()
33
                ->mkdir('a/b')
34
                ->touch('a/b/b.txt')
35
            ->taskFilesystemStack()
36
                ->mkdir('a/c')
37
                ->touch('a/c/c.txt')
38
            ->run();
39
40
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
41
42
        // All of the tasks created by the builder should be added
43
        // to a collection, and `run()` should run them all.
44
        $I->seeDirFound('a');
45
        $I->seeFileFound('a/a.txt');
46
        $I->seeDirFound('a/b');
47
        $I->seeFileFound('a/b/b.txt');
48
        $I->seeDirFound('a/c');
49
        $I->seeFileFound('a/c/c.txt');
50
    }
51
52
    public function toUseAWorkingDirWithACollectionBuilder(CliGuy $I)
53
    {
54
        // Run the same test with a working directory.  The working
55
        // directory path will point to a temporary directory which
56
        // will be moved into place once the tasks complete.
57
        $collection = $I->collectionBuilder();
58
        $workDirPath = $collection->workDir("build");
59
        $I->assertNotEquals("build", basename($workDirPath));
60
        $result = $collection->taskFilesystemStack()
61
                ->mkdir("{$workDirPath}/a")
62
                ->touch("{$workDirPath}/a/a.txt")
63
            ->taskFilesystemStack()
64
                ->mkdir("{$workDirPath}/a/b")
65
                ->touch("{$workDirPath}/a/b/b.txt")
66
            ->taskFilesystemStack()
67
                ->mkdir("{$workDirPath}/a/c")
68
                ->touch("{$workDirPath}/a/c/c.txt")
69
            ->run();
70
71
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
72
73
        // All of the tasks created by the builder should be added
74
        // to a collection, and `run()` should run them all.
75
        $I->seeDirFound('build/a');
76
        $I->seeFileFound('build/a/a.txt');
77
        $I->seeDirFound('build/a/b');
78
        $I->seeFileFound('build/a/b/b.txt');
79
        $I->seeDirFound('build/a/c');
80
        $I->seeFileFound('build/a/c/c.txt');
81
    }
82
83 View Code Duplication
    public function toRollbackAfterFailureViaACollectionBuilder(CliGuy $I)
84
    {
85
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
86
        // except we force an error at the end, and confirm that the
87
        // rollback function is called.
88
        $collection = $I->collectionBuilder();
89
        $result = $collection->taskFilesystemStack()
90
                ->mkdir('j')
91
                ->touch('j/j.txt')
92
            ->rollback(
93
                $I->taskDeleteDir('j')
94
            )
95
            ->taskFilesystemStack()
96
                ->mkdir('j/k')
97
                ->touch('j/k/k.txt')
98
            ->taskFilesystemStack()
99
                ->mkdir('j/k/m')
100
                ->touch('j/k/m/m.txt')
101
            ->taskCopyDir(['doesNotExist' => 'copied'])
102
            ->run();
103
104
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
105
106
        // All of the tasks created by the builder should be added
107
        // to a collection, and `run()` should run them all.
108
        $I->dontSeeFileFound('q/q.txt');
109
        $I->dontSeeFileFound('j/j.txt');
110
        $I->dontSeeFileFound('j/k/k.txt');
111
        $I->dontSeeFileFound('j/k/m/m.txt');
112
    }
113
114 View Code Duplication
    public function toAbortRollbackOrCompletion(CliGuy $I)
115
    {
116
        // This is like the previous test, except we throw a ForcedException()
117
        // inside the rollback to abort the rollback.
118
        $collection = $I->collectionBuilder();
119
        $result = $collection->taskFilesystemStack()
120
            ->mkdir('j')
121
            ->touch('j/j.txt')
122
            ->rollback(
123
                $I->taskDeleteDir('j')
124
            )
125
            ->rollbackCode(function () {
126
                throw new AbortTasksException('Aborting rollback.');
127
            })
128
            ->taskFilesystemStack()
129
            ->mkdir('j/k')
130
            ->touch('j/k/k.txt')
131
            ->taskFilesystemStack()
132
            ->mkdir('j/k/m')
133
            ->touch('j/k/m/m.txt')
134
            ->taskCopyDir(['doesNotExist' => 'copied'])
135
            ->run();
136
137
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
138
139
        // All of the tasks created by the builder should be added
140
        // to a collection, and `run()` should run them all.
141
        $I->seeFileFound('j/j.txt');
142
        $I->seeFileFound('j/k/k.txt');
143
        $I->seeFileFound('j/k/m/m.txt');
144
    }
145
146
    public function toRollbackAWorkingDir(CliGuy $I)
147
    {
148
        // Run the same test with a working directory.  The working
149
        // directory path will point to a temporary directory which
150
        // will be moved into place once the tasks complete.
151
        $collection = $I->collectionBuilder();
152
        $workDirPath = $collection->workDir("build");
153
        $I->assertNotEquals("build", basename($workDirPath));
154
        $result = $collection->taskFilesystemStack()
155
                ->mkdir("{$workDirPath}/a")
156
                ->touch("{$workDirPath}/a/a.txt")
157
            ->taskFilesystemStack()
158
                ->mkdir("{$workDirPath}/a/b")
159
                ->touch("{$workDirPath}/a/b/b.txt")
160
            ->taskFilesystemStack()
161
                ->mkdir("{$workDirPath}/a/c")
162
                ->touch("{$workDirPath}/a/c/c.txt")
163
            ->taskCopyDir(['doesNotExist' => 'copied'])
164
            ->run();
165
166
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
167
168
        // All of the tasks created by the builder should be added
169
        // to a collection, and `run()` should run them all.
170
        $I->dontSeeFileFound('build/a');
171
        $I->dontSeeFileFound($workDirPath);
172
    }
173
174
    public function toBuildFilesViaAddIterable(CliGuy $I)
175
    {
176
        $processList = ['cats', 'dogs', 'sheep', 'fish', 'horses', 'cows'];
177
178
        $collection = $I->collectionBuilder();
179
        $result = $collection
180
            ->taskFilesystemStack()
181
                ->mkdir('stuff')
182
            ->taskForEach($processList)
183
                ->withBuilder(
184
                    function ($builder, $key, $value) {
185
                        return $builder
186
                            ->taskFilesystemStack()
187
                                ->touch("stuff/{$value}.txt");
188
                    }
189
                )
190
            ->run();
191
192
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
193
194
        $I->seeFileFound('stuff/cats.txt');
195
        $I->seeFileFound('stuff/dogs.txt');
196
        $I->seeFileFound('stuff/sheep.txt');
197
        $I->seeFileFound('stuff/fish.txt');
198
        $I->seeFileFound('stuff/horses.txt');
199
        $I->seeFileFound('stuff/cows.txt');
200
    }
201
202
    public function toRollbackANestedCollection(CliGuy $I)
203
    {
204
        // This is like the previous test, toRunMultipleTasksViaACollectionBuilder,
205
        // except we force an error at the end, and confirm that the
206
        // rollback function is called.
207
        $collection = $I->collectionBuilder();
208
        $collection->taskFilesystemStack()
209
                ->mkdir('j')
210
                ->touch('j/j.txt')
211
            ->rollback(
212
                $I->taskDeleteDir('j')
213
            )
214
            ->taskFilesystemStack()
215
                ->mkdir('j/k')
216
                ->touch('j/k/k.txt')
217
            ->taskFilesystemStack()
218
                ->mkdir('j/k/m')
219
                ->touch('j/k/m/m.txt');
220
221
        $result = $I->collectionBuilder()
222
            ->taskFilesystemStack()
223
                ->mkdir('q')
224
                ->touch('q/q.txt')
225
            ->addTask($collection)
226
            ->taskCopyDir(['doesNotExist' => 'copied'])
227
            ->run();
228
229
        $I->assertEquals(1, $result->getExitCode(), $result->getMessage());
230
231
        // All of the tasks created by the builder should be added
232
        // to a collection, and `run()` should run them all.
233
        $I->seeFileFound('q/q.txt');
234
        $I->dontSeeFileFound('j/j.txt');
235
        $I->dontSeeFileFound('j/k/k.txt');
236
        $I->dontSeeFileFound('j/k/m/m.txt');
237
    }
238
239
    public function toRollbackInCorrectOrder(CliGuy $I)
240
    {
241
        $expected_order = [6,5,4,3,2,1];
242
        $actual_order = [];
243
        $collection = $I->collectionBuilder();
244
        $collection->rollbackCode(function () use (&$actual_order) {
245
            $actual_order[] = 1;
246
        });
247
        $collection->rollbackCode(function () use (&$actual_order) {
248
            $actual_order[] = 2;
249
        });
250
        $collection->rollbackCode(function () use (&$actual_order) {
251
            $actual_order[] = 3;
252
        });
253
        // Add a nested collection with rollbacks.
254
        $nested_collection = $I->collectionBuilder();
255
        $nested_collection->rollbackCode(function () use (&$actual_order) {
256
            $actual_order[] = 4;
257
        });
258
        $nested_collection->rollbackCode(function () use (&$actual_order) {
259
            $actual_order[] = 5;
260
        });
261
        $collection->addTask($nested_collection);
262
263
        $collection->rollbackCode(function () use (&$actual_order) {
264
            $actual_order[] = 6;
265
        });
266
        $collection->addCode(function () {
267
            return Result::EXITCODE_ERROR;
268
        });
269
        $result = $collection->run();
270
        $I->assertEquals($expected_order, $actual_order);
271
    }
272
273 View Code Duplication
    public function toCreateDirViaCollection(CliGuy $I)
274
    {
275
        // Set up a collection to add tasks to
276
        $collection = $I->collectionBuilder();
277
278
        // Set up a filesystem stack
279
        $collection->taskFilesystemStack()
280
            ->mkdir('log')
281
            ->touch('log/error.txt');
282
283
        // FilesystemStack has not run yet, so file should not be found.
284
        $I->dontSeeFileFound('log/error.txt');
285
286
        // Run the task collection; now the files should be present
287
        $collection->run();
288
        $I->seeFileFound('log/error.txt');
289
        $I->seeDirFound('log');
290
    }
291
292
    public function toUseATmpDirAndConfirmItIsDeleted(CliGuy $I)
293
    {
294
        // Set up a collection to add tasks to
295
        $collection = $I->collectionBuilder();
296
297
        // Get a temporary directory to work in. Note that we get a
298
        // name back, but the directory is not created until the task
299
        // runs.  This technically is not thread-safe, but we create
300
        // a random name, so it is unlikely to conflict.
301
        $tmpPath = $collection->tmpDir();
302
303
        // Set up a filesystem stack, but use a collection to defer execution
304
        $collection->taskFilesystemStack()
305
            ->mkdir("$tmpPath/tmp")
306
            ->touch("$tmpPath/tmp/error.txt")
307
            ->rename("$tmpPath/tmp", "$tmpPath/log");
308
309
        // Copy our tmp directory to a location that is not transient
310
        $collection->taskCopyDir([$tmpPath => 'copied']);
311
312
        // FilesystemStack has not run yet, so no files should be found.
313
        $I->dontSeeFileFound("$tmpPath/tmp/error.txt");
314
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
315
        $I->dontSeeFileFound('copied/log/error.txt');
316
317
        // Run the task collection
318
        $result = $collection->run();
319
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
320
        $I->assertEquals($result['path'], $tmpPath, "Tmp dir result matches accessor.");
321
322
        // The file 'error.txt' should have been copied into the "copied" dir.
323
        // This also proves that the tmp directory was created.
324
        $I->seeFileFound('copied/log/error.txt');
325
        // $tmpPath should be deleted after $collection->run() completes.
326
        $I->dontSeeFileFound("$tmpPath/tmp/error.txt");
327
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
328
        $I->dontSeeFileFound("$tmpPath");
329
    }
330
331
    public function toUseATmpDirAndChangeWorkingDirectory(CliGuy $I)
332
    {
333
        // Set up a collection to add tasks to
334
        $collection = $I->collectionBuilder();
335
336
        $cwd = getcwd();
337
338
        $tmpPath = $collection->taskTmpDir()
339
            ->cwd()
340
            ->getPath();
341
342
        // Set up a filesystem stack, but use a collection to defer execution.
343
        // Note that since we used 'cwd()' above, the relative file paths
344
        // used below will be inside the temporary directory.
345
        $collection->taskFilesystemStack()
346
            ->mkdir("log")
347
            ->touch("log/error.txt");
348
349
        // Copy our tmp directory to a location that is not transient
350
        $collection->taskCopyDir(['log' => "$cwd/copied2"]);
351
352
        // FilesystemStack has not run yet, so no files should be found.
353
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
354
        $I->dontSeeFileFound('$cwd/copied2/log/error.txt');
355
356
        // Run the task collection
357
        $result = $collection->run();
358
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
359
360
        // The file 'error.txt' should have been copied into the "copied" dir
361
        $I->seeFileFound("$cwd/copied2/error.txt");
362
        // $tmpPath should be deleted after $collection->run() completes.
363
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
364
        // Make sure that 'log' was created in the temporary directory, not
365
        // at the current working directory.
366
        $I->dontSeeFileFound("$cwd/log/error.txt");
367
368
        // Make sure that our working directory was restored.
369
        $finalWorkingDir = getcwd();
370
        $I->assertEquals($cwd, $finalWorkingDir);
371
    }
372
373
    public function toCreateATmpFileAndConfirmItIsDeleted(CliGuy $I)
374
    {
375
        // Set up a collection to add tasks to
376
        $collection = $I->collectionBuilder();
377
378
        // Write to a temporary file. Note that we can get the path
379
        // to the tempoary file that will be created, even though the
380
        // the file is not created until the task collecction runs.
381
        $tmpPath = $collection->taskTmpFile('tmp', '.txt')
382
            ->line("This is a test file")
383
            ->getPath();
384
385
        // Copy our tmp directory to a location that is not transient
386
        $collection->taskFilesystemStack()
387
            ->copy($tmpPath, 'copied.txt');
388
389
        // FilesystemStack has not run yet, so no files should be found.
390
        $I->dontSeeFileFound("$tmpPath");
391
        $I->dontSeeFileFound('copied.txt');
392
393
        // Run the task collection
394
        $result = $collection->run();
395
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
396
397
        // The file 'copied.txt' should have been copied from the tmp file
398
        $I->seeFileFound('copied.txt');
399
        // $tmpPath should be deleted after $collection->run() completes.
400
        $I->dontSeeFileFound("$tmpPath");
401
    }
402
403
    public function toUseATmpDirWithAlternateSyntax(CliGuy $I)
404
    {
405
        $collection = $I->collectionBuilder();
406
407
        // This test is equivalent to toUseATmpDirAndConfirmItIsDeleted,
408
        // but uses a different technique to create a collection of tasks.
409
        $tmpPath = $collection->tmpDir();
410
411
        // Now, rather than creating the tasks with a collection builder,
412
        // which automatically adds the tasks to the collection as they are
413
        // created, we will instead create them individually and then add
414
        // them to the collection via the addTaskList() method.
415
        $result = $collection->addTaskList(
416
            [
417
                $I->taskFilesystemStack()->mkdir("$tmpPath/log")->touch("$tmpPath/log/error.txt"),
418
                $I->taskCopyDir([$tmpPath => 'copied3']),
419
            ]
420
        )->run();
421
422
        // The results of this operation should be the same.
423
        $I->assertEquals(0, $result->getExitCode(), $result->getMessage());
424
        $I->seeFileFound('copied3/log/error.txt');
425
        $I->dontSeeFileFound("$tmpPath/log/error.txt");
426
    }
427
428
    public function toCreateATmpDirWithoutACollection(CliGuy $I)
429
    {
430
        // Create a temporary directory, using our function name as
431
        // the prefix for the directory name.
432
        $tmpDirTask = $I->taskTmpDir(__FUNCTION__);
433
        $tmpPath = $tmpDirTask->getPath();
434
        $I->dontSeeFileFound($tmpPath);
435
        $tmpDirTask->run();
436
        $I->seeDirFound($tmpPath);
437
        // Creating a temporary directory without a task collection will
438
        // cause the temporary directory to be deleted when the program
439
        // terminates.  We can force it to clean up sooner by calling
440
        // TransientManager::complete(); note that this deletes ALL global tmp
441
        // directories, so this is not thread-safe!  Useful in tests, though.
442
        Temporary::complete();
443
        $I->dontSeeFileFound($tmpPath);
444
    }
445
446
    public function toCreateATmpDirUsingShortcut(CliGuy $I)
447
    {
448
        // Create a temporary directory, using our function name as
449
        // the prefix for the directory name.
450
        $tmpPath = $I->shortcutTmpDir(__FUNCTION__);
451
        $I->seeDirFound($tmpPath);
452
        // Creating a temporary directory without a task collection will
453
        // cause the temporary directory to be deleted when the program
454
        // terminates.  We can force it to clean up sooner by calling
455
        // TransientManager::complete(); note that this deletes ALL global tmp
456
        // directories, so this is not thread-safe!  Useful in tests, though.
457
        Temporary::complete();
458
        $I->dontSeeFileFound($tmpPath);
459
    }
460
461
    public function toThrowAnExceptionAndConfirmItIsCaught(CliGuy $I)
462
    {
463
        $collection = $I->getContainer()->get('collection');
464
465
        $collection->addCode(
466
            function () {
467
                throw new \RuntimeException('Error');
468
            }
469
        );
470
        $result = $collection->run();
471
        $I->assertEquals('Error', $result->getMessage());
472
        $I->assertEquals(1, $result->getExitCode());
473
    }
474
475
    public function toChainData(CliGuy $I)
476
    {
477
        $collection = $I->collectionBuilder();
478
479
        $result = $collection
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...
480
            ->taskValueProvider()
481
                ->provideMessage('1st') // Sets Result's message to '1st'
482
                ->storeState('one') // Copy Result's message to $state['one']
483
            ->taskValueProvider()
484
                ->provideMessage('2nd')
485
                ->storeState('two')
486
            ->taskValueProvider()
487
                ->deferTaskConfiguration('provideItem', 'one') // Same as ->proivdeItem($state['one']), but runs immediately before this task's run() method.
488
                ->deferTaskConfiguration('provideMessage', 'two')
489
                ->storeState('final')
490
            ->run();
491
492
        $state = $collection->getState();
493
        $I->assertEquals('1st', $state['one']);
494
        $I->assertEquals('1st', $state['item']);
495
        $I->assertEquals('2nd', $state['final']);
496
    }
497
}
498