Completed
Push — master ( 264630...c90943 )
by mw
230:08 queued 195:34
created

tests/phpunit/includes/SemanticDataTest.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SMW\Tests;
4
5
use SMW\DataValueFactory;
6
use SMW\DIProperty;
7
use SMW\DIWikiPage;
8
use SMW\Localizer;
9
use SMW\SemanticData;
10
use SMW\Subobject;
11
use SMWDITime as DITime;
12
use Title;
13
14
/**
15
 * @covers \SMW\SemanticData
16
 * @group semantic-mediawiki
17
 *
18
 * @license GNU GPL v2+
19
 * @since 1.9
20
 *
21
 * @author mwjames
22
 */
23
class SemanticDataTest extends \PHPUnit_Framework_TestCase {
24
25
	private $semanticDataValidator;
26
	private $dataValueFactory;
27
	private $testEnvironment;
28
29
	protected function setUp() {
30
		parent::setUp();
31
32
		$this->testEnvironment = new TestEnvironment();
33
34
		$store = $this->getMockBuilder( '\SMW\SQLStore\SQLStore' )
35
			->disableOriginalConstructor()
36
			->getMock();
37
38
		$store->expects( $this->any() )
39
			->method( 'getRedirectTarget' )
40
			->will( $this->returnArgument( 0 ) );
41
42
		$this->testEnvironment->registerObject( 'Store', $store );
43
44
		$this->semanticDataValidator = $this->testEnvironment->getUtilityFactory()->newValidatorFactory()->newSemanticDataValidator();
45
		$this->dataValueFactory = DataValueFactory::getInstance();
46
	}
47
48
	protected function tearDown() {
49
		$this->testEnvironment->tearDown();
50
	}
51
52
	public function testConstructor() {
53
54
		$instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
55
56
		$this->assertInstanceOf(
57
			'\SMW\SemanticData',
58
			$instance
59
		);
60
61
		$this->assertInstanceOf(
62
			'SMWSemanticData',
63
			$instance
64
		);
65
	}
66
67
	public function testGetPropertyValues() {
68
69
		$instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
70
71
		$this->assertInstanceOf(
72
			'SMW\DIWikiPage',
73
			$instance->getSubject()
74
		);
75
76
		$this->assertEmpty(
77
			$instance->getPropertyValues( new DIProperty( 'Foo', true ) )
78
		);
79
80
		$this->assertEmpty(
81
			$instance->getPropertyValues( new DIProperty( 'Foo' ) )
82
		);
83
	}
84
85
	public function testAddPropertyValue() {
86
87
		$instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
88
89
		$instance->addPropertyValue(
90
			'addPropertyValue',
91
			DIWikiPage::doUnserialize( 'Foo#0#' )
92
		);
93
94
		$key = Localizer::getInstance()->getNamespaceTextById( SMW_NS_PROPERTY ) . ':' . 'addPropertyValue';
95
96
		$expected = array(
97
			'propertyCount'  => 1,
98
			'propertyLabels' => array( $key ),
99
			'propertyValues' => array( 'Foo' )
100
		);
101
102
		$this->semanticDataValidator->assertThatPropertiesAreSet(
103
			$expected,
104
			$instance
105
		);
106
	}
107
108
	public function testGetHash() {
109
110
		$instance = new SemanticData( DIWikiPage::newFromText( __METHOD__ ) );
111
112
		$instance->addDataValue(
113
			DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' )
114
		);
115
116
		$subobject = $this->newSubobject( $instance->getSubject()->getTitle() );
117
118
		$instance->addPropertyObjectValue(
119
			$subobject->getProperty(),
120
			$subobject->getContainer()
121
		);
122
123
		$this->assertInternalType(
124
			'string',
125
			$instance->getHash()
126
		);
127
	}
128
129
	public function testPropertyOrderDoesNotInfluenceHash() {
130
131
		$instance = new SemanticData(
132
			new DIWikiPage( 'Foo', NS_MAIN )
133
		);
134
135
		$instance->addDataValue(
136
			$this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
137
		);
138
139
		$instance->addDataValue(
140
			$this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
141
		);
142
143
		$instanceToCheck = new SemanticData(
144
			new DIWikiPage( 'Foo', NS_MAIN )
145
		);
146
147
		$instanceToCheck->addDataValue(
148
			$this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
149
		);
150
151
		$instanceToCheck->addDataValue(
152
			$this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
153
		);
154
155
		$this->assertEquals(
156
			$instance->getHash(),
157
			$instanceToCheck->getHash()
158
		);
159
	}
160
161
	public function testSubSemanticPropertyOrderDoesNotInfluenceHash() {
162
163
		$subobject = new Subobject( Title::newFromText( 'Foo' ) );
164
		$subobject->setEmptyContainerForId( 'Foo' );
165
166
		$subobject->addDataValue(
167
			$this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
168
		);
169
170
		$subobject->addDataValue(
171
			$this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
172
		);
173
174
		$instance = new SemanticData(
175
			new DIWikiPage( 'Foo', NS_MAIN )
176
		);
177
178
		$instance->addSubobject(
179
			$subobject
180
		);
181
182
		$subobject = new Subobject( Title::newFromText( 'Foo' ) );
183
		$subobject->setEmptyContainerForId( 'Foo' );
184
185
		$subobject->addDataValue(
186
			$this->dataValueFactory->newDataValueByText( 'Bar', 'Foo' )
187
		);
188
189
		$subobject->addDataValue(
190
			$this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
191
		);
192
193
		$instanceToCheck = new SemanticData(
194
			new DIWikiPage( 'Foo', NS_MAIN )
195
		);
196
197
		$instanceToCheck->addSubobject(
198
			$subobject
199
		);
200
201
		$this->assertEquals(
202
			$instance->getHash(),
203
			$instanceToCheck->getHash()
204
		);
205
	}
206
207
	public function testThatChangingDataDoesEnforceDifferentHash() {
208
209
		$instance = new SemanticData(
210
			new DIWikiPage( 'Foo', NS_MAIN )
211
		);
212
213
		$firstHash = $instance->getHash();
214
215
		$instance->addDataValue(
216
			$this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
217
		);
218
219
		$secondHash = $instance->getHash();
220
221
		$this->assertNotEquals(
222
			$firstHash,
223
			$secondHash
224
		);
225
226
		$subobject = new Subobject( Title::newFromText( 'Foo' ) );
227
		$subobject->setEmptyContainerForId( 'Foo' );
228
229
		$subobject->addDataValue(
230
			$this->dataValueFactory->newDataValueByText( 'Foo', 'Bar' )
231
		);
232
233
		$instance->addSubSemanticData(
234
			$subobject->getSemanticData()
235
		);
236
237
		$thirdHash = $instance->getHash();
238
239
		$this->assertNotEquals(
240
			$secondHash,
241
			$thirdHash
242
		);
243
244
		// Remove the data added in the third step and expect
245
		// the hash from the second
246
		$instance->removeSubSemanticData(
247
			$subobject->getSemanticData()
248
		);
249
250
		$this->assertEquals(
251
			$secondHash,
252
			$instance->getHash()
253
		);
254
	}
255
256
	public function testGetSubSemanticData() {
257
258
		$title = Title::newFromText( __METHOD__ );
259
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
260
261
		// Adds only a subobject reference to the container
262
		$subobject = $this->newSubobject( $title );
263
264
		$instance->addPropertyObjectValue(
265
			$subobject->getProperty(),
266
			$subobject->getSemanticData()->getSubject()
267
		);
268
269
		$this->assertNotInstanceOf(
270
			'SMWContainerSemanticData',
271
			$instance->getSubSemanticData()
272
		);
273
274
		// Adds a complete container
275
		$instance->addPropertyObjectValue(
276
			$subobject->getProperty(),
277
			$subobject->getContainer()
278
		);
279
280
		foreach ( $instance->getSubSemanticData() as $subSemanticData ) {
281
282
			$this->assertInstanceOf(
283
				'SMWContainerSemanticData',
284
				$subSemanticData
285
			);
286
		}
287
	}
288
289
	public function testAddAndRemoveSubSemanticData() {
290
291
		$title = Title::newFromText( __METHOD__ );
292
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
293
294
		// Adds only a subobject reference to the container
295
		$subobject = $this->newSubobject( $title );
296
297
		$instance->addSubobject( $subobject );
298
299
		$this->assertInternalType(
300
			'array',
301
			$instance->getSubSemanticData()
302
		);
303
304
		foreach ( $instance->getSubSemanticData() as $subSemanticData ) {
305
306
			$this->assertInstanceOf(
307
				'SMWContainerSemanticData',
308
				$subSemanticData
309
			);
310
311
			$this->assertEquals(
312
				$subSemanticData,
313
				$subobject->getSemanticData()
314
			);
315
		}
316
317
		$instance->removeSubSemanticData( $subobject->getSemanticData() );
318
319
		$this->assertNotInstanceOf(
320
			'SMWContainerSemanticData',
321
			$instance->getSubSemanticData()
322
		);
323
	}
324
325
	public function testAddSubSemanticDataWithOutSubobjectNameThrowsException() {
326
327
		$instance = new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) ) );
