package org.smoothbuild.db.values;
import static org.hamcrest.Matchers.not;
import static org.smoothbuild.db.values.ValuesDb.memoryValuesDb;
import static org.smoothbuild.lang.type.Types.BLOB;
import static org.smoothbuild.testing.common.ExceptionMatcher.exception;
import static org.smoothbuild.util.Streams.inputStreamToByteArray;
import static org.smoothbuild.util.Streams.writeAndClose;
import static org.testory.Testory.given;
import static org.testory.Testory.thenReturned;
import static org.testory.Testory.thenThrown;
import static org.testory.Testory.when;
import org.junit.Before;
import org.junit.Test;
import org.smoothbuild.db.hashed.HashedDbException;
import org.smoothbuild.lang.value.Blob;
import org.smoothbuild.lang.value.BlobBuilder;
import com.google.common.hash.HashCode;
public class BlobTest {
private final byte[] bytes = new byte[] { 1, 2, 3 };
private final byte[] otherBytes = new byte[] { 4, 5, 6 };
private ValuesDb valuesDb;
private BlobBuilder blobBuilder;
private Blob blob;
private Blob blob2;
private HashCode hash;
@Before
public void before() {
valuesDb = memoryValuesDb();
}
@Test
public void creating_blob_without_content_creates_empty_blob() throws Exception {
given(blobBuilder = valuesDb.blobBuilder());
given(blob = blobBuilder.build());
when(inputStreamToByteArray(blob.openInputStream()));
thenReturned(new byte[] {});
}
@Test
public void type_of_blob_is_blob() throws Exception {
given(blob = createBlob(valuesDb, bytes));
when(blob).type();
thenReturned(BLOB);
}
@Test
public void empty_blob_is_empty() throws Exception {
given(blobBuilder = valuesDb.blobBuilder());
given(blobBuilder).close();
given(blob = blobBuilder.build());
when(inputStreamToByteArray(blob.openInputStream()));
thenReturned(new byte[] {});
}
@Test
public void blob_has_content_passed_to_builder() throws Exception {
given(blob = createBlob(valuesDb, bytes));
when(inputStreamToByteArray(blob.openInputStream()));
thenReturned(bytes);
}
@Test
public void blob_has_content_passed_to_write_byte_method() throws Exception {
given(blobBuilder = valuesDb.blobBuilder());
given(blobBuilder).write(0x17);
given(blob = blobBuilder.build());
when(blob.openInputStream().read());
thenReturned(0x17);
}
@Test
public void blob_has_content_passed_to_write_byte_array_method() throws Exception {
given(blobBuilder = valuesDb.blobBuilder());
given(blobBuilder).write(bytes);
given(blob = blobBuilder.build());
when(inputStreamToByteArray(blob.openInputStream()));
thenReturned(bytes);
}
@Test
public void blob_has_content_passed_to_write_byte_array_with_range_method() throws Exception {
given(blobBuilder = valuesDb.blobBuilder());
given(blobBuilder).write(new byte[] { 1, 2, 3, 4, 5 }, 1, 3);
given(blob = blobBuilder.build());
when(inputStreamToByteArray(blob.openInputStream()));
thenReturned(new byte[] { 2, 3, 4 });
}
@Test
public void blobs_with_equal_content_are_equal() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(blob2 = createBlob(valuesDb, bytes));
when(blob);
thenReturned(blob2);
}
@Test
public void blobs_with_different_content_are_not_equal() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(blob2 = createBlob(valuesDb, otherBytes));
when(blob);
thenReturned(not(blob2));
}
@Test
public void hash_of_blobs_with_equal_content_is_the_same() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(blob2 = createBlob(valuesDb, bytes));
when(blob.hash());
thenReturned(blob2.hash());
}
@Test
public void hash_of_blobs_with_different_content_is_not_the_same() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(blob2 = createBlob(valuesDb, otherBytes));
when(blob.hash());
thenReturned(not(blob2.hash()));
}
@Test
public void hash_code_of_blob_with_equal_content_is_the_same() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(blob2 = createBlob(valuesDb, bytes));
when(blob.hashCode());
thenReturned(blob2.hashCode());
}
@Test
public void hash_code_of_blobs_with_different_values_is_not_the_same() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(blob2 = createBlob(valuesDb, otherBytes));
when(blob.hashCode());
thenReturned(not(blob2.hashCode()));
}
@Test
public void blob_can_be_fetch_by_hash() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(hash = blob.hash());
when(valuesDb.read(BLOB, hash));
thenReturned(blob);
}
@Test
public void blob_fetched_by_hash_has_same_content() throws Exception {
given(blob = createBlob(valuesDb, bytes));
given(hash = blob.hash());
when(inputStreamToByteArray(((Blob) valuesDb.read(BLOB, hash)).openInputStream()));
thenReturned(inputStreamToByteArray(blob.openInputStream()));
}
@Test
public void to_string_contains_type_name_and_bytes_count() throws Exception {
given(blob = createBlob(valuesDb, new byte[] { 1, 2, 3 }));
when(blob).toString();
thenReturned("Blob(3 bytes)");
}
private static Blob createBlob(ValuesDb valuesDb, byte[] content) throws Exception {
BlobBuilder blobBuilder = valuesDb.blobBuilder();
writeAndClose(blobBuilder, content);
return blobBuilder.build();
}
@Test
public void reading_not_stored_blob_fails() throws Exception {
given(hash = HashCode.fromInt(33));
given(blob = (Blob) valuesDb.read(BLOB, hash));
when(blob).openInputStream();
thenThrown(exception(new HashedDbException("Could not find " + hash + " object.")));
}
}