|
44 | 44 | import static org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT96; |
45 | 45 | import static org.apache.parquet.schema.Type.Repetition.REQUIRED; |
46 | 46 | import static org.junit.Assert.assertEquals; |
| 47 | +import static org.mockito.Mockito.CALLS_REAL_METHODS; |
47 | 48 |
|
| 49 | +import com.google.common.collect.ImmutableSet; |
48 | 50 | import com.google.common.collect.Lists; |
49 | 51 | import com.google.common.io.Resources; |
50 | 52 | import java.util.Arrays; |
|
53 | 55 | import org.apache.avro.LogicalTypes; |
54 | 56 | import org.apache.avro.Schema; |
55 | 57 | import org.apache.hadoop.conf.Configuration; |
| 58 | +import org.apache.parquet.schema.LogicalTypeAnnotation; |
56 | 59 | import org.apache.parquet.schema.MessageType; |
57 | 60 | import org.apache.parquet.schema.MessageTypeParser; |
58 | 61 | import org.apache.parquet.schema.PrimitiveType; |
59 | 62 | import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName; |
| 63 | +import org.apache.parquet.schema.Type; |
60 | 64 | import org.apache.parquet.schema.Types; |
61 | 65 | import org.junit.Assert; |
| 66 | +import org.junit.Before; |
62 | 67 | import org.junit.BeforeClass; |
63 | 68 | import org.junit.Test; |
64 | | - |
| 69 | +import org.junit.runner.RunWith; |
| 70 | +import org.mockito.Mockito; |
| 71 | +import org.powermock.api.mockito.PowerMockito; |
| 72 | +import org.powermock.core.classloader.annotations.PrepareForTest; |
| 73 | +import org.powermock.modules.junit4.PowerMockRunner; |
| 74 | + |
| 75 | +@RunWith(PowerMockRunner.class) |
| 76 | +@PrepareForTest(AvroRecordConverter.class) |
65 | 77 | public class TestAvroSchemaConverter { |
66 | 78 |
|
67 | 79 | private static final Configuration NEW_BEHAVIOR = new Configuration(false); |
68 | 80 |
|
| 81 | + @Before |
| 82 | + public void setupMockito() { |
| 83 | + PowerMockito.mockStatic(AvroRecordConverter.class, CALLS_REAL_METHODS); |
| 84 | + } |
| 85 | + |
69 | 86 | @BeforeClass |
70 | 87 | public static void setupConf() { |
71 | 88 | NEW_BEHAVIOR.setBoolean("parquet.avro.add-list-element-records", false); |
@@ -665,6 +682,27 @@ public void testTimestampMillisType() throws Exception { |
665 | 682 | testRoundTripConversion( |
666 | 683 | expected, "message myrecord {\n" + " required int64 timestamp (TIMESTAMP(MILLIS,true));\n" + "}\n"); |
667 | 684 |
|
| 685 | + // Test that conversions for timestamp types only use APIs that are available in the user's Avro version |
| 686 | + for (String avroVersion : ImmutableSet.of("1.7.0", "1.8.0", "1.9.0", "1.10.0", "1.11.0")) { |
| 687 | + Mockito.when(AvroRecordConverter.getRuntimeAvroVersion()).thenReturn(avroVersion); |
| 688 | + final Schema converted = new AvroSchemaConverter() |
| 689 | + .convert(Types.buildMessage() |
| 690 | + .addField(Types.primitive(INT64, Type.Repetition.REQUIRED) |
| 691 | + .as(LogicalTypeAnnotation.timestampType( |
| 692 | + false, LogicalTypeAnnotation.TimeUnit.MILLIS)) |
| 693 | + .length(1) |
| 694 | + .named("timestamp_type")) |
| 695 | + .named("TestAvro")); |
| 696 | + |
| 697 | + assertEquals( |
| 698 | + avroVersion.matches("1\\.[789]\\.\\d+") ? "timestamp-millis" : "local-timestamp-millis", |
| 699 | + converted |
| 700 | + .getField("timestamp_type") |
| 701 | + .schema() |
| 702 | + .getLogicalType() |
| 703 | + .getName()); |
| 704 | + } |
| 705 | + |
668 | 706 | for (PrimitiveTypeName primitive : |
669 | 707 | new PrimitiveTypeName[] {INT32, INT96, FLOAT, DOUBLE, BOOLEAN, BINARY, FIXED_LEN_BYTE_ARRAY}) { |
670 | 708 | final PrimitiveType type; |
@@ -729,6 +767,27 @@ public void testTimestampMicrosType() throws Exception { |
729 | 767 | IllegalArgumentException.class, |
730 | 768 | () -> new AvroSchemaConverter().convert(message(type))); |
731 | 769 | } |
| 770 | + |
| 771 | + // Test that conversions for timestamp types only use APIs that are available in the user's Avro version |
| 772 | + for (String avroVersion : ImmutableSet.of("1.7.0", "1.8.0", "1.9.0", "1.10.0", "1.11.0")) { |
| 773 | + Mockito.when(AvroRecordConverter.getRuntimeAvroVersion()).thenReturn(avroVersion); |
| 774 | + final Schema converted = new AvroSchemaConverter() |
| 775 | + .convert(Types.buildMessage() |
| 776 | + .addField(Types.primitive(INT64, Type.Repetition.REQUIRED) |
| 777 | + .as(LogicalTypeAnnotation.timestampType( |
| 778 | + false, LogicalTypeAnnotation.TimeUnit.MICROS)) |
| 779 | + .length(1) |
| 780 | + .named("timestamp_type")) |
| 781 | + .named("TestAvro")); |
| 782 | + |
| 783 | + assertEquals( |
| 784 | + avroVersion.matches("1\\.[789]\\.\\d+") ? "timestamp-micros" : "local-timestamp-micros", |
| 785 | + converted |
| 786 | + .getField("timestamp_type") |
| 787 | + .schema() |
| 788 | + .getLogicalType() |
| 789 | + .getName()); |
| 790 | + } |
732 | 791 | } |
733 | 792 |
|
734 | 793 | @Test |
|
0 commit comments