testAcquireTermIdsStoresTermsInDatabase()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 9.504
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\TermStore\MediaWiki\Tests\Unit\PackagePrivate;
4
5
use PHPUnit\Framework\TestCase;
6
use Wikibase\TermStore\MediaWiki\TermStoreSchemaUpdater;
7
use Wikibase\TermStore\MediaWiki\PackagePrivate\DatabaseTermIdsAcquirer;
8
use Wikibase\TermStore\MediaWiki\PackagePrivate\InMemoryTypeIdsStore;
9
use Wikibase\TermStore\MediaWiki\Tests\Util\FakeLoadBalancer;
10
use Wikimedia\Rdbms\IDatabase;
11
use Wikimedia\Rdbms\DatabaseSqlite;
12
use Wikimedia\Rdbms\ILoadBalancer;
13
14
class DatabaseTermIdsAcquirerTest extends TestCase {
15
16
	/**
17
	 * @var IDatabase $db
18
	 */
19
	private $db;
20
21
	/**
22
	 * @var ILoadBalancer
23
	 */
24
	private $loadBalancer;
25
26
	public function setUp() {
27
		$this->db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
28
		$this->db->sourceFile( TermStoreSchemaUpdater::getSqlFileAbsolutePath() );
29
		$this->loadBalancer = new FakeLoadBalancer( [
30
			'dbr' => $this->db,
31
		] );
32
	}
33
34
	public function testAcquireTermIdsReturnsArrayOfIdsForAllTerms() {
35
		$typeIdsAcquirer = new InMemoryTypeIdsStore();
36
37
		$dbTermIdsAcquirer = new DatabaseTermIdsAcquirer(
38
			$this->loadBalancer,
39
			$typeIdsAcquirer
40
		);
41
42
		$termsArray = [
43
			'label' => [
44
				'en' => 'same',
45
				'de' => 'same',
46
			],
47
			'description' => [ 'en' => 'same' ],
48
			'alias' => [
49
				'en' => [ 'same', 'same', 'another', 'yet another' ]
50
			]
51
		];
52
53
		$acquiredTermIds = $dbTermIdsAcquirer->acquireTermIds( $termsArray );
54
55
		$this->assertInternalType( 'array', $acquiredTermIds );
56
		$this->assertCount( 7, $acquiredTermIds );
57
	}
58
59
	public function testAcquireTermIdsStoresTermsInDatabase() {
60
		$typeIdsAcquirer = new InMemoryTypeIdsStore();
61
		$alreadyAcquiredTypeIds = $typeIdsAcquirer->acquireTypeIds(
62
			[ 'label', 'description', 'alias' ]
63
		);
64
65
		$dbTermIdsAcquirer = new DatabaseTermIdsAcquirer(
66
			$this->loadBalancer,
67
			$typeIdsAcquirer
68
		);
69
70
		$termsArray = [
71
			'label' => [
72
				'en' => 'same',
73
				'de' => 'same',
74
			],
75
			'description' => [ 'en' => 'same' ],
76
			'alias' => [
77
				'en' => [ 'same', 'same', 'another', 'yet another' ]
78
			]
79
		];
80
81
		$acquiredTermIds = $dbTermIdsAcquirer->acquireTermIds( $termsArray );
0 ignored issues
show
Unused Code introduced by
$acquiredTermIds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
82
83
		$this->assertTermsArrayExistInDb( $termsArray, $alreadyAcquiredTypeIds );
84
	}
85
86
	public function testAcquireTermIdsStoresOnlyUniqueTexts() {
87
		$typeIdsAcquirer = new InMemoryTypeIdsStore();
88
89
		$dbTermIdsAcquirer = new DatabaseTermIdsAcquirer(
90
			$this->loadBalancer,
91
			$typeIdsAcquirer
92
		);
93
94
		$termsArray = [
95
			'label' => [
96
				'en' => 'same',
97
				'de' => 'same',
98
			],
99
			'description' => [ 'en' => 'same' ],
100
			'alias' => [
101
				'en' => [ 'same', 'same', 'another', 'yet another' ]
102
			]
103
		];
104
105
		$acquiredTermIds = $dbTermIdsAcquirer->acquireTermIds( $termsArray );
0 ignored issues
show
Unused Code introduced by
$acquiredTermIds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
106
107
		$this->assertSame(
108
			3,
109
			$this->db->selectRowCount( 'wbt_text', '*' )
110
		);
111
	}
112
113
	public function testAcquireTermIdsStoresOnlyUniqueTextInLang() {
114
		$typeIdsAcquirer = new InMemoryTypeIdsStore();
115
116
		$dbTermIdsAcquirer = new DatabaseTermIdsAcquirer(
117
			$this->loadBalancer,
118
			$typeIdsAcquirer
119
		);
120
121
		$termsArray = [
122
			'label' => [
123
				'en' => 'same',
124
				'de' => 'same',
125
			],
126
			'description' => [ 'en' => 'same' ],
127
			'alias' => [
128
				'en' => [ 'same', 'same', 'another', 'yet another' ]
129
			]
130
		];
131
132
		$acquiredTermIds = $dbTermIdsAcquirer->acquireTermIds( $termsArray );
0 ignored issues
show
Unused Code introduced by
$acquiredTermIds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
133
134
		$this->assertSame(
135
			4,
136
			$this->db->selectRowCount( 'wbt_text_in_lang', '*' )
137
		);
138
	}
139
140
	public function testAcquireTermIdsStoresOnlyUniqueTermInLang() {
141
		$typeIdsAcquirer = new InMemoryTypeIdsStore();
142
143
		$dbTermIdsAcquirer = new DatabaseTermIdsAcquirer(
144
			$this->loadBalancer,
145
			$typeIdsAcquirer
146
		);
147
148
		$termsArray = [
149
			'label' => [
150
				'en' => 'same',
151
				'de' => 'same',
152
			],
153
			'description' => [ 'en' => 'same' ],
154
			'alias' => [
155
				'en' => [ 'same', 'same', 'another', 'yet another' ]
156
			]
157
		];
158
159
		$acquiredTermIds = $dbTermIdsAcquirer->acquireTermIds( $termsArray );
0 ignored issues
show
Unused Code introduced by
$acquiredTermIds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
160
161
		$this->assertSame(
162
			6,
163
			$this->db->selectRowCount( 'wbt_term_in_lang', '*' )
164
		);
165
	}
166
167
	public function testAcquireTermIdsReusesExistingTerms() {
168
		$termsArray = [
169
			'label' => [
170
				'en' => 'same',
171
				'de' => 'same',
172
			],
173
			'description' => [ 'en' => 'same' ],
174
			'alias' => [
175
				'en' => [ 'same', 'same', 'another', 'yet another' ]
176
			]
177
		];
178
179
		// We will populate DB with two terms that both have
180
		// text "same". One is of type "label" in language "en",
181
		// and the other is of type "alias" in language "en.
182
		//
183
		// TermIdsAcquirer should then reuse those terms for the given
184
		// termsArray above, meaning thoese pre-inserted terms will
185
		// appear (their ids) in the returned array from
186
		// TermIdsAcquirer::acquireTermIds( $termsArray )
187
		$typeIdsAcquirer = new InMemoryTypeIdsStore();
188
		$alreadyAcquiredTypeIds = $typeIdsAcquirer->acquireTypeIds(
189
			[ 'label', 'description', 'alias' ]
190
		);
191
192
		$this->db->insert( 'wbt_text', [ 'wbx_text' => 'same' ] );
193
		$sameTextId = $this->db->insertId();
194
195
		$this->db->insert(
196
			'wbt_text_in_lang',
197
			[ 'wbxl_text_id' => $sameTextId, 'wbxl_language' => 'en' ]
198
		);
199
		$enSameTextInLangId = $this->db->insertId();
200
201
		$this->db->insert(
202
			'wbt_term_in_lang',
203
			[ 'wbtl_text_in_lang_id' => $enSameTextInLangId,
204
			  'wbtl_type_id' => $alreadyAcquiredTypeIds['label'] ]
205
		);
206
		$labelEnSameTermInLangId = (string)$this->db->insertId();
207
208
		$this->db->insert(
209
			'wbt_term_in_lang',
210
			[ 'wbtl_text_in_lang_id' => $enSameTextInLangId,
211
			  'wbtl_type_id' => $alreadyAcquiredTypeIds['alias'] ]
212
		);
213
		$aliasEnSameTermInLangId = (string)$this->db->insertId();
214
215
		$dbTermIdsAcquirer = new DatabaseTermIdsAcquirer(
216
			$this->loadBalancer,
217
			$typeIdsAcquirer
218
		);
219
220
		$acquiredTermIds = $dbTermIdsAcquirer->acquireTermIds( $termsArray );
221
222
		$this->assertCount( 7, $acquiredTermIds );
223
224
		// We will assert that the returned ids of acquired terms contains
225
		// one occurence of the term id for en label "same" that already existed in db,
226
		// and two occurences of the term id for en alias "same" that already existed
227
		// in db.
228
		$this->assertCount(
229
			1,
230
			array_filter(
231
				$acquiredTermIds,
232
				function ( $id ) use ( $labelEnSameTermInLangId ) {
233
					return $id === $labelEnSameTermInLangId;
234
				}
235
			)
236
		);
237
		$this->assertCount(
238
			2,
239
			array_filter(
240
				$acquiredTermIds,
241
				function ( $id ) use ( $aliasEnSameTermInLangId ) {
242
					return $id === $aliasEnSameTermInLangId;
243
				}
244
			)
245
		);
246
	}
247
248
	private function assertTermsArrayExistInDb( $termsArray, $typeIds ) {
249
		foreach ( $termsArray as $type => $textsPerLang ) {
250
			foreach ( $textsPerLang as $lang => $texts ) {
251
				foreach ( (array)$texts as $text ) {
252
					$textId = $this->db->selectField(
253
						'wbt_text',
254
						'wbx_id',
255
						[ 'wbx_text' => $text ]
256
					);
257
258
					$this->assertNotEmpty(
259
						$textId,
260
						"Expected record for text '$text' is not in wbt_text"
261
					);
262
263
					$textInLangId = $this->db->selectField(
264
						'wbt_text_in_lang',
265
						'wbxl_id',
266
						[ 'wbxl_language' => $lang, 'wbxl_text_id' => $textId ]
267
					);
268
269
					$this->assertNotEmpty(
270
						$textInLangId,
271
						"Expected text '$text' in language '$lang' is not in wbt_text_in_lang"
272
					);
273
274
					$this->assertNotEmpty(
275
						$this->db->selectField(
276
							'wbt_term_in_lang',
277
							'wbtl_id',
278
							[ 'wbtl_type_id' => $typeIds[$type], 'wbtl_text_in_lang_id' => $textInLangId ]
279
						),
280
						"Expected $type '$text' in language '$lang' is not in wbt_term_in_lang"
281
					);
282
				}
283
			}
284
		}
285
	}
286
}
287