Found the bug, it was just a SQL syntax error.

This commit is contained in:
akwizgran
2011-07-23 11:29:23 +01:00
parent 0edcb31d64
commit 13f18d9e40
9 changed files with 165 additions and 41 deletions

View File

@@ -2,5 +2,5 @@ package net.sf.briar.api.protocol;
public interface GroupFactory { public interface GroupFactory {
Group createGroup(GroupId id, String name, byte[] salt, byte[] publicKey); Group createGroup(GroupId id, String name, boolean restricted, byte[] b);
} }

View File

@@ -2,7 +2,6 @@ package net.sf.briar.db;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.security.PublicKey;
import java.sql.Blob; import java.sql.Blob;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
@@ -40,9 +39,9 @@ abstract class JdbcDatabase implements Database<Connection> {
private static final String CREATE_LOCAL_SUBSCRIPTIONS = private static final String CREATE_LOCAL_SUBSCRIPTIONS =
"CREATE TABLE localSubscriptions" "CREATE TABLE localSubscriptions"
+ " (groupId HASH NOT NULL," + " (groupId HASH NOT NULL,"
+ " name VARCHAR NOT NULL," + " groupName VARCHAR NOT NULL,"
+ " salt BINARY," + " restricted BOOLEAN NOT NULL,"
+ " publicKey BINARY," + " groupKey BINARY NOT NULL,"
+ " PRIMARY KEY (groupId))"; + " PRIMARY KEY (groupId))";
private static final String CREATE_MESSAGES = private static final String CREATE_MESSAGES =
@@ -90,9 +89,9 @@ abstract class JdbcDatabase implements Database<Connection> {
"CREATE TABLE contactSubscriptions" "CREATE TABLE contactSubscriptions"
+ " (contactId INT NOT NULL," + " (contactId INT NOT NULL,"
+ " groupId HASH NOT NULL," + " groupId HASH NOT NULL,"
+ " name VARCHAR NOT NULL," + " groupName VARCHAR NOT NULL,"
+ " salt BINARY," + " restricted BOOLEAN NOT NULL,"
+ " publicKey BINARY," + " groupKey BINARY NOT NULL,"
+ " PRIMARY KEY (contactId, groupId)," + " PRIMARY KEY (contactId, groupId),"
+ " FOREIGN KEY (contactId) REFERENCES contacts (contactId)" + " FOREIGN KEY (contactId) REFERENCES contacts (contactId)"
+ " ON DELETE CASCADE)"; + " ON DELETE CASCADE)";
@@ -531,14 +530,14 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
String sql = "INSERT INTO localSubscriptions" String sql = "INSERT INTO localSubscriptions"
+ " (groupId, name, salt, publicKey)" + " (groupId, groupName, restricted, groupKey)"
+ " VALUES (?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setBytes(1, g.getId().getBytes()); ps.setBytes(1, g.getId().getBytes());
ps.setString(2, g.getName()); ps.setString(2, g.getName());
ps.setBytes(3, g.getSalt()); ps.setBoolean(3, g.isRestricted());
PublicKey k = g.getPublicKey(); if(g.isRestricted()) ps.setBytes(4, g.getPublicKey().getEncoded());
ps.setBytes(4, k == null ? null : k.getEncoded()); else ps.setBytes(4, g.getSalt());
int rowsAffected = ps.executeUpdate(); int rowsAffected = ps.executeUpdate();
assert rowsAffected == 1; assert rowsAffected == 1;
ps.close(); ps.close();
@@ -990,7 +989,7 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT (groupId, name, salt, publicKey)" String sql = "SELECT groupId, groupName, restricted, groupKey"
+ " FROM localSubscriptions"; + " FROM localSubscriptions";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
rs = ps.executeQuery(); rs = ps.executeQuery();
@@ -998,9 +997,9 @@ abstract class JdbcDatabase implements Database<Connection> {
while(rs.next()) { while(rs.next()) {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
byte[] salt = rs.getBytes(3); boolean restricted = rs.getBoolean(3);
byte[] publicKey = rs.getBytes(4); byte[] key = rs.getBytes(4);
subs.add(groupFactory.createGroup(id, name, salt, publicKey)); subs.add(groupFactory.createGroup(id, name, restricted, key));
} }
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1018,7 +1017,7 @@ abstract class JdbcDatabase implements Database<Connection> {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {
String sql = "SELECT (groupId, name, salt, publicKey)" String sql = "SELECT groupId, groupName, restricted, groupKey"
+ " FROM contactSubscriptions" + " FROM contactSubscriptions"
+ " WHERE contactId = ?"; + " WHERE contactId = ?";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
@@ -1028,9 +1027,9 @@ abstract class JdbcDatabase implements Database<Connection> {
while(rs.next()) { while(rs.next()) {
GroupId id = new GroupId(rs.getBytes(1)); GroupId id = new GroupId(rs.getBytes(1));
String name = rs.getString(2); String name = rs.getString(2);
byte[] salt = rs.getBytes(3); boolean restricted = rs.getBoolean(3);
byte[] publicKey = rs.getBytes(4); byte[] key = rs.getBytes(4);
subs.add(groupFactory.createGroup(id, name, salt, publicKey)); subs.add(groupFactory.createGroup(id, name, restricted, key));
} }
rs.close(); rs.close();
ps.close(); ps.close();
@@ -1390,16 +1389,17 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.close(); ps.close();
// Store the new subscriptions // Store the new subscriptions
sql = "INSERT INTO contactSubscriptions" sql = "INSERT INTO contactSubscriptions"
+ "(contactId, groupId, name, salt, publicKey)" + "(contactId, groupId, groupName, restricted, groupKey)"
+ " VALUES (?, ?, ?, ?, ?)"; + " VALUES (?, ?, ?, ?, ?)";
ps = txn.prepareStatement(sql); ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt()); ps.setInt(1, c.getInt());
for(Group g : subs) { for(Group g : subs) {
ps.setBytes(2, g.getId().getBytes()); ps.setBytes(2, g.getId().getBytes());
ps.setString(3, g.getName()); ps.setString(3, g.getName());
ps.setBytes(4, g.getSalt()); ps.setBoolean(4, g.isRestricted());
PublicKey k = g.getPublicKey(); if(g.isRestricted())
ps.setBytes(5, k == null ? null : k.getEncoded()); ps.setBytes(5, g.getPublicKey().getEncoded());
else ps.setBytes(5, g.getSalt());
ps.addBatch(); ps.addBatch();
} }
int[] rowsAffectedArray = ps.executeBatch(); int[] rowsAffectedArray = ps.executeBatch();

View File

@@ -19,20 +19,15 @@ class GroupFactoryImpl implements GroupFactory {
this.keyParser = keyParser; this.keyParser = keyParser;
} }
public Group createGroup(GroupId id, String name, byte[] salt, public Group createGroup(GroupId id, String name, boolean restricted,
byte[] publicKey) { byte[] b) {
if(salt == null && publicKey == null) if(restricted) {
throw new IllegalArgumentException();
if(salt != null && publicKey != null)
throw new IllegalArgumentException();
PublicKey key = null;
if(publicKey != null) {
try { try {
key = keyParser.parsePublicKey(publicKey); PublicKey key = keyParser.parsePublicKey(b);
return new GroupImpl(id, name, null, key);
} catch (InvalidKeySpecException e) { } catch (InvalidKeySpecException e) {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }
} } else return new GroupImpl(id, name, b, null);
return new GroupImpl(id, name, salt, key);
} }
} }

View File

@@ -39,4 +39,14 @@ public class GroupImpl implements Group {
public PublicKey getPublicKey() { public PublicKey getPublicKey() {
return publicKey; return publicKey;
} }
@Override
public boolean equals(Object o) {
return o instanceof Group && id.equals(((Group) o).getId());
}
@Override
public int hashCode() {
return id.hashCode();
}
} }

View File

@@ -54,7 +54,7 @@ class MessageImpl implements Message {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
return o instanceof Message && id.equals(((Message)o).getId()); return o instanceof Message && id.equals(((Message) o).getId());
} }
@Override @Override

View File

@@ -13,6 +13,7 @@
<path refid='test-classes'/> <path refid='test-classes'/>
<path refid='util-classes'/> <path refid='util-classes'/>
</classpath> </classpath>
<test name='net.sf.briar.db.BasicH2Test'/>
<test name='net.sf.briar.db.DatabaseCleanerImplTest'/> <test name='net.sf.briar.db.DatabaseCleanerImplTest'/>
<test name='net.sf.briar.db.H2DatabaseTest'/> <test name='net.sf.briar.db.H2DatabaseTest'/>
<test name='net.sf.briar.db.ReadWriteLockDatabaseComponentTest'/> <test name='net.sf.briar.db.ReadWriteLockDatabaseComponentTest'/>

View File

@@ -0,0 +1,117 @@
package net.sf.briar.db;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import junit.framework.TestCase;
import net.sf.briar.TestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class BasicH2Test extends TestCase {
private static final String CREATE_TABLE =
"CREATE TABLE foo"
+ " (uniqueId BINARY(32) NOT NULL,"
+ " name VARCHAR NOT NULL,"
+ " PRIMARY KEY (uniqueId))";
private final File testDir = TestUtils.getTestDirectory();
private final File db = new File(testDir, "db");
private final String url = "jdbc:h2:" + db.getPath();
private Connection connection = null;
@Before
public void setUp() throws Exception {
testDir.mkdirs();
Class.forName("org.h2.Driver");
connection = DriverManager.getConnection(url);
}
@Test
public void testCreateTableAndAddRow() throws Exception {
// Create the table
createTable(connection);
// Generate a unique ID
byte[] uniqueId = new byte[32];
new Random().nextBytes(uniqueId);
// Insert the unique ID and name into the table
addRow(uniqueId, "foo");
}
@Test
public void testCreateTableAddAndRetrieveRow() throws Exception {
// Create the table
createTable(connection);
// Generate a unique ID
byte[] uniqueId = new byte[32];
new Random().nextBytes(uniqueId);
// Insert the unique ID and name into the table
addRow(uniqueId, "foo");
// Check that the name can be retrieved using the unique ID
assertEquals("foo", getName(uniqueId));
}
private void addRow(byte[] uniqueId, String name) throws SQLException {
String sql = "INSERT INTO foo (uniqueId, name) VALUES (?, ?)";
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setBytes(1, uniqueId);
ps.setString(2, name);
int rowsAffected = ps.executeUpdate();
ps.close();
assertEquals(1, rowsAffected);
} catch(SQLException e) {
connection.close();
throw e;
}
}
private String getName(byte[] uniqueId) throws SQLException {
String sql = "SELECT name FROM foo WHERE uniqueID = ?";
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement(sql);
ps.setBytes(1, uniqueId);
rs = ps.executeQuery();
assertTrue(rs.next());
String name = rs.getString(1);
assertFalse(rs.next());
rs.close();
ps.close();
return name;
} catch(SQLException e) {
connection.close();
throw e;
}
}
private void createTable(Connection connection) throws SQLException {
Statement s;
try {
s = connection.createStatement();
s.executeUpdate(CREATE_TABLE);
s.close();
} catch(SQLException e) {
connection.close();
throw e;
}
}
@After
public void tearDown() throws Exception {
if(connection != null) connection.close();
TestUtils.deleteTestDirectory(testDir);
}
}

