diff --git a/doc/changes/changes_18.0.2.md b/doc/changes/changes_18.0.2.md
index 00a63aaa..6beddc6c 100644
--- a/doc/changes/changes_18.0.2.md
+++ b/doc/changes/changes_18.0.2.md
@@ -20,6 +20,7 @@ Code name: Improve code quality
* #311: Fixed metadata parsing and conversion diagnostics for missing JSON fields and nullable notes/comments, and made `SqlFunctionScalarCast` tolerate a null argument consistently with related SQL AST nodes.
* #310: Fixed `SqlStatementSelect.Builder.build()` so empty and partial builders no longer fail with a raw `NullPointerException`.
* #309: Fixed the `SqlNodeVisitor` API documentation and parameter names for `SqlPredicateIsNotNull` and `SqlPredicateIsNull`.
+* #317: Applied small allocation cleanups in request parsing, logging timestamp formatting, and schema metadata JSON conversion.
* #308: Fixed `SqlLimit` so `limit` and `offset` stay non-negative for the full object lifetime by making the node immutable and aligning the validation message with the accepted zero values.
* #307: Fixed `PushdownSqlRenderer` so `HASHTYPE` data types include `bytesize` in rendered pushdown SQL JSON.
* #312: Fixed logging utility resource and handler lifecycle issues by closing version metadata streams, falling back when the thread context class loader is missing, defaulting absent version properties to `UNKNOWN`, closing replaced root log handlers, and resetting closed remote socket handlers before reuse.
diff --git a/src/main/java/com/exasol/adapter/metadata/converter/SchemaMetadataJsonConverter.java b/src/main/java/com/exasol/adapter/metadata/converter/SchemaMetadataJsonConverter.java
index 24e35abe..99aabf61 100644
--- a/src/main/java/com/exasol/adapter/metadata/converter/SchemaMetadataJsonConverter.java
+++ b/src/main/java/com/exasol/adapter/metadata/converter/SchemaMetadataJsonConverter.java
@@ -53,6 +53,7 @@ public final class SchemaMetadataJsonConverter {
private static final String COMMENT_KEY = "comment";
private static final String IDENTITY_KEY = "isIdentity";
private static final String DEFAULT_KEY = "default";
+ private static final String COLUMNS_KEY = "columns";
private final JsonBuilderFactory factory = Json.createBuilderFactory(Collections.emptyMap());
/**
@@ -94,7 +95,7 @@ private JsonObjectBuilder convertTableMetadata(final TableMetadata table) {
final JsonObjectBuilder tableBuilder = this.factory.createObjectBuilder();
tableBuilder.add(TYPE_KEY, "table");
tableBuilder.add(TABLE_NAME_KEY, table.getName());
- final JsonArrayBuilder columnsBuilder = Json.createArrayBuilder();
+ final JsonArrayBuilder columnsBuilder = this.factory.createArrayBuilder();
for (final ColumnMetadata column : table.getColumns()) {
columnsBuilder.add(convertColumnMetadata(column));
}
@@ -104,7 +105,7 @@ private JsonObjectBuilder convertTableMetadata(final TableMetadata table) {
if (table.hasComment()) {
tableBuilder.add(COMMENT_KEY, table.getComment());
}
- tableBuilder.add("columns", columnsBuilder);
+ tableBuilder.add(COLUMNS_KEY, columnsBuilder);
return tableBuilder;
}
diff --git a/src/main/java/com/exasol/adapter/request/parser/AbstractRequestParser.java b/src/main/java/com/exasol/adapter/request/parser/AbstractRequestParser.java
index 57f51962..acef10f6 100644
--- a/src/main/java/com/exasol/adapter/request/parser/AbstractRequestParser.java
+++ b/src/main/java/com/exasol/adapter/request/parser/AbstractRequestParser.java
@@ -2,8 +2,7 @@
import static com.exasol.adapter.request.parser.RequestParserConstants.PROPERTIES_KEY;
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
+import java.io.StringReader;
import java.util.*;
import java.util.Map.Entry;
@@ -27,9 +26,7 @@ class AbstractRequestParser {
* @return JSON reader
*/
protected JsonReader createJsonReader(final String rawRequest) {
- final ByteArrayInputStream rawRequestStream = new ByteArrayInputStream(
- rawRequest.getBytes(StandardCharsets.UTF_8));
- return Json.createReader(rawRequestStream);
+ return Json.createReader(new StringReader(rawRequest));
}
/**
diff --git a/src/main/java/com/exasol/adapter/response/converter/ResponseJsonConverter.java b/src/main/java/com/exasol/adapter/response/converter/ResponseJsonConverter.java
index 5f5a3cb8..2859e333 100644
--- a/src/main/java/com/exasol/adapter/response/converter/ResponseJsonConverter.java
+++ b/src/main/java/com/exasol/adapter/response/converter/ResponseJsonConverter.java
@@ -1,5 +1,7 @@
package com.exasol.adapter.response.converter;
+import static java.util.Collections.emptyMap;
+
import com.exasol.adapter.capabilities.*;
import com.exasol.adapter.metadata.converter.SchemaMetadataJsonConverter;
import com.exasol.adapter.response.*;
@@ -16,6 +18,7 @@ public final class ResponseJsonConverter {
private static final String LITERAL_PREFIX = "LITERAL_";
private static final String SCHEMA_METADATA = "schemaMetadata";
private static final ResponseJsonConverter responseJsonConverter = new ResponseJsonConverter();
+ private final JsonBuilderFactory factory = Json.createBuilderFactory(emptyMap());
private ResponseJsonConverter() {
}
@@ -37,7 +40,7 @@ public static ResponseJsonConverter getInstance() {
*/
@SuppressWarnings("squid:S1172")
public String convertDropVirtualSchemaResponse(final DropVirtualSchemaResponse dropResponse) {
- return Json.createObjectBuilder() //
+ return this.factory.createObjectBuilder() //
.add("type", "dropVirtualSchema") //
.build() //
.toString();
@@ -50,7 +53,7 @@ public String convertDropVirtualSchemaResponse(final DropVirtualSchemaResponse d
* @return string representation of a JSON Object
*/
public String convertCreateVirtualSchemaResponse(final CreateVirtualSchemaResponse createResponse) {
- return Json.createObjectBuilder() //
+ return this.factory.createObjectBuilder() //
.add("type", "createVirtualSchema") //
.add(SCHEMA_METADATA,
SchemaMetadataJsonConverter.getInstance().convert(createResponse.getSchemaMetadata())) //
@@ -65,7 +68,7 @@ public String convertCreateVirtualSchemaResponse(final CreateVirtualSchemaRespon
* @return string representation of a JSON Object
*/
public String convertPushDownResponse(final PushDownResponse pushDownResponse) {
- return Json.createObjectBuilder() //
+ return this.factory.createObjectBuilder() //
.add("type", "pushdown") //
.add("sql", pushDownResponse.getPushDownSql()) //
.build() //
@@ -79,8 +82,8 @@ public String convertPushDownResponse(final PushDownResponse pushDownResponse) {
* @return string representation of a JSON Object
*/
public String convertGetCapabilitiesResponse(final GetCapabilitiesResponse getCapabilitiesResponse) {
- final JsonObjectBuilder builder = Json.createObjectBuilder().add("type", "getCapabilities");
- final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ final JsonObjectBuilder builder = this.factory.createObjectBuilder().add("type", "getCapabilities");
+ final JsonArrayBuilder arrayBuilder = this.factory.createArrayBuilder();
final Capabilities capabilities = getCapabilitiesResponse.getCapabilities();
addMainCapabilitiesToBuilder(capabilities, arrayBuilder);
addScalarFunctionCapabilitiesToBuilder(capabilities, arrayBuilder);
@@ -136,7 +139,7 @@ private void addMainCapabilitiesToBuilder(final Capabilities capabilities, final
* @return string representation of a JSON Object
*/
public String convertRefreshResponse(final RefreshResponse refreshResponse) {
- return Json.createObjectBuilder() //
+ return this.factory.createObjectBuilder() //
.add("type", "refresh") //
.add(SCHEMA_METADATA,
SchemaMetadataJsonConverter.getInstance().convert(refreshResponse.getSchemaMetadata())) //
@@ -151,7 +154,7 @@ public String convertRefreshResponse(final RefreshResponse refreshResponse) {
* @return string representation of a JSON Object
*/
public String convertSetPropertiesResponse(final SetPropertiesResponse setPropertiesResponse) {
- final JsonObjectBuilder builder = Json.createObjectBuilder();
+ final JsonObjectBuilder builder = this.factory.createObjectBuilder();
builder.add("type", "setProperties");
if (setPropertiesResponse.getSchemaMetadata() != null) {
builder.add(SCHEMA_METADATA,
diff --git a/src/main/java/com/exasol/logging/CompactFormatter.java b/src/main/java/com/exasol/logging/CompactFormatter.java
index d1fa0ea7..5347d2c3 100644
--- a/src/main/java/com/exasol/logging/CompactFormatter.java
+++ b/src/main/java/com/exasol/logging/CompactFormatter.java
@@ -3,7 +3,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Instant;
-import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
@@ -13,7 +13,8 @@
*/
public class CompactFormatter extends Formatter {
private static final String LOG_LEVEL_FORMAT = "%-8s";
- private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
+ private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
+ .withZone(ZoneOffset.UTC);
/**
* Formats a log record according in a compact manner.
@@ -24,14 +25,14 @@ public class CompactFormatter extends Formatter {
* yyyy-MM-dd HH:mm:ss.SSS LEVEL [c.e.ClassName] The message.
*/
@Override
- public String format(final LogRecord record) {
+ public String format(final LogRecord logRecord) {
final StringBuilder builder = new StringBuilder();
- builder.append(formatTimestamp(record.getMillis()));
+ builder.append(formatTimestamp(logRecord.getMillis()));
builder.append(" ");
- builder.append(String.format(LOG_LEVEL_FORMAT, record.getLevel()));
- appendClassName(record.getSourceClassName(), builder);
- builder.append(formatMessage(record));
- formatException(record, builder);
+ builder.append(String.format(LOG_LEVEL_FORMAT, logRecord.getLevel()));
+ appendClassName(logRecord.getSourceClassName(), builder);
+ builder.append(formatMessage(logRecord));
+ formatException(logRecord, builder);
builder.append(System.lineSeparator());
return builder.toString();
}
@@ -61,11 +62,11 @@ private void appendNonEmptyClassName(final String className, final StringBuilder
private String formatTimestamp(final long millis) {
final Instant instant = Instant.ofEpochMilli(millis);
- return this.dateTimeFormatter.format(instant.atZone(ZoneId.of("Z")));
+ return this.dateTimeFormatter.format(instant);
}
- private void formatException(final LogRecord record, final StringBuilder builder) {
- final Throwable thrown = record.getThrown();
+ private void formatException(final LogRecord logRecord, final StringBuilder builder) {
+ final Throwable thrown = logRecord.getThrown();
if (thrown != null) {
builder.append("\n\t");
final StringWriter errors = new StringWriter();
@@ -73,4 +74,4 @@ private void formatException(final LogRecord record, final StringBuilder builder
builder.append(errors);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/com/exasol/adapter/request/parser/RequestParserTest.java b/src/test/java/com/exasol/adapter/request/parser/RequestParserTest.java
index 25d4abab..c11c1c92 100644
--- a/src/test/java/com/exasol/adapter/request/parser/RequestParserTest.java
+++ b/src/test/java/com/exasol/adapter/request/parser/RequestParserTest.java
@@ -64,6 +64,17 @@ void setPropertiesRequest() {
() -> assertThat(properties, hasEntry(equalTo("NULL_value"), equalTo(null))));
}
+ @Test
+ void setPropertiesRequestPreservesUtf8Characters() {
+ final String rawRequest = JsonEntry.object(
+ entry("type", "setProperties"),
+ entry("properties", object(entry("CITY", "München"))),
+ SCHEMA_METADATA_INFO).render();
+ final AdapterRequest request = this.parser.parse(rawRequest);
+ final Map properties = ((SetPropertiesRequest) request).getProperties();
+ assertThat(properties, hasEntry(equalTo("CITY"), equalTo("München")));
+ }
+
@Test
void unsupportedPropertyType() {
final String rawRequest = JsonEntry.object(//
@@ -157,4 +168,4 @@ private JsonParent createPushDownRequest(final JsonEntry selectListDataTypes) {
)))))))), //
SCHEMA_METADATA_INFO);
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/com/exasol/adapter/request/parser/TablesMetadataParserTest.java b/src/test/java/com/exasol/adapter/request/parser/TablesMetadataParserTest.java
index bd8013bf..a62469e0 100644
--- a/src/test/java/com/exasol/adapter/request/parser/TablesMetadataParserTest.java
+++ b/src/test/java/com/exasol/adapter/request/parser/TablesMetadataParserTest.java
@@ -10,8 +10,7 @@
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
@@ -24,6 +23,8 @@
import jakarta.json.*;
class TablesMetadataParserTest {
+ private static final JsonBuilderFactory JSON = Json.createBuilderFactory(Collections.emptyMap());
+
@Test
void testParseMetadata() throws IOException {
final List tableColumns = new ArrayList<>();
@@ -126,17 +127,25 @@ private List createExpectedTableMetadata() {
return expectedInvolvedTablesMetadata;
}
+ private static JsonArrayBuilder arrayBuilder() {
+ return JSON.createArrayBuilder();
+ }
+
+ private static JsonObjectBuilder objectBuilder() {
+ return JSON.createObjectBuilder();
+ }
+
@Test
void testParseColumnMetadataUsesBooleanDefaults() {
- final JsonArray tablesAsJson = Json.createArrayBuilder().add(Json.createObjectBuilder()
+ final JsonArray tablesAsJson = arrayBuilder().add(objectBuilder()
.add("name", "T1")
- .add("columns", Json.createArrayBuilder()
- .add(Json.createObjectBuilder().add("name", "DEFAULTS")
- .add("dataType", Json.createObjectBuilder().add("type", "DECIMAL").add("precision", 18)
+ .add("columns", arrayBuilder()
+ .add(objectBuilder().add("name", "DEFAULTS")
+ .add("dataType", objectBuilder().add("type", "DECIMAL").add("precision", 18)
.add("scale", 0)))
- .add(Json.createObjectBuilder().add("name", "EXPLICIT_VALUES").add("isNullable", false)
+ .add(objectBuilder().add("name", "EXPLICIT_VALUES").add("isNullable", false)
.add("isIdentity", true)
- .add("dataType", Json.createObjectBuilder().add("type", "DECIMAL").add("precision", 18)
+ .add("dataType", objectBuilder().add("type", "DECIMAL").add("precision", 18)
.add("scale", 0)))))
.build();
@@ -155,18 +164,18 @@ void testParseColumnMetadataUsesBooleanDefaults() {
@Test
void testParseMetadataReadsAdapterNotes() {
- final JsonArray tablesAsJson = Json.createArrayBuilder().add(Json.createObjectBuilder()
+ final JsonArray tablesAsJson = arrayBuilder().add(objectBuilder()
.add("name", "T1")
- .add("adapterNotes", Json.createObjectBuilder().add("table", true))
- .add("columns", Json.createArrayBuilder()
- .add(Json.createObjectBuilder().add("name", "C1")
+ .add("adapterNotes", objectBuilder().add("table", true))
+ .add("columns", arrayBuilder()
+ .add(objectBuilder().add("name", "C1")
.add("adapterNotes", "column notes")
- .add("dataType", Json.createObjectBuilder().add("type", "BOOLEAN")))
- .add(Json.createObjectBuilder().add("name", "C2")
- .add("adapterNotes", Json.createObjectBuilder().add("nested", 1))
- .add("dataType", Json.createObjectBuilder().add("type", "DATE")))
- .add(Json.createObjectBuilder().add("name", "C3")
- .add("dataType", Json.createObjectBuilder().add("type", "DOUBLE")))))
+ .add("dataType", objectBuilder().add("type", "BOOLEAN")))
+ .add(objectBuilder().add("name", "C2")
+ .add("adapterNotes", objectBuilder().add("nested", 1))
+ .add("dataType", objectBuilder().add("type", "DATE")))
+ .add(objectBuilder().add("name", "C3")
+ .add("dataType", objectBuilder().add("type", "DOUBLE")))))
.build();
final List tables = TablesMetadataParser.create().parse(tablesAsJson);
@@ -193,50 +202,50 @@ void testParseMetadataThrowsException(final JsonArray tablesAsJson,
private static Stream invalidTableMetadata() {
return Stream.of(
- Arguments.of(Json.createArrayBuilder().add(Json.createObjectBuilder().add("name", "T1")).build(),
+ Arguments.of(arrayBuilder().add(objectBuilder().add("name", "T1")).build(),
"E-VSCOMJAVA-44: Failed to parse 'table 'T1'' because mandatory field 'columns' is missing."),
- Arguments.of(Json.createArrayBuilder().add(Json.createObjectBuilder()
+ Arguments.of(arrayBuilder().add(objectBuilder()
.add("name", "T1")
- .add("columns", Json.createArrayBuilder()
- .add(Json.createObjectBuilder()
- .add("dataType", Json.createObjectBuilder().add("type", "DECIMAL")
+ .add("columns", arrayBuilder()
+ .add(objectBuilder()
+ .add("dataType", objectBuilder().add("type", "DECIMAL")
.add("precision", 18).add("scale", 0)))))
.build(),
"E-VSCOMJAVA-44: Failed to parse 'column #0 of table 'T1'' because mandatory field 'name' is missing."),
- Arguments.of(Json.createArrayBuilder().add(Json.createObjectBuilder()
+ Arguments.of(arrayBuilder().add(objectBuilder()
.add("name", "T1")
- .add("columns", Json.createArrayBuilder().add(Json.createObjectBuilder().add("name", "C1"))))
+ .add("columns", arrayBuilder().add(objectBuilder().add("name", "C1"))))
.build(),
"E-VSCOMJAVA-44: Failed to parse 'column 'C1' of table 'T1'' because mandatory field 'dataType' is missing."),
- Arguments.of(Json.createArrayBuilder().add(Json.createObjectBuilder()
+ Arguments.of(arrayBuilder().add(objectBuilder()
.add("name", "T1")
- .add("columns", Json.createArrayBuilder()
- .add(Json.createObjectBuilder().add("name", "C1")
+ .add("columns", arrayBuilder()
+ .add(objectBuilder().add("name", "C1")
.add("dataType",
- Json.createObjectBuilder().add("precision", 18).add("scale", 0)))))
+ objectBuilder().add("precision", 18).add("scale", 0)))))
.build(),
"E-VSCOMJAVA-44: Failed to parse 'column 'C1' of table 'T1' data type' because mandatory field 'type' is missing."),
// Unsupported data types
Arguments.of(createSingleColumnTable("VARCHAR",
- Json.createObjectBuilder().add("size", 10).add("characterSet", "INVALID").build()),
+ objectBuilder().add("size", 10).add("characterSet", "INVALID").build()),
"E-VSCOMJAVA-19: Unsupported charset encountered: 'INVALID'."),
Arguments.of(createSingleColumnTable("INTERVAL",
- Json.createObjectBuilder().add("fromTo", "CENTURY TO MINUTE").build()),
+ objectBuilder().add("fromTo", "CENTURY TO MINUTE").build()),
"E-VSCOMJAVA-20: Unsupported interval data type encountered: 'CENTURY TO MINUTE'."),
- Arguments.of(createSingleColumnTable("UNSUPPORTED_TYPE", Json.createObjectBuilder().build()),
+ Arguments.of(createSingleColumnTable("UNSUPPORTED_TYPE", objectBuilder().build()),
"E-VSCOMJAVA-18: Unsupported data type encountered: 'UNSUPPORTED_TYPE'."));
}
private static JsonArray createSingleColumnTable(final String type, final JsonObject typeAttributes) {
- final JsonObjectBuilder dataType = Json.createObjectBuilder().add("type", type);
+ final JsonObjectBuilder dataType = objectBuilder().add("type", type);
for (final String key : typeAttributes.keySet()) {
dataType.add(key, typeAttributes.get(key));
}
- return Json.createArrayBuilder().add(Json.createObjectBuilder()
+ return arrayBuilder().add(objectBuilder()
.add("name", "T1")
- .add("columns", Json.createArrayBuilder()
- .add(Json.createObjectBuilder().add("name", "C1").add("dataType", dataType))))
+ .add("columns", arrayBuilder()
+ .add(objectBuilder().add("name", "C1").add("dataType", dataType))))
.build();
}
}
diff --git a/src/test/java/com/exasol/logging/CompactFormatterTest.java b/src/test/java/com/exasol/logging/CompactFormatterTest.java
index 80e4e8e4..57dbe47a 100644
--- a/src/test/java/com/exasol/logging/CompactFormatterTest.java
+++ b/src/test/java/com/exasol/logging/CompactFormatterTest.java
@@ -1,72 +1,60 @@
package com.exasol.logging;
import static com.exasol.logging.RemoteLogManagerTest.*;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.text.MatchesPattern.matchesPattern;
import static org.junit.jupiter.api.Assertions.assertAll;
+import java.time.Instant;
import java.util.logging.Level;
import java.util.logging.LogRecord;
+import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
class CompactFormatterTest {
- private LogRecord record;
+ private LogRecord logRecord;
private final CompactFormatter formatter = new CompactFormatter();
@BeforeEach
void beforeEach() {
- this.record = new LogRecord(Level.SEVERE, "message");
+ this.logRecord = new LogRecord(Level.SEVERE, "message");
}
@Test
void testFormat() {
- final String formattedRecord = this.formatter.format(this.record);
+ final String formattedRecord = this.formatter.format(this.logRecord);
assertThat(formattedRecord, matchesTimeStamp(" SEVERE +message"));
}
@Test
- void testFormatWithEmptyClass() {
- this.record.setSourceClassName("");
- final String formattedRecord = this.formatter.format(this.record);
- assertThat(formattedRecord, matchesTimeStamp(" SEVERE +message"));
- }
-
- @Test
- void testFormatWithSimpleClass() {
- this.record.setSourceClassName("example");
- final String formattedRecord = this.formatter.format(this.record);
- assertThat(formattedRecord, matchesTimeStamp(" SEVERE +\\[example\\] +message"));
- }
-
- @Test
- void testFormatWithFullClass() {
- this.record.setSourceClassName("com.exasol.example");
- final String formattedRecord = this.formatter.format(this.record);
- assertThat(formattedRecord, matchesTimeStamp(" SEVERE +\\[c\\.e\\.example\\] +message"));
- }
-
- @Test
- void testFormatRobustAgainstDoubleDot() {
- this.record.setSourceClassName("com.exasol..example");
- final String formattedRecord = this.formatter.format(this.record);
- assertThat(formattedRecord, matchesTimeStamp(" SEVERE +\\[c\\.e\\.\\.example\\] +message"));
+ void testFormatUsesUtcTimestamp() {
+ this.logRecord.setInstant(Instant.ofEpochMilli(0));
+ final String formattedRecord = this.formatter.format(this.logRecord);
+ assertThat(formattedRecord, equalTo("1970-01-01 00:00:00.000 SEVERE message\n"));
}
- @Test
- void testFormatRobustAgainstEndDot() {
- this.record.setSourceClassName("com.exasol.");
- final String formattedRecord = this.formatter.format(this.record);
- assertThat(formattedRecord, matchesTimeStamp(" SEVERE +\\[c\\.e\\.\\] +message"));
+ @ParameterizedTest
+ @MethodSource("classNameFormats")
+ void testFormatWithClassName(final String sourceClassName, final String expectedContent) {
+ this.logRecord.setSourceClassName(sourceClassName);
+ final String formattedRecord = this.formatter.format(this.logRecord);
+ assertThat(formattedRecord, matchesTimeStamp(expectedContent));
}
- @Test
- void testFormatRobustAgainstOnlyDot() {
- this.record.setSourceClassName(".");
- final String formattedRecord = this.formatter.format(this.record);
- assertThat(formattedRecord, matchesTimeStamp(" SEVERE +\\[\\.\\] +message"));
+ private static Stream classNameFormats() {
+ return Stream.of(Arguments.of("", " SEVERE +message"),
+ Arguments.of("example", " SEVERE +\\[example\\] +message"),
+ Arguments.of("com.exasol.example", " SEVERE +\\[c\\.e\\.example\\] +message"),
+ Arguments.of("com.exasol..example", " SEVERE +\\[c\\.e\\.\\.example\\] +message"),
+ Arguments.of("com.exasol.", " SEVERE +\\[c\\.e\\.\\] +message"),
+ Arguments.of(".", " SEVERE +\\[\\.\\] +message"));
}
@Test
@@ -81,13 +69,13 @@ void testFormatWithPlaceholders() {
void testFormatException() {
final IllegalStateException cause = new IllegalStateException("the cause");
final IllegalArgumentException exception = new IllegalArgumentException("the exception", cause);
- this.record.setMessage("the message");
- this.record.setThrown(exception);
- final String formattedRecord = this.formatter.format(this.record);
+ this.logRecord.setMessage("the message");
+ this.logRecord.setThrown(exception);
+ final String formattedRecord = this.formatter.format(this.logRecord);
assertAll(
() -> assertThat(formattedRecord,
matchesPattern(TIMESTAMP_PATTERN + " SEVERE the message\\n(.*" + LINEFEED_PATTERN + ")*")),
() -> assertThat(formattedRecord, containsString("the exception")),
() -> assertThat(formattedRecord, containsString("the cause")));
}
-}
\ No newline at end of file
+}