diff options
36 files changed, 1290 insertions, 18 deletions
diff --git a/gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java b/gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java new file mode 100644 index 00000000..d48649ea --- /dev/null +++ b/gson/src/main/java/org/onap/policy/common/gson/JacksonHandler.java @@ -0,0 +1,50 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.gson; + +import com.google.gson.GsonBuilder; + +/** + * Provider used to serialize and deserialize policy objects via gson using jackson + * default behaviors and annotations. + */ +public class JacksonHandler extends GsonMessageBodyHandler { + + /** + * Constructs the object. + */ + public JacksonHandler() { + this(new GsonBuilder()); + } + + /** + * Constructs the object. + * @param builder builder to use to create the gson object + */ + public JacksonHandler(GsonBuilder builder) { + super(builder + .registerTypeAdapterFactory(new JacksonFieldAdapterFactory()) + .registerTypeAdapterFactory(new JacksonMethodAdapterFactory()) + .setExclusionStrategies(new JacksonExclusionStrategy()) + .create()); + } + +} diff --git a/gson/src/test/java/org/onap/policy/common/gson/JacksonHandlerTest.java b/gson/src/test/java/org/onap/policy/common/gson/JacksonHandlerTest.java new file mode 100644 index 00000000..5a49a403 --- /dev/null +++ b/gson/src/test/java/org/onap/policy/common/gson/JacksonHandlerTest.java @@ -0,0 +1,132 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.gson; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; +import javax.ws.rs.core.MediaType; +import org.junit.Test; +import org.onap.policy.common.gson.JacksonHandler; +import org.onap.policy.common.gson.annotation.GsonJsonAnyGetter; +import org.onap.policy.common.gson.annotation.GsonJsonAnySetter; + +public class JacksonHandlerTest { + + @Test + public void test() throws Exception { + JacksonHandler hdlr = new JacksonHandler(); + + assertTrue(hdlr.isReadable(null, null, null, MediaType.APPLICATION_JSON_TYPE)); + assertFalse(hdlr.isReadable(null, null, null, MediaType.TEXT_PLAIN_TYPE)); + + JsonObject expected = new JsonObject(); + expected.addProperty("myId", 100); + expected.addProperty("value", "a value"); + expected.addProperty("abc", "def"); + expected.addProperty("hello", "world"); + + Data data = new Data(); + data.id = 10; + data.value = "a value"; + data.props = new HashMap<>(); + data.props.put("abc", "def"); + data.props.put("hello", "world"); + + /* + * Ensure everything serializes as expected. + */ + ByteArrayOutputStream outstr = new ByteArrayOutputStream(); + hdlr.writeTo(data, Data.class, Data.class, null, null, null, outstr); + + StringReader rdr = new StringReader(outstr.toString("UTF-8")); + JsonObject json = new Gson().fromJson(rdr, JsonObject.class); + + assertEquals(expected, json); + + /* + * Ensure everything deserializes as expected. + */ + Data data2 = (Data) hdlr.readFrom(Object.class, Data.class, null, null, null, + new ByteArrayInputStream(outstr.toByteArray())); + + // id is not serialized, so we must copy it manually before comparing + data2.id = data.id; + + assertEquals(data.toString(), data2.toString()); + } + + /** + * This class includes all policy-specific gson annotations. + */ + public static class Data { + protected int id; + + protected String value; + + protected Map<String, String> props; + + public int getMyId() { + return 100; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + @GsonJsonAnyGetter + public Map<String, String> getProps() { + return props; + } + + /** + * Sets a property. + * @param name property name + * @param value new value + */ + @GsonJsonAnySetter + public void setProperty(String name, String value) { + if (props == null) { + props = new TreeMap<>(); + } + + props.put(name, value); + } + + @Override + public String toString() { + return "Data [id=" + id + ", value=" + value + ", props=" + props + "]"; + } + } +} diff --git a/policy-endpoints/pom.xml b/policy-endpoints/pom.xml index 2c8b0d7f..c7bc8c4a 100644 --- a/policy-endpoints/pom.xml +++ b/policy-endpoints/pom.xml @@ -195,6 +195,13 @@ </dependency> <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>utils-test</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> @@ -209,7 +216,6 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.11.1</version> <scope>test</scope> </dependency> diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java index 9912761f..ebed381d 100644 --- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java +++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxy.java @@ -31,6 +31,7 @@ import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSink; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSource; import org.onap.policy.common.endpoints.event.comm.bus.UebTopicSink; import org.onap.policy.common.endpoints.event.comm.bus.UebTopicSource; +import org.onap.policy.common.gson.annotation.GsonJsonIgnore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -229,35 +230,42 @@ class TopicEndpointProxy implements TopicEndpoint { } @JsonIgnore + @GsonJsonIgnore @Override public List<UebTopicSource> getUebTopicSources() { return UebTopicSource.factory.inventory(); } @JsonIgnore + @GsonJsonIgnore @Override public List<DmaapTopicSource> getDmaapTopicSources() { return DmaapTopicSource.factory.inventory(); } + @JsonIgnore + @GsonJsonIgnore @Override public List<NoopTopicSource> getNoopTopicSources() { return NoopTopicSource.factory.inventory(); } @JsonIgnore + @GsonJsonIgnore @Override public List<UebTopicSink> getUebTopicSinks() { return UebTopicSink.factory.inventory(); } @JsonIgnore + @GsonJsonIgnore @Override public List<DmaapTopicSink> getDmaapTopicSinks() { return DmaapTopicSink.factory.inventory(); } @JsonIgnore + @GsonJsonIgnore @Override public List<NoopTopicSink> getNoopTopicSinks() { return NoopTopicSink.factory.inventory(); @@ -325,6 +333,7 @@ class TopicEndpointProxy implements TopicEndpoint { * @return list of managed endpoints */ @JsonIgnore + @GsonJsonIgnore protected List<Startable> getEndpoints() { final List<Startable> endpoints = new ArrayList<>(); diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java index 9b2e6f5c..1c2d6eeb 100644 --- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java +++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusPublisher.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -41,6 +41,7 @@ import org.onap.dmaap.mr.client.response.MRPublisherResponse; import org.onap.dmaap.mr.test.clients.ProtocolTypeConstants; import org.onap.policy.common.endpoints.event.comm.bus.DmaapTopicSinkFactory; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; +import org.onap.policy.common.gson.annotation.GsonJsonIgnore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,6 +73,7 @@ public interface BusPublisher { * The actual Cambria publisher. */ @JsonIgnore + @GsonJsonIgnore protected volatile CambriaBatchingPublisher publisher; /** diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java index 2287486e..01f9fbe3 100644 --- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java +++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/client/internal/JerseyClient.java @@ -41,6 +41,7 @@ import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; import org.onap.policy.common.endpoints.http.client.HttpClient; +import org.onap.policy.common.gson.annotation.GsonJsonIgnore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -270,6 +271,7 @@ public class JerseyClient implements HttpClient { } @JsonIgnore + @GsonJsonIgnore @Override public String getPassword() { return password; diff --git a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java index 0c52aca8..76ad116f 100644 --- a/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java +++ b/policy-endpoints/src/main/java/org/onap/policy/common/endpoints/http/server/internal/JettyServletServer.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,6 +44,7 @@ import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.onap.aaf.cadi.filter.CadiFilter; import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.gson.annotation.GsonJsonIgnore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -486,6 +487,7 @@ public abstract class JettyServletServer implements HttpServletServer, Runnable * @return the password */ @JsonIgnore + @GsonJsonIgnore public String getPassword() { return password; } diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java index 19dde432..a311c0b0 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.java @@ -33,6 +33,7 @@ import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.bus.DmaapTopicPropertyBuilder; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicPropertyBuilder; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class TopicEndpointProxyTest { @@ -112,6 +113,16 @@ public class TopicEndpointProxyTest { } @Test + public void testSerialize() { + TopicEndpoint manager = new TopicEndpointProxy(); + + manager.addTopicSources(configuration); + manager.addTopicSinks(configuration); + + new GsonTestUtils().compareGson(manager, TopicEndpointProxyTest.class); + } + + @Test public void addTopicSources() { TopicEndpoint manager = new TopicEndpointProxy(); diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java index 56d3b47a..83a94bd5 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class BusTopicBaseTest extends TopicTestBase { @@ -49,6 +50,11 @@ public class BusTopicBaseTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(base, BusTopicBaseTest.class); + } + + @Test public void testGetApiKey() { assertEquals(MY_API_KEY, base.getApiKey()); } diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java index 7330e6f7..cb6eb107 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicListener; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class InlineBusTopicSinkTest extends TopicTestBase { @@ -58,6 +59,11 @@ public class InlineBusTopicSinkTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(sink, InlineBusTopicSinkTest.class); + } + + @Test public void testInlineBusTopicSinkImpl() { // verify that different wrappers can be built sink = new InlineBusTopicSinkImpl(makeBuilder().build()); diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java index bf064100..aaab402c 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class InlineDmaapTopicSinkTest extends TopicTestBase { private InlineDmaapTopicSink sink; @@ -48,6 +49,11 @@ public class InlineDmaapTopicSinkTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(sink, InlineDmaapTopicSinkTest.class); + } + + @Test public void testToString() { assertTrue(sink.toString().startsWith("InlineDmaapTopicSink [")); } diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java index 610070e3..2516406f 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class InlineUebTopicSinkTest extends TopicTestBase { private InlineUebTopicSink sink; @@ -48,6 +49,11 @@ public class InlineUebTopicSinkTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(sink, InlineUebTopicSinkTest.class); + } + + @Test public void testToString() { assertTrue(sink.toString().startsWith("InlineUebTopicSink [")); } diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java index d0e8569b..f930fb6b 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +43,7 @@ import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicListener; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; import org.onap.policy.common.endpoints.event.comm.bus.internal.BusConsumer.FilterableBusConsumer; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class SingleThreadedBusTopicSourceTest extends TopicTestBase { private Thread thread; @@ -69,6 +70,11 @@ public class SingleThreadedBusTopicSourceTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(source, SingleThreadedBusTopicSourceTest.class); + } + + @Test public void testRegister() { source.register(listener); assertEquals(1, source.initCount); @@ -146,7 +152,7 @@ public class SingleThreadedBusTopicSourceTest extends TopicTestBase { // do nothing } }; - + assertNotNull(source2.makePollerThread()); } diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java index c7444034..29c34591 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class SingleThreadedDmaapTopicSourceTest extends TopicTestBase { private SingleThreadedDmaapTopicSource source; @@ -49,6 +50,11 @@ public class SingleThreadedDmaapTopicSourceTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(source, SingleThreadedDmaapTopicSourceTest.class); + } + + @Test public void testToString() { assertTrue(source.toString().startsWith("SingleThreadedDmaapTopicSource [")); source.shutdown(); diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java index b8cb0c13..99dc6fb7 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * policy-endpoints * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class SingleThreadedUebTopicSourceTest extends TopicTestBase { private SingleThreadedUebTopicSource source; @@ -48,6 +49,11 @@ public class SingleThreadedUebTopicSourceTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(source, SingleThreadedUebTopicSourceTest.class); + } + + @Test public void testToString() { assertTrue(source.toString().startsWith("SingleThreadedUebTopicSource [")); source.shutdown(); diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java index 76883b3c..a8ea84fc 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.java @@ -2,14 +2,14 @@ * ============LICENSE_START======================================================= * ONAP Policy Engine - Common Modules * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -37,6 +37,7 @@ import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicListener; import org.onap.policy.common.endpoints.event.comm.bus.TopicTestBase; +import org.onap.policy.common.utils.gson.GsonTestUtils; public class TopicBaseTest extends TopicTestBase { @@ -48,7 +49,7 @@ public class TopicBaseTest extends TopicTestBase { @Before public void setUp() { super.setUp(); - + base = new TopicBaseImpl(servers, MY_TOPIC); } @@ -73,6 +74,11 @@ public class TopicBaseTest extends TopicTestBase { } @Test + public void testSerialize() { + new GsonTestUtils().compareGson(base, TopicBaseTest.class); + } + + @Test public void testRegister() { TopicListener listener = mock(TopicListener.class); base.register(listener); @@ -246,7 +252,7 @@ public class TopicBaseTest extends TopicTestBase { /** * Constructor. - * + * * @param servers list of servers * @param topic topic name */ @@ -285,7 +291,7 @@ public class TopicBaseTest extends TopicTestBase { /** * Adds an event to the list of recent events. - * + * * @param event event to be added */ public void addEvent(String event) { diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java index 3d80793e..972fc666 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/HttpServerTest.java @@ -39,6 +39,7 @@ import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.utils.gson.GsonTestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -233,6 +234,16 @@ public class HttpServerTest { } @Test + public void testSerialize() { + HttpServletServer server = HttpServletServer.factory.build("echo", "localhost", port, "/", false, true); + server.addServletPackage("/*", this.getClass().getPackage().getName()); + server.addFilterClass("/*", TestFilter.class.getCanonicalName()); + + // ensure we can serialize the server + new GsonTestUtils().compareGson(server, HttpServerTest.class); + } + + @Test public void testSingleServer() throws Exception { logger.info("-- testSingleServer() --"); diff --git a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java index 5778eeeb..c211881f 100644 --- a/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java +++ b/policy-endpoints/src/test/java/org/onap/policy/common/endpoints/http/server/test/RestEchoReqResp.java @@ -22,6 +22,7 @@ package org.onap.policy.common.endpoints.http.server.test; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName; +import org.onap.policy.common.gson.annotation.GsonJsonProperty; /** * "ECHO" request and response supporting serialization and de-serialization via @@ -29,10 +30,12 @@ import com.google.gson.annotations.SerializedName; */ public class RestEchoReqResp { @JsonProperty("reqId") + @GsonJsonProperty("reqId") @SerializedName("reqId") private int requestId; @JsonProperty("textValue") + @GsonJsonProperty("textValue") @SerializedName("textValue") private String text; diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.json new file mode 100644 index 00000000..11624af0 --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/TopicEndpointProxyTest.json @@ -0,0 +1,74 @@ +{ + "locked" : false, + "alive" : false, + "topicSources" : [ { + "servers" : [ "my-server" ], + "topic" : "ueb-source", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : null, + "apiSecret" : null, + "useHttps" : true, + "allowSelfSignedCerts" : true, + "consumerGroup" : "${obj.topicSources[0].consumerGroup}", + "consumerInstance" : "${obj.topicSources[0].consumerInstance}", + "fetchTimeout" : 15000, + "fetchLimit" : 100, + "topicCommInfrastructure" : "UEB" + }, { + "servers" : [ "my-server" ], + "topic" : "dmaap-source", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "consumerGroup" : "my-cons-group", + "consumerInstance" : "my-cons-inst", + "fetchTimeout" : 101, + "fetchLimit" : 100, + "topicCommInfrastructure" : "DMAAP" + }, { + "servers" : [ "my-server" ], + "topic" : "noop-source", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "topicCommInfrastructure" : "NOOP" + } ], + "topicSinks" : [ { + "servers" : [ "my-server" ], + "topic" : "ueb-sink", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : null, + "apiSecret" : null, + "useHttps" : true, + "allowSelfSignedCerts" : true, + "topicCommInfrastructure" : "UEB", + "partitionKey" : "${obj.topicSinks[0].partitionKey}" + }, { + "servers" : [ "my-server" ], + "topic" : "dmaap-sink", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "topicCommInfrastructure" : "DMAAP", + "partitionKey" : "my-partition" + }, { + "servers" : [ "my-server" ], + "topic" : "noop-sink", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "topicCommInfrastructure" : "NOOP" + } ] +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.json new file mode 100644 index 00000000..49eafaf1 --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/BusTopicBaseTest.json @@ -0,0 +1,12 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "topicCommInfrastructure" : "NOOP" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.json new file mode 100644 index 00000000..98318751 --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineBusTopicSinkTest.json @@ -0,0 +1,13 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "topicCommInfrastructure" : "NOOP", + "partitionKey" : "my-partition" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.json new file mode 100644 index 00000000..a83f5c97 --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineDmaapTopicSinkTest.json @@ -0,0 +1,13 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "topicCommInfrastructure" : "DMAAP", + "partitionKey" : "my-partition" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.json new file mode 100644 index 00000000..4ec0c80f --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/InlineUebTopicSinkTest.json @@ -0,0 +1,13 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "topicCommInfrastructure" : "UEB", + "partitionKey" : "my-partition" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.json new file mode 100644 index 00000000..4f880257 --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedBusTopicSourceTest.json @@ -0,0 +1,16 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "consumerGroup" : "my-cons-group", + "consumerInstance" : "my-cons-inst", + "fetchTimeout" : 101, + "fetchLimit" : 100, + "topicCommInfrastructure" : "NOOP" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.json new file mode 100644 index 00000000..82e4b3ff --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedDmaapTopicSourceTest.json @@ -0,0 +1,16 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "consumerGroup" : "my-cons-group", + "consumerInstance" : "my-cons-inst", + "fetchTimeout" : 101, + "fetchLimit" : 100, + "topicCommInfrastructure" : "DMAAP" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.json new file mode 100644 index 00000000..4eeacc6d --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/SingleThreadedUebTopicSourceTest.json @@ -0,0 +1,16 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "apiKey" : "my-api-key", + "apiSecret" : "my-api-secret", + "useHttps" : true, + "allowSelfSignedCerts" : true, + "consumerGroup" : "my-cons-group", + "consumerInstance" : "my-cons-inst", + "fetchTimeout" : 101, + "fetchLimit" : 100, + "topicCommInfrastructure" : "UEB" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.json new file mode 100644 index 00000000..7431854d --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/event/comm/bus/internal/TopicBaseTest.json @@ -0,0 +1,8 @@ +{ + "servers" : [ "svra", "svrb" ], + "topic" : "my-topic", + "recentEvents" : [ ], + "alive" : false, + "locked" : false, + "topicCommInfrastructure" : "NOOP" +} diff --git a/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/http/server/internal/HttpServerTest.json b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/http/server/internal/HttpServerTest.json new file mode 100644 index 00000000..5f4a7a90 --- /dev/null +++ b/policy-endpoints/src/test/resources/org/onap/policy/common/endpoints/http/server/internal/HttpServerTest.json @@ -0,0 +1,7 @@ +{ + "aaf": false, + "alive": false, + "host": "localhost", + "name": "echo", + "port": ${obj.port} +} diff --git a/utils-test/pom.xml b/utils-test/pom.xml index bf36472b..fffe6105 100644 --- a/utils-test/pom.xml +++ b/utils-test/pom.xml @@ -44,7 +44,6 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.11.1</version> <scope>test</scope> </dependency> <dependency> @@ -57,6 +56,11 @@ <version>${project.version}</version> </dependency> <dependency> + <groupId>org.onap.policy.common</groupId> + <artifactId>gson</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <scope>test</scope> diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonSerializer.java b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonSerializer.java new file mode 100644 index 00000000..db9c1c7e --- /dev/null +++ b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonSerializer.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.gson; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import java.io.IOException; + +/** + * Gson serializer, providing stub implementation of "read". + * + * @param <T> type of object that this serializes + */ +public abstract class GsonSerializer<T> extends TypeAdapter<T> { + @Override + public T read(JsonReader in) throws IOException { + throw new UnsupportedOperationException("read from pseudo TypeAdapter"); + } +} diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtils.java b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtils.java new file mode 100644 index 00000000..bfdca97c --- /dev/null +++ b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtils.java @@ -0,0 +1,314 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.gson; + +import static org.junit.Assert.assertEquals; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utilities used to test encoding and decoding of Policy objects. + */ +public class GsonTestUtils { + + private static final Logger logger = LoggerFactory.getLogger(GsonTestUtils.class); + + /** + * Matches script items, of the form ${xxx}, within text. + */ + private static final Pattern SCRIPT_PAT = Pattern.compile("\\$\\{([^}]+)\\}"); + + /** + * Engine used to interpolate strings before they're compared. + */ + private static volatile ScriptEngine engine = null; + + /** + * Used to encode and decode an object via gson. + */ + private Gson gson; + + /** + * Constructs the object. + */ + public GsonTestUtils() { + GsonTestUtils other = new GsonTestUtilsBuilder().build(); + + gson = other.gson; + } + + /** + * Constructs the object. + * + * @param gson used to encode via gson + */ + protected GsonTestUtils(Gson gson) { + this.gson = gson; + } + + public Gson getGson() { + return gson; + } + + /** + * Serializes and then deserializes an object using gson. + * + * @param object the object to be serialized + * @param clazz the class of object to deserialize + * @return the deserialized object + */ + public <T> T gsonRoundTrip(T object, Class<T> clazz) { + String sgson = gsonEncode(object); + return gson.fromJson(sgson, clazz); + } + + /** + * Encodes an object using gson and then compares it to the expected value, after + * sorting the elements. The class name is used to find the json file, whose contents + * is interpolated (i.e., script elements, of the form ${obj.xxx}, are expanded). + * + * @param object the object to be encoded + * @param expected the expected value + * @throws Exception if the file cannot be read + */ + public void compareGson(Object object, Class<?> expected) { + compareGson(object, new File(expected.getSimpleName() + ".json")); + } + + /** + * Encodes an object using gson and then compares it to the expected value, after + * sorting the elements. The content of the file is interpolated (i.e., script + * elements, of the form ${obj.xxx}, are expanded). + * + * @param object the object to be encoded + * @param expected the expected value + * @throws Exception if the file cannot be read + */ + public void compareGson(Object object, File expected) { + // file is not required to have a full path - find it via getResource() + URL url = object.getClass().getResource(expected.getName()); + if (url == null) { + throw new JsonParseException(new FileNotFoundException(expected.getName())); + } + + String expectedText; + try { + expectedText = readFile(new File(url.getFile())); + + } catch (IOException e) { + throw new JsonParseException("error reading: " + expected, e); + } + + compareGson(object, expectedText); + } + + /** + * Encodes an object using gson and then compares it to the expected value, after + * sorting the elements. The expected value is interpolated (i.e., script elements, of + * the form ${obj.xxx}, are expanded). + * + * @param object the object to be encoded + * @param expected the expected value + */ + public void compareGson(Object object, String expected) { + String result = applyScripts(expected, object); + compareGson(object, gson.fromJson(result, JsonElement.class)); + } + + /** + * Encodes an object using gson and then compares it to the expected value, after + * sorting the elements. + * + * @param object the object to be encoded + * @param expected the expected value + */ + public void compareGson(Object object, JsonElement expected) { + String sgson = gsonEncode(object); + + JsonElement gsonjo = reorder(gson.fromJson(sgson, JsonElement.class)); + JsonElement expjo = reorder(expected); + + assertEquals(expjo.toString(), gsonjo.toString()); + } + + /** + * Reads the content of a file. + * @param file file to read + * @return the content of the file + * @throws IOException if an error occurs + */ + protected String readFile(File file) throws IOException { + return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); + } + + + /** + * Interpolates script elements, of the form ${obj.xxx}, within some text. The script + * is evaluated via javascript, where "obj" references the object used by each script + * element. + * + * @param object object to be used by the script + * @param text text to be evaluated + * @return the text, after interpolating the script elements + */ + public String applyScripts(String text, Object object) { + Matcher mat = SCRIPT_PAT.matcher(text); + if (!mat.find()) { + // contains no script elements - just return it as is + return text; + } + + // create the engine and bind the object to the variable, "obj" + if (engine == null) { + // race condition here, but it's ok to overwrite with a new engine + engine = new ScriptEngineManager().getEngineByName("javascript"); + } + + Bindings bindings = engine.createBindings(); + bindings.put("obj", object); + + // work our way through the text, interpolating script elements as we go + StringBuilder bldr = new StringBuilder(); + int ilast = 0; + mat.reset(); + while (mat.find(ilast)) { + // append segment that appears between last match and this + int inext = mat.start(); + bldr.append(text.substring(ilast, inext)); + + // next match begins after the current match + ilast = mat.end(); + + // interpolate the script + String script = mat.group(1); + try { + Object result = engine.eval(script, bindings); + bldr.append(result == null ? "null" : result.toString()); + + } catch (ScriptException e) { + throw new RuntimeException("cannot expand element: " + mat.group(), e); + } + } + + // append final segment + bldr.append(text.substring(ilast)); + + return bldr.toString(); + } + + /** + * Encodes an object using gson. + * + * @param object the object to be encoded + * @return the encoded object + */ + public String gsonEncode(Object object) { + String sgson = gson.toJson(object); + logger.debug("gson=" + sgson); + return sgson; + } + + /** + * Recursively re-orders a json object, arranging the keys alphabetically and removing + * null items. + * + * @param jsonObj object from which nulls are to be removed + * @return a new object, without the null items + */ + public JsonObject reorder(JsonObject jsonObj) { + JsonObject newjo = new JsonObject(); + + // sort the keys before copying to the new object + List<Entry<String, JsonElement>> sortedSet = new ArrayList<>(jsonObj.entrySet()); + Collections.sort(sortedSet, (left, right) -> left.getKey().compareTo(right.getKey())); + + for (Entry<String, JsonElement> ent : sortedSet) { + JsonElement val = ent.getValue(); + if (val.isJsonNull()) { + continue; + } + + newjo.add(ent.getKey(), reorder(val)); + } + + return newjo; + } + + /** + * Recursively re-orders a json array, arranging the keys alphabetically and removing + * null items. + * + * @param jsonArray array from which nulls are to be removed + * @return a new array, with null items removed from all elements + */ + public JsonArray reorder(JsonArray jsonArray) { + JsonArray newarr = new JsonArray(); + for (JsonElement ent : jsonArray) { + newarr.add(reorder(ent)); + } + + return newarr; + } + + /** + * Recursively re-orders a json element, arranging the keys alphabetically and + * removing null items. + * + * @param jsonEl element from which nulls are to be removed + * @return a new element, with null items removed + */ + public JsonElement reorder(JsonElement jsonEl) { + if (jsonEl == null) { + return null; + + } else if (jsonEl.isJsonObject()) { + return reorder(jsonEl.getAsJsonObject()); + + } else if (jsonEl.isJsonArray()) { + return reorder(jsonEl.getAsJsonArray()); + + } else { + return jsonEl; + } + } +} diff --git a/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java new file mode 100644 index 00000000..1f697fdb --- /dev/null +++ b/utils-test/src/main/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilder.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.gson; + +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapterFactory; +import org.onap.policy.common.gson.JacksonHandler; + +/** + * Used to builder a utility class. + */ +public class GsonTestUtilsBuilder { + private final GsonBuilder gsonBldr; + + /** + * Constructs the object. + */ + public GsonTestUtilsBuilder() { + gsonBldr = new GsonBuilder(); + + // register jackson behaviors with the builder + new JacksonHandler(gsonBldr); + } + + /** + * Builds the utility. + * + * @return a new utility + */ + public GsonTestUtils build() { + return new GsonTestUtils(gsonBldr.create()); + } + + /** + * Adds gson support for serializing a mock of a class. + * + * @param clazz mocked class to be supported + * @param sgson gson serializer + */ + protected <T> void addMock(Class<T> clazz, TypeAdapterFactory sgson) { + gsonBldr.registerTypeAdapterFactory(sgson); + } +} diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonSerializerTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonSerializerTest.java new file mode 100644 index 00000000..82f5ede0 --- /dev/null +++ b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonSerializerTest.java @@ -0,0 +1,47 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.gson; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.io.StringReader; +import org.junit.Test; + +public class GsonSerializerTest { + + @Test + public void testReadJsonReader() { + JsonReader rdr = new JsonReader(new StringReader("10")); + + GsonSerializer<Object> ser = new GsonSerializer<Object>() { + @Override + public void write(JsonWriter out, Object value) throws IOException { + // do nothing + } + }; + + assertThatThrownBy(() -> ser.read(rdr)).isInstanceOf(UnsupportedOperationException.class) + .hasMessage("read from pseudo TypeAdapter"); + } +} diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilderTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilderTest.java new file mode 100644 index 00000000..3e4244dd --- /dev/null +++ b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsBuilderTest.java @@ -0,0 +1,93 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.gson; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import org.junit.Before; +import org.junit.Test; + +public class GsonTestUtilsBuilderTest { + + private GsonTestUtilsBuilder bldr; + private GsonTestUtils utils; + + @Before + public void setUp() { + bldr = new MyBuilder(); + utils = bldr.build(); + } + + @Test + public void testBuilderAddMock() { + PreMock pre = mock(PreMock.class); + when(pre.getId()).thenReturn(2000); + + assertEquals("{\"name\":2000}", utils.gsonEncode(pre)); + } + + /** + * Builder that provides an adapter for mock(PreMock.class). + */ + private static class MyBuilder extends GsonTestUtilsBuilder { + public MyBuilder() { + TypeAdapterFactory sgson = new TypeAdapterFactory() { + @Override + public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { + Class<? super T> clazz = type.getRawType(); + + if (PreMock.class.isAssignableFrom(clazz)) { + return new GsonSerializer<T>() { + @Override + public void write(JsonWriter out, T value) throws IOException { + PreMock obj = (PreMock) value; + out.beginObject().name("name").value(obj.getId()).endObject(); + } + }; + } + + return null; + } + }; + + addMock(PreMock.class, sgson); + } + } + + /** + * Class that will be mocked. + */ + public static class PreMock { + protected int id = 1000; + + public int getId() { + return id; + } + } +} diff --git a/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsTest.java b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsTest.java new file mode 100644 index 00000000..39cde7dc --- /dev/null +++ b/utils-test/src/test/java/org/onap/policy/common/utils/gson/GsonTestUtilsTest.java @@ -0,0 +1,248 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.gson; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import javax.script.ScriptException; +import org.junit.Before; +import org.junit.Test; + +public class GsonTestUtilsTest { + private static final String HELLO = "hello"; + + private GsonTestUtils utils; + + @Before + public void setUp() { + utils = new GsonTestUtils(); + } + + @Test + public void testGetGson() { + assertNotNull(utils.getGson()); + } + + @Test + public void testGsonRoundTrip() { + Data data = new Data(); + data.setId(500); + + // try with null text + data.setText(null); + assertEquals(data.toString(), utils.gsonRoundTrip(data, Data.class).toString()); + + // try with non-null text + data.setText(HELLO); + assertEquals(data.toString(), utils.gsonRoundTrip(data, Data.class).toString()); + } + + @Test + public void testCompareGsonObjectClass_testCompareGsonObjectFile() { + Data data = new Data(); + data.setId(500); + data.setText(HELLO); + + utils.compareGson(data, GsonTestUtilsTest.class); + + // file not found + assertThatThrownBy(() -> utils.compareGson(data, + new File(GsonTestUtilsTest.class.getSimpleName() + "-NotFound.json"))) + .isInstanceOf(JsonParseException.class) + .hasCauseInstanceOf(FileNotFoundException.class); + + // force I/O error while reading file + GsonTestUtils utils2 = new GsonTestUtils() { + @Override + protected String readFile(File file) throws IOException { + throw new IOException("expected exception"); + } + }; + assertThatThrownBy(() -> utils2.compareGson(data, GsonTestUtilsTest.class)) + .isInstanceOf(JsonParseException.class).hasCauseInstanceOf(IOException.class) + .hasMessage("error reading: GsonTestUtilsTest.json"); + } + + @Test + public void testCompareGsonObjectString() { + Data data = new Data(); + data.setId(600); + data.setText(HELLO); + + utils.compareGson(data, "{'id': ${obj.id}, 'text': '${obj.text}'}".replace('\'', '"')); + } + + @Test + public void testCompareGsonObjectJsonElement() { + Data data = new Data(); + data.setId(650); + data.setText(HELLO); + + JsonObject json = new JsonObject(); + json.addProperty("id", data.getId()); + json.addProperty("text", data.getText()); + + utils.compareGson(data, json); + + // mismatch + data.setText("world"); + assertThatThrownBy(() -> utils.compareGson(data, json)).isInstanceOf(AssertionError.class); + } + + @Test + public void testApplyScripts() { + Data data = new Data(); + data.setId(700); + data.setText(HELLO); + + String result = utils.applyScripts("no interpolation", data); + assertEquals("no interpolation", result); + + result = utils.applyScripts("${obj.id} at start, ${obj.text} in middle, and end ${obj.id}", data); + assertEquals("700 at start, hello in middle, and end 700", result); + + // try null value + data.setText(null); + result = utils.applyScripts("use ${obj.text} this", data); + assertEquals("use null this", result); + + assertThatThrownBy(() -> utils.applyScripts("use ${obj.text} this", null)).isInstanceOf(RuntimeException.class) + .hasCauseInstanceOf(ScriptException.class).hasMessage("cannot expand element: ${obj.text}"); + } + + @Test + public void testReorderJsonObject() { + // insert properties in a non-alphabetical order + JsonObject inner = new JsonObject(); + inner.addProperty("objBint", 100); + inner.add("objBNull", JsonNull.INSTANCE); + inner.addProperty("objB", true); + + JsonArray arr = new JsonArray(); + arr.add(110); + arr.add(inner); + arr.add(false); + + JsonObject outer = new JsonObject(); + outer.add("objANull", JsonNull.INSTANCE); + outer.addProperty("objA", true); + outer.addProperty("objAStr", "obj-a-string"); + outer.add("nested-array", arr); + + outer = utils.reorder(outer); + assertEquals("{'nested-array':[110,{'objB':true,'objBint':100},false],'objA':true,'objAStr':'obj-a-string'}" + .replace('\'', '"'), outer.toString()); + } + + @Test + public void testReorderJsonArray() { + // insert properties in a non-alphabetical order + JsonObject inner = new JsonObject(); + inner.add("objCNull", JsonNull.INSTANCE); + inner.addProperty("objCStr", "obj-c-string"); + inner.addProperty("objC", true); + + JsonArray arr = new JsonArray(); + arr.add(200); + arr.add(inner); + arr.add(false); + + arr = utils.reorder(arr); + assertEquals("[200,{'objC':true,'objCStr':'obj-c-string'},false]".replace('\'', '"'), arr.toString()); + } + + @Test + public void testReorderJsonElement() { + // null element + JsonElement jsonEl = null; + assertNull(utils.reorder(jsonEl)); + + // object element + JsonObject obj = new JsonObject(); + obj.add("objDNull", JsonNull.INSTANCE); + obj.addProperty("objDStr", "obj-d-string"); + obj.addProperty("objD", true); + jsonEl = obj; + jsonEl = utils.reorder(jsonEl); + assertEquals("{'objD':true,'objDStr':'obj-d-string'}".replace('\'', '"'), jsonEl.toString()); + + // boolean + jsonEl = obj.get("objD"); + jsonEl = utils.reorder(jsonEl); + assertEquals("true", jsonEl.toString()); + + // JsonNull + jsonEl = JsonNull.INSTANCE; + jsonEl = utils.reorder(jsonEl); + assertEquals("null", jsonEl.toString()); + + // array element + JsonObject inner = new JsonObject(); + inner.add("objENull", JsonNull.INSTANCE); + inner.addProperty("objEStr", "obj-e-string"); + inner.addProperty("objE", true); + + JsonArray arr = new JsonArray(); + arr.add(300); + arr.add(inner); + arr.add(false); + jsonEl = arr; + jsonEl = utils.reorder(jsonEl); + assertEquals("[300,{'objE':true,'objEStr':'obj-e-string'},false]".replace('\'', '"'), jsonEl.toString()); + } + + public static class Data { + private int id; + private String text; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + @Override + public String toString() { + return "Data [id=" + id + ", text=" + text + "]"; + } + } +} diff --git a/utils-test/src/test/resources/org/onap/policy/common/utils/gson/GsonTestUtilsTest.json b/utils-test/src/test/resources/org/onap/policy/common/utils/gson/GsonTestUtilsTest.json new file mode 100644 index 00000000..ff7ed70b --- /dev/null +++ b/utils-test/src/test/resources/org/onap/policy/common/utils/gson/GsonTestUtilsTest.json @@ -0,0 +1,4 @@ +{ + "id": ${obj.id}, + "text": "${obj.text}" +} |