19db21a6ff04c068ea4ef8294eb47551f1bbfa54
[yaffs-website] / web / core / modules / migrate / tests / src / Unit / MigrateTestCase.php
1 <?php
2
3 namespace Drupal\Tests\migrate\Unit;
4
5 use Drupal\Core\Database\Driver\sqlite\Connection;
6 use Drupal\Core\DependencyInjection\ContainerBuilder;
7 use Drupal\migrate\Plugin\MigrationInterface;
8 use Drupal\Tests\UnitTestCase;
9
10 /**
11  * Provides setup and helper methods for Migrate module tests.
12  */
13 abstract class MigrateTestCase extends UnitTestCase {
14
15   /**
16    * An array of migration configuration values.
17    *
18    * @var array
19    */
20   protected $migrationConfiguration = [];
21
22   /**
23    * The migration ID map.
24    *
25    * @var \Drupal\migrate\Plugin\MigrateIdMapInterface|\PHPUnit_Framework_MockObject_MockObject
26    */
27   protected $idMap;
28
29   /**
30    * Local store for mocking setStatus()/getStatus().
31    *
32    * @var \Drupal\migrate\Plugin\MigrationInterface::STATUS_*
33    */
34   protected $migrationStatus = MigrationInterface::STATUS_IDLE;
35
36   /**
37    * Retrieves a mocked migration.
38    *
39    * @return \Drupal\migrate\Plugin\MigrationInterface|\PHPUnit_Framework_MockObject_MockObject
40    *   The mocked migration.
41    */
42   protected function getMigration() {
43     $this->migrationConfiguration += ['migrationClass' => 'Drupal\migrate\Plugin\Migration'];
44     $this->idMap = $this->getMock('Drupal\migrate\Plugin\MigrateIdMapInterface');
45
46     $this->idMap
47       ->method('getQualifiedMapTableName')
48       ->willReturn('test_map');
49
50     $migration = $this->getMockBuilder($this->migrationConfiguration['migrationClass'])
51       ->disableOriginalConstructor()
52       ->getMock();
53
54     $migration->method('checkRequirements')
55       ->willReturn(TRUE);
56
57     $migration->method('getIdMap')
58       ->willReturn($this->idMap);
59
60     // We need the state to be toggled throughout the test so we store the value
61     // on the test class and use a return callback.
62     $migration->expects($this->any())
63       ->method('getStatus')
64       ->willReturnCallback(function() {
65         return $this->migrationStatus;
66       });
67     $migration->expects($this->any())
68       ->method('setStatus')
69       ->willReturnCallback(function($status) {
70         $this->migrationStatus = $status;
71       });
72
73     $migration->method('getMigrationDependencies')
74       ->willReturn([
75         'required' => [],
76         'optional' => [],
77       ]);
78
79     $configuration = &$this->migrationConfiguration;
80
81     $migration->method('getHighWaterProperty')
82       ->willReturnCallback(function () use ($configuration) {
83         return isset($configuration['high_water_property']) ? $configuration['high_water_property'] : '';
84       });
85
86     $migration->method('set')
87       ->willReturnCallback(function ($argument, $value) use (&$configuration) {
88         $configuration[$argument] = $value;
89       });
90
91     $migration->method('id')
92       ->willReturn($configuration['id']);
93
94     return $migration;
95   }
96
97   /**
98    * Gets an SQLite database connection object for use in tests.
99    *
100    * @param array $database_contents
101    *   The database contents faked as an array. Each key is a table name, each
102    *   value is a list of table rows, an associative array of field => value.
103    * @param array $connection_options
104    *   (optional) Options for the database connection. Defaults to an empty
105    *   array.
106    *
107    * @return \Drupal\Core\Database\Driver\sqlite\Connection
108    *   The database connection.
109    */
110   protected function getDatabase(array $database_contents, $connection_options = []) {
111     if (extension_loaded('pdo_sqlite')) {
112       $connection_options['database'] = ':memory:';
113       $pdo = Connection::open($connection_options);
114       $connection = new Connection($pdo, $connection_options);
115     }
116     else {
117       $this->markTestSkipped('The pdo_sqlite extension is not available.');
118     }
119
120     // Initialize the DIC with a fake module handler for alterable queries.
121     $container = new ContainerBuilder();
122     $container->set('module_handler', $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'));
123     \Drupal::setContainer($container);
124
125     // Create the tables and load them up with data, skipping empty ones.
126     foreach (array_filter($database_contents) as $table => $rows) {
127       $pilot_row = reset($rows);
128       $connection->schema()->createTable($table, $this->createSchemaFromRow($pilot_row));
129
130       $insert = $connection->insert($table)->fields(array_keys($pilot_row));
131       array_walk($rows, [$insert, 'values']);
132       $insert->execute();
133     }
134
135     return $connection;
136   }
137
138   /**
139    * Generates a table schema from a row.
140    *
141    * @param array $row
142    *   The reference row on which to base the schema.
143    *
144    * @return array
145    *   The Schema API-ready table schema.
146    */
147   protected function createSchemaFromRow(array $row) {
148     // SQLite uses loose ("affinity") typing, so it is OK for every column to be
149     // a text field.
150     $fields = array_map(function() { return ['type' => 'text']; }, $row);
151     return ['fields' => $fields];
152   }
153
154   /**
155    * Tests a query.
156    *
157    * @param array|\Traversable $iter
158    *   The countable. foreach-able actual results if a query is being run.
159    * @param array $expected_results
160    *   An array of expected results.
161    */
162   public function queryResultTest($iter, $expected_results) {
163     $this->assertSame(count($expected_results), count($iter), 'Number of results match');
164     $count = 0;
165     foreach ($iter as $data_row) {
166       $expected_row = $expected_results[$count];
167       $count++;
168       foreach ($expected_row as $key => $expected_value) {
169         $this->retrievalAssertHelper($expected_value, $this->getValue($data_row, $key), sprintf('Value matches for key "%s"', $key));
170       }
171     }
172     $this->assertSame(count($expected_results), $count);
173   }
174
175   /**
176    * Gets the value on a row for a given key.
177    *
178    * @param array $row
179    *   The row information.
180    * @param string $key
181    *   The key identifier.
182    *
183    * @return mixed
184    *   The value on a row for a given key.
185    */
186   protected function getValue($row, $key) {
187     return $row[$key];
188   }
189
190   /**
191    * Asserts tested values during test retrieval.
192    *
193    * @param mixed $expected_value
194    *   The incoming expected value to test.
195    * @param mixed $actual_value
196    *   The incoming value itself.
197    * @param string $message
198    *   The tested result as a formatted string.
199    */
200   protected function retrievalAssertHelper($expected_value, $actual_value, $message) {
201     if (is_array($expected_value)) {
202       // If the expected and actual values are empty, no need to array compare.
203       if (empty($expected_value && $actual_value)) {
204         return;
205       }
206       $this->assertArrayEquals($expected_value, $actual_value, $message);
207     }
208     else {
209       $this->assertSame((string) $expected_value, (string) $actual_value, $message);
210     }
211   }
212
213 }