4242import java .util .Set ;
4343
4444import org .mockito .Mockito ;
45+ import org .apache .commons .lang3 .reflect .FieldUtils ;
4546import org .slf4j .Logger ;
4647import org .slf4j .LoggerFactory ;
4748import org .apache .hadoop .conf .Configuration ;
@@ -617,6 +618,24 @@ public void testEmptyLegacyBlockTokenBytesIsLegacy() throws IOException {
617618 readToken .readFields (dib );
618619 }
619620
621+ /**
622+ * If the NameNode predates HDFS-6708 and HDFS-9807, then the LocatedBlocks
623+ * that it returns to the client will have block tokens that don't include
624+ * the storage types or storage IDs. Simulate this by setting the storage
625+ * type and storage ID to null to test backwards compatibility.
626+ */
627+ @ Test
628+ public void testLegacyBlockTokenWithoutStorages () throws IOException ,
629+ IllegalAccessException {
630+ BlockTokenIdentifier identifier = new BlockTokenIdentifier ("user" ,
631+ "blockpool" , 123 ,
632+ EnumSet .allOf (BlockTokenIdentifier .AccessMode .class ), null , null ,
633+ false );
634+ FieldUtils .writeField (identifier , "storageTypes" , null , true );
635+ FieldUtils .writeField (identifier , "storageIds" , null , true );
636+ testCraftedBlockTokenIdentifier (identifier , false , false , false );
637+ }
638+
620639 @ Test
621640 public void testProtobufBlockTokenBytesIsProtobuf () throws IOException {
622641 final boolean useProto = true ;
@@ -662,13 +681,17 @@ public void testProtobufBlockTokenBytesIsProtobuf() throws IOException {
662681 assertEquals (protobufToken , readToken );
663682 }
664683
665- private void testCraftedProtobufBlockTokenIdentifier (
684+ private void testCraftedBlockTokenIdentifier (
666685 BlockTokenIdentifier identifier , boolean expectIOE ,
667- boolean expectRTE ) throws IOException {
686+ boolean expectRTE , boolean isProtobuf ) throws IOException {
668687 DataOutputBuffer dob = new DataOutputBuffer (4096 );
669688 DataInputBuffer dib = new DataInputBuffer ();
670689
671- identifier .writeProtobuf (dob );
690+ if (isProtobuf ) {
691+ identifier .writeProtobuf (dob );
692+ } else {
693+ identifier .writeLegacy (dob );
694+ }
672695 byte [] identBytes = Arrays .copyOf (dob .getData (), dob .getLength ());
673696
674697 BlockTokenIdentifier legacyToken = new BlockTokenIdentifier ();
@@ -691,22 +714,23 @@ private void testCraftedProtobufBlockTokenIdentifier(
691714 invalidLegacyMessage = true ;
692715 }
693716
694- assertTrue (invalidLegacyMessage );
695-
696- dib .reset (identBytes , identBytes .length );
697- protobufToken .readFieldsProtobuf (dib );
717+ if (isProtobuf ) {
718+ assertTrue (invalidLegacyMessage );
698719
699- dib .reset (identBytes , identBytes .length );
700- readToken .readFieldsProtobuf (dib );
701- assertEquals (protobufToken , readToken );
702- assertEquals (identifier , readToken );
720+ dib .reset (identBytes , identBytes .length );
721+ protobufToken .readFieldsProtobuf (dib );
722+ dib .reset (identBytes , identBytes .length );
723+ readToken .readFields (dib );
724+ assertEquals (identifier , readToken );
725+ assertEquals (protobufToken , readToken );
726+ }
703727 }
704728
705729 @ Test
706730 public void testEmptyProtobufBlockTokenBytesIsProtobuf () throws IOException {
707731 // Empty BlockTokenIdentifiers throw IOException
708732 BlockTokenIdentifier identifier = new BlockTokenIdentifier ();
709- testCraftedProtobufBlockTokenIdentifier (identifier , true , false );
733+ testCraftedBlockTokenIdentifier (identifier , true , false , true );
710734 }
711735
712736 @ Test
@@ -727,10 +751,10 @@ public void testCraftedProtobufBlockTokenBytesIsProtobuf() throws
727751 datetime = ((datetime / 1000 ) * 1000 ); // strip milliseconds.
728752 datetime = datetime + 71 ; // 2017-02-09 00:12:35,071+0100
729753 identifier .setExpiryDate (datetime );
730- testCraftedProtobufBlockTokenIdentifier (identifier , false , true );
754+ testCraftedBlockTokenIdentifier (identifier , false , true , true );
731755 datetime += 1 ; // 2017-02-09 00:12:35,072+0100
732756 identifier .setExpiryDate (datetime );
733- testCraftedProtobufBlockTokenIdentifier (identifier , true , false );
757+ testCraftedBlockTokenIdentifier (identifier , true , false , true );
734758 }
735759
736760 private BlockTokenIdentifier writeAndReadBlockToken (
0 commit comments