public function testOrchestrationsWarn()
 {
     // create orchestration
     $options = array('crontabRecord' => '1 1 1 1 1');
     $orchestration = $this->client->createOrchestration(sprintf('%s %s', self::TESTING_ORCHESTRATION_NAME, uniqid()), $options);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'createOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'createOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'createOrchestration' should return orchestration info");
     // orchestrations tasks
     $tasks = $this->client->updateTasks($orchestration['id'], $this->createTestDataWithWarn());
     // orchestration detail
     $orchestration = $this->client->getOrchestration($orchestration['id']);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'getOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'getOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'getOrchestration' should return orchestration info");
     // orchestration update
     $crontabRecord = '* * * * *';
     $active = false;
     $options = array('active' => $active, 'crontabRecord' => $crontabRecord);
     $orchestration = $this->client->updateOrchestration($orchestration['id'], $options);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'updateOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertArrayHasKey('active', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertEquals($active, $orchestration['active'], "Result of API command 'updateOrchestration' should return disabled orchestration");
     $this->assertEquals($crontabRecord, $orchestration['crontabRecord'], "Result of API command 'updateOrchestration' should return modified orchestration");
     // enqueue job
     $job = $this->client->runOrchestration($orchestration['id']);
     $this->assertArrayHasKey('id', $job, "Result of API command 'createJob' should contain new created job ID");
     $this->assertArrayHasKey('isFinished', $job, "Result of API command 'createJob' should contain isFinished status");
     $this->assertArrayHasKey('orchestrationId', $job, "Result of API command 'createJob' should return job info");
     $this->assertArrayHasKey('status', $job, "Result of API command 'createJob' should return job info");
     $this->assertEquals('waiting', $job['status'], "Result of API command 'createJob' should return new waiting job");
     $this->assertEquals($orchestration['id'], $job['orchestrationId'], "Result of API command 'createJob' should return new waiting job for given orchestration");
     // wait for processing job
     while (!$job['isFinished']) {
         sleep(5);
         $job = $this->client->getJob($job['id']);
         $this->assertArrayHasKey('isFinished', $job);
     }
     // job detail
     $job = $this->client->getJob($job['id']);
     $this->assertArrayHasKey('id', $job, "Result of API command 'getJob' should contain job ID");
     $this->assertArrayHasKey('orchestrationId', $job, "Result of API command 'getJob' should return job info");
     $this->assertArrayHasKey('status', $job, "Result of API command 'getJob' should return job info");
     $this->assertEquals($orchestration['id'], $job['orchestrationId'], "Result of API command 'getJob' should return job for given orchestration");
     $errorsCount = 0;
     $cancelledCount = 0;
     $successCount = 0;
     $processingCount = 0;
     $warnCount = 0;
     $otherCount = 0;
     $jobs = $this->client->getOrchestrationJobs($orchestration['id']);
     foreach ($jobs as $job) {
         if ($job['status'] === 'success') {
             $successCount++;
             continue;
         }
         if ($job['status'] === 'processing') {
             $processingCount++;
             continue;
         }
         if ($job['status'] === 'warn') {
             $warnCount++;
             continue;
         }
         if ($job['status'] === 'error') {
             $errorsCount++;
             continue;
         }
         if ($job['status'] === 'cancelled') {
             $cancelledCount++;
             continue;
         }
         if ($job['status'] === 'terminated') {
             $cancelledCount++;
             continue;
         }
         if ($job['status'] === 'terminating') {
             $cancelledCount++;
             continue;
         }
         $otherCount++;
     }
     $this->assertLessThan(1, $successCount, "Result of API command 'getOrchestrationJobs' should return any job with 'status' status");
     $this->assertLessThan(1, $errorsCount, "Result of API command 'getOrchestrationJobs' should return any job with 'error' status");
     $this->assertGreaterThan(0, $warnCount, "Result of API command 'getOrchestrationJobs' should return least one job with 'warn' status");
     $this->assertLessThan(1, $otherCount, "Result of API command 'getOrchestrationJobs' should return only finished jobs");
     // delete orchestration
     $result = $this->client->deleteOrchestration($orchestration['id']);
     $this->assertTrue($result, "Result of API command 'deleteOrchestration' should return TRUE");
 }
 public function testOrchestrationsPhaseNames()
 {
     // create orchestration
     $options = array('crontabRecord' => '1 1 1 1 1', 'tasks' => array(0 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "first phase", 'actionParameters' => array('delay' => 180)), 2 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => null, 'actionParameters' => array('delay' => 5)), 3 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "0", 'actionParameters' => array('delay' => 5)), 4 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "", 'actionParameters' => array('delay' => 5))));
     $orchestration = $this->client->createOrchestration(sprintf('%s %s', self::TESTING_ORCHESTRATION_NAME, uniqid()), $options);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'createOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('tasks', $orchestration, "Result of API command 'createOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'createOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'createOrchestration' should return orchestration info");
     $tasks = $orchestration['tasks'];
     $this->assertCount(4, $tasks);
     $this->assertArrayHasKey('phase', $tasks[0]);
     $this->assertEquals('first phase', $tasks[0]['phase']);
     $this->assertArrayHasKey('phase', $tasks[1]);
     $this->assertNull($tasks[1]['phase']);
     $this->assertArrayHasKey('phase', $tasks[2]);
     $this->assertNotNull($tasks[2]['phase']);
     $this->assertEquals(0, $tasks[2]['phase']);
     $this->assertArrayHasKey('phase', $tasks[3]);
     $this->assertNull($tasks[3]['phase']);
     // update orchestration
     $options = array('crontabRecord' => '1 1 1 1 1', 'tasks' => array(0 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "first phase", 'actionParameters' => array('delay' => 180)), 1 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "first phase", 'actionParameters' => array('delay' => 30)), 2 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => null, 'actionParameters' => array('delay' => 5)), 3 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "0", 'actionParameters' => array('delay' => 5)), 4 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "", 'actionParameters' => array('delay' => 5))));
     $orchestration = $this->client->updateOrchestration($orchestration['id'], $options);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'createOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('tasks', $orchestration, "Result of API command 'createOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'createOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'createOrchestration' should return orchestration info");
     $tasks = $orchestration['tasks'];
     $this->assertCount(5, $tasks);
     $this->assertArrayHasKey('phase', $tasks[0]);
     $this->assertEquals('first phase', $tasks[0]['phase']);
     $this->assertArrayHasKey('phase', $tasks[1]);
     $this->assertEquals('first phase', $tasks[1]['phase']);
     $this->assertArrayHasKey('phase', $tasks[2]);
     $this->assertNull($tasks[2]['phase']);
     $this->assertArrayHasKey('phase', $tasks[3]);
     $this->assertNotNull($tasks[3]['phase']);
     $this->assertEquals(0, $tasks[3]['phase']);
     $this->assertArrayHasKey('phase', $tasks[4]);
     $this->assertNull($tasks[4]['phase']);
     // orchestrations tasks
     $tasks = $this->client->updateTasks($orchestration['id'], $this->createTestData());
     // orchestration detail
     $orchestration = $this->client->getOrchestration($orchestration['id']);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'getOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'getOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'getOrchestration' should return orchestration info");
     // orchestration update
     $crontabRecord = '* * * * *';
     $active = false;
     $options = array('active' => $active, 'crontabRecord' => $crontabRecord, 'tasks' => array(0 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "first phase", 'actionParameters' => array('delay' => 180)), 1 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "first phase", 'actionParameters' => array('delay' => 30)), 2 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => null, 'actionParameters' => array('delay' => 5)), 3 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "0", 'actionParameters' => array('delay' => 5)), 4 => array('componentUrl' => 'https://syrup.keboola.com/timeout/jobs', 'active' => true, 'phase' => "", 'actionParameters' => array('delay' => 5))));
     $orchestration = $this->client->updateOrchestration($orchestration['id'], $options);
     $this->assertArrayHasKey('id', $orchestration, "Result of API command 'updateOrchestration' should contain new created orchestration ID");
     $this->assertArrayHasKey('crontabRecord', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertArrayHasKey('nextScheduledTime', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertArrayHasKey('active', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertArrayHasKey('tasks', $orchestration, "Result of API command 'updateOrchestration' should return orchestration info");
     $this->assertEquals($active, $orchestration['active'], "Result of API command 'updateOrchestration' should return disabled orchestration");
     $this->assertEquals($crontabRecord, $orchestration['crontabRecord'], "Result of API command 'updateOrchestration' should return modified orchestration");
     $tasks = $orchestration['tasks'];
     $this->assertCount(5, $tasks);
     $this->assertArrayHasKey('phase', $tasks[0]);
     $this->assertEquals('first phase', $tasks[0]['phase']);
     $this->assertArrayHasKey('phase', $tasks[1]);
     $this->assertEquals('first phase', $tasks[1]['phase']);
     $this->assertArrayHasKey('phase', $tasks[2]);
     $this->assertNull($tasks[2]['phase']);
     $this->assertArrayHasKey('phase', $tasks[3]);
     $this->assertNotNull($tasks[3]['phase']);
     $this->assertEquals(0, $tasks[3]['phase']);
     $this->assertArrayHasKey('phase', $tasks[4]);
     $this->assertNull($tasks[4]['phase']);
     // enqueue job
     $job = $this->client->runOrchestration($orchestration['id']);
     $this->assertArrayHasKey('id', $job, "Result of API command 'createJob' should contain new created job ID");
     $this->assertArrayHasKey('orchestrationId', $job, "Result of API command 'createJob' should return job info");
     $this->assertArrayHasKey('status', $job, "Result of API command 'createJob' should return job info");
     $this->assertEquals('waiting', $job['status'], "Result of API command 'createJob' should return new waiting job");
     $this->assertEquals($orchestration['id'], $job['orchestrationId'], "Result of API command 'createJob' should return new waiting job for given orchestration");
     // wait for processing job
     while (!in_array($job['status'], array('ok', 'success', 'error', 'warn'))) {
         sleep(5);
         $job = $this->client->getJob($job['id']);
         $this->assertArrayHasKey('status', $job, "Result of API command 'getJob' should return job info");
     }
     // phases and tasks results in response
     $this->assertArrayHasKey('results', $job, "Result of API command 'getJob' should return results");
     $results = $job['results'];
     $this->assertArrayHasKey('tasks', $results, "Result of API command 'getJob' should return tasks results");
     $this->assertArrayHasKey('phases', $results, "Result of API command 'getJob' should return phases results");
     $this->assertEquals('success', $job['status'], "Result of API command 'getJob' should return job with success status");
     $this->assertCount(4, $results['phases']);
     $this->assertCount(5, $results['tasks']);
     // task status
     $successCount = 0;
     foreach ($results['tasks'] as $taskResult) {
         $this->assertArrayHasKey('status', $taskResult, "Task result should contains execution status");
         if ($taskResult['status'] === 'success') {
             $successCount++;
         }
     }
     $this->assertEquals(5, $successCount, "All executed tasks should have 'success' status");
     // task execution order
     $i = 0;
     $taskOrder = array();
     foreach ($results['tasks'] as $taskResult) {
         $taskOrder[$taskResult['id']] = $i;
         $i++;
     }
     $i = 0;
     foreach ($results['phases'] as $phase) {
         foreach ($phase as $taskResult) {
             $this->assertEquals($i, $taskOrder[$taskResult['id']], "Tasks in tasks result and phases result should have same order");
             $i++;
         }
     }
     // parallel job processing
     $phase = $results['phases'][0];
     $task1Start = new \DateTime($phase[0]['startTime']);
     $task1End = new \DateTime($phase[0]['endTime']);
     $task2Start = new \DateTime($phase[1]['startTime']);
     $task2End = new \DateTime($phase[1]['endTime']);
     $validTime = false;
     if ($task1Start->getTimestamp() < $task2Start->getTimestamp()) {
         if ($task1End->getTimestamp() > $task2End->getTimestamp()) {
             $validTime = true;
         }
     }
     $this->assertTrue($validTime, 'First phase should have parallel processed tasks');
 }