*/ class DeliveryMonitoringServiceTest extends TaoPhpUnitTestRunner { /** * @var MonitoringStorage */ protected $service; /** * @var common_persistence_SqlPersistence */ protected $persistence; protected $deliveryExecutionId = 'http://sample/first.rdf#i1450191587554175_test_record'; protected $fixtureData = [ [ MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554175_test_record', MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_1', MonitoringStorage::COLUMN_STATUS => 'active_test', 'user_uri' => 'http://sample/first.rdf#i1450191587554175_test_user', 'error_code' => 1, 'session_id' => 'i1450191587554175', ], [ MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554176_test_record', MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_2', MonitoringStorage::COLUMN_STATUS => 'paused_test', 'user_uri' => 'http://sample/first.rdf#i1450191587554176_test_user', 'error_code' => 2, 'session_id' => 'i1450191587554176', ], [ MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554177_test_record', MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_3', MonitoringStorage::COLUMN_STATUS => 'finished_test', 'user_uri' => 'http://sample/first.rdf#i1450191587554177_test_user', 'error_code' => 3, 'session_id' => 'i1450191587554177', ], [ MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554178_test_record', MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_4', MonitoringStorage::COLUMN_STATUS => 'finished_test', 'user_uri' => 'http://sample/first.rdf#i1450191587554178_test_user', 'error_code' => 0, 'session_id' => 'i1450191587554178', ], [ MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554179_test_record', MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_5', MonitoringStorage::COLUMN_STATUS => 'terminated_test', ], ]; private function getService(): MonitoringStorage { if (!$this->service) { $this->service = new MonitoringStorage([ MonitoringStorage::OPTION_PERSISTENCE => 'test_monitoring', MonitoringStorage::OPTION_PRIMARY_COLUMNS => array( 'delivery_execution_id', 'status', 'current_assessment_item', 'test_taker', 'authorized_by', 'start_time', 'end_time' ) ]); } return $this->service; } /** * @return common_persistence_Persistence */ private function getPersistence(): common_persistence_Persistence { if (!$this->persistence) { $sqlMock = $this->getSqlMock('test_monitoring'); $cacheMock = $this->getKvMock('cache'); $this->persistence = $sqlMock->getPersistenceById('test_monitoring'); DbSetup::generateTable($this->persistence); $pmMock = $this->getMockBuilder(PersistenceManager::class) ->setMethods(['getPersistenceById']) ->getMock(); $pmMock->method('getPersistenceById') ->willReturnCallback(static function ($persistenceId) use ($sqlMock, $cacheMock) { if ($persistenceId === 'cache') { return $cacheMock->getPersistenceById('cache'); } if ($persistenceId === 'test_monitoring') { return $sqlMock->getPersistenceById('test_monitoring'); } return false; }); $sl = $this->prophesize(ServiceLocatorInterface::class); $sl->get(PersistenceManager::SERVICE_ID)->willReturn($pmMock); $this->getService()->setServiceLocator($sl->reveal()); } return $this->persistence; } public function setUp(): void { $this->getService(); $this->getPersistence(); } public function tearDown(): void { parent::tearDown(); $this->deleteTestData(); } /** * @after * @before */ public function deleteTestData() { $sql = 'DELETE FROM ' . MonitoringStorage::TABLE_NAME . ' WHERE ' . MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID . " LIKE '%_test_record'"; $this->getPersistence()->exec($sql); } public function testPartialSave() { // 1. create regular cache record $dataToUpdate = [ MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_id', MonitoringStorage::COLUMN_STATUS => 'active', ]; $secondaryDataToUpdate = [ 'secondary_data_key' => 'secondary_data_val', 'secondary_data_key_2' => 'secondary_data_val_2', ]; $dataToCheck = $dataToUpdate; $secondaryDataToCheck = $secondaryDataToUpdate; $this->save(false, false, $dataToUpdate, $secondaryDataToUpdate, $dataToCheck, $secondaryDataToCheck); // 2. update partially $dataToCheck = $dataToUpdate; $secondaryDataToCheck = $secondaryDataToUpdate; $dataToUpdate = [ MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_id_STEP_2', ]; $dataToCheck[MonitoringStorage::COLUMN_TEST_TAKER] = 'test_taker_id_STEP_2'; $secondaryDataToUpdate = [ 'secondary_data_key_2' => 'secondary_data_val_2_STEP_2', ]; $secondaryDataToCheck['secondary_data_key_2'] = 'secondary_data_val_2_STEP_2'; $this->save(true, true, $dataToUpdate, $secondaryDataToUpdate, $dataToCheck, $secondaryDataToCheck); } public function testSaveFallbackAfterInsertFailed() { // 1. create regular cache record $dataToUpdate = [ MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_id', MonitoringStorage::COLUMN_STATUS => 'active', ]; $secondaryDataToUpdate = [ 'secondary_data_key' => 'secondary_data_val', 'secondary_data_key_2' => 'secondary_data_val_2', ]; $dataToCheck = $dataToUpdate; $secondaryDataToCheck = $secondaryDataToUpdate; $this->save(false, false, $dataToUpdate, $secondaryDataToUpdate, $dataToCheck, $secondaryDataToCheck); // 2. check fallback of partialSave() (insert fails, update works) $dataToCheck = $dataToUpdate; $dataToUpdate[MonitoringStorage::COLUMN_TEST_TAKER] = 'test_taker_id_STEP_2'; $dataToCheck[MonitoringStorage::COLUMN_TEST_TAKER] = 'test_taker_id_STEP_2'; $secondaryDataToUpdate['secondary_data_key_2'] = 'secondary_data_val_2_STEP_2'; $secondaryDataToCheck['secondary_data_key_2'] = 'secondary_data_val_2_STEP_2'; $this->save(false, true, $dataToUpdate, $secondaryDataToUpdate, $dataToCheck, $secondaryDataToCheck); } public function testSaveFallbackAfterUpdateReturns0Rows() { // 1. create regular cache record $dataToUpdate = [ MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_id', MonitoringStorage::COLUMN_STATUS => 'active', ]; $secondaryDataToUpdate = [ 'secondary_data_key' => 'secondary_data_val', 'secondary_data_key_2' => 'secondary_data_val_2', ]; $dataToCheck = $dataToUpdate; $secondaryDataToCheck = $secondaryDataToUpdate; $this->save(false, true, $dataToUpdate, $secondaryDataToUpdate, $dataToCheck, $secondaryDataToCheck); } /** * @param $partialModel * @param $saveAsPartial * @param array $dataToUpdate * @param array $secondaryDataToUpdate * @param array $dataToCheck * @param array $secondaryDataToCheck * @throws \common_exception_NotFound */ protected function save($partialModel, $saveAsPartial, array $dataToUpdate, array $secondaryDataToUpdate, array $dataToCheck, array $secondaryDataToCheck) { $deliveryExecution = $this->getDeliveryExecution($this->deliveryExecutionId, 'active'); if ($partialModel) { $dataModel = $this->service->createMonitoringData($deliveryExecution); } else { $dataModel = $this->service->getData($deliveryExecution); } foreach ($dataToUpdate as $key => $val) { $dataModel->addValue($key, $val, true); } foreach ($secondaryDataToUpdate as $secKey => $secVal) { $dataModel->addValue($secKey, $secVal, true); } if ($saveAsPartial) { $saveResult = $this->service->partialSave($dataModel); } else { $saveResult = $this->service->save($dataModel); } $this->assertTrue($saveResult); $this->assertEmpty($dataModel->getErrors()); $insertedData = $this->getRecordByDeliveryExecutionId($this->deliveryExecutionId); $this->assertNotEmpty($insertedData); $this->assertEquals(1, count($insertedData)); $this->assertEquals('active', $insertedData[0][MonitoringStorage::COLUMN_STATUS]); foreach ($dataToCheck as $key => $val) { $this->assertEquals($insertedData[0][$key], $val); } // check key value data $service = $this->service; $insertedKvData = $this->getKvRecordsByParentId($insertedData[0][$service::COLUMN_ID]); $this->assertNotEmpty($insertedKvData); $insertedKvDataNotEmptyFieldCount = 0; foreach ($insertedKvData as $fieldData) { $fieldValue = $fieldData[MonitoringStorage::KV_COLUMN_VALUE]; if ($fieldValue !== null) { $insertedKvDataNotEmptyFieldCount++; } } $this->assertEquals(count($secondaryDataToCheck), $insertedKvDataNotEmptyFieldCount); foreach ($insertedKvData as $kvData) { $key = $kvData[MonitoringStorage::KV_COLUMN_KEY]; $val = $kvData[MonitoringStorage::KV_COLUMN_VALUE]; if ($val !== null) { $this->assertTrue(isset($secondaryDataToCheck[$key])); $this->assertEquals($secondaryDataToCheck[$key], $val); } } } public function testDelete() { $data = [ MonitoringStorage::COLUMN_TEST_TAKER => 'test_taker_id', MonitoringStorage::COLUMN_STATUS => 'active', 'secondary_data_key' => 'secondary_data_val', 'secondary_data_key_2' => 'secondary_data_val_2', ]; $dataModel = $this->service->getData($this->getDeliveryExecution()); foreach ($data as $key => $val) { $dataModel->addValue($key, $val); } $this->assertTrue($this->service->save($dataModel)); $insertedData = $this->getRecordByDeliveryExecutionId($this->deliveryExecutionId); $this->assertNotEmpty($insertedData); $this->assertTrue($this->service->delete($dataModel)); $insertedData = $this->getRecordByDeliveryExecutionId($this->deliveryExecutionId); $this->assertEmpty($insertedData); } public function testFind() { $this->loadFixture(); $result = $this->service->find([ [MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554175_test_record'] ]); $this->assertEquals(count($result), 1); $this->assertEquals($result[0]->get()[MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID], 'http://sample/first.rdf#i1450191587554175_test_record'); $result = $this->service->find([ ['error_code' => '1'], 'OR', ['error_code' => '2'], ]); $this->assertEquals(count($result), 2); $result = $this->service->find([ ['error_code' => '1'], 'AND', ['session_id' => 'i1450191587554175'], ]); $this->assertEquals(count($result), 1); $result = $this->service->find([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ['error_code' => '1'], ]); $this->assertEquals(count($result), 0); $result = $this->service->find([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], 'AND', [['error_code' => '0'], 'OR', ['error_code' => '1']], ]); $this->assertEquals(count($result), 1); $result = $this->service->find([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ['error_code' => '0'], ]); $this->assertEquals(count($result), 1); $this->assertEquals($result[0]->get()[MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID], 'http://sample/first.rdf#i1450191587554178_test_record'); $result = $this->service->find([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ['error_code' => '0'], ], [], true); $this->assertEquals(count($result), 1); $this->assertEquals($result[0]->get()[MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID], 'http://sample/first.rdf#i1450191587554178_test_record'); $this->assertEquals($result[0]->get()['error_code'], '0'); $result = $this->service->find([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ], [], true); $this->assertEquals(count($result), 2); foreach ($result as $resultRow) { $this->assertTrue(isset($resultRow->get()['error_code'])); $this->assertTrue(isset($resultRow->get()['session_id'])); } $result = $this->service->find([ ['error_code' => '>=0'], ], ['order' => 'error_code ASC, session_id'], true); $this->assertEquals(count($result), 4); foreach ($result as $rowKey => $resultRow) { $this->assertEquals($rowKey, $resultRow->get()['error_code']); } $result = $this->service->find([ [MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => [ 'http://sample/first.rdf#i1450191587554175_test_record', 'http://sample/first.rdf#i1450191587554176_test_record', 'http://sample/first.rdf#i1450191587554177_test_record' ]], ], ['order' => 'session_id'], true); $this->assertEquals(count($result), 3); $this->assertEquals($result[0]->get()[MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID], 'http://sample/first.rdf#i1450191587554175_test_record'); $this->assertEquals($result[1]->get()[MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID], 'http://sample/first.rdf#i1450191587554176_test_record'); $this->assertEquals($result[2]->get()[MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID], 'http://sample/first.rdf#i1450191587554177_test_record'); } public function testCount() { $this->loadFixture(); $result = $this->service->count(); $this->assertEquals(count($this->fixtureData), $result); $result = $this->service->count([ [MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => 'http://sample/first.rdf#i1450191587554175_test_record'] ]); $this->assertEquals(1, $result); $result = $this->service->count([ ['error_code' => '1'], 'OR', ['error_code' => '2'], ]); $this->assertEquals(2, $result); $result = $this->service->count([ ['error_code' => '1'], 'AND', ['session_id' => 'i1450191587554175'], ]); $this->assertEquals(1, $result); $result = $this->service->count([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ['error_code' => '1'], ]); $this->assertEquals(0, $result); $result = $this->service->count([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], 'AND', [['error_code' => '0'], 'OR', ['error_code' => '1']], ]); $this->assertEquals(1, $result); $result = $this->service->count([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ['error_code' => '0'], ]); $this->assertEquals(1, $result); $result = $this->service->count([ [MonitoringStorage::COLUMN_STATUS => 'finished_test'], ]); $this->assertEquals(2, $result); $result = $this->service->count([ ['error_code' => '>=0'], ]); $this->assertEquals(4, $result); $result = $this->service->count([ [MonitoringStorage::COLUMN_DELIVERY_EXECUTION_ID => [ 'http://sample/first.rdf#i1450191587554175_test_record', 'http://sample/first.rdf#i1450191587554176_test_record', 'http://sample/first.rdf#i1450191587554177_test_record' ]], ]); $this->assertEquals(3, $result); } protected function loadFixture() { $this->setUp(); foreach ($this->fixtureData as $item) { $dataModel = $this->service->getData($this->getDeliveryExecution($item[MonitoringStorage::DELIVERY_EXECUTION_ID])); foreach ($item as $key => $val) { $dataModel->addValue($key, $val); } $this->service->save($dataModel); } return [ [$this->fixtureData], ]; } protected function getRecordByDeliveryExecutionId($id) { $service = $this->service; $sql = 'SELECT * FROM ' . $service::TABLE_NAME . ' WHERE ' . $service::COLUMN_DELIVERY_EXECUTION_ID . '=?'; return $this->persistence->query($sql, [$id])->fetchAll(); } protected function getKvRecordsByParentId($parentId) { $service = $this->service; $sql = 'SELECT * FROM ' . $service::KV_TABLE_NAME . ' WHERE ' . $service::KV_COLUMN_PARENT_ID . '=?'; return $this->persistence->query($sql, [$parentId])->fetchAll(\PDO::FETCH_ASSOC); } protected function getDeliveryExecution($id = null, $state = null) { if ($id === null) { $id = $this->deliveryExecutionId; } $prophet = new \Prophecy\Prophet(); $deliveryExecutionProphecy = $prophet->prophesize('oat\taoDelivery\model\execution\DeliveryExecution'); $deliveryExecutionProphecy->getIdentifier()->willReturn($id); $stateProphecy = $this->prophesize(\core_kernel_classes_Resource::class); $stateProphecy->getUri()->willReturn($state); $deliveryExecutionProphecy->getState()->willReturn($stateProphecy); return $deliveryExecutionProphecy->reveal(); } }