328
329
		$this->setExpectedException( 'MWException' );
330
331
		$instance->addSubSemanticData(
332
			new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( 'addSubSemanticData' ) ) )
333
		);
334
	}
335
336
	public function testDifferentSubSemanticDataSubjectThrowsException() {
337
338
		$instance = new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) ) );
339
340
		$this->setExpectedException( 'MWException' );
341
		$instance->addSubobject( $this->newSubobject( Title::newFromText( 'addSubSemanticData' ) ) );
342
	}
343
344
	public function testImportDataFromForDifferentSubjectThrowsException() {
345
346
		$instance = new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) ) );
347
348
		$this->setExpectedException( 'MWException' );
349
350
		$instance->importDataFrom(
351
			new SemanticData( DIWikiPage::newFromTitle( Title::newFromText( 'importDataFrom' ) ) )
352
		);
353
	}
354
355
	public function testHasAndFindSubSemanticData() {
356
357
		$title = Title::newFromText( __METHOD__ );
358
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
359
360
		$subobject = $this->newSubobject( $title );
361
		$subobjectName = $subobject->getSemanticData()->getSubject()->getSubobjectName();
362
363
		$this->assertFalse(	$instance->hasSubSemanticData() );
364
		$this->assertEmpty(	$instance->findSubSemanticData( $subobjectName ));
365
366
		// Adds only a subobject reference to the container
367
		$instance->addPropertyObjectValue(
368
			$subobject->getProperty(),
369
			$subobject->getSemanticData()->getSubject()
370
		);
371
372
		$this->assertFalse( $instance->hasSubSemanticData( $subobjectName ) );
373
		$this->assertEmpty( $instance->findSubSemanticData( $subobjectName ) );
374
375
		$instance->addSubSemanticData( $subobject->getSemanticData() );
376
377
		$this->assertTrue( $instance->hasSubSemanticData( $subobjectName ) );
378
		$this->assertNotEmpty($instance->findSubSemanticData( $subobjectName ) );
379
380
		$this->assertInstanceOf(
381
			'SMWContainerSemanticData',
382
			$instance->findSubSemanticData( $subobjectName )
383
		);
384
	}
385
386
	public function testSubSemanticDataForNonStringSubobjectName() {
387
388
		$instance = new SemanticData(
389
			DIWikiPage::newFromTitle( Title::newFromText( __METHOD__ ) )
390
		);
391
392
		$this->assertFalse(
393
			$instance->hasSubSemanticData( new \stdClass )
394
		);
395
396
		$this->assertEmpty(
397
			$instance->findSubSemanticData( new \stdClass )
398
		);
399
	}
400
401
	public function testSetLastModified() {
402
403
		$instance = new SemanticData(
404
			new DIWikiPage( 'Foo', NS_MAIN )
405
		);
406
407
		$instance->setLastModified( 1001 );
408
409
		$this->assertEquals(
410
			1001,
411
			$instance->getLastModified()
412
		);
413
	}
414
415
	public function testGetLastModifiedForEmptyModificationDate() {
416
417
		$instance = new SemanticData(
418
			new DIWikiPage( 'Foo', NS_MAIN )
419
		);
420
421
		$this->assertNull(
422
			$instance->getLastModified()
423
		);
424
	}
425
426
	public function testGetLastModifiedFromModificationDate() {
427
428
		$instance = new SemanticData(
429
			new DIWikiPage( 'Foo', NS_MAIN )
430
		);
431
432
		$instance->addPropertyObjectValue(
433
			new DIProperty( '_MDAT' ),
434
			DITime::newFromTimestamp( 1272508903 )
0 ignored issues
show
It seems like \SMWDITime::newFromTimestamp(1272508903) targeting SMWDITime::newFromTimestamp() can also be of type false; however, SMW\SemanticData::addPropertyObjectValue() does only seem to accept object<SMWDataItem>, did you maybe forget to handle an error condition?
Loading history...
435
		);
436
437
		$this->assertEquals(
438
			1272508903,
439
			$instance->getLastModified()
440
		);
441
	}
442
443
	public function testVisibility() {
444
445
		$title = Title::newFromText( __METHOD__ );
446
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
447
448
		$instance->addDataValue(
449
			DataValueFactory::getInstance()->newDataValueByText( 'Has fooQuex', 'Bar' )
450
		);
451
452
		$this->assertTrue(
453
			$instance->hasVisibleProperties()
454
		);
455
456
		$instance->addSubobject(
457
			$this->newSubobject( $title )
458
		);
459
460
		$this->assertTrue(
461
			$instance->hasVisibleSpecialProperties()
462
		);
463
	}
464
465
	/**
466
	 * @dataProvider removePropertyObjectProvider
467
	 */
468
	public function testRemovePropertyObjectValue( $title, $property, $dataItem ) {
469
470
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
471
472
		$instance->addPropertyObjectValue( $property, $dataItem );
473
		$this->assertFalse( $instance->isEmpty() );
474
475
		$instance->removePropertyObjectValue( $property, $dataItem );
476
		$this->assertTrue( $instance->isEmpty() );
477
	}
478
479
	public function testClear() {
480
481
		$title = Title::newFromText( __METHOD__ );
482
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
483
484
		$instance->addPropertyObjectValue(
485
			new DIProperty( '_MDAT' ),
486
			DITime::newFromTimestamp( 1272508903 )
0 ignored issues
show
It seems like \SMWDITime::newFromTimestamp(1272508903) targeting SMWDITime::newFromTimestamp() can also be of type false; however, SMW\SemanticData::addPropertyObjectValue() does only seem to accept object<SMWDataItem>, did you maybe forget to handle an error condition?
Loading history...
487
		);
488
489
		$this->assertFalse( $instance->isEmpty() );
490
491
		$instance->clear();
492
		$this->assertTrue( $instance->isEmpty() );
493
	}
494
495
	/**
496
	 * @dataProvider dataValueDataProvider
497
	 */
498
	public function testAddDataValues( $dataValues, $expected ) {
499
500
		$title = Title::newFromText( __METHOD__ );
501
		$instance = new SemanticData( DIWikiPage::newFromTitle( $title ) );
502
503
		foreach ( $dataValues as $dataValue ) {
504
			$instance->addDataValue( $dataValue );
505
		}
506
507
		if ( $expected['error'] > 0 ) {
508
			return $this->assertCount( $expected['error'], $instance->getErrors() );
509
		}
510
511
		$this->semanticDataValidator->assertThatPropertiesAreSet(
512
			$expected,
513
			$instance
514
		);
515
	}
516
517
	/**
518
	 * @return array
519
	 */
520
	public function removePropertyObjectProvider() {
521
522
		$provider = array();
523
524
		$title = Title::newFromText( __METHOD__ );
525
		$subobject = $this->newSubobject( $title, __METHOD__, '999' );
526
527
		// #0
528
		$provider[] = array(
529
			$title,
530
			new DIProperty( '_MDAT'),
531
			DITime::newFromTimestamp( 1272508903 )
532
		);
533
534
		// #1
535
		$provider[] = array(
536
			$title,
537
			$subobject->getProperty(),
538
			$subobject->getContainer()
539
		);
540
541
		return $provider;
542
	}
543
544
	/**
545
	 * @return array
546
	 */
547
	public function dataValueDataProvider() {
548
549
		$provider = array();
550
551
		// #0 Single DataValue is added
552
		$provider[] = array(
553
			array(
554
				DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
555
			),
556
			array(
557
				'error'         => 0,
558
				'propertyCount' => 1,
559
				'propertyLabels' => 'Foo',
560
				'propertyValues' => 'Bar'
561
			)
562
		);
563
564
		// #1 Equal Datavalues will only result in one added object
565
		$provider[] = array(
566
			array(
567
				DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
568
				DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
569
			),
570
			array(
571
				'error'         => 0,
572
				'propertyCount' => 1,
573
				'propertyLabels' => 'Foo',
574
				'propertyValues' => 'Bar'
575
			)
576
		);
577
578
		// #2 Two different DataValue objects
579
		$provider[] = array(
580
			array(
581
				DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
582
				DataValueFactory::getInstance()->newDataValueByText( 'Lila', 'Lula' ),
583
			),
584
			array(
585
				'error'         => 0,
586
				'propertyCount' => 2,
587
				'propertyLabels' => array( 'Foo', 'Lila' ),
588
				'propertyValues' => array( 'Bar', 'Lula' )
589
			)
590
		);
591
592
		// #3 Error (Inverse)
593
		$provider[] = array(
594
			array(
595
				DataValueFactory::getInstance()->newDataValueByText( '-Foo', 'Bar' ),
596
			),
597
			array(
598
				'error'         => 1,
599
				'propertyCount' => 0,
600
			)
601
		);
602
603
		// #4 One valid DataValue + an error object
604
		$provider[] = array(
605
			array(
606
				DataValueFactory::getInstance()->newDataValueByText( 'Foo', 'Bar' ),
607
				DataValueFactory::getInstance()->newDataValueByText( '-Foo', 'bar' ),
608
			),
609
			array(
610
				'error'         => 1,
611
				'propertyCount' => 1,
612
				'propertyLabels' => array( 'Foo' ),
613
				'propertyValues' => array( 'Bar' )
614
			)
615
		);
616
617
618
		// #5 Error (Predefined)
619
		$provider[] = array(
620
			array(
621
				DataValueFactory::getInstance()->newDataValueByText( '_Foo', 'Bar' ),
622
			),
623
			array(
624
				'error'         => 1,
625
				'propertyCount' => 0,
626
			)
627
		);
628
629
		// #6 Error (Known predefined property)
630
		$provider[] = array(
631
			array(
632
				DataValueFactory::getInstance()->newDataValueByText( 'Modification date', 'Bar' ),
633
			),
634
			array(
635
				'error'         => 1,
636
				'propertyCount' => 0,
637
			)
638
		);
639
640
		return $provider;
641
	}
642
643
	private function newSubobject( Title $title, $property = 'Quuy', $value = 'Xeer' ) {
644
645
		$subobject = new Subobject( $title );
646
		$subobject->setEmptyContainerForId( 'Foo' );
647
648
		$subobject->addDataValue(
649
			DataValueFactory::getInstance()->newDataValueByText( $property, $value )
650
		);
651
652
		return $subobject;
653
	}
654
655
}
656