View File

@@ -468,6 +468,7 @@ public abstract class DatabaseComponentTest extends TestCase {
will(returnValue(true)); will(returnValue(true));
oneOf(ackWriter).addBatchId(batchId1); oneOf(ackWriter).addBatchId(batchId1);
will(returnValue(false)); will(returnValue(false));
oneOf(ackWriter).finish();
// Record the batch that was acked // Record the batch that was acked
oneOf(database).removeBatchesToAck(txn, contactId, acks); oneOf(database).removeBatchesToAck(txn, contactId, acks);
}}); }});

View File

@@ -76,8 +76,8 @@ public class H2DatabaseTest extends TestCase {
random.nextBytes(raw); random.nextBytes(raw);
message = new TestMessage(messageId, MessageId.NONE, groupId, authorId, message = new TestMessage(messageId, MessageId.NONE, groupId, authorId,
timestamp, raw); timestamp, raw);
group = groupFactory.createGroup(groupId, "Group name", group = groupFactory.createGroup(groupId, "Group name", false,
TestUtils.getRandomId(), null); TestUtils.getRandomId());
} }
@Before @Before
@@ -533,7 +533,7 @@ public class H2DatabaseTest extends TestCase {
MessageId childId3 = new MessageId(TestUtils.getRandomId()); MessageId childId3 = new MessageId(TestUtils.getRandomId());
GroupId groupId1 = new GroupId(TestUtils.getRandomId()); GroupId groupId1 = new GroupId(TestUtils.getRandomId());
Group group1 = groupFactory.createGroup(groupId1, "Another group name", Group group1 = groupFactory.createGroup(groupId1, "Another group name",
TestUtils.getRandomId(), null); false, TestUtils.getRandomId());
Message child1 = new TestMessage(childId1, messageId, groupId, Message child1 = new TestMessage(childId1, messageId, groupId,
authorId, timestamp, raw); authorId, timestamp, raw);
Message child2 = new TestMessage(childId2, messageId, groupId, Message child2 = new TestMessage(childId2, messageId, groupId,
@@ -758,7 +758,7 @@ public class H2DatabaseTest extends TestCase {
public void testUpdateSubscriptions() throws DbException { public void testUpdateSubscriptions() throws DbException {
GroupId groupId1 = new GroupId(TestUtils.getRandomId()); GroupId groupId1 = new GroupId(TestUtils.getRandomId());
Group group1 = groupFactory.createGroup(groupId1, "Another group name", Group group1 = groupFactory.createGroup(groupId1, "Another group name",
TestUtils.getRandomId(), null); false, TestUtils.getRandomId());
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();
@@ -783,7 +783,7 @@ public class H2DatabaseTest extends TestCase {
throws DbException { throws DbException {
GroupId groupId1 = new GroupId(TestUtils.getRandomId()); GroupId groupId1 = new GroupId(TestUtils.getRandomId());
Group group1 = groupFactory.createGroup(groupId1, "Another group name", Group group1 = groupFactory.createGroup(groupId1, "Another group name",
TestUtils.getRandomId(), null); false, TestUtils.getRandomId());
Database<Connection> db = open(false); Database<Connection> db = open(false);
Connection txn = db.startTransaction(); Connection txn = db.startTransaction();