Completed
Push — master ( fbddd8...ac075e )
by Sam
18:17 queued 10:25
created

testIndexesDontRerequestChanges()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

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