Look ma, unit tests that run against HSQLDB.

This commit is contained in:
Michael Bayne
2010-03-16 04:57:52 +00:00
parent aae3d909a2
commit 8b871dcf19
6 changed files with 296 additions and 115 deletions
+7 -3
View File
@@ -2,10 +2,14 @@
<!-- declares the libraries needed to build depot -->
<project name="library-dependencies">
<fileset dir="${libs.dir}" id="depot.libs">
<include name="ant.jar"/>
<include name="ehcache.jar"/>
<include name="google-collect.jar"/>
<include name="junit4.jar"/>
<include name="samskivert.jar"/>
<!-- ehcache adapter dependencies (optional) -->
<include name="ehcache.jar"/>
<!-- ant task dependencies (optional) -->
<include name="ant.jar"/>
<!-- unit test dependencies (optional) -->
<include name="hsqldb.jar"/>
<include name="junit4.jar"/>
</fileset>
</project>
@@ -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.tests;
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,104 @@
//
// $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.tests;
import java.util.Collections;
import com.google.common.collect.Sets;
import com.samskivert.util.RandomUtil;
import com.samskivert.depot.Exps;
import com.samskivert.depot.Key;
import com.samskivert.depot.KeySet;
import com.samskivert.depot.PersistentRecord;
import com.samskivert.depot.annotation.Computed;
import com.samskivert.depot.clause.Where;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* 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,98 @@
//
// $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.tests;
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 com.samskivert.depot.PersistenceContext;
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));
}
}
@@ -60,7 +60,7 @@ public class TestRecord extends PersistentRecord
public String homeTown;
@Index
// @Index // TODO: this horks HSQLDB
public Date created;
public Timestamp lastModified;
@@ -20,130 +20,25 @@
package com.samskivert.depot.tests;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.Set;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.samskivert.jdbc.StaticConnectionProvider;
import com.samskivert.util.RandomUtil;
import com.samskivert.depot.DepotRepository;
import com.samskivert.depot.Key;
import com.samskivert.depot.KeySet;
import com.samskivert.depot.PersistenceContext;
import com.samskivert.depot.PersistentRecord;
import com.samskivert.depot.SchemaMigration;
import com.samskivert.depot.annotation.Computed;
import com.samskivert.depot.clause.Where;
import com.samskivert.depot.impl.expression.LiteralExp;
import com.samskivert.depot.impl.operator.GreaterThan;
import com.samskivert.depot.impl.operator.LessThan;
/**
* A test tool for the Depot repository services.
*/
public class TestRepository extends DepotRepository
{
@Computed(shadowOf=TestRecord.class)
public static class TestNameRecord extends PersistentRecord
public TestRecord loadNoCache (int recordId)
{
public int recordId;
public String name;
@Override public String toString () {
return recordId + ":" + name;
}
return load(TestRecord.getKey(recordId), CacheStrategy.NONE);
}
public static void main (String[] args)
throws Exception
public TestRecord loadWithCache (int recordId)
{
PersistenceContext perCtx = new PersistenceContext();
perCtx.init("test", new StaticConnectionProvider("depot.properties"),
new TestCacheAdapter());
// tests a bogus rename migration
// perCtx.registerMigration(TestRecord.class, new SchemaMigration.Rename(1, "foo", "bar"));
// tests a custom add column migration
perCtx.registerMigration(TestRecord.class,
new SchemaMigration.Add(2, TestRecord.HOME_TOWN, "'Anytown USA'"));
TestRepository repo = new TestRepository(perCtx);
System.out.println("Deleting old record.");
repo.delete(TestRecord.getKey(1));
Date now = new Date(System.currentTimeMillis());
Timestamp tnow = new Timestamp(System.currentTimeMillis());
TestRecord record = new TestRecord();
record.recordId = 1;
record.name = "Elvis";
record.age = 99;
record.created = now;
record.homeTown = "Right here";
record.lastModified = tnow;
record.numbers = new int[] { 9, 0, 2, 1, 0 };
repo.insert(record);
System.out.println("Record: " + repo.load(TestRecord.getKey(record.recordId)));
// record.age = 25;
// record.name = "Bob";
// record.numbers = new int[] { 1, 2, 3, 4, 5 };
// repo.update(record, TestRecord.AGE, TestRecord.NAME, TestRecord.NUMBERS);
repo.updatePartial(TestRecord.getKey(record.recordId),
ImmutableMap.of(TestRecord.AGE, 25, TestRecord.NAME, "Bob",
TestRecord.NUMBERS, new int[] { 1, 2, 3, 4, 5 }));
System.out.println("Updated " + repo.load(TestRecord.getKey(record.recordId)));
for (int ii = 2; ii < CREATE_RECORDS; ii++) {
record = new TestRecord();
record.recordId = ii;
record.name = "Spam!";
record.age = RandomUtil.getInt(150);
record.homeTown = "Over there";
record.numbers = new int[] { 5, 4, 3, 2, 1 };
record.created = now;
record.lastModified = tnow;
repo.insert(record);
}
// test the empty ky set
KeySet<TestRecord> none = KeySet.newKeySet(
TestRecord.class, Collections.<Key<TestRecord>>emptySet());
System.out.println("Load none " + repo.loadAll(none.toCollection()) + ".");
System.out.println("Delete none " + repo.deleteAll(TestRecord.class, none) + ".");
// test collection caching
Where where = new Where(new GreaterThan(TestRecord.RECORD_ID, 100));
System.out.println("100 and up: " + repo.findAll(TestRecord.class, where).size());
System.out.println("100 and up again: " + 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));
System.out.println("Load some " + repo.loadAll(some.toCollection()) + ".");
System.out.println("Names " + repo.findAll(TestNameRecord.class) + ".");
System.out.println("Have " + repo.findAll(TestRecord.class).size() + " records.");
repo.deleteAll(TestRecord.class, new Where(new LessThan(
TestRecord.RECORD_ID, CREATE_RECORDS/2)));
System.out.println("Now have " + repo.findAll(TestRecord.class).size() + " records.");
repo.deleteAll(TestRecord.class, new Where(new LiteralExp("true")));
// // 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));
System.out.println("Now have " + repo.findAll(TestRecord.class).size() + " records.");
return load(TestRecord.getKey(recordId));
}
public TestRepository (PersistenceContext perCtx)
@@ -156,6 +51,4 @@ public class TestRepository extends DepotRepository
{
classes.add(TestRecord.class);
}
protected static final int CREATE_RECORDS = 150;
}