From 49d5287a3922e2613726e26f3aba58186d2ed97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20J=C3=A4ckle?= Date: Thu, 2 Jan 2025 11:47:32 +0100 Subject: [PATCH] #2072: add unit test for caching signal enrichment with pre-defined extra fields --- .../DittoCachingSignalEnrichmentFacade.java | 4 +- ...ractCachingSignalEnrichmentFacadeTest.java | 2 +- ...ittoCachingSignalEnrichmentFacadeTest.java | 76 ++++++++++++++++++- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/internal/models/signalenrichment/src/main/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacade.java b/internal/models/signalenrichment/src/main/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacade.java index 222b9bef00..198ce9142c 100644 --- a/internal/models/signalenrichment/src/main/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacade.java +++ b/internal/models/signalenrichment/src/main/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacade.java @@ -458,11 +458,11 @@ private CompletionStage doSmartUpdateCachedObject(final SignalEnrich } private static T getLast(final List list) { - return list.get(list.size() - 1); + return list.getLast(); } private static T getFirst(final List list) { - return list.get(0); + return list.getFirst(); } private CompletionStage handleNextExpectedThingEvents(final SignalEnrichmentCacheKey cacheKey, diff --git a/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/AbstractCachingSignalEnrichmentFacadeTest.java b/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/AbstractCachingSignalEnrichmentFacadeTest.java index 2d51c3cc96..f62a080dcc 100644 --- a/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/AbstractCachingSignalEnrichmentFacadeTest.java +++ b/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/AbstractCachingSignalEnrichmentFacadeTest.java @@ -50,7 +50,7 @@ */ abstract class AbstractCachingSignalEnrichmentFacadeTest extends AbstractSignalEnrichmentFacadeTest { - private static final String ISSUER_PREFIX = "test:"; + protected static final String ISSUER_PREFIX = "test:"; private static final String CACHE_CONFIG_KEY = "my-cache"; private static final String CACHE_CONFIG = CACHE_CONFIG_KEY + """ { diff --git a/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacadeTest.java b/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacadeTest.java index 8b54abe56e..abc5ed273b 100644 --- a/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacadeTest.java +++ b/internal/models/signalenrichment/src/test/java/org/eclipse/ditto/internal/models/signalenrichment/DittoCachingSignalEnrichmentFacadeTest.java @@ -12,9 +12,26 @@ */ package org.eclipse.ditto.internal.models.signalenrichment; +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.CompletionStage; + import org.apache.pekko.testkit.javadsl.TestKit; +import org.eclipse.ditto.base.model.auth.AuthorizationContext; +import org.eclipse.ditto.base.model.auth.AuthorizationSubject; +import org.eclipse.ditto.base.model.auth.DittoAuthorizationContextType; +import org.eclipse.ditto.base.model.entity.metadata.MetadataModelFactory; +import org.eclipse.ditto.base.model.headers.DittoHeaderDefinition; +import org.eclipse.ditto.base.model.headers.DittoHeaders; +import org.eclipse.ditto.base.model.signals.DittoTestSystem; import org.eclipse.ditto.internal.utils.cache.config.CacheConfig; +import org.eclipse.ditto.json.JsonFieldSelector; import org.eclipse.ditto.json.JsonObject; +import org.eclipse.ditto.json.JsonPointer; +import org.eclipse.ditto.json.JsonValue; +import org.eclipse.ditto.things.model.ThingId; +import org.eclipse.ditto.things.model.signals.events.AttributeModified; +import org.junit.Test; /** * Unit tests for {@link DittoCachingSignalEnrichmentFacade}. @@ -27,7 +44,37 @@ public final class DittoCachingSignalEnrichmentFacadeTest extends AbstractCachin "attributes": {"x": 5}, "features": {"y": {"properties": {"z": true}}}, "_metadata": {"attributes": {"x": {"type": "x attribute"}}} - }"""); + }""" + ); + + private static final JsonObject EXPECTED_THING_JSON_PRE_DEFINED_EXTRA = JsonObject.of(""" + { + "definition": "some:cool:definition", + "attributes": {"x": 5, "pre": {"bar": [1,2,3]}, "pre2": {"some": 41, "secret": true}} + }""" + ); + + private static final AttributeModified THING_EVENT_PRE_DEFINED_EXTRA_FIELDS = AttributeModified.of( + ThingId.generateRandom("org.eclipse.test"), + JsonPointer.of("x"), + JsonValue.of(42), + 4L, + Instant.EPOCH, + DittoHeaders.newBuilder() + .putHeader(DittoHeaderDefinition.PRE_DEFINED_EXTRA_FIELDS.getKey(), + "[\"/definition\",\"/attributes/pre\",\"/attributes/pre2\"]") + .putHeader(DittoHeaderDefinition.PRE_DEFINED_EXTRA_FIELDS_READ_GRANT_OBJECT.getKey(), + "{\"/definition\":[\"test:user\"],\"/attributes/pre\":[\"test:user\"]}") + .putHeader(DittoHeaderDefinition.PRE_DEFINED_EXTRA_FIELDS_OBJECT.getKey(), + "{\"definition\":\"some:cool:definition\",\"attributes\":{\"pre\":{\"bar\": [1,2,3]}}}") + .build(), + MetadataModelFactory.newMetadataBuilder() + .set("type", "x attribute") + .build()); + + private static final JsonFieldSelector SELECTOR_PRE_DEFINED_EXTRA_FIELDS = + JsonFieldSelector.newInstance("definition", "attributes/pre", "attributes/pre2"); + @Override protected CachingSignalEnrichmentFacade createCachingSignalEnrichmentFacade(final TestKit kit, @@ -44,5 +91,32 @@ protected JsonObject getExpectedThingJson() { return EXPECTED_THING_JSON; } + @Test + public void enrichedEventWithPreDefinedExtraFieldsDoesNotLeadToCacheLookup() { + DittoTestSystem.run(this, kit -> { + final SignalEnrichmentFacade underTest = + createSignalEnrichmentFacadeUnderTest(kit, Duration.ofSeconds(10L)); + final ThingId thingId = ThingId.generateRandom(); + final String userId = ISSUER_PREFIX + "user"; + final DittoHeaders headers = DittoHeaders.newBuilder() + .authorizationContext(AuthorizationContext.newInstance(DittoAuthorizationContextType.UNSPECIFIED, + AuthorizationSubject.newInstance(userId))) + .randomCorrelationId() + .build(); + final CompletionStage askResult = + underTest.retrievePartialThing(thingId, SELECTOR_PRE_DEFINED_EXTRA_FIELDS, headers, + THING_EVENT_PRE_DEFINED_EXTRA_FIELDS); + + // THEN: no cache lookup should be done + kit.expectNoMessage(Duration.ofSeconds(1)); + askResult.toCompletableFuture().join(); + // AND: the resulting thing JSON includes the with the updated value: + final JsonObject expectedThingJson = EXPECTED_THING_JSON_PRE_DEFINED_EXTRA.toBuilder() + .remove("attributes/x") // x was not asked for in extra fields + .remove("attributes/pre2") // we don't have the read grant for this field + .build(); + softly.assertThat(askResult).isCompletedWithValue(expectedThingJson); + }); + } }