Completed
Push — 3 ( eecbe0...aac828 )
by Loz
35s
created

testClassNameSpecGeneration()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 46
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 33
nc 1
nop 0
dl 0
loc 46
rs 8.9411
c 0
b 0
f 0
1
<?php
2
3
class DataObjectSchemaGenerationTest extends SapphireTest {
4
	protected $extraDataObjects = array(
5
		'DataObjectSchemaGenerationTest_DO',
6
		'DataObjectSchemaGenerationTest_IndexDO'
7
	);
8
9
	public function setUpOnce() {
10
11
		// enable fulltext option on this table
12
		Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'create_table_options',
13
			array(MySQLSchemaManager::ID => 'ENGINE=MyISAM'));
14
15
		parent::setUpOnce();
16
	}
17
18
	/**
19
	 * Check that once a schema has been generated, then it doesn't need any more updating
20
	 */
21
	public function testFieldsDontRerequestChanges() {
22
		$schema = DB::get_schema();
23
		$test = $this;
24
		DB::quiet();
25
26
		// Table will have been initially created by the $extraDataObjects setting
27
28
		// Verify that it doesn't need to be recreated
29
		$schema->schemaUpdate(function() use ($test, $schema) {
30
			$obj = new DataObjectSchemaGenerationTest_DO();
31
			$obj->requireTable();
32
			$needsUpdating = $schema->doesSchemaNeedUpdating();
33
			$schema->cancelSchemaUpdate();
34
			$test->assertFalse($needsUpdating);
35
		});
36
	}
37
38
	/**
39
	 * Check that updates to a class fields are reflected in the database
40
	 */
41
	public function testFieldsRequestChanges() {
42
		$schema = DB::get_schema();
43
		$test = $this;
44
		DB::quiet();
45
46
		// Table will have been initially created by the $extraDataObjects setting
47
48
		// Let's insert a new field here
49
		Config::inst()->update('DataObjectSchemaGenerationTest_DO', 'db', array(
50
			'SecretField' => 'Varchar(100)'
51
		));
52
53
		// Verify that the above extra field triggered a schema update
54
		$schema->schemaUpdate(function() use ($test, $schema) {
55
			$obj = new DataObjectSchemaGenerationTest_DO();
56
			$obj->requireTable();
57
			$needsUpdating = $schema->doesSchemaNeedUpdating();
58
			$schema->cancelSchemaUpdate();
59
			$test->assertTrue($needsUpdating);
60
		});
61
	}
62
63
	/**
64
	 * Check that indexes on a newly generated class do not subsequently request modification
65
	 */
66
	public function testIndexesDontRerequestChanges() {
67
		$schema = DB::get_schema();
68
		$test = $this;
69
		DB::quiet();
70
71
		// Table will have been initially created by the $extraDataObjects setting
72
73
		// Verify that it doesn't need to be recreated
74
		$schema->schemaUpdate(function() use ($test, $schema) {
75
			$obj = new DataObjectSchemaGenerationTest_IndexDO();
76
			$obj->requireTable();
77
			$needsUpdating = $schema->doesSchemaNeedUpdating();
78
			$schema->cancelSchemaUpdate();
79
			$test->assertFalse($needsUpdating);
80
		});
81
82
		// Test with alternate index format, although these indexes are the same
83
		Config::inst()->remove('DataObjectSchemaGenerationTest_IndexDO', 'indexes');
84
		Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes',
85
			Config::inst()->get('DataObjectSchemaGenerationTest_IndexDO', 'indexes_alt')
86
		);
87
88
		// Verify that it still doesn't need to be recreated
89
		$schema->schemaUpdate(function() use ($test, $schema) {
90
			$obj2 = new DataObjectSchemaGenerationTest_IndexDO();
91
			$obj2->requireTable();
92
			$needsUpdating = $schema->doesSchemaNeedUpdating();
93
			$schema->cancelSchemaUpdate();
94
			$test->assertFalse($needsUpdating);
95
		});
96
	}
97
98
	/**
99
	 * Check that updates to a dataobject's indexes are reflected in DDL
100
	 */
101
	public function testIndexesRerequestChanges() {
102
		$schema = DB::get_schema();
103
		$test = $this;
104
		DB::quiet();
105
106
		// Table will have been initially created by the $extraDataObjects setting
107
108
		// Update the SearchFields index here
109
		Config::inst()->update('DataObjectSchemaGenerationTest_IndexDO', 'indexes', array(
110
			'SearchFields' => array(
111
				'value' => 'Title'
112
			)
113
		));
114
115
		// Verify that the above index change triggered a schema update
116
		$schema->schemaUpdate(function() use ($test, $schema) {
117
			$obj = new DataObjectSchemaGenerationTest_IndexDO();
118
			$obj->requireTable();
119
			$needsUpdating = $schema->doesSchemaNeedUpdating();
120
			$schema->cancelSchemaUpdate();
121
			$test->assertTrue($needsUpdating);
122
		});
123
	}
124
125
	/**
126
	 * Tests the generation of the ClassName spec and ensure it's not unnecessarily influenced
127
	 * by the order of classnames of existing records
128
	 */
