Problem/Motivation
While working on #2737719: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method, I ported the "send invalid UUID and see what happens" test coverage from \Drupal\rest\Tests\CreateTest::assertCreateEntityInvalidSerialized()
. See #2737719-85: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method.
This is what is sent:
{…, uuid: '<INVALID-UUID>', … }
This works great! But CreateTest
was only testing the json
format, not the hal_json
format… and I want test coverage to be comprehensive, so I applied it to hal_json
too. And upon doing so, I noticed this was sadly completely broken.
You'd get error responses like this:
Drupal\Tests\hal\Functional\EntityResource\Comment\CommentHalJsonAnonTest::testPost
Exception: Warning: Invalid argument supplied for foreach()
Drupal\hal\Normalizer\FieldNormalizer->denormalize()() (Line: 68)
/var/www/html/core/lib/Drupal/Core/Test/HttpClientMiddleware/TestHttpClientMiddleware.php:44
/var/www/html/vendor/guzzlehttp/promises/src/FulfilledPromise.php:39
/var/www/html/vendor/guzzlehttp/promises/src/TaskQueue.php:61
/var/www/html/vendor/guzzlehttp/promises/src/Promise.php:246
/var/www/html/vendor/guzzlehttp/promises/src/Promise.php:223
/var/www/html/vendor/guzzlehttp/promises/src/Promise.php:266
/var/www/html/vendor/guzzlehttp/promises/src/Promise.php:225
/var/www/html/vendor/guzzlehttp/promises/src/Promise.php:62
/var/www/html/vendor/guzzlehttp/guzzle/src/Client.php:129
/var/www/html/core/modules/rest/tests/src/Functional/ResourceTestBase.php:254
/var/www/html/core/modules/rest/tests/src/Functional/EntityResource/EntityResourceTestBase.php:429
That's of course not remotely helpful.
Turns out the reason is that HAL's \Drupal\hal\Normalizer\FieldNormalizer::denormalize()
is incapable of handling "abbreviated" field structures like the one mentioned above. It demands this:
{…, uuid: [{value: '<INVALID-UUID>'}], … }
Proposed resolution
Either:
- Match
\Drupal\hal\Normalizer\FieldNormalizer::denormalize()
's behavior - Better error output.
Remaining tasks
TBD
User interface changes
None.
API changes
TBD, hopefully none.
Data model changes
TBD, hopefully none.
Comment | File | Size | Author |
---|---|---|---|
#11 | interdiff-2820743-11.txt | 1.99 KB | damiankloip |
#11 | 2820743-11.patch | 5.21 KB | damiankloip |
#6 | 2820743-6.patch | 4.95 KB | damiankloip |
Comments
Comment #2
vdanielpop CreditAttribution: vdanielpop at PitechPlus commentedComment #3
vdanielpop CreditAttribution: vdanielpop at PitechPlus commentedComment #4
dawehnerI think throwing some better error message would be the preferred solution. We should tell people as early as possible when something of their passed input is wrong.
Comment #5
damiankloip CreditAttribution: damiankloip at Acquia commentedSo we could just check that the value that's about to be passed to the denormalization for the field item is an array or not. It should then be handled correctly. Alternatively, we could check for this scalar value and just handle that instead like:
Even just casting the value to an array would actually get handled correct too, I think...
I made a change to the hal FieldNormalizer as we have the same problem in both. I then realised we have the same code in both - if the hal FieldNormalizer extends the serialization FieldNormalizer we can share this method.
Comment #6
damiankloip CreditAttribution: damiankloip at Acquia commentedComment #8
damiankloip CreditAttribution: damiankloip at Acquia commentedSince we did #2827218: Denormalization on field items is never called: add FieldNormalizer + FieldItemNormalizer with denormalize() methods this is also a problem for serialization module too. Hence the direction of the patch. Re-titling accordingly.
Comment #9
damiankloip CreditAttribution: damiankloip at Acquia commentedComment #10
dawehnerHere is just a quick review.
Can we use the field name in the exception message? This makes it a bit easier to debug later one day
Note: We use
$this->setExpectedException
nowComment #11
damiankloip CreditAttribution: damiankloip at Acquia commentedThanks Daniel! Seems like fair points you have there.
Comment #12
dawehnerWFM
Comment #14
catchCommitted/pushed to 8.3.x, thanks!
Comment #18
Wim LeersSmall follow-up because this overlooked one
@todo
: #2853296: Address remaining @todo in EntityResourceTestBase.Comment #19
kevin.dutra CreditAttribution: kevin.dutra at Workday, Inc. commentedJust wanted to share our unfortunate experience with regard to this change.
We're on the trailing end of upgrading from 8.2 to 8.4 and just discovered that our external integrations are broken as they are using JSON with abbreviated field structures. When the integrations started failing, I was able to trace it back to this issue. I'm surprised that a BC breaking change like this didn't end up with at least a change record.