Problem/Motivation

Follow-up to #3320792: Make build tests fail 1) more explicitly, 2) earlier when possible (failing StatusCheckEvent subscribers)

the status checks were not passing in \Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::createTestProject because core version had an error when didn't affect automatic_updates_extensions working but still show up

Steps to reproduce

Proposed resolution

Step core version for a correct update and call \Drupal\Tests\automatic_updates\Build\UpdateTestBase::assertStatusReportChecksSuccessful

Remaining tasks

User interface changes

API changes

Data model changes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

tedbow created an issue. See original summary.

tedbow’s picture

Title: [PP-1] Assert all status check pass at the beginning of \Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest » Assert all status check pass at the beginning of \Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest
Status: Postponed » Active

Unpostponing but also not tagging with sprint because it is contrib-only

wim leers’s picture

First pushed a test. That should fail like this:

1) Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::testApi
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-''
+'
+Drupal cannot be automatically updated from the installed version, 10.0.3-dev, because automatic updates from a dev version to any other version are not supported.'
wim leers’s picture

As expected:

10.1

Testing Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest
FF                                                                  2 / 2 (100%)

Time: 02:26.304, Memory: 18.00 MB

There were 2 failures:

1) Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::testApi
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-''
+'
+Drupal cannot be automatically updated from the installed version, 10.1.0-dev, because automatic updates from a dev version to any other version are not supported.'

2) Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::testUi
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-''
+'
+Drupal cannot be automatically updated from the installed version, 10.1.0-dev, because automatic updates from a dev version to any other version are not supported.'

https://www.drupal.org/pift-ci-job/2581810

9.5.2
Tests pass…
wim leers’s picture

Assigned: wim leers » Unassigned
Priority: Normal » Major
Issue tags: -contrib-only +maintainability, +core-mvp, +Needs title update

If I now extract/cherry-pick the solution from https://git.drupalcode.org/project/automatic_updates/-/merge_requests/65... (which finds its origin in https://git.drupalcode.org/project/automatic_updates/-/merge_requests/65...), we can see that … it does not pass tests.

Why did it work for #3331168: Limit trusted Composer plugins to a known list, allow user to add more? Probably because #3331168 did less strict assertions that assertStatusReportChecksSuccessful() (introduced by #3320792: Make build tests fail 1) more explicitly, 2) earlier when possible (failing StatusCheckEvent subscribers)) does.

So I started debugging … and found a mind-boggling rabbit hole. Put a breakpoint in update_get_available() and observe how many times it gets called. It's insane. There's call stacks like this:

update.module:324, update_get_available()
ProjectInfo.php:195, Drupal\package_manager\ProjectInfo->getAvailableProjects()
ProjectInfo.php:109, Drupal\package_manager\ProjectInfo->getInstallableReleases()
VersionPolicyValidator.php:236, Drupal\automatic_updates\Validator\VersionPolicyValidator->getAvailableReleases()
VersionPolicyValidator.php:119, Drupal\automatic_updates\Validator\VersionPolicyValidator->validateVersion()
ReleaseChooser.php:57, Drupal\automatic_updates\ReleaseChooser->Drupal\automatic_updates\{closure:/private/tmp/build_workspace_aaf970c10050f82aef4c7bae01d73e2e72cpBo/project/web/modules/contrib/automatic_updates/src/ReleaseChooser.php:56-58}()
ReleaseChooser.php:62, array_filter()
ReleaseChooser.php:62, Drupal\automatic_updates\ReleaseChooser->getInstallableReleases()
ReleaseChooser.php:84, Drupal\automatic_updates\ReleaseChooser->getMostRecentReleaseInMinor()
ReleaseChooser.php:121, Drupal\automatic_updates\ReleaseChooser->getLatestInInstalledMinor()
CronUpdater.php:135, Drupal\automatic_updates\CronUpdater->getTargetRelease()
VersionPolicyValidator.php:210, Drupal\automatic_updates\Validator\VersionPolicyValidator->getTargetVersion()
VersionPolicyValidator.php:149, Drupal\automatic_updates\Validator\VersionPolicyValidator->checkVersion()
ContainerAwareEventDispatcher.php:111, call_user_func:{/private/tmp/build_workspace_aaf970c10050f82aef4c7bae01d73e2e72cpBo/project/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php:111}()
ContainerAwareEventDispatcher.php:111, Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()
StatusCheckTrait.php:49, Drupal\automatic_updates\Validation\StatusChecker->runStatusCheck()
StatusChecker.php:105, Drupal\automatic_updates\Validation\StatusChecker->run()
automatic_updates.module:204, automatic_updates_modules_installed()
<snip>

