package tachyon.client;

import java.io.IOException;
import java.io.InputStream;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import tachyon.LocalTachyonCluster;
import tachyon.TestUtils;
import tachyon.UnderFileSystem;
import tachyon.thrift.FileAlreadyExistException;
import tachyon.thrift.InvalidPathException;

/**
 * Unit tests for <code>tachyon.client.FileOutStream</code>.
 */
public class FileOutStreamTest {
  private final int MIN_LEN = 0;
  private final int MAX_LEN = 255;
  private final int DELTA = 33;
  private LocalTachyonCluster mLocalTachyonCluster = null;
  private TachyonFS mTfs = null;

  @Before
  public final void before() throws IOException {
    System.setProperty("tachyon.user.quota.unit.bytes", "1000");
    mLocalTachyonCluster = new LocalTachyonCluster(10000);
    mLocalTachyonCluster.start();
    mTfs = mLocalTachyonCluster.getClient();
  }

  @After
  public final void after() throws Exception {
    mLocalTachyonCluster.stop();
    System.clearProperty("tachyon.user.quota.unit.bytes");
  }

  private void writeTest1Util(String filePath, WriteType op, int len)
      throws InvalidPathException, FileAlreadyExistException, IOException {
    int fileId = mTfs.createFile(filePath);
    TachyonFile file = mTfs.getFile(fileId);
    OutStream os = file.getOutStream(op);
    Assert.assertTrue(os instanceof FileOutStream);
    for (int k = 0; k < len; k ++) {
      os.write((byte) k);
    }
    os.close();

    for (ReadType rOp : ReadType.values()) {
      file = mTfs.getFile(filePath);
      InStream is = file.getInStream(rOp);
      byte[] res = new byte[(int) file.length()];
      Assert.assertEquals((int) file.length(), is.read(res));
      Assert.assertTrue(TestUtils.equalIncreasingByteArray(len, res));
    }

    if (op.isThrough()) {
      file = mTfs.getFile(filePath);
      String checkpointPath = file.getCheckpointPath();
      UnderFileSystem ufs = UnderFileSystem.get(checkpointPath);

      InputStream is = ufs.open(checkpointPath);
      byte[] res = new byte[(int) file.length()];
      Assert.assertEquals((int) file.length(), is.read(res));
      Assert.assertTrue(TestUtils.equalIncreasingByteArray(len, res));
    }
  }

  /**
   * Test <code>void write(int b)</code>.
   */
  @Test
  public void writeTest1() throws IOException, InvalidPathException, FileAlreadyExistException {
    for (int k = MIN_LEN; k <= MAX_LEN; k += DELTA) {
      for (WriteType op : WriteType.values()) {
        writeTest1Util("/root/testFile_" + k + "_" + op, op, k);
      }
    }
  }

  private void writeTest2Util(String filePath, WriteType op, int len)
      throws InvalidPathException, FileAlreadyExistException, IOException {
    int fileId = mTfs.createFile(filePath);
    TachyonFile file = mTfs.getFile(fileId);
    OutStream os = file.getOutStream(op);
    Assert.assertTrue(os instanceof FileOutStream);
    os.write(TestUtils.getIncreasingByteArray(len));
    os.close();

    for (ReadType rOp : ReadType.values()) {
      file = mTfs.getFile(filePath);
      InStream is = file.getInStream(rOp);
      byte[] res = new byte[(int) file.length()];
      Assert.assertEquals((int) file.length(), is.read(res));
      Assert.assertTrue(TestUtils.equalIncreasingByteArray(len, res));
    }

    if (op.isThrough()) {
      file = mTfs.getFile(filePath);
      String checkpointPath = file.getCheckpointPath();
      UnderFileSystem ufs = UnderFileSystem.get(checkpointPath);

      InputStream is = ufs.open(checkpointPath);
      byte[] res = new byte[(int) file.length()];
      Assert.assertEquals((int) file.length(), is.read(res));
      Assert.assertTrue(TestUtils.equalIncreasingByteArray(len, res));
    }
  }

  /**
   * Test <code>void write(byte b[])</code>.
   */
  @Test
  public void writeTest2() throws IOException, InvalidPathException, FileAlreadyExistException {
    for (int k = MIN_LEN; k <= MAX_LEN; k += DELTA) {
      for (WriteType op : WriteType.values()) {
        writeTest2Util("/root/testFile_" + k + "_" + op, op, k);
      }
    }
  }

  private void writeTest3Util(String filePath, WriteType op, int len)
      throws InvalidPathException, FileAlreadyExistException, IOException {
    int fileId = mTfs.createFile(filePath);
    TachyonFile file = mTfs.getFile(fileId);
    OutStream os = file.getOutStream(op);
    Assert.assertTrue(os instanceof FileOutStream);
    os.write(TestUtils.getIncreasingByteArray(len), 0, len / 2);
    os.close();

    for (ReadType rOp : ReadType.values()) {
      file = mTfs.getFile(filePath);
      InStream is = file.getInStream(rOp);
      byte[] res = new byte[(int) file.length()];
      Assert.assertEquals((int) file.length(), is.read(res));
      Assert.assertTrue(TestUtils.equalIncreasingByteArray(len / 2, res));
    }

    if (op.isThrough()) {
      file = mTfs.getFile(filePath);
      String checkpointPath = file.getCheckpointPath();
      UnderFileSystem ufs = UnderFileSystem.get(checkpointPath);

      InputStream is = ufs.open(checkpointPath);
      byte[] res = new byte[(int) file.length()];
      Assert.assertEquals((int) file.length(), is.read(res));
      Assert.assertTrue(TestUtils.equalIncreasingByteArray(len / 2, res));
    }
  }

  /**
   * Test <code>void write(byte[] b, int off, int len)</code>.
   */
  @Test
  public void writeTest3() throws IOException, InvalidPathException, FileAlreadyExistException {
    for (int k = MIN_LEN; k <= MAX_LEN; k += DELTA) {
      for (WriteType op : WriteType.values()) {
        writeTest3Util("/root/testFile_" + k + "_" + op, op, k);
      }
    }
  }
}

@@ -781,16 +781,87 @@
 1000%22);%0A
+    System.setProperty(%22tachyon.user.default.block.size.byte%22, %22128%22);%0A
     mLoc
@@ -1143,16 +1143,82 @@
 ytes%22);%0A
+    System.clearProperty(%22tachyon.user.default.block.size.byte%22);%0A
   %7D%0A%0A  p
@@ -4582,19 +4582,104 @@
 teArray(
-len
+0, len / 2), 0, len / 2);%0A    os.write(TestUtils.getIncreasingByteArray(len / 2, len / 2
 ), 0, le
@@ -4996,32 +4996,36 @@
 gByteArray(len /
+ 2 *
  2, res));%0A    %7D
@@ -5364,32 +5364,32 @@
  is.read(res));%0A
-
       Assert.ass
@@ -5432,24 +5432,28 @@
 eArray(len /
+ 2 *
  2, res));%0A 

enhance fostest