/*
 * Licensed to the University of California, Berkeley 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 tachyon.worker.block.meta;

import java.io.IOException;
import java.util.List;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import tachyon.Constants;
import tachyon.StorageLevelAlias;
import tachyon.conf.TachyonConf;

public class StorageTierTest {
  private static final long TEST_USER_ID = 2;
  private static final long TEST_TEMP_BLOCK_ID = 10;
  private static final long TEST_BLOCK_SIZE = 20;
  private static final String TEST_DIR1_PATH = "/mnt/ramdisk/0/";
  private static final String TEST_DIR2_PATH = "/mnt/ramdisk/1/";
  private static final long TEST_DIR1_CAPACITY = 2000;
  private static final long TEST_DIR2_CAPACITY = 3000;
  private static final int TEST_TIER_LEVEL = 0;
  private static final int TEST_TIER_ALIAS = StorageLevelAlias.MEM.getValue();
  private StorageTier mTier;
  private StorageDir mDir1;
  private TempBlockMeta mTempBlockMeta;

  @Rule
  public ExpectedException mThrown = ExpectedException.none();

  @Before
  public final void before() throws Exception {
    TachyonConf tachyonConf = new TachyonConf();
    tachyonConf.set(
        String.format(Constants.WORKER_TIERED_STORAGE_LEVEL_ALIAS_FORMAT, TEST_TIER_LEVEL), "MEM");
    tachyonConf.set(
        String.format(Constants.WORKER_TIERED_STORAGE_LEVEL_DIRS_PATH_FORMAT, TEST_TIER_LEVEL),
        TEST_DIR1_PATH + "," + TEST_DIR2_PATH);
    tachyonConf.set(
        String.format(Constants.WORKER_TIERED_STORAGE_LEVEL_DIRS_QUOTA_FORMAT, TEST_TIER_LEVEL),
        TEST_DIR1_CAPACITY + "," + TEST_DIR2_CAPACITY);

    mTier = StorageTier.newStorageTier(tachyonConf, TEST_TIER_LEVEL);
    mDir1 = mTier.getDir(0);
    mTempBlockMeta = new TempBlockMeta(TEST_USER_ID, TEST_TEMP_BLOCK_ID, TEST_BLOCK_SIZE, mDir1);

  }

  @Test
  public void getTierAliasTest() {
    Assert.assertEquals(TEST_TIER_ALIAS, mTier.getTierAlias());
  }

  @Test
  public void getTierLevelTest() {
    Assert.assertEquals(TEST_TIER_LEVEL, mTier.getTierLevel());
  }

  @Test
  public void getCapacityBytesTest() throws IOException {
    Assert.assertEquals(TEST_DIR1_CAPACITY + TEST_DIR2_CAPACITY, mTier.getCapacityBytes());

    // Capacity should not change after adding block to a dir.
    mDir1.addTempBlockMeta(mTempBlockMeta);
    Assert.assertEquals(TEST_DIR1_CAPACITY + TEST_DIR2_CAPACITY, mTier.getCapacityBytes());
  }

  @Test
  public void getAvailableBytesTest() throws IOException {
    Assert.assertEquals(TEST_DIR1_CAPACITY + TEST_DIR2_CAPACITY, mTier.getAvailableBytes());

    // Capacity should subtract block size after adding block to a dir.
    mDir1.addTempBlockMeta(mTempBlockMeta);
    Assert.assertEquals(TEST_DIR1_CAPACITY + TEST_DIR2_CAPACITY - TEST_BLOCK_SIZE,
        mTier.getAvailableBytes());
  }

  @Test
  public void getDirTest() {
    mThrown.expect(IndexOutOfBoundsException.class);
    StorageDir dir1 = mTier.getDir(0);
    Assert.assertEquals(TEST_DIR1_PATH, dir1.getDirPath());
    StorageDir dir2 = mTier.getDir(1);
    Assert.assertEquals(TEST_DIR2_PATH, dir2.getDirPath());
    // Get dir by a non-existing index, expect getDir to fail and throw IndexOutOfBoundsException
    mTier.getDir(2);
  }

  @Test
  public void getStorageDirsTest() {
    List<StorageDir> dirs = mTier.getStorageDirs();
    Assert.assertEquals(2, dirs.size());
    Assert.assertEquals(TEST_DIR1_PATH, dirs.get(0).getDirPath());
    Assert.assertEquals(TEST_DIR2_PATH, dirs.get(1).getDirPath());
  }
}

@@ -1011,16 +1011,56 @@
 ception;
+%0Aimport org.junit.rules.TemporaryFolder;
 %0A%0Aimport
@@ -1331,140 +1331,8 @@
 20;%0A
-  private static final String TEST_DIR1_PATH = %22/mnt/ramdisk/0/%22;%0A  private static final String TEST_DIR2_PATH = %22/mnt/ramdisk/1/%22;%0A
   pr
@@ -1564,16 +1564,80 @@
 alue();%0A
+  private String mTestDirPath1;%0A  private String mTestDirPath2;%0A
   privat
@@ -1726,16 +1726,83 @@
 kMeta;%0A%0A
+  @Rule%0A  public TemporaryFolder mFolder = new TemporaryFolder();%0A%0A
   @Rule%0A
@@ -1931,50 +1931,224 @@
     
-TachyonConf tachyonConf = new TachyonConf(
+mTestDirPath1 = mFolder.newFolder().getAbsolutePath();%0A    mTestDirPath2 = mFolder.newFolder().getAbsolutePath();%0A%0A    TachyonConf tachyonConf = new TachyonConf();%0A    tachyonConf.set(Constants.WORKER_DATA_FOLDER, %22%22
 );%0A 
@@ -2396,45 +2396,43 @@
     
-TEST_DIR1_PATH + %22,%22 + TEST_DIR2_PATH
+mTestDirPath1 + %22,%22 + mTestDirPath2
 );%0A 
@@ -3945,38 +3945,37 @@
 ssertEquals(
-TEST_DIR1_PATH
+mTestDirPath1
 , dir1.getDi
@@ -4043,38 +4043,37 @@
 ssertEquals(
-TEST_DIR2_PATH
+mTestDirPath2
 , dir2.getDi
@@ -4372,22 +4372,21 @@
 als(
-TEST_DIR1_PATH
+mTestDirPath1
 , di
@@ -4438,22 +4438,21 @@
 als(
-TEST_DIR2_PATH
+mTestDirPath2
 , di

Update StorageTier tests.