Note how VersionPolicyValidator (which throws the error messages mentioned in #6 causing tests to fail on 10.x) ends up calling itself. And there's plenty more examples where that came from. The amount of unnecessary function calls is incredible. Now, of course, "premature optimization is the root of all evil", but at this point it interferes with debuggability and hence maintainability.

Another example:

ProjectInfo.php:149, Drupal\package_manager\ProjectInfo->getInstallableReleases()
VersionPolicyValidator.php:236, Drupal\automatic_updates\Validator\VersionPolicyValidator->getAvailableReleases()
VersionPolicyValidator.php:119, Drupal\automatic_updates\Validator\VersionPolicyValidator->validateVersion()
ReleaseChooser.php:57, Drupal\automatic_updates\ReleaseChooser->Drupal\automatic_updates\{closure:/private/tmp/build_workspace_aaf970c10050f82aef4c7bae01d73e2e72cpBo/project/web/modules/contrib/automatic_updates/src/ReleaseChooser.php:56-58}()
ReleaseChooser.php:62, array_filter()
ReleaseChooser.php:62, Drupal\automatic_updates\ReleaseChooser->getInstallableReleases()
ReleaseChooser.php:84, Drupal\automatic_updates\ReleaseChooser->getMostRecentReleaseInMinor()
ReleaseChooser.php:121, Drupal\automatic_updates\ReleaseChooser->getLatestInInstalledMinor()
CronUpdater.php:135, Drupal\automatic_updates\CronUpdater->getTargetRelease()
VersionPolicyValidator.php:210, Drupal\automatic_updates\Validator\VersionPolicyValidator->getTargetVersion()
VersionPolicyValidator.php:149, Drupal\automatic_updates\Validator\VersionPolicyValidator->checkVersion()
<snip>

ProjectInfo->getInstallableReleases() cannot return different results within the same PHP process by definition, yet it is recomputed countless times.

So I did not understand why CoreUpdateTest was not affected by this. It also has a assertStatusReportChecksSuccessful() and it passes tests, why?! What is it doing differently?

Turns out that both ModuleUpdateTest and CoreUpdateTest end up in \Drupal\automatic_updates\Validator\VersionPolicy\SupportedBranchInstalled::validate() looking at the real, actually requested Drupal core version info! 😬😳😱

Turns out that both CoreUpdateTest and ModuleUpdateTest use

    $this->setReleaseMetadata([
      'drupal' => __DIR__ . '/../../../../package_manager/tests/fixtures/release-history/drupal.9.8.1-security.xml',

… and setReleaseMetadata() writes this to settings.php: $config['update_test.settings']['xml_map'] = … → but the update_test module is never even installed! 😳😱

Reclassifying this as core-mvp because this severely undermined my trust in both of these tests

wim leers’s picture

Compared to #6, the extracted/cherry-picked commit results in:

10.1
As expected: the error message no longer mentions 10.1 but 9.8
Testing Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest
FF                                                                  2 / 2 (100%)

Time: 02:39.279, Memory: 18.00 MB

There were 2 failures:

1) Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::testApi
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-''
+'
+Updating from Drupal 9.8.1 is not allowed. The currently installed version of Drupal core, 9.8.1, is not in a supported minor version. Your site will not be automatically updated during cron until it is updated to a supported minor version.See the available updates page for available updates.'


2) Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::testUi
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-''
+'
+Updating from Drupal 9.8.1 is not allowed. The currently installed version of Drupal core, 9.8.1, is not in a supported minor version. Your site will not be automatically updated during cron until it is updated to a supported minor version.See the available updates page for available updates.'
9.5
… the exact same failures as on 10.1! Which is good: it means we're testing the same thing across all Drupal versions.
wim leers’s picture

Title: Assert all status check pass at the beginning of \Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest » CoreUpdateTest & ModuleUpdateTest do not correctly mock the update XML, ModuleUpdateTest does not correctly mock the core version
Assigned: Unassigned » tedbow
Status: Active » Needs review
Issue tags: -Needs title update

Finally found it!

wim leers’s picture

Simplified further.

wim leers’s picture

It looks like the edge case uncovered/investigated in #7 and #9 can also cause random failures: see #3325654-36: Improve the user experience of having your staged update deleted before it was applied, and specifically https://www.drupal.org/pift-ci-job/2583990, which failed like this:

Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest
fail: [Other] Line 0 of sites/default/files/simpletest/phpunit-1.xml:
PHPUnit Test failed to complete; Error: PHPUnit 9.5.26 by Sebastian Bergmann and contributors.

Testing Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest
.F                                                                  2 / 2 (100%)

Time: 03:13.888, Memory: 18.00 MB

There was 1 failure:

1) Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::testUi
Failed asserting that two strings are identical.
--- Expected
+++ Actual
@@ @@
-''
+'Error message There is a security update available for your version of Drupal. To ensure the security of your server, you should update immediately! See the available updates page for more information and to install your missing updates.'

/var/www/html/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:122
/var/www/html/vendor/phpunit/phpunit/src/Framework/Constraint/IsIdentical.php:79
/var/www/html/modules/contrib/automatic_updates/automatic_updates_extensions/tests/src/Build/ModuleUpdateTest.php:123
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:673
/var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:661
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:144
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:97

FAILURES!
Tests: 2, Assertions: 162, Failures: 1.
tedbow’s picture

Version: 8.x-2.x-dev » 3.0.x-dev
wim leers’s picture

Issue tags: +blocker
Related issues: +#3341708: Update requirements for 3.x

This now blocks #3341708 — see #3341708-4: Update requirements for 3.x.

wim leers’s picture

Rebased the old MR onto 3.0.x and opened a new MR 👍

wim leers’s picture

Assigned: tedbow » Unassigned
Issue tags: -blocker

Nope, doesn't block that anymore: #3341708-6: Update requirements for 3.x.

wim leers’s picture

Title: CoreUpdateTest & ModuleUpdateTest do not correctly mock the update XML, ModuleUpdateTest does not correctly mock the core version » [PP-because-focus-on-PM] CoreUpdateTest & ModuleUpdateTest do not correctly mock the update XML, ModuleUpdateTest does not correctly mock the core version

@tedbow and @tim.plunkett discussed the plan for getting Automatic Updates, Project Browser and Package Manager into core. We're likely going to aim to land Package Manager first. So postponing this issue for now, until the dust settles on that.

wim leers’s picture

Status: Needs review » Postponed
wim leers’s picture

Title: [PP-because-focus-on-PM] CoreUpdateTest & ModuleUpdateTest do not correctly mock the update XML, ModuleUpdateTest does not correctly mock the core version » CoreUpdateTest & ModuleUpdateTest do not correctly mock the update XML, ModuleUpdateTest does not correctly mock the core version
Assigned: Unassigned » yash.rode
Status: Postponed » Active
Issue tags: +blocker
Related issues: +#3358878: Test failing on 8.x-2.x on 10.0.x and 10.1.x
wim leers’s picture

Update on #20: confirmed at #3358878-7: Test failing on 8.x-2.x on 10.0.x and 10.1.x that the fix in this issue is essential.

wim leers’s picture

Assigned: yash.rode » wim leers

I'll push this across the finish line, there's too much tricky past history at play here.

wim leers’s picture

Assigned: wim leers » Unassigned

No time for this.

tedbow’s picture

Component: Code » Automatic Updates Extensions
Status: Active » Needs work
Issue tags: -core-mvp, -blocker

This issue was fixed in #3362746-7: fix 10.0.x phpstan errors. It was needed to get the tests were passing after I fixed the phpstan issues. I probably shouldn't have committed in that issue but I think the solution is correct. '

Currently \Drupal\Tests\automatic_updates\Build\CoreUpdateTest::createTestProject calls

$this->setUpstreamCoreVersion('9.8.1');
    $this->setReleaseMetadata([
      'drupal' => __DIR__ . '/../../../package_manager/tests/fixtures/release-history/drupal.9.8.1-security.xml',
    ]);

Then later calls

$this->assertStatusReportChecksSuccessful();

To affirm all the status checks are passing after we have created the project.

Since ModuleUpdateTest extends UpdateTestBase this also fixes it for this that test.

So I think the only thing left to do on this issue add an extra call to assertStatusReportChecksSuccessful() to ensure that after \Drupal\Tests\automatic_updates_extensions\Build\ModuleUpdateTest::createTestProject has altered the XML fixtures in use that all thats status checks pass and there are no other errors before we start the tests.

I am removing core-mvp because we just have a problem left in automatic_updates_extensions

tedbow’s picture

Title: CoreUpdateTest & ModuleUpdateTest do not correctly mock the update XML, ModuleUpdateTest does not correctly mock the core version » Assert no errors after creating the test project in ModuleUpdateTest
Status: Needs work » Needs review
tedbow’s picture

Assigned: Unassigned » phenaproxima
phenaproxima’s picture

Assigned: phenaproxima » Unassigned
Status: Needs review » Reviewed & tested by the community

I don't see a problem with this. More checks and safety in our tests, especially our build tests, is a good thing.

  • tedbow committed a469e081 on 3.0.x authored by Wim Leers
    Issue #3337049 by Wim Leers, tedbow: Assert no errors after creating the...
tedbow’s picture

Status: Reviewed & tested by the community » Fixed
wim leers’s picture

🥳 Weird to see code you wrote in January landing suddenly 😄

Status: Fixed » Closed (fixed)

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