feeds_scheduler.test 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <?php
  2. /**
  3. * @file
  4. * Feeds tests.
  5. */
  6. /**
  7. * Test cron scheduling.
  8. */
  9. class FeedsSchedulerTestCase extends FeedsWebTestCase {
  10. public static function getInfo() {
  11. return array(
  12. 'name' => 'Scheduler',
  13. 'description' => 'Tests for feeds scheduler.',
  14. 'group' => 'Feeds',
  15. );
  16. }
  17. /**
  18. * Test scheduling on cron.
  19. */
  20. public function testScheduling() {
  21. // Create importer configuration.
  22. $this->createImporterConfiguration();
  23. $this->addMappings('syndication',
  24. array(
  25. 0 => array(
  26. 'source' => 'title',
  27. 'target' => 'title',
  28. 'unique' => FALSE,
  29. ),
  30. 1 => array(
  31. 'source' => 'description',
  32. 'target' => 'body',
  33. ),
  34. 2 => array(
  35. 'source' => 'timestamp',
  36. 'target' => 'created',
  37. ),
  38. 3 => array(
  39. 'source' => 'url',
  40. 'target' => 'url',
  41. 'unique' => TRUE,
  42. ),
  43. 4 => array(
  44. 'source' => 'guid',
  45. 'target' => 'guid',
  46. 'unique' => TRUE,
  47. ),
  48. )
  49. );
  50. // Create 10 feed nodes. Turn off import on create before doing that.
  51. $edit = array(
  52. 'import_on_create' => FALSE,
  53. );
  54. $this->drupalPost('admin/structure/feeds/syndication/settings', $edit, 'Save');
  55. $this->assertText('Do not import on submission');
  56. $nids = $this->createFeedNodes();
  57. // This implicitly tests the import_on_create node setting being 0.
  58. $this->assertTrue($nids[0] == 1 && $nids[1] == 2, 'Node ids sequential.');
  59. // Check whether feed got properly added to scheduler.
  60. foreach ($nids as $nid) {
  61. $this->assertEqual(1, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND id = :nid AND name = 'feeds_source_import' AND last <> 0 AND scheduled = 0 AND period = 1800 AND periodic = 1", array(':nid' => $nid))->fetchField());
  62. }
  63. // Take time for comparisons.
  64. $time = time();
  65. sleep(1);
  66. // Log out and run cron, no changes.
  67. $this->drupalLogout();
  68. $this->cronRun();
  69. $count = db_query("SELECT COUNT(*) FROM {job_schedule} WHERE last > :time", array(':time' => $time))->fetchField();
  70. $this->assertEqual($count, 0, '0 feeds refreshed on cron.');
  71. // Set next time to 0 to simulate updates.
  72. // There should be 2 x job_schedule_num (= 10) feeds updated now.
  73. db_query("UPDATE {job_schedule} SET next = 0");
  74. $this->cronRun();
  75. $this->cronRun();
  76. // There should be feeds_schedule_num X 2 (= 20) feeds updated now.
  77. $schedule = array();
  78. $rows = db_query("SELECT id, last, scheduled FROM {job_schedule} WHERE last > :time", array(':time' => $time));
  79. foreach ($rows as $row) {
  80. $schedule[$row->id] = $row;
  81. }
  82. $this->assertEqual(count($schedule), 20, '20 feeds refreshed on cron.' . $count);
  83. // There should be 200 article nodes in the database.
  84. $count = db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article' AND status = 1")->fetchField();
  85. $this->assertEqual($count, 200, 'There are 200 article nodes aggregated.' . $count);
  86. // There shouldn't be any items with scheduled = 1 now, if so, this would
  87. // mean they are stuck.
  88. $count = db_query("SELECT COUNT(*) FROM {job_schedule} WHERE scheduled = 1")->fetchField();
  89. $this->assertEqual($count, 0, 'All items are unscheduled (schedule flag = 0).' . $count);
  90. // Hit cron again twice.
  91. $this->cronRun();
  92. $this->cronRun();
  93. // The import_period setting of the feed configuration is 1800, there
  94. // shouldn't be any change to the database now.
  95. $equal = TRUE;
  96. $rows = db_query("SELECT id, last, scheduled FROM {job_schedule} WHERE last > :time", array(':time' => $time));
  97. foreach ($rows as $row) {
  98. $equal = $equal && ($row->last == $schedule[$row->id]->last);
  99. }
  100. $this->assertTrue($equal, 'Schedule did not change.');
  101. // Log back in and set refreshing to as often as possible.
  102. $this->drupalLogin($this->admin_user);
  103. $edit = array(
  104. 'import_period' => 0,
  105. );
  106. $this->drupalPost('admin/structure/feeds/syndication/settings', $edit, 'Save');
  107. $this->assertText('Periodic import: as often as possible');
  108. $this->drupalLogout();
  109. // Hit cron once, this should cause Feeds to reschedule all entries.
  110. $this->cronRun();
  111. $equal = FALSE;
  112. $rows = db_query("SELECT id, last, scheduled FROM {job_schedule} WHERE last > :time", array(':time' => $time));
  113. foreach ($rows as $row) {
  114. $equal = $equal && ($row->last == $schedule[$row->id]->last);
  115. $schedule[$row->id] = $row;
  116. }
  117. $this->assertFalse($equal, 'Every feed schedule time changed.');
  118. // Hit cron again, 4 times now, every item should change again.
  119. for ($i = 0; $i < 4; $i++) {
  120. $this->cronRun();
  121. }
  122. $equal = FALSE;
  123. $rows = db_query("SELECT id, last, scheduled FROM {job_schedule} WHERE last > :time", array(':time' => $time));
  124. foreach ($rows as $row) {
  125. $equal = $equal && ($row->last == $schedule[$row->id]->last);
  126. }
  127. $this->assertFalse($equal, 'Every feed schedule time changed.');
  128. // There should be 200 article nodes in the database.
  129. $count = db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article' AND status = 1")->fetchField();
  130. $this->assertEqual($count, 200, 'The total of 200 article nodes has not changed.');
  131. // Set expire settings, check rescheduling.
  132. $max_last = db_query("SELECT MAX(last) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period = 0")->fetchField();
  133. $min_last = db_query("SELECT MIN(last) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period = 0")->fetchField();
  134. $this->assertEqual(0, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_expire'")->fetchField());
  135. $this->drupalLogin($this->admin_user);
  136. $this->setSettings('syndication', 'FeedsNodeProcessor', array('expire' => 86400));
  137. $this->drupalLogout();
  138. sleep(1);
  139. $this->cronRun();
  140. // There should be 20 feeds_source_expire jobs now, and all last fields should be reset.
  141. $this->assertEqual(count($nids), db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_expire' AND last <> 0 AND scheduled = 0 AND period = 3600")->fetchField());
  142. $new_max_last = db_query("SELECT MAX(last) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period = 0")->fetchField();
  143. $new_min_last = db_query("SELECT MIN(last) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period = 0")->fetchField();
  144. $this->assertNotEqual($new_max_last, $max_last);
  145. $this->assertNotEqual($new_min_last, $min_last);
  146. $this->assertEqual($new_max_last, $new_min_last);
  147. $max_last = $new_max_last;
  148. $min_last = $new_min_last;
  149. // Set import settings, check rescheduling.
  150. $this->drupalLogin($this->admin_user);
  151. $this->setSettings('syndication', '', array('import_period' => 3600));
  152. $this->drupalLogout();
  153. sleep(1);
  154. $this->cronRun();
  155. $new_max_last = db_query("SELECT MAX(last) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period = 3600")->fetchField();
  156. $new_min_last = db_query("SELECT MIN(last) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period = 3600")->fetchField();
  157. $this->assertNotEqual($new_max_last, $max_last);
  158. $this->assertNotEqual($new_min_last, $min_last);
  159. $this->assertEqual($new_max_last, $new_min_last);
  160. $this->assertEqual(0, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND period <> 3600")->fetchField());
  161. $this->assertEqual(count($nids), db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_expire' AND period = 3600 AND last = :last", array(':last' => $new_min_last))->fetchField());
  162. // Delete source, delete importer, check schedule.
  163. $this->drupalLogin($this->admin_user);
  164. $nid = array_shift($nids);
  165. $this->drupalPost("node/$nid/delete", array(), t('Delete'));
  166. $this->assertEqual(0, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import' AND id = :nid", array(':nid' => $nid))->fetchField());
  167. $this->assertEqual(0, db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_expire' AND id = :nid", array(':nid' => $nid))->fetchField());
  168. $this->assertEqual(count($nids), db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import'")->fetchField());
  169. $this->assertEqual(count($nids), db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_expire'")->fetchField());
  170. $this->drupalPost('admin/structure/feeds/syndication/delete', array(), t('Delete'));
  171. $this->assertEqual(count($nids), db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_expire'")->fetchField());
  172. $this->assertEqual(count($nids), db_query("SELECT COUNT(*) FROM {job_schedule} WHERE type = 'syndication' AND name = 'feeds_source_import'")->fetchField());
  173. }
  174. /**
  175. * Test batching on cron.
  176. */
  177. function testBatching() {
  178. // Set up an importer.
  179. $this->createImporterConfiguration('Node import', 'node');
  180. // Set and configure plugins and mappings.
  181. $edit = array(
  182. 'content_type' => '',
  183. );
  184. $this->drupalPost('admin/structure/feeds/node/settings', $edit, 'Save');
  185. $this->setPlugin('node', 'FeedsFileFetcher');
  186. $this->setPlugin('node', 'FeedsCSVParser');
  187. $mappings = array(
  188. 0 => array(
  189. 'source' => 'title',
  190. 'target' => 'title',
  191. ),
  192. );
  193. $this->addMappings('node', $mappings);
  194. // Verify that there are 86 nodes total.
  195. $this->importFile('node', $this->absolutePath() . '/tests/feeds/many_nodes.csv');
  196. $this->assertText('Created 86 nodes');
  197. // Run batch twice with two different process limits.
  198. // 50 = FEEDS_PROCESS_LIMIT.
  199. foreach (array(10, 50) as $limit) {
  200. variable_set('feeds_process_limit', $limit);
  201. db_query("UPDATE {job_schedule} SET next = 0");
  202. $this->drupalPost('import/node/delete-items', array(), 'Delete');
  203. $node_count = db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article'")->fetchField();
  204. $this->assertEqual(0, $node_count);
  205. // Hit cron for importing, until we have all items.
  206. while ($node_count < 86) {
  207. $this->cronRun();
  208. $node_count = db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article'")->fetchField();
  209. }
  210. $this->assertEqual(86, db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article'")->fetchField(), 'Number of nodes is correct after batched importing via cron.');
  211. // Import should be rescheduled for 1800 seconds.
  212. $this->assertEqual(1800, db_query("SELECT period FROM {job_schedule} WHERE type = 'node' AND id = 0")->fetchField());
  213. }
  214. // Delete a couple of nodes, then hit cron again. They should not be replaced
  215. // as the minimum update time is 30 minutes.
  216. $nodes = db_query_range("SELECT nid FROM {node} WHERE type = 'article'", 0, 2);
  217. foreach ($nodes as $node) {
  218. $this->drupalPost("node/{$node->nid}/delete", array(), 'Delete');
  219. }
  220. $this->assertEqual(84, db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article'")->fetchField());
  221. $this->cronRun();
  222. $this->assertEqual(84, db_query("SELECT COUNT(*) FROM {node} WHERE type = 'article'")->fetchField());
  223. }
  224. }