ManagerTest.php 25 KB

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