/**
 * 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.hadoop.hdfs.protocol;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;

import org.apache.hadoop.hdfs.protocol.LayoutVersion.Feature;
import org.apache.hadoop.hdfs.protocol.LayoutVersion.FeatureInfo;
import org.apache.hadoop.hdfs.protocol.LayoutVersion.LayoutFeature;
import org.apache.hadoop.hdfs.server.datanode.DataNodeLayoutVersion;
import org.apache.hadoop.hdfs.server.namenode.NameNodeLayoutVersion;
import org.junit.Test;

/**
 * Test for {@link LayoutVersion}
 */
public class TestLayoutVersion {
  public static final LayoutFeature LAST_NON_RESERVED_COMMON_FEATURE;
  public static final LayoutFeature LAST_COMMON_FEATURE;
  static {
    final Feature[] features = Feature.values();
    LAST_COMMON_FEATURE = features[features.length - 1];
    LAST_NON_RESERVED_COMMON_FEATURE = LayoutVersion.getLastNonReservedFeature(features);
  }
  
  /**
   * Tests to make sure a given layout version supports all the
   * features from the ancestor
   */
  @Test
  public void testFeaturesFromAncestorSupported() {
    for (LayoutFeature f : Feature.values()) {
      validateFeatureList(f);
    }
  }
  
  /**
   * Test to make sure 0.20.203 supports delegation token
   */
  @Test
  public void testRelease203() {
    assertTrue(NameNodeLayoutVersion.supports(LayoutVersion.Feature.DELEGATION_TOKEN, 
        Feature.RESERVED_REL20_203.getInfo().getLayoutVersion()));
  }
  
  /**
   * Test to make sure 0.20.204 supports delegation token
   */
  @Test
  public void testRelease204() {
    assertTrue(NameNodeLayoutVersion.supports(LayoutVersion.Feature.DELEGATION_TOKEN, 
        Feature.RESERVED_REL20_204.getInfo().getLayoutVersion()));
  }
  
  /**
   * Test to make sure release 1.2.0 support CONCAT
   */
  @Test
  public void testRelease1_2_0() {
    assertTrue(NameNodeLayoutVersion.supports(LayoutVersion.Feature.CONCAT, 
        Feature.RESERVED_REL1_2_0.getInfo().getLayoutVersion()));
  }
  
  /**
   * Test to make sure NameNode.Feature support previous features
   */
  @Test
  public void testNameNodeFeature() {
    final LayoutFeature first = NameNodeLayoutVersion.Feature.ROLLING_UPGRADE; 
    assertTrue(NameNodeLayoutVersion.supports(LAST_NON_RESERVED_COMMON_FEATURE,
        first.getInfo().getLayoutVersion()));
    assertEquals(LAST_COMMON_FEATURE.getInfo().getLayoutVersion() - 1,
        first.getInfo().getLayoutVersion());
  }
  
  /**
   * Test to make sure DataNode.Feature support previous features
   */
  @Test
  public void testDataNodeFeature() {
    final LayoutFeature first = DataNodeLayoutVersion.Feature.FIRST_LAYOUT; 
    assertTrue(DataNodeLayoutVersion.supports(LAST_NON_RESERVED_COMMON_FEATURE,
        first.getInfo().getLayoutVersion()));
    assertEquals(LAST_COMMON_FEATURE.getInfo().getLayoutVersion() - 1,
        first.getInfo().getLayoutVersion());
  }

  /**
   * Tests expected values for minimum compatible layout version in NameNode
   * features.  TRUNCATE, APPEND_NEW_BLOCK and QUOTA_BY_STORAGE_TYPE are all
   * features that launched in the same release.  TRUNCATE was added first, so
   * we expect all 3 features to have a minimum compatible layout version equal
   * to TRUNCATE's layout version.  All features older than that existed prior
   * to the concept of a minimum compatible layout version, so for each one, the
   * minimum compatible layout version must be equal to itself.
   */
  @Test
  public void testNameNodeFeatureMinimumCompatibleLayoutVersions() {
    int baseLV = NameNodeLayoutVersion.Feature.TRUNCATE.getInfo()
        .getLayoutVersion();
    EnumSet<NameNodeLayoutVersion.Feature> compatibleFeatures = EnumSet.of(
        NameNodeLayoutVersion.Feature.TRUNCATE,
        NameNodeLayoutVersion.Feature.APPEND_NEW_BLOCK,
        NameNodeLayoutVersion.Feature.QUOTA_BY_STORAGE_TYPE);
    for (LayoutFeature f : compatibleFeatures) {
      assertEquals(String.format("Expected minimum compatible layout version " +
          "%d for feature %s.", baseLV, f), baseLV,
          f.getInfo().getMinimumCompatibleLayoutVersion());
    }
    List<LayoutFeature> features = new ArrayList<>();
    features.addAll(EnumSet.allOf(LayoutVersion.Feature.class));
    features.addAll(EnumSet.allOf(NameNodeLayoutVersion.Feature.class));
    for (LayoutFeature f : features) {
      if (!compatibleFeatures.contains(f)) {
        assertEquals(String.format("Expected feature %s to have minimum " +
            "compatible layout version set to itself.", f),
            f.getInfo().getLayoutVersion(),
            f.getInfo().getMinimumCompatibleLayoutVersion());
      }
    }
  }

