Passed
Push — master ( 750c68...36913a )
by
unknown
02:38
created

getTestSubjectInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Wikibase\TermStore\MediaWiki\Tests\Integration\PackagePrivate\Util;
4
5
use PHPUnit\Framework\TestCase;
6
use Wikibase\TermStore\MediaWiki\PackagePrivate\Util\ReplicaMasterAwareRecordIdsAcquirer;
7
use Wikimedia\Rdbms\IDatabase;
8
use Wikimedia\Rdbms\DatabaseSqlite;
9
10
class ReplicaMasterAwareRecordIdsAcquirerTest extends TestCase {
11
12
	const TABLE_DDL_FILE_PATH = __DIR__ . '/ReplicaMasterAwareRecordIdsAcquirerTest_tableDDL.sql';
13
	const TABLE_NAME = 'replica_master_aware_record_ids_acquirer_test';
14
	const ID_COLUMN = 'id';
15
16
	/**
17
	 * @var IDatabase $dbMaster
18
	 */
19
	private $dbMaster;
20
21
	/**
22
	 * @var IDatabase $dbReplica
23
	 */
24
	private $dbReplica;
25
26
	public function setUp() {
27
		$this->dbMaster = DatabaseSqlite::newStandaloneInstance( ':memory:' );
28
		$this->dbMaster->sourceFile( self::TABLE_DDL_FILE_PATH );
29
30
		$this->dbReplica = DatabaseSqlite::newStandaloneInstance( ':memory:' );
31
		$this->dbReplica->sourceFile( self::TABLE_DDL_FILE_PATH );
32
	}
33
34
	public function testWhenAllRecordsExistInReplica() {
35
		$records = $this->getTestRecords();
36
37
		$this->dbReplica->insert(
38
			self::TABLE_NAME,
39
			$records
40
		);
41
		$this->assertSameRecordsInDb( $records, $this->dbReplica );
42
43
		$idsAcquirer = $this->getTestSubjectInstance();
44
		$acquiredRecordsWithIds = $idsAcquirer->acquireIds( $records );
45
46
		$this->assertNoRecordsInDb( $records, $this->dbMaster );
47
		$this->assertSameRecordsInDb( $acquiredRecordsWithIds, $this->dbReplica );
48
	}
49
50
	public function testWhenAllRecordsExistInMaster() {
51
		$records = $this->getTestRecords();
52
53
		$this->dbMaster->insert(
54
			self::TABLE_NAME,
55
			$records
56
		);
57
		$this->assertSameRecordsInDb( $records, $this->dbMaster );
58
59
		$idsAcquirer = $this->getTestSubjectInstance();
60
		$acquiredRecordsWithIds = $idsAcquirer->acquireIds( $records );
61
62
		$this->assertNoRecordsInDb( $records, $this->dbReplica );
63
		$this->assertSameRecordsInDb( $acquiredRecordsWithIds, $this->dbMaster );
64
	}
65
66
	public function testWhenAllRecordsDoNotExistInReplicaOrMaster() {
67
		$records = $this->getTestRecords();
68
69
		$idsAcquirer = $this->getTestSubjectInstance();
70
		$acquiredRecordsWithIds = $idsAcquirer->acquireIds( $records );
71
72
		$this->assertNoRecordsInDb( $records, $this->dbReplica );
73
		$this->assertSameRecordsInDb( $acquiredRecordsWithIds, $this->dbMaster );
74
	}
75
76
	public function testWhenSomeRecordsDoNotExistInReplicaButExistInMaster() {
77
		$records = $this->getTestRecords();
78
79
		$recordsInReplica = [ $records[0], $records[1] ];
80
		$recordsInMaster = [ $records[2] ];
81
82
		$this->dbReplica->insert(
83
			self::TABLE_NAME,
84
			$recordsInReplica
85
		);
86
		$this->assertSameRecordsInDb( $recordsInReplica, $this->dbReplica );
87
88
		$this->dbMaster->insert(
89
			self::TABLE_NAME,
90
			$recordsInMaster
91
		);
92
		$this->assertSameRecordsInDb( $recordsInMaster, $this->dbMaster );
93
94
		$idsAcquirer = $this->getTestSubjectInstance();
95
		$acquiredRecordsWithIds = $idsAcquirer->acquireIds( $records );
96
97
		$this->assertSame(
98
			count( $acquiredRecordsWithIds ),
99
			count( $records )
100
		);
101
		$this->assertSameRecordsInDb( [ $records[3] ], $this->dbMaster );
102
		$this->assertNoRecordsInDb( $recordsInReplica, $this->dbMaster );
103
		$this->assertNoRecordsInDb( $recordsInMaster, $this->dbReplica );
104
	}
105
106
	private function assertNoRecordsInDb( array $records, IDatabase $db ) {
107
		$recordsInDbCount = $db->selectRowCount(
108
			self::TABLE_NAME,
109
			'*',
110
			$this->recordsToSelectConditions( $records, $db )
111
		);
112
113
		$this->assertSame( 0, $recordsInDbCount );
114
	}
115
116
	private function assertSameRecordsInDb( array $records, IDatabase $db ) {
117
		$recordsInDbCount = $db->selectRowCount(
118
			self::TABLE_NAME,
119
			'*',
120
			$this->recordsToSelectConditions( $records, $db )
121
		);
122
123
		$this->assertCount( $recordsInDbCount, $records );
124
	}
125
126
	private function recordsToSelectConditions( array $records, IDatabase $db ) {
127
		$conditionsPairs = [];
0 ignored issues
show
Unused Code introduced by
$conditionsPairs 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...
128
		foreach ( $records as $record ) {
129
			$conditionPairs[] = $db->makeList( $record, IDatabase::LIST_AND );
0 ignored issues
show
Coding Style Comprehensibility introduced by
$conditionPairs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $conditionPairs = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
130
		}
131
132
		return $db->makeList( $conditionPairs, IDatabase::LIST_OR );
0 ignored issues
show
Bug introduced by
The variable $conditionPairs does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
133
	}
134
135
	private function getTestSubjectInstance() {
136
		return new ReplicaMasterAwareRecordIdsAcquirer(
137
			$this->dbMaster,
138
			$this->dbReplica,
139
			self::TABLE_NAME,
140
			self::ID_COLUMN
141
		);
142
	}
143
144
	private function getTestRecords() {
145
		return [
146
			[ 'column_value' => 'valueA1', 'column_id' => '1' ],
147
			[ 'column_value' => 'valueA2', 'column_id' => '2' ],
148
			[ 'column_value' => 'valueA3', 'column_id' => '3' ],
149
			[ 'column_value' => 'valueA4', 'column_id' => '4' ]
150
		];
151
	}
152
}
153
154