SettingTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace Tests\Core\Command\User;
  8. use OC\Core\Command\User\Setting;
  9. use OCP\IConfig;
  10. use OCP\IDBConnection;
  11. use OCP\IUserManager;
  12. use Symfony\Component\Console\Input\InputInterface;
  13. use Symfony\Component\Console\Output\OutputInterface;
  14. use Test\TestCase;
  15. class SettingTest extends TestCase {
  16. /** @var \OCP\IUserManager|\PHPUnit\Framework\MockObject\MockObject */
  17. protected $userManager;
  18. /** @var \OCP\IConfig|\PHPUnit\Framework\MockObject\MockObject */
  19. protected $config;
  20. /** @var \OCP\IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
  21. protected $connection;
  22. /** @var \Symfony\Component\Console\Input\InputInterface|\PHPUnit\Framework\MockObject\MockObject */
  23. protected $consoleInput;
  24. /** @var \Symfony\Component\Console\Output\OutputInterface|\PHPUnit\Framework\MockObject\MockObject */
  25. protected $consoleOutput;
  26. protected function setUp(): void {
  27. parent::setUp();
  28. $this->userManager = $this->getMockBuilder(IUserManager::class)
  29. ->disableOriginalConstructor()
  30. ->getMock();
  31. $this->config = $this->getMockBuilder(IConfig::class)
  32. ->disableOriginalConstructor()
  33. ->getMock();
  34. $this->connection = $this->getMockBuilder(IDBConnection::class)
  35. ->disableOriginalConstructor()
  36. ->getMock();
  37. $this->consoleInput = $this->getMockBuilder(InputInterface::class)
  38. ->disableOriginalConstructor()
  39. ->getMock();
  40. $this->consoleOutput = $this->getMockBuilder(OutputInterface::class)
  41. ->disableOriginalConstructor()
  42. ->getMock();
  43. }
  44. public function getCommand(array $methods = []) {
  45. if (empty($methods)) {
  46. return new Setting($this->userManager, $this->config);
  47. } else {
  48. $mock = $this->getMockBuilder(Setting::class)
  49. ->setConstructorArgs([
  50. $this->userManager,
  51. $this->config,
  52. ])
  53. ->onlyMethods($methods)
  54. ->getMock();
  55. return $mock;
  56. }
  57. }
  58. public function dataCheckInput() {
  59. return [
  60. [
  61. [['uid', 'username']],
  62. [['ignore-missing-user', true]],
  63. [],
  64. false,
  65. false,
  66. ],
  67. [
  68. [['uid', 'username']],
  69. [['ignore-missing-user', false]],
  70. [],
  71. null,
  72. 'The user "username" does not exist.',
  73. ],
  74. [
  75. [['uid', 'username'], ['key', 'configkey']],
  76. [['ignore-missing-user', true]],
  77. [['--default-value', false, true]],
  78. false,
  79. false,
  80. ],
  81. [
  82. [['uid', 'username'], ['key', '']],
  83. [['ignore-missing-user', true]],
  84. [['--default-value', false, true]],
  85. false,
  86. 'The "default-value" option can only be used when specifying a key.',
  87. ],
  88. [
  89. [['uid', 'username'], ['key', 'configkey'], ['value', '']],
  90. [['ignore-missing-user', true]],
  91. [],
  92. false,
  93. false,
  94. ],
  95. [
  96. [['uid', 'username'], ['key', ''], ['value', '']],
  97. [['ignore-missing-user', true]],
  98. [],
  99. false,
  100. 'The value argument can only be used when specifying a key.',
  101. ],
  102. [
  103. [['uid', 'username'], ['key', 'configkey'], ['value', '']],
  104. [['ignore-missing-user', true]],
  105. [['--default-value', false, true]],
  106. false,
  107. 'The value argument can not be used together with "default-value".',
  108. ],
  109. [
  110. [['uid', 'username'], ['key', 'configkey'], ['value', '']],
  111. [['ignore-missing-user', true], ['update-only', true]],
  112. [],
  113. false,
  114. false,
  115. ],
  116. [
  117. [['uid', 'username'], ['key', 'configkey'], ['value', null]],
  118. [['ignore-missing-user', true], ['update-only', true]],
  119. [],
  120. false,
  121. 'The "update-only" option can only be used together with "value".',
  122. ],
  123. [
  124. [['uid', 'username'], ['key', 'configkey']],
  125. [['ignore-missing-user', true], ['delete', true]],
  126. [],
  127. false,
  128. false,
  129. ],
  130. [
  131. [['uid', 'username'], ['key', '']],
  132. [['ignore-missing-user', true], ['delete', true]],
  133. [],
  134. false,
  135. 'The "delete" option can only be used when specifying a key.',
  136. ],
  137. [
  138. [['uid', 'username'], ['key', 'configkey']],
  139. [['ignore-missing-user', true], ['delete', true]],
  140. [['--default-value', false, true]],
  141. false,
  142. 'The "delete" option can not be used together with "default-value".',
  143. ],
  144. [
  145. [['uid', 'username'], ['key', 'configkey'], ['value', '']],
  146. [['ignore-missing-user', true], ['delete', true]],
  147. [],
  148. false,
  149. 'The "delete" option can not be used together with "value".',
  150. ],
  151. [
  152. [['uid', 'username'], ['key', 'configkey']],
  153. [['ignore-missing-user', true], ['delete', true], ['error-if-not-exists', true]],
  154. [],
  155. false,
  156. false,
  157. ],
  158. [
  159. [['uid', 'username'], ['key', 'configkey']],
  160. [['ignore-missing-user', true], ['delete', false], ['error-if-not-exists', true]],
  161. [],
  162. false,
  163. 'The "error-if-not-exists" option can only be used together with "delete".',
  164. ],
  165. ];
  166. }
  167. /**
  168. * @dataProvider dataCheckInput
  169. *
  170. * @param array $arguments
  171. * @param array $options
  172. * @param array $parameterOptions
  173. * @param mixed $user
  174. * @param string $expectedException
  175. */
  176. public function testCheckInput($arguments, $options, $parameterOptions, $user, $expectedException): void {
  177. $this->consoleInput->expects($this->any())
  178. ->method('getArgument')
  179. ->willReturnMap($arguments);
  180. $this->consoleInput->expects($this->any())
  181. ->method('getOption')
  182. ->willReturnMap($options);
  183. $this->consoleInput->expects($this->any())
  184. ->method('hasParameterOption')
  185. ->willReturnCallback(function (string|array $config, bool $default = false) use ($parameterOptions): bool {
  186. foreach ($parameterOptions as $parameterOption) {
  187. if ($config === $parameterOption[0]
  188. // Check the default value if the maps has 3 entries
  189. && (!isset($parameterOption[2]) || $default === $parameterOption[1])) {
  190. return end($parameterOption);
  191. }
  192. }
  193. return false;
  194. });
  195. if ($user !== false) {
  196. $this->userManager->expects($this->once())
  197. ->method('get')
  198. ->willReturn($user);
  199. } else {
  200. $this->userManager->expects($this->never())
  201. ->method('get');
  202. }
  203. $command = $this->getCommand();
  204. try {
  205. $this->invokePrivate($command, 'checkInput', [$this->consoleInput]);
  206. $this->assertFalse($expectedException);
  207. } catch (\InvalidArgumentException $e) {
  208. $this->assertEquals($expectedException, $e->getMessage());
  209. }
  210. }
  211. public function testCheckInputExceptionCatch(): void {
  212. $command = $this->getCommand(['checkInput']);
  213. $command->expects($this->once())
  214. ->method('checkInput')
  215. ->willThrowException(new \InvalidArgumentException('test'));
  216. $this->consoleOutput->expects($this->once())
  217. ->method('writeln')
  218. ->with('<error>test</error>');
  219. $this->assertEquals(1, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
  220. }
  221. public function dataExecuteDelete() {
  222. return [
  223. ['config', false, null, 0],
  224. ['config', true, null, 0],
  225. [null, false, null, 0],
  226. [null, true, '<error>The setting does not exist for user "username".</error>', 1],
  227. ];
  228. }
  229. /**
  230. * @dataProvider dataExecuteDelete
  231. *
  232. * @param string|null $value
  233. * @param bool $errorIfNotExists
  234. * @param string $expectedLine
  235. * @param int $expectedReturn
  236. */
  237. public function testExecuteDelete($value, $errorIfNotExists, $expectedLine, $expectedReturn): void {
  238. $command = $this->getCommand([
  239. 'writeArrayInOutputFormat',
  240. 'checkInput',
  241. 'getUserSettings',
  242. ]);
  243. $this->consoleInput->expects($this->any())
  244. ->method('getArgument')
  245. ->willReturnMap([
  246. ['uid', 'username'],
  247. ['app', 'appname'],
  248. ['key', 'configkey'],
  249. ]);
  250. $command->expects($this->once())
  251. ->method('checkInput');
  252. $this->config->expects($this->once())
  253. ->method('getUserValue')
  254. ->with('username', 'appname', 'configkey', null)
  255. ->willReturn($value);
  256. $this->consoleInput->expects($this->atLeastOnce())
  257. ->method('hasParameterOption')
  258. ->willReturnMap([
  259. ['--delete', false, true],
  260. ['--error-if-not-exists', false, $errorIfNotExists],
  261. ]);
  262. if ($expectedLine === null) {
  263. $this->consoleOutput->expects($this->never())
  264. ->method('writeln');
  265. $this->config->expects($this->once())
  266. ->method('deleteUserValue')
  267. ->with('username', 'appname', 'configkey');
  268. } else {
  269. $this->consoleOutput->expects($this->once())
  270. ->method('writeln')
  271. ->with($expectedLine);
  272. $this->config->expects($this->never())
  273. ->method('deleteUserValue');
  274. }
  275. $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
  276. }
  277. public function dataExecuteSet() {
  278. return [
  279. ['config', false, null, 0],
  280. ['config', true, null, 0],
  281. [null, false, null, 0],
  282. [null, true, '<error>The setting does not exist for user "username".</error>', 1],
  283. ];
  284. }
  285. /**
  286. * @dataProvider dataExecuteSet
  287. *
  288. * @param string|null $value
  289. * @param bool $updateOnly
  290. * @param string $expectedLine
  291. * @param int $expectedReturn
  292. */
  293. public function testExecuteSet($value, $updateOnly, $expectedLine, $expectedReturn): void {
  294. $command = $this->getCommand([
  295. 'writeArrayInOutputFormat',
  296. 'checkInput',
  297. 'getUserSettings',
  298. ]);
  299. $this->consoleInput->expects($this->atLeast(4))
  300. ->method('getArgument')
  301. ->willReturnMap([
  302. ['uid', 'username'],
  303. ['app', 'appname'],
  304. ['key', 'configkey'],
  305. ['value', 'setValue'],
  306. ]);
  307. $command->expects($this->once())
  308. ->method('checkInput');
  309. $this->config->expects($this->once())
  310. ->method('getUserValue')
  311. ->with('username', 'appname', 'configkey', null)
  312. ->willReturn($value);
  313. $this->consoleInput->expects($this->atLeastOnce())
  314. ->method('hasParameterOption')
  315. ->willReturnMap([
  316. ['--update-only', false, $updateOnly],
  317. ]);
  318. if ($expectedLine === null) {
  319. $this->consoleOutput->expects($this->never())
  320. ->method('writeln');
  321. $this->consoleInput->expects($this->never())
  322. ->method('getOption');
  323. $this->config->expects($this->once())
  324. ->method('setUserValue')
  325. ->with('username', 'appname', 'configkey', 'setValue');
  326. } else {
  327. $this->consoleOutput->expects($this->once())
  328. ->method('writeln')
  329. ->with($expectedLine);
  330. $this->config->expects($this->never())
  331. ->method('setUserValue');
  332. }
  333. $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
  334. }
  335. public function dataExecuteGet() {
  336. return [
  337. ['config', null, 'config', 0],
  338. [null, 'config', 'config', 0],
  339. [null, null, '<error>The setting does not exist for user "username".</error>', 1],
  340. ];
  341. }
  342. /**
  343. * @dataProvider dataExecuteGet
  344. *
  345. * @param string|null $value
  346. * @param string|null $defaultValue
  347. * @param string $expectedLine
  348. * @param int $expectedReturn
  349. */
  350. public function testExecuteGet($value, $defaultValue, $expectedLine, $expectedReturn): void {
  351. $command = $this->getCommand([
  352. 'writeArrayInOutputFormat',
  353. 'checkInput',
  354. 'getUserSettings',
  355. ]);
  356. $this->consoleInput->expects($this->any())
  357. ->method('getArgument')
  358. ->willReturnMap([
  359. ['uid', 'username'],
  360. ['app', 'appname'],
  361. ['key', 'configkey'],
  362. ]);
  363. $command->expects($this->once())
  364. ->method('checkInput');
  365. $this->config->expects($this->once())
  366. ->method('getUserValue')
  367. ->with('username', 'appname', 'configkey', null)
  368. ->willReturn($value);
  369. if ($value === null) {
  370. if ($defaultValue === null) {
  371. $this->consoleInput->expects($this->atLeastOnce())
  372. ->method('hasParameterOption')
  373. ->willReturn(false);
  374. } else {
  375. $this->consoleInput->expects($this->atLeastOnce())
  376. ->method('hasParameterOption')
  377. ->willReturnCallback(function (string|array $config, bool $default = false): bool {
  378. if ($config === '--default-value' && $default === false) {
  379. return true;
  380. }
  381. return false;
  382. });
  383. $this->consoleInput->expects($this->once())
  384. ->method('getOption')
  385. ->with('default-value')
  386. ->willReturn($defaultValue);
  387. }
  388. }
  389. $this->consoleOutput->expects($this->once())
  390. ->method('writeln')
  391. ->with($expectedLine);
  392. $this->assertEquals($expectedReturn, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
  393. }
  394. public function testExecuteList(): void {
  395. $command = $this->getCommand([
  396. 'writeArrayInOutputFormat',
  397. 'checkInput',
  398. 'getUserSettings',
  399. ]);
  400. $this->consoleInput->expects($this->any())
  401. ->method('getArgument')
  402. ->willReturnMap([
  403. ['uid', 'username'],
  404. ['app', 'appname'],
  405. ['key', ''],
  406. ]);
  407. $command->expects($this->once())
  408. ->method('checkInput');
  409. $command->expects($this->once())
  410. ->method('getUserSettings')
  411. ->willReturn(['settings']);
  412. $command->expects($this->once())
  413. ->method('writeArrayInOutputFormat')
  414. ->with($this->consoleInput, $this->consoleOutput, ['settings']);
  415. $this->assertEquals(0, $this->invokePrivate($command, 'execute', [$this->consoleInput, $this->consoleOutput]));
  416. }
  417. }