ManagerTest.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
  4. *
  5. * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
  6. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  7. * @author Joas Schilling <coding@schilljs.com>
  8. * @author Julius Härtl <jus@bitgrid.net>
  9. * @author Roeland Jago Douma <roeland@famdouma.nl>
  10. *
  11. * @license GNU AGPL version 3 or any later version
  12. *
  13. * This program is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU Affero General Public License as
  15. * published by the Free Software Foundation, either version 3 of the
  16. * License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU Affero General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU Affero General Public License
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. *
  26. */
  27. namespace OCA\WorkflowEngine\Tests;
  28. use OC\Files\Config\UserMountCache;
  29. use OC\L10N\L10N;
  30. use OCA\WorkflowEngine\Entity\File;
  31. use OCA\WorkflowEngine\Helper\ScopeContext;
  32. use OCA\WorkflowEngine\Manager;
  33. use OCP\AppFramework\QueryException;
  34. use OCP\EventDispatcher\IEventDispatcher;
  35. use OCP\Files\Events\Node\NodeCreatedEvent;
  36. use OCP\Files\IRootFolder;
  37. use OCP\Files\Mount\IMountManager;
  38. use OCP\ICache;
  39. use OCP\ICacheFactory;
  40. use OCP\IConfig;
  41. use OCP\IDBConnection;
  42. use OCP\IL10N;
  43. use OCP\IServerContainer;
  44. use OCP\IURLGenerator;
  45. use OCP\IUserManager;
  46. use OCP\IUserSession;
  47. use OCP\SystemTag\ISystemTagManager;
  48. use OCP\WorkflowEngine\Events\RegisterEntitiesEvent;
  49. use OCP\WorkflowEngine\ICheck;
  50. use OCP\WorkflowEngine\IEntity;
  51. use OCP\WorkflowEngine\IEntityEvent;
  52. use OCP\WorkflowEngine\IManager;
  53. use OCP\WorkflowEngine\IOperation;
  54. use PHPUnit\Framework\MockObject\MockObject;
  55. use Psr\Log\LoggerInterface;
  56. use Test\TestCase;
  57. /**
  58. * Class ManagerTest
  59. *
  60. * @package OCA\WorkflowEngine\Tests
  61. * @group DB
  62. */
  63. class ManagerTest extends TestCase {
  64. /** @var Manager */
  65. protected $manager;
  66. /** @var MockObject|IDBConnection */
  67. protected $db;
  68. /** @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface */
  69. protected $logger;
  70. /** @var MockObject|IServerContainer */
  71. protected $container;
  72. /** @var MockObject|IUserSession */
  73. protected $session;
  74. /** @var MockObject|L10N */
  75. protected $l;
  76. /** @var MockObject|IEventDispatcher */
  77. protected $dispatcher;
  78. /** @var MockObject|IConfig */
  79. protected $config;
  80. /** @var MockObject|ICacheFactory */
  81. protected $cacheFactory;
  82. protected function setUp(): void {
  83. parent::setUp();
  84. $this->db = \OC::$server->getDatabaseConnection();
  85. $this->container = $this->createMock(IServerContainer::class);
  86. /** @var IL10N|MockObject $l */
  87. $this->l = $this->createMock(IL10N::class);
  88. $this->l->method('t')
  89. ->willReturnCallback(function ($text, $parameters = []) {
  90. return vsprintf($text, $parameters);
  91. });
  92. $this->logger = $this->createMock(LoggerInterface::class);
  93. $this->session = $this->createMock(IUserSession::class);
  94. $this->dispatcher = $this->createMock(IEventDispatcher::class);
  95. $this->config = $this->createMock(IConfig::class);
  96. $this->cacheFactory = $this->createMock(ICacheFactory::class);
  97. $this->manager = new Manager(
  98. \OC::$server->getDatabaseConnection(),
  99. $this->container,
  100. $this->l,
  101. $this->logger,
  102. $this->session,
  103. $this->dispatcher,
  104. $this->config,
  105. $this->cacheFactory
  106. );
  107. $this->clearTables();
  108. }
  109. protected function tearDown(): void {
  110. $this->clearTables();
  111. parent::tearDown();
  112. }
  113. /**
  114. * @return MockObject|ScopeContext
  115. */
  116. protected function buildScope(string $scopeId = null): MockObject {
  117. $scopeContext = $this->createMock(ScopeContext::class);
  118. $scopeContext->expects($this->any())
  119. ->method('getScope')
  120. ->willReturn($scopeId ? IManager::SCOPE_USER : IManager::SCOPE_ADMIN);
  121. $scopeContext->expects($this->any())
  122. ->method('getScopeId')
  123. ->willReturn($scopeId ?? '');
  124. $scopeContext->expects($this->any())
  125. ->method('getHash')
  126. ->willReturn(md5($scopeId ?? ''));
  127. return $scopeContext;
  128. }
  129. public function clearTables() {
  130. $query = $this->db->getQueryBuilder();
  131. foreach (['flow_checks', 'flow_operations', 'flow_operations_scope'] as $table) {
  132. $query->delete($table)
  133. ->execute();
  134. }
  135. }
  136. public function testChecks() {
  137. $check1 = $this->invokePrivate($this->manager, 'addCheck', ['Test', 'equal', 1]);
  138. $check2 = $this->invokePrivate($this->manager, 'addCheck', ['Test', '!equal', 2]);
  139. $data = $this->manager->getChecks([$check1]);
  140. $this->assertArrayHasKey($check1, $data);
  141. $this->assertArrayNotHasKey($check2, $data);
  142. $data = $this->manager->getChecks([$check1, $check2]);
  143. $this->assertArrayHasKey($check1, $data);
  144. $this->assertArrayHasKey($check2, $data);
  145. $data = $this->manager->getChecks([$check2, $check1]);
  146. $this->assertArrayHasKey($check1, $data);
  147. $this->assertArrayHasKey($check2, $data);
  148. $data = $this->manager->getChecks([$check2]);
  149. $this->assertArrayNotHasKey($check1, $data);
  150. $this->assertArrayHasKey($check2, $data);
  151. }
  152. public function testScope() {
  153. $adminScope = $this->buildScope();
  154. $userScope = $this->buildScope('jackie');
  155. $entity = File::class;
  156. $opId1 = $this->invokePrivate(
  157. $this->manager,
  158. 'insertOperation',
  159. ['OCA\WFE\TestOp', 'Test01', [11, 22], 'foo', $entity, []]
  160. );
  161. $this->invokePrivate($this->manager, 'addScope', [$opId1, $adminScope]);
  162. $opId2 = $this->invokePrivate(
  163. $this->manager,
  164. 'insertOperation',
  165. ['OCA\WFE\TestOp', 'Test02', [33, 22], 'bar', $entity, []]
  166. );
  167. $this->invokePrivate($this->manager, 'addScope', [$opId2, $userScope]);
  168. $opId3 = $this->invokePrivate(
  169. $this->manager,
  170. 'insertOperation',
  171. ['OCA\WFE\TestOp', 'Test03', [11, 44], 'foobar', $entity, []]
  172. );
  173. $this->invokePrivate($this->manager, 'addScope', [$opId3, $userScope]);
  174. $this->assertTrue($this->invokePrivate($this->manager, 'canModify', [$opId1, $adminScope]));
  175. $this->assertFalse($this->invokePrivate($this->manager, 'canModify', [$opId2, $adminScope]));
  176. $this->assertFalse($this->invokePrivate($this->manager, 'canModify', [$opId3, $adminScope]));
  177. $this->assertFalse($this->invokePrivate($this->manager, 'canModify', [$opId1, $userScope]));
  178. $this->assertTrue($this->invokePrivate($this->manager, 'canModify', [$opId2, $userScope]));
  179. $this->assertTrue($this->invokePrivate($this->manager, 'canModify', [$opId3, $userScope]));
  180. }
  181. public function testGetAllOperations() {
  182. $adminScope = $this->buildScope();
  183. $userScope = $this->buildScope('jackie');
  184. $entity = File::class;
  185. $adminOperation = $this->createMock(IOperation::class);
  186. $adminOperation->expects($this->any())
  187. ->method('isAvailableForScope')
  188. ->willReturnMap([
  189. [IManager::SCOPE_ADMIN, true],
  190. [IManager::SCOPE_USER, false],
  191. ]);
  192. $userOperation = $this->createMock(IOperation::class);
  193. $userOperation->expects($this->any())
  194. ->method('isAvailableForScope')
  195. ->willReturnMap([
  196. [IManager::SCOPE_ADMIN, false],
  197. [IManager::SCOPE_USER, true],
  198. ]);
  199. $this->container->expects($this->any())
  200. ->method('query')
  201. ->willReturnCallback(function ($className) use ($adminOperation, $userOperation) {
  202. switch ($className) {
  203. case 'OCA\WFE\TestAdminOp':
  204. return $adminOperation;
  205. case 'OCA\WFE\TestUserOp':
  206. return $userOperation;
  207. }
  208. });
  209. $opId1 = $this->invokePrivate(
  210. $this->manager,
  211. 'insertOperation',
  212. ['OCA\WFE\TestAdminOp', 'Test01', [11, 22], 'foo', $entity, []]
  213. );
  214. $this->invokePrivate($this->manager, 'addScope', [$opId1, $adminScope]);
  215. $opId2 = $this->invokePrivate(
  216. $this->manager,
  217. 'insertOperation',
  218. ['OCA\WFE\TestUserOp', 'Test02', [33, 22], 'bar', $entity, []]
  219. );
  220. $this->invokePrivate($this->manager, 'addScope', [$opId2, $userScope]);
  221. $opId3 = $this->invokePrivate(
  222. $this->manager,
  223. 'insertOperation',
  224. ['OCA\WFE\TestUserOp', 'Test03', [11, 44], 'foobar', $entity, []]
  225. );
  226. $this->invokePrivate($this->manager, 'addScope', [$opId3, $userScope]);
  227. $opId4 = $this->invokePrivate(
  228. $this->manager,
  229. 'insertOperation',
  230. ['OCA\WFE\TestAdminOp', 'Test04', [41, 10, 4], 'NoBar', $entity, []]
  231. );
  232. $this->invokePrivate($this->manager, 'addScope', [$opId4, $userScope]);
  233. $adminOps = $this->manager->getAllOperations($adminScope);
  234. $userOps = $this->manager->getAllOperations($userScope);
  235. $this->assertSame(1, count($adminOps));
  236. $this->assertTrue(array_key_exists('OCA\WFE\TestAdminOp', $adminOps));
  237. $this->assertFalse(array_key_exists('OCA\WFE\TestUserOp', $adminOps));
  238. $this->assertSame(1, count($userOps));
  239. $this->assertFalse(array_key_exists('OCA\WFE\TestAdminOp', $userOps));
  240. $this->assertTrue(array_key_exists('OCA\WFE\TestUserOp', $userOps));
  241. $this->assertSame(2, count($userOps['OCA\WFE\TestUserOp']));
  242. }
  243. public function testGetOperations() {
  244. $adminScope = $this->buildScope();
  245. $userScope = $this->buildScope('jackie');
  246. $entity = File::class;
  247. $opId1 = $this->invokePrivate(
  248. $this->manager,
  249. 'insertOperation',
  250. ['OCA\WFE\TestOp', 'Test01', [11, 22], 'foo', $entity, []]
  251. );
  252. $this->invokePrivate($this->manager, 'addScope', [$opId1, $adminScope]);
  253. $opId4 = $this->invokePrivate(
  254. $this->manager,
  255. 'insertOperation',
  256. ['OCA\WFE\OtherTestOp', 'Test04', [5], 'foo', $entity, []]
  257. );
  258. $this->invokePrivate($this->manager, 'addScope', [$opId4, $adminScope]);
  259. $opId2 = $this->invokePrivate(
  260. $this->manager,
  261. 'insertOperation',
  262. ['OCA\WFE\TestOp', 'Test02', [33, 22], 'bar', $entity, []]
  263. );
  264. $this->invokePrivate($this->manager, 'addScope', [$opId2, $userScope]);
  265. $opId3 = $this->invokePrivate(
  266. $this->manager,
  267. 'insertOperation',
  268. ['OCA\WFE\TestOp', 'Test03', [11, 44], 'foobar', $entity, []]
  269. );
  270. $this->invokePrivate($this->manager, 'addScope', [$opId3, $userScope]);
  271. $opId5 = $this->invokePrivate(
  272. $this->manager,
  273. 'insertOperation',
  274. ['OCA\WFE\OtherTestOp', 'Test05', [5], 'foobar', $entity, []]
  275. );
  276. $this->invokePrivate($this->manager, 'addScope', [$opId5, $userScope]);
  277. $operation = $this->createMock(IOperation::class);
  278. $operation->expects($this->any())
  279. ->method('isAvailableForScope')
  280. ->willReturnMap([
  281. [IManager::SCOPE_ADMIN, true],
  282. [IManager::SCOPE_USER, true],
  283. ]);
  284. $this->container->expects($this->any())
  285. ->method('query')
  286. ->willReturnCallback(function ($className) use ($operation) {
  287. switch ($className) {
  288. case 'OCA\WFE\TestOp':
  289. return $operation;
  290. case 'OCA\WFE\OtherTestOp':
  291. throw new QueryException();
  292. }
  293. });
  294. $adminOps = $this->manager->getOperations('OCA\WFE\TestOp', $adminScope);
  295. $userOps = $this->manager->getOperations('OCA\WFE\TestOp', $userScope);
  296. $this->assertSame(1, count($adminOps));
  297. array_walk($adminOps, function ($op) {
  298. $this->assertTrue($op['class'] === 'OCA\WFE\TestOp');
  299. });
  300. $this->assertSame(2, count($userOps));
  301. array_walk($userOps, function ($op) {
  302. $this->assertTrue($op['class'] === 'OCA\WFE\TestOp');
  303. });
  304. }
  305. public function testGetAllConfiguredEvents() {
  306. $adminScope = $this->buildScope();
  307. $userScope = $this->buildScope('jackie');
  308. $entity = File::class;
  309. $opId5 = $this->invokePrivate(
  310. $this->manager,
  311. 'insertOperation',
  312. ['OCA\WFE\OtherTestOp', 'Test04', [], 'foo', $entity, [NodeCreatedEvent::class]]
  313. );
  314. $this->invokePrivate($this->manager, 'addScope', [$opId5, $userScope]);
  315. $allOperations = null;
  316. $cache = $this->createMock(ICache::class);
  317. $cache
  318. ->method('get')
  319. ->willReturnCallback(function () use (&$allOperations) {
  320. if ($allOperations) {
  321. return $allOperations;
  322. }
  323. return null;
  324. });
  325. $this->cacheFactory->method('createDistributed')->willReturn($cache);
  326. $allOperations = $this->manager->getAllConfiguredEvents();
  327. $this->assertCount(1, $allOperations);
  328. $allOperationsCached = $this->manager->getAllConfiguredEvents();
  329. $this->assertCount(1, $allOperationsCached);
  330. $this->assertEquals($allOperationsCached, $allOperations);
  331. }
  332. public function testUpdateOperation() {
  333. $adminScope = $this->buildScope();
  334. $userScope = $this->buildScope('jackie');
  335. $entity = File::class;
  336. $cache = $this->createMock(ICache::class);
  337. $cache->expects($this->exactly(4))
  338. ->method('remove')
  339. ->with('events');
  340. $this->cacheFactory->method('createDistributed')->willReturn($cache);
  341. $operationMock = $this->createMock(IOperation::class);
  342. $operationMock->expects($this->any())
  343. ->method('isAvailableForScope')
  344. ->withConsecutive(
  345. [IManager::SCOPE_ADMIN],
  346. [IManager::SCOPE_USER]
  347. )
  348. ->willReturn(true);
  349. $this->container->expects($this->any())
  350. ->method('query')
  351. ->willReturnCallback(function ($class) use ($operationMock) {
  352. if (substr($class, -2) === 'Op') {
  353. return $operationMock;
  354. } elseif ($class === File::class) {
  355. return $this->getMockBuilder(File::class)
  356. ->setConstructorArgs([
  357. $this->l,
  358. $this->createMock(IURLGenerator::class),
  359. $this->createMock(IRootFolder::class),
  360. $this->createMock(IUserSession::class),
  361. $this->createMock(ISystemTagManager::class),
  362. $this->createMock(IUserManager::class),
  363. $this->createMock(UserMountCache::class),
  364. $this->createMock(IMountManager::class),
  365. ])
  366. ->setMethodsExcept(['getEvents'])
  367. ->getMock();
  368. }
  369. return $this->createMock(ICheck::class);
  370. });
  371. $opId1 = $this->invokePrivate(
  372. $this->manager,
  373. 'insertOperation',
  374. ['OCA\WFE\TestAdminOp', 'Test01', [11, 22], 'foo', $entity, []]
  375. );
  376. $this->invokePrivate($this->manager, 'addScope', [$opId1, $adminScope]);
  377. $opId2 = $this->invokePrivate(
  378. $this->manager,
  379. 'insertOperation',
  380. ['OCA\WFE\TestUserOp', 'Test02', [33, 22], 'bar', $entity, []]
  381. );
  382. $this->invokePrivate($this->manager, 'addScope', [$opId2, $userScope]);
  383. $check1 = ['class' => 'OCA\WFE\C22', 'operator' => 'eq', 'value' => 'asdf'];
  384. $check2 = ['class' => 'OCA\WFE\C33', 'operator' => 'eq', 'value' => 23456];
  385. /** @noinspection PhpUnhandledExceptionInspection */
  386. $op = $this->manager->updateOperation($opId1, 'Test01a', [$check1, $check2], 'foohur', $adminScope, $entity, ['\OCP\Files::postDelete']);
  387. $this->assertSame('Test01a', $op['name']);
  388. $this->assertSame('foohur', $op['operation']);
  389. /** @noinspection PhpUnhandledExceptionInspection */
  390. $op = $this->manager->updateOperation($opId2, 'Test02a', [$check1], 'barfoo', $userScope, $entity, ['\OCP\Files::postDelete']);
  391. $this->assertSame('Test02a', $op['name']);
  392. $this->assertSame('barfoo', $op['operation']);
  393. foreach ([[$adminScope, $opId2], [$userScope, $opId1]] as $run) {
  394. try {
  395. /** @noinspection PhpUnhandledExceptionInspection */
  396. $this->manager->updateOperation($run[1], 'Evil', [$check2], 'hackx0r', $run[0], $entity, []);
  397. $this->assertTrue(false, 'DomainException not thrown');
  398. } catch (\DomainException $e) {
  399. $this->assertTrue(true);
  400. }
  401. }
  402. }
  403. public function testDeleteOperation() {
  404. $adminScope = $this->buildScope();
  405. $userScope = $this->buildScope('jackie');
  406. $entity = File::class;
  407. $cache = $this->createMock(ICache::class);
  408. $cache->expects($this->exactly(4))
  409. ->method('remove')
  410. ->with('events');
  411. $this->cacheFactory->method('createDistributed')->willReturn($cache);
  412. $opId1 = $this->invokePrivate(
  413. $this->manager,
  414. 'insertOperation',
  415. ['OCA\WFE\TestAdminOp', 'Test01', [11, 22], 'foo', $entity, []]
  416. );
  417. $this->invokePrivate($this->manager, 'addScope', [$opId1, $adminScope]);
  418. $opId2 = $this->invokePrivate(
  419. $this->manager,
  420. 'insertOperation',
  421. ['OCA\WFE\TestUserOp', 'Test02', [33, 22], 'bar', $entity, []]
  422. );
  423. $this->invokePrivate($this->manager, 'addScope', [$opId2, $userScope]);
  424. foreach ([[$adminScope, $opId2], [$userScope, $opId1]] as $run) {
  425. try {
  426. /** @noinspection PhpUnhandledExceptionInspection */
  427. $this->manager->deleteOperation($run[1], $run[0]);
  428. $this->assertTrue(false, 'DomainException not thrown');
  429. } catch (\Exception $e) {
  430. $this->assertInstanceOf(\DomainException::class, $e);
  431. }
  432. }
  433. /** @noinspection PhpUnhandledExceptionInspection */
  434. $this->manager->deleteOperation($opId1, $adminScope);
  435. /** @noinspection PhpUnhandledExceptionInspection */
  436. $this->manager->deleteOperation($opId2, $userScope);
  437. foreach ([$opId1, $opId2] as $opId) {
  438. try {
  439. $this->invokePrivate($this->manager, 'getOperation', [$opId]);
  440. $this->assertTrue(false, 'UnexpectedValueException not thrown');
  441. } catch (\Exception $e) {
  442. $this->assertInstanceOf(\UnexpectedValueException::class, $e);
  443. }
  444. }
  445. }
  446. public function testGetEntitiesListBuildInOnly() {
  447. $fileEntityMock = $this->createMock(File::class);
  448. $this->container->expects($this->once())
  449. ->method('query')
  450. ->with(File::class)
  451. ->willReturn($fileEntityMock);
  452. $entities = $this->manager->getEntitiesList();
  453. $this->assertCount(1, $entities);
  454. $this->assertInstanceOf(IEntity::class, $entities[0]);
  455. }
  456. public function testGetEntitiesList() {
  457. $fileEntityMock = $this->createMock(File::class);
  458. $this->container->expects($this->once())
  459. ->method('query')
  460. ->with(File::class)
  461. ->willReturn($fileEntityMock);
  462. /** @var MockObject|IEntity $extraEntity */
  463. $extraEntity = $this->createMock(IEntity::class);
  464. $this->dispatcher->expects($this->once())
  465. ->method('dispatchTyped')
  466. ->willReturnCallback(function (RegisterEntitiesEvent $e) use ($extraEntity) {
  467. $this->manager->registerEntity($extraEntity);
  468. });
  469. $entities = $this->manager->getEntitiesList();
  470. $this->assertCount(2, $entities);
  471. $entityTypeCounts = array_reduce($entities, function (array $carry, IEntity $entity) {
  472. if ($entity instanceof File) {
  473. $carry[0]++;
  474. } elseif ($entity instanceof IEntity) {
  475. $carry[1]++;
  476. }
  477. return $carry;
  478. }, [0, 0]);
  479. $this->assertSame(1, $entityTypeCounts[0]);
  480. $this->assertSame(1, $entityTypeCounts[1]);
  481. }
  482. public function testValidateOperationOK() {
  483. $check = [
  484. 'class' => ICheck::class,
  485. 'operator' => 'is',
  486. 'value' => 'barfoo',
  487. ];
  488. $operationMock = $this->createMock(IOperation::class);
  489. $entityMock = $this->createMock(IEntity::class);
  490. $eventEntityMock = $this->createMock(IEntityEvent::class);
  491. $checkMock = $this->createMock(ICheck::class);
  492. $scopeMock = $this->createMock(ScopeContext::class);
  493. $scopeMock->expects($this->any())
  494. ->method('getScope')
  495. ->willReturn(IManager::SCOPE_ADMIN);
  496. $operationMock->expects($this->once())
  497. ->method('isAvailableForScope')
  498. ->with(IManager::SCOPE_ADMIN)
  499. ->willReturn(true);
  500. $operationMock->expects($this->once())
  501. ->method('validateOperation')
  502. ->with('test', [$check], 'operationData');
  503. $entityMock->expects($this->any())
  504. ->method('getEvents')
  505. ->willReturn([$eventEntityMock]);
  506. $eventEntityMock->expects($this->any())
  507. ->method('getEventName')
  508. ->willReturn('MyEvent');
  509. $checkMock->expects($this->any())
  510. ->method('supportedEntities')
  511. ->willReturn([IEntity::class]);
  512. $checkMock->expects($this->atLeastOnce())
  513. ->method('validateCheck');
  514. $this->container->expects($this->any())
  515. ->method('query')
  516. ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
  517. switch ($className) {
  518. case IOperation::class:
  519. return $operationMock;
  520. case IEntity::class:
  521. return $entityMock;
  522. case IEntityEvent::class:
  523. return $eventEntityMock;
  524. case ICheck::class:
  525. return $checkMock;
  526. default:
  527. return $this->createMock($className);
  528. }
  529. });
  530. $this->manager->validateOperation(IOperation::class, 'test', [$check], 'operationData', $scopeMock, IEntity::class, ['MyEvent']);
  531. }
  532. public function testValidateOperationCheckInputLengthError() {
  533. $check = [
  534. 'class' => ICheck::class,
  535. 'operator' => 'is',
  536. 'value' => str_pad('', IManager::MAX_CHECK_VALUE_BYTES + 1, 'FooBar'),
  537. ];
  538. $operationMock = $this->createMock(IOperation::class);
  539. $entityMock = $this->createMock(IEntity::class);
  540. $eventEntityMock = $this->createMock(IEntityEvent::class);
  541. $checkMock = $this->createMock(ICheck::class);
  542. $scopeMock = $this->createMock(ScopeContext::class);
  543. $scopeMock->expects($this->any())
  544. ->method('getScope')
  545. ->willReturn(IManager::SCOPE_ADMIN);
  546. $operationMock->expects($this->once())
  547. ->method('isAvailableForScope')
  548. ->with(IManager::SCOPE_ADMIN)
  549. ->willReturn(true);
  550. $operationMock->expects($this->once())
  551. ->method('validateOperation')
  552. ->with('test', [$check], 'operationData');
  553. $entityMock->expects($this->any())
  554. ->method('getEvents')
  555. ->willReturn([$eventEntityMock]);
  556. $eventEntityMock->expects($this->any())
  557. ->method('getEventName')
  558. ->willReturn('MyEvent');
  559. $checkMock->expects($this->any())
  560. ->method('supportedEntities')
  561. ->willReturn([IEntity::class]);
  562. $checkMock->expects($this->never())
  563. ->method('validateCheck');
  564. $this->container->expects($this->any())
  565. ->method('query')
  566. ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
  567. switch ($className) {
  568. case IOperation::class:
  569. return $operationMock;
  570. case IEntity::class:
  571. return $entityMock;
  572. case IEntityEvent::class:
  573. return $eventEntityMock;
  574. case ICheck::class:
  575. return $checkMock;
  576. default:
  577. return $this->createMock($className);
  578. }
  579. });
  580. try {
  581. $this->manager->validateOperation(IOperation::class, 'test', [$check], 'operationData', $scopeMock, IEntity::class, ['MyEvent']);
  582. } catch (\UnexpectedValueException $e) {
  583. $this->assertSame('The provided check value is too long', $e->getMessage());
  584. }
  585. }
  586. public function testValidateOperationDataLengthError() {
  587. $check = [
  588. 'class' => ICheck::class,
  589. 'operator' => 'is',
  590. 'value' => 'barfoo',
  591. ];
  592. $operationData = str_pad('', IManager::MAX_OPERATION_VALUE_BYTES + 1, 'FooBar');
  593. $operationMock = $this->createMock(IOperation::class);
  594. $entityMock = $this->createMock(IEntity::class);
  595. $eventEntityMock = $this->createMock(IEntityEvent::class);
  596. $checkMock = $this->createMock(ICheck::class);
  597. $scopeMock = $this->createMock(ScopeContext::class);
  598. $scopeMock->expects($this->any())
  599. ->method('getScope')
  600. ->willReturn(IManager::SCOPE_ADMIN);
  601. $operationMock->expects($this->once())
  602. ->method('isAvailableForScope')
  603. ->with(IManager::SCOPE_ADMIN)
  604. ->willReturn(true);
  605. $operationMock->expects($this->never())
  606. ->method('validateOperation');
  607. $entityMock->expects($this->any())
  608. ->method('getEvents')
  609. ->willReturn([$eventEntityMock]);
  610. $eventEntityMock->expects($this->any())
  611. ->method('getEventName')
  612. ->willReturn('MyEvent');
  613. $checkMock->expects($this->any())
  614. ->method('supportedEntities')
  615. ->willReturn([IEntity::class]);
  616. $checkMock->expects($this->never())
  617. ->method('validateCheck');
  618. $this->container->expects($this->any())
  619. ->method('query')
  620. ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
  621. switch ($className) {
  622. case IOperation::class:
  623. return $operationMock;
  624. case IEntity::class:
  625. return $entityMock;
  626. case IEntityEvent::class:
  627. return $eventEntityMock;
  628. case ICheck::class:
  629. return $checkMock;
  630. default:
  631. return $this->createMock($className);
  632. }
  633. });
  634. try {
  635. $this->manager->validateOperation(IOperation::class, 'test', [$check], $operationData, $scopeMock, IEntity::class, ['MyEvent']);
  636. } catch (\UnexpectedValueException $e) {
  637. $this->assertSame('The provided operation data is too long', $e->getMessage());
  638. }
  639. }
  640. public function testValidateOperationScopeNotAvailable() {
  641. $check = [
  642. 'class' => ICheck::class,
  643. 'operator' => 'is',
  644. 'value' => 'barfoo',
  645. ];
  646. $operationData = str_pad('', IManager::MAX_OPERATION_VALUE_BYTES + 1, 'FooBar');
  647. $operationMock = $this->createMock(IOperation::class);
  648. $entityMock = $this->createMock(IEntity::class);
  649. $eventEntityMock = $this->createMock(IEntityEvent::class);
  650. $checkMock = $this->createMock(ICheck::class);
  651. $scopeMock = $this->createMock(ScopeContext::class);
  652. $scopeMock->expects($this->any())
  653. ->method('getScope')
  654. ->willReturn(IManager::SCOPE_ADMIN);
  655. $operationMock->expects($this->once())
  656. ->method('isAvailableForScope')
  657. ->with(IManager::SCOPE_ADMIN)
  658. ->willReturn(false);
  659. $operationMock->expects($this->never())
  660. ->method('validateOperation');
  661. $entityMock->expects($this->any())
  662. ->method('getEvents')
  663. ->willReturn([$eventEntityMock]);
  664. $eventEntityMock->expects($this->any())
  665. ->method('getEventName')
  666. ->willReturn('MyEvent');
  667. $checkMock->expects($this->any())
  668. ->method('supportedEntities')
  669. ->willReturn([IEntity::class]);
  670. $checkMock->expects($this->never())
  671. ->method('validateCheck');
  672. $this->container->expects($this->any())
  673. ->method('query')
  674. ->willReturnCallback(function ($className) use ($operationMock, $entityMock, $eventEntityMock, $checkMock) {
  675. switch ($className) {
  676. case IOperation::class:
  677. return $operationMock;
  678. case IEntity::class:
  679. return $entityMock;
  680. case IEntityEvent::class:
  681. return $eventEntityMock;
  682. case ICheck::class:
  683. return $checkMock;
  684. default:
  685. return $this->createMock($className);
  686. }
  687. });
  688. try {
  689. $this->manager->validateOperation(IOperation::class, 'test', [$check], $operationData, $scopeMock, IEntity::class, ['MyEvent']);
  690. } catch (\UnexpectedValueException $e) {
  691. $this->assertSame('Operation OCP\WorkflowEngine\IOperation is invalid', $e->getMessage());
  692. }
  693. }
  694. }