tao-test/app/taoProctoring/test/integration/monitorCache/DeliveryMonitoringServiceTest.php

558 lines
20 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2015 (original work) Open Assessment Technologies SA;
*
*
*/
namespace oat\taoProctoring\test\integration\monitorCache;
require_once dirname(__FILE__).'/../../../../tao/includes/raw_start.php';
use common_persistence_Persistence;
use common_persistence_SqlPersistence;
use oat\generis\persistence\PersistenceManager;
use oat\tao\test\TaoPhpUnitTestRunner;
use oat\taoProctoring\model\monitorCache\implementation\MonitoringStorage;
use oat\taoProctoring\scripts\install\db\DbSetup;
use Zend\ServiceManager\ServiceLocatorInterface;
/**
* class DeliveryMonitoringData
*
* Represents data model of delivery execution.
*
* @package oat\taoProctoring
* @author Aleh Hutnikau <hutnikau@1pt.com>
*/
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();
}
}