|
@@ -12,6 +12,7 @@ import com.provectus.kafka.ui.model.SeekType;
|
|
|
import com.provectus.kafka.ui.model.TopicMessage;
|
|
|
import io.confluent.kafka.schemaregistry.ParsedSchema;
|
|
|
import io.confluent.kafka.schemaregistry.avro.AvroSchema;
|
|
|
+import io.confluent.kafka.schemaregistry.json.JsonSchema;
|
|
|
import io.confluent.kafka.schemaregistry.protobuf.ProtobufSchema;
|
|
|
import java.time.Duration;
|
|
|
import java.util.Map;
|
|
@@ -21,8 +22,6 @@ import java.util.function.Consumer;
|
|
|
import lombok.SneakyThrows;
|
|
|
import org.apache.kafka.clients.admin.NewTopic;
|
|
|
import org.apache.kafka.common.TopicPartition;
|
|
|
-import org.junit.Assert;
|
|
|
-import org.junit.jupiter.api.Assertions;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
@@ -81,6 +80,33 @@ public class SendAndReadTests extends AbstractBaseTest {
|
|
|
private static final String PROTOBUF_SCHEMA_JSON_RECORD
|
|
|
= "{ \"f1\" : \"test str\", \"f2\" : 123 }";
|
|
|
|
|
|
+
|
|
|
+ private static final JsonSchema JSON_SCHEMA = new JsonSchema(
|
|
|
+ "{ "
|
|
|
+ + " \"$schema\": \"http://json-schema.org/draft-07/schema#\", "
|
|
|
+ + " \"$id\": \"http://example.com/myURI.schema.json\", "
|
|
|
+ + " \"title\": \"TestRecord\","
|
|
|
+ + " \"type\": \"object\","
|
|
|
+ + " \"additionalProperties\": false,"
|
|
|
+ + " \"properties\": {"
|
|
|
+ + " \"f1\": {"
|
|
|
+ + " \"type\": \"integer\""
|
|
|
+ + " },"
|
|
|
+ + " \"f2\": {"
|
|
|
+ + " \"type\": \"string\""
|
|
|
+ + " },"
|
|
|
+ // it is important special case since there is code in KafkaJsonSchemaSerializer
|
|
|
+ // that checks fields with this name (it should be worked around)
|
|
|
+ + " \"schema\": {"
|
|
|
+ + " \"type\": \"string\""
|
|
|
+ + " }"
|
|
|
+ + " }"
|
|
|
+ + "}"
|
|
|
+ );
|
|
|
+
|
|
|
+ private static final String JSON_SCHEMA_RECORD
|
|
|
+ = "{ \"f1\": 12, \"f2\": \"testJsonSchema1\", \"schema\": \"some txt\" }";
|
|
|
+
|
|
|
@Autowired
|
|
|
private ClusterService clusterService;
|
|
|
|
|
@@ -236,15 +262,14 @@ public class SendAndReadTests extends AbstractBaseTest {
|
|
|
|
|
|
@Test
|
|
|
void valueWithAvroSchemaShouldThrowExceptionArgIsNotValidJsonObject() {
|
|
|
- assertThatThrownBy(() -> {
|
|
|
- new SendAndReadSpec()
|
|
|
- .withValueSchema(AVRO_SCHEMA_2)
|
|
|
- .withMsgToSend(
|
|
|
- new CreateTopicMessage()
|
|
|
- .content("not a json object")
|
|
|
- )
|
|
|
- .doAssert(polled -> Assertions.fail());
|
|
|
- }).hasMessageContaining("Failed to serialize record");
|
|
|
+ new SendAndReadSpec()
|
|
|
+ .withValueSchema(AVRO_SCHEMA_2)
|
|
|
+ .withMsgToSend(
|
|
|
+ new CreateTopicMessage()
|
|
|
+ // f2 has type object instead of string
|
|
|
+ .content("{ \"f1\": 111, \"f2\": {} }")
|
|
|
+ )
|
|
|
+ .assertSendThrowsException();
|
|
|
}
|
|
|
|
|
|
@Test
|
|
@@ -281,15 +306,56 @@ public class SendAndReadTests extends AbstractBaseTest {
|
|
|
|
|
|
@Test
|
|
|
void valueWithProtoSchemaShouldThrowExceptionArgIsNotValidJsonObject() {
|
|
|
- assertThatThrownBy(() -> {
|
|
|
- new SendAndReadSpec()
|
|
|
- .withValueSchema(PROTOBUF_SCHEMA)
|
|
|
- .withMsgToSend(
|
|
|
- new CreateTopicMessage()
|
|
|
- .content("not a json object")
|
|
|
- )
|
|
|
- .doAssert(polled -> Assertions.fail());
|
|
|
- }).hasMessageContaining("Failed to serialize record");
|
|
|
+ new SendAndReadSpec()
|
|
|
+ .withValueSchema(PROTOBUF_SCHEMA)
|
|
|
+ .withMsgToSend(
|
|
|
+ new CreateTopicMessage()
|
|
|
+ // f2 field has type object instead of int
|
|
|
+ .content("{ \"f1\" : \"test str\", \"f2\" : {} }"))
|
|
|
+ .assertSendThrowsException();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void keyWithProtoSchemaValueWithJsonSchema() {
|
|
|
+ new SendAndReadSpec()
|
|
|
+ .withKeySchema(PROTOBUF_SCHEMA)
|
|
|
+ .withValueSchema(JSON_SCHEMA)
|
|
|
+ .withMsgToSend(
|
|
|
+ new CreateTopicMessage()
|
|
|
+ .key(PROTOBUF_SCHEMA_JSON_RECORD)
|
|
|
+ .content(JSON_SCHEMA_RECORD)
|
|
|
+ )
|
|
|
+ .doAssert(polled -> {
|
|
|
+ assertJsonEqual(polled.getKey(), PROTOBUF_SCHEMA_JSON_RECORD);
|
|
|
+ assertJsonEqual(polled.getContent(), JSON_SCHEMA_RECORD);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void keyWithJsonValueWithJsonSchemaKeyValueIsNull() {
|
|
|
+ new SendAndReadSpec()
|
|
|
+ .withKeySchema(JSON_SCHEMA)
|
|
|
+ .withValueSchema(JSON_SCHEMA)
|
|
|
+ .withMsgToSend(
|
|
|
+ new CreateTopicMessage()
|
|
|
+ .key(JSON_SCHEMA_RECORD)
|
|
|
+ )
|
|
|
+ .doAssert(polled -> {
|
|
|
+ assertJsonEqual(polled.getKey(), JSON_SCHEMA_RECORD);
|
|
|
+ assertThat(polled.getContent()).isNull();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void valueWithJsonSchemaThrowsExceptionIfArgIsNotValidJsonObject() {
|
|
|
+ new SendAndReadSpec()
|
|
|
+ .withValueSchema(JSON_SCHEMA)
|
|
|
+ .withMsgToSend(
|
|
|
+ new CreateTopicMessage()
|
|
|
+ // 'f2' field has has type object instead of string
|
|
|
+ .content("{ \"f1\": 12, \"f2\": {}, \"schema\": \"some txt\" }")
|
|
|
+ )
|
|
|
+ .assertSendThrowsException();
|
|
|
}
|
|
|
|
|
|
|
|
@@ -320,7 +386,7 @@ public class SendAndReadTests extends AbstractBaseTest {
|
|
|
}
|
|
|
|
|
|
@SneakyThrows
|
|
|
- public void doAssert(Consumer<TopicMessage> msgAssert) {
|
|
|
+ private String createTopicAndCreateSchemas() {
|
|
|
Objects.requireNonNull(msgToSend);
|
|
|
String topic = UUID.randomUUID().toString();
|
|
|
createTopic(new NewTopic(topic, 1, (short) 1));
|
|
@@ -330,9 +396,23 @@ public class SendAndReadTests extends AbstractBaseTest {
|
|
|
if (valueSchema != null) {
|
|
|
schemaRegistry.schemaRegistryClient().register(topic + "-value", valueSchema);
|
|
|
}
|
|
|
-
|
|
|
// need to update to see new topic & schemas
|
|
|
clustersMetricsScheduler.updateMetrics();
|
|
|
+ return topic;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void assertSendThrowsException() {
|
|
|
+ String topic = createTopicAndCreateSchemas();
|
|
|
+ try {
|
|
|
+ assertThatThrownBy(() -> clusterService.sendMessage(LOCAL, topic, msgToSend).block());
|
|
|
+ } finally {
|
|
|
+ deleteTopic(topic);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @SneakyThrows
|
|
|
+ public void doAssert(Consumer<TopicMessage> msgAssert) {
|
|
|
+ String topic = createTopicAndCreateSchemas();
|
|
|
try {
|
|
|
clusterService.sendMessage(LOCAL, topic, msgToSend).block();
|
|
|
TopicMessage polled = clusterService.getMessages(
|