Build package / xml-lint (push) Successful in 1m4s
Build package / php-lint (8.5) (push) Successful in 4m0s
Build package / unit-tests (push) Successful in 4m13s
Build package / php-lint (8.4) (push) Successful in 4m34s
Build package / package (push) Successful in 1m38s
Every enabled workflow is an edge "source stack -> target stack"; LoopDetector finds circles in that graph, a workflow whose source is its own target being the shortest. Without a check, two workflows A -> B and B -> A move the same cards back and forth on every run, even within a single run, with a notice for each move. The trigger date is ignored on purpose: by start date one way and by due date the other, a card with both dates passed still circles. Chains stay allowed. The controller rejects saving an enabled workflow that would close a loop and names the workflows involved. Workflows stored before this check are skipped by the runner (logged, not disabled) and flagged in the settings list via a new `loop` field from index().
77 lines
2.0 KiB
PHP
77 lines
2.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace OCA\WorkflowDeckAutomation\Tests\Unit\Service;
|
|
|
|
use OCA\WorkflowDeckAutomation\Service\LoopDetector;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class LoopDetectorTest extends TestCase {
|
|
public function testNoWorkflowsHaveNoLoop(): void {
|
|
$this->assertSame([], LoopDetector::findLoopingWorkflows([]));
|
|
}
|
|
|
|
public function testSameSourceAndTargetIsALoop(): void {
|
|
$this->assertSame([1], LoopDetector::findLoopingWorkflows([1 => [10, 10]]));
|
|
}
|
|
|
|
public function testTwoWorkflowsBackAndForthAreALoop(): void {
|
|
$this->assertSame([1, 2], LoopDetector::findLoopingWorkflows([
|
|
1 => [10, 20],
|
|
2 => [20, 10],
|
|
]));
|
|
}
|
|
|
|
public function testLongerCircleIsALoop(): void {
|
|
$this->assertSame([1, 2, 3], LoopDetector::findLoopingWorkflows([
|
|
1 => [10, 20],
|
|
2 => [20, 30],
|
|
3 => [30, 10],
|
|
]));
|
|
}
|
|
|
|
public function testChainIsNoLoop(): void {
|
|
$this->assertSame([], LoopDetector::findLoopingWorkflows([
|
|
1 => [10, 20],
|
|
2 => [20, 30],
|
|
]));
|
|
}
|
|
|
|
public function testOnlyWorkflowsOnTheCircleAreReported(): void {
|
|
// 1 feeds into the circle 2 → 3 → 2 and 4 leads out of it; neither
|
|
// lies on it.
|
|
$this->assertSame([2, 3], LoopDetector::findLoopingWorkflows([
|
|
1 => [10, 20],
|
|
2 => [20, 30],
|
|
3 => [30, 20],
|
|
4 => [30, 40],
|
|
]));
|
|
}
|
|
|
|
public function testTwoWorkflowsFromTheSameSourceAreNoLoop(): void {
|
|
$this->assertSame([], LoopDetector::findLoopingWorkflows([
|
|
1 => [10, 20],
|
|
2 => [10, 30],
|
|
]));
|
|
}
|
|
|
|
public function testFindPathListsTheWorkflowsInOrder(): void {
|
|
$edges = [
|
|
7 => [30, 10],
|
|
5 => [10, 20],
|
|
6 => [20, 30],
|
|
];
|
|
$this->assertSame([5, 6], LoopDetector::findPath($edges, 10, 30));
|
|
$this->assertSame([6, 7], LoopDetector::findPath($edges, 20, 10));
|
|
}
|
|
|
|
public function testFindPathWithoutConnectionIsNull(): void {
|
|
$this->assertNull(LoopDetector::findPath([1 => [10, 20]], 20, 10));
|
|
}
|
|
|
|
public function testFindPathToItselfIsEmpty(): void {
|
|
$this->assertSame([], LoopDetector::findPath([], 10, 10));
|
|
}
|
|
}
|