From 2b29c6049b9d346aad060d35b45053a003825930 Mon Sep 17 00:00:00 2001 From: Xiaowei Zhu <33129495+zhu-xiaowei@users.noreply.github.com> Date: Tue, 12 Sep 2023 19:29:51 +0800 Subject: [PATCH] feat: add error code and clickstream error event (#37) Co-authored-by: xiaoweii --- .../clickstream/AWSClickstreamPlugin.java | 2 +- .../clickstream/client/AnalyticsClient.java | 36 ++-- .../clickstream/client/AnalyticsEvent.java | 5 +- .../solution/clickstream/client/Event.java | 108 +++++++++--- .../clickstream/AnalyticsClientTest.java | 164 ++++++++++++------ .../clickstream/AnalyticsEventTest.java | 11 +- .../clickstream/EventRecorderTest.java | 12 +- 7 files changed, 236 insertions(+), 102 deletions(-) diff --git a/clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPlugin.java b/clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPlugin.java index 22b7f2a..693aa10 100644 --- a/clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPlugin.java +++ b/clickstream/src/main/java/software/aws/solution/clickstream/AWSClickstreamPlugin.java @@ -98,7 +98,7 @@ public void recordEvent(@NonNull AnalyticsEventBehavior analyticsEvent) { final AnalyticsEvent clickstreamEvent = analyticsClient.createEvent(analyticsEvent.getName()); - if (analyticsEvent.getProperties() != null) { + if (clickstreamEvent != null && analyticsEvent.getProperties() != null) { for (Map.Entry> entry : analyticsEvent.getProperties()) { AnalyticsPropertyBehavior property = entry.getValue(); clickstreamEvent.addAttribute(entry.getKey(), property.getValue()); diff --git a/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java b/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java index 7bad881..b2f89c3 100644 --- a/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java +++ b/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsClient.java @@ -33,7 +33,6 @@ */ public class AnalyticsClient { private static final Log LOG = LogFactory.getLog(AnalyticsClient.class); - private static final int MAX_EVENT_TYPE_LENGTH = 50; private final ClickstreamContext context; private final Map globalAttributes = new ConcurrentHashMap<>(); private JSONObject userAttributes; @@ -67,9 +66,10 @@ public void addGlobalAttribute(String name, Object value) { if (value != null) { Event.EventError error = Event.checkAttribute(globalAttributes.size(), name, value); if (error != null) { - if (!globalAttributes.containsKey(error.getErrorType())) { - globalAttributes.put(error.getErrorType(), error.getErrorMessage()); - } + final AnalyticsEvent event = createEvent(Event.PresetEvent.CLICKSTREAM_ERROR); + event.addAttribute(Event.ReservedAttribute.ERROR_CODE, error.getErrorCode()); + event.addAttribute(Event.ReservedAttribute.ERROR_MESSAGE, error.getErrorMessage()); + recordEvent(event); return; } globalAttributes.put(name, value); @@ -101,9 +101,10 @@ public void addUserAttribute(String name, Object value) { if (value != null) { Event.EventError error = Event.checkUserAttribute(userAttributes.length(), name, value); if (error != null) { - if (!globalAttributes.containsKey(error.getErrorType())) { - globalAttributes.put(error.getErrorType(), error.getErrorMessage()); - } + final AnalyticsEvent event = createEvent(Event.PresetEvent.CLICKSTREAM_ERROR); + event.addAttribute(Event.ReservedAttribute.ERROR_CODE, error.getErrorCode()); + event.addAttribute(Event.ReservedAttribute.ERROR_MESSAGE, error.getErrorMessage()); + recordEvent(event); return; } try { @@ -166,16 +167,19 @@ public void updateUserAttribute() { * @throws IllegalArgumentException throws when fail to check the argument. */ public AnalyticsEvent createEvent(String eventType) { - if (eventType.length() > MAX_EVENT_TYPE_LENGTH) { - LOG.error("The event name is too long, the max event type length is " + MAX_EVENT_TYPE_LENGTH + - " characters. event name:" + eventType); - throw new IllegalArgumentException("The event name passed into create event was too long"); - } - if (!Event.isValidName(eventType)) { - LOG.error("Event name can only contains uppercase and lowercase letters, underscores, number, " + - "and is not start with a number. event name:" + eventType); - throw new IllegalArgumentException("The event name was not valid"); + Event.EventError error = Event.checkEventName(eventType); + if (error != null) { + LOG.error(error.getErrorMessage()); + AnalyticsEvent event = createAnalyticsEvent(Event.PresetEvent.CLICKSTREAM_ERROR); + event.addAttribute(Event.ReservedAttribute.ERROR_CODE, error.getErrorCode()); + event.addAttribute(Event.ReservedAttribute.ERROR_MESSAGE, error.getErrorMessage()); + recordEvent(event); + return null; } + return createAnalyticsEvent(eventType); + } + + private AnalyticsEvent createAnalyticsEvent(String eventType) { long timestamp = System.currentTimeMillis(); AnalyticsEvent event = new AnalyticsEvent(eventType, globalAttributes, userAttributes, timestamp, userUniqueId); event.setDeviceId(this.context.getDeviceId()); diff --git a/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsEvent.java b/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsEvent.java index 3259a6e..7e72ae9 100644 --- a/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsEvent.java +++ b/clickstream/src/main/java/software/aws/solution/clickstream/client/AnalyticsEvent.java @@ -252,8 +252,9 @@ public void addAttribute(final String name, final Object value) { Event.EventError attributeError = Event.checkAttribute(getCurrentNumOfAttributes(), name, value); try { if (attributeError != null) { - if (!attributes.has(attributeError.getErrorType())) { - attributes.putOpt(attributeError.getErrorType(), attributeError.getErrorMessage()); + if (!attributes.has(Event.ReservedAttribute.ERROR_CODE)) { + attributes.putOpt(Event.ReservedAttribute.ERROR_CODE, attributeError.getErrorCode()); + attributes.putOpt(Event.ReservedAttribute.ERROR_MESSAGE, attributeError.getErrorMessage()); } } else { attributes.putOpt(name, value); diff --git a/clickstream/src/main/java/software/aws/solution/clickstream/client/Event.java b/clickstream/src/main/java/software/aws/solution/clickstream/client/Event.java index 7b82e4c..413fcbe 100644 --- a/clickstream/src/main/java/software/aws/solution/clickstream/client/Event.java +++ b/clickstream/src/main/java/software/aws/solution/clickstream/client/Event.java @@ -30,6 +30,25 @@ public final class Event { private Event() { } + /** + * check the event type. + * + * @param eventName the event name + * @return the EventError object + */ + public static EventError checkEventName(String eventName) { + if (!isValidName(eventName)) { + return new EventError(ErrorCode.EVENT_NAME_INVALID, + "Event name can only contains uppercase and lowercase letters, " + + "underscores, number, and is not start with a number. event name: " + eventName); + } else if (eventName.length() > Limit.MAX_LENGTH_OF_NAME) { + return new EventError(ErrorCode.EVENT_NAME_LENGTH_EXCEED, + "Event name is too long, the max event type length is " + + Limit.MAX_LENGTH_OF_NAME + "characters. event name: " + eventName); + } + return null; + } + /** * check the attribute error. * @@ -42,14 +61,14 @@ public static EventError checkAttribute(int currentNumber, String name, Object v if (currentNumber >= Limit.MAX_NUM_OF_ATTRIBUTES) { LOG.error("reached the max number of attributes limit (" + Limit.MAX_NUM_OF_ATTRIBUTES + "). and the attribute: " + name + " will not be recorded"); - return new EventError(ErrorType.ATTRIBUTE_SIZE_EXCEED, + return new EventError(ErrorCode.ATTRIBUTE_SIZE_EXCEED, StringUtil.clipString("attribute name: " + name, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } if (name.length() > Limit.MAX_LENGTH_OF_NAME) { LOG.error("attribute : " + name + ", reached the max length of attributes name limit(" + Limit.MAX_LENGTH_OF_NAME + "). current length is:(" + name.length() + ") and the attribute will not be recorded"); - return new EventError(ErrorType.ATTRIBUTE_NAME_LENGTH_EXCEED, + return new EventError(ErrorCode.ATTRIBUTE_NAME_LENGTH_EXCEED, StringUtil.clipString("attribute name length is:(" + name.length() + ") name is:" + name, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } @@ -57,7 +76,7 @@ public static EventError checkAttribute(int currentNumber, String name, Object v LOG.error("attribute : " + name + ", was not valid, attribute name can only contains" + " uppercase and lowercase letters, underscores, number, and is not start with a number." + " so the attribute will not be recorded"); - return new EventError(ErrorType.ATTRIBUTE_NAME_INVALID, + return new EventError(ErrorCode.ATTRIBUTE_NAME_INVALID, StringUtil.clipString(name, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } @@ -68,7 +87,7 @@ public static EventError checkAttribute(int currentNumber, String name, Object v + Limit.MAX_LENGTH_OF_VALUE + "). current length is:(" + valueLength + "). and the attribute will not be recorded, attribute value:" + value); - return new EventError(ErrorType.ATTRIBUTE_VALUE_LENGTH_EXCEED, + return new EventError(ErrorCode.ATTRIBUTE_VALUE_LENGTH_EXCEED, StringUtil.clipString("attribute name:" + name + ", attribute value:" + value, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } @@ -88,14 +107,14 @@ public static EventError checkUserAttribute(int currentNumber, String name, Obje if (currentNumber >= Limit.MAX_NUM_OF_USER_ATTRIBUTES) { LOG.error("reached the max number of user attributes limit (" + Limit.MAX_NUM_OF_USER_ATTRIBUTES + "). and the user attribute: " + name + " will not be recorded"); - return new EventError(ErrorType.ATTRIBUTE_SIZE_EXCEED, + return new EventError(ErrorCode.USER_ATTRIBUTE_SIZE_EXCEED, StringUtil.clipString("attribute name: " + name, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } if (name.length() > Limit.MAX_LENGTH_OF_NAME) { LOG.error("user attribute : " + name + ", reached the max length of attributes name limit(" + Limit.MAX_LENGTH_OF_NAME + "). current length is:(" + name.length() + ") and the attribute will not be recorded"); - return new EventError(ErrorType.ATTRIBUTE_NAME_LENGTH_EXCEED, + return new EventError(ErrorCode.USER_ATTRIBUTE_NAME_LENGTH_EXCEED, StringUtil.clipString("user attribute name length is:(" + name.length() + ") name is:" + name, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } @@ -106,7 +125,7 @@ public static EventError checkUserAttribute(int currentNumber, String name, Obje LOG.error("user attribute : " + name + ", was not valid, user attribute name can only contains" + " uppercase and lowercase letters, underscores, number, and is not start with a number." + " so the attribute will not be recorded"); - return new EventError(ErrorType.ATTRIBUTE_NAME_INVALID, + return new EventError(ErrorCode.USER_ATTRIBUTE_NAME_INVALID, StringUtil.clipString(name, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } if (value instanceof String) { @@ -115,7 +134,7 @@ public static EventError checkUserAttribute(int currentNumber, String name, Obje LOG.error("user attribute : " + name + ", reached the max length of attributes value limit (" + Limit.MAX_LENGTH_OF_USER_VALUE + "). current length is:(" + valueLength + "). and the attribute will not be recorded, attribute value:" + value); - return new EventError(ErrorType.ATTRIBUTE_VALUE_LENGTH_EXCEED, + return new EventError(ErrorCode.USER_ATTRIBUTE_VALUE_LENGTH_EXCEED, StringUtil.clipString("user attribute name:" + name + ", attribute value:" + value, Limit.MAX_LENGTH_OF_ERROR_VALUE, true)); } @@ -173,15 +192,51 @@ private Limit() { } /** - * event error type. + * the event error code constants. */ - public static final class ErrorType { - private static final String ATTRIBUTE_NAME_INVALID = "_error_name_invalid"; - private static final String ATTRIBUTE_NAME_LENGTH_EXCEED = "_error_name_length_exceed"; - private static final String ATTRIBUTE_VALUE_LENGTH_EXCEED = "_error_value_length_exceed"; - private static final String ATTRIBUTE_SIZE_EXCEED = "_error_attribute_size_exceed"; + public static final class ErrorCode { + /** + * error code for event name invalid. + */ + public static final int EVENT_NAME_INVALID = 1001; + /** + * error code for event name length exceed the limit. + */ + public static final int EVENT_NAME_LENGTH_EXCEED = 1002; + /** + * error code for attribute name length exceed. + */ + public static final int ATTRIBUTE_NAME_LENGTH_EXCEED = 2001; + /** + * error code for attribute name invalid. + */ + public static final int ATTRIBUTE_NAME_INVALID = 2002; + /** + * error code for attribute value length exceed. + */ + public static final int ATTRIBUTE_VALUE_LENGTH_EXCEED = 2003; + /** + * error code for attribute size exceed. + */ + public static final int ATTRIBUTE_SIZE_EXCEED = 2004; + /** + * error code for user attribute size exceed. + */ + public static final int USER_ATTRIBUTE_SIZE_EXCEED = 3001; + /** + * error code for user attribute name length exceed. + */ + public static final int USER_ATTRIBUTE_NAME_LENGTH_EXCEED = 3002; + /** + * error code for user user attribute name invalid. + */ + public static final int USER_ATTRIBUTE_NAME_INVALID = 3003; + /** + * error code for user attribute value length exceed. + */ + public static final int USER_ATTRIBUTE_VALUE_LENGTH_EXCEED = 3004; - private ErrorType() { + private ErrorCode() { } } @@ -189,11 +244,11 @@ private ErrorType() { * Event for return. */ public static class EventError { - private final String errorType; + private final int errorCode; private final String errorMessage; - EventError(String errorType, String errorMessage) { - this.errorType = errorType; + EventError(int errorType, String errorMessage) { + this.errorCode = errorType; this.errorMessage = errorMessage; } @@ -202,8 +257,8 @@ public static class EventError { * * @return error type */ - public String getErrorType() { - return errorType; + public int getErrorCode() { + return errorCode; } /** @@ -287,6 +342,14 @@ public static final class ReservedAttribute { * is the first time attribute. */ public static final String IS_FIRST_TIME = "_is_first_time"; + /** + * is the error code attribute. + */ + public static final String ERROR_CODE = "_error_code"; + /** + * is the error message attribute. + */ + public static final String ERROR_MESSAGE = "_error_message"; private ReservedAttribute() { } @@ -346,6 +409,11 @@ public static final class PresetEvent { */ public static final String PROFILE_SET = "_profile_set"; + /** + * clickstream error event. + */ + public static final String CLICKSTREAM_ERROR = "_clickstream_error"; + private PresetEvent() { } } diff --git a/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java b/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java index 70fe867..8ed5d57 100644 --- a/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java +++ b/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsClientTest.java @@ -25,16 +25,24 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import software.aws.solution.clickstream.client.AnalyticsClient; +import software.aws.solution.clickstream.client.AnalyticsEvent; import software.aws.solution.clickstream.client.ClickstreamManager; import software.aws.solution.clickstream.client.Event; +import software.aws.solution.clickstream.client.Event.ErrorCode; import software.aws.solution.clickstream.util.ReflectUtil; import java.util.Map; import java.util.Objects; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) public class AnalyticsClientTest { @@ -46,6 +54,12 @@ public class AnalyticsClientTest { private final String invalidName = "1_goods_expose"; private String exceedLengthValue = ""; + private AnalyticsClient mockAnalyticsClient; + private ArgumentCaptor analyticsEventCaptor; + + private String errorCodeKey = Event.ReservedAttribute.ERROR_CODE; + private String errorMessageKey = Event.ReservedAttribute.ERROR_MESSAGE; + /** * prepare eventRecorder and context. * @@ -72,25 +86,45 @@ public void setup() throws Exception { } exceedLengthValue = sb.toString(); exceedLengthName = exceedLengthName + "1"; + mockAnalyticsClient = Mockito.spy(analyticsClient); + analyticsEventCaptor = ArgumentCaptor.forClass(AnalyticsEvent.class); } /** - * test create event when event name exceed the max length or event name was not valid. + * test create event when event name exceed the max length. + * + * @throws JSONException the json exception */ @Test - public void testCreateEventException() { - try { - analyticsClient.createEvent(exceedLengthName); - } catch (Exception exception) { - Assert.assertEquals("The event name passed into create event was too long", exception.getMessage()); - } - try { - analyticsClient.createEvent(invalidName); - } catch (Exception exception) { - Assert.assertEquals("The event name was not valid", exception.getMessage()); - } + public void testCreateEventWithNameLengthError() throws JSONException { + AnalyticsEvent event = mockAnalyticsClient.createEvent(exceedLengthName); + Assert.assertNull(event); + + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent errorEvent = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, errorEvent.getEventType()); + Assert.assertEquals(ErrorCode.EVENT_NAME_LENGTH_EXCEED, + errorEvent.getAttributes().get(errorCodeKey)); + } + + /** + * test create event when event name was invalid. + * + * @throws JSONException the json exception + */ + @Test + public void testCreateEventWithInvalidNameError() throws JSONException { + AnalyticsEvent event = mockAnalyticsClient.createEvent(invalidName); + Assert.assertNull(event); + + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent errorEvent = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, errorEvent.getEventType()); + Assert.assertEquals(ErrorCode.EVENT_NAME_INVALID, + errorEvent.getAttributes().get(errorCodeKey)); } + /** * test add global attribute when success. */ @@ -103,25 +137,33 @@ public void testAddGlobalAttributeWhenSuccess() { /** * test add global attribute when error. + * + * @throws JSONException the json exception */ @Test - public void testAddGlobalAttributeWhenError() { - analyticsClient.addGlobalAttribute(exceedLengthName, "value"); - Assert.assertTrue(globalAttributes.containsKey("_error_name_length_exceed")); - Assert.assertTrue(Objects.requireNonNull(globalAttributes.get("_error_name_length_exceed")).toString() - .contains(exceedLengthName)); - - analyticsClient.addGlobalAttribute(invalidName, "value"); - Assert.assertTrue(globalAttributes.containsKey("_error_name_invalid")); - Assert.assertTrue( - Objects.requireNonNull(globalAttributes.get("_error_name_invalid")).toString().contains(invalidName)); - - analyticsClient.addGlobalAttribute("name01", exceedLengthValue); - Assert.assertTrue(globalAttributes.containsKey("_error_value_length_exceed")); - Assert.assertTrue( - Objects.requireNonNull(globalAttributes.get("_error_value_length_exceed")).toString().contains("name01")); - Assert.assertTrue(Objects.requireNonNull(globalAttributes.get("_error_value_length_exceed")).toString() - .contains("attribute value:")); + public void testAddGlobalAttributeWhenError() throws JSONException { + mockAnalyticsClient.addGlobalAttribute(exceedLengthName, "value"); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent errorEvent = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, errorEvent.getEventType()); + Assert.assertEquals(ErrorCode.ATTRIBUTE_NAME_LENGTH_EXCEED, + errorEvent.getAttributes().get(errorCodeKey)); + + Mockito.reset(mockAnalyticsClient); + mockAnalyticsClient.addGlobalAttribute(invalidName, "value"); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent errorEvent1 = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, errorEvent1.getEventType()); + Assert.assertEquals(ErrorCode.ATTRIBUTE_NAME_INVALID, + errorEvent1.getAttributes().get(errorCodeKey)); + + Mockito.reset(mockAnalyticsClient); + mockAnalyticsClient.addGlobalAttribute("name01", exceedLengthValue); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent errorEvent2 = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, errorEvent2.getEventType()); + Assert.assertEquals(ErrorCode.ATTRIBUTE_VALUE_LENGTH_EXCEED, + errorEvent2.getAttributes().get(errorCodeKey)); } /** @@ -143,9 +185,10 @@ public void deleteGlobalAttribute() { @Test public void testAddGlobalAttributeSameNameMultiTimes() { for (int i = 0; i < 501; i++) { - analyticsClient.addGlobalAttribute("name", "value" + i); + mockAnalyticsClient.addGlobalAttribute("name", "value" + i); } Assert.assertFalse(globalAttributes.containsKey("_error_attribute_size_exceed")); + verify(mockAnalyticsClient, never()).createEvent(anyString()); Assert.assertEquals(1, globalAttributes.size()); Assert.assertEquals("value500", Objects.requireNonNull(globalAttributes.get("name")).toString()); } @@ -166,38 +209,49 @@ public void testAddUserAttributeWhenSuccess() throws JSONException { /** * test add user attribute when error. + * + * @throws JSONException the json exception */ @Test - public void testAddUserAttributeWhenError() { - analyticsClient.addUserAttribute(exceedLengthName, "value"); - Assert.assertTrue(globalAttributes.containsKey("_error_name_length_exceed")); - Assert.assertTrue(Objects.requireNonNull(globalAttributes.get("_error_name_length_exceed")).toString() - .contains(exceedLengthName)); - - analyticsClient.addUserAttribute(invalidName, "value"); - Assert.assertTrue(globalAttributes.containsKey("_error_name_invalid")); - Assert.assertTrue( - Objects.requireNonNull(globalAttributes.get("_error_name_invalid")).toString().contains(invalidName)); - - analyticsClient.addUserAttribute("name01", exceedLengthValue); - Assert.assertTrue(globalAttributes.containsKey("_error_value_length_exceed")); - Assert.assertTrue( - Objects.requireNonNull(globalAttributes.get("_error_value_length_exceed")).toString().contains("name01")); - Assert.assertTrue(Objects.requireNonNull(globalAttributes.get("_error_value_length_exceed")).toString() - .contains("attribute value:")); + public void testAddUserAttributeWhenError() throws JSONException { + mockAnalyticsClient.addUserAttribute(exceedLengthName, "value"); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent event = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, event.getEventType()); + Assert.assertEquals(ErrorCode.USER_ATTRIBUTE_NAME_LENGTH_EXCEED, + event.getAttributes().get(errorCodeKey)); + + Mockito.reset(mockAnalyticsClient); + mockAnalyticsClient.addUserAttribute(invalidName, "value"); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent event1 = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, event1.getEventType()); + Assert.assertEquals(ErrorCode.USER_ATTRIBUTE_NAME_INVALID, + event1.getAttributes().get(errorCodeKey)); + + Mockito.reset(mockAnalyticsClient); + mockAnalyticsClient.addUserAttribute("name01", exceedLengthValue); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent event2 = analyticsEventCaptor.getValue(); + Assert.assertEquals(Event.PresetEvent.CLICKSTREAM_ERROR, event2.getEventType()); + Assert.assertEquals(ErrorCode.USER_ATTRIBUTE_VALUE_LENGTH_EXCEED, + event2.getAttributes().get(errorCodeKey)); } /** * test add user attribute when exceed max number limit. + * + * @throws JSONException the json exception */ @Test - public void testAddUserAttributeWhenExceedNumberLimit() { - for (int i = 0; i < 101; i++) { - analyticsClient.addUserAttribute("name" + i, "value" + i); + public void testAddUserAttributeWhenExceedNumberLimit() throws JSONException { + for (int i = 0; i < 100; i++) { + mockAnalyticsClient.addUserAttribute("name" + i, "value" + i); } - Assert.assertTrue(globalAttributes.containsKey("_error_attribute_size_exceed")); - Assert.assertEquals("attribute name: name99", - Objects.requireNonNull(globalAttributes.get("_error_attribute_size_exceed")).toString()); + verify(mockAnalyticsClient).recordEvent(analyticsEventCaptor.capture()); + AnalyticsEvent event = analyticsEventCaptor.getValue(); + Assert.assertEquals(ErrorCode.USER_ATTRIBUTE_SIZE_EXCEED, event.getAttributes().get(errorCodeKey)); + Assert.assertEquals("attribute name: name99", event.getAttributes().get(errorMessageKey)); } /** @@ -209,9 +263,9 @@ public void testAddUserAttributeWhenExceedNumberLimit() { @Test public void testAddUserAttributeSameNameMultiTimes() throws JSONException { for (int i = 0; i < 101; i++) { - analyticsClient.addUserAttribute("name", "value" + i); + mockAnalyticsClient.addUserAttribute("name", "value" + i); } - Assert.assertFalse(globalAttributes.containsKey("_error_attribute_size_exceed")); + verify(mockAnalyticsClient, never()).createEvent(anyString()); Assert.assertEquals(2, userAttributes.length()); Assert.assertEquals("value100", ((JSONObject) userAttributes.get("name")).get("value")); } diff --git a/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsEventTest.java b/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsEventTest.java index 0be686e..68330c0 100644 --- a/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsEventTest.java +++ b/clickstream/src/test/java/software/aws/solution/clickstream/AnalyticsEventTest.java @@ -29,6 +29,7 @@ import software.aws.solution.clickstream.client.AnalyticsClient; import software.aws.solution.clickstream.client.AnalyticsEvent; import software.aws.solution.clickstream.client.ClickstreamManager; +import software.aws.solution.clickstream.client.Event; @RunWith(RobolectricTestRunner.class) @Config(manifest = Config.NONE) @@ -93,9 +94,11 @@ public void eventAttribute() { /** * test the event attribute reach the limit. + * + * @throws JSONException the json exception */ @Test - public void eventAttributeReachLimit() { + public void eventAttributeReachLimit() throws JSONException { AnalyticsEvent event = analyticsClient.createEvent("testEvent"); for (int i = 1; i < 502; i++) { event.addAttribute("name" + i, "value" + i); @@ -104,9 +107,9 @@ public void eventAttributeReachLimit() { Assert.assertEquals(event.getStringAttribute("name11"), "value11"); Assert.assertEquals(event.getStringAttribute("name500"), "value500"); Assert.assertNull(event.getStringAttribute("name501")); - Assert.assertEquals(event.getCurrentNumOfAttributes(), 501); - Assert.assertTrue(event.hasAttribute("_error_attribute_size_exceed")); - Assert.assertNotNull(event.getStringAttribute("_error_attribute_size_exceed")); + Assert.assertEquals(502, event.getCurrentNumOfAttributes()); + Assert.assertEquals(Event.ErrorCode.ATTRIBUTE_SIZE_EXCEED, + event.getAttributes().get(Event.ReservedAttribute.ERROR_CODE)); } /** diff --git a/clickstream/src/test/java/software/aws/solution/clickstream/EventRecorderTest.java b/clickstream/src/test/java/software/aws/solution/clickstream/EventRecorderTest.java index cca770e..f57f951 100644 --- a/clickstream/src/test/java/software/aws/solution/clickstream/EventRecorderTest.java +++ b/clickstream/src/test/java/software/aws/solution/clickstream/EventRecorderTest.java @@ -24,6 +24,7 @@ import com.github.dreamhead.moco.HttpServer; import com.github.dreamhead.moco.Runner; import org.json.JSONArray; +import org.json.JSONException; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -38,6 +39,7 @@ import software.aws.solution.clickstream.client.ClickstreamConfiguration; import software.aws.solution.clickstream.client.ClickstreamContext; import software.aws.solution.clickstream.client.ClickstreamManager; +import software.aws.solution.clickstream.client.Event; import software.aws.solution.clickstream.client.EventRecorder; import software.aws.solution.clickstream.client.db.ClickstreamDBUtil; import software.aws.solution.clickstream.util.ReflectUtil; @@ -162,16 +164,18 @@ public void testRecordEventForReachedMaxDbSize() throws Exception { /** * test insert single event when exceed attribute number limit. + * @throws JSONException the json exception */ @Test - public void testRecordEventExceedAttributeNumberLimit() { + public void testRecordEventExceedAttributeNumberLimit() throws JSONException { for (int i = 0; i < 501; i++) { event.addAttribute("name" + i, "value" + i); } assertEquals("value499", event.getStringAttribute("name499")); assertFalse(event.hasAttribute("name500")); - assertTrue(event.hasAttribute("_error_attribute_size_exceed")); - assertEquals("attribute name: name500", event.getStringAttribute("_error_attribute_size_exceed")); + assertEquals(Event.ErrorCode.ATTRIBUTE_SIZE_EXCEED, + event.getAttributes().get(Event.ReservedAttribute.ERROR_CODE)); + assertEquals("attribute name: name500", event.getStringAttribute(Event.ReservedAttribute.ERROR_MESSAGE)); } /** @@ -185,7 +189,7 @@ public void testRecordEventAddSameAttributeMultiTimes() { } assertEquals("value500", event.getStringAttribute("name")); Assert.assertEquals(1, event.getCurrentNumOfAttributes()); - assertFalse(event.hasAttribute("_error_attribute_size_exceed")); + assertFalse(event.hasAttribute(Event.ReservedAttribute.ERROR_CODE)); } /**