UserConfigTest.php 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace Test\lib\Config;
  8. use NCU\Config\Exceptions\TypeConflictException;
  9. use NCU\Config\Exceptions\UnknownKeyException;
  10. use NCU\Config\IUserConfig;
  11. use NCU\Config\ValueType;
  12. use OC\Config\UserConfig;
  13. use OCP\IDBConnection;
  14. use OCP\Security\ICrypto;
  15. use Psr\Log\LoggerInterface;
  16. use Test\TestCase;
  17. /**
  18. * Class UserPreferencesTest
  19. *
  20. * @group DB
  21. *
  22. * @package Test
  23. */
  24. class UserConfigTest extends TestCase {
  25. protected IDBConnection $connection;
  26. private LoggerInterface $logger;
  27. private ICrypto $crypto;
  28. private array $originalPreferences;
  29. /**
  30. * @var array<string, array<string, array<array<string, string, int, bool, bool>>> [userId => [appId => prefKey, prefValue, valueType, lazy, sensitive]]]
  31. */
  32. private array $basePreferences =
  33. [
  34. 'user1' =>
  35. [
  36. 'app1' => [
  37. 'key1' => ['key1', 'value1'],
  38. 'key22' => ['key22', '31'],
  39. 'fast_string' => ['fast_string', 'f_value', ValueType::STRING],
  40. 'lazy_string' => ['lazy_string', 'l_value', ValueType::STRING, true],
  41. 'fast_string_sensitive' => [
  42. 'fast_string_sensitive', 'fs_value', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE
  43. ],
  44. 'lazy_string_sensitive' => [
  45. 'lazy_string_sensitive', 'ls_value', ValueType::STRING, true, UserConfig::FLAG_SENSITIVE
  46. ],
  47. 'fast_int' => ['fast_int', 11, ValueType::INT],
  48. 'lazy_int' => ['lazy_int', 12, ValueType::INT, true],
  49. 'fast_int_sensitive' => ['fast_int_sensitive', 2024, ValueType::INT, false, UserConfig::FLAG_SENSITIVE],
  50. 'lazy_int_sensitive' => ['lazy_int_sensitive', 2048, ValueType::INT, true, UserConfig::FLAG_SENSITIVE],
  51. 'fast_float' => ['fast_float', 3.14, ValueType::FLOAT],
  52. 'lazy_float' => ['lazy_float', 3.14159, ValueType::FLOAT, true],
  53. 'fast_float_sensitive' => [
  54. 'fast_float_sensitive', 1.41, ValueType::FLOAT, false, UserConfig::FLAG_SENSITIVE
  55. ],
  56. 'lazy_float_sensitive' => [
  57. 'lazy_float_sensitive', 1.4142, ValueType::FLOAT, true, UserConfig::FLAG_SENSITIVE
  58. ],
  59. 'fast_array' => ['fast_array', ['year' => 2024], ValueType::ARRAY],
  60. 'lazy_array' => ['lazy_array', ['month' => 'October'], ValueType::ARRAY, true],
  61. 'fast_array_sensitive' => [
  62. 'fast_array_sensitive', ['password' => 'pwd'], ValueType::ARRAY, false, UserConfig::FLAG_SENSITIVE
  63. ],
  64. 'lazy_array_sensitive' => [
  65. 'lazy_array_sensitive', ['password' => 'qwerty'], ValueType::ARRAY, true, UserConfig::FLAG_SENSITIVE
  66. ],
  67. 'fast_boolean' => ['fast_boolean', true, ValueType::BOOL],
  68. 'fast_boolean_0' => ['fast_boolean_0', false, ValueType::BOOL],
  69. 'lazy_boolean' => ['lazy_boolean', true, ValueType::BOOL, true],
  70. 'lazy_boolean_0' => ['lazy_boolean_0', false, ValueType::BOOL, true],
  71. ],
  72. 'app2' => [
  73. 'key2' => ['key2', 'value2a', ValueType::STRING, false, 0, true],
  74. 'key3' => ['key3', 'value3', ValueType::STRING, true],
  75. 'key4' => ['key4', 'value4', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE],
  76. 'key8' => ['key8', 11, ValueType::INT, false, 0, true],
  77. 'key9' => ['key9', 'value9a', ValueType::STRING],
  78. ],
  79. 'app3' => [
  80. 'key1' => ['key1', 'value123'],
  81. 'key3' => ['key3', 'value3'],
  82. 'key8' => ['key8', 12, ValueType::INT, false, UserConfig::FLAG_SENSITIVE, true],
  83. 'key9' => ['key9', 'value9b', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE],
  84. 'key10' => ['key10', true, ValueType::BOOL, false, 0, true],
  85. ],
  86. 'only-lazy' => [
  87. 'key1' => ['key1', 'value456', ValueType::STRING, true, 0, true],
  88. 'key2' => ['key2', 'value2c', ValueType::STRING, true, UserConfig::FLAG_SENSITIVE],
  89. 'key3' => ['key3', 42, ValueType::INT, true],
  90. 'key4' => ['key4', 17.42, ValueType::FLOAT, true],
  91. 'key5' => ['key5', true, ValueType::BOOL, true],
  92. ]
  93. ],
  94. 'user2' =>
  95. [
  96. 'app1' => [
  97. '1' => ['1', 'value1'],
  98. '2' => ['2', 'value2', ValueType::STRING, true, UserConfig::FLAG_SENSITIVE],
  99. '3' => ['3', 17, ValueType::INT, true],
  100. '4' => ['4', 42, ValueType::INT, false, UserConfig::FLAG_SENSITIVE],
  101. '5' => ['5', 17.42, ValueType::FLOAT, false],
  102. '6' => ['6', true, ValueType::BOOL, false],
  103. ],
  104. 'app2' => [
  105. 'key2' => ['key2', 'value2b', ValueType::STRING, false, 0, true],
  106. 'key3' => ['key3', 'value3', ValueType::STRING, true],
  107. 'key4' => ['key4', 'value4', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE],
  108. 'key8' => ['key8', 12, ValueType::INT, false, 0, true],
  109. ],
  110. 'app3' => [
  111. 'key10' => ['key10', false, ValueType::BOOL, false, 0, true],
  112. ],
  113. 'only-lazy' => [
  114. 'key1' => ['key1', 'value1', ValueType::STRING, true, 0, true]
  115. ]
  116. ],
  117. 'user3' =>
  118. [
  119. 'app2' => [
  120. 'key2' => ['key2', 'value2c', ValueType::MIXED, false, 0, true],
  121. 'key3' => ['key3', 'value3', ValueType::STRING, true, ],
  122. 'key4' => ['key4', 'value4', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE],
  123. 'fast_string_sensitive' => [
  124. 'fast_string_sensitive', 'fs_value', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE
  125. ],
  126. 'lazy_string_sensitive' => [
  127. 'lazy_string_sensitive', 'ls_value', ValueType::STRING, true, UserConfig::FLAG_SENSITIVE
  128. ],
  129. ],
  130. 'only-lazy' => [
  131. 'key3' => ['key3', 'value3', ValueType::STRING, true]
  132. ]
  133. ],
  134. 'user4' =>
  135. [
  136. 'app2' => [
  137. 'key1' => ['key1', 'value1'],
  138. 'key2' => ['key2', 'value2A', ValueType::MIXED, false, 0, true],
  139. 'key3' => ['key3', 'value3', ValueType::STRING, true,],
  140. 'key4' => ['key4', 'value4', ValueType::STRING, false, UserConfig::FLAG_SENSITIVE],
  141. ],
  142. 'app3' => [
  143. 'key10' => ['key10', true, ValueType::BOOL, false, 0, true],
  144. ],
  145. 'only-lazy' => [
  146. 'key1' => ['key1', 123, ValueType::INT, true, 0, true]
  147. ]
  148. ],
  149. 'user5' =>
  150. [
  151. 'app1' => [
  152. 'key1' => ['key1', 'value1']
  153. ],
  154. 'app2' => [
  155. 'key8' => ['key8', 12, ValueType::INT, false, 0, true]
  156. ],
  157. 'only-lazy' => [
  158. 'key1' => ['key1', 'value1', ValueType::STRING, true, 0, true]
  159. ]
  160. ],
  161. ];
  162. protected function setUp(): void {
  163. parent::setUp();
  164. $this->connection = \OCP\Server::get(IDBConnection::class);
  165. $this->logger = \OCP\Server::get(LoggerInterface::class);
  166. $this->crypto = \OCP\Server::get(ICrypto::class);
  167. // storing current preferences and emptying the data table
  168. $sql = $this->connection->getQueryBuilder();
  169. $sql->select('*')
  170. ->from('preferences');
  171. $result = $sql->executeQuery();
  172. $this->originalPreferences = $result->fetchAll();
  173. $result->closeCursor();
  174. $sql = $this->connection->getQueryBuilder();
  175. $sql->delete('preferences');
  176. $sql->executeStatement();
  177. $sql = $this->connection->getQueryBuilder();
  178. $sql->insert('preferences')
  179. ->values(
  180. [
  181. 'userid' => $sql->createParameter('userid'),
  182. 'appid' => $sql->createParameter('appid'),
  183. 'configkey' => $sql->createParameter('configkey'),
  184. 'configvalue' => $sql->createParameter('configvalue'),
  185. 'type' => $sql->createParameter('type'),
  186. 'lazy' => $sql->createParameter('lazy'),
  187. 'flags' => $sql->createParameter('flags'),
  188. 'indexed' => $sql->createParameter('indexed')
  189. ]
  190. );
  191. foreach ($this->basePreferences as $userId => $userData) {
  192. foreach ($userData as $appId => $appData) {
  193. foreach ($appData as $key => $row) {
  194. $value = $row[1];
  195. $type = ($row[2] ?? ValueType::MIXED)->value;
  196. if ($type === ValueType::ARRAY->value) {
  197. $value = json_encode($value);
  198. }
  199. if ($type === ValueType::BOOL->value && $value === false) {
  200. $value = '0';
  201. }
  202. $flags = $row[4] ?? 0;
  203. if ((UserConfig::FLAG_SENSITIVE & $flags) !== 0) {
  204. $value = self::invokePrivate(UserConfig::class, 'ENCRYPTION_PREFIX')
  205. . $this->crypto->encrypt((string)$value);
  206. } else {
  207. $indexed = (($row[5] ?? false) === true) ? $value : '';
  208. }
  209. $sql->setParameters(
  210. [
  211. 'userid' => $userId,
  212. 'appid' => $appId,
  213. 'configkey' => $row[0],
  214. 'configvalue' => $value,
  215. 'type' => $type,
  216. 'lazy' => (($row[3] ?? false) === true) ? 1 : 0,
  217. 'flags' => $flags,
  218. 'indexed' => $indexed ?? ''
  219. ]
  220. )->executeStatement();
  221. }
  222. }
  223. }
  224. }
  225. protected function tearDown(): void {
  226. $sql = $this->connection->getQueryBuilder();
  227. $sql->delete('preferences');
  228. $sql->executeStatement();
  229. $sql = $this->connection->getQueryBuilder();
  230. $sql->insert('preferences')
  231. ->values(
  232. [
  233. 'userid' => $sql->createParameter('userid'),
  234. 'appid' => $sql->createParameter('appid'),
  235. 'configkey' => $sql->createParameter('configkey'),
  236. 'configvalue' => $sql->createParameter('configvalue'),
  237. 'lazy' => $sql->createParameter('lazy'),
  238. 'type' => $sql->createParameter('type'),
  239. ]
  240. );
  241. foreach ($this->originalPreferences as $key => $configs) {
  242. $sql->setParameter('userid', $configs['userid'])
  243. ->setParameter('appid', $configs['appid'])
  244. ->setParameter('configkey', $configs['configkey'])
  245. ->setParameter('configvalue', $configs['configvalue'])
  246. ->setParameter('lazy', ($configs['lazy'] === '1') ? '1' : '0')
  247. ->setParameter('type', $configs['type']);
  248. $sql->executeStatement();
  249. }
  250. parent::tearDown();
  251. }
  252. /**
  253. * @param array $preLoading preload the 'fast' cache for a list of users)
  254. *
  255. * @return IUserConfig
  256. */
  257. private function generateUserConfig(array $preLoading = []): IUserConfig {
  258. $userConfig = new \OC\Config\UserConfig(
  259. $this->connection,
  260. $this->logger,
  261. $this->crypto,
  262. );
  263. $msg = ' generateUserConfig() failed to confirm cache status';
  264. // confirm cache status
  265. $status = $userConfig->statusCache();
  266. $this->assertSame([], $status['fastLoaded'], $msg);
  267. $this->assertSame([], $status['lazyLoaded'], $msg);
  268. $this->assertSame([], $status['fastCache'], $msg);
  269. $this->assertSame([], $status['lazyCache'], $msg);
  270. foreach ($preLoading as $preLoadUser) {
  271. // simple way to initiate the load of non-lazy preferences values in cache
  272. $userConfig->getValueString($preLoadUser, 'core', 'preload');
  273. // confirm cache status
  274. $status = $userConfig->statusCache();
  275. $this->assertSame(true, $status['fastLoaded'][$preLoadUser], $msg);
  276. $this->assertSame(false, $status['lazyLoaded'][$preLoadUser], $msg);
  277. $apps = array_values(array_diff(array_keys($this->basePreferences[$preLoadUser]), ['only-lazy']));
  278. $this->assertEqualsCanonicalizing($apps, array_keys($status['fastCache'][$preLoadUser]), $msg);
  279. $this->assertSame([], array_keys($status['lazyCache'][$preLoadUser]), $msg);
  280. }
  281. return $userConfig;
  282. }
  283. public function testGetUserIdsEmpty(): void {
  284. $userConfig = $this->generateUserConfig();
  285. $this->assertEqualsCanonicalizing(array_keys($this->basePreferences), $userConfig->getUserIds());
  286. }
  287. public function testGetUserIds(): void {
  288. $userConfig = $this->generateUserConfig();
  289. $this->assertEqualsCanonicalizing(['user1', 'user2', 'user5'], $userConfig->getUserIds('app1'));
  290. }
  291. public function testGetApps(): void {
  292. $userConfig = $this->generateUserConfig();
  293. $this->assertEqualsCanonicalizing(
  294. array_keys($this->basePreferences['user1']), $userConfig->getApps('user1')
  295. );
  296. }
  297. public function testGetKeys(): void {
  298. $userConfig = $this->generateUserConfig(['user1']);
  299. $this->assertEqualsCanonicalizing(
  300. array_keys($this->basePreferences['user1']['app1']), $userConfig->getKeys('user1', 'app1')
  301. );
  302. }
  303. /**
  304. * @return array[]
  305. */
  306. public function providerHasKey(): array {
  307. return [
  308. ['user1', 'app1', 'key1', false, true],
  309. ['user0', 'app1', 'key1', false, false],
  310. ['user1', 'app1', 'key1', true, false],
  311. ['user1', 'app1', 'key0', false, false],
  312. ['user1', 'app1', 'key0', true, false],
  313. ['user1', 'app1', 'fast_string_sensitive', false, true],
  314. ['user1', 'app1', 'lazy_string_sensitive', true, true],
  315. ['user2', 'only-lazy', 'key1', false, false],
  316. ['user2', 'only-lazy', 'key1', true, true],
  317. ];
  318. }
  319. /**
  320. * @dataProvider providerHasKey
  321. */
  322. public function testHasKey(string $userId, string $appId, string $key, ?bool $lazy, bool $result): void {
  323. $userConfig = $this->generateUserConfig();
  324. $this->assertEquals($result, $userConfig->hasKey($userId, $appId, $key, $lazy));
  325. }
  326. /**
  327. * @return array[]
  328. */
  329. public function providerIsSensitive(): array {
  330. return [
  331. ['user1', 'app1', 'key1', false, false, false],
  332. ['user0', 'app1', 'key1', false, false, true],
  333. ['user1', 'app1', 'key1', true, false, true],
  334. ['user1', 'app1', 'key1', null, false, false],
  335. ['user1', 'app1', 'key0', false, false, true],
  336. ['user1', 'app1', 'key0', true, false, true],
  337. ['user1', 'app1', 'fast_string_sensitive', false, true, false],
  338. ['user1', 'app1', 'lazy_string_sensitive', true, true, false],
  339. ['user1', 'app1', 'fast_string_sensitive', true, true, true],
  340. ['user1', 'app1', 'lazy_string_sensitive', false, true, true],
  341. ['user1', 'app1', 'lazy_string_sensitive', null, true, false],
  342. ['user2', 'only-lazy', 'key1', false, false, true],
  343. ['user2', 'only-lazy', 'key1', true, false, false],
  344. ['user2', 'only-lazy', 'key1', null, false, false],
  345. ];
  346. }
  347. /**
  348. * @dataProvider providerIsSensitive
  349. */
  350. public function testIsSensitive(
  351. string $userId,
  352. string $appId,
  353. string $key,
  354. ?bool $lazy,
  355. bool $result,
  356. bool $exception,
  357. ): void {
  358. $userConfig = $this->generateUserConfig();
  359. if ($exception) {
  360. $this->expectException(UnknownKeyException::class);
  361. }
  362. $this->assertEquals($result, $userConfig->isSensitive($userId, $appId, $key, $lazy));
  363. }
  364. /**
  365. * @return array[]
  366. */
  367. public function providerIsLazy(): array {
  368. return [
  369. ['user1', 'app1', 'key1', false, false],
  370. ['user0', 'app1', 'key1', false, true],
  371. ['user1', 'app1', 'key0', false, true],
  372. ['user1', 'app1', 'key0', false, true],
  373. ['user1', 'app1', 'fast_string_sensitive', false, false],
  374. ['user1', 'app1', 'lazy_string_sensitive', true, false],
  375. ['user2', 'only-lazy', 'key1', true, false],
  376. ];
  377. }
  378. /**
  379. * @dataProvider providerIsLazy
  380. */
  381. public function testIsLazy(
  382. string $userId,
  383. string $appId,
  384. string $key,
  385. bool $result,
  386. bool $exception,
  387. ): void {
  388. $userConfig = $this->generateUserConfig();
  389. if ($exception) {
  390. $this->expectException(UnknownKeyException::class);
  391. }
  392. $this->assertEquals($result, $userConfig->isLazy($userId, $appId, $key));
  393. }
  394. public function providerGetValues(): array {
  395. return [
  396. [
  397. 'user1', 'app1', '', true,
  398. [
  399. 'fast_array' => ['year' => 2024],
  400. 'fast_array_sensitive' => '***REMOVED SENSITIVE VALUE***',
  401. 'fast_boolean' => true,
  402. 'fast_boolean_0' => false,
  403. 'fast_float' => 3.14,
  404. 'fast_float_sensitive' => '***REMOVED SENSITIVE VALUE***',
  405. 'fast_int' => 11,
  406. 'fast_int_sensitive' => '***REMOVED SENSITIVE VALUE***',
  407. 'fast_string' => 'f_value',
  408. 'fast_string_sensitive' => '***REMOVED SENSITIVE VALUE***',
  409. 'key1' => 'value1',
  410. 'key22' => '31',
  411. 'lazy_array' => ['month' => 'October'],
  412. 'lazy_array_sensitive' => '***REMOVED SENSITIVE VALUE***',
  413. 'lazy_boolean' => true,
  414. 'lazy_boolean_0' => false,
  415. 'lazy_float' => 3.14159,
  416. 'lazy_float_sensitive' => '***REMOVED SENSITIVE VALUE***',
  417. 'lazy_int' => 12,
  418. 'lazy_int_sensitive' => '***REMOVED SENSITIVE VALUE***',
  419. 'lazy_string' => 'l_value',
  420. 'lazy_string_sensitive' => '***REMOVED SENSITIVE VALUE***',
  421. ]
  422. ],
  423. [
  424. 'user1', 'app1', '', false,
  425. [
  426. 'fast_array' => ['year' => 2024],
  427. 'fast_array_sensitive' => ['password' => 'pwd'],
  428. 'fast_boolean' => true,
  429. 'fast_boolean_0' => false,
  430. 'fast_float' => 3.14,
  431. 'fast_float_sensitive' => 1.41,
  432. 'fast_int' => 11,
  433. 'fast_int_sensitive' => 2024,
  434. 'fast_string' => 'f_value',
  435. 'fast_string_sensitive' => 'fs_value',
  436. 'key1' => 'value1',
  437. 'key22' => '31',
  438. 'lazy_array' => ['month' => 'October'],
  439. 'lazy_array_sensitive' => ['password' => 'qwerty'],
  440. 'lazy_boolean' => true,
  441. 'lazy_boolean_0' => false,
  442. 'lazy_float' => 3.14159,
  443. 'lazy_float_sensitive' => 1.4142,
  444. 'lazy_int' => 12,
  445. 'lazy_int_sensitive' => 2048,
  446. 'lazy_string' => 'l_value',
  447. 'lazy_string_sensitive' => 'ls_value'
  448. ]
  449. ],
  450. [
  451. 'user1', 'app1', 'fast_', true,
  452. [
  453. 'fast_array' => ['year' => 2024],
  454. 'fast_array_sensitive' => '***REMOVED SENSITIVE VALUE***',
  455. 'fast_boolean' => true,
  456. 'fast_boolean_0' => false,
  457. 'fast_float' => 3.14,
  458. 'fast_float_sensitive' => '***REMOVED SENSITIVE VALUE***',
  459. 'fast_int' => 11,
  460. 'fast_int_sensitive' => '***REMOVED SENSITIVE VALUE***',
  461. 'fast_string' => 'f_value',
  462. 'fast_string_sensitive' => '***REMOVED SENSITIVE VALUE***',
  463. ]
  464. ],
  465. [
  466. 'user1', 'app1', 'fast_', false,
  467. [
  468. 'fast_array' => ['year' => 2024],
  469. 'fast_array_sensitive' => ['password' => 'pwd'],
  470. 'fast_boolean' => true,
  471. 'fast_boolean_0' => false,
  472. 'fast_float' => 3.14,
  473. 'fast_float_sensitive' => 1.41,
  474. 'fast_int' => 11,
  475. 'fast_int_sensitive' => 2024,
  476. 'fast_string' => 'f_value',
  477. 'fast_string_sensitive' => 'fs_value',
  478. ]
  479. ],
  480. [
  481. 'user1', 'app1', 'key1', true,
  482. [
  483. 'key1' => 'value1',
  484. ]
  485. ],
  486. [
  487. 'user2', 'app1', '', false,
  488. [
  489. '1' => 'value1',
  490. '4' => 42,
  491. '5' => 17.42,
  492. '6' => true,
  493. '2' => 'value2',
  494. '3' => 17,
  495. ]
  496. ],
  497. [
  498. 'user2', 'app1', '', true,
  499. [
  500. '1' => 'value1',
  501. '4' => '***REMOVED SENSITIVE VALUE***',
  502. '5' => 17.42,
  503. '6' => true,
  504. '2' => '***REMOVED SENSITIVE VALUE***',
  505. '3' => 17,
  506. ]
  507. ],
  508. ];
  509. }
  510. /**
  511. * @dataProvider providerGetValues
  512. */
  513. public function testGetValues(
  514. string $userId,
  515. string $appId,
  516. string $prefix,
  517. bool $filtered,
  518. array $result,
  519. ): void {
  520. $userConfig = $this->generateUserConfig();
  521. $this->assertJsonStringEqualsJsonString(
  522. json_encode($result), json_encode($userConfig->getValues($userId, $appId, $prefix, $filtered))
  523. );
  524. }
  525. public function providerGetAllValues(): array {
  526. return [
  527. [
  528. 'user2', false,
  529. [
  530. 'app1' => [
  531. '1' => 'value1',
  532. '4' => 42,
  533. '5' => 17.42,
  534. '6' => true,
  535. '2' => 'value2',
  536. '3' => 17,
  537. ],
  538. 'app2' => [
  539. 'key2' => 'value2b',
  540. 'key3' => 'value3',
  541. 'key4' => 'value4',
  542. 'key8' => 12,
  543. ],
  544. 'app3' => [
  545. 'key10' => false,
  546. ],
  547. 'only-lazy' => [
  548. 'key1' => 'value1',
  549. ]
  550. ],
  551. ],
  552. [
  553. 'user2', true,
  554. [
  555. 'app1' => [
  556. '1' => 'value1',
  557. '4' => '***REMOVED SENSITIVE VALUE***',
  558. '5' => 17.42,
  559. '6' => true,
  560. '2' => '***REMOVED SENSITIVE VALUE***',
  561. '3' => 17,
  562. ],
  563. 'app2' => [
  564. 'key2' => 'value2b',
  565. 'key3' => 'value3',
  566. 'key4' => '***REMOVED SENSITIVE VALUE***',
  567. 'key8' => 12,
  568. ],
  569. 'app3' => [
  570. 'key10' => false,
  571. ],
  572. 'only-lazy' => [
  573. 'key1' => 'value1',
  574. ]
  575. ],
  576. ],
  577. [
  578. 'user3', true,
  579. [
  580. 'app2' => [
  581. 'key2' => 'value2c',
  582. 'key3' => 'value3',
  583. 'key4' => '***REMOVED SENSITIVE VALUE***',
  584. 'fast_string_sensitive' => '***REMOVED SENSITIVE VALUE***',
  585. 'lazy_string_sensitive' => '***REMOVED SENSITIVE VALUE***',
  586. ],
  587. 'only-lazy' => [
  588. 'key3' => 'value3',
  589. ]
  590. ],
  591. ],
  592. [
  593. 'user3', false,
  594. [
  595. 'app2' => [
  596. 'key2' => 'value2c',
  597. 'key3' => 'value3',
  598. 'key4' => 'value4',
  599. 'fast_string_sensitive' => 'fs_value',
  600. 'lazy_string_sensitive' => 'ls_value',
  601. ],
  602. 'only-lazy' => [
  603. 'key3' => 'value3',
  604. ]
  605. ],
  606. ],
  607. ];
  608. }
  609. /**
  610. * @dataProvider providerGetAllValues
  611. */
  612. public function testGetAllValues(
  613. string $userId,
  614. bool $filtered,
  615. array $result,
  616. ): void {
  617. $userConfig = $this->generateUserConfig();
  618. $this->assertEqualsCanonicalizing($result, $userConfig->getAllValues($userId, $filtered));
  619. }
  620. public function providerSearchValuesByApps(): array {
  621. return [
  622. [
  623. 'user1', 'key1', false, null,
  624. [
  625. 'app1' => 'value1',
  626. 'app3' => 'value123'
  627. ]
  628. ],
  629. [
  630. 'user1', 'key1', true, null,
  631. [
  632. 'only-lazy' => 'value456'
  633. ]
  634. ],
  635. [
  636. 'user1', 'key8', false, null,
  637. [
  638. 'app2' => 11,
  639. 'app3' => 12,
  640. ]
  641. ],
  642. [
  643. 'user1', 'key9', false, ValueType::INT,
  644. [
  645. 'app2' => 0,
  646. 'app3' => 0,
  647. ]
  648. ]
  649. ];
  650. }
  651. /**
  652. * @dataProvider providerSearchValuesByApps
  653. */
  654. public function testSearchValuesByApps(
  655. string $userId,
  656. string $key,
  657. bool $lazy,
  658. ?ValueType $typedAs,
  659. array $result,
  660. ): void {
  661. $userConfig = $this->generateUserConfig();
  662. $this->assertEquals($result, $userConfig->getValuesByApps($userId, $key, $lazy, $typedAs));
  663. }
  664. public function providerSearchValuesByUsers(): array {
  665. return [
  666. [
  667. 'app2', 'key2', null, null,
  668. [
  669. 'user1' => 'value2a',
  670. 'user2' => 'value2b',
  671. 'user3' => 'value2c',
  672. 'user4' => 'value2A'
  673. ]
  674. ],
  675. [
  676. 'app2', 'key2', null, ['user1', 'user3'],
  677. [
  678. 'user1' => 'value2a',
  679. 'user3' => 'value2c',
  680. ]
  681. ],
  682. [
  683. 'app2', 'key2', ValueType::INT, ['user1', 'user3'],
  684. [
  685. 'user1' => 0,
  686. 'user3' => 0,
  687. ]
  688. ],
  689. [
  690. 'app2', 'key8', ValueType::INT, null,
  691. [
  692. 'user1' => 11,
  693. 'user2' => 12,
  694. 'user5' => 12,
  695. ]
  696. ],
  697. ];
  698. }
  699. /**
  700. * @dataProvider providerSearchValuesByUsers
  701. */
  702. public function testSearchValuesByUsers(
  703. string $app,
  704. string $key,
  705. ?ValueType $typedAs = null,
  706. ?array $userIds = null,
  707. array $result = [],
  708. ): void {
  709. $userConfig = $this->generateUserConfig();
  710. $this->assertEqualsCanonicalizing(
  711. $result, $userConfig->getValuesByUsers($app, $key, $typedAs, $userIds)
  712. );
  713. }
  714. public function providerSearchValuesByValueString(): array {
  715. return [
  716. ['app2', 'key2', 'value2a', false, ['user1']],
  717. ['app2', 'key2', 'value2A', false, ['user4']],
  718. ['app2', 'key2', 'value2A', true, ['user1', 'user4']]
  719. ];
  720. }
  721. /**
  722. * @dataProvider providerSearchValuesByValueString
  723. */
  724. public function testSearchUsersByValueString(
  725. string $app,
  726. string $key,
  727. string|array $value,
  728. bool $ci,
  729. array $result,
  730. ): void {
  731. $userConfig = $this->generateUserConfig();
  732. $this->assertEqualsCanonicalizing($result, iterator_to_array($userConfig->searchUsersByValueString($app, $key, $value, $ci)));
  733. }
  734. public function providerSearchValuesByValueInt(): array {
  735. return [
  736. ['app3', 'key8', 12, []], // sensitive value, cannot search
  737. ['app2', 'key8', 12, ['user2', 'user5']], // sensitive value, cannot search
  738. ['only-lazy', 'key1', 123, ['user4']],
  739. ];
  740. }
  741. /**
  742. * @dataProvider providerSearchValuesByValueInt
  743. */
  744. public function testSearchUsersByValueInt(
  745. string $app,
  746. string $key,
  747. int $value,
  748. array $result,
  749. ): void {
  750. $userConfig = $this->generateUserConfig();
  751. $this->assertEqualsCanonicalizing($result, iterator_to_array($userConfig->searchUsersByValueInt($app, $key, $value)));
  752. }
  753. public function providerSearchValuesByValues(): array {
  754. return [
  755. ['app2', 'key2', ['value2a', 'value2b'], ['user1', 'user2']],
  756. ['app2', 'key2', ['value2a', 'value2c'], ['user1', 'user3']],
  757. ];
  758. }
  759. /**
  760. * @dataProvider providerSearchValuesByValues
  761. */
  762. public function testSearchUsersByValues(
  763. string $app,
  764. string $key,
  765. array $values,
  766. array $result,
  767. ): void {
  768. $userConfig = $this->generateUserConfig();
  769. $this->assertEqualsCanonicalizing($result, iterator_to_array($userConfig->searchUsersByValues($app, $key, $values)));
  770. }
  771. public function providerSearchValuesByValueBool(): array {
  772. return [
  773. ['app3', 'key10', true, ['user1', 'user4']],
  774. ['app3', 'key10', false, ['user2']],
  775. ];
  776. }
  777. /**
  778. * @dataProvider providerSearchValuesByValueBool
  779. */
  780. public function testSearchUsersByValueBool(
  781. string $app,
  782. string $key,
  783. bool $value,
  784. array $result,
  785. ): void {
  786. $userConfig = $this->generateUserConfig();
  787. $this->assertEqualsCanonicalizing($result, iterator_to_array($userConfig->searchUsersByValueBool($app, $key, $value)));
  788. }
  789. public function providerGetValueMixed(): array {
  790. return [
  791. [
  792. ['user1'], 'user1', 'app1', 'key0', 'default_because_unknown_key', true,
  793. 'default_because_unknown_key'
  794. ],
  795. [
  796. null, 'user1', 'app1', 'key0', 'default_because_unknown_key', true,
  797. 'default_because_unknown_key'
  798. ],
  799. [
  800. ['user1'], 'user1', 'app1', 'key0', 'default_because_unknown_key', false,
  801. 'default_because_unknown_key'
  802. ],
  803. [
  804. null, 'user1', 'app1', 'key0', 'default_because_unknown_key', false,
  805. 'default_because_unknown_key'
  806. ],
  807. [['user1'], 'user1', 'app1', 'fast_string', 'default_because_unknown_key', false, 'f_value'],
  808. [null, 'user1', 'app1', 'fast_string', 'default_because_unknown_key', false, 'f_value'],
  809. [['user1'], 'user1', 'app1', 'fast_string', 'default_because_unknown_key', true, 'f_value'],
  810. // because non-lazy are already loaded
  811. [
  812. null, 'user1', 'app1', 'fast_string', 'default_because_unknown_key', true,
  813. 'default_because_unknown_key'
  814. ],
  815. [
  816. ['user1'], 'user1', 'app1', 'lazy_string', 'default_because_unknown_key', false,
  817. 'default_because_unknown_key'
  818. ],
  819. [
  820. null, 'user1', 'app1', 'lazy_string', 'default_because_unknown_key', false,
  821. 'default_because_unknown_key'
  822. ],
  823. [['user1'], 'user1', 'app1', 'lazy_string', 'default_because_unknown_key', true, 'l_value'],
  824. [null, 'user1', 'app1', 'lazy_string', 'default_because_unknown_key', true, 'l_value'],
  825. [
  826. ['user1'], 'user1', 'app1', 'fast_string_sensitive', 'default_because_unknown_key', false,
  827. 'fs_value'
  828. ],
  829. [
  830. null, 'user1', 'app1', 'fast_string_sensitive', 'default_because_unknown_key', false,
  831. 'fs_value'
  832. ],
  833. [
  834. ['user1'], 'user1', 'app1', 'fast_string_sensitive', 'default_because_unknown_key', true,
  835. 'fs_value'
  836. ],
  837. [
  838. null, 'user1', 'app1', 'fast_string_sensitive', 'default_because_unknown_key', true,
  839. 'default_because_unknown_key'
  840. ],
  841. [
  842. ['user1'], 'user1', 'app1', 'lazy_string_sensitive', 'default_because_unknown_key', false,
  843. 'default_because_unknown_key'
  844. ],
  845. [
  846. null, 'user1', 'app1', 'lazy_string_sensitive', 'default_because_unknown_key', false,
  847. 'default_because_unknown_key'
  848. ],
  849. [
  850. ['user1'], 'user1', 'app1', 'lazy_string_sensitive', 'default_because_unknown_key', true,
  851. 'ls_value'
  852. ],
  853. [null, 'user1', 'app1', 'lazy_string_sensitive', 'default_because_unknown_key', true, 'ls_value'],
  854. ];
  855. }
  856. /**
  857. * @dataProvider providerGetValueMixed
  858. */
  859. public function testGetValueMixed(
  860. ?array $preload,
  861. string $userId,
  862. string $app,
  863. string $key,
  864. string $default,
  865. bool $lazy,
  866. string $result,
  867. ): void {
  868. $userConfig = $this->generateUserConfig($preload ?? []);
  869. $this->assertEquals($result, $userConfig->getValueMixed($userId, $app, $key, $default, $lazy));
  870. }
  871. /**
  872. * @dataProvider providerGetValueMixed
  873. */
  874. public function testGetValueString(
  875. ?array $preload,
  876. string $userId,
  877. string $app,
  878. string $key,
  879. string $default,
  880. bool $lazy,
  881. string $result,
  882. ): void {
  883. $userConfig = $this->generateUserConfig($preload ?? []);
  884. $this->assertEquals($result, $userConfig->getValueString($userId, $app, $key, $default, $lazy));
  885. }
  886. public function providerGetValueInt(): array {
  887. return [
  888. [['user1'], 'user1', 'app1', 'key0', 54321, true, 54321],
  889. [null, 'user1', 'app1', 'key0', 54321, true, 54321],
  890. [['user1'], 'user1', 'app1', 'key0', 54321, false, 54321],
  891. [null, 'user1', 'app1', 'key0', 54321, false, 54321],
  892. [null, 'user1', 'app1', 'key22', 54321, false, 31],
  893. [['user1'], 'user1', 'app1', 'fast_int', 54321, false, 11],
  894. [null, 'user1', 'app1', 'fast_int', 54321, false, 11],
  895. [['user1'], 'user1', 'app1', 'fast_int', 54321, true, 11],
  896. [null, 'user1', 'app1', 'fast_int', 54321, true, 54321],
  897. [['user1'], 'user1', 'app1', 'fast_int_sensitive', 54321, false, 2024],
  898. [null, 'user1', 'app1', 'fast_int_sensitive', 54321, false, 2024],
  899. [['user1'], 'user1', 'app1', 'fast_int_sensitive', 54321, true, 2024],
  900. [null, 'user1', 'app1', 'fast_int_sensitive', 54321, true, 54321],
  901. [['user1'], 'user1', 'app1', 'lazy_int', 54321, false, 54321],
  902. [null, 'user1', 'app1', 'lazy_int', 54321, false, 54321],
  903. [['user1'], 'user1', 'app1', 'lazy_int', 54321, true, 12],
  904. [null, 'user1', 'app1', 'lazy_int', 54321, true, 12],
  905. [['user1'], 'user1', 'app1', 'lazy_int_sensitive', 54321, false, 54321],
  906. [null, 'user1', 'app1', 'lazy_int_sensitive', 54321, false, 54321],
  907. [['user1'], 'user1', 'app1', 'lazy_int_sensitive', 54321, true, 2048],
  908. [null, 'user1', 'app1', 'lazy_int_sensitive', 54321, true, 2048],
  909. ];
  910. }
  911. /**
  912. * @dataProvider providerGetValueInt
  913. */
  914. public function testGetValueInt(
  915. ?array $preload,
  916. string $userId,
  917. string $app,
  918. string $key,
  919. int $default,
  920. bool $lazy,
  921. int $result,
  922. ): void {
  923. $userConfig = $this->generateUserConfig($preload ?? []);
  924. $this->assertEquals($result, $userConfig->getValueInt($userId, $app, $key, $default, $lazy));
  925. }
  926. public function providerGetValueFloat(): array {
  927. return [
  928. [['user1'], 'user1', 'app1', 'key0', 54.321, true, 54.321],
  929. [null, 'user1', 'app1', 'key0', 54.321, true, 54.321],
  930. [['user1'], 'user1', 'app1', 'key0', 54.321, false, 54.321],
  931. [null, 'user1', 'app1', 'key0', 54.321, false, 54.321],
  932. [['user1'], 'user1', 'app1', 'fast_float', 54.321, false, 3.14],
  933. [null, 'user1', 'app1', 'fast_float', 54.321, false, 3.14],
  934. [['user1'], 'user1', 'app1', 'fast_float', 54.321, true, 3.14],
  935. [null, 'user1', 'app1', 'fast_float', 54.321, true, 54.321],
  936. [['user1'], 'user1', 'app1', 'fast_float_sensitive', 54.321, false, 1.41],
  937. [null, 'user1', 'app1', 'fast_float_sensitive', 54.321, false, 1.41],
  938. [['user1'], 'user1', 'app1', 'fast_float_sensitive', 54.321, true, 1.41],
  939. [null, 'user1', 'app1', 'fast_float_sensitive', 54.321, true, 54.321],
  940. [['user1'], 'user1', 'app1', 'lazy_float', 54.321, false, 54.321],
  941. [null, 'user1', 'app1', 'lazy_float', 54.321, false, 54.321],
  942. [['user1'], 'user1', 'app1', 'lazy_float', 54.321, true, 3.14159],
  943. [null, 'user1', 'app1', 'lazy_float', 54.321, true, 3.14159],
  944. [['user1'], 'user1', 'app1', 'lazy_float_sensitive', 54.321, false, 54.321],
  945. [null, 'user1', 'app1', 'lazy_float_sensitive', 54.321, false, 54.321],
  946. [['user1'], 'user1', 'app1', 'lazy_float_sensitive', 54.321, true, 1.4142],
  947. [null, 'user1', 'app1', 'lazy_float_sensitive', 54.321, true, 1.4142],
  948. ];
  949. }
  950. /**
  951. * @dataProvider providerGetValueFloat
  952. */
  953. public function testGetValueFloat(
  954. ?array $preload,
  955. string $userId,
  956. string $app,
  957. string $key,
  958. float $default,
  959. bool $lazy,
  960. float $result,
  961. ): void {
  962. $userConfig = $this->generateUserConfig($preload ?? []);
  963. $this->assertEquals($result, $userConfig->getValueFloat($userId, $app, $key, $default, $lazy));
  964. }
  965. public function providerGetValueBool(): array {
  966. return [
  967. [['user1'], 'user1', 'app1', 'key0', false, true, false],
  968. [null, 'user1', 'app1', 'key0', false, true, false],
  969. [['user1'], 'user1', 'app1', 'key0', true, true, true],
  970. [null, 'user1', 'app1', 'key0', true, true, true],
  971. [['user1'], 'user1', 'app1', 'key0', false, false, false],
  972. [null, 'user1', 'app1', 'key0', false, false, false],
  973. [['user1'], 'user1', 'app1', 'key0', true, false, true],
  974. [null, 'user1', 'app1', 'key0', true, false, true],
  975. [['user1'], 'user1', 'app1', 'fast_boolean', false, false, true],
  976. [null, 'user1', 'app1', 'fast_boolean', false, false, true],
  977. [['user1'], 'user1', 'app1', 'fast_boolean_0', false, false, false],
  978. [null, 'user1', 'app1', 'fast_boolean_0', false, false, false],
  979. [['user1'], 'user1', 'app1', 'fast_boolean', true, false, true],
  980. [null, 'user1', 'app1', 'fast_boolean', true, false, true],
  981. [['user1'], 'user1', 'app1', 'fast_boolean_0', true, false, false],
  982. [null, 'user1', 'app1', 'fast_boolean_0', true, false, false],
  983. [['user1'], 'user1', 'app1', 'fast_boolean', false, true, true],
  984. [null, 'user1', 'app1', 'fast_boolean', false, true, false],
  985. [['user1'], 'user1', 'app1', 'fast_boolean_0', false, true, false],
  986. [null, 'user1', 'app1', 'fast_boolean_0', false, true, false],
  987. [['user1'], 'user1', 'app1', 'fast_boolean', true, true, true],
  988. [null, 'user1', 'app1', 'fast_boolean', true, true, true],
  989. [['user1'], 'user1', 'app1', 'fast_boolean_0', true, true, false],
  990. [null, 'user1', 'app1', 'fast_boolean_0', true, true, true],
  991. [['user1'], 'user1', 'app1', 'lazy_boolean', false, false, false],
  992. [null, 'user1', 'app1', 'lazy_boolean', false, false, false],
  993. [['user1'], 'user1', 'app1', 'lazy_boolean_0', false, false, false],
  994. [null, 'user1', 'app1', 'lazy_boolean_0', false, false, false],
  995. [['user1'], 'user1', 'app1', 'lazy_boolean', true, false, true],
  996. [null, 'user1', 'app1', 'lazy_boolean', true, false, true],
  997. [['user1'], 'user1', 'app1', 'lazy_boolean_0', true, false, true],
  998. [null, 'user1', 'app1', 'lazy_boolean_0', true, false, true],
  999. [['user1'], 'user1', 'app1', 'lazy_boolean', false, true, true],
  1000. [null, 'user1', 'app1', 'lazy_boolean', false, true, true],
  1001. [['user1'], 'user1', 'app1', 'lazy_boolean_0', false, true, false],
  1002. [null, 'user1', 'app1', 'lazy_boolean_0', false, true, false],
  1003. [['user1'], 'user1', 'app1', 'lazy_boolean', true, true, true],
  1004. [null, 'user1', 'app1', 'lazy_boolean', true, true, true],
  1005. [['user1'], 'user1', 'app1', 'lazy_boolean_0', true, true, false],
  1006. [null, 'user1', 'app1', 'lazy_boolean_0', true, true, false],
  1007. ];
  1008. }
  1009. /**
  1010. * @dataProvider providerGetValueBool
  1011. */
  1012. public function testGetValueBool(
  1013. ?array $preload,
  1014. string $userId,
  1015. string $app,
  1016. string $key,
  1017. bool $default,
  1018. bool $lazy,
  1019. bool $result,
  1020. ): void {
  1021. $userConfig = $this->generateUserConfig($preload ?? []);
  1022. $this->assertEquals($result, $userConfig->getValueBool($userId, $app, $key, $default, $lazy));
  1023. }
  1024. public function providerGetValueArray(): array {
  1025. return [
  1026. [
  1027. ['user1'], 'user1', 'app1', 'key0', ['default_because_unknown_key'], true,
  1028. ['default_because_unknown_key']
  1029. ],
  1030. [
  1031. null, 'user1', 'app1', 'key0', ['default_because_unknown_key'], true,
  1032. ['default_because_unknown_key']
  1033. ],
  1034. [
  1035. ['user1'], 'user1', 'app1', 'key0', ['default_because_unknown_key'], false,
  1036. ['default_because_unknown_key']
  1037. ],
  1038. [
  1039. null, 'user1', 'app1', 'key0', ['default_because_unknown_key'], false,
  1040. ['default_because_unknown_key']
  1041. ],
  1042. ];
  1043. }
  1044. /**
  1045. * @dataProvider providerGetValueArray
  1046. */
  1047. public function testGetValueArray(
  1048. ?array $preload,
  1049. string $userId,
  1050. string $app,
  1051. string $key,
  1052. array $default,
  1053. bool $lazy,
  1054. array $result,
  1055. ): void {
  1056. $userConfig = $this->generateUserConfig($preload ?? []);
  1057. $this->assertEqualsCanonicalizing(
  1058. $result, $userConfig->getValueArray($userId, $app, $key, $default, $lazy)
  1059. );
  1060. }
  1061. public function providerGetValueType(): array {
  1062. return [
  1063. [null, 'user1', 'app1', 'key1', false, ValueType::MIXED],
  1064. [null, 'user1', 'app1', 'key1', true, null, UnknownKeyException::class],
  1065. [null, 'user1', 'app1', 'fast_string', true, ValueType::STRING, UnknownKeyException::class],
  1066. [['user1'], 'user1', 'app1', 'fast_string', true, ValueType::STRING],
  1067. [null, 'user1', 'app1', 'fast_string', false, ValueType::STRING],
  1068. [null, 'user1', 'app1', 'lazy_string', true, ValueType::STRING],
  1069. [null, 'user1', 'app1', 'lazy_string', false, ValueType::STRING, UnknownKeyException::class],
  1070. [
  1071. null, 'user1', 'app1', 'fast_string_sensitive', true, ValueType::STRING,
  1072. UnknownKeyException::class
  1073. ],
  1074. [['user1'], 'user1', 'app1', 'fast_string_sensitive', true, ValueType::STRING],
  1075. [null, 'user1', 'app1', 'fast_string_sensitive', false, ValueType::STRING],
  1076. [null, 'user1', 'app1', 'lazy_string_sensitive', true, ValueType::STRING],
  1077. [
  1078. null, 'user1', 'app1', 'lazy_string_sensitive', false, ValueType::STRING,
  1079. UnknownKeyException::class
  1080. ],
  1081. [null, 'user1', 'app1', 'fast_int', true, ValueType::INT, UnknownKeyException::class],
  1082. [['user1'], 'user1', 'app1', 'fast_int', true, ValueType::INT],
  1083. [null, 'user1', 'app1', 'fast_int', false, ValueType::INT],
  1084. [null, 'user1', 'app1', 'lazy_int', true, ValueType::INT],
  1085. [null, 'user1', 'app1', 'lazy_int', false, ValueType::INT, UnknownKeyException::class],
  1086. [null, 'user1', 'app1', 'fast_float', true, ValueType::FLOAT, UnknownKeyException::class],
  1087. [['user1'], 'user1', 'app1', 'fast_float', true, ValueType::FLOAT],
  1088. [null, 'user1', 'app1', 'fast_float', false, ValueType::FLOAT],
  1089. [null, 'user1', 'app1', 'lazy_float', true, ValueType::FLOAT],
  1090. [null, 'user1', 'app1', 'lazy_float', false, ValueType::FLOAT, UnknownKeyException::class],
  1091. [null, 'user1', 'app1', 'fast_boolean', true, ValueType::BOOL, UnknownKeyException::class],
  1092. [['user1'], 'user1', 'app1', 'fast_boolean', true, ValueType::BOOL],
  1093. [null, 'user1', 'app1', 'fast_boolean', false, ValueType::BOOL],
  1094. [null, 'user1', 'app1', 'lazy_boolean', true, ValueType::BOOL],
  1095. [null, 'user1', 'app1', 'lazy_boolean', false, ValueType::BOOL, UnknownKeyException::class],
  1096. ];
  1097. }
  1098. /**
  1099. * @dataProvider providerGetValueType
  1100. */
  1101. public function testGetValueType(
  1102. ?array $preload,
  1103. string $userId,
  1104. string $app,
  1105. string $key,
  1106. ?bool $lazy,
  1107. ?ValueType $result,
  1108. ?string $exception = null,
  1109. ): void {
  1110. $userConfig = $this->generateUserConfig($preload ?? []);
  1111. if ($exception !== null) {
  1112. $this->expectException($exception);
  1113. }
  1114. $type = $userConfig->getValueType($userId, $app, $key, $lazy);
  1115. if ($exception === null) {
  1116. $this->assertEquals($result->value, $type->value);
  1117. }
  1118. }
  1119. public function providerSetValueMixed(): array {
  1120. return [
  1121. [null, 'user1', 'app1', 'key1', 'value', false, false, true],
  1122. [null, 'user1', 'app1', 'key1', '12345', true, false, true],
  1123. [null, 'user1', 'app1', 'key1', '12345', true, true, true],
  1124. [null, 'user1', 'app1', 'key1', 'value1', false, false, false],
  1125. [null, 'user1', 'app1', 'key1', 'value1', true, false, true],
  1126. [null, 'user1', 'app1', 'key1', 'value1', false, true, true],
  1127. [
  1128. null, 'user1', 'app1', 'fast_string', 'f_value_2', false, false, true,
  1129. TypeConflictException::class
  1130. ],
  1131. [
  1132. null, 'user1', 'app1', 'fast_string', 'f_value', true, false, true,
  1133. TypeConflictException::class
  1134. ],
  1135. [null, 'user1', 'app1', 'fast_string', 'f_value', true, true, true, TypeConflictException::class],
  1136. [null, 'user1', 'app1', 'fast_int', 'n_value', false, false, true, TypeConflictException::class],
  1137. [
  1138. null, 'user1', 'app1', 'fast_float', 'n_value', false, false, true,
  1139. TypeConflictException::class
  1140. ],
  1141. [
  1142. null, 'user1', 'app1', 'lazy_string', 'l_value_2', false, false, true,
  1143. TypeConflictException::class
  1144. ],
  1145. [null, 'user1', 'app1', 'lazy_string', 'l_value', true, false, false],
  1146. [null, 'user1', 'app1', 'lazy_string', 'l_value', true, true, true, TypeConflictException::class],
  1147. [null, 'user1', 'app1', 'lazy_int', 'l_value', false, false, true, TypeConflictException::class],
  1148. [
  1149. null, 'user1', 'app1', 'lazy_float', 'l_value', false, false, true,
  1150. TypeConflictException::class
  1151. ],
  1152. ];
  1153. }
  1154. /**
  1155. * @dataProvider providerSetValueMixed
  1156. */
  1157. public function testSetValueMixed(
  1158. ?array $preload,
  1159. string $userId,
  1160. string $app,
  1161. string $key,
  1162. string $value,
  1163. bool $lazy,
  1164. bool $sensitive,
  1165. bool $result,
  1166. ?string $exception = null,
  1167. ): void {
  1168. $userConfig = $this->generateUserConfig($preload ?? []);
  1169. if ($exception !== null) {
  1170. $this->expectException($exception);
  1171. }
  1172. $edited = $userConfig->setValueMixed($userId, $app, $key, $value, $lazy, ($sensitive) ? 1 : 0);
  1173. if ($exception === null) {
  1174. $this->assertEquals($result, $edited);
  1175. }
  1176. }
  1177. public function providerSetValueString(): array {
  1178. return [
  1179. [null, 'user1', 'app1', 'key1', 'value', false, false, true],
  1180. [null, 'user1', 'app1', 'key1', '12345', true, false, true],
  1181. [null, 'user1', 'app1', 'key1', '12345', true, true, true],
  1182. [null, 'user1', 'app1', 'key1', 'value1', false, false, false],
  1183. [null, 'user1', 'app1', 'key1', 'value1', true, false, true],
  1184. [null, 'user1', 'app1', 'key1', 'value1', false, true, true],
  1185. [null, 'user1', 'app1', 'fast_string', 'f_value_2', false, false, true],
  1186. [null, 'user1', 'app1', 'fast_string', 'f_value', false, false, false],
  1187. [null, 'user1', 'app1', 'fast_string', 'f_value', true, false, true],
  1188. [null, 'user1', 'app1', 'fast_string', 'f_value', true, true, true],
  1189. [null, 'user1', 'app1', 'lazy_string', 'l_value_2', false, false, true],
  1190. [null, 'user1', 'app1', 'lazy_string', 'l_value', true, false, false],
  1191. [null, 'user1', 'app1', 'lazy_string', 'l_value', true, true, true],
  1192. [null, 'user1', 'app1', 'fast_string_sensitive', 'fs_value', false, true, false],
  1193. [null, 'user1', 'app1', 'fast_string_sensitive', 'fs_value', true, true, true],
  1194. [null, 'user1', 'app1', 'fast_string_sensitive', 'fs_value', true, false, true],
  1195. [null, 'user1', 'app1', 'lazy_string_sensitive', 'ls_value', false, true, true],
  1196. [null, 'user1', 'app1', 'lazy_string_sensitive', 'ls_value', true, true, false],
  1197. [null, 'user1', 'app1', 'lazy_string_sensitive', 'ls_value', true, false, false],
  1198. [null, 'user1', 'app1', 'lazy_string_sensitive', 'ls_value_2', true, false, true],
  1199. [null, 'user1', 'app1', 'fast_int', 'n_value', false, false, true, TypeConflictException::class],
  1200. [
  1201. null, 'user1', 'app1', 'fast_float', 'n_value', false, false, true,
  1202. TypeConflictException::class
  1203. ],
  1204. [
  1205. null, 'user1', 'app1', 'fast_float', 'n_value', false, false, true,
  1206. TypeConflictException::class
  1207. ],
  1208. [null, 'user1', 'app1', 'lazy_int', 'n_value', false, false, true, TypeConflictException::class],
  1209. [
  1210. null, 'user1', 'app1', 'lazy_boolean', 'n_value', false, false, true,
  1211. TypeConflictException::class
  1212. ],
  1213. [
  1214. null, 'user1', 'app1', 'lazy_float', 'n_value', false, false, true,
  1215. TypeConflictException::class
  1216. ],
  1217. ];
  1218. }
  1219. /**
  1220. * @dataProvider providerSetValueString
  1221. */
  1222. public function testSetValueString(
  1223. ?array $preload,
  1224. string $userId,
  1225. string $app,
  1226. string $key,
  1227. string $value,
  1228. bool $lazy,
  1229. bool $sensitive,
  1230. bool $result,
  1231. ?string $exception = null,
  1232. ): void {
  1233. $userConfig = $this->generateUserConfig($preload ?? []);
  1234. if ($exception !== null) {
  1235. $this->expectException($exception);
  1236. }
  1237. $edited = $userConfig->setValueString($userId, $app, $key, $value, $lazy, ($sensitive) ? 1 : 0);
  1238. if ($exception !== null) {
  1239. return;
  1240. }
  1241. $this->assertEquals($result, $edited);
  1242. if ($result) {
  1243. $this->assertEquals($value, $userConfig->getValueString($userId, $app, $key, $value, $lazy));
  1244. $userConfig = $this->generateUserConfig($preload ?? []);
  1245. $this->assertEquals($value, $userConfig->getValueString($userId, $app, $key, $value, $lazy));
  1246. }
  1247. }
  1248. public function providerSetValueInt(): array {
  1249. return [
  1250. [null, 'user1', 'app1', 'key1', 12345, false, false, true],
  1251. [null, 'user1', 'app1', 'key1', 12345, true, false, true],
  1252. [null, 'user1', 'app1', 'key1', 12345, true, true, true],
  1253. [null, 'user1', 'app1', 'fast_int', 11, false, false, false],
  1254. [null, 'user1', 'app1', 'fast_int', 111, false, false, true],
  1255. [null, 'user1', 'app1', 'fast_int', 111, true, false, true],
  1256. [null, 'user1', 'app1', 'fast_int', 111, false, true, true],
  1257. [null, 'user1', 'app1', 'fast_int', 11, true, false, true],
  1258. [null, 'user1', 'app1', 'fast_int', 11, false, true, true],
  1259. [null, 'user1', 'app1', 'lazy_int', 12, false, false, true],
  1260. [null, 'user1', 'app1', 'lazy_int', 121, false, false, true],
  1261. [null, 'user1', 'app1', 'lazy_int', 121, true, false, true],
  1262. [null, 'user1', 'app1', 'lazy_int', 121, false, true, true],
  1263. [null, 'user1', 'app1', 'lazy_int', 12, true, false, false],
  1264. [null, 'user1', 'app1', 'lazy_int', 12, false, true, true],
  1265. [null, 'user1', 'app1', 'fast_string', 12345, false, false, true, TypeConflictException::class],
  1266. [null, 'user1', 'app1', 'fast_string', 12345, false, false, false, TypeConflictException::class],
  1267. [null, 'user1', 'app1', 'fast_string', 12345, true, false, true, TypeConflictException::class],
  1268. [null, 'user1', 'app1', 'fast_string', 12345, true, true, true, TypeConflictException::class],
  1269. [null, 'user1', 'app1', 'lazy_string', 12345, false, false, true, TypeConflictException::class],
  1270. [null, 'user1', 'app1', 'lazy_string', 12345, true, false, false, TypeConflictException::class],
  1271. [null, 'user1', 'app1', 'lazy_string', 12345, true, true, true, TypeConflictException::class],
  1272. [null, 'user1', 'app1', 'fast_float', 12345, false, false, true, TypeConflictException::class],
  1273. [null, 'user1', 'app1', 'fast_float', 12345, false, false, true, TypeConflictException::class],
  1274. [null, 'user1', 'app1', 'lazy_boolean', 12345, false, false, true, TypeConflictException::class],
  1275. [null, 'user1', 'app1', 'lazy_float', 12345, false, false, true, TypeConflictException::class],
  1276. ];
  1277. }
  1278. /**
  1279. * @dataProvider providerSetValueInt
  1280. */
  1281. public function testSetValueInt(
  1282. ?array $preload,
  1283. string $userId,
  1284. string $app,
  1285. string $key,
  1286. int $value,
  1287. bool $lazy,
  1288. bool $sensitive,
  1289. bool $result,
  1290. ?string $exception = null,
  1291. ): void {
  1292. $userConfig = $this->generateUserConfig($preload ?? []);
  1293. if ($exception !== null) {
  1294. $this->expectException($exception);
  1295. }
  1296. $edited = $userConfig->setValueInt($userId, $app, $key, $value, $lazy, ($sensitive) ? 1 : 0);
  1297. if ($exception !== null) {
  1298. return;
  1299. }
  1300. $this->assertEquals($result, $edited);
  1301. if ($result) {
  1302. $this->assertEquals($value, $userConfig->getValueInt($userId, $app, $key, $value, $lazy));
  1303. $userConfig = $this->generateUserConfig($preload ?? []);
  1304. $this->assertEquals($value, $userConfig->getValueInt($userId, $app, $key, $value, $lazy));
  1305. }
  1306. }
  1307. public function providerSetValueFloat(): array {
  1308. return [
  1309. [null, 'user1', 'app1', 'key1', 12.345, false, false, true],
  1310. [null, 'user1', 'app1', 'key1', 12.345, true, false, true],
  1311. [null, 'user1', 'app1', 'key1', 12.345, true, true, true],
  1312. [null, 'user1', 'app1', 'fast_float', 3.14, false, false, false],
  1313. [null, 'user1', 'app1', 'fast_float', 3.15, false, false, true],
  1314. [null, 'user1', 'app1', 'fast_float', 3.15, true, false, true],
  1315. [null, 'user1', 'app1', 'fast_float', 3.15, false, true, true],
  1316. [null, 'user1', 'app1', 'fast_float', 3.14, true, false, true],
  1317. [null, 'user1', 'app1', 'fast_float', 3.14, false, true, true],
  1318. [null, 'user1', 'app1', 'lazy_float', 3.14159, false, false, true],
  1319. [null, 'user1', 'app1', 'lazy_float', 3.14158, false, false, true],
  1320. [null, 'user1', 'app1', 'lazy_float', 3.14158, true, false, true],
  1321. [null, 'user1', 'app1', 'lazy_float', 3.14158, false, true, true],
  1322. [null, 'user1', 'app1', 'lazy_float', 3.14159, true, false, false],
  1323. [null, 'user1', 'app1', 'lazy_float', 3.14159, false, true, true],
  1324. [null, 'user1', 'app1', 'fast_string', 12.345, false, false, true, TypeConflictException::class],
  1325. [null, 'user1', 'app1', 'fast_string', 12.345, false, false, false, TypeConflictException::class],
  1326. [null, 'user1', 'app1', 'fast_string', 12.345, true, false, true, TypeConflictException::class],
  1327. [null, 'user1', 'app1', 'fast_string', 12.345, true, true, true, TypeConflictException::class],
  1328. [null, 'user1', 'app1', 'lazy_string', 12.345, false, false, true, TypeConflictException::class],
  1329. [null, 'user1', 'app1', 'lazy_string', 12.345, true, false, false, TypeConflictException::class],
  1330. [null, 'user1', 'app1', 'fast_array', 12.345, true, true, true, TypeConflictException::class],
  1331. [null, 'user1', 'app1', 'fast_int', 12.345, false, false, true, TypeConflictException::class],
  1332. [null, 'user1', 'app1', 'fast_int', 12.345, false, false, true, TypeConflictException::class],
  1333. [null, 'user1', 'app1', 'lazy_boolean', 12.345, false, false, true, TypeConflictException::class],
  1334. ];
  1335. }
  1336. /**
  1337. * @dataProvider providerSetValueFloat
  1338. */
  1339. public function testSetValueFloat(
  1340. ?array $preload,
  1341. string $userId,
  1342. string $app,
  1343. string $key,
  1344. float $value,
  1345. bool $lazy,
  1346. bool $sensitive,
  1347. bool $result,
  1348. ?string $exception = null,
  1349. ): void {
  1350. $userConfig = $this->generateUserConfig($preload ?? []);
  1351. if ($exception !== null) {
  1352. $this->expectException($exception);
  1353. }
  1354. $edited = $userConfig->setValueFloat($userId, $app, $key, $value, $lazy, ($sensitive) ? 1 : 0);
  1355. if ($exception !== null) {
  1356. return;
  1357. }
  1358. $this->assertEquals($result, $edited);
  1359. if ($result) {
  1360. $this->assertEquals($value, $userConfig->getValueFloat($userId, $app, $key, $value, $lazy));
  1361. $userConfig = $this->generateUserConfig($preload ?? []);
  1362. $this->assertEquals($value, $userConfig->getValueFloat($userId, $app, $key, $value, $lazy));
  1363. }
  1364. }
  1365. public function providerSetValueArray(): array {
  1366. return [
  1367. [null, 'user1', 'app1', 'key1', [], false, false, true],
  1368. [null, 'user1', 'app1', 'key1', [], true, false, true],
  1369. [null, 'user1', 'app1', 'key1', [], true, true, true],
  1370. [null, 'user1', 'app1', 'fast_array', ['year' => 2024], false, false, false],
  1371. [null, 'user1', 'app1', 'fast_array', [], false, false, true],
  1372. [null, 'user1', 'app1', 'fast_array', [], true, false, true],
  1373. [null, 'user1', 'app1', 'fast_array', [], false, true, true],
  1374. [null, 'user1', 'app1', 'fast_array', ['year' => 2024], true, false, true],
  1375. [null, 'user1', 'app1', 'fast_array', ['year' => 2024], false, true, true],
  1376. [null, 'user1', 'app1', 'lazy_array', ['month' => 'October'], false, false, true],
  1377. [null, 'user1', 'app1', 'lazy_array', ['month' => 'September'], false, false, true],
  1378. [null, 'user1', 'app1', 'lazy_array', ['month' => 'September'], true, false, true],
  1379. [null, 'user1', 'app1', 'lazy_array', ['month' => 'September'], false, true, true],
  1380. [null, 'user1', 'app1', 'lazy_array', ['month' => 'October'], true, false, false],
  1381. [null, 'user1', 'app1', 'lazy_array', ['month' => 'October'], false, true, true],
  1382. [null, 'user1', 'app1', 'fast_string', [], false, false, true, TypeConflictException::class],
  1383. [null, 'user1', 'app1', 'fast_string', [], false, false, false, TypeConflictException::class],
  1384. [null, 'user1', 'app1', 'fast_string', [], true, false, true, TypeConflictException::class],
  1385. [null, 'user1', 'app1', 'fast_string', [], true, true, true, TypeConflictException::class],
  1386. [null, 'user1', 'app1', 'lazy_string', [], false, false, true, TypeConflictException::class],
  1387. [null, 'user1', 'app1', 'lazy_string', [], true, false, false, TypeConflictException::class],
  1388. [null, 'user1', 'app1', 'lazy_string', [], true, true, true, TypeConflictException::class],
  1389. [null, 'user1', 'app1', 'fast_int', [], false, false, true, TypeConflictException::class],
  1390. [null, 'user1', 'app1', 'fast_int', [], false, false, true, TypeConflictException::class],
  1391. [null, 'user1', 'app1', 'lazy_boolean', [], false, false, true, TypeConflictException::class],
  1392. ];
  1393. }
  1394. /**
  1395. * @dataProvider providerSetValueArray
  1396. */
  1397. public function testSetValueArray(
  1398. ?array $preload,
  1399. string $userId,
  1400. string $app,
  1401. string $key,
  1402. array $value,
  1403. bool $lazy,
  1404. bool $sensitive,
  1405. bool $result,
  1406. ?string $exception = null,
  1407. ): void {
  1408. $userConfig = $this->generateUserConfig($preload ?? []);
  1409. if ($exception !== null) {
  1410. $this->expectException($exception);
  1411. }
  1412. $edited = $userConfig->setValueArray($userId, $app, $key, $value, $lazy, ($sensitive) ? 1 : 0);
  1413. if ($exception !== null) {
  1414. return;
  1415. }
  1416. $this->assertEquals($result, $edited);
  1417. if ($result) {
  1418. $this->assertEqualsCanonicalizing(
  1419. $value, $userConfig->getValueArray($userId, $app, $key, $value, $lazy)
  1420. );
  1421. $userConfig = $this->generateUserConfig($preload ?? []);
  1422. $this->assertEqualsCanonicalizing(
  1423. $value, $userConfig->getValueArray($userId, $app, $key, $value, $lazy)
  1424. );
  1425. }
  1426. }
  1427. public function providerUpdateSensitive(): array {
  1428. return [
  1429. [null, 'user1', 'app1', 'key1', false, false],
  1430. [['user1'], 'user1', 'app1', 'key1', false, false],
  1431. [null, 'user1', 'app1', 'key1', true, true],
  1432. [['user1'], 'user1', 'app1', 'key1', true, true],
  1433. ];
  1434. }
  1435. /**
  1436. * @dataProvider providerUpdateSensitive
  1437. */
  1438. public function testUpdateSensitive(
  1439. ?array $preload,
  1440. string $userId,
  1441. string $app,
  1442. string $key,
  1443. bool $sensitive,
  1444. bool $result,
  1445. ?string $exception = null,
  1446. ): void {
  1447. $userConfig = $this->generateUserConfig($preload ?? []);
  1448. if ($exception !== null) {
  1449. $this->expectException($exception);
  1450. }
  1451. $edited = $userConfig->updateSensitive($userId, $app, $key, $sensitive);
  1452. if ($exception !== null) {
  1453. return;
  1454. }
  1455. $this->assertEquals($result, $edited);
  1456. if ($result) {
  1457. $this->assertEquals($sensitive, $userConfig->isSensitive($userId, $app, $key));
  1458. $userConfig = $this->generateUserConfig($preload ?? []);
  1459. $this->assertEquals($sensitive, $userConfig->isSensitive($userId, $app, $key));
  1460. if ($sensitive) {
  1461. $this->assertEquals(true, str_starts_with(
  1462. $userConfig->statusCache()['fastCache'][$userId][$app][$key] ??
  1463. $userConfig->statusCache()['lazyCache'][$userId][$app][$key],
  1464. '$UserConfigEncryption$')
  1465. );
  1466. }
  1467. }
  1468. }
  1469. public function providerUpdateGlobalSensitive(): array {
  1470. return [[true], [false]];
  1471. }
  1472. /**
  1473. * @dataProvider providerUpdateGlobalSensitive
  1474. */
  1475. public function testUpdateGlobalSensitive(bool $sensitive): void {
  1476. $userConfig = $this->generateUserConfig($preload ?? []);
  1477. $app = 'app2';
  1478. if ($sensitive) {
  1479. $key = 'key2';
  1480. $value = 'value2a';
  1481. } else {
  1482. $key = 'key4';
  1483. $value = 'value4';
  1484. }
  1485. $this->assertEquals($value, $userConfig->getValueString('user1', $app, $key));
  1486. foreach (['user1', 'user2', 'user3', 'user4'] as $userId) {
  1487. $userConfig->getValueString($userId, $app, $key); // cache loading for userId
  1488. $this->assertEquals(
  1489. !$sensitive, str_starts_with(
  1490. $userConfig->statusCache()['fastCache'][$userId][$app][$key] ??
  1491. $userConfig->statusCache()['lazyCache'][$userId][$app][$key],
  1492. '$UserConfigEncryption$'
  1493. )
  1494. );
  1495. }
  1496. $userConfig->updateGlobalSensitive($app, $key, $sensitive);
  1497. $this->assertEquals($value, $userConfig->getValueString('user1', $app, $key));
  1498. foreach (['user1', 'user2', 'user3', 'user4'] as $userId) {
  1499. $this->assertEquals($sensitive, $userConfig->isSensitive($userId, $app, $key));
  1500. // should only work if updateGlobalSensitive drop cache
  1501. $this->assertEquals($sensitive, str_starts_with(
  1502. $userConfig->statusCache()['fastCache'][$userId][$app][$key] ??
  1503. $userConfig->statusCache()['lazyCache'][$userId][$app][$key],
  1504. '$UserConfigEncryption$')
  1505. );
  1506. }
  1507. }
  1508. public function providerUpdateLazy(): array {
  1509. return [
  1510. [null, 'user1', 'app1', 'key1', false, false],
  1511. [['user1'], 'user1', 'app1', 'key1', false, false],
  1512. [null, 'user1', 'app1', 'key1', true, true],
  1513. [['user1'], 'user1', 'app1', 'key1', true, true],
  1514. ];
  1515. }
  1516. /**
  1517. * @dataProvider providerUpdateLazy
  1518. */
  1519. public function testUpdateLazy(
  1520. ?array $preload,
  1521. string $userId,
  1522. string $app,
  1523. string $key,
  1524. bool $lazy,
  1525. bool $result,
  1526. ?string $exception = null,
  1527. ): void {
  1528. $userConfig = $this->generateUserConfig($preload ?? []);
  1529. if ($exception !== null) {
  1530. $this->expectException($exception);
  1531. }
  1532. $edited = $userConfig->updateLazy($userId, $app, $key, $lazy);
  1533. if ($exception !== null) {
  1534. return;
  1535. }
  1536. $this->assertEquals($result, $edited);
  1537. if ($result) {
  1538. $this->assertEquals($lazy, $userConfig->isLazy($userId, $app, $key));
  1539. $userConfig = $this->generateUserConfig($preload ?? []);
  1540. $this->assertEquals($lazy, $userConfig->isLazy($userId, $app, $key));
  1541. }
  1542. }
  1543. public function providerUpdateGlobalLazy(): array {
  1544. return [[true], [false]];
  1545. }
  1546. /**
  1547. * @dataProvider providerUpdateGlobalLazy
  1548. */
  1549. public function testUpdateGlobalLazy(bool $lazy): void {
  1550. $userConfig = $this->generateUserConfig($preload ?? []);
  1551. $app = 'app2';
  1552. if ($lazy) {
  1553. $key = 'key4';
  1554. $value = 'value4';
  1555. } else {
  1556. $key = 'key3';
  1557. $value = 'value3';
  1558. }
  1559. $this->assertEquals($value, $userConfig->getValueString('user1', $app, $key, '', !$lazy));
  1560. foreach (['user1', 'user2', 'user3', 'user4'] as $userId) {
  1561. $this->assertEquals(!$lazy, $userConfig->isLazy($userId, $app, $key));
  1562. }
  1563. $userConfig->updateGlobalLazy($app, $key, $lazy);
  1564. $this->assertEquals($value, $userConfig->getValueString('user1', $app, $key, '', $lazy));
  1565. foreach (['user1', 'user2', 'user3', 'user4'] as $userId) {
  1566. $this->assertEquals($lazy, $userConfig->isLazy($userId, $app, $key));
  1567. }
  1568. }
  1569. public function providerGetDetails(): array {
  1570. return [
  1571. [
  1572. 'user3', 'app2', 'key2',
  1573. [
  1574. 'userId' => 'user3',
  1575. 'app' => 'app2',
  1576. 'key' => 'key2',
  1577. 'value' => 'value2c',
  1578. 'type' => 0,
  1579. 'lazy' => false,
  1580. 'typeString' => 'mixed',
  1581. 'sensitive' => false
  1582. ]
  1583. ],
  1584. [
  1585. 'user1', 'app1', 'lazy_int',
  1586. [
  1587. 'userId' => 'user1',
  1588. 'app' => 'app1',
  1589. 'key' => 'lazy_int',
  1590. 'value' => 12,
  1591. 'type' => 2,
  1592. 'lazy' => true,
  1593. 'typeString' => 'int',
  1594. 'sensitive' => false
  1595. ]
  1596. ],
  1597. [
  1598. 'user1', 'app1', 'fast_float_sensitive',
  1599. [
  1600. 'userId' => 'user1',
  1601. 'app' => 'app1',
  1602. 'key' => 'fast_float_sensitive',
  1603. 'value' => 1.41,
  1604. 'type' => 3,
  1605. 'lazy' => false,
  1606. 'typeString' => 'float',
  1607. 'sensitive' => true
  1608. ]
  1609. ],
  1610. ];
  1611. }
  1612. /**
  1613. * @dataProvider providerGetDetails
  1614. */
  1615. public function testGetDetails(string $userId, string $app, string $key, array $result): void {
  1616. $userConfig = $this->generateUserConfig($preload ?? []);
  1617. $this->assertEqualsCanonicalizing($result, $userConfig->getDetails($userId, $app, $key));
  1618. }
  1619. public function providerDeletePreference(): array {
  1620. return [
  1621. [null, 'user1', 'app1', 'key22'],
  1622. [['user1'], 'user1', 'app1', 'fast_string_sensitive'],
  1623. [null, 'user1', 'app1', 'lazy_array_sensitive'],
  1624. [['user2'], 'user1', 'app1', 'lazy_array_sensitive'],
  1625. [null, 'user2', 'only-lazy', 'key1'],
  1626. [['user2'], 'user2', 'only-lazy', 'key1'],
  1627. ];
  1628. }
  1629. /**
  1630. * @dataProvider providerDeletePreference
  1631. */
  1632. public function testDeletePreference(
  1633. ?array $preload,
  1634. string $userId,
  1635. string $app,
  1636. string $key,
  1637. ): void {
  1638. $userConfig = $this->generateUserConfig($preload ?? []);
  1639. $lazy = $userConfig->isLazy($userId, $app, $key);
  1640. $userConfig = $this->generateUserConfig($preload ?? []);
  1641. $this->assertEquals(true, $userConfig->hasKey($userId, $app, $key, $lazy));
  1642. $userConfig->deleteUserConfig($userId, $app, $key);
  1643. $this->assertEquals(false, $userConfig->hasKey($userId, $app, $key, $lazy));
  1644. $userConfig = $this->generateUserConfig($preload ?? []);
  1645. $this->assertEquals(false, $userConfig->hasKey($userId, $app, $key, $lazy));
  1646. }
  1647. public function providerDeleteKey(): array {
  1648. return [
  1649. [null, 'app2', 'key3'],
  1650. [['user1'], 'app2', 'key3'],
  1651. [null, 'only-lazy', 'key1'],
  1652. [['user2'], 'only-lazy', 'key1'],
  1653. [null, 'app2', 'lazy_string_sensitive'],
  1654. [['user3', 'user1'], 'app2', 'lazy_string_sensitive'],
  1655. ];
  1656. }
  1657. /**
  1658. * @dataProvider providerDeleteKey
  1659. */
  1660. public function testDeleteKey(
  1661. ?array $preload,
  1662. string $app,
  1663. string $key,
  1664. ): void {
  1665. $userConfig = $this->generateUserConfig($preload ?? []);
  1666. $userConfig->deleteKey($app, $key);
  1667. foreach (['user1', 'user2', 'user3', 'user4'] as $userId) {
  1668. $this->assertEquals(false, $userConfig->hasKey($userId, $app, $key, null));
  1669. $userConfigTemp = $this->generateUserConfig($preload ?? []);
  1670. $this->assertEquals(false, $userConfigTemp->hasKey($userId, $app, $key, null));
  1671. }
  1672. }
  1673. public function testDeleteApp(): void {
  1674. $userConfig = $this->generateUserConfig();
  1675. $userConfig->deleteApp('only-lazy');
  1676. foreach (['user1', 'user2', 'user3', 'user4'] as $userId) {
  1677. $this->assertEquals(false, in_array('only-lazy', $userConfig->getApps($userId)));
  1678. $userConfigTemp = $this->generateUserConfig();
  1679. $this->assertEquals(false, in_array('only-lazy', $userConfigTemp->getApps($userId)));
  1680. }
  1681. }
  1682. public function testDeleteAllPreferences(): void {
  1683. $userConfig = $this->generateUserConfig();
  1684. $userConfig->deleteAllUserConfig('user1');
  1685. $this->assertEqualsCanonicalizing([], $userConfig->getApps('user1'));
  1686. $userConfig = $this->generateUserConfig();
  1687. $this->assertEqualsCanonicalizing([], $userConfig->getApps('user1'));
  1688. }
  1689. public function testClearCache(): void {
  1690. $userConfig = $this->generateUserConfig(['user1', 'user2']);
  1691. $userConfig->clearCache('user1');
  1692. $this->assertEquals(true, $userConfig->statusCache()['fastLoaded']['user2']);
  1693. $this->assertEquals(false, $userConfig->statusCache()['fastLoaded']['user1']);
  1694. $this->assertEquals('value2a', $userConfig->getValueString('user1', 'app2', 'key2'));
  1695. $this->assertEquals(false, $userConfig->statusCache()['lazyLoaded']['user1']);
  1696. $this->assertEquals(true, $userConfig->statusCache()['fastLoaded']['user1']);
  1697. }
  1698. public function testClearCacheAll(): void {
  1699. $userConfig = $this->generateUserConfig(['user1', 'user2']);
  1700. $userConfig->clearCacheAll();
  1701. $this->assertEqualsCanonicalizing(
  1702. [
  1703. 'fastLoaded' => [],
  1704. 'fastCache' => [],
  1705. 'lazyLoaded' => [],
  1706. 'lazyCache' => [],
  1707. 'valueTypes' => [],
  1708. ],
  1709. $userConfig->statusCache()
  1710. );
  1711. }
  1712. }