129
	public function testClassNameSpecGeneration() {
130
131
		// Test with blank entries
132
		DataObject::clear_classname_spec_cache();
133
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
134
		$this->assertEquals(
135
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
136
			$fields['ClassName']
137
		);
138
139
		// Test with instance of subclass
140
		$item1 = new DataObjectSchemaGenerationTest_IndexDO();
141
		$item1->write();
142
		DataObject::clear_classname_spec_cache();
143
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
144
		$this->assertEquals(
145
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
146
			$fields['ClassName']
147
		);
148
		$item1->delete();
149
150
		// Test with instance of main class
151
		$item2 = new DataObjectSchemaGenerationTest_DO();
152
		$item2->write();
153
		DataObject::clear_classname_spec_cache();
154
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
155
		$this->assertEquals(
156
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
157
			$fields['ClassName']
158
		);
159
		$item2->delete();
160
161
		// Test with instances of both classes
162
		$item1 = new DataObjectSchemaGenerationTest_IndexDO();
163
		$item1->write();
164
		$item2 = new DataObjectSchemaGenerationTest_DO();
165
		$item2->write();
166
		DataObject::clear_classname_spec_cache();
167
		$fields = DataObject::database_fields('DataObjectSchemaGenerationTest_DO');
168
		$this->assertEquals(
169
			"Enum('DataObjectSchemaGenerationTest_DO, DataObjectSchemaGenerationTest_IndexDO')",
170
			$fields['ClassName']
171
		);
172
		$item1->delete();
173
		$item2->delete();
174
	}
175
176
    public function testSortFieldBecomeIndexes()
177
    {
178
        $object = new DataObjectSchemaGenerationTest_Sorted();
179
        $indexes = $object->databaseIndexes();
180
        $this->assertArrayHasKey('Sort', $indexes);
181
        $this->assertTrue($indexes['Sort']);
182
183
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', 'Sort ASC');
184
        $indexes = $object->databaseIndexes();
185
        $this->assertArrayHasKey('Sort', $indexes);
186
        $this->assertTrue($indexes['Sort']);
187
188
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', 'Sort DESC');
189
        $indexes = $object->databaseIndexes();
190
        $this->assertArrayHasKey('Sort', $indexes);
191
        $this->assertTrue($indexes['Sort']);
192
193
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"Sort" DESC');
194
        $indexes = $object->databaseIndexes();
195
        $this->assertArrayHasKey('Sort', $indexes);
196
        $this->assertTrue($indexes['Sort']);
197
198
199
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"DataObjectSchemaGenerationTest_Sorted"."Sort" ASC');
200
        $indexes = $object->databaseIndexes();
201
        $this->assertArrayHasKey('Sort', $indexes);
202
        $this->assertTrue($indexes['Sort']);
203
204
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"Sort" DESC, "Title" ASC');
205
        $indexes = $object->databaseIndexes();
206
        $this->assertArrayHasKey('Sort', $indexes);
207
        $this->assertTrue($indexes['Sort']);
208
        $this->assertArrayHasKey('Title', $indexes);
209
        $this->assertTrue($indexes['Title']);
210
211
        // make sure that specific indexes aren't overwritten
212
        Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'indexes', array(
213
            'Sort' => 'unique',
214
        ));
215
216
        $indexes = $object->databaseIndexes();
217
        $this->assertArrayHasKey('Sort', $indexes);
218
        $this->assertEquals('unique', $indexes['Sort']);
219
	}
220
}
221
222
class DataObjectSchemaGenerationTest_DO extends DataObject implements TestOnly {
223
	private static $db = array(
224
		'Enum1' => 'Enum("A, B, C, D","")',
225
		'Enum2' => 'Enum("A, B, C, D","A")',
226
		'NumberField' => 'Decimal',
227
		'FloatingField' => 'Decimal(10,3,1.1)',
228
		'TextValue' => 'Varchar',
229
		'Date' => 'SS_Datetime',
230
		'MyNumber' => 'Int'
231
	);
232
}
233
234
235
class DataObjectSchemaGenerationTest_IndexDO extends DataObjectSchemaGenerationTest_DO implements TestOnly {
236
	private static $db = array(
237
		'Title' => 'Varchar(255)',
238
		'Content' => 'Text'
239
	);
240
241
	private static $indexes = array(
242
		'NameIndex' => 'unique ("Title")',
243
		'SearchFields' => array(
244
			'type' => 'fulltext',
245
			'name' => 'SearchFields',
246
			'value' => '"Title","Content"'
247
		)
248
	);
249
250
	/** @config */
251
	private static $indexes_alt = array(
252
		'NameIndex' => array(
253
			'type' => 'unique',
254
			'name' => 'NameIndex',
255
			'value' => '"Title"'
256
		),
257
		'SearchFields' => 'fulltext ("Title","Content")'
258
	);
259
}
260
261
class DataObjectSchemaGenerationTest_Sorted extends DataObject implements TestOnly {
262
    private static $db = array(
263
        'Title' => 'Varchar',
264
        'Sort' => 'Int',
265
    );
266
267
    private static $default_sort = "Sort";
268
}