package groups; import java.sql.*; import junit.textui.*; import junit.framework.*; import junit.extensions.*; import java.util.Iterator; import java.util.ArrayList; import java.util.List; import java.util.Random; /* Copyright Richard Emberson Use but remember me (copyright must appear in all copies). */ public class GroupLimits extends TestSetup { static final String FILE = "group_limits.sql"; private static String[] args; private static Connection conn; private static final StringBuffer buf = new StringBuffer(); private static final String dropSQL = "DROP TABLE group_limits;"; private static final String deleteSQL = "DELETE FROM group_limits;"; private static final String countSQL = "SELECT count(*) FROM group_limits;"; private static final String loadSQL = "INSERT INTO group_limits (lower_bound,size,upper_bound) VALUES (0,9223372036854775807,9223372036854775807);"; private static final long SUCCESS_INSERT = 1; private static final long SUCCESS_UPDATE = 2; private static final long STATUS_NEW_ROW = 1; private static final long STATUS_LOWER = 2; private static final long STATUS_HIGHER = 3; private static final long STATUS_LOWER_AND_HIGHER = 4; private static final long ERROR_NO_MORE_SEGMENTS = -1100011; // lower_bound < lb_p AND upper_bound > lb_p private static final long ERROR_LOWER_BOUND_BAD = -1100012; // lower_bound < (lb_p+size_p) AND upper_bound > (lb_p+size_p); private static final long ERROR_UPPER_BOUND_BAD = -1100013; public static class Segment { long lower; long size; Segment(long lower, long size) { this.lower = lower; this.size = size; } } public static class Tests extends TestCase { public Tests(String name) { super(name); } public void testConnection() { clearAndLoadTable(conn); assert(conn != null); checkNosOfRows(1); } /* select group_limits_get(10); select group_limits_return(0,10); 0-end */ public void testSimple1() { clearAndLoadTable(conn); Segment s = getSegment(10); checkNosOfRows(1); int status = returnSegement(s); assert(status == STATUS_HIGHER); } /* select group_limits_get(10); select group_limits_get(10); select group_limits_return(0,10); 0-10, 10,end select group_limits_return(10,10); 0-end */ public void testSimple2() { clearAndLoadTable(conn); Segment s1 = getSegment(10); Segment s2 = getSegment(10); checkNosOfRows(1); int status = returnSegement(s1); assert(status == STATUS_NEW_ROW); checkNosOfRows(2); status = returnSegement(s2); assert(status == STATUS_LOWER_AND_HIGHER); checkNosOfRows(1); } /* select group_limits_get(10); select group_limits_get(10); select group_limits_return(10,10); 10-end select group_limits_return(0,10); 0-end */ public void testSimple3() { clearAndLoadTable(conn); Segment s1 = getSegment(10); Segment s2 = getSegment(10); checkNosOfRows(1); int status = returnSegement(s2); assert(status == STATUS_HIGHER); checkNosOfRows(1); status = returnSegement(s1); assert(status == STATUS_HIGHER); checkNosOfRows(1); } public void testBad1() { clearAndLoadTable(conn); Segment s1 = getSegment(10); Segment s2 = getSegment(10); int status = returnSegement(s1); assert(status == STATUS_NEW_ROW); // 0-10, 20-end Segment sLowerBad = new Segment(5, 10); status = returnSegement(sLowerBad); assert(status == ERROR_LOWER_BOUND_BAD); Segment sUpperBad = new Segment(15, 10); status = returnSegement(sUpperBad); assert(status == ERROR_UPPER_BOUND_BAD); } public void testHard1() { clearAndLoadTable(conn); int n = 100; List l = new ArrayList(); Random r = new Random(); for (int i = 0; i < n; i++) { int ri = r.nextInt(); if (ri == 0) { continue; } if (ri < 0) { ri = -ri; } //System.out.println("ri = "+ri); Segment s = getSegment(ri); l.add(s); } while (l.size() > 0) { int index = r.nextInt(); if (index < 0) { index = -index; } index = index % l.size(); Segment s = (Segment)l.remove(index); returnSegement(s); } // and we get back to one row!!! checkNosOfRows(1); } //////////////////////////////////////////////////////////////////////// private void checkNosOfRows(int n) { int nosOfRows = countTable(conn); assert(nosOfRows == n); } private Segment getSegment(long size) { long lower = doGetQuery(size); Segment s = new Segment(lower, size); return s; } private long doGetQuery(long size) { String query = makeGetQuery(size); return execute(conn, query); } private String makeGetQuery(long size) { buf.setLength(0); buf.append("SELECT group_limits_get("); buf.append(size); buf.append(");"); return buf.toString(); } private int returnSegement(Segment s) { return (int)doReturnQuery(s.lower, s.size); } private long doReturnQuery(long lower, long size) { String query = makeReturnQuery(lower, size); return execute(conn, query); } private String makeReturnQuery(long lower, long size) { buf.setLength(0); buf.append("SELECT group_limits_return("); buf.append(lower); buf.append(","); buf.append(size); buf.append(");"); return buf.toString(); } /* //////////////////////////////////////////////////////////////////////// */ private int countTable(Connection conn) { return (int)execute(conn, countSQL); } private void clearAndLoadTable(Connection conn) { clearTable(conn); loadTable(conn); } private void clearTable(Connection conn) { execute(conn, deleteSQL); } private void loadTable(Connection conn) { execute(conn, loadSQL); } private long execute(Connection conn, String query) { Statement st = null; long result = -1; try { st = conn.createStatement(); if (st.execute(query)) { // for pl/pgsql ResultSet rs = st.getResultSet(); if (rs.next()) { result = rs.getLong(1); } } else { // for sql delete result = st.getUpdateCount(); } } catch (SQLException ex) { ex.printStackTrace(); fail("Exception: " +ex); } finally { try { st.close(); } catch (Exception ex) {} } return result; } } public GroupLimits() { super(new TestSuite(groups.GroupLimits.Tests.class)); } protected void setUp() throws Exception { String[] args = GroupLimits.args; if (args == null) { args = AllTests.args; } conn = AllTests.makeConnection(args); System.out.println("Got connection"); AllTests.loadFile(GroupLimits.FILE); } protected void tearDown() throws Exception { if (conn != null) { AllTests.execute(conn, dropSQL); System.out.println("Closing connection"); conn.close(); } } public static void main(String args[]) { GroupLimits.args = args; junit.textui.TestRunner.run(GroupLimits.class); } }