Discovered in #2171683: Remove all Simpletest overrides and rely on native multi-site functionality instead

Problem

  • Drupal\views\Tests\Plugin\DisplayFeedTest passes tests, but the internal browser actually shows a fatal error in the web page output:

    Fatal error: Call to a member function hasPath() on a non-object in ViewListController::getDisplayPaths()

Details

  • DisplayBag may return NULL in ViewsListController::getDisplayPaths().
  • Not caused by a missing module dependency. The views_test module is enabled when ViewsListController iterates over the DisplayBag.
  • First assumed the failure would be caused by an outdated/malformed views test config file, but that wasn't the case.
  • Now, the actual assertions in the feed display test did actually pass. The test only happens to contain an initial straw drupalGet() to the basic edit page of the test view (without any comments or assertions), and only on that edit page, a fatal error is triggered.

  • Studying the code of DisplayBag and PluginBag, there are various conditions in which the Iterator can return NULL instead of a plugin instance. When manually iterating over a PluginBag, the loop has to take that possibility into account.

  • The foreach loop over DisplayBag in ViewListController::getDisplayPaths() did not care for that, so simply checking for whether the Iterator yielded NULL instead of a display appears to be the adequate fix.

  • This was revealed by #2171683: Remove all Simpletest overrides and rely on native multi-site functionality instead, since the Simpletest fatal error.log is set up much earlier with that, so fatal errors in new-style controllers are actually caught.

Comments

Status: Needs review » Needs work

The last submitted patch, drupal8.views-displaybag-fatal.0.patch, failed testing.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new875 bytes
new1.63 KB

Alright, tested + confirmed that this also happens in HEAD.

As mentioned in the issue summary, the fatal error is not caught, because the fatal error.log for tests is set up too late for new-style controllers.

Attaching two patches: Complete patch + regression test only.

sun’s picture

dawehner’s picture

We should at least write something to the watchdog if a display on the actual frontend does not exists,
as hiding this fact is a bad idea.

dawehner’s picture

Maybe we should also try to skip invalid plugins on the iterator.

damiankloip’s picture

StatusFileSize
new1.33 KB
new1.25 KB

First of all, good find!

Not caused by a missing module dependency.

It kind of is, the actual fatal is not coming from the 'test_display_feed' view, but from the 'content_recent' view in the test. The block module is not enabled, but node is is. And the content_recent view has configuration for a view display.

I think this needs to be fixed in the actual pluginBag class, otherwise you will need to check for this every time you iterate over some plugin bag class.

I think something like this. Not sure if this is best, as get() will get called again but checking anything in current() is too late, so valid() makes the most sense from that point of view. This is only during iteration too, we lose nothing on single get() calls.

EDIT: Oh, didn't realise Daniel just posted here too (just looked at comment number and posted patch). Seems he had a similar idea of where the fix should live.

The last submitted patch, 2: drupal8.views-displaybag-fatal.2.test-only.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 6: 2189453-6.patch, failed testing.

sun’s picture

It looks like the approach of the patch in #6 could work without too much pain, too — only two fatal errors across the core test suite.

Most likely, those two are caused by bogus test configuration or bogus test expectations.

Lastly, I think a code comment on the adjusted iterator line would help readers to understand why that is done. Also, not sure whether the parenthesis around the conditions are necessary?

sun’s picture

Assigned: sun » Unassigned
Priority: Major » Critical

Unless we go with the originally proposed patch, I have to unassign myself, as I'm not familiar with the code that you are touching :-)

Because this issue is seemingly blocking the parent issue, #2171683: Remove all Simpletest overrides and rely on native multi-site functionality instead, I'd love to see this getting fixed as soon as possible. — I wish I could be of more help... That said, according to our issue priority documentation, a fatal error means critical, so let me bump the priority accordingly.

damiankloip’s picture

Assigned: Unassigned » damiankloip

Ok, no worries :) let me fix the remaining tests.

damiankloip’s picture

Assigned: damiankloip » Unassigned
Status: Needs work » Needs review
StatusFileSize
new3.53 KB
new2.7 KB

OK, let's see how this gets on.

It was indeed a bogus test - The setupPluginBag method was creating a value map to return the plugin. However, because the setConfiguration method was changing the configuration data for that plugin, the plugin map did not match both parameters anymore, so returned NULL. I have switched this to use a returnCallback instead.

Parenthesis weren't necessary but I tend to favour that, as visually it is easier to follow the conditions. Anyway, meh - I've reverted that change :)

Status: Needs review » Needs work

The last submitted patch, 12: 2189453-12.patch, failed testing.

damiankloip’s picture

12: 2189453-12.patch queued for re-testing.

Seems like another random one (UserCancelTest).

dawehner’s picture

Status: Needs work » Reviewed & tested by the community

+1 for checking on this level.

webchick’s picture

Assigned: Unassigned » catch

Catch asked for this one to be split off, so assigning to him.

catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Component/Plugin/PluginBag.php
@@ -161,7 +161,11 @@ public function key() {
+    return $key !== NULL && $key !== FALSE && $this->get($key);

This needs a @todo to remove when #2080823: Create API to discover config entities' soft dependencies and use this to present a confirm form on module uninstall is fixed. Silently eating errors like this makes for horrible debugging. Otherwise patch looks OK.

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new3.62 KB
new650 bytes

@todo added.

catch’s picture

Status: Needs review » Reviewed & tested by the community
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

Status: Fixed » Closed (fixed)

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