Problem/Motivation

A random fail has been detected in Drupal\comment\Tests\CommentFieldsTest::testCommentInstallAfterContentModule()

exception: [Warning] Line 177 of core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php:
uasort(): Array was modified by the user comparison functionuasort(Array, Array) (Line: 177)
Drupal\Core\Config\Entity\ConfigDependencyManager->getDependentEntities('config', 'field.field.node.article.comment') (Line: 256)
Drupal\Core\Config\ConfigManager->findConfigEntityDependents('config', Array, Object) (Line: 265)
Drupal\Core\Config\ConfigManager->findConfigEntityDependentsAsEntities('config', Array, Object) (Line: 298)
Drupal\Core\Config\ConfigManager->getConfigEntitiesToChangeOnDependencyRemoval('config', Array, ) (Line: 590)
Drupal\Core\Config\Entity\ConfigEntityBase::preDelete(Object, Array) (Line: 193)
Drupal\field\Entity\FieldConfig::preDelete(Object, Array) (Line: 357)
Drupal\Core\Entity\EntityStorageBase->delete(Array) (Line: 366)
Drupal\Core\Entity\Entity->delete() (Line: 596)
Drupal\Core\Config\Entity\ConfigEntityBase::preDelete(Object, Array) (Line: 406)
Drupal\field\Entity\FieldStorageConfig::preDelete(Object, Array) (Line: 357)
Drupal\Core\Entity\EntityStorageBase->delete(Array) (Line: 366)
Drupal\Core\Entity\Entity->delete() (Line: 192)
Drupal\comment\Tests\CommentFieldsTest->testCommentInstallAfterContentModule() (Line: 1057)
Drupal\simpletest\TestBase->run(Array) (Line: 723)
simpletest_script_run_one_test('199', 'Drupal\comment\Tests\CommentFieldsTest') (Line: 59)

Have no idea how this happens... I've run the test well over 100 times locally - no fail.

    $graph = $this->getGraph();
    uasort($graph, array($this, 'sortGraph'));
    return array_replace(array_intersect_key($graph, $dependencies), $dependencies);
  public function sortGraph(array $a, array $b) {
    $weight_cmp = SortArray::sortByKeyInt($a, $b, 'weight') * -1;

    if ($weight_cmp === 0) {
      return SortArray::sortByKeyString($a, $b, 'component');
    }
    return $weight_cmp;
  }

Proposed resolution

The graph is sorting on the component key added by the Graph object. It was assumed this was equivalent to the config object name - it is not. Therefore the patch adds the 'name' key and value to the graph so it can use it in the sort. Also it removes the array_reverse() since this doesn't have the expected impact on an already sorted list where the sort is on both weight and alphabet.

Remaining tasks

User interface changes

None

API changes

None - the ConfigDependencyManager public methods now actually return things in the expected order. Previously they correctly ordered things according to dependency (which is the vital thing) but sometimes messed up alphabetical sorting (which is a nice to have - just so things are repeatable and not dependent on PHP version).

Data model changes

None

CommentFileSizeAuthor
#20 2757427-20.patch9.1 KBalexpott
#20 16-20-interdiff.txt652 bytesalexpott
#16 2757427-16.patch8.46 KBalexpott
#16 15-16-interdiff.txt7.21 KBalexpott
#15 2757427-15.patch1.72 KBalexpott
#12 2757427-12.patch1.16 KBalexpott
#11 2757427-component-no-sort.patch1.67 KBalexpott
#10 2757427-component-copy.patch1.02 KBalexpott
#9 2757427-casts.patch1.65 KBalexpott
#8 2757427-copy.patch996 bytesalexpott
#7 2757427-reset.patch938 bytesalexpott
#6 drupal_2757427_6.patch2.62 KBXano
#5 2757427-copy_array.patch1.5 KBalexpott
#3 2757427-test-only.patch518 bytesalexpott
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alexpott created an issue. See original summary.

alexpott’s picture

Here's the first know fail... https://www.drupal.org/pift-ci-job/348229

alexpott’s picture

Xano’s picture

I also checked http://www.php.net/ChangeLog-5.php and no sort-related bugs have been fixed in PHP 5.6, except one with array_multisort() which is not what this issue is about.

In my experience this exception is also thrown when the sort callback triggers an error or throws an exception internally, without any actual array modifications taking place.

alexpott’s picture

Xano’s picture

Since I cannot seem to reproduce this locally and 3v4l.org says full graph output is too much to process, let's see what this gets us.

alexpott’s picture

alexpott’s picture

alexpott’s picture

alexpott’s picture

alexpott’s picture

alexpott’s picture

alexpott’s picture

Priority: Normal » Major

Given that this fail is not random on 8.1.x with PHP 5.6.6 making this a major bug.

alexpott’s picture

alexpott’s picture

So PHP7 means that we need to sort by name too - therefore we need add the real name to the graph so we can sort it.

alexpott’s picture

alexpott’s picture

Priority: Major » Critical

Discussed with @catch and we agreed this is critical because currently it is preventing a successful 8.1.x test on PHP 5.6. Therefore, arguably 8.1.x is in an unreleaseable state. The problem is the bugs fixed by #2754477: Unexpected config entity delete due to dependency calculations are considerable worse than this one - since this is just a warning and the test actually executes successfully.

alexpott’s picture

xjm’s picture

Yep this is critical per https://www.drupal.org/core/issue-priority#critical-bug:

Cause tests to fail in HEAD on the automated testing platform for any supported environment (including random failures), since this blocks all other work.

alexpott’s picture

The last submitted patch, 16: 2757427-16.patch, failed testing.

Fabianx’s picture

Status: Needs review » Reviewed & tested by the community
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyManager.php
@@ -199,7 +220,7 @@ public function sortAll() {
-   *   arrays that include a 'weight' and a 'component' key.
+   *   arrays that include a 'weight' and a 'name' key.

Does this need a change record or is this 100% internal?

--

Besides this, this looks great and is RTBC.

alexpott’s picture

Although the user sort function \Drupal\Core\Config\Entity\ConfigDependencyManager::sortGraph is public it really shouldn't be. I think we could file a follow-up issue to make it protected in 8.2.x.

alexpott’s picture

Issue summary: View changes
alexpott’s picture

+++ b/core/tests/Drupal/Tests/Core/Config/StorageComparerTest.php
@@ -196,8 +196,8 @@ public function testCreateChangelistDelete() {
     $expected = array(
-      'field.field.node.article.body',
       'views.view.test_view',
+      'field.field.node.article.body',
       'field.storage.node.body',
     );

This is not the expected alphabetical order because the StorageComparer has to reverse the dependencies so that fields are deleted before field storages. Basically it's array_reverse is doing what the one in ConfigDependencyManager::sortAll() was doing - but here it is necessary.

alexpott’s picture

Issue tags: +Triaged D8 critical

Discussed with @xjm, @catch, @cottser, and @effulgentsia we agreed that the persistent fail in PHP 5.6 testing is a critical.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Nice work tracking this down, nasty one.

Committed/pushed to 8.2.x and cherry-picked to 8.1.x. Thanks!

Xano’s picture

Status: Fixed » Reviewed & tested by the community

@catch: it looks like the push failed: https://www.drupal.org/node/3060/commits does not display any commits referencing this issue.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 20: 2757427-20.patch, failed testing.

catch’s picture

Status: Needs work » Fixed

It did push OK, just something up with drupal.org I think - you can see it on cgit.drupal.org:

http://cgit.drupalcode.org/drupal/commit/?id=3eb2def4460c25cff93940a6331...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.