package gobblin.converter.avro; import java.io.File; import java.io.IOException; import java.util.Properties; import org.apache.avro.Schema; import org.apache.avro.file.DataFileReader; import org.apache.avro.generic.GenericDatumReader; import org.apache.avro.generic.GenericRecord; import org.apache.commons.io.FileUtils; import org.testng.annotations.Test; import junit.framework.Assert; import gobblin.configuration.WorkUnitState; import gobblin.converter.DataConversionException; import gobblin.converter.SchemaConversionException; import gobblin.util.AvroUtils; @Test public class FlattenNestedKeyConverterTest { /** * Test schema and record conversion * 1. A successful schema and record conversion * 2. Another successful conversion by reusing the converter * 3. An expected failed conversion by reusing the converter */ public void testConversion() throws IOException { String key = FlattenNestedKeyConverter.class.getSimpleName() + "." + FlattenNestedKeyConverter.FIELDS_TO_FLATTEN; Properties props = new Properties(); props.put(key, "name,address.street_number"); WorkUnitState workUnitState = new WorkUnitState(); workUnitState.addAll(props); Schema inputSchema = new Schema.Parser().parse(getClass().getResourceAsStream("/converter/nested.avsc")); GenericDatumReader<GenericRecord> datumReader = new GenericDatumReader<GenericRecord>(inputSchema); File tmp = File.createTempFile(this.getClass().getSimpleName(), null); FileUtils.copyInputStreamToFile(getClass().getResourceAsStream("/converter/nested.avro"), tmp); DataFileReader<GenericRecord> dataFileReader = new DataFileReader<GenericRecord>(tmp, datumReader); GenericRecord inputRecord = dataFileReader.next(); FlattenNestedKeyConverter converter = new FlattenNestedKeyConverter(); Schema outputSchema = null; try { outputSchema = converter.convertSchema(inputSchema, workUnitState); } catch (SchemaConversionException e) { Assert.fail(e.getMessage()); } Assert.assertTrue(outputSchema.getFields().size() == inputSchema.getFields().size() + 1); Assert.assertTrue(outputSchema.getField("addressStreet_number") != null); GenericRecord outputRecord = null; try { outputRecord = converter.convertRecord(outputSchema, inputRecord, workUnitState).iterator().next(); } catch (DataConversionException e) { Assert.fail(e.getMessage()); } Object expected = AvroUtils.getFieldValue(outputRecord, "address.street_number").get(); Assert.assertTrue(outputRecord.get("addressStreet_number") == expected); // Reuse the converter to do another successful conversion props.put(key, "name,address.city"); workUnitState.addAll(props); try { outputSchema = converter.convertSchema(inputSchema, workUnitState); } catch (SchemaConversionException e) { Assert.fail(e.getMessage()); } Assert.assertTrue(outputSchema.getFields().size() == inputSchema.getFields().size() + 1); Assert.assertTrue(outputSchema.getField("addressCity") != null); try { outputRecord = converter.convertRecord(outputSchema, inputRecord, workUnitState).iterator().next(); } catch (DataConversionException e) { Assert.fail(e.getMessage()); } expected = AvroUtils.getFieldValue(outputRecord, "address.city").get(); Assert.assertTrue(outputRecord.get("addressCity") == expected); // Reuse the converter to do a failed conversion props.put(key, "name,address.anInvalidField"); workUnitState.addAll(props); boolean hasAnException = false; try { converter.convertSchema(inputSchema, workUnitState); } catch (SchemaConversionException e) { hasAnException = true; } Assert.assertTrue(hasAnException); } }