  /**
   * Tests that NameNode features are listed in order of minimum compatible
   * layout version.  It would be inconsistent to have features listed out of
   * order with respect to minimum compatible layout version, because it would
   * imply going back in time to change compatibility logic in a software release
   * that had already shipped.
   */
  @Test
  public void testNameNodeFeatureMinimumCompatibleLayoutVersionAscending() {
    LayoutFeature prevF = null;
    for (LayoutFeature f : EnumSet.allOf(NameNodeLayoutVersion.Feature.class)) {
      if (prevF != null) {
        assertTrue(String.format("Features %s and %s not listed in order of " +
            "minimum compatible layout version.", prevF, f),
            f.getInfo().getMinimumCompatibleLayoutVersion() <=
            prevF.getInfo().getMinimumCompatibleLayoutVersion());
      } else {
        prevF = f;
      }
    }
  }

  /**
   * Tests that attempting to add a new NameNode feature out of order with
   * respect to minimum compatible layout version will fail fast.
   */
  @Test(expected=AssertionError.class)
  public void testNameNodeFeatureMinimumCompatibleLayoutVersionOutOfOrder() {
    FeatureInfo ancestorF = LayoutVersion.Feature.RESERVED_REL2_4_0.getInfo();
    LayoutFeature f = mock(LayoutFeature.class);
    when(f.getInfo()).thenReturn(new FeatureInfo(
        ancestorF.getLayoutVersion() - 1, ancestorF.getLayoutVersion(),
        ancestorF.getMinimumCompatibleLayoutVersion() + 1, "Invalid feature.",
        false));
    Map<Integer, SortedSet<LayoutFeature>> features = new HashMap<>();
    LayoutVersion.updateMap(features, LayoutVersion.Feature.values());
    LayoutVersion.updateMap(features, new LayoutFeature[] { f });
  }

  /**
   * Asserts the current minimum compatible layout version of the software, if a
   * release were created from the codebase right now.  This test is meant to
   * make developers stop and reconsider if they introduce a change that requires
   * a new minimum compatible layout version.  This would make downgrade
   * impossible.
   */
  @Test
  public void testCurrentMinimumCompatibleLayoutVersion() {
    int expectedMinCompatLV = NameNodeLayoutVersion.Feature.TRUNCATE.getInfo()
        .getLayoutVersion();
    int actualMinCompatLV = LayoutVersion.getMinimumCompatibleLayoutVersion(
        NameNodeLayoutVersion.Feature.values());
    assertEquals("The minimum compatible layout version has changed.  " +
        "Downgrade to prior versions is no longer possible.  Please either " +
        "restore compatibility, or if the incompatibility is intentional, " +
        "then update this assertion.", expectedMinCompatLV, actualMinCompatLV);
  }

  /**
   * Given feature {@code f}, ensures the layout version of that feature
   * supports all the features supported by it's ancestor.
   */
  private void validateFeatureList(LayoutFeature f) {
    final FeatureInfo info = f.getInfo();
    int lv = info.getLayoutVersion();
    int ancestorLV = info.getAncestorLayoutVersion();
    SortedSet<LayoutFeature> ancestorSet = NameNodeLayoutVersion.getFeatures(ancestorLV);
    assertNotNull(ancestorSet);
    for (LayoutFeature  feature : ancestorSet) {
      assertTrue("LV " + lv + " does nto support " + feature
          + " supported by the ancestor LV " + info.getAncestorLayoutVersion(),
          NameNodeLayoutVersion.supports(feature, lv));
    }
  }
  
  /**
   * When a LayoutVersion support SNAPSHOT, it must support
   * FSIMAGE_NAME_OPTIMIZATION.
   */
  @Test
  public void testSNAPSHOT() {
    for(Feature f : Feature.values()) {
      final int version = f.getInfo().getLayoutVersion();
      if (NameNodeLayoutVersion.supports(Feature.SNAPSHOT, version)) {
        assertTrue(NameNodeLayoutVersion.supports(
            Feature.FSIMAGE_NAME_OPTIMIZATION, version));
      }
    }
  }
}
