/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.flume.serialization; import org.apache.avro.Schema; import org.apache.avro.SchemaNormalization; import org.apache.avro.file.DataFileWriter; import org.apache.avro.generic.GenericDatumReader; import org.apache.avro.generic.GenericDatumWriter; import org.apache.avro.generic.GenericRecord; import org.apache.avro.generic.GenericRecordBuilder; import org.apache.avro.io.BinaryDecoder; import org.apache.avro.io.DatumReader; import org.apache.avro.io.DecoderFactory; import org.apache.commons.codec.binary.Hex; import org.apache.flume.Context; import org.apache.flume.Event; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.Collections; public class TestAvroEventDeserializer { private static final Logger logger = LoggerFactory.getLogger(TestAvroEventDeserializer.class); private static final Schema schema; static { schema = Schema.createRecord("MyRecord", "", "org.apache.flume", false); Schema.Field field = new Schema.Field("foo", Schema.create(Schema.Type.STRING), "", null); schema.setFields(Collections.singletonList(field)); } @Test public void resetTest() throws IOException { File tempFile = newTestFile(true); String target = tempFile.getAbsolutePath(); logger.info("Target: {}", target); TransientPositionTracker tracker = new TransientPositionTracker(target); AvroEventDeserializer.Builder desBuilder = new AvroEventDeserializer.Builder(); EventDeserializer deserializer = desBuilder.build(new Context(), new ResettableFileInputStream(tempFile, tracker)); BinaryDecoder decoder = null; DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema); decoder = DecoderFactory.get().binaryDecoder( deserializer.readEvent().getBody(), decoder); assertEquals("bar", reader.read(null, decoder).get("foo").toString()); deserializer.reset(); decoder = DecoderFactory.get().binaryDecoder( deserializer.readEvent().getBody(), decoder); assertEquals("bar", reader.read(null, decoder).get("foo").toString()); deserializer.mark(); decoder = DecoderFactory.get().binaryDecoder( deserializer.readEvent().getBody(), decoder); assertEquals("baz", reader.read(null, decoder).get("foo").toString()); deserializer.reset(); decoder = DecoderFactory.get().binaryDecoder( deserializer.readEvent().getBody(), decoder); assertEquals("baz", reader.read(null, decoder).get("foo").toString()); assertNull(deserializer.readEvent()); } @Test public void testSchemaHash() throws IOException, NoSuchAlgorithmException { File tempFile = newTestFile(true); String target = tempFile.getAbsolutePath(); logger.info("Target: {}", target); TransientPositionTracker tracker = new TransientPositionTracker(target); Context context = new Context(); context.put(AvroEventDeserializer.CONFIG_SCHEMA_TYPE_KEY, AvroEventDeserializer.AvroSchemaType.HASH.toString()); ResettableInputStream in = new ResettableFileInputStream(tempFile, tracker); EventDeserializer des = new AvroEventDeserializer.Builder().build(context, in); Event event = des.readEvent(); String eventSchemaHash = event.getHeaders().get(AvroEventDeserializer.AVRO_SCHEMA_HEADER_HASH); String expectedSchemaHash = Hex.encodeHexString( SchemaNormalization.parsingFingerprint("CRC-64-AVRO", schema)); Assert.assertEquals(expectedSchemaHash, eventSchemaHash); } @Test public void testSchemaLiteral() throws IOException { File tempFile = newTestFile(true); String target = tempFile.getAbsolutePath(); logger.info("Target: {}", target); TransientPositionTracker tracker = new TransientPositionTracker(target); Context context = new Context(); context.put(AvroEventDeserializer.CONFIG_SCHEMA_TYPE_KEY, AvroEventDeserializer.AvroSchemaType.LITERAL.toString()); ResettableInputStream in = new ResettableFileInputStream(tempFile, tracker); EventDeserializer des = new AvroEventDeserializer.Builder().build(context, in); Event event = des.readEvent(); String eventSchema = event.getHeaders().get(AvroEventDeserializer.AVRO_SCHEMA_HEADER_LITERAL); Assert.assertEquals(schema.toString(), eventSchema); } private File newTestFile(boolean deleteOnExit) throws IOException { File tempFile = File.createTempFile("testDirectFile", "tmp"); if (deleteOnExit) { tempFile.deleteOnExit(); } DataFileWriter<GenericRecord> writer = new DataFileWriter<GenericRecord>( new GenericDatumWriter<GenericRecord>(schema)); writer.create(schema, tempFile); GenericRecordBuilder recordBuilder; recordBuilder = new GenericRecordBuilder(schema); recordBuilder.set("foo", "bar"); GenericRecord record = recordBuilder.build(); writer.append(record); writer.sync(); recordBuilder = new GenericRecordBuilder(schema); recordBuilder.set("foo", "baz"); record = recordBuilder.build(); writer.append(record); writer.sync(); writer.flush(); writer.close(); return tempFile; } }