Moving toward more standard project layout.

This commit is contained in:
Michael Bayne
2010-08-27 17:47:07 +00:00
parent 5a97565eaa
commit 6778ada227
14 changed files with 42 additions and 55 deletions
@@ -0,0 +1,199 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Arrays;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.annotation.Column;
import com.samskivert.depot.annotation.Id;
/**
* Tests all of the supported Depot field types.
*/
public class AllTypesRecord extends PersistentRecord
{
// AUTO-GENERATED: FIELDS START
public static final Class<AllTypesRecord> _R = AllTypesRecord.class;
public static final ColumnExp RECORD_ID = colexp(_R, "recordId");
public static final ColumnExp BOOLEAN_VALUE = colexp(_R, "booleanValue");
public static final ColumnExp BYTE_VALUE = colexp(_R, "byteValue");
public static final ColumnExp SHORT_VALUE = colexp(_R, "shortValue");
public static final ColumnExp INT_VALUE = colexp(_R, "intValue");
public static final ColumnExp LONG_VALUE = colexp(_R, "longValue");
public static final ColumnExp FLOAT_VALUE = colexp(_R, "floatValue");
public static final ColumnExp DOUBLE_VALUE = colexp(_R, "doubleValue");
public static final ColumnExp BOXED_BOOLEAN = colexp(_R, "boxedBoolean");
public static final ColumnExp BOXED_BYTE = colexp(_R, "boxedByte");
public static final ColumnExp BOXED_SHORT = colexp(_R, "boxedShort");
public static final ColumnExp BOXED_INT = colexp(_R, "boxedInt");
public static final ColumnExp BOXED_LONG = colexp(_R, "boxedLong");
public static final ColumnExp BOXED_FLOAT = colexp(_R, "boxedFloat");
public static final ColumnExp BOXED_DOUBLE = colexp(_R, "boxedDouble");
public static final ColumnExp BYTE_ARRAY = colexp(_R, "byteArray");
public static final ColumnExp INT_ARRAY = colexp(_R, "intArray");
public static final ColumnExp STRING = colexp(_R, "string");
public static final ColumnExp DATE = colexp(_R, "date");
public static final ColumnExp TIME = colexp(_R, "time");
public static final ColumnExp TIMESTAMP = colexp(_R, "timestamp");
public static final ColumnExp NULL_BOXED_BOOLEAN = colexp(_R, "nullBoxedBoolean");
public static final ColumnExp NULL_BOXED_BYTE = colexp(_R, "nullBoxedByte");
public static final ColumnExp NULL_BOXED_SHORT = colexp(_R, "nullBoxedShort");
public static final ColumnExp NULL_BOXED_INT = colexp(_R, "nullBoxedInt");
public static final ColumnExp NULL_BOXED_LONG = colexp(_R, "nullBoxedLong");
public static final ColumnExp NULL_BOXED_FLOAT = colexp(_R, "nullBoxedFloat");
public static final ColumnExp NULL_BOXED_DOUBLE = colexp(_R, "nullBoxedDouble");
public static final ColumnExp NULL_BYTE_ARRAY = colexp(_R, "nullByteArray");
public static final ColumnExp NULL_INT_ARRAY = colexp(_R, "nullIntArray");
public static final ColumnExp NULL_STRING = colexp(_R, "nullString");
public static final ColumnExp NULL_DATE = colexp(_R, "nullDate");
public static final ColumnExp NULL_TIME = colexp(_R, "nullTime");
public static final ColumnExp NULL_TIMESTAMP = colexp(_R, "nullTimestamp");
// AUTO-GENERATED: FIELDS END
public static final int SCHEMA_VERSION = 1;
@Id public int recordId;
public boolean booleanValue;
public byte byteValue;
public short shortValue;
public int intValue;
public long longValue;
public float floatValue;
public double doubleValue;
public Boolean boxedBoolean;
public Byte boxedByte;
public Short boxedShort;
public Integer boxedInt;
public Long boxedLong;
public Float boxedFloat;
public Double boxedDouble;
public byte[] byteArray;
public int[] intArray;
public String string;
public Date date;
public Time time;
public Timestamp timestamp;
// public Blob blob; // tested by byte[]
// public Clob clob; // not clear how to test this
@Column(nullable=true) public Boolean nullBoxedBoolean;
@Column(nullable=true) public Byte nullBoxedByte;
@Column(nullable=true) public Short nullBoxedShort;
@Column(nullable=true) public Integer nullBoxedInt;
@Column(nullable=true) public Long nullBoxedLong;
@Column(nullable=true) public Float nullBoxedFloat;
@Column(nullable=true) public Double nullBoxedDouble;
@Column(nullable=true) public byte[] nullByteArray;
@Column(nullable=true) public int[] nullIntArray;
@Column(nullable=true) public String nullString;
@Column(nullable=true) public Date nullDate;
@Column(nullable=true) public Time nullTime;
@Column(nullable=true) public Timestamp nullTimestamp;
@Override public boolean equals (Object other) {
if (!(other instanceof AllTypesRecord)) {
return false;
}
AllTypesRecord orec = (AllTypesRecord)other;
return (booleanValue == orec.booleanValue) &&
(byteValue == orec.byteValue) &&
(shortValue == orec.shortValue) &&
(intValue == orec.intValue) &&
(longValue == orec.longValue) &&
(floatValue == orec.floatValue) &&
(doubleValue == orec.doubleValue) &&
boxedBoolean.equals(orec.boxedBoolean) &&
boxedByte.equals(orec.boxedByte) &&
boxedShort.equals(orec.boxedShort) &&
boxedInt.equals(orec.boxedInt) &&
boxedLong.equals(orec.boxedLong) &&
boxedFloat.equals(orec.boxedFloat) &&
boxedDouble.equals(orec.boxedDouble) &&
Arrays.equals(byteArray, orec.byteArray) &&
Arrays.equals(intArray, orec.intArray) &&
string.equals(orec.string) &&
date.equals(orec.date) &&
time.equals(orec.time) &&
timestamp.equals(orec.timestamp) &&
(nullBoxedBoolean == orec.nullBoxedBoolean) &&
(nullBoxedByte == orec.nullBoxedByte) &&
(nullBoxedShort == orec.nullBoxedShort) &&
(nullBoxedInt == orec.nullBoxedInt) &&
(nullBoxedLong == orec.nullBoxedLong) &&
(nullBoxedFloat == orec.nullBoxedFloat) &&
(nullBoxedDouble == orec.nullBoxedDouble) &&
(nullByteArray == orec.nullByteArray) &&
(nullIntArray == orec.nullIntArray) &&
(nullString == orec.nullString) &&
(nullDate == orec.nullDate) &&
(nullTime == orec.nullTime) &&
(nullTimestamp == orec.nullTimestamp);
}
public static AllTypesRecord createRecord (int recordId)
{
AllTypesRecord rec = new AllTypesRecord();
rec.recordId = recordId;
rec.booleanValue = true;
rec.byteValue = 1;
rec.shortValue = 2;
rec.intValue = 3;
rec.longValue = 4;
rec.floatValue = 5.5f;
rec.doubleValue = 6.6;
rec.boxedBoolean = true;
rec.boxedByte = 7;
rec.boxedShort = 8;
rec.boxedInt = 9;
rec.boxedLong = 10l;
rec.boxedFloat = 11.11f;
rec.boxedDouble = 12.12;
rec.byteArray = new byte[] { 13, 14 };
rec.intArray = new int[] { 15, 16 };
rec.string = "seventeen";
rec.date = Date.valueOf("2010-01-18");
rec.time = Time.valueOf("19:19:19");
rec.timestamp = new Timestamp(System.currentTimeMillis()+20);
return rec;
}
// AUTO-GENERATED: METHODS START
/**
* Create and return a primary {@link Key} to identify a {@link AllTypesRecord}
* with the supplied key values.
*/
public static Key<AllTypesRecord> getKey (int recordId)
{
return newKey(_R, recordId);
}
/** Register the key fields in an order matching the getKey() factory. */
static { registerKeyFields(RECORD_ID); }
// AUTO-GENERATED: METHODS END
}
@@ -0,0 +1,72 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Tests the handling of our various supported field types.
*/
public class AllTypesTest extends TestBase
{
@Test public void testCreateReadDelete ()
{
AllTypesRecord in = AllTypesRecord.createRecord(1);
_repo.insert(in);
AllTypesRecord out = _repo.loadNoCache(in.recordId);
assertNotNull(out != null); // we got a result
assertTrue(in != out); // it didn't come from the cache
// make sure all of the fields were marshalled and unmarshalled correctly
assertEquals(in, out);
// finally clean up after ourselves
_repo.delete(AllTypesRecord.getKey(in.recordId));
assertNull(_repo.loadNoCache(in.recordId));
}
protected static class TestRepository extends DepotRepository
{
public AllTypesRecord loadNoCache (int recordId)
{
return load(AllTypesRecord.getKey(recordId), CacheStrategy.NONE);
}
public TestRepository (PersistenceContext perCtx)
{
super(perCtx);
}
@Override // from DepotRepository
protected void getManagedRecords (Set<Class<? extends PersistentRecord>> classes)
{
classes.add(AllTypesRecord.class);
}
}
// the HSQL in-memory database persists for the lifetime of the VM, which means we have to
// clean up after ourselves in every test; thus we go ahead and share a repository
protected TestRepository _repo = new TestRepository(createPersistenceContext());
}
@@ -0,0 +1,77 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.lang.reflect.Field;
import org.junit.Test;
import static org.junit.Assert.*;
import com.samskivert.util.ByteEnum;
import com.samskivert.depot.impl.FieldMarshaller;
/**
* Tests ByteEnum related bits.
*/
public class ByteEnumTest
{
public enum TestEnum implements ByteEnum {
ONE(1), TWO(2), THREE(3);
// from interface ByteEnum
public byte toByte () {
return _code;
}
TestEnum (int code) {
_code = (byte)code;
}
protected byte _code;
}
public class NotAnEnum implements ByteEnum {
public byte toByte () {
return 0;
}
}
public static class TestRecord extends PersistentRecord
{
public TestEnum good;
public NotAnEnum bad;
}
@Test public void testMarshaller ()
throws NoSuchFieldException
{
Field good = TestRecord.class.getField("good");
Field bad = TestRecord.class.getField("bad");
assertTrue(FieldMarshaller.createMarshaller(good) != null);
try {
FieldMarshaller.createMarshaller(bad);
fail();
} catch (IllegalArgumentException iae) {
// expected
}
}
}
@@ -0,0 +1,82 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.util.Arrays;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Tests simple create/read/update/delete behaviors.
*/
public class CrudTest extends TestBase
{
@Test public void testCreateReadDelete ()
{
TestRecord in = createTestRecord(1);
_repo.insert(in);
TestRecord out = _repo.loadNoCache(in.recordId);
assertNotNull(out != null); // we got a result
assertTrue(in != out); // it didn't come from the cache
// make sure all of the fields were marshalled and unmarshalled correctly
assertTestRecordEquals(in, out);
// finally clean up after ourselves
_repo.delete(TestRecord.getKey(in.recordId));
assertNull(_repo.loadNoCache(in.recordId));
}
@Test public void testUpdateDelete ()
{
TestRecord in = createTestRecord(1);
_repo.insert(in);
// first try updating using the whole-record update mechanism
in.homeTown = "Funky Town";
_repo.update(in);
assertTestRecordEquals(in, _repo.loadNoCache(in.recordId));
// then try update partial
String name = "Bob";
int age = 25;
int[] numbers = { 1, 2, 3, 4, 5 };
_repo.updatePartial(TestRecord.getKey(in.recordId),
ImmutableMap.of(TestRecord.NAME, name, TestRecord.AGE, age,
TestRecord.NUMBERS, numbers));
TestRecord up = _repo.loadNoCache(in.recordId);
assertEquals(name, up.name);
assertEquals(age, up.age);
assertTrue(Arrays.equals(numbers, up.numbers));
// finally clean up after ourselves
_repo.delete(TestRecord.getKey(in.recordId));
assertNull(_repo.loadNoCache(in.recordId));
}
// the HSQL in-memory database persists for the lifetime of the VM, which means we have to
// clean up after ourselves in every test; thus we go ahead and share a repository
protected TestRepository _repo = createTestRepository();
}
@@ -0,0 +1,68 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import org.junit.Test;
import static org.junit.Assert.*;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.impl.DepotUtil;
/**
* Tests some super basic {@link Key} stuff.
*/
public class KeyTest
{
@Test public void testSlowConstructor ()
{
int species = 10, monkeyId = 15;
Key<MonkeyRecord> key = MonkeyRecord.getKey(species, monkeyId);
// make sure that the arguments we passed in got assigned in the right positions
ColumnExp[] kfs = DepotUtil.getKeyFields(MonkeyRecord.class);
int kspecies = 0, kmonkeyId = 0;
for (int ii = 0; ii < kfs.length; ii++) {
if (MonkeyRecord.SPECIES.equals(kfs[ii])) {
kspecies = (Integer)(key.getValues()[ii]);
} else if (MonkeyRecord.MONKEY_ID.equals(kfs[ii])) {
kmonkeyId = (Integer)(key.getValues()[ii]);
}
}
assertEquals(species, kspecies);
assertEquals(monkeyId, kmonkeyId);
}
@Test public void testFastConstructor ()
{
int recordId = 10;
Key<TestRecord> key = TestRecord.getKey(recordId);
// make sure that the arguments we passed in got assigned in the right positions
ColumnExp[] kfs = DepotUtil.getKeyFields(TestRecord.class);
int krecordId = 0;
for (int ii = 0; ii < kfs.length; ii++) {
if (TestRecord.RECORD_ID.equals(kfs[ii])) {
krecordId = (Integer)(key.getValues()[ii]);
}
}
assertEquals(recordId, krecordId);
}
}
@@ -0,0 +1,59 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.annotation.Id;
/**
* Used for testing.
*/
public class MonkeyRecord extends PersistentRecord
{
// AUTO-GENERATED: FIELDS START
public static final Class<MonkeyRecord> _R = MonkeyRecord.class;
public static final ColumnExp SPECIES = colexp(_R, "species");
public static final ColumnExp MONKEY_ID = colexp(_R, "monkeyId");
public static final ColumnExp NAME = colexp(_R, "name");
// AUTO-GENERATED: FIELDS END
/** This monkey's species. This is part of our key so that we have a composite key. */
@Id public int species;
/** This monkey's unique identifier. */
@Id public int monkeyId;
public String name;
// AUTO-GENERATED: METHODS START
/**
* Create and return a primary {@link Key} to identify a {@link MonkeyRecord}
* with the supplied key values.
*/
public static Key<MonkeyRecord> getKey (int species, int monkeyId)
{
return newKey(_R, species, monkeyId);
}
/** Register the key fields in an order matching the getKey() factory. */
static { registerKeyFields(SPECIES, MONKEY_ID); }
// AUTO-GENERATED: METHODS END
}
@@ -0,0 +1,100 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.util.Collections;
import com.google.common.collect.Sets;
import com.samskivert.util.RandomUtil;
import org.junit.Test;
import static org.junit.Assert.*;
import com.samskivert.depot.annotation.Computed;
import com.samskivert.depot.clause.Where;
/**
* Tests queries.
*/
public class QueryTest extends TestBase
{
@Computed(shadowOf=TestRecord.class)
public static class TestNameRecord extends PersistentRecord
{
public int recordId;
public String name;
@Override public String toString () {
return recordId + ":" + name;
}
}
@Test public void testQueries ()
{
for (int ii = 1; ii <= CREATE_RECORDS; ii++) {
TestRecord record = createTestRecord(ii);
record.name = "Spam! " + ii;
record.age = RandomUtil.getInt(100);
record.homeTown = "Over there";
_repo.insert(record);
}
// test the empty key set
KeySet<TestRecord> none = KeySet.newKeySet(
TestRecord.class, Collections.<Key<TestRecord>>emptySet());
assertEquals(0, _repo.deleteAll(TestRecord.class, none));
// test collection caching (TODO: check that the records are ==)
Where where = new Where(TestRecord.RECORD_ID.greaterThan(CREATE_RECORDS-50));
assertEquals(50, _repo.findAll(TestRecord.class, where).size());
assertEquals(50, _repo.findAll(TestRecord.class, where).size());
// test a partial key set
KeySet<TestRecord> some = KeySet.newSimpleKeySet(
TestRecord.class, Sets.newHashSet(1, 3, 5, 7, 9));
assertEquals(5, _repo.loadAll(some.toCollection()).size());
// make sure our computed records work
for (TestNameRecord tnr : _repo.findAll(TestNameRecord.class)) {
assertEquals("Spam! " + tnr.recordId, tnr.name);
}
assertEquals(CREATE_RECORDS, _repo.findAll(TestRecord.class).size());
_repo.deleteAll(TestRecord.class, new Where(TestRecord.RECORD_ID.lessEq(CREATE_RECORDS/2)));
assertEquals(CREATE_RECORDS/2, _repo.findAll(TestRecord.class).size());
_repo.deleteAll(TestRecord.class, new Where(Exps.literal("true")));
assertEquals(0, _repo.findAll(TestRecord.class).size());
// // TODO: try to break our In() clause
// Set<Integer> ids = Sets.newHashSet();
// for (int ii = 1; ii <= In.MAX_KEYS*2+3; ii++) {
// ids.add(ii);
// }
// _repo.deleteAll(TestRecord.class, KeySet.newSimpleKeySet(TestRecord.class, ids));
}
// the HSQL in-memory database persists for the lifetime of the VM, which means we have to
// clean up after ourselves in every test; thus we go ahead and share a repository
protected TestRepository _repo = createTestRepository();
protected static final int CREATE_RECORDS = 150;
}
@@ -0,0 +1,96 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Properties;
import com.samskivert.jdbc.StaticConnectionProvider;
import com.samskivert.util.Calendars;
import static org.junit.Assert.*;
/**
* Contains shared code to set up in-memory databases for unit testing.
*/
public abstract class TestBase
{
/**
* Creates a persistence context configured to run against an (empty) in-memory HSQLDB.
* <b>Note:</b> the in-memory HSQL database is shared for the duration of the VM, so tests have
* to clean up after themselves to avoid conflicting with one another.
*/
protected PersistenceContext createPersistenceContext ()
{
Properties props = new Properties();
props.put("default.driver", "org.hsqldb.jdbcDriver");
props.put("default.url", "jdbc:hsqldb:mem:test");
props.put("default.username", "sa");
props.put("default.password", "");
PersistenceContext perCtx = new PersistenceContext();
perCtx.init("test", new StaticConnectionProvider(props), new TestCacheAdapter());
return perCtx;
}
/**
* If a test doesn't need any special repository setup, it can use this method to create a
* fresh persistence context and test repository in one fell swoop.
*/
protected TestRepository createTestRepository ()
{
return new TestRepository(createPersistenceContext());
}
/**
* Creates a test record with all fields initialized to valid values.
*/
protected TestRecord createTestRecord (int recordId)
{
Date now = Calendars.now().zeroTime().toSQLDate();
Timestamp tnow = new Timestamp(System.currentTimeMillis());
TestRecord rec = new TestRecord();
rec.recordId = recordId;
rec.name = "Elvis";
rec.age = 99;
rec.created = now;
rec.homeTown = "Right here";
rec.lastModified = tnow;
rec.numbers = new int[] { 9, 0, 2, 1, 0 };
return rec;
}
/**
* Confirms that the supplied test records are field-by-field equal.
*/
protected void assertTestRecordEquals (TestRecord expect, TestRecord got)
{
assertEquals(expect.recordId, got.recordId);
assertEquals(expect.name, got.name);
assertEquals(expect.age, got.age);
assertEquals(expect.created, got.created);
assertEquals(expect.homeTown, got.homeTown);
assertEquals(expect.lastModified, got.lastModified);
assertTrue(Arrays.equals(expect.numbers, got.numbers));
}
}
@@ -0,0 +1,86 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2008 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.samskivert.util.Tuple;
/**
* A simple cache adapter that stores all cached values in an in-memory map and never flushes.
* Don't use this for anything other than testing or you'll regret it.
*/
public class TestCacheAdapter implements CacheAdapter
{
// from interface CacheAdapter
public void shutdown ()
{
// nothing doing!
}
protected static class TestCachedValue<T> implements CacheAdapter.CachedValue<T>
{
public TestCachedValue (T value) {
_value = value;
}
public T getValue () {
return _value;
}
protected final T _value;
}
public <T> CacheAdapter.CachedValue<T> lookup (String cacheId, Serializable key) {
// System.err.println("GET " + key + ": " + _cache.containsKey(key));
@SuppressWarnings("unchecked")
CachedValue<T> value = (CachedValue<T>) _cache.get(
new Tuple<String, Serializable>(cacheId, key));
return value;
}
public <T> void store (CacheCategory category, String cacheId, Serializable key, T value) {
// System.err.println("STORE " + key);
_cache.put(new Tuple<String, Serializable>(cacheId, key), new TestCachedValue<T>(value));
}
public void remove (String cacheId, Serializable key) {
// System.err.println("REMOVE " + key);
_cache.remove(new Tuple<String, Serializable>(cacheId, key));
}
public <T> Iterable<Serializable> enumerate (String cacheId)
{
// in a real implementation this would be a lazily constructed iterable
List<Serializable> result = Lists.newArrayList();
for (Map.Entry<Tuple<String, Serializable>, CachedValue<?>> entry: _cache.entrySet()) {
if (entry.getKey().left.equals(cacheId)) {
result.add(entry.getKey().right);
}
}
return result;
}
protected Map<Tuple<String, Serializable>, CachedValue<?>> _cache =
Collections.synchronizedMap(
Maps.<Tuple<String, Serializable>, CachedValue<?>>newHashMap());
}
@@ -0,0 +1,87 @@
//
// $Id$
//
// samskivert library - useful routines for java programs
// Copyright (C) 2006-2008 Michael Bayne, Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.sql.Date;
import java.sql.Timestamp;
import com.samskivert.util.StringUtil;
import com.samskivert.depot.annotation.Entity;
import com.samskivert.depot.annotation.Id;
import com.samskivert.depot.annotation.Index;
import com.samskivert.depot.expression.ColumnExp;
/**
* A test persistent object.
*/
@Entity
public class TestRecord extends PersistentRecord
{
// AUTO-GENERATED: FIELDS START
public static final Class<TestRecord> _R = TestRecord.class;
public static final ColumnExp RECORD_ID = colexp(_R, "recordId");
public static final ColumnExp NAME = colexp(_R, "name");
public static final ColumnExp AGE = colexp(_R, "age");
public static final ColumnExp HOME_TOWN = colexp(_R, "homeTown");
public static final ColumnExp CREATED = colexp(_R, "created");
public static final ColumnExp LAST_MODIFIED = colexp(_R, "lastModified");
public static final ColumnExp NUMBERS = colexp(_R, "numbers");
// AUTO-GENERATED: FIELDS END
public static final int SCHEMA_VERSION = 3;
@Id
public int recordId;
public String name;
public int age;
public String homeTown;
// @Index // TODO: this horks HSQLDB
public Date created;
public Timestamp lastModified;
public int[] numbers;
@Override
public String toString ()
{
return StringUtil.fieldsToString(this);
}
// AUTO-GENERATED: METHODS START
/**
* Create and return a primary {@link Key} to identify a {@link TestRecord}
* with the supplied key values.
*/
public static Key<TestRecord> getKey (int recordId)
{
return newKey(_R, recordId);
}
/** Register the key fields in an order matching the getKey() factory. */
static { registerKeyFields(RECORD_ID); }
// AUTO-GENERATED: METHODS END
}
@@ -0,0 +1,50 @@
//
// $Id$
//
// samskivert library - useful routines for java programs
// Copyright (C) 2006-2008 Michael Bayne, Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.util.Set;
/**
* A test tool for the Depot repository services.
*/
public class TestRepository extends DepotRepository
{
public TestRecord loadNoCache (int recordId)
{
return load(TestRecord.getKey(recordId), CacheStrategy.NONE);
}
public TestRecord loadWithCache (int recordId)
{
return load(TestRecord.getKey(recordId));
}
public TestRepository (PersistenceContext perCtx)
{
super(perCtx);
}
@Override // from DepotRepository
protected void getManagedRecords (Set<Class<? extends PersistentRecord>> classes)
{
classes.add(TestRecord.class);
}
}
@@ -0,0 +1,289 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.samskivert.util.ByteEnum;
import com.samskivert.depot.Key;
import com.samskivert.depot.expression.ColumnExp;
import com.samskivert.depot.annotation.Column;
import com.samskivert.depot.annotation.Id;
import com.samskivert.depot.annotation.Transform;
import com.samskivert.depot.impl.FieldMarshaller;
import static org.junit.Assert.*;
/**
* Tests the @Transform annotation.
*/
public class TransformTest extends TestBase
{
@Transform(CustomTypeTransformer.class)
public static class CustomType
{
public final String value;
public CustomType (String value) {
this.value = value;
}
@Override public boolean equals (Object other) {
return (other instanceof CustomType) && value.equals(((CustomType)other).value);
}
@Override public int hashCode () {
return value.hashCode();
}
}
@Transform(CustomTypeTransformer.class)
public static class InvalidCustomType
{
}
@Transform(ShortEnumTransformer.class)
public static interface ShortEnum
{
public short toShort ();
}
public enum Ordinal implements ShortEnum {
ONE(1), TWO(2), THREE(3);
public short toShort () {
return _code;
}
Ordinal (int code) {
_code = (short)code;
}
protected short _code;
}
public enum ExtraOrdinal implements ByteEnum {
ONE, TWO, THREE;
public byte toByte () {
return (byte)ordinal(); // sufficient for testing
}
}
public static class CustomTypeTransformer implements Transformer<CustomType, String>
{
public String toPersistent (CustomType value) {
return value.value;
}
public CustomType fromPersistent (Type ftype, String value) {
return new CustomType(value);
}
}
public static class ShortEnumTransformer implements Transformer<ShortEnum, Short>
{
public Short toPersistent (ShortEnum value) {
return value.toShort();
}
public ShortEnum fromPersistent (Type ftype, Short value) {
@SuppressWarnings("unchecked") Class<Dummy> eclass = (Class<Dummy>)ftype;
return fromShort(eclass, value);
}
private enum Dummy implements ShortEnum {
DUMMY;
public short toShort () { return 0; }
};
}
public static class TransformRecord extends PersistentRecord
{
// AUTO-GENERATED: FIELDS START
public static final Class<TransformRecord> _R = TransformRecord.class;
public static final ColumnExp RECORD_ID = colexp(_R, "recordId");
public static final ColumnExp STRINGS = colexp(_R, "strings");
public static final ColumnExp STRING_LIST = colexp(_R, "stringList");
public static final ColumnExp STRING_SET = colexp(_R, "stringSet");
public static final ColumnExp CUSTOM = colexp(_R, "custom");
public static final ColumnExp ORDINAL = colexp(_R, "ordinal");
public static final ColumnExp BOBS = colexp(_R, "bobs");
// AUTO-GENERATED: FIELDS END
public static final int SCHEMA_VERSION = 1;
@Id public int recordId;
@Column(nullable=true) @Transform(Transformers.StringArray.class)
public String[] strings;
@Column(nullable=true) @Transform(Transformers.StringIterable.class)
public List<String> stringList;
@Column(nullable=true) @Transform(Transformers.StringIterable.class)
public Set<String> stringSet;
public CustomType custom;
public Ordinal ordinal;
@Transform(Transformers.ByteEnumSet.class)
public Set<ExtraOrdinal> bobs;
// AUTO-GENERATED: METHODS START
/**
* Create and return a primary {@link Key} to identify a {@link TestRecord}
* with the supplied key values.
*/
public static Key<TransformRecord> getKey (int recordId)
{
return newKey(_R, recordId);
}
/** Register the key fields in an order matching the getKey() factory. */
static { registerKeyFields(RECORD_ID); }
// AUTO-GENERATED: METHODS END
}
public static class BadTransformRecord extends PersistentRecord
{
@Transform(Transformers.StringArray.class)
public Thread thread;
public InvalidCustomType invalid;
}
@Test public void testValidAnnotations ()
throws NoSuchFieldException
{
Field field = TransformRecord.class.getField("strings");
assertTrue(FieldMarshaller.createMarshaller(field) != null);
field = TransformRecord.class.getField("custom");
assertTrue(FieldMarshaller.createMarshaller(field).getClass().
getName().endsWith("FieldMarshaller$TransformingMarshaller"));
}
@Test public void testInvalidFieldAnnotation ()
throws NoSuchFieldException
{
try {
Field field = BadTransformRecord.class.getField("thread");
FieldMarshaller.createMarshaller(field);
fail();
} catch (IllegalArgumentException iae) {
assertTrue(iae.getMessage().indexOf("@Transform error") != -1);
}
}
@Test public void testInvalidTypeAnnotation ()
throws NoSuchFieldException
{
try {
Field field = BadTransformRecord.class.getField("invalid");
FieldMarshaller.createMarshaller(field);
fail();
} catch (IllegalArgumentException iae) {
assertTrue(iae.getMessage().indexOf("@Transform error") != -1);
}
}
@Test public void testCreateReadDelete ()
{
testCreateReadDelete(new String[] { "one", "two", "three" });
testCreateReadDelete(new String[] { ",", null, "" });
testCreateReadDelete(new String[] { "" });
testCreateReadDelete(new String[] {});
testCreateReadDelete(null);
testCreateReadDelete(new String[] { "", "\n", "", "\n\n" });
}
protected void testCreateReadDelete (String[] strings)
{
TransformRecord in = new TransformRecord();
in.recordId = 1;
in.strings = strings;
in.stringList = (strings == null) ? null : Lists.newArrayList(strings);
in.stringSet = (strings == null) ? null : Sets.newHashSet(strings);
in.custom = new CustomType("custom");
in.ordinal = Ordinal.THREE;
in.bobs = EnumSet.of(ExtraOrdinal.TWO);
_repo.insert(in);
TransformRecord out = _repo.loadNoCache(in.recordId);
assertNotNull(out != null); // we got a result
assertTrue(in != out); // it didn't come from the cache
// make sure all of the fields were marshalled and unmarshalled correctly
assertEquals(in.recordId, out.recordId);
assertArrayEquals(in.strings, out.strings);
assertTrue(Objects.equal(in.stringList, out.stringList));
assertTrue(Objects.equal(in.stringSet, out.stringSet));
assertEquals(in.custom, out.custom);
assertEquals(in.ordinal, out.ordinal);
assertEquals(in.bobs, out.bobs);
// finally clean up after ourselves
_repo.delete(TransformRecord.getKey(in.recordId));
assertNull(_repo.loadNoCache(in.recordId));
}
protected static <E extends Enum<E> & ShortEnum> E fromShort (Class<E> eclass, short code)
{
for (E value : eclass.getEnumConstants()) {
if (value.toShort() == code) {
return value;
}
}
throw new IllegalArgumentException(eclass + " has no value with code " + code);
}
protected static class TransformRepository extends DepotRepository
{
public TransformRepository (PersistenceContext ctx) {
super(ctx);
}
public TransformRecord loadNoCache (int recordId)
{
return load(TransformRecord.getKey(recordId), CacheStrategy.NONE);
}
@Override // from DepotRepository
protected void getManagedRecords (Set<Class<? extends PersistentRecord>> classes) {
classes.add(TransformRecord.class);
}
}
// the HSQL in-memory database persists for the lifetime of the VM, which means we have to
// clean up after ourselves in every test; thus we go ahead and share a repository
protected TransformRepository _repo = new TransformRepository(createPersistenceContext());
}
@@ -0,0 +1,89 @@
//
// $Id$
//
// Depot library - a Java relational persistence library
// Copyright (C) 2006-2010 Michael Bayne and Pär Winzell
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.samskivert.depot;
import java.util.EnumSet;
import java.util.Set;
import org.junit.Test;
import static org.junit.Assert.*;
import com.google.common.collect.Sets;
import com.samskivert.util.ByteEnum;
/**
* Tests the stock transformers.
*/
public class TransformersTest
{
@Test public void testStringArray ()
{
String[] data = { "something", "", null, "\nprenewline", "postnewline\n", "in\nnewline",
"a slash \\", "\\ two slashes \\", "\n\n\n" };
Transformers.StringArray xform = new Transformers.StringArray();
assertArrayEquals(data, xform.fromPersistent(null, xform.toPersistent(data)));
}
@Test public void testEmptyStringArrays ()
{
Transformers.StringArray xform = new Transformers.StringArray();
Set<String> set = Sets.newHashSet();
// all three of these should obviously encode to different Strings
set.add(xform.toPersistent(null));
set.add(xform.toPersistent(new String[] {}));
set.add(xform.toPersistent(new String[] {""}));
assertTrue(set.size() == 3);
}
@Test public void testByteEnumSets ()
{
Transformers.ByteEnumSet<LilEnum> xform = new Transformers.ByteEnumSet<LilEnum>();
Set<Integer> set = Sets.newHashSet();
set.add(xform.toPersistent(null));
set.add(xform.toPersistent(EnumSet.noneOf(LilEnum.class)));
set.add(xform.toPersistent(EnumSet.of(LilEnum.ONE)));
set.add(xform.toPersistent(EnumSet.of(LilEnum.TWO, LilEnum.THREE)));
set.add(xform.toPersistent(EnumSet.allOf(LilEnum.class)));
assertTrue(set.size() == 5);
set.clear();
for (Set<LilEnum> subset : Sets.powerSet(EnumSet.allOf(LilEnum.class))) {
set.add(xform.toPersistent(subset));
}
assertTrue(set.size() == 8);
}
private static enum LilEnum
implements ByteEnum
{
ONE,
TWO,
THREE;
// from ByteEnum
public byte toByte ()
{
return (byte)ordinal(); // we're just testing here, chill out
}
}
}