ManagerTest.php 25 KB

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