-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ECO-5139] feat: add action
and serial
fields
#1048
Conversation
WalkthroughThe changes in this pull request introduce new functionality to the Changes
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
d536b10
to
91e85ca
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 4
🧹 Outside diff range and nitpick comments (5)
lib/src/test/java/io/ably/lib/types/MessageTest.java (3)
50-70
: Consider adding edge cases for action fieldWhile the test covers the basic case, consider adding tests for:
- null action
- boundary values of action enum
72-91
: Consider using parameterized tests for MessageAction valuesTo ensure comprehensive coverage of the MessageAction enum, consider using JUnit's Parameterized tests to verify serialization/deserialization of all possible action values.
Example structure:
@ParameterizedTest @EnumSource(MessageAction.class) void deserialize_message_with_different_actions(MessageAction action) { // Test implementation }
49-113
: Consider additional test coverageWhile the current tests provide good coverage of the happy path and some edge cases, consider adding tests for:
- Null values for action and serial fields
- Empty or malformed serial strings
- Boundary conditions for both fields
lib/src/main/java/io/ably/lib/types/BaseMessage.java (1)
Line range hint
1-1
: Consider adding integer field support in serialization methods.Since this PR adds a new integer field (
serial
), theBaseMessage
class should be updated to properly handle integer fields in its serialization methods:
toJsonObject
: Add support for integer field serializationwriteFields
: Add support for integer field serialization in MessagePack formatHere's a suggested implementation:
public static JsonObject toJsonObject(final BaseMessage message) { JsonObject json = new JsonObject(); + // Add support for integer fields + if (message instanceof Message) { + Message msg = (Message) message; + if (msg.serial != null) { + json.addProperty("serial", msg.serial); + } + } // ... existing code ... } void writeFields(MessagePacker packer) throws IOException { + // Add support for integer fields + if (this instanceof Message) { + Message msg = (Message) this; + if (msg.serial != null) { + packer.packString("serial"); + packer.packInt(msg.serial); + } + } // ... existing code ... }lib/src/main/java/io/ably/lib/types/Message.java (1)
66-68
: Enhance the Javadoc comment for theaction
fieldThe Javadoc comment for the
action
field is minimal. Consider providing a more detailed description to clarify its purpose and usage.
🛑 Comments failed to post (4)
lib/src/main/java/io/ably/lib/types/MessageAction.java (1)
12-14: 🛠️ Refactor suggestion
Consider enhancing the utility method.
The method has a few areas for improvement:
- The method should be
public
since it needs to be accessed by theMessage
class for serialization/deserialization- Missing Javadoc documentation
- No validation for negative ordinals
Consider applying these improvements:
- static MessageAction tryFindByOrdinal(int ordinal) { - return values().length <= ordinal ? null: values()[ordinal]; + /** + * Attempts to find a MessageAction by its ordinal value. + * @param ordinal the ordinal value to look up + * @return the corresponding MessageAction or null if not found + */ + public static MessageAction tryFindByOrdinal(int ordinal) { + if (ordinal < 0 || ordinal >= values().length) { + return null; + } + return values()[ordinal]; + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements./** * Attempts to find a MessageAction by its ordinal value. * @param ordinal the ordinal value to look up * @return the corresponding MessageAction or null if not found */ public static MessageAction tryFindByOrdinal(int ordinal) { if (ordinal < 0 || ordinal >= values().length) { return null; } return values()[ordinal]; }
lib/src/test/java/io/ably/lib/types/MessageTest.java (2)
57-57: 💡 Codebase verification
Serial number format should be documented in the Message class
The serial number format (
timestamp-sequence@node:version
) is not documented in the codebase. While the format is being used in tests, there's no clear documentation explaining its structure and requirements. Please add JSDoc comments to theserial
field in the Message class to document:
- The format pattern:
timestamp-sequence@node:version
- The purpose of each component
- Any validation requirements
🔗 Analysis chain
Verify the serial number format documentation
The serial number follows a specific format:
timestamp-sequence@node:version
. Please ensure this format is documented in the Message class or relevant documentation.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for documentation of serial number format rg -l "serial.*format|message.*serial" --type mdLength of output: 63
Script:
#!/bin/bash # Check the content of CHANGELOG.md for serial format documentation rg -A 5 -B 5 "serial.*format|message.*serial" CHANGELOG.md # Also search for serial-related documentation in source files ast-grep --pattern 'class Message { $$$ serial $$$ }' # Look for any comments or documentation about serial format rg "serial.*format|message.*serial" --type javaLength of output: 4262
94-113: 💡 Codebase verification
Add test cases for boundary values of MessageAction
The current test verifies behavior for action=10, but should be expanded to cover:
- Negative values (-1)
- Values at the boundary (6, 7)
- Integer.MAX_VALUE
The behavior is properly implemented in
MessageAction.tryFindByOrdinal()
which returns null for any ordinal >= values().length, but this isn't documented. Add javadoc to:
- Message.action field explaining null handling for invalid values
- MessageAction.tryFindByOrdinal() documenting the null return for out-of-range values
Locations needing documentation:
- lib/src/main/java/io/ably/lib/types/Message.java: action field
- lib/src/main/java/io/ably/lib/types/MessageAction.java: tryFindByOrdinal method
🔗 Analysis chain
Enhance invalid action value testing
The test handles unknown action values well, but consider:
- Adding test cases for other invalid values (negative numbers, Integer.MAX_VALUE)
- Documenting this behavior in the Message class
Let me search for more context about the action field and its documentation.
Let me check the MessageAction enum to understand the valid action values and their documentation.
Let me check the content of the MessageAction enum file to understand the implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for documentation of action field behavior rg -A 5 "action.*field|invalid.*action" --type java lib/src/main/java/io/ably/lib/types/Message.javaLength of output: 321
Script:
#!/bin/bash # Search for action field declaration and related code ast-grep --pattern 'class Message { $$$ action $$$ }' # Search for any javadoc or comments related to action field rg -B 5 "action" --type java lib/src/main/java/io/ably/lib/types/Message.javaLength of output: 2347
Script:
#!/bin/bash # Search for MessageAction enum definition rg -B 5 "enum MessageAction" --type java # Search for tryFindByOrdinal implementation ast-grep --pattern 'tryFindByOrdinal($$$)'Length of output: 308
Script:
#!/bin/bash # Get the content of MessageAction.java cat lib/src/main/java/io/ably/lib/types/MessageAction.javaLength of output: 431
lib/src/main/java/io/ably/lib/types/Message.java (1)
155-156:
⚠️ Potential issueInclude
version
infieldCount
for serializationIn the
writeMsgpack
method, theversion
field is not included in thefieldCount
calculation. This omission may prevent theversion
field from being serialized properly. Please includeversion
in the field count to ensure it is serialized.Apply the following diff to fix the issue:
if(name != null) ++fieldCount; if(extras != null) ++fieldCount; if(serial != null) ++fieldCount; +if(version != null) ++fieldCount; if(action != null) ++fieldCount;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if(serial != null) ++fieldCount; if(version != null) ++fieldCount; if(action != null) ++fieldCount;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (3)
lib/src/test/java/io/ably/lib/types/MessageTest.java (2)
50-70
: Consider adding more test cases for serialization.While the test covers the basic serialization case, consider adding the following test cases for better coverage:
- Different MessageAction values
- Null/empty serial numbers
- Invalid serial number formats
Here's a suggested additional test:
@Test public void serialize_message_with_null_fields() { Message message = new Message("test-name", "test-data"); message.action = null; message.serial = null; JsonElement serializedElement = serializer.serialize(message, null, null); JsonObject serializedObject = serializedElement.getAsJsonObject(); assertNull(serializedObject.get("action")); assertNull(serializedObject.get("serial")); }
94-113
: Enhance error handling test coverage.While the test verifies handling of one unknown action value, consider adding tests for:
- Negative action values
- Action values at type boundaries (Integer.MAX_VALUE)
- Invalid data types for action (string, boolean)
Here's a suggested additional test:
@Test public void deserialize_message_with_invalid_action_type() throws Exception { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("clientId", "test-client-id"); jsonObject.addProperty("action", "invalid_string"); // Invalid type Message message = Message.fromEncoded(jsonObject, new ChannelOptions()); assertNull(message.action); }lib/src/main/java/io/ably/lib/types/Message.java (1)
Line range hint
1-411
: Consider versioning strategy for MessageActionWhile the implementation is solid, consider these architectural points:
- Document the stability guarantee for MessageAction ordinals
- Consider adding a version field to the wire protocol to handle future enum extensions
- Consider using string representations instead of ordinals for better forward compatibility
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
lib/src/main/java/io/ably/lib/types/BaseMessage.java
(1 hunks)lib/src/main/java/io/ably/lib/types/Message.java
(6 hunks)lib/src/main/java/io/ably/lib/types/MessageAction.java
(1 hunks)lib/src/test/java/io/ably/lib/types/MessageTest.java
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- lib/src/main/java/io/ably/lib/types/BaseMessage.java
- lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (6)
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)
72-91
: Document the serial number format requirements.
The test uses a specific format for the serial number (01826232498871-001@abcdefghij:001
), which appears to contain timestamp and sequence information. This format should be documented and validated.
Let's check if there's any documentation about the serial number format:
Consider adding a comment explaining the serial number format and its components:
@Test
public void deserialize_message_with_serial() throws Exception {
+ // Serial number format: <timestamp>-<sequence>@<connection-id>:<message-sequence>
// Given
JsonObject jsonObject = new JsonObject();
lib/src/main/java/io/ably/lib/types/Message.java (5)
49-69
: LGTM! Well-documented field additions
The new fields are thoroughly documented with clear specifications and initialization requirements. The documentation effectively explains the complex logic for version field initialization.
360-364
: LGTM! Clean JSON deserialization implementation
The implementation properly handles null values and uses appropriate helper methods for type conversion.
198-203
: Consider handling invalid action ordinals
The tryFindByOrdinal
result should be validated as it might return null for invalid ordinals.
Let's check the implementation of tryFindByOrdinal:
380-388
: Verify test coverage for serialization edge cases
The serialization logic looks correct, but we should ensure comprehensive test coverage for various combinations of null and non-null values.
Let's check for existing tests:
✅ Verification successful
Test coverage for serialization is adequate
The test coverage for the serialization of serial
, version
, and action
fields is well implemented in MessageTest.java
. Specifically:
- Test case
serialize_message_with_serial
verifies serialization ofserial
andaction
fields - Both positive and negative test cases exist for
action
field (including unknown action values) - Null checks are implicitly tested through
serialize_message_with_name_and_data
which verifies optional fields are not included when null
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Find test files covering Message serialization
fd -e java -e kt --exec rg -l "Message.*[Ss]eriali[sz]" {} \;
Length of output: 1383
Script:
#!/bin/bash
# Check MessageTest.java for specific test cases covering serial, version, and action serialization
rg -A 5 -B 5 "serial|version|action.*serializ" ./lib/src/test/java/io/ably/lib/types/MessageTest.java
# Also check MessageSerializer tests
rg -A 5 -B 5 "serial|version|action.*serializ" ./lib/src/test/java/io/ably/lib/types/MessageSerializer.java
Length of output: 4638
Line range hint 155-178
: Verify MessageAction ordinal stability across versions
The code packs the action as an ordinal integer. This approach requires careful consideration of backward compatibility.
Let's verify the MessageAction enum's stability:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (4)
lib/src/main/java/io/ably/lib/types/Message.java (4)
56-59
: Enhance documentation for theaction
fieldThe documentation for the
action
field is minimal. Consider adding details about:
- The purpose of this field
- Possible values from MessageAction enum
- When this field is expected to be set/used
162-164
: Consider using a more stable enum serialization approachUsing
ordinal()
for enum serialization is risky as it depends on the enum declaration order. If theMessageAction
enum is modified in the future (reordering, inserting new values), it could break message compatibility.Consider using:
- A string representation of the enum value, or
- A dedicated numeric value that doesn't depend on declaration order
345-347
: Consider validating the serial field formatThe
serial
field is read without any validation. If there are expectations about its format (e.g., length, character set), consider adding validation to ensure data integrity.
49-60
: Consider adding unit tests for new fieldsThe implementation of the new
serial
andaction
fields appears complete with proper serialization/deserialization support. To ensure robustness, consider adding unit tests for:
- Serialization/deserialization of both fields in various formats (Msgpack, JSON)
- Edge cases (null values, invalid action ordinals)
- Serial field format validation
- Backward compatibility with messages lacking these fields
Would you like me to help generate comprehensive unit tests for these scenarios?
Also applies to: 145-164, 184-187, 344-347, 363-368
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
lib/src/main/java/io/ably/lib/types/Message.java
(6 hunks)
🔇 Additional comments (1)
lib/src/main/java/io/ably/lib/types/Message.java (1)
184-187
: Verify error handling for invalid action values
Please ensure that MessageAction.tryFindByOrdinal()
properly handles invalid ordinal values. Consider:
- What happens if the ordinal is out of range?
- Should we log a warning when an invalid action is encountered?
✅ Verification successful
Let me try a different approach to find the implementation of MessageAction.tryFindByOrdinal
.
Error handling for invalid action values is properly implemented
The MessageAction.tryFindByOrdinal()
implementation safely handles invalid ordinal values by:
- Returning
null
for out-of-range ordinals (when ordinal >= values length) - Safely accessing valid ordinals through the enum's
values()
array
The calling code in Message.java
also properly handles null
actions, and there's already logging in place for unexpected fields. No additional error handling is needed.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for tryFindByOrdinal implementation and its error handling
ast-grep --pattern 'tryFindByOrdinal($_) {
$$$
}'
Length of output: 53
Script:
#!/bin/bash
# First, let's find the MessageAction enum file
fd MessageAction.java
# Then let's look at its content to find tryFindByOrdinal implementation
rg -A 5 "tryFindByOrdinal" --type java
Length of output: 1614
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to https://github.com/ably/specification/pull/210/files and https://github.com/ably/specification/pull/235/files.
I'm not sure why we didn't address other materialization fields as a part of this PR
e.g. as per TM2k
@(TM2k)@ @serial@ string - an opaque string that uniquely identifies the message. If a message received from Ably (whether over realtime or REST, eg history) with an @action@ of @MESSAGE_CREATE@ does not contain a @serial@, the SDK must set it equal to its @TM2p@ @version@
Seems TM2p version
field is missing
It requires some thinking, more tests and it will be better to implement as part of separate PR |
Sure, but the spec says |
addebf3
to
d730716
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Outside diff range and nitpick comments (5)
lib/src/test/java/io/ably/lib/types/MessageTest.java (3)
50-70
: Consider adding edge cases to the serialization test.While the current test covers the happy path, consider adding test cases for:
- Null action and serial fields
- Empty serial string
- Invalid serial format
Here's a suggested additional test:
@Test public void serialize_message_with_null_fields() { // Given Message message = new Message("test-name", "test-data"); message.action = null; message.serial = null; // When JsonElement serializedElement = serializer.serialize(message, null, null); // Then JsonObject serializedObject = serializedElement.getAsJsonObject(); assertNull(serializedObject.get("action")); assertNull(serializedObject.get("serial")); }
72-91
: Add tests for different JSON formats.Consider adding test cases for:
- JSON with missing optional fields
- Different data types (e.g., numbers as strings)
- Malformed JSON handling
Example test case:
@Test public void deserialize_message_with_missing_optional_fields() throws Exception { // Given JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name", "test-name"); jsonObject.addProperty("data", "test-data"); // When Message message = Message.fromEncoded(jsonObject, new ChannelOptions()); // Then assertNull(message.action); assertNull(message.serial); assertEquals("test-name", message.name); assertEquals("test-data", message.data); }
94-113
: Add boundary tests for action values.The current test only checks one unknown action value (10). Consider adding tests for:
- Negative action values
- Maximum integer value
- Zero value
Example test:
@Test public void deserialize_message_with_boundary_action_values() throws Exception { // Test cases: -1, 0, Integer.MAX_VALUE int[] testValues = {-1, 0, Integer.MAX_VALUE}; for (int actionValue : testValues) { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name", "test-name"); jsonObject.addProperty("action", actionValue); Message message = Message.fromEncoded(jsonObject, new ChannelOptions()); assertNull("Action should be null for value: " + actionValue, message.action); } }lib/src/main/java/io/ably/lib/types/Message.java (1)
Line range hint
155-179
: Remove version-related serialization logicThe serialization logic includes the
version
field which should be removed as per PR objectives. Otherwise, the implementation forserial
andaction
fields is correct.Apply this diff to remove version-related serialization:
if(serial != null) ++fieldCount; - if(version != null) ++fieldCount; if(action != null) ++fieldCount; packer.packMapHeader(fieldCount); super.writeFields(packer); if(name != null) { packer.packString(NAME); packer.packString(name); } if(extras != null) { packer.packString(EXTRAS); extras.write(packer); } if(serial != null) { packer.packString(SERIAL); packer.packString(serial); } - if(version != null) { - packer.packString(VERSION); - packer.packString(version); - } if(action != null) { packer.packString(ACTION); packer.packInt(action.ordinal()); }lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1)
846-849
: Consider adding detailed documentation for version and serial fields.The integration of version and serial fields in the message processing flow is clean and well-placed. However, consider adding more detailed comments explaining:
- The purpose and significance of these fields
- The relationship between version and serial
- Any assumptions or limitations of the format
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (5)
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
(1 hunks)lib/src/main/java/io/ably/lib/types/BaseMessage.java
(1 hunks)lib/src/main/java/io/ably/lib/types/Message.java
(6 hunks)lib/src/main/java/io/ably/lib/types/MessageAction.java
(1 hunks)lib/src/test/java/io/ably/lib/types/MessageTest.java
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- lib/src/main/java/io/ably/lib/types/BaseMessage.java
- lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (3)
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)
49-113
: Addressing previous version field comment.
Based on the PR discussion, the version
field was intentionally removed to focus on essential fields for Chat Beta. The current test implementation correctly reflects this decision by focusing on the action
and serial
fields.
lib/src/main/java/io/ably/lib/types/Message.java (1)
65-68
: Verify MessageAction enum implementation and usage
The code references MessageAction
enum but its implementation is not visible in the provided context. We should verify:
- The enum implementation includes all required action types
- The impact of these changes on message handling throughout the SDK
Let's verify the MessageAction enum implementation and its usage:
✅ Verification successful
Let's gather more information about the MessageAction enum definition since it wasn't found in the previous search:
MessageAction enum implementation is complete and properly used
The MessageAction enum is well-defined in lib/src/main/java/io/ably/lib/types/MessageAction.java
with all required action types:
- MESSAGE_UNSET (0)
- MESSAGE_CREATE (1)
- MESSAGE_UPDATE (2)
- MESSAGE_DELETE (3)
- ANNOTATION_CREATE (4)
- ANNOTATION_DELETE (5)
- META_OCCUPANCY (6)
The enum is properly used in Message class for:
- Deserialization via
tryFindByOrdinal
- Message creation and validation in tests
- Handling message serials with MESSAGE_CREATE action
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Find MessageAction enum definition
echo "=== MessageAction enum definition ==="
ast-grep --pattern 'enum MessageAction {
$$$
}'
# Find all usages of MessageAction
echo -e "\n=== MessageAction usages ==="
rg "MessageAction\." -A 2
Length of output: 1389
Script:
#!/bin/bash
# Search for MessageAction enum definition with a broader pattern
echo "=== MessageAction enum definition ==="
fd MessageAction --exec cat {}
# Search for any references to MESSAGE_CREATE to find potential enum values
echo -e "\n=== MESSAGE_CREATE references ==="
rg "MESSAGE_CREATE" -B 2 -A 2
Length of output: 2536
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1)
846-849
: Consider adding format validation and overflow handling.
The implementation of version and serial fields looks good, but there are a few considerations:
- The version format using
channelSerial:messageIndex
with zero-padded index is clean. - Setting serial equal to version aligns with the PR objectives.
However, consider:
- Adding validation for channelSerial format
- Handling cases where messageIndex exceeds 999 to prevent format issues
Let's verify the channelSerial format across the codebase:
d730716
to
5f0f7df
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (11)
lib/src/test/java/io/ably/lib/types/MessageTest.java (3)
50-70
: Add test cases for edge cases and invalid inputs.While the basic serialization test is good, consider adding test cases for:
- Empty/null serial numbers
- Invalid serial number formats
- Different MessageAction values
Example test case:
@Test public void serialize_message_with_null_serial() { Message message = new Message("test-name", "test-data"); message.action = MessageAction.MESSAGE_CREATE; message.serial = null; JsonElement serialized = serializer.serialize(message, null, null); JsonObject serializedObject = serialized.getAsJsonObject(); assertEquals(1, serializedObject.get("action").getAsInt()); assertNull(serializedObject.get("serial")); }
72-91
: Add tests for JSON structure validation and optional fields.The current test only covers the happy path. Consider adding tests for:
- Missing optional fields in JSON
- Malformed JSON input
- Different data types for fields (e.g., numeric vs string serial)
Example test case:
@Test public void deserialize_message_with_missing_optional_fields() throws Exception { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name", "test-name"); jsonObject.addProperty("data", "test-data"); Message message = Message.fromEncoded(jsonObject, new ChannelOptions()); assertNull(message.action); assertNull(message.serial); }
94-113
: Add boundary tests and document action handling.The test correctly verifies unknown action handling, but consider:
- Testing boundary values (0, negative numbers)
- Adding a comment explaining the null action behavior
- Testing all valid MessageAction enum values
Example test case:
@Test public void deserialize_message_with_boundary_action_values() throws Exception { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("name", "test-name"); // Test negative value jsonObject.addProperty("action", -1); Message message = Message.fromEncoded(jsonObject, new ChannelOptions()); assertNull(message.action); }lib/src/main/java/io/ably/lib/types/Message.java (5)
80-83
: Constants are well-defined but include unnecessary VERSION constantThe constants follow the existing naming pattern and are properly defined. However, the VERSION constant should be removed along with its corresponding field.
private static final String SERIAL = "serial"; - private static final String VERSION = "version"; private static final String ACTION = "action"; private static final String CREATED_AT = "createdAt";
Line range hint
163-192
: Message packing implementation is correct but includes version fieldThe message packing implementation correctly handles the new fields with proper null checks and type conversions. However, version-related packing should be removed.
int fieldCount = super.countFields(); if(name != null) ++fieldCount; if(extras != null) ++fieldCount; if(serial != null) ++fieldCount; - if(version != null) ++fieldCount; if(action != null) ++fieldCount; if(createdAt != null) ++fieldCount; // ... other code ... if(serial != null) { packer.packString(SERIAL); packer.packString(serial); } - if(version != null) { - packer.packString(VERSION); - packer.packString(version); - } if(action != null) { packer.packString(ACTION); packer.packInt(action.ordinal()); }
212-219
: Message unpacking implementation is correct but includes version fieldThe message unpacking implementation correctly handles the new fields with proper type conversions. However, version-related unpacking should be removed.
} else if (fieldName.equals(SERIAL)) { serial = unpacker.unpackString(); - } else if (fieldName.equals(VERSION)) { - version = unpacker.unpackString(); } else if (fieldName.equals(ACTION)) { action = MessageAction.tryFindByOrdinal(unpacker.unpackInt()); } else if (fieldName.equals(CREATED_AT)) { createdAt = unpacker.unpackLong();
376-381
: JSON reading implementation is correct but includes version fieldThe JSON reading implementation correctly handles the new fields with proper helper methods and null handling. However, version-related reading should be removed.
serial = readString(map, SERIAL); - version = readString(map, VERSION); Integer actionOrdinal = readInt(map, ACTION); action = actionOrdinal == null ? null : MessageAction.tryFindByOrdinal(actionOrdinal); createdAt = readLong(map, CREATED_AT);
397-408
: JSON serialization implementation is correct but includes version fieldThe JSON serialization implementation correctly handles the new fields with proper null checks and type conversions. However, version-related serialization should be removed.
if (message.serial != null) { json.addProperty(SERIAL, message.serial); } - if (message.version != null) { - json.addProperty(VERSION, message.version); - } if (message.action != null) { json.addProperty(ACTION, message.action.ordinal()); } if (message.createdAt != null) { json.addProperty(CREATED_AT, message.createdAt); }lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (3)
998-1007
: Consider using a helper method for creating chat messages.The REST API call could be encapsulated in a helper method to improve reusability and readability, especially if more chat-related tests will be added in the future.
+ private void publishChatMessage(AblyRealtime realtime, String roomId, String text) throws AblyException { + JsonObject chatMessage = new JsonObject(); + chatMessage.addProperty("text", text); + realtime.request( + "POST", + "/chat/v2/rooms/" + roomId + "/messages", + new Param[] { new Param("v", 3) }, + HttpUtils.requestBodyFromGson(chatMessage, realtime.options.useBinaryProtocol), + null + ); + }
1009-1011
: Consider adding more specific error messages.The assertion message could be more descriptive to help identify failures more easily.
- assertNull(msgComplete.waitFor(1, 3_000)); + assertNull("Message should be received within 3 seconds", msgComplete.waitFor(1, 3_000));
983-984
: Consider documenting the key permissions.It would be helpful to add a comment explaining what permissions key[5] has, as it's specifically chosen for this test.
+ // Using key[5] which has permissions for chat operations ClientOptions opts = createOptions(testVars.keys[5].keyStr);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (6)
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
(1 hunks)lib/src/main/java/io/ably/lib/types/BaseMessage.java
(1 hunks)lib/src/main/java/io/ably/lib/types/Message.java
(6 hunks)lib/src/main/java/io/ably/lib/types/MessageAction.java
(1 hunks)lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java
(3 hunks)lib/src/test/java/io/ably/lib/types/MessageTest.java
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- lib/src/main/java/io/ably/lib/types/BaseMessage.java
- lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (4)
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)
49-113
: Past comment about version field tests is no longer applicable.
According to the PR objectives, the version
field was intentionally removed to focus on essential fields for Chat Beta. The existing test coverage for action
and serial
fields aligns with the current implementation scope.
lib/src/main/java/io/ably/lib/types/Message.java (1)
49-76
: Field declarations look good, except for the version
field
The field declarations and documentation for serial
, action
, and createdAt
are well-implemented and properly documented with their respective spec references (TM2k, TM2j, TM2o).
The version
field and its documentation should be removed as discussed in the PR objectives.
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (1)
982-996
: LGTM! Well-structured test setup and assertions.
The test method effectively validates the new message fields and their expected values. The assertions are comprehensive and cover all the required fields: serial, version, createdAt, action, and message format.
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java (1)
851-851
:
Ensure createdAt is only set if not provided by server
The current implementation always overwrites createdAt
with timestamp
. According to TM2o spec and the previous review comment, we should only set it if not provided by the server.
Apply this diff to fix the issue:
-if(msg.createdAt == null) msg.createdAt = msg.timestamp;
+if(msg.createdAt == null) msg.createdAt = msg.timestamp;
Likely invalid or redundant comment.
Add 256 bit AES CBC encrypted variable length data generated by Java client library SDK (#49)
5f0f7df
to
0c65aff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (6)
lib/src/test/resources/local/testAppSpec.json (1)
23-25
: Document the purpose of the wildcard capabilityConsider adding a comment in the JSON to explain why this broad capability is needed, particularly in relation to testing the new message actions and serial fields being added in this PR.
{ + "description": "Capability for testing message actions across all channels", "capability": "{ \"[*]*\":[\"*\"] }" }
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)
50-70
: Consider adding edge cases to the serialization test.While the test covers the basic serialization scenario, consider adding test cases for:
- Null values for action and serial fields
- Different MessageAction values besides MESSAGE_CREATE
- Maximum length/special characters in serial field
Example test case:
@Test public void serialize_message_with_null_fields() { Message message = new Message("test-name", "test-data"); message.action = null; message.serial = null; JsonElement serialized = serializer.serialize(message, null, null); JsonObject serializedObject = serialized.getAsJsonObject(); assertNull(serializedObject.get("action")); assertNull(serializedObject.get("serial")); }lib/src/main/java/io/ably/lib/types/Message.java (1)
Line range hint
163-192
: Remove version field from MessagePack serializationRemove version-related serialization logic as the field is being removed.
int fieldCount = super.countFields(); if(name != null) ++fieldCount; if(extras != null) ++fieldCount; if(serial != null) ++fieldCount; - if(version != null) ++fieldCount; if(action != null) ++fieldCount; if(createdAt != null) ++fieldCount; // ... later in the code ... if(serial != null) { packer.packString(SERIAL); packer.packString(serial); } - if(version != null) { - packer.packString(VERSION); - packer.packString(version); - } if(action != null) { packer.packString(ACTION); packer.packInt(action.ordinal()); }lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (3)
978-982
: Add test documentationConsider adding Javadoc to explain the test's purpose, expected behavior, and its relationship to the Chat SDK.
+/** + * Verifies that Chat SDK message fields (serial, action, createdAt) are properly populated + * when receiving messages through the chat API endpoint. + * + * @throws AblyException if test setup or execution fails + */ @Test public void should_have_serial_action_createdAt() throws AblyException {
986-986
: Extract magic strings into constantsConsider extracting the channel name pattern and API endpoint into constants for better maintainability.
+private static final String CHAT_MESSAGES_CHANNEL_PATTERN = "%s::$chat::$chatMessages"; +private static final String CHAT_MESSAGES_ENDPOINT = "/chat/v2/rooms/%s/messages"; -final Channel channel = realtime.channels.get("foo::$chat::$chatMessages"); +final Channel channel = realtime.channels.get(String.format(CHAT_MESSAGES_CHANNEL_PATTERN, "foo")); -"/chat/v2/rooms/foo/messages", +String.format(CHAT_MESSAGES_ENDPOINT, "foo"),Also applies to: 1003-1003
1010-1010
: Extract timeout value into a constantThe 10-second timeout value should be extracted into a named constant for better maintainability.
+private static final long CHAT_MESSAGE_TIMEOUT_MS = 10_000; -assertNull(msgComplete.waitFor(1, 10_000)); +assertNull(msgComplete.waitFor(1, CHAT_MESSAGE_TIMEOUT_MS));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (7)
lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
(2 hunks)lib/src/main/java/io/ably/lib/types/BaseMessage.java
(1 hunks)lib/src/main/java/io/ably/lib/types/Message.java
(6 hunks)lib/src/main/java/io/ably/lib/types/MessageAction.java
(1 hunks)lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java
(3 hunks)lib/src/test/java/io/ably/lib/types/MessageTest.java
(1 hunks)lib/src/test/resources/local/testAppSpec.json
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- lib/src/main/java/io/ably/lib/realtime/ChannelBase.java
- lib/src/main/java/io/ably/lib/types/BaseMessage.java
- lib/src/main/java/io/ably/lib/types/MessageAction.java
🔇 Additional comments (8)
lib/src/test/resources/local/testAppSpec.json (1)
23-25
: Verify the security implications of wildcard permissions
The new capability grants unrestricted access (*
) to all channels in all namespaces ([*]*
). While this is acceptable for testing purposes, we should ensure this configuration is only used in test environments.
✅ Verification successful
Wildcard permissions are safely confined to test environment
The verification confirms that:
- The wildcard capability pattern
[*]*
with*
permissions only exists intestAppSpec.json
- This file is exclusively used in test contexts:
- Located in
test/resources/local/
directory - Only referenced by test setup code (
Setup.java
) and test build script - No usage found in production or example code
- Located in
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that this wildcard capability is only used in test configurations
# and not in production code or examples
# Check if similar wildcard patterns exist in non-test files
rg -g '!test*' -g '!*.test.*' -l '\[\*\]\*.*\*'
# Check if this file is referenced outside of test code
rg -g '!test*' -g '!*.test.*' 'testAppSpec.json'
Length of output: 98
Script:
#!/bin/bash
# Let's try a different approach to verify the security implications:
# 1. Find all JSON files that might contain capability configurations
fd -e json
# 2. Search for wildcard patterns in all JSON files
rg -t json '\[\*\]\*.*\*' -C 2
# 3. Check if testAppSpec.json is referenced anywhere in the codebase
rg "testAppSpec\.json"
Length of output: 747
lib/src/test/java/io/ably/lib/types/MessageTest.java (1)
94-113
: Address integration testing requirements.
While this unit test properly handles unknown actions, there are two pending items from the PR discussion:
- Integration tests for inbound message handling were requested
- If version field is planned for future implementation, we should document this requirement
Let's check if there are any existing integration tests:
Consider creating a separate integration test class (e.g., MessageIntegrationTest
) to verify the end-to-end behavior of these fields in a real connection scenario.
lib/src/main/java/io/ably/lib/types/Message.java (4)
56-64
: Remove version field and documentation
The version field should be removed as per PR objectives to focus on essential fields for Chat Beta.
376-381
:
Implement missing serial field requirement and remove version
- Remove version-related deserialization
- Implement the spec requirement: "if MESSAGE_CREATE does not contain a serial, set it equal to its version"
serial = readString(map, SERIAL);
- version = readString(map, VERSION);
Integer actionOrdinal = readInt(map, ACTION);
action = actionOrdinal == null ? null : MessageAction.tryFindByOrdinal(actionOrdinal);
+ // Set serial equal to version for MESSAGE_CREATE action when serial is missing
+ if (serial == null && action == MessageAction.MESSAGE_CREATE) {
+ serial = version;
+ }
createdAt = readLong(map, CREATED_AT);
Likely invalid or redundant comment.
397-408
: 🛠️ Refactor suggestion
Remove version field from JSON serialization
Remove version-related serialization logic as the field is being removed.
if (message.serial != null) {
json.addProperty(SERIAL, message.serial);
}
- if (message.version != null) {
- json.addProperty(VERSION, message.version);
- }
if (message.action != null) {
json.addProperty(ACTION, message.action.ordinal());
}
Likely invalid or redundant comment.
212-219
: 🛠️ Refactor suggestion
Remove version field from MessagePack deserialization
Remove version-related deserialization logic as the field is being removed.
} else if (fieldName.equals(SERIAL)) {
serial = unpacker.unpackString();
- } else if (fieldName.equals(VERSION)) {
- version = unpacker.unpackString();
} else if (fieldName.equals(ACTION)) {
action = MessageAction.tryFindByOrdinal(unpacker.unpackInt());
} else if (fieldName.equals(CREATED_AT)) {
createdAt = unpacker.unpackLong();
Likely invalid or redundant comment.
lib/src/test/java/io/ably/lib/test/realtime/RealtimeMessageTest.java (2)
6-7
: LGTM: Required imports added for new test
The new imports are necessary and properly used in the new test method.
Also applies to: 22-22
988-996
: Consider adding error case verification
The test only verifies the success path. Consider adding assertions for error cases such as:
- Invalid message format
- Missing required fields
- Invalid action types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lgtm
Add
action
andserial
fields to the message object for the Chat SDKSummary by CodeRabbit
New Features
serial
,version
,action
,createdAt
) to the Message class for enhanced message details.MessageAction
) to represent various message actions.Bug Fixes
Tests