/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): N/A. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.store.xa; // Java 2 standard packages import java.io.*; // Third party packages import junit.framework.*; import org.apache.log4j.Logger; // Local packages import org.mulgara.util.Constants; import org.mulgara.util.TempDir; /** * Test cases for AVLFile. * * @created 2001-09-20 * * @author David Makepeace * * @version $Revision: 1.9 $ * * @modified $Date: 2005/01/05 04:59:31 $ @maintenanceAuthor $Author: newmana $ * * @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A> * * @copyright ©2001 <a href="http://www.pisoftware.com/">Plugged In * Software Pty Ltd</a> * * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ public class AVLFileTest extends TestCase { /** * Logger. */ @SuppressWarnings("unused") private final static Logger logger = Logger.getLogger(AVLFileTest.class); /** * Description of the Field * */ private static AVLComparator comparator = new IntComparator(); /** * Description of the Field * */ private static Block metaroot = Block.newInstance(AVLFile.Phase.RECORD_SIZE * Constants.SIZEOF_LONG); /** * Description of the Field * */ private AVLFile avlFile; /** * Named constructor. * * @param name The name of the test. */ public AVLFileTest(String name) { super(name); } /** * Hook for test runner to obtain a test suite from. * * @return The test suite to run. */ public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new AVLFileTest("testInsert")); suite.addTest(new AVLFileTest("testFind")); suite.addTest(new AVLFileTest("testRemove")); suite.addTest(new AVLFileTest("testReinsert")); suite.addTest(new AVLFileTest("testPersist")); suite.addTest(new AVLFileTest("testMultiphase")); return suite; } /** * Default test runner. * * @param args The command line arguments */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Gets the Key attribute of the AVLFileTest class * * @param node PARAMETER TO DO * @return The Key value */ private static int getKey(AVLNode node) { return (node == null) ? 0 : node.getPayloadInt(1); } /** * Creates a new file required to do the testing. * * @throws IOException EXCEPTION TO DO */ public void setUp() throws IOException { boolean exceptionOccurred = true; try { File dir = TempDir.getTempDir(); avlFile = new AVLFile(new File(dir, "avlfiletest"), 1); exceptionOccurred = false; } finally { if (exceptionOccurred) { tearDown(); } } } /** * Closes the file used for testing. * * @throws IOException EXCEPTION TO DO */ public void tearDown() throws IOException { if (avlFile != null) { try { avlFile.unmap(); if (System.getProperty("os.name").startsWith("Win")) { // Need this for Windows or truncate() always fails for mapped files. System.gc(); System.runFinalization(); } avlFile.close(); } finally { avlFile = null; } } } /** * Test insert * * @throws IOException EXCEPTION TO DO */ public void testInsert() throws IOException { AVLFile.Phase phase0 = avlFile.new Phase(); avlFile.clear(); //AVLNode node = phase0.newAVLNodeInstance(); insert(phase0, 60); assertEquals(1, getHeight(phase0)); insert(phase0, 50); assertEquals(2, getHeight(phase0)); insert(phase0, 70); assertEquals(2, getHeight(phase0)); insert(phase0, 80); assertEquals(3, getHeight(phase0)); // test RR rotation insert(phase0, 90); assertEquals(3, getHeight(phase0)); // test RL rotation insert(phase0, 65); assertEquals(3, getHeight(phase0)); insert(phase0, 75); assertEquals(3, getHeight(phase0)); insert(phase0, 77); assertEquals(4, getHeight(phase0)); try { insert(phase0, 50); fail("Able to insert the same node values twice"); } catch (IllegalArgumentException e) { } } /** * Test find * * @throws IOException EXCEPTION TO DO */ public void testFind() throws IOException { AVLFile.Phase phase0 = avlFile.new Phase(); avlFile.clear(); AVLNode[] nodes = find(phase0, 5); if (nodes != null) { fail("Found node in empty tree"); } insert(phase0, 6); insert(phase0, 5); insert(phase0, 8); assertFound(find(phase0, 5), 5); assertNotFound(find(phase0, 7), 6, 8); } /** * Test remove * * @throws IOException EXCEPTION TO DO */ public void testRemove() throws IOException { AVLFile.Phase phase0 = avlFile.new Phase(); avlFile.clear(); insert(phase0, 60); assertEquals(1, getHeight(phase0)); insert(phase0, 50); assertEquals(2, getHeight(phase0)); insert(phase0, 70); assertEquals(2, getHeight(phase0)); insert(phase0, 80); assertEquals(3, getHeight(phase0)); insert(phase0, 90); assertEquals(3, getHeight(phase0)); insert(phase0, 65); assertEquals(3, getHeight(phase0)); insert(phase0, 75); assertEquals(3, getHeight(phase0)); insert(phase0, 77); assertEquals(4, getHeight(phase0)); find(phase0, 60)[0].remove(); assertEquals(4, getHeight(phase0)); assertNotFound(find(phase0, 60), 50, 65); assertFound(find(phase0, 65), 65); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 80), 80); assertFound(find(phase0, 90), 90); assertFound(find(phase0, 65), 65); assertFound(find(phase0, 75), 75); assertFound(find(phase0, 77), 77); find(phase0, 50)[0].remove(); assertEquals(3, getHeight(phase0)); assertNotFound(find(phase0, 50), 0, 65); assertFound(find(phase0, 65), 65); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 75), 75); assertFound(find(phase0, 77), 77); assertFound(find(phase0, 80), 80); assertFound(find(phase0, 90), 90); find(phase0, 75)[0].remove(); assertEquals(3, getHeight(phase0)); assertNotFound(find(phase0, 75), 70, 77); assertFound(find(phase0, 65), 65); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 77), 77); assertFound(find(phase0, 80), 80); assertFound(find(phase0, 90), 90); find(phase0, 65)[0].remove(); assertEquals(3, getHeight(phase0)); assertNotFound(find(phase0, 65), 0, 70); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 77), 77); assertFound(find(phase0, 80), 80); assertFound(find(phase0, 90), 90); find(phase0, 90)[0].remove(); assertEquals(2, getHeight(phase0)); assertNotFound(find(phase0, 90), 80, 0); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 77), 77); assertFound(find(phase0, 80), 80); find(phase0, 80)[0].remove(); assertEquals(2, getHeight(phase0)); assertNotFound(find(phase0, 80), 77, 0); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 77), 77); find(phase0, 70)[0].remove(); assertEquals(1, getHeight(phase0)); assertNotFound(find(phase0, 70), 0, 77); assertFound(find(phase0, 77), 77); find(phase0, 77)[0].remove(); assertNull(phase0.getRootNode()); assertNull(find(phase0, 77)); } /** * Test reinsert * * @throws IOException EXCEPTION TO DO */ public void testReinsert() throws IOException { AVLFile.Phase phase0 = avlFile.new Phase(); avlFile.clear(); insert(phase0, 60); insert(phase0, 50); insert(phase0, 70); insert(phase0, 80); assertFound(find(phase0, 60), 60); assertFound(find(phase0, 50), 50); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 80), 80); find(phase0, 60)[0].remove(); assertNotFound(find(phase0, 60), 50, 70); assertFound(find(phase0, 50), 50); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 80), 80); insert(phase0, 60); assertFound(find(phase0, 60), 60); assertFound(find(phase0, 50), 50); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 80), 80); // set up for testPersist() phase0.writeToBlock(metaroot, 0); } /** * A unit test for JUnit * * @throws IOException EXCEPTION TO DO */ public void testPersist() throws IOException { AVLFile.Phase phase0 = avlFile.new Phase(metaroot, 0); @SuppressWarnings("unused") AVLFile.Phase.Token token0 = phase0.use(); AVLFile.Phase phase1 = avlFile.new Phase(); assertFound(find(phase1, 60), 60); assertFound(find(phase1, 50), 50); assertFound(find(phase1, 70), 70); assertFound(find(phase1, 80), 80); } /** * Test multiphasic modifications * * @throws IOException EXCEPTION TO DO */ public void testMultiphase() throws IOException { AVLFile.Phase phase0 = avlFile.new Phase(); avlFile.clear(); insert(phase0, 60); insert(phase0, 50); insert(phase0, 70); insert(phase0, 80); assertFound(find(phase0, 60), 60); assertFound(find(phase0, 50), 50); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 80), 80); @SuppressWarnings("unused") AVLFile.Phase.Token token0 = phase0.use(); AVLFile.Phase phase1 = avlFile.new Phase(); find(phase1, 60)[0].remove(); assertNotFound(find(phase1, 60), 50, 70); assertFound(find(phase1, 50), 50); assertFound(find(phase1, 70), 70); assertFound(find(phase1, 80), 80); assertFound(find(phase0, 60), 60); assertFound(find(phase0, 50), 50); assertFound(find(phase0, 70), 70); assertFound(find(phase0, 80), 80); insert(phase1, 60); assertFound(find(phase1, 60), 60); assertFound(find(phase1, 50), 50); assertFound(find(phase1, 70), 70); assertFound(find(phase1, 80), 80); try { find(phase0, 60)[0].remove(); fail("Able to remove from a read-only phase"); } catch (IllegalStateException ex) { } try { insert(phase0, 75); fail("Able to insert into a read-only phase"); } catch (IllegalStateException ex) { } } /** * METHOD TO DO * * @param phase PARAMETER TO DO */ void dumpTree(AVLFile.Phase phase) { AVLNode node = phase.getRootNode(); System.out.println(toString(node)); if (node != null) { node.release(); } } /** * METHOD TO DO * * @param node PARAMETER TO DO * @return RETURNED VALUE TO DO */ String toString(AVLNode node) { if (node == null) { return "."; } AVLNode lNode = node.getLeftChildNode(); AVLNode rNode = node.getRightChildNode(); String str = "<" + getKey(node) + "[" + toString(lNode) + "," + toString(rNode) + "]>"; if (lNode != null) { lNode.release(); } if (rNode != null) { rNode.release(); } return str; } /** * Gets the Height attribute of the AVLFileTest object * * @param phase PARAMETER TO DO * @return The Height value */ private int getHeight(AVLFile.Phase phase) { AVLNode rootNode = phase.getRootNode(); int height = rootNode.getHeight(); rootNode.release(); return height; } /** * METHOD TO DO * * @param phase PARAMETER TO DO * @param value PARAMETER TO DO * @throws IOException EXCEPTION TO DO */ private void insert(AVLFile.Phase phase, int value) throws IOException { AVLNode[] findResult = find(phase, value); try { AVLNode newNode = phase.newAVLNodeInstance(); try { newNode.putPayloadInt(1, value); newNode.write(); if (findResult == null) { phase.insertFirst(newNode); } else { // Insert the node into the tree. int li = AVLFile.leafIndex(findResult); findResult[li].insert(newNode, 1 - li); } } finally { newNode.release(); } } finally { if (findResult != null) { AVLFile.release(findResult); } } } /** * METHOD TO DO * * @param phase PARAMETER TO DO * @param value PARAMETER TO DO * @return RETURNED VALUE TO DO */ private AVLNode[] find(AVLFile.Phase phase, int value) { return phase.find(comparator, new long[] {value}); } /** * METHOD TO DO * * @param nodes PARAMETER TO DO * @param value PARAMETER TO DO */ private void assertFound(AVLNode[] nodes, int value) { try { assertNotNull("No present node found in occupied tree.", nodes); assertEquals("Incorrect number of nodes returned from find " + ( (nodes.length == 2) ? ("(" + getKey(nodes[0]) + ", " + getKey(nodes[1]) + ")") : ""), 1, nodes.length); assertEquals("Incorrect node found", value, getKey(nodes[0])); } finally { AVLFile.release(nodes); } } /** * METHOD TO DO * * @param nodes PARAMETER TO DO * @param valueL PARAMETER TO DO * @param valueR PARAMETER TO DO */ private void assertNotFound(AVLNode[] nodes, int valueL, int valueR) { try { assertNotNull("No in-between nodes found in occupied tree.", nodes); assertEquals("Incorrect number of nodes returned from find", 2, nodes.length); if (valueL == 0) { assertNull("Non-null node found when searching for small node", nodes[0]); } else { assertNotNull("Null node returned as first node from find", nodes[0]); } if (valueR == 0) { assertNull("Non-null node found when searching for large node", nodes[1]); } else { assertNotNull("Null node returned as first node from find", nodes[1]); } assertEquals("Incorrect node found (other node is " + getKey(nodes[1]) + ")", valueL, getKey(nodes[0])); assertEquals("Incorrect node found", valueR, getKey(nodes[1])); } finally { AVLFile.release(nodes); } } static class IntComparator implements AVLComparator { public int compare(long[] key, AVLNode node) { return (int) key[0] - node.getPayloadInt(1); } } }