Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions .claude/skills/migrate-groovy-to-java/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ description: migrate test groovy files to java

Migrate test Groovy files to Java using JUnit 5

1. List all groovy files of the current gradle module
2. convert groovy files to Java using Junit 5
3. make sure the tests are still passing after migration
4. remove groovy files
1. List all Groovy files of the current Gradle module
2. Convert Groovy files to Java using JUnit 5
3. Make sure the tests are still passing after migration and that the test count has not changed
4. Remove Groovy files

When converting groovy code to java code make sure that:
- the Java code generated is compatible with JDK 8
- when translating Spock test, favor using `@CsvSource` with `|` delimiters
- when using a `@MethodSource`, use the test method name, and suffix it with `_arguments`
- when converting tuples, create light dedicated structure instead to keep the typing system
When converting Groovy code to Java code, make sure that:
- The Java code generated is compatible with JDK 8
- When translating Spock tests, favor using `@CsvSource` with `|` delimiters
- When using `@MethodSource`, name the arguments method by appending `Arguments` using camelCase to the test method name (e.g. `testMethodArguments`)
- Ensure parameterized test names are human-readable (i.e. no hashcodes); instead add a description string as the first `Arguments.of(...)` value or index the test case
- When converting tuples, create a light dedicated structure instead to keep the typing system
- Instead of checking a state and throwing an exception, use JUnit asserts
- Do not wrap checked exception and throwing a Runtime exception, prefer adding a throws clause at method declaration
- Do not wrap checked exceptions and throw a Runtime exception; prefer adding a throws clause at method declaration
- Do not mark local variables `final`
- Ensure variables are human-readable; avoid single-letter names and pre-define variables that are referenced multiple times
170 changes: 0 additions & 170 deletions components/json/src/test/groovy/datadog/json/JsonMapperTest.groovy

This file was deleted.

194 changes: 194 additions & 0 deletions components/json/src/test/java/datadog/json/JsonMapperTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package datadog.json;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;

class JsonMapperTest {

@ParameterizedTest(name = "test mapping to JSON object: {0}")
@MethodSource("testMappingToJsonObjectArguments")
void testMappingToJsonObject(String testCase, Map<String, Object> input, String expected)
throws IOException {
String json = JsonMapper.toJson(input);
assertEquals(expected, json);

Map<String, Object> parsed = JsonMapper.fromJsonToMap(json);
if (input == null) {
assertEquals(emptyMap(), parsed);
} else {
assertEquals(input.size(), parsed.size());
for (Map.Entry<String, Object> entry : input.entrySet()) {
String expectedKey = entry.getKey();
Object expectedValue = entry.getValue();
assertTrue(parsed.containsKey(expectedKey));
Object parsedValue = parsed.get(expectedKey);
if (expectedValue instanceof UnsupportedType) {
assertEquals(expectedValue.toString(), parsedValue);
} else if (expectedValue instanceof Float) {
assertTrue(parsedValue instanceof Double);
assertEquals((Float) expectedValue, (Double) parsedValue, 0.001);
} else {
assertEquals(expectedValue, parsedValue);
}
}
}
Comment thread
sarahchen6 marked this conversation as resolved.
}

static Stream<Arguments> testMappingToJsonObjectArguments() {
Map<String, Object> singleEntry = new LinkedHashMap<>();
singleEntry.put("key1", "value1");

Map<String, Object> twoEntries = new LinkedHashMap<>();
twoEntries.put("key1", "value1");
twoEntries.put("key2", "value2");

Map<String, Object> quotedEntries = new LinkedHashMap<>();
quotedEntries.put("key1", "va\"lu\"e1");
quotedEntries.put("ke\"y2", "value2");

Map<String, Object> complexMap = new LinkedHashMap<>();
complexMap.put("key1", null);
complexMap.put("key2", "bar");
complexMap.put("key3", 3);
complexMap.put("key4", 3456789123L);
complexMap.put("key5", 3.142f);
complexMap.put("key6", Math.PI);
complexMap.put("key7", true);
complexMap.put("key8", new UnsupportedType());

return Stream.of(
Arguments.of("null input", null, "{}"),
Arguments.of("empty map", new HashMap<>(), "{}"),
Arguments.of("single entry", singleEntry, "{\"key1\":\"value1\"}"),
Arguments.of("two entries", twoEntries, "{\"key1\":\"value1\",\"key2\":\"value2\"}"),
Arguments.of(
"quoted entries",
quotedEntries,
"{\"key1\":\"va\\\"lu\\\"e1\",\"ke\\\"y2\":\"value2\"}"),
Arguments.of(
"complex map",
complexMap,
"{\"key1\":null,\"key2\":\"bar\",\"key3\":3,\"key4\":3456789123,\"key5\":3.142,\"key6\":3.141592653589793,\"key7\":true,\"key8\":\"toString\"}"));
}

@ParameterizedTest(name = "test mapping to Map from empty JSON object: {0}")
@MethodSource("testMappingToMapFromEmptyJsonObjectArguments")
void testMappingToMapFromEmptyJsonObject(String json) throws IOException {
Map<String, Object> parsed = JsonMapper.fromJsonToMap(json);
assertEquals(emptyMap(), parsed);
}

static Stream<Arguments> testMappingToMapFromEmptyJsonObjectArguments() {
return Stream.of(
Arguments.of((Object) null), Arguments.of("null"), Arguments.of(""), Arguments.of("{}"));
}

@ParameterizedTest(name = "test mapping to Map from non-object JSON: {0}")
@ValueSource(strings = {"1", "[1, 2]"})
void testMappingToMapFromNonObjectJson(String json) {
assertThrows(IOException.class, () -> JsonMapper.fromJsonToMap(json));
}

@ParameterizedTest(name = "test mapping iterable to JSON array: {0}")
@MethodSource("testMappingIterableToJsonArrayArguments")
void testMappingIterableToJsonArray(List<String> input, String expected) throws IOException {
String json = JsonMapper.toJson(input);
assertEquals(expected, json);

List<String> parsed = JsonMapper.fromJsonToList(json);
assertEquals(input != null ? input : emptyList(), parsed);
}

static Stream<Arguments> testMappingIterableToJsonArrayArguments() {
return Stream.of(
Arguments.of(null, "[]"),
Arguments.of(new ArrayList<>(), "[]"),
Arguments.of(Arrays.asList("value1"), "[\"value1\"]"),
Arguments.of(Arrays.asList("value1", "value2"), "[\"value1\",\"value2\"]"),
Arguments.of(Arrays.asList("va\"lu\"e1", "value2"), "[\"va\\\"lu\\\"e1\",\"value2\"]"));
}

@ParameterizedTest(name = "test mapping array to JSON array: {0}")
@MethodSource("testMappingArrayToJsonArrayArguments")
void testMappingArrayToJsonArray(String testCase, String[] input, String expected)
throws IOException {
String json = JsonMapper.toJson(input);
assertEquals(expected, json);

String[] parsed = JsonMapper.fromJsonToList(json).toArray(new String[] {});
assertArrayEquals(input != null ? input : new String[] {}, parsed);
}

static Stream<Arguments> testMappingArrayToJsonArrayArguments() {
return Stream.of(
Arguments.of("null input", (Object) null, "[]"),
Arguments.of("empty array", new String[] {}, "[]"),
Arguments.of("single element", new String[] {"value1"}, "[\"value1\"]"),
Arguments.of("two elements", new String[] {"value1", "value2"}, "[\"value1\",\"value2\"]"),
Arguments.of(
"escaped quotes",
new String[] {"va\"lu\"e1", "value2"},
"[\"va\\\"lu\\\"e1\",\"value2\"]"));
}

@ParameterizedTest(name = "test mapping to List from empty JSON object: {0}")
@MethodSource("testMappingToListFromEmptyJsonObjectArguments")
void testMappingToListFromEmptyJsonObject(String json) throws IOException {
List<String> parsed = JsonMapper.fromJsonToList(json);
assertEquals(emptyList(), parsed);
}

static Stream<Arguments> testMappingToListFromEmptyJsonObjectArguments() {
return Stream.of(
Arguments.of((Object) null), Arguments.of("null"), Arguments.of(""), Arguments.of("[]"));
}

@ParameterizedTest(name = "test mapping to JSON string: {0}")
@MethodSource("testMappingToJsonStringArguments")
void testMappingToJsonString(String input, String expected) {
String json = JsonMapper.toJson(input);
assertEquals(expected, json);
}

static Stream<Arguments> testMappingToJsonStringArguments() {
return Stream.of(
Arguments.of((Object) null, ""),
Arguments.of("", ""),
Arguments.of(String.valueOf((char) 4096), "\"\\u1000\""),
Arguments.of(String.valueOf((char) 256), "\"\\u0100\""),
Arguments.of(String.valueOf((char) 128), "\"\\u0080\""),
Arguments.of("\b", "\"\\b\""),
Arguments.of("\t", "\"\\t\""),
Arguments.of("\n", "\"\\n\""),
Arguments.of("\f", "\"\\f\""),
Arguments.of("\r", "\"\\r\""),
Arguments.of("\"", "\"\\\"\""),
Arguments.of("/", "\"\\/\""),
Arguments.of("\\", "\"\\\\\""),
Arguments.of("a", "\"a\""));
}

private static class UnsupportedType {
@Override
public String toString() {
return "toString";
}
}
}