package com.zendesk.maxwell; import java.util.*; import java.io.*; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import com.zendesk.maxwell.row.RowMap; import org.apache.commons.lang3.StringUtils; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; public class MaxwellTestJSON { /* methods around running JSON test files */ public static final TypeReference<Map<String, Object>> MAP_STRING_OBJECT_REF = new TypeReference<Map<String, Object>>() {}; public static Map<String, Object> parseJSON(String json) throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); return mapper.readValue(json, MAP_STRING_OBJECT_REF); } public static void assertJSON(List<Map<String, Object>> jsonOutput, List<Map<String, Object>> jsonAsserts) { ArrayList<Map<String, Object>> missing = new ArrayList<>(); for ( Map m : jsonAsserts ) { if ( !jsonOutput.contains(m) ) missing.add(m); } if ( missing.size() > 0 ) { String msg = "Did not find:\n" + StringUtils.join(missing.iterator(), "\n") + "\n\n in:\n" + StringUtils.join(jsonOutput.iterator(), "\n"); assertThat(msg, false, is(true)); } } private static void runJSONTest(MysqlIsolatedServer server, List<String> sql, List<Map<String, Object>> expectedJSON, MaxwellFilter filter) throws Exception { List<Map<String, Object>> eventJSON = new ArrayList<>(); List<RowMap> rows = MaxwellTestSupport.getRowsWithReplicator(server, filter, sql.toArray(new String[sql.size()]), null); for ( RowMap r : rows ) { String s = r.toJSON(); Map<String, Object> outputMap = parseJSON(s); outputMap.remove("ts"); outputMap.remove("xid"); outputMap.remove("commit"); eventJSON.add(outputMap); } assertJSON(eventJSON, expectedJSON); } public static class SQLAndJSON { public ArrayList<Map<String, Object>> jsonAsserts; public ArrayList<String> inputSQL; protected SQLAndJSON() { this.jsonAsserts = new ArrayList<>(); this.inputSQL = new ArrayList<>(); } } static final String JSON_PATTERN = "^\\s*\\->\\s*\\{.*"; public static SQLAndJSON parseJSONTestFile(String fname) throws Exception { File file = new File(fname); SQLAndJSON ret = new SQLAndJSON(); BufferedReader reader = new BufferedReader(new FileReader(file)); ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); String buffer = null; boolean bufferIsJSON = false; while ( reader.ready() ) { String line = reader.readLine(); if (line.matches("^\\s*$")) { // skip blanks continue; } if ( buffer != null ) { if (line.matches("^\\s+.*$") && !line.matches(JSON_PATTERN)) { // leading whitespace -- continuation of previous line buffer = buffer + " " + line.trim(); } else { if ( bufferIsJSON ) { ret.jsonAsserts.add(mapper.<Map<String, Object>>readValue(buffer, MAP_STRING_OBJECT_REF)); } else { ret.inputSQL.add(buffer); } buffer = null; } } if ( buffer == null ) { if ( line.matches(JSON_PATTERN) ) { line = line.replaceAll("^\\s*\\->\\s*", ""); bufferIsJSON = true; } else { bufferIsJSON = false; } buffer = line; } } if ( buffer != null ) { if ( bufferIsJSON ) { ret.jsonAsserts.add(mapper.<Map<String, Object>>readValue(buffer, MAP_STRING_OBJECT_REF)); } else { ret.inputSQL.add(buffer); } } reader.close(); return ret; } protected static void runJSONTestFile(MysqlIsolatedServer server, String dir, String fname, MaxwellFilter filter) throws Exception { SQLAndJSON testResources = parseJSONTestFile(new File(dir, fname).toString()); runJSONTest(server, testResources.inputSQL, testResources.jsonAsserts, filter); } protected static void runJSONTestFile(MysqlIsolatedServer server, String fname, MaxwellFilter filter) throws Exception { runJSONTestFile(server, MaxwellTestSupport.getSQLDir(), fname, filter); } }