ManagerTest.php 25 KB

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