Skip to content

Commit

Permalink
Lab 4 test updates
Browse files Browse the repository at this point in the history
- Split TransactionTest into TransactionTest{One, Two, Five, Ten, AllDirty}
- Updated build.xml to make the timeout configurable
- Improved comments in DeadlockTest, LockingTest, and TransactionTest

Co-authored-by: Geoffrey Yu <[email protected]>
Co-authored-by: Anna Zeng <[email protected]>
  • Loading branch information
geoffxy and annazeng committed Nov 4, 2022
1 parent 480a34f commit 728b471
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 67 deletions.
19 changes: 12 additions & 7 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@
</sequential>
</macrodef>


<!-- Common macro for running junit tests in both the test and runtest targets -->
<macrodef name="RunJunit">
<attribute name="haltonfailure" default="yes" />
<attribute name="timeoutMs" />
<element name="testspecification" implicit="yes" />
<sequential>
<!-- timeout at 10.5 minutes, since TransactionTest is limited to 10 minutes. -->
<junit printsummary="on" fork="yes" timeout="120000" haltonfailure="@{haltonfailure}" maxmemory="128M" failureproperty="junit.failed">
<junit printsummary="on" fork="yes" timeout="@{timeoutMs}" haltonfailure="@{haltonfailure}" maxmemory="128M" failureproperty="junit.failed">
<classpath refid="classpath.test" />
<formatter type="plain" usefile="false"/>
<assertions><enable/></assertions>
Expand Down Expand Up @@ -217,8 +218,11 @@
</Compile>
</target>

<!-- Timeout is 2 minutes for all tests except TransactionTest{One, Two, Five, Ten} (10 minutes each). -->
<property name="timeoutMs" value="120000" />

<target name="test" depends="testcompile" description="Run all unit tests">
<RunJunit>
<RunJunit timeoutMs="${timeoutMs}">
<batchtest>
<fileset dir="${build.test}">
<include name="**/*Test.class"/>
Expand All @@ -230,7 +234,7 @@
</target>

<target name="systemtest" depends="testcompile" description="Run all system tests">
<RunJunit>
<RunJunit timeoutMs="${timeoutMs}">
<batchtest>
<fileset dir="${build.test}">
<include name="simpledb/systemtest/*Test.class"/>
Expand All @@ -250,7 +254,7 @@
</available>
<fail unless="test.exists" message="Test ${test} could not be found"/>

<RunJunit>
<RunJunit timeoutMs="${timeoutMs}">
<test name="simpledb.${test}"/>
</RunJunit>
</target>
Expand All @@ -266,18 +270,19 @@
</available>
<fail unless="test.exists" message="Test ${test} could not be found"/>

<RunJunit>
<RunJunit timeoutMs="${timeoutMs}">
<test name="simpledb.systemtest.${test}"/>
</RunJunit>
</target>


<!-- The following target is used for automated grading. -->
<target name="test-report" depends="testcompile"
description="Generates HTML test reports in ${test.reports}">
<mkdir dir="${test.reports}"/>

<!-- do not halt on failure so we always produce HTML reports. -->
<RunJunit haltonfailure="no">
<RunJunit haltonfailure="no" timeoutMs="${timeoutMs}">
<formatter type="xml"/>
<formatter type="plain" usefile="true"/>
<batchtest todir="${test.reports}" >
Expand Down
12 changes: 7 additions & 5 deletions lab4.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,9 @@ Whether the transaction commits or aborts, you should also release any state the
the transaction held.

At this point, your code should pass the `TransactionTest` unit test and the
`AbortEvictionTest` system test. You may find the `TransactionTest` system test
illustrative, but it will likely fail until you complete the next exercise.
`AbortEvictionTest` system test. You may find the `TransactionTest{One, Two
Five, Ten, AllDirty}` system tests illustrative, but they will likely fail until
you complete the next exercise.

### 2.8. Deadlocks and Aborts

Expand Down Expand Up @@ -316,7 +317,7 @@ alternatives.
You should ensure that your code aborts transactions properly when a deadlock
occurs, by throwing a `TransactionAbortedException` exception. This exception
will be caught by the code executing the transaction (e.g.,
`TransactionTest.java`), which should call `transactionComplete()` to cleanup
`TransactionTestUtil.java`), which should call `transactionComplete()` to cleanup
after the transaction. You are not expected to automatically restart a
transaction which fails due to a deadlock -- you can assume that higher level
code will take care of this.
Expand All @@ -335,8 +336,9 @@ if you use a timeout-based detection method. The tests will output
`TransactionAbortedExceptions` corresponding to resolved deadlocks to the
console.

Your code should now should pass the `TransactionTest` system test (which may
also run for quite a long time depending on your implementation).
Your code should now should pass the `TransactionTest{One, Two, Five, Ten,
AllDirty}` system tests (which may also run for quite a long time depending on
your implementation).

At this point, you should have a recoverable database, in the sense that if the
database system crashes (at a point other than `transactionComplete()`) or if
Expand Down
4 changes: 3 additions & 1 deletion test/simpledb/DeadlockTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public class DeadlockTest extends TestUtil.CreateHeapFile {
empty.insertTuple(tid, Utility.getHeapTuple(i, 2));
}

// if this fails, complain to the TA
// if the line below fails, check if the addTuple test in HeapFileWriteTest
// still passes. if HeapFileWriteTest is passing and this line is still failing
// w/out known reason, come talk with the TAs to further debug the issue.
assertEquals(3, empty.numPages());

this.p0 = new HeapPageId(empty.getId(), 0);
Expand Down
4 changes: 3 additions & 1 deletion test/simpledb/LockingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public class LockingTest extends TestUtil.CreateHeapFile {
empty.insertTuple(tid, Utility.getHeapTuple(i, 2));
}

// if this fails, complain to the TA
// if the line below fails, check if the addTuple test in HeapFileWriteTest
// still passes. if HeapFileWriteTest is passing and this line is still failing
// w/out known reason, come talk with the TAs to further debug the issue.
assertEquals(3, empty.numPages());

this.p0 = new HeapPageId(empty.getId(), 0);
Expand Down
4 changes: 3 additions & 1 deletion test/simpledb/TransactionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ public class TransactionTest extends TestUtil.CreateHeapFile {
empty.insertTuple(tid, Utility.getHeapTuple(i, 2));
}

// if this fails, complain to the TA
// if the line below fails, check if the addTuple test in HeapFileWriteTest
// still passes. if HeapFileWriteTest is passing and this line is still failing
// w/out known reason, come talk with the TAs to further debug the issue.
assertEquals(3, empty.numPages());

this.p0 = new HeapPageId(empty.getId(), 0);
Expand Down
41 changes: 41 additions & 0 deletions test/simpledb/systemtest/TransactionTestAllDirty.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package simpledb.systemtest;

import java.io.IOException;

import org.junit.Test;

import simpledb.common.Database;
import simpledb.common.DbException;
import simpledb.storage.*;
import simpledb.transaction.Transaction;
import simpledb.transaction.TransactionAbortedException;

import static org.junit.Assert.*;

public class TransactionTestAllDirty extends SimpleDbTestBase {
@Test public void testAllDirtyFails()
throws IOException, DbException, TransactionAbortedException {
// Allocate a file with ~10 pages of data
HeapFile f = SystemTestUtil.createRandomHeapFile(2, 512*10, null, null);
Database.resetBufferPool(1);

// BEGIN TRANSACTION
Transaction t = new Transaction();
t.start();

// Insert a new row
AbortEvictionTest.insertRow(f, t);

// Scanning the table must fail because it can't evict the dirty page
try {
AbortEvictionTest.findMagicTuple(f, t);
fail("Expected scan to run out of available buffer pages");
} catch (DbException ignored) {}
t.commit();
}

/** Make test compatible with older version of ant. */
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(TransactionTestAllDirty.class);
}
}
25 changes: 25 additions & 0 deletions test/simpledb/systemtest/TransactionTestFive.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package simpledb.systemtest;

import java.io.IOException;

import org.junit.Test;

import simpledb.common.DbException;
import simpledb.transaction.TransactionAbortedException;

/**
* Tests running concurrent transactions.
* You do not need to pass this test until Lab 4.
* @see simpledb.systemtest.TransactionTestShared
*/
public class TransactionTestFive extends SimpleDbTestBase {
@Test public void testFiveThreads()
throws IOException, DbException, TransactionAbortedException {
TransactionTestUtil.validateTransactions(5);
}

/** Make test compatible with older version of ant. */
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(TransactionTestFive.class);
}
}
25 changes: 25 additions & 0 deletions test/simpledb/systemtest/TransactionTestOne.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package simpledb.systemtest;

import java.io.IOException;

import org.junit.Test;

import simpledb.common.DbException;
import simpledb.transaction.TransactionAbortedException;

/**
* Tests running concurrent transactions.
* You do not need to pass this test until Lab 4.
* @see simpledb.systemtest.TransactionTestShared
*/
public class TransactionTestOne extends SimpleDbTestBase {
@Test public void testSingleThread()
throws IOException, DbException, TransactionAbortedException {
TransactionTestUtil.validateTransactions(1);
}

/** Make test compatible with older version of ant. */
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(TransactionTestOne.class);
}
}
25 changes: 25 additions & 0 deletions test/simpledb/systemtest/TransactionTestTen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package simpledb.systemtest;

import java.io.IOException;

import org.junit.Test;

import simpledb.common.DbException;
import simpledb.transaction.TransactionAbortedException;

/**
* Tests running concurrent transactions.
* You do not need to pass this test until Lab 4.
* @see simpledb.systemtest.TransactionTestShared
*/
public class TransactionTestTen extends SimpleDbTestBase {
@Test public void testTenThreads()
throws IOException, DbException, TransactionAbortedException {
TransactionTestUtil.validateTransactions(10);
}

/** Make test compatible with older version of ant. */
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(TransactionTestTen.class);
}
}
25 changes: 25 additions & 0 deletions test/simpledb/systemtest/TransactionTestTwo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package simpledb.systemtest;

import java.io.IOException;

import org.junit.Test;

import simpledb.common.DbException;
import simpledb.transaction.TransactionAbortedException;

/**
* Tests running concurrent transactions.
* You do not need to pass this test until Lab 4.
* @see simpledb.systemtest.TransactionTestShared
*/
public class TransactionTestTwo extends SimpleDbTestBase {
@Test public void testTwoThreads()
throws IOException, DbException, TransactionAbortedException {
TransactionTestUtil.validateTransactions(2);
}

/** Make test compatible with older version of ant. */
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(TransactionTestTwo.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Test;

import simpledb.common.Database;
import simpledb.common.DbException;
import simpledb.execution.Delete;
Expand All @@ -26,13 +24,13 @@
import static org.junit.Assert.*;

/**
* Tests running concurrent transactions.
* You do not need to pass this test until lab3.
* Utilities for testing concurrent transactions.
*/
public class TransactionTest extends SimpleDbTestBase {
public class TransactionTestUtil {
// Wait up to 10 minutes for the test to complete
private static final int TIMEOUT_MILLIS = 10 * 60 * 1000;
private void validateTransactions(int threads)

public static void validateTransactions(int threads)
throws DbException, TransactionAbortedException, IOException {
// Create a table with a single integer value = 0
Map<Integer, Integer> columnSpecification = new HashMap<>();
Expand Down Expand Up @@ -213,50 +211,4 @@ public void run() {
}
}
}

@Test public void testSingleThread()
throws IOException, DbException, TransactionAbortedException {
validateTransactions(1);
}

@Test public void testTwoThreads()
throws IOException, DbException, TransactionAbortedException {
validateTransactions(2);
}

@Test public void testFiveThreads()
throws IOException, DbException, TransactionAbortedException {
validateTransactions(5);
}

@Test public void testTenThreads()
throws IOException, DbException, TransactionAbortedException {
validateTransactions(10);
}

@Test public void testAllDirtyFails()
throws IOException, DbException, TransactionAbortedException {
// Allocate a file with ~10 pages of data
HeapFile f = SystemTestUtil.createRandomHeapFile(2, 512*10, null, null);
Database.resetBufferPool(1);

// BEGIN TRANSACTION
Transaction t = new Transaction();
t.start();

// Insert a new row
AbortEvictionTest.insertRow(f, t);

// Scanning the table must fail because it can't evict the dirty page
try {
AbortEvictionTest.findMagicTuple(f, t);
fail("Expected scan to run out of available buffer pages");
} catch (DbException ignored) {}
t.commit();
}

/** Make test compatible with older version of ant. */
public static junit.framework.Test suite() {
return new junit.framework.JUnit4TestAdapter(TransactionTest.class);
}
}

0 comments on commit 728b471

Please sign in to comment.