ensure that sorting is stable

Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
This commit is contained in:
Arthur Schiwon 2017-10-11 17:25:21 +02:00
parent 8f0a9ae51f
commit 8722458d2a
No known key found for this signature in database
GPG Key ID: 7424F1874854DF23
4 changed files with 37 additions and 11 deletions

View File

@ -58,12 +58,23 @@ class CommentersSorter implements ISorter {
continue;
}
usort($byType, function ($a, $b) use ($commenters, $type) {
$r = $this->compare($a, $b, $commenters[$type]);
// at least on PHP 5.6 usort turned out to be not stable. So we add
// the current index to the value and compare it on a draw
$i = 0;
$workArray = array_map(function($element) use (&$i) {
return [$i++, $element];
}, $byType);
usort($workArray, function ($a, $b) use ($commenters, $type) {
$r = $this->compare($a[1], $b[1], $commenters[$type]);
if($r === 0) {
$r = $a[0] - $b[0];
}
return $r;
});
$s = '';
// and remove the index values again
$byType = array_column($workArray, 1);
}
}

View File

@ -59,7 +59,7 @@ class CommentersSorterTest extends TestCase {
$workArray = $data['input'];
$this->sorter->sort($workArray, ['itemType' => 'files', 'itemId' => '24']);
$this->assertSame($data['expected'], $workArray);
$this->assertEquals($data['expected'], $workArray);
}
public function sortDataProvider() {

View File

@ -61,9 +61,24 @@ class ShareRecipientSorter implements ISorter {
if(!isset($al[$type]) || !is_array($al[$type])) {
continue;
}
usort($byType, function ($a, $b) use ($al, $type) {
return $this->compare($a, $b, $al[$type]);
// at least on PHP 5.6 usort turned out to be not stable. So we add
// the current index to the value and compare it on a draw
$i = 0;
$workArray = array_map(function($element) use (&$i) {
return [$i++, $element];
}, $byType);
usort($workArray, function ($a, $b) use ($al, $type) {
$result = $this->compare($a[1], $b[1], $al[$type]);
if($result === 0) {
$result = $a[0] - $b[0];
}
return $result;
});
// and remove the index values again
$byType = array_column($workArray, 1);
}
}

View File

@ -74,7 +74,7 @@ class ShareRecipientSorterTest extends TestCase {
$workArray = $data['input'];
$this->sorter->sort($workArray, $data['context']);
$this->assertSame($data['expected'], $workArray);
$this->assertEquals($data['expected'], $workArray);
}
public function testSortNoNodes() {
@ -98,7 +98,7 @@ class ShareRecipientSorterTest extends TestCase {
public function sortDataProvider() {
return [[
[
#1 sort properly and otherwise keep existing order
#0 sort properly and otherwise keep existing order
'context' => ['itemType' => 'files', 'itemId' => 42],
'accessList' => ['users' => ['celia', 'darius', 'faruk', 'gail'], 'bots' => ['r2-d2']],
'input' => [
@ -135,7 +135,7 @@ class ShareRecipientSorterTest extends TestCase {
],
],
[
# 2 no recipients
#1 no recipients
'context' => ['itemType' => 'files', 'itemId' => 42],
'accessList' => ['users' => false],
'input' => [
@ -172,7 +172,7 @@ class ShareRecipientSorterTest extends TestCase {
],
],
[
#3 unsupported item type
#2 unsupported item type
'context' => ['itemType' => 'announcements', 'itemId' => 42],
'accessList' => null, // not needed
'input' => [
@ -209,7 +209,7 @@ class ShareRecipientSorterTest extends TestCase {
],
],
[
#4 no nothing
#3 no nothing
'context' => ['itemType' => 'files', 'itemId' => 42],
'accessList' => [],
'input' => [],