Merge pull request #23573 from colemanw/searchKitBetterDefaults
[civicrm-core.git] / tests / phpunit / CRM / Upgrade / SnapshotTest.php
1 <?php
2
3 /**
4 * Class CRM_Upgrade_SnapshotTest
5 * @group headless
6 */
7 class CRM_Upgrade_SnapshotTest extends CiviUnitTestCase {
8
9 protected function setUp(): void {
10 parent::setUp();
11 CRM_Upgrade_Snapshot::$pageSize = 10;
12 CRM_Upgrade_Snapshot::$cleanupAfter = 4;
13 }
14
15 public function testTableNames_good() {
16 $this->assertEquals('snap_civicrm_v5_45_stuff', CRM_Upgrade_Snapshot::createTableName('civicrm', '5.45', 'stuff'));
17 $this->assertEquals('snap_civicrm_v5_50_stuffy_things', CRM_Upgrade_Snapshot::createTableName('civicrm', '5.50', 'stuffy_things'));
18 $this->assertEquals('snap_oauth_client_v12_34_ext_things', CRM_Upgrade_Snapshot::createTableName('oauth_client', '12.34', 'ext_things'));
19 $this->assertEquals('snap_oauth_client_v0_1234_ext_things', CRM_Upgrade_Snapshot::createTableName('oauth_client', '0.1234', 'ext_things'));
20 }
21
22 public function testTableNames_bad() {
23 try {
24 CRM_Upgrade_Snapshot::createTableName('civicrm', '5.45', 'ab&cd');
25 $this->fail('Accepted invalid name');
26 }
27 catch (CRM_Core_Exception $e) {
28 $this->assertRegExp('/Malformed snapshot name/', $e->getMessage());
29 }
30 try {
31 CRM_Upgrade_Snapshot::createTableName('civicrm', '5.45', 'loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmod');
32 $this->fail('Accepted excessive name');
33 }
34 catch (CRM_Core_Exception $e) {
35 $this->assertRegExp('/Snapshot name is too long/', $e->getMessage());
36 }
37 }
38
39 /**
40 * This example creates a snapshot based on particular sliver of data (ie
41 * the "display_name" and "sort_name" for "Individual" records). It ensures that:
42 *
43 * 1. Some columns are copied - while other columns are not (based on `select()`).
44 * 2. Some rows are copied - while other rows are not (based on `where()`).
45 * 3. Multiple pages of data are copied.
46 */
47 public function testContent(): void {
48 for ($i = 0; $i < 15; $i++) {
49 $this->individualCreate([], $i);
50 $this->organizationCreate([], $i);
51 }
52
53 $this->runAll(CRM_Upgrade_Snapshot::createTasks('civicrm', '5.45', 'names', CRM_Utils_SQL_Select::from('civicrm_contact')
54 ->select('id, display_name, sort_name, modified_date')
55 ->where('contact_type = "Individual"')
56 ));
57 $this->assertTrue(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_45_names'));
58 $this->assertSameSchema('civicrm_contact.display_name', 'snap_civicrm_v5_45_names.display_name');
59 $this->assertSameSchema('civicrm_contact.sort_name', 'snap_civicrm_v5_45_names.sort_name');
60 $this->assertSameSchema('civicrm_contact.modified_date', 'snap_civicrm_v5_45_names.modified_date');
61 $this->assertTrue(CRM_Core_BAO_SchemaHandler::checkIfFieldExists('civicrm_contact', 'legal_name'));
62 $this->assertFalse(CRM_Core_BAO_SchemaHandler::checkIfFieldExists('snap_civicrm_v5_45_names', 'legal_name'));
63
64 $liveContacts = CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_contact');
65 $liveIndividuals = CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM civicrm_contact WHERE contact_type = "Individual"');
66 $snapCount = CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM snap_civicrm_v5_45_names');
67 $this->assertEquals($liveIndividuals, $snapCount, 'The snapshot should have as many records as live table.');
68 $this->assertTrue($liveContacts > $liveIndividuals);
69 $this->assertGreaterThan(CRM_Upgrade_Snapshot::$pageSize, $snapCount, "There should be more than 1 page of data in the snapshot. Found $snapCount records.");
70
71 CRM_Core_DAO::executeQuery('DROP TABLE snap_civicrm_v5_45_names');
72 }
73
74 /**
75 * This example creates multiple snapshots (attributed to different versions, v5.45 and v5.50),
76 * and it ensures that they can be cleaned-up by future upgrades (eg v5.52 and v5.58).
77 */
78 public function testBasicLifecycle(): void {
79 for ($i = 0; $i < 15; $i++) {
80 $this->individualCreate([], $i);
81 $this->organizationCreate([], $i);
82 }
83 $this->eventCreate([]);
84 $this->eventCreate([]);
85
86 $this->runAll(CRM_Upgrade_Snapshot::createTasks('civicrm', '5.45', 'names', CRM_Utils_SQL_Select::from('civicrm_contact')
87 ->select('id, display_name, sort_name')
88 ->where('contact_type = "Individual"')
89 ));
90 $this->assertTrue(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_45_names'));
91 $this->assertSameSchema('civicrm_contact.display_name', 'snap_civicrm_v5_45_names.display_name');
92 $this->assertGreaterThan(1, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM snap_civicrm_v5_45_names'));
93
94 $this->runAll(CRM_Upgrade_Snapshot::createTasks('civicrm', '5.50', 'dates', CRM_Utils_SQL_Select::from('civicrm_event')
95 ->select('id, start_date, end_date, registration_start_date, registration_end_date')
96 ));
97 $this->assertTrue(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_50_dates'));
98 $this->assertSameSchema('civicrm_event.start_date', 'snap_civicrm_v5_50_dates.start_date');
99 $this->assertGreaterThan(1, CRM_Core_DAO::singleValueQuery('SELECT count(*) FROM snap_civicrm_v5_50_dates'));
100
101 CRM_Upgrade_Snapshot::cleanupTask(NULL, 'civicrm', '5.52', 6);
102 $this->assertFalse(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_45_names'));
103 $this->assertTrue(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_50_dates'));
104
105 CRM_Upgrade_Snapshot::cleanupTask(NULL, 'civicrm', '5.58', 6);
106 $this->assertFalse(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_45_names'));
107 $this->assertFalse(CRM_Core_DAO::checkTableExists('snap_civicrm_v5_50_dates'));
108 }
109
110 /**
111 * Assert that two columns have the same schema.
112 *
113 * @param string $expectField
114 * ex: "table_1.column_1"
115 * @param string $actualField
116 * ex: "table_2.column_2"
117 */
118 protected function assertSameSchema(string $expectField, string $actualField): void {
119 [$expectTable, $expectColumn] = explode('.', $expectField);
120 [$actualTable, $actualColumn] = explode('.', $actualField);
121
122 $expectDao = CRM_Core_DAO::executeQuery("SHOW COLUMNS FROM {$expectTable} LIKE %1", [
123 1 => [$expectColumn, 'String'],
124 ]);
125 $expectDao->fetch();
126
127 $actualDao = CRM_Core_DAO::executeQuery("SHOW COLUMNS FROM {$actualTable} LIKE %1", [
128 1 => [$actualColumn, 'String'],
129 ]);
130 $actualDao->fetch();
131
132 foreach (['Type', 'Null'] as $fieldProp) {
133 $this->assertEquals($expectDao->{$fieldProp}, $actualDao->{$fieldProp}, "The fields $expectField and $actualField should have the same schema.");
134 }
135 }
136
137 protected function runAll(iterable $tasks): void {
138 $queue = Civi::queue('snaptest', ['type' => 'Memory']);
139 foreach ($tasks as $task) {
140 $queue->createItem($task);
141 }
142 $r = new CRM_Queue_Runner([
143 'queue' => $queue,
144 'errorMode' => CRM_Queue_Runner::ERROR_ABORT,
145 ]);
146 $r->runAll();
147 }
148
149 }