This is an automated email from the ASF dual-hosted git repository.

steveloughran pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 9318632ebfb HADOOP-19928. Move to Avro 1.12.1 (#8567)
9318632ebfb is described below

commit 9318632ebfbe22cc1bd9b9ed78c89fd225f62a67
Author: Steve Loughran <[email protected]>
AuthorDate: Tue Jun 30 19:21:23 2026 +0100

    HADOOP-19928. Move to Avro 1.12.1 (#8567)
    
    
    Contains code contributed by Anthropic Claude
    
    Contributed by Steve Loughran
---
 LICENSE-binary                                     |   2 +-
 .../io/serializer/avro/TestAvroSerialization.java  |  91 +++++++++++++----
 .../hadoop/mapreduce/jobhistory/TestEvents.java    | 111 ++++++++++++---------
 hadoop-project/pom.xml                             |   2 +-
 4 files changed, 136 insertions(+), 70 deletions(-)

diff --git a/LICENSE-binary b/LICENSE-binary
index 780902ae05c..c5d6d6f1763 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -363,7 +363,7 @@ io.swagger:swagger-annotations:1.5.4
 javax.inject:javax.inject:1
 net.java.dev.jna:jna:5.2.0
 net.minidev:accessors-smart:1.21
-org.apache.avro:avro:1.11.5
+org.apache.avro:avro:1.12.1
 org.apache.commons:commons-compress:1.26.1
 org.apache.commons:commons-configuration2:2.10.1
 org.apache.commons:commons-csv:1.9.0
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/serializer/avro/TestAvroSerialization.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/serializer/avro/TestAvroSerialization.java
index dc040d16e7e..3f658754137 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/serializer/avro/TestAvroSerialization.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/serializer/avro/TestAvroSerialization.java
@@ -18,8 +18,9 @@
 
 package org.apache.hadoop.io.serializer.avro;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
+import java.util.Objects;
+
+import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.io.serializer.SerializationFactory;
@@ -35,7 +36,7 @@ public void testSpecific() throws Exception {
     AvroRecord before = new AvroRecord();
     before.setIntField(5);
     AvroRecord after = SerializationTestUtil.testSerialization(conf, before);
-    assertEquals(before, after);
+    assertThat(after).isEqualTo(before);
   }
 
   @Test
@@ -45,14 +46,14 @@ public void testReflectPkg() throws Exception {
     conf.set(AvroReflectSerialization.AVRO_REFLECT_PACKAGES, 
         before.getClass().getPackage().getName());
     Record after = SerializationTestUtil.testSerialization(conf, before);
-    assertEquals(before, after);
+    assertThat(after).isEqualTo(before);
   }
 
   @Test
   public void testAcceptHandlingPrimitivesAndArrays() throws Exception {
     SerializationFactory factory = new SerializationFactory(conf);
-    assertNull(factory.getSerializer(byte[].class));
-    assertNull(factory.getSerializer(byte.class));
+    assertThat(factory.getSerializer(byte[].class)).isNull();
+    assertThat(factory.getSerializer(byte.class)).isNull();
   }
 
   @Test
@@ -62,18 +63,34 @@ public void testReflectInnerClass() throws Exception {
     conf.set(AvroReflectSerialization.AVRO_REFLECT_PACKAGES, 
         before.getClass().getPackage().getName());
     InnerRecord after = SerializationTestUtil.testSerialization(conf, before);
-    assertEquals(before, after);
+    assertThat(after).isEqualTo(before);
   }
 
   @Test
   public void testReflect() throws Exception {
     RefSerializable before = new RefSerializable();
     before.x = 10;
-    RefSerializable after = 
+    RefSerializable after =
       SerializationTestUtil.testSerialization(conf, before);
-    assertEquals(before, after);
+    assertThat(after).isEqualTo(before);
+  }
+
+  /**
+   * Round-trip a reflect-serializable record that carries a String field.
+   * String handling is the part of the Avro API most affected by changes to
+   * {@code org.apache.avro.util.Utf8}, so this guards the reflect 
serialization
+   * path across Avro upgrades.
+   */
+  @Test
+  public void testReflectStringField() throws Exception {
+    StringRecord before = new StringRecord();
+    before.x = 10;
+    before.s = "value";
+    StringRecord after =
+        SerializationTestUtil.testSerialization(conf, before);
+    assertThat(after).isEqualTo(before);
   }
-  
+
   public static class InnerRecord {
     public int x = 7;
 
@@ -84,20 +101,21 @@ public int hashCode() {
 
     @Override
     public boolean equals(Object obj) {
-      if (this == obj)
+      if (this == obj) {
         return true;
-      if (obj == null)
+      }
+      if (obj == null) {
         return false;
-      if (getClass() != obj.getClass())
+      }
+      if (getClass() != obj.getClass()) {
         return false;
+      }
       final InnerRecord other = (InnerRecord) obj;
-      if (x != other.x)
-        return false;
-      return true;
+      return x == other.x;
     }
   }
 
-  public static class RefSerializable implements AvroReflectSerializable {
+  public static final class RefSerializable implements AvroReflectSerializable 
{
     public int x = 7;
 
     @Override
@@ -107,16 +125,45 @@ public int hashCode() {
 
     @Override
     public boolean equals(Object obj) {
-      if (this == obj)
+      if (this == obj) {
         return true;
-      if (obj == null)
+      }
+      if (obj == null) {
         return false;
-      if (getClass() != obj.getClass())
+      }
+      if (getClass() != obj.getClass()) {
         return false;
+      }
       final RefSerializable other = (RefSerializable) obj;
-      if (x != other.x)
+      return x == other.x;
+    }
+  }
+
+  public static final class StringRecord implements AvroReflectSerializable {
+    public int x = 7;
+    public String s = "";
+
+    @Override
+    public int hashCode() {
+      return x * 31 + (s == null ? 0 : s.hashCode());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+      if (this == obj) {
+        return true;
+      }
+      if (obj == null) {
+        return false;
+      }
+      if (getClass() != obj.getClass()) {
+        return false;
+      }
+      final StringRecord other = (StringRecord) obj;
+      if (x != other.x) {
         return false;
-      return true;
+      }
+      return Objects.equals(s, other.s);
     }
   }
 }
diff --git 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/jobhistory/TestEvents.java
 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/jobhistory/TestEvents.java
index 1819a641999..80882e5aca6 100644
--- 
a/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/jobhistory/TestEvents.java
+++ 
b/hadoop-mapreduce-project/hadoop-mapreduce-client/hadoop-mapreduce-client-app/src/test/java/org/apache/hadoop/mapreduce/jobhistory/TestEvents.java
@@ -19,8 +19,6 @@
 package org.apache.hadoop.mapreduce.jobhistory;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -72,7 +70,7 @@ public void testTaskAttemptFinishedEvent() throws Exception {
     assertThat(test.getTaskId()).isEqualTo(tid);
     assertThat(test.getTaskStatus()).isEqualTo("TEST");
     assertThat(test.getTaskType()).isEqualTo(TaskType.REDUCE);
-    assertEquals(234, test.getStartTime());
+    assertThat(test.getStartTime()).isEqualTo(234);
   }
 
   /**
@@ -121,88 +119,109 @@ public void testTaskUpdated() throws Exception {
   /*
    * test EventReader EventReader should read the list of events and return
    * instance of HistoryEvent Different HistoryEvent should have a different
-   * datum.
+   * datum. Uses the Avro-Json encoding.
    */
   @Test
   @Timeout(value = 10)
   public void testEvents() throws Exception {
+    verifyEvents(getEvents(EventWriter.WriteMode.JSON));
+  }
+
+  /*
+   * As {@link #testEvents()} but exercising the Avro-Binary encoding, which is
+   * the format job history files are written in. This guards the
+   * SpecificDatumWriter/SpecificDatumReader binary round-trip across Avro
+   * upgrades.
+   */
+  @Test
+  @Timeout(value = 10)
+  public void testEventsBinary() throws Exception {
+    verifyEvents(getEvents(EventWriter.WriteMode.BINARY));
+  }
+
+  private void verifyEvents(byte[] events) throws Exception {
 
     EventReader reader = new EventReader(new DataInputStream(
-        new ByteArrayInputStream(getEvents())));
+        new ByteArrayInputStream(events)));
     HistoryEvent e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.JOB_PRIORITY_CHANGED));
-    assertEquals("ID", ((JobPriorityChange) 
e.getDatum()).getJobid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.JOB_PRIORITY_CHANGED);
+    assertThat(((JobPriorityChange) e.getDatum()).getJobid().toString())
+        .isEqualTo("ID");
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.JOB_STATUS_CHANGED));
-    assertEquals("ID", ((JobStatusChanged) 
e.getDatum()).getJobid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.JOB_STATUS_CHANGED);
+    assertThat(((JobStatusChanged) e.getDatum()).getJobid().toString())
+        .isEqualTo("ID");
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.TASK_UPDATED));
-    assertEquals("ID", ((TaskUpdated) e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.TASK_UPDATED);
+    assertThat(((TaskUpdated) e.getDatum()).getTaskid().toString())
+        .isEqualTo("ID");
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_KILLED));
-    assertEquals(taskId,
-        ((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_KILLED);
+    assertThat(((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.JOB_KILLED));
-    assertEquals("ID",
-        ((JobUnsuccessfulCompletion) e.getDatum()).getJobid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.JOB_KILLED);
+    assertThat(((JobUnsuccessfulCompletion) 
e.getDatum()).getJobid().toString())
+        .isEqualTo("ID");
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_STARTED));
-    assertEquals(taskId,
-        ((TaskAttemptStarted) e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_STARTED);
+    assertThat(((TaskAttemptStarted) e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_FINISHED));
-    assertEquals(taskId,
-        ((TaskAttemptFinished) e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_FINISHED);
+    assertThat(((TaskAttemptFinished) e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_KILLED));
-    assertEquals(taskId,
-        ((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_KILLED);
+    assertThat(((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_KILLED));
-    assertEquals(taskId,
-        ((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_KILLED);
+    assertThat(((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_STARTED));
-    assertEquals(taskId,
-        ((TaskAttemptStarted) e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_STARTED);
+    assertThat(((TaskAttemptStarted) e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_FINISHED));
-    assertEquals(taskId,
-        ((TaskAttemptFinished) e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_FINISHED);
+    assertThat(((TaskAttemptFinished) e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_KILLED));
-    assertEquals(taskId,
-        ((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_KILLED);
+    assertThat(((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     e = reader.getNextEvent();
-    assertTrue(e.getEventType().equals(EventType.REDUCE_ATTEMPT_KILLED));
-    assertEquals(taskId,
-        ((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString());
+    assertThat(e.getEventType()).isEqualTo(EventType.REDUCE_ATTEMPT_KILLED);
+    assertThat(((TaskAttemptUnsuccessfulCompletion) 
e.getDatum()).getTaskid().toString())
+        .isEqualTo(taskId);
 
     reader.close();
   }
 
-  /*
-   * makes array of bytes with History events
+  /**
+   * makes array of bytes with History events, encoded in the given write mode.
+   * @param mode write mode.
+   * @return the marshalled output
+   * @throws Exception failure
    */
-  private byte[] getEvents() throws Exception {
+  private byte[] getEvents(EventWriter.WriteMode mode) throws Exception {
     ByteArrayOutputStream output = new ByteArrayOutputStream();
     FSDataOutputStream fsOutput = new FSDataOutputStream(output,
         new FileSystem.Statistics("scheme"));
-    EventWriter writer = new EventWriter(fsOutput,
-        EventWriter.WriteMode.JSON);
+    EventWriter writer = new EventWriter(fsOutput, mode);
     writer.write(getJobPriorityChangedEvent());
     writer.write(getJobStatusChangedEvent());
     writer.write(getTaskUpdatedEvent());
diff --git a/hadoop-project/pom.xml b/hadoop-project/pom.xml
index a92998ce262..b6df5330cd2 100644
--- a/hadoop-project/pom.xml
+++ b/hadoop-project/pom.xml
@@ -62,7 +62,7 @@
     <java.security.egd>file:///dev/urandom</java.security.egd>
 
     <!-- avro version -->
-    <avro.version>1.11.5</avro.version>
+    <avro.version>1.12.1</avro.version>
 
     <!-- jersey version -->
     <jersey2.version>2.46</jersey2.version>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to