UpdaterTest.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. <?php
  2. require_once 'application/config/ConfigManager.php';
  3. require_once 'tests/Updater/DummyUpdater.php';
  4. require_once 'inc/rain.tpl.class.php';
  5. /**
  6. * Class UpdaterTest.
  7. * Runs unit tests against the Updater class.
  8. */
  9. class UpdaterTest extends PHPUnit_Framework_TestCase
  10. {
  11. /**
  12. * @var string Path to test datastore.
  13. */
  14. protected static $testDatastore = 'sandbox/datastore.php';
  15. /**
  16. * @var string Config file path (without extension).
  17. */
  18. protected static $configFile = 'tests/utils/config/configJson';
  19. /**
  20. * @var ConfigManager
  21. */
  22. protected $conf;
  23. /**
  24. * Executed before each test.
  25. */
  26. public function setUp()
  27. {
  28. $this->conf = new ConfigManager(self::$configFile);
  29. }
  30. /**
  31. * Test read_updates_file with an empty/missing file.
  32. */
  33. public function testReadEmptyUpdatesFile()
  34. {
  35. $this->assertEquals(array(), read_updates_file(''));
  36. $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
  37. touch($updatesFile);
  38. $this->assertEquals(array(), read_updates_file($updatesFile));
  39. unlink($updatesFile);
  40. }
  41. /**
  42. * Test read/write updates file.
  43. */
  44. public function testReadWriteUpdatesFile()
  45. {
  46. $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
  47. $updatesMethods = array('m1', 'm2', 'm3');
  48. write_updates_file($updatesFile, $updatesMethods);
  49. $readMethods = read_updates_file($updatesFile);
  50. $this->assertEquals($readMethods, $updatesMethods);
  51. // Update
  52. $updatesMethods[] = 'm4';
  53. write_updates_file($updatesFile, $updatesMethods);
  54. $readMethods = read_updates_file($updatesFile);
  55. $this->assertEquals($readMethods, $updatesMethods);
  56. unlink($updatesFile);
  57. }
  58. /**
  59. * Test errors in write_updates_file(): empty updates file.
  60. *
  61. * @expectedException Exception
  62. * @expectedExceptionMessageRegExp /Updates file path is not set(.*)/
  63. */
  64. public function testWriteEmptyUpdatesFile()
  65. {
  66. write_updates_file('', array('test'));
  67. }
  68. /**
  69. * Test errors in write_updates_file(): not writable updates file.
  70. *
  71. * @expectedException Exception
  72. * @expectedExceptionMessageRegExp /Unable to write(.*)/
  73. */
  74. public function testWriteUpdatesFileNotWritable()
  75. {
  76. $updatesFile = $this->conf->get('resource.data_dir') . '/updates.txt';
  77. touch($updatesFile);
  78. chmod($updatesFile, 0444);
  79. try {
  80. @write_updates_file($updatesFile, array('test'));
  81. } catch (Exception $e) {
  82. unlink($updatesFile);
  83. throw $e;
  84. }
  85. }
  86. /**
  87. * Test the update() method, with no update to run.
  88. * 1. Everything already run.
  89. * 2. User is logged out.
  90. */
  91. public function testNoUpdates()
  92. {
  93. $updates = array(
  94. 'updateMethodDummy1',
  95. 'updateMethodDummy2',
  96. 'updateMethodDummy3',
  97. 'updateMethodException',
  98. );
  99. $updater = new DummyUpdater($updates, array(), $this->conf, true);
  100. $this->assertEquals(array(), $updater->update());
  101. $updater = new DummyUpdater(array(), array(), $this->conf, false);
  102. $this->assertEquals(array(), $updater->update());
  103. }
  104. /**
  105. * Test the update() method, with all updates to run (except the failing one).
  106. */
  107. public function testUpdatesFirstTime()
  108. {
  109. $updates = array('updateMethodException',);
  110. $expectedUpdates = array(
  111. 'updateMethodDummy1',
  112. 'updateMethodDummy2',
  113. 'updateMethodDummy3',
  114. );
  115. $updater = new DummyUpdater($updates, array(), $this->conf, true);
  116. $this->assertEquals($expectedUpdates, $updater->update());
  117. }
  118. /**
  119. * Test the update() method, only one update to run.
  120. */
  121. public function testOneUpdate()
  122. {
  123. $updates = array(
  124. 'updateMethodDummy1',
  125. 'updateMethodDummy3',
  126. 'updateMethodException',
  127. );
  128. $expectedUpdate = array('updateMethodDummy2');
  129. $updater = new DummyUpdater($updates, array(), $this->conf, true);
  130. $this->assertEquals($expectedUpdate, $updater->update());
  131. }
  132. /**
  133. * Test Update failed.
  134. *
  135. * @expectedException UpdaterException
  136. */
  137. public function testUpdateFailed()
  138. {
  139. $updates = array(
  140. 'updateMethodDummy1',
  141. 'updateMethodDummy2',
  142. 'updateMethodDummy3',
  143. );
  144. $updater = new DummyUpdater($updates, array(), $this->conf, true);
  145. $updater->update();
  146. }
  147. /**
  148. * Test update mergeDeprecatedConfig:
  149. * 1. init a config file.
  150. * 2. init a options.php file with update value.
  151. * 3. merge.
  152. * 4. check updated value in config file.
  153. */
  154. public function testUpdateMergeDeprecatedConfig()
  155. {
  156. $this->conf->setConfigFile('tests/utils/config/configPhp');
  157. $this->conf->reset();
  158. $optionsFile = 'tests/Updater/options.php';
  159. $options = '<?php
  160. $GLOBALS[\'privateLinkByDefault\'] = true;';
  161. file_put_contents($optionsFile, $options);
  162. // tmp config file.
  163. $this->conf->setConfigFile('tests/Updater/config');
  164. // merge configs
  165. $updater = new Updater(array(), array(), $this->conf, true);
  166. // This writes a new config file in tests/Updater/config.php
  167. $updater->updateMethodMergeDeprecatedConfigFile();
  168. // make sure updated field is changed
  169. $this->conf->reload();
  170. $this->assertTrue($this->conf->get('privacy.default_private_links'));
  171. $this->assertFalse(is_file($optionsFile));
  172. // Delete the generated file.
  173. unlink($this->conf->getConfigFileExt());
  174. }
  175. /**
  176. * Test mergeDeprecatedConfig in without options file.
  177. */
  178. public function testMergeDeprecatedConfigNoFile()
  179. {
  180. $updater = new Updater(array(), array(), $this->conf, true);
  181. $updater->updateMethodMergeDeprecatedConfigFile();
  182. $this->assertEquals('root', $this->conf->get('credentials.login'));
  183. }
  184. /**
  185. * Test renameDashTags update method.
  186. */
  187. public function testRenameDashTags()
  188. {
  189. $refDB = new ReferenceLinkDB();
  190. $refDB->write(self::$testDatastore);
  191. $linkDB = new LinkDB(self::$testDatastore, true, false);
  192. $this->assertEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
  193. $updater = new Updater(array(), $linkDB, $this->conf, true);
  194. $updater->updateMethodRenameDashTags();
  195. $this->assertNotEmpty($linkDB->filterSearch(array('searchtags' => 'exclude')));
  196. }
  197. /**
  198. * Convert old PHP config file to JSON config.
  199. */
  200. public function testConfigToJson()
  201. {
  202. $configFile = 'tests/utils/config/configPhp';
  203. $this->conf->setConfigFile($configFile);
  204. $this->conf->reset();
  205. // The ConfigIO is initialized with ConfigPhp.
  206. $this->assertTrue($this->conf->getConfigIO() instanceof ConfigPhp);
  207. $updater = new Updater(array(), array(), $this->conf, false);
  208. $done = $updater->updateMethodConfigToJson();
  209. $this->assertTrue($done);
  210. // The ConfigIO has been updated to ConfigJson.
  211. $this->assertTrue($this->conf->getConfigIO() instanceof ConfigJson);
  212. $this->assertTrue(file_exists($this->conf->getConfigFileExt()));
  213. // Check JSON config data.
  214. $this->conf->reload();
  215. $this->assertEquals('root', $this->conf->get('credentials.login'));
  216. $this->assertEquals('lala', $this->conf->get('redirector.url'));
  217. $this->assertEquals('data/datastore.php', $this->conf->get('resource.datastore'));
  218. $this->assertEquals('1', $this->conf->get('plugins.WALLABAG_VERSION'));
  219. rename($configFile . '.save.php', $configFile . '.php');
  220. unlink($this->conf->getConfigFileExt());
  221. }
  222. /**
  223. * Launch config conversion update with an existing JSON file => nothing to do.
  224. */
  225. public function testConfigToJsonNothingToDo()
  226. {
  227. $filetime = filemtime($this->conf->getConfigFileExt());
  228. $updater = new Updater(array(), array(), $this->conf, false);
  229. $done = $updater->updateMethodConfigToJson();
  230. $this->assertTrue($done);
  231. $expected = filemtime($this->conf->getConfigFileExt());
  232. $this->assertEquals($expected, $filetime);
  233. }
  234. /**
  235. * Test escapeUnescapedConfig with valid data.
  236. */
  237. public function testEscapeConfig()
  238. {
  239. $sandbox = 'sandbox/config';
  240. copy(self::$configFile . '.json.php', $sandbox . '.json.php');
  241. $this->conf = new ConfigManager($sandbox);
  242. $title = '<script>alert("title");</script>';
  243. $headerLink = '<script>alert("header_link");</script>';
  244. $redirectorUrl = '<script>alert("redirector");</script>';
  245. $this->conf->set('general.title', $title);
  246. $this->conf->set('general.header_link', $headerLink);
  247. $this->conf->set('redirector.url', $redirectorUrl);
  248. $updater = new Updater(array(), array(), $this->conf, true);
  249. $done = $updater->updateMethodEscapeUnescapedConfig();
  250. $this->assertTrue($done);
  251. $this->conf->reload();
  252. $this->assertEquals(escape($title), $this->conf->get('general.title'));
  253. $this->assertEquals(escape($headerLink), $this->conf->get('general.header_link'));
  254. $this->assertEquals(escape($redirectorUrl), $this->conf->get('redirector.url'));
  255. unlink($sandbox . '.json.php');
  256. }
  257. /**
  258. * Test updateMethodApiSettings(): create default settings for the API (enabled + secret).
  259. */
  260. public function testUpdateApiSettings()
  261. {
  262. $confFile = 'sandbox/config';
  263. copy(self::$configFile .'.json.php', $confFile .'.json.php');
  264. $conf = new ConfigManager($confFile);
  265. $updater = new Updater(array(), array(), $conf, true);
  266. $this->assertFalse($conf->exists('api.enabled'));
  267. $this->assertFalse($conf->exists('api.secret'));
  268. $updater->updateMethodApiSettings();
  269. $conf->reload();
  270. $this->assertTrue($conf->get('api.enabled'));
  271. $this->assertTrue($conf->exists('api.secret'));
  272. unlink($confFile .'.json.php');
  273. }
  274. /**
  275. * Test updateMethodApiSettings(): already set, do nothing.
  276. */
  277. public function testUpdateApiSettingsNothingToDo()
  278. {
  279. $confFile = 'sandbox/config';
  280. copy(self::$configFile .'.json.php', $confFile .'.json.php');
  281. $conf = new ConfigManager($confFile);
  282. $conf->set('api.enabled', false);
  283. $conf->set('api.secret', '');
  284. $updater = new Updater(array(), array(), $conf, true);
  285. $updater->updateMethodApiSettings();
  286. $this->assertFalse($conf->get('api.enabled'));
  287. $this->assertEmpty($conf->get('api.secret'));
  288. unlink($confFile .'.json.php');
  289. }
  290. /**
  291. * Test updateMethodDatastoreIds().
  292. */
  293. public function testDatastoreIds()
  294. {
  295. $links = array(
  296. '20121206_182539' => array(
  297. 'linkdate' => '20121206_182539',
  298. 'title' => 'Geek and Poke',
  299. 'url' => 'http://geek-and-poke.com/',
  300. 'description' => 'desc',
  301. 'tags' => 'dev cartoon tag1 tag2 tag3 tag4 ',
  302. 'updated' => '20121206_190301',
  303. 'private' => false,
  304. ),
  305. '20121206_172539' => array(
  306. 'linkdate' => '20121206_172539',
  307. 'title' => 'UserFriendly - Samba',
  308. 'url' => 'http://ars.userfriendly.org/cartoons/?id=20010306',
  309. 'description' => '',
  310. 'tags' => 'samba cartoon web',
  311. 'private' => false,
  312. ),
  313. '20121206_142300' => array(
  314. 'linkdate' => '20121206_142300',
  315. 'title' => 'UserFriendly - Web Designer',
  316. 'url' => 'http://ars.userfriendly.org/cartoons/?id=20121206',
  317. 'description' => 'Naming conventions... #private',
  318. 'tags' => 'samba cartoon web',
  319. 'private' => true,
  320. ),
  321. );
  322. $refDB = new ReferenceLinkDB();
  323. $refDB->setLinks($links);
  324. $refDB->write(self::$testDatastore);
  325. $linkDB = new LinkDB(self::$testDatastore, true, false);
  326. $checksum = hash_file('sha1', self::$testDatastore);
  327. $this->conf->set('resource.data_dir', 'sandbox');
  328. $this->conf->set('resource.datastore', self::$testDatastore);
  329. $updater = new Updater(array(), $linkDB, $this->conf, true);
  330. $this->assertTrue($updater->updateMethodDatastoreIds());
  331. $linkDB = new LinkDB(self::$testDatastore, true, false);
  332. $backup = glob($this->conf->get('resource.data_dir') . '/datastore.'. date('YmdH') .'*.php');
  333. $backup = $backup[0];
  334. $this->assertFileExists($backup);
  335. $this->assertEquals($checksum, hash_file('sha1', $backup));
  336. unlink($backup);
  337. $this->assertEquals(3, count($linkDB));
  338. $this->assertTrue(isset($linkDB[0]));
  339. $this->assertFalse(isset($linkDB[0]['linkdate']));
  340. $this->assertEquals(0, $linkDB[0]['id']);
  341. $this->assertEquals('UserFriendly - Web Designer', $linkDB[0]['title']);
  342. $this->assertEquals('http://ars.userfriendly.org/cartoons/?id=20121206', $linkDB[0]['url']);
  343. $this->assertEquals('Naming conventions... #private', $linkDB[0]['description']);
  344. $this->assertEquals('samba cartoon web', $linkDB[0]['tags']);
  345. $this->assertTrue($linkDB[0]['private']);
  346. $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_142300'), $linkDB[0]['created']);
  347. $this->assertTrue(isset($linkDB[1]));
  348. $this->assertFalse(isset($linkDB[1]['linkdate']));
  349. $this->assertEquals(1, $linkDB[1]['id']);
  350. $this->assertEquals('UserFriendly - Samba', $linkDB[1]['title']);
  351. $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_172539'), $linkDB[1]['created']);
  352. $this->assertTrue(isset($linkDB[2]));
  353. $this->assertFalse(isset($linkDB[2]['linkdate']));
  354. $this->assertEquals(2, $linkDB[2]['id']);
  355. $this->assertEquals('Geek and Poke', $linkDB[2]['title']);
  356. $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_182539'), $linkDB[2]['created']);
  357. $this->assertEquals(DateTime::createFromFormat(LinkDB::LINK_DATE_FORMAT, '20121206_190301'), $linkDB[2]['updated']);
  358. }
  359. /**
  360. * Test updateMethodDatastoreIds() with the update already applied: nothing to do.
  361. */
  362. public function testDatastoreIdsNothingToDo()
  363. {
  364. $refDB = new ReferenceLinkDB();
  365. $refDB->write(self::$testDatastore);
  366. $linkDB = new LinkDB(self::$testDatastore, true, false);
  367. $this->conf->set('resource.data_dir', 'sandbox');
  368. $this->conf->set('resource.datastore', self::$testDatastore);
  369. $checksum = hash_file('sha1', self::$testDatastore);
  370. $updater = new Updater(array(), $linkDB, $this->conf, true);
  371. $this->assertTrue($updater->updateMethodDatastoreIds());
  372. $this->assertEquals($checksum, hash_file('sha1', self::$testDatastore));
  373. }
  374. /**
  375. * Test defaultTheme update with default settings: nothing to do.
  376. */
  377. public function testDefaultThemeWithDefaultSettings()
  378. {
  379. $sandbox = 'sandbox/config';
  380. copy(self::$configFile . '.json.php', $sandbox . '.json.php');
  381. $this->conf = new ConfigManager($sandbox);
  382. $updater = new Updater([], [], $this->conf, true);
  383. $this->assertTrue($updater->updateMethodDefaultTheme());
  384. $this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
  385. $this->assertEquals('default', $this->conf->get('resource.theme'));
  386. $this->conf = new ConfigManager($sandbox);
  387. $this->assertEquals('tpl/', $this->conf->get('resource.raintpl_tpl'));
  388. $this->assertEquals('default', $this->conf->get('resource.theme'));
  389. unlink($sandbox . '.json.php');
  390. }
  391. /**
  392. * Test defaultTheme update with a custom theme in a subfolder
  393. */
  394. public function testDefaultThemeWithCustomTheme()
  395. {
  396. $theme = 'iamanartist';
  397. $sandbox = 'sandbox/config';
  398. copy(self::$configFile . '.json.php', $sandbox . '.json.php');
  399. $this->conf = new ConfigManager($sandbox);
  400. mkdir('sandbox/'. $theme);
  401. touch('sandbox/'. $theme .'/linklist.html');
  402. $this->conf->set('resource.raintpl_tpl', 'sandbox/'. $theme .'/');
  403. $updater = new Updater([], [], $this->conf, true);
  404. $this->assertTrue($updater->updateMethodDefaultTheme());
  405. $this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
  406. $this->assertEquals($theme, $this->conf->get('resource.theme'));
  407. $this->conf = new ConfigManager($sandbox);
  408. $this->assertEquals('sandbox', $this->conf->get('resource.raintpl_tpl'));
  409. $this->assertEquals($theme, $this->conf->get('resource.theme'));
  410. unlink($sandbox . '.json.php');
  411. unlink('sandbox/'. $theme .'/linklist.html');
  412. rmdir('sandbox/'. $theme);
  413. }
  414. }