-
Notifications
You must be signed in to change notification settings - Fork 253
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
KAFKA-165: Add change.stream.show.expanded.events property #172
Changes from all commits
30b5a9d
91b5f12
cec8de5
3df7a73
705a448
eb2ff49
9c6df56
bc0d5df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ | |
|
||
import java.time.Instant; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Locale; | ||
|
@@ -1053,6 +1054,144 @@ void testFullDocumentBeforeChange() { | |
} | ||
} | ||
|
||
@Test | ||
@DisplayName("Ensure disambiguatedPaths exist when showExpandedEvents is true") | ||
void testDisambiguatedPathsExistWhenShowExpandedEventsIsTrue() { | ||
assumeTrue(isAtLeastSevenDotZero()); | ||
MongoDatabase db = getDatabaseWithPostfix(); | ||
try (AutoCloseableSourceTask task = createSourceTask()) { | ||
MongoCollection<Document> coll = db.getCollection("coll"); | ||
coll.drop(); | ||
db.createCollection(coll.getNamespace().getCollectionName(), new CreateCollectionOptions()); | ||
HashMap<String, String> cfg = new HashMap<>(); | ||
cfg.put( | ||
MongoSourceConfig.OUTPUT_FORMAT_VALUE_CONFIG, | ||
OutputFormat.SCHEMA.name().toLowerCase(Locale.ROOT)); | ||
cfg.put(MongoSourceConfig.SHOW_EXPANDED_EVENTS_CONFIG, "true"); | ||
task.start(cfg); | ||
int id = 0; | ||
Document expected = new Document("_id", id); | ||
coll.insertOne(expected); | ||
coll.updateOne(Filters.eq(id), Document.parse("{ $set: { foo: 1 } }")); | ||
coll.deleteOne(Filters.eq(id)); | ||
List<SourceRecord> records = getNextResults(task); | ||
assertEquals(3, records.size()); | ||
Struct update = (Struct) records.get(1).value(); | ||
assertEquals(OperationType.UPDATE.getValue(), update.getString("operationType")); | ||
Struct updateDescription = (Struct) update.get("updateDescription"); | ||
assertEquals("{}", updateDescription.getString("disambiguatedPaths")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you might have already mentioned this offline, but why aren't we checking that it contains the expected fields similar to this example? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah this is because I wasn't able to produce disambiguatedPaths results because trying to update a field with a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to take another look at this to make sure I wasn't missing something obvious 😄 |
||
} finally { | ||
db.drop(); | ||
} | ||
} | ||
|
||
@Test | ||
@DisplayName("Ensure disambiguatedPaths don't exist when showExpandedEvents is false") | ||
void testDisambiguatedPathsDontExistWhenShowExpandedEventsIsTrue() { | ||
assumeTrue(isAtLeastSevenDotZero()); | ||
MongoDatabase db = getDatabaseWithPostfix(); | ||
try (AutoCloseableSourceTask task = createSourceTask()) { | ||
MongoCollection<Document> coll = db.getCollection("coll"); | ||
coll.drop(); | ||
db.createCollection(coll.getNamespace().getCollectionName(), new CreateCollectionOptions()); | ||
HashMap<String, String> cfg = new HashMap<>(); | ||
cfg.put( | ||
MongoSourceConfig.OUTPUT_FORMAT_VALUE_CONFIG, | ||
OutputFormat.SCHEMA.name().toLowerCase(Locale.ROOT)); | ||
cfg.put(MongoSourceConfig.SHOW_EXPANDED_EVENTS_CONFIG, "false"); | ||
task.start(cfg); | ||
int id = 0; | ||
Document expected = new Document("_id", id); | ||
coll.insertOne(expected); | ||
coll.updateOne(Filters.eq(id), Document.parse("{ $set: { foo: 1 } }")); | ||
coll.deleteOne(Filters.eq(id)); | ||
List<SourceRecord> records = getNextResults(task); | ||
assertEquals(3, records.size()); | ||
Struct update = (Struct) records.get(1).value(); | ||
assertEquals(OperationType.UPDATE.getValue(), update.getString("operationType")); | ||
Struct updateDescription = (Struct) update.get("updateDescription"); | ||
assertNull(updateDescription.getString("disambiguatedPaths")); | ||
} finally { | ||
db.drop(); | ||
} | ||
} | ||
|
||
@Test | ||
@DisplayName("Ensure disambiguatedPaths don't exist by default") | ||
void testDisambiguatedPathsDontExistByDefault() { | ||
assumeTrue(isAtLeastSevenDotZero()); | ||
MongoDatabase db = getDatabaseWithPostfix(); | ||
try (AutoCloseableSourceTask task = createSourceTask()) { | ||
MongoCollection<Document> coll = db.getCollection("coll"); | ||
coll.drop(); | ||
db.createCollection(coll.getNamespace().getCollectionName(), new CreateCollectionOptions()); | ||
HashMap<String, String> cfg = new HashMap<>(); | ||
cfg.put( | ||
MongoSourceConfig.OUTPUT_FORMAT_VALUE_CONFIG, | ||
OutputFormat.SCHEMA.name().toLowerCase(Locale.ROOT)); | ||
task.start(cfg); | ||
int id = 0; | ||
Document expected = new Document("_id", id); | ||
coll.insertOne(expected); | ||
coll.updateOne(Filters.eq(id), Document.parse("{ $set: { foo: 1 } }")); | ||
coll.deleteOne(Filters.eq(id)); | ||
List<SourceRecord> records = getNextResults(task); | ||
assertEquals(3, records.size()); | ||
Struct update = (Struct) records.get(1).value(); | ||
assertEquals(OperationType.UPDATE.getValue(), update.getString("operationType")); | ||
Struct updateDescription = (Struct) update.get("updateDescription"); | ||
assertNull(updateDescription.getString("disambiguatedPaths")); | ||
} finally { | ||
db.drop(); | ||
} | ||
} | ||
|
||
@Test | ||
@DisplayName("Ensure truncatedArrays works") | ||
void testTruncatedArrays() { | ||
assumeTrue(isAtLeastSixDotZero()); | ||
MongoDatabase db = getDatabaseWithPostfix(); | ||
try (AutoCloseableSourceTask task = createSourceTask()) { | ||
MongoCollection<Document> coll = db.getCollection("coll"); | ||
coll.drop(); | ||
db.createCollection(coll.getNamespace().getCollectionName(), new CreateCollectionOptions()); | ||
HashMap<String, String> cfg = new HashMap<>(); | ||
cfg.put( | ||
MongoSourceConfig.OUTPUT_FORMAT_VALUE_CONFIG, | ||
OutputFormat.SCHEMA.name().toLowerCase(Locale.ROOT)); | ||
task.start(cfg); | ||
int id = 0; | ||
Document expected = | ||
new Document("_id", id) | ||
.append("items", Arrays.asList(2, 30, 5, 10, 11, 100, 200, 250, 300, 5, 600)); | ||
coll.insertOne(expected); | ||
coll.updateOne( | ||
Filters.eq(id), | ||
singletonList(Document.parse("{ $set: { items: [2,30,5,10,11,100,200,250,300,5] } }"))); | ||
coll.deleteOne(Filters.eq(id)); | ||
List<SourceRecord> records = getNextResults(task); | ||
assertEquals(3, records.size()); | ||
Struct update = (Struct) records.get(1).value(); | ||
assertEquals(OperationType.UPDATE.getValue(), update.getString("operationType")); | ||
Struct updateDescription = (Struct) update.get("updateDescription"); | ||
|
||
Schema schema = | ||
SchemaBuilder.struct() | ||
.name("truncatedArray") | ||
.field("field", Schema.STRING_SCHEMA) | ||
.field("newSize", Schema.INT32_SCHEMA) | ||
.build(); | ||
|
||
Struct truncatedArrayStruct = new Struct(schema).put("field", "items").put("newSize", 10); | ||
|
||
List<Struct> expectedTruncatedArray = new ArrayList<>(); | ||
expectedTruncatedArray.add(truncatedArrayStruct); | ||
assertEquals(expectedTruncatedArray, updateDescription.getArray("truncatedArrays")); | ||
} finally { | ||
db.drop(); | ||
} | ||
} | ||
|
||
/** | ||
* We insert a document into a collection before starting the {@link MongoSourceTask}, yet we | ||
* observe the change due to specifying {@link | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,7 +52,12 @@ class UpdateTest { | |
+ " updatedFields: {" | ||
+ " email: 'alice@10gen.com'" | ||
+ " }," | ||
+ " removedFields: ['phoneNumber']" | ||
+ " removedFields: ['phoneNumber']," | ||
+ " truncatedArrays: [{ field: 'foo', newSize: 1 }]," | ||
+ " disambiguatedPaths: {" | ||
+ " 'home.town': [ 'home.town' ]," | ||
+ " 'residences.0.0': [ 'residences', 0, '0' ]" | ||
+ " }" | ||
+ " }," | ||
+ " fullDocument: {" | ||
+ " _id: ObjectId(\"58a4eb4a30c75625e00d2820\")," | ||
|
@@ -148,7 +153,7 @@ void testMissingChangeEventData() { | |
new SinkDocument( | ||
null, | ||
BsonDocument.parse( | ||
"{documentKey: {}, updateDescription: {updatedFields: 1}}")))), | ||
"{documentKey: {}, updateDescription: {updatedFields: 1, removedFields: []}}")))), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [q] what's the reason for changing this test? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you were to adjust updatedFields to a valid value, the test would still fail because removedFields is a required field. This more closely matches the expected behavior of validating updatedFields instead of failing due to another reason. |
||
() -> | ||
assertThrows( | ||
DataException.class, | ||
|
@@ -157,7 +162,25 @@ void testMissingChangeEventData() { | |
new SinkDocument( | ||
null, | ||
BsonDocument.parse( | ||
"{documentKey: {}, updateDescription: {removedFields: 1}}")))), | ||
"{documentKey: {}, updateDescription: {updatedFields: {}, removedFields: 1}}")))), | ||
() -> | ||
assertThrows( | ||
DataException.class, | ||
() -> | ||
UPDATE.perform( | ||
new SinkDocument( | ||
null, | ||
BsonDocument.parse( | ||
"{documentKey: {}, updateDescription: {updatedFields: {}, removedFields: [], truncatedArrays: 1}}")))), | ||
() -> | ||
assertThrows( | ||
DataException.class, | ||
() -> | ||
UPDATE.perform( | ||
new SinkDocument( | ||
null, | ||
BsonDocument.parse( | ||
"{documentKey: {}, updateDescription: {updatedFields: {}, removedFields: [], disambiguatedPaths: 1}}")))), | ||
() -> | ||
assertThrows( | ||
DataException.class, | ||
|
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.
[q] thoughts on adding integration tests against different major versions? It looks like we're missing 6 and 7.
This can be done as part of a separate ticket.
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.
Yeah that's a good idea, I added this ticket to the backlog.