summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/test/java/com/amazon/carbonado/TestStorables.java505
-rw-r--r--src/test/java/com/amazon/carbonado/stored/SequenceAndAltKey.java44
-rw-r--r--src/test/java/com/amazon/carbonado/stored/StorableWithLobs.java47
3 files changed, 596 insertions, 0 deletions
diff --git a/src/test/java/com/amazon/carbonado/TestStorables.java b/src/test/java/com/amazon/carbonado/TestStorables.java
index b3824da..ecb7c8c 100644
--- a/src/test/java/com/amazon/carbonado/TestStorables.java
+++ b/src/test/java/com/amazon/carbonado/TestStorables.java
@@ -18,8 +18,13 @@
package com.amazon.carbonado;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+
import java.util.Comparator;
import java.util.List;
+import java.util.Random;
import junit.framework.TestCase;
import junit.framework.TestSuite;
@@ -46,6 +51,11 @@ import com.amazon.carbonado.UniqueConstraintException;
import com.amazon.carbonado.cursor.SortedCursor;
+import com.amazon.carbonado.lob.Blob;
+import com.amazon.carbonado.lob.ByteArrayBlob;
+import com.amazon.carbonado.lob.Clob;
+import com.amazon.carbonado.lob.StringClob;
+
import com.amazon.carbonado.spi.RepairExecutor;
import com.amazon.carbonado.gen.WrappedSupport;
@@ -1246,6 +1256,33 @@ public class TestStorables extends TestCase {
assertEquals("4", seq.getSomeString());
}
+ public void test_sequenceRollback() throws Exception {
+ // Make sure sequence does not rollback with the main
+ // transaction. Sequences must always increase, even if enclosing
+ // transaction rolls back. Otherwise, you get race conditions and
+ // sequence values might get re-used.
+
+ Storage<SequenceAndAltKey> storage = getRepository().storageFor(SequenceAndAltKey.class);
+
+ SequenceAndAltKey obj = storage.prepare();
+ obj.setName("foo");
+ obj.setData("hello");
+ obj.insert();
+
+ int lastID = obj.getID();
+
+ for (int i=0; i<10000; i++) {
+ obj = storage.prepare();
+ obj.setName("foo");
+ obj.setData("world");
+ // Alternate key constraint.
+ assertFalse(obj.tryInsert());
+ // Sequence must always increase, even if insert failed.
+ assertTrue(obj.getID() > lastID);
+ lastID = obj.getID();
+ }
+ }
+
public void test_oldIndexEntryDeletion() throws Exception {
// Very simple test that ensures that old index entries are deleted
// when the master record is updated. There is no guarantee that the
@@ -2288,6 +2325,474 @@ public class TestStorables extends TestCase {
assertEquals(total, actual);
}
+ public void test_lobInsert() throws Exception {
+ Storage<StorableWithLobs> storage = getRepository().storageFor(StorableWithLobs.class);
+
+ // Test null insert
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ lobs.load();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ }
+
+ // Test content insert
+ int id;
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world"));
+ lobs.insert();
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+ lobs.load();
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+ id = lobs.getId();
+ }
+
+ // Test update of inserted lobs
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setId(id);
+ lobs.load();
+
+ Blob blob = lobs.getBlobValue();
+ OutputStream out = blob.openOutputStream();
+ out.write("the sky is falling".getBytes());
+ out.close();
+
+ assertEquals("the sky is falling", blob.asString());
+
+ lobs.load();
+ assertEquals(blob, lobs.getBlobValue());
+
+ Clob clob = lobs.getClobValue();
+ Writer writer = clob.openWriter();
+ writer.write("the quick brown fox");
+ writer.close();
+
+ assertEquals("the quick brown fox", clob.asString());
+
+ lobs.load();
+ assertEquals(blob, lobs.getBlobValue());
+ assertEquals(clob, lobs.getClobValue());
+ }
+
+ // Test insert failure
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setId(id);
+
+ Blob newBlob = new ByteArrayBlob("blob insert should fail".getBytes());
+ Clob newClob = new StringClob("clob insert should fail");
+
+ lobs.setBlobValue(newBlob);
+ lobs.setClobValue(newClob);
+
+ try {
+ lobs.insert();
+ fail();
+ } catch (UniqueConstraintException e) {
+ }
+
+ assertTrue(newBlob == lobs.getBlobValue());
+ assertTrue(newClob == lobs.getClobValue());
+ }
+ }
+
+ public void test_lobUpdate() throws Exception {
+ Storage<StorableWithLobs> storage = getRepository().storageFor(StorableWithLobs.class);
+
+ // Test null replaces null
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+
+ lobs.setBlobValue(null);
+ lobs.setClobValue(null);
+
+ lobs.update();
+
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+
+ lobs.load();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ }
+
+ // Test null replaces content and verify content deleted
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world!!!"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ assertEquals(5, blob.getLength());
+ assertEquals(8, clob.getLength());
+
+ lobs.setBlobValue(null);
+
+ lobs.update();
+
+ assertNull(lobs.getBlobValue());
+ assertEquals(clob, lobs.getClobValue());
+
+ try {
+ blob.getLength();
+ fail();
+ } catch (FetchNoneException e) {
+ }
+ assertEquals(8, clob.getLength());
+
+ lobs.load();
+
+ assertNull(lobs.getBlobValue());
+ assertEquals(clob, lobs.getClobValue());
+
+ lobs.setClobValue(null);
+
+ lobs.update();
+
+ assertNull(lobs.getBlobValue());
+ assertNull(lobs.getClobValue());
+
+ try {
+ blob.getLength();
+ fail();
+ } catch (FetchNoneException e) {
+ }
+ try {
+ clob.getLength();
+ fail();
+ } catch (FetchNoneException e) {
+ }
+
+ lobs.load();
+
+ assertNull(lobs.getBlobValue());
+ assertNull(lobs.getClobValue());
+
+ try {
+ blob.setLength(100);
+ fail();
+ } catch (PersistNoneException e) {
+ }
+ try {
+ clob.setLength(100);
+ fail();
+ } catch (PersistNoneException e) {
+ }
+
+ try {
+ blob.setValue("hello");
+ fail();
+ } catch (PersistNoneException e) {
+ }
+ try {
+ clob.setValue("hello");
+ fail();
+ } catch (PersistNoneException e) {
+ }
+ }
+
+ // Test content replaces null
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world"));
+
+ assertTrue(lobs.getBlobValue() instanceof ByteArrayBlob);
+ assertTrue(lobs.getClobValue() instanceof StringClob);
+
+ lobs.update();
+
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+
+ assertFalse(lobs.getBlobValue() instanceof ByteArrayBlob);
+ assertFalse(lobs.getClobValue() instanceof StringClob);
+
+ lobs.load();
+
+ assertEquals("hello", lobs.getBlobValue().asString());
+ assertEquals("world", lobs.getClobValue().asString());
+
+ assertFalse(lobs.getBlobValue() instanceof ByteArrayBlob);
+ assertFalse(lobs.getClobValue() instanceof StringClob);
+ }
+
+ // Test content replaces content of same length
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.setBlobValue(new ByteArrayBlob("12345".getBytes()));
+ lobs.update();
+
+ assertEquals(5, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("12345", lobs.getBlobValue().asString());
+ assertEquals("world?", lobs.getClobValue().asString());
+
+ assertTrue(blob.equals(lobs.getBlobValue()));
+ assertTrue(clob.equals(lobs.getClobValue()));
+
+ lobs.setClobValue(new StringClob("123456"));
+ lobs.update();
+
+ assertEquals(5, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("12345", lobs.getBlobValue().asString());
+ assertEquals("123456", lobs.getClobValue().asString());
+
+ assertTrue(blob.equals(lobs.getBlobValue()));
+ assertTrue(clob.equals(lobs.getClobValue()));
+ }
+
+ // Test content replaces content of longer length
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.setBlobValue(new ByteArrayBlob("123".getBytes()));
+ lobs.update();
+
+ assertEquals(3, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("123", lobs.getBlobValue().asString());
+ assertEquals("world?", lobs.getClobValue().asString());
+
+ assertTrue(blob.equals(lobs.getBlobValue()));
+ assertTrue(clob.equals(lobs.getClobValue()));
+
+ lobs.setClobValue(new StringClob("12"));
+ lobs.update();
+
+ assertEquals(3, lobs.getBlobValue().getLength());
+ assertEquals(2, lobs.getClobValue().getLength());
+
+ assertEquals("123", lobs.getBlobValue().asString());
+ assertEquals("12", lobs.getClobValue().asString());
+
+ assertTrue(blob.equals(lobs.getBlobValue()));
+ assertTrue(clob.equals(lobs.getClobValue()));
+ }
+
+ // Test content replaces content of shorter length
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.setBlobValue(new ByteArrayBlob("123456789".getBytes()));
+ lobs.update();
+
+ assertEquals(9, lobs.getBlobValue().getLength());
+ assertEquals(6, lobs.getClobValue().getLength());
+
+ assertEquals("123456789", lobs.getBlobValue().asString());
+ assertEquals("world?", lobs.getClobValue().asString());
+
+ assertTrue(blob.equals(lobs.getBlobValue()));
+ assertTrue(clob.equals(lobs.getClobValue()));
+
+ lobs.setClobValue(new StringClob("1234567890"));
+ lobs.update();
+
+ assertEquals(9, lobs.getBlobValue().getLength());
+ assertEquals(10, lobs.getClobValue().getLength());
+
+ assertEquals("123456789", lobs.getBlobValue().asString());
+ assertEquals("1234567890", lobs.getClobValue().asString());
+
+ assertTrue(blob.equals(lobs.getBlobValue()));
+ assertTrue(clob.equals(lobs.getClobValue()));
+ }
+
+ // Test update failure
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setId(10000);
+
+ Blob newBlob = new ByteArrayBlob("blob update should fail".getBytes());
+ Clob newClob = new StringClob("clob update should fail");
+
+ lobs.setBlobValue(newBlob);
+ lobs.setClobValue(newClob);
+
+ try {
+ lobs.update();
+ fail();
+ } catch (PersistNoneException e) {
+ }
+
+ assertTrue(newBlob == lobs.getBlobValue());
+ assertTrue(newClob == lobs.getClobValue());
+ }
+ }
+
+ public void test_lobDelete() throws Exception {
+ Storage<StorableWithLobs> storage = getRepository().storageFor(StorableWithLobs.class);
+
+ // Test delete of null lob
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.insert();
+ lobs.delete();
+ assertEquals(null, lobs.getBlobValue());
+ assertEquals(null, lobs.getClobValue());
+ }
+
+ // Test delete of non-null lob
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob("hello".getBytes()));
+ lobs.setClobValue(new StringClob("world?"));
+ lobs.insert();
+
+ Blob blob = lobs.getBlobValue();
+ Clob clob = lobs.getClobValue();
+
+ lobs.delete();
+
+ try {
+ blob.getLength();
+ fail();
+ } catch (FetchNoneException e) {
+ }
+
+ try {
+ clob.getLength();
+ fail();
+ } catch (FetchNoneException e) {
+ }
+
+ try {
+ blob.setLength(100);
+ fail();
+ } catch (PersistNoneException e) {
+ }
+ try {
+ clob.setLength(100);
+ fail();
+ } catch (PersistNoneException e) {
+ }
+
+ try {
+ blob.setValue("hello");
+ fail();
+ } catch (PersistNoneException e) {
+ }
+ try {
+ clob.setValue("hello");
+ fail();
+ } catch (PersistNoneException e) {
+ }
+ }
+
+ // Test delete failure
+ {
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setId(10000);
+
+ Blob newBlob = new ByteArrayBlob("blob update should fail".getBytes());
+ Clob newClob = new StringClob("clob update should fail");
+
+ lobs.setBlobValue(newBlob);
+ lobs.setClobValue(newClob);
+
+ try {
+ lobs.delete();
+ fail();
+ } catch (PersistNoneException e) {
+ }
+
+ assertTrue(newBlob == lobs.getBlobValue());
+ assertTrue(newClob == lobs.getClobValue());
+ }
+ }
+
+ public void test_insertLobBig() throws Exception {
+ // LobEngine tests are fairly exhaustive when it comes to large
+ // content. This is just a basic check.
+
+ final long seed = 287623451234L;
+ final int length = 123456;
+
+ Storage<StorableWithLobs> storage = getRepository().storageFor(StorableWithLobs.class);
+
+ StorableWithLobs lobs = storage.prepare();
+ lobs.setBlobValue(new ByteArrayBlob(1));
+ lobs.insert();
+
+ Random rnd = new Random(seed);
+ OutputStream out = lobs.getBlobValue().openOutputStream(0, 500);
+ for (int i=0; i<length; i++) {
+ out.write(rnd.nextInt());
+ }
+ out.close();
+
+ assertEquals(length, lobs.getBlobValue().getLength());
+
+ lobs.load();
+
+ rnd = new Random(seed);
+ InputStream in = lobs.getBlobValue().openInputStream(0, 2000);
+ for (int i=0; i<length; i++) {
+ assertEquals(rnd.nextInt() & 0xff, in.read());
+ }
+ assertEquals(-1, in.read());
+ in.close();
+
+ // Verify content stored in StoredLob.Block.
+ // Only applicable if LobEngine is used.
+ /*
+ Query<StoredLob.Block> query = getRepository().storageFor(StoredLob.Block.class).query();
+ Cursor<StoredLob.Block> cursor = query.fetch();
+ assertTrue(cursor.hasNext());
+ cursor.close();
+
+ // Verify its all gone after delete.
+ lobs.delete();
+
+ cursor = query.fetch();
+ assertFalse(cursor.hasNext());
+ cursor.close();
+
+ // Master record should be gone too.
+ Cursor<?> c = getRepository().storageFor(StoredLob.class).query().fetch();
+ assertFalse(c.hasNext());
+ c.close();
+ */
+ }
+
private void assertUninitialized(boolean expected, Storable storable, String... properties) {
for (String property : properties) {
assertEquals(expected, storable.isPropertyUninitialized(property));
diff --git a/src/test/java/com/amazon/carbonado/stored/SequenceAndAltKey.java b/src/test/java/com/amazon/carbonado/stored/SequenceAndAltKey.java
new file mode 100644
index 0000000..564a501
--- /dev/null
+++ b/src/test/java/com/amazon/carbonado/stored/SequenceAndAltKey.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed 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 com.amazon.carbonado.stored;
+
+import com.amazon.carbonado.AlternateKeys;
+import com.amazon.carbonado.Key;
+import com.amazon.carbonado.PrimaryKey;
+import com.amazon.carbonado.Sequence;
+import com.amazon.carbonado.Storable;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+@PrimaryKey("ID")
+@AlternateKeys(@Key("name"))
+public interface SequenceAndAltKey extends Storable {
+ @Sequence("SEQ_ID")
+ int getID();
+ void setID(int id);
+
+ String getName();
+ void setName(String name);
+
+ String getData();
+ void setData(String data);
+}
diff --git a/src/test/java/com/amazon/carbonado/stored/StorableWithLobs.java b/src/test/java/com/amazon/carbonado/stored/StorableWithLobs.java
new file mode 100644
index 0000000..5f3b0bc
--- /dev/null
+++ b/src/test/java/com/amazon/carbonado/stored/StorableWithLobs.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2006 Amazon Technologies, Inc. or its affiliates.
+ * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks
+ * of Amazon Technologies, Inc. or its affiliates. All rights reserved.
+ *
+ * Licensed 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 com.amazon.carbonado.stored;
+
+import com.amazon.carbonado.Nullable;
+import com.amazon.carbonado.Sequence;
+import com.amazon.carbonado.Storable;
+import com.amazon.carbonado.PrimaryKey;
+
+import com.amazon.carbonado.lob.Blob;
+import com.amazon.carbonado.lob.Clob;
+
+/**
+ *
+ *
+ * @author Brian S O'Neill
+ */
+@PrimaryKey("id")
+public interface StorableWithLobs extends Storable {
+ @Sequence("foo")
+ int getId();
+ void setId(int id);
+
+ @Nullable
+ Blob getBlobValue();
+ void setBlobValue(Blob value);
+
+ @Nullable
+ Clob getClobValue();
+ void setClobValue(Clob value);
+}