- π¨πSwitzerland bircher π¨πΏ
Re-titling the issue, because we don't necessarily need a new service it can be used with the typed config.
- Assigned to wim leers
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
This blocks Recipes; it prevents Recipes from reliably detecting whether config is the same or has changed: #3416287: ConfigConfigurator should be insensitive to key order when comparing active config to recipe config β .
- πΊπΈUnited States phenaproxima Massachusetts
To be clear, this is a stable blocker for the Recipes initiative. (In practical terms, it is a soft blocker.)
Initially in #3416287: ConfigConfigurator should be insensitive to key order when comparing active config to recipe config β , I identified a workaround that will suffice in the short term, and we can commit that to the Recipes repository for now; see #3416287-27: ConfigConfigurator should be insensitive to key order when comparing active config to recipe config β .
- Status changed to Needs work
12 months ago 2:18pm 29 January 2024 - πΊπΈUnited States phenaproxima Massachusetts
Adjusting the remaining tasks; let's start by bringing Wim's excellent work from #3416287: ConfigConfigurator should be insensitive to key order when comparing active config to recipe config β into a new MR on this issue.
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
It's gonna be tricky to exactly match the expectations of
SchemaConfigListenerTestTrait
, i.e. this rather odd output:catch (SchemaIncompleteException $e) { $this->assertEquals("Schema errors for config_test.types with the following errors: config_test.types:array variable type is integer but applied schema class is Drupal\Core\Config\Schema\Sequence, config_test.types:foo missing schema, 0 [foo] 'foo' is not a supported key.", $e->getMessage()); }
β¦ I'll need some more time tomorrow to figure out a way forward for that π€
That being said, 99% of tests are passing already π
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
Following up on #12: I had two choices:
- either not changing any of those assertions and hence being forced to save invalid config data first, because that is necessary for keeping
SchemaCheckTrait::checkValue
unchanged: it must be able to find flaws in stored config data - or changing the assertions and disallowing invalid config data to be saved β but this would be a disruptive BC break and a DX regression (not all info about invalid config data/missing schema at once, but one-by-one)
Did that in
f2c1390d2ecb0ffde75514e2e75012211d7b98cd
. - either not changing any of those assertions and hence being forced to save invalid config data first, because that is necessary for keeping
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
The 3 remaining failures are all in Views test coverage. They all relate to
ViewExecutable
wrappingView
(the "storage" config entity) and both of them manipulating (in these 3 tests and only these 3!) settings on-the-fly and expectingViewExecutable
,View
, display plugin, style plugin etc. all to remain in sync thanks to references to a private array π±See
\Drupal\views\DisplayPluginCollection::initializePlugin()
, which does// Retrieve and initialize the new display handler with data. $display = &$this->view->storage->getDisplay($display_id); β¦ $this->pluginInstances[$display_id]->initDisplay($this->view, $display);
there is a reference to the raw array in the config from within the
ViewExecutable
, this one is the culprit. Automatically resetting this is what I did in60631295ad052a64464d14b758cc3c2d99d55db1
and that fixes 1 of the 3 failures. - Issue was unassigned.
- Status changed to Needs review
12 months ago 5:13pm 30 January 2024 - π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
Whew. There are 2 functional Views tests that are doing very unholy things β the 1 (out of 3) that was fixed in #14 was the least bad one. See https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... + https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... for two examples of
View
andViewExecutable
being expected to magically remain in sync with in-memory-only overrides (i.e. modifications that are not part of theView
config entity, but manipulate runtime state). These two needed tiny tweaks to have more reasonable expectations of the connection betweenView
andViewExecutable
. - Status changed to Needs work
12 months ago 6:10pm 30 January 2024 - πΊπΈUnited States phenaproxima Massachusetts
This looks really good to me. I have a few minor things (mostly commenting-phrasing nits), as I usually do, but in general I understand this -- and when dealing with the typed config system, that's saying something -- and feel okay with it.
That said, I think the final sign-off here should belong to @bircher, who understands this more deeply than I and whose blessing would give me more confidence.
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
TIL
\Drupal\Core\TypedData\TypedDataManagerInterface::getCanonicalRepresentation()
was introduced in #2488568: Add a TypedDataManagerInterface and use it for typed parameters β β we should be able to use that instead, rather than expanding the API surface? π€ - Assigned to wim leers
- Issue was unassigned.
- Status changed to Needs review
12 months ago 3:45pm 31 January 2024 - π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
Whew, #17 was tricky, but I managed to do it β with a much simpler and less disruptive MR as the result! π€© I'm kinda proud of this one π€
https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... has
13 files changed, 103 insertions(+), 103 deletions(-)
as the diffstat and causes:β¦ same exact diffstat, but 3 fewer files touched, and no BC breaks/contrib disruption π₯³
And actually, looks like @bircher kinda predicted this years ago, because in the issue summary he stated .
- Assigned to wim leers
- Status changed to Needs work
12 months ago 6:49pm 1 February 2024 - π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
- The only failing test was
ConfigEntityAdapterTest::testValidate()
βConfigEntityAdapter
was added in #1818574: Support config entities in typed data EntityAdapter β . With very thin test coverage, because config entities were even less validatable back then than they are today. - In fixing that, it turns out that https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... was insufficient: that only caught the case of assigning the empty array
[]
to e.g.StringData
orBooleanData
. What's needed is to instead ensure that as soon as anyPrimitiveInterface
contains non-compliant data, the raw value is used in the canonical representation. - But then another test starts failing, because there is one test case in all of core that requires
FloatData
andIntegerData
which have the empty string''
assigned to be converted toNULL
π€ͺ Still, always better to minimize disruption, so matched that logic fromStorableConfigBase::castValue()
, by treating those as valid values instead (which exactly matches the intent) inPrimitiveTypeConstraintValidator
and allowing(Float|Integer)Data::getCastedValue()
to do whichever casting they please. π - Then a wide range of additional failures occurred β¦ because apparently a LOT of tests rely on
BooleanData
accepting'TRUE'
/'FALSE'
as an equivalent ofTRUE
/FALSE
, despite no explicit PHP logic existing to do that π³ β¦ nor test coverage π - I was able to work around that, but then followed a huge range of migration test failures (and some node type-related test failures). Lots of migrations are migrating nonsense β for example it's setting the
type: boolean
settings.alt_field
(for the "image" field type's settings) toTest alt
, which obviously is not a boolean π ) - β¦ to be continued tomorrow
The end result will be a more consistent (same representation during validation + saving β issue summary updated to reflect this) and understandable (no global knowledge in a protected method in a base class but each
TypedData
object has knowledge about itself) config system.It also makes it possible to deprecate weird things (see the boolean/float/integer special cases above) at some point in the future.
- The only failing test was
- π§πͺBelgium wim leers Ghent π§πͺπͺπΊ
- Found a similar problem with
Integer
andFloat
(https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co...) and another one forInteger
(https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co...) - That got us again to a single test failure. This time in
\Drupal\KernelTests\Core\TypedData\TypedDataTest::testGetAndSet()
. This bit:
// Boolean type. $typed_data = $this->createTypedData(['type' => 'boolean'], TRUE); $this->assertInstanceOf(BooleanInterface::class, $typed_data); β¦ $typed_data->setValue('invalid'); $this->assertEquals(1, $typed_data->validate()->count(), 'Validation detected invalid value.');
β¦ this is only passing because it's testing an alternate reality: there's LOTS of examples of string values being assigned to
type: boolean
and the configuration system silently ignoring this (not even reporting it viaSchemaCheckTrait
), because as soon as we disallow this (by reverting the boolean-related additions toPrimitiveTypeConstraintValidator
), lots of tests fail.Which means the only choice we have here is to change this expectation, so that it matches reality.
P.S.: in reading that method, it's clear there's many more known bugs in this area, for example it points to the following
@todo
: π DateTimeIso8601::setDateTime() vs. DateTimeItem::schema(): (at least) one of them is broken Needs work . - NOW IT IS GREEN AGAIN!
- While working on this, I discovered how closely related this issue is to
π
Config export key order is not predictable, use config schema to order keys for maps
Fixed
. This builds on top of what that did, and simplifies it; it makes the overall system more consistent. I bet it'd have been far more difficult if that had not happened! In principle, many of the test changes that happened there should no longer be necessary, as well as the various explicit pieces of sorting logic. To prove this, https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... reverted the changes that issue made to
ConfigEntityBase::preSave()
to sort dependencies correctly. - Nope, that didn't work out because
ConfigInstaller
does$entity->trustData()->save();
, which bypasses the call to::getCanonicalRepresentation()
. That's easily mitigated by making\Drupal\Core\Config\Config::save()
always use::getCanonicalRepresentation()
, even for trusted data: https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... - This unveiled another range of invalid config in tests, and hence tests of an alternate reality rather than the real world. π€ͺ
- So another range of trivial test expectation adjustments was needed: https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co..., https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co..., https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co....
- This also needed to invert a single assertion that
#2432791: Skip Config::save schema validation of config data for trusted data β
introduced β the test suite takes just as long as to run as in HEAD after the change to ALWAYS save with the canonical representation! Turns out that #2432791 especially made core faster thanks to not using config schema in
::toArray()
π That inverted expectation: https://git.drupalcode.org/project/drupal/-/merge_requests/6369/diffs?co... (which related to #2432791: Skip Config::save schema validation of config data for trusted data β ) - Down to zero kernel test failures again, now a handful of functional test failures. The first two were for
InstallerExistingConfigTestBase
β¦ turns out the multilingual fixture in there is wrong, it should've been updated in π Get rid of using 'views.settings':skip_cache in ViewsData Fixed but wasn't.
(To be continued. Down to 2 functional test failures. And a LOT more sanity.)
- Found a similar problem with