Completed
Push — master ( dbb54e...c0d95f )
by mw
643:42 queued 609:28
created

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

Severity

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