/* Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Jun 11, 2008 */ package com.bigdata.btree.filter; import java.util.NoSuchElementException; import java.util.Random; import java.util.UUID; import com.bigdata.btree.AbstractBTree; import com.bigdata.btree.AbstractBTreeTupleCursor.ReadOnlyBTreeTupleCursor; import com.bigdata.btree.AbstractTupleCursorTestCase; import com.bigdata.btree.BTree; import com.bigdata.btree.IRangeQuery; import com.bigdata.btree.ITupleCursor; import com.bigdata.btree.ITupleCursor2; import com.bigdata.btree.ITupleIterator; import com.bigdata.btree.IndexMetadata; import com.bigdata.btree.TestTuple; import com.bigdata.btree.Tuple; import com.bigdata.rawstore.SimpleMemoryRawStore; /** * Test suite for the {@link Reverserator}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> */ public class TestReverserator extends AbstractTupleCursorTestCase { /** * */ public TestReverserator() { } /** * @param arg0 */ public TestReverserator(String arg0) { super(arg0); } @Override protected ITupleCursor2<String> newCursor(AbstractBTree btree, int flags, byte[] fromKey, byte[] toKey) { return new ReadOnlyBTreeTupleCursor<String>((BTree) btree, new Tuple<String>(btree, IRangeQuery.DEFAULT), fromKey, toKey); } /** * @todo add tests for the rest of the {@link ITupleCursor} API since the * {@link Reverserator} implements the full {@link ITupleCursor} API. */ public void test_reverse_traversal() { BTree btree = BTree.create(new SimpleMemoryRawStore(), new IndexMetadata( UUID.randomUUID())); btree.insert(10, "Bryan"); btree.insert(20, "Mike"); btree.insert(30, "James"); // test reverse iterator, including linked state with cursor. { final ITupleCursor2<String> cursor = newCursor(btree, IRangeQuery.DEFAULT, null/* fromKey */, null/* toKey */); final ITupleIterator<String> itr = new Reverserator<String>(cursor); // assertEquals(null, cursor.tuple()); assertTrue(itr.hasNext()); assertEquals(new TestTuple<String>(30, "James"), itr.next()); assertEquals(new TestTuple<String>(30, "James"), cursor.tuple()); assertTrue(itr.hasNext()); assertEquals(new TestTuple<String>(20, "Mike"), itr.next()); assertEquals(new TestTuple<String>(20, "Mike"), cursor.tuple()); assertTrue(itr.hasNext()); assertEquals(new TestTuple<String>(10, "Bryan"), itr.next()); assertEquals(new TestTuple<String>(10, "Bryan"), cursor.tuple()); // exhausted. assertFalse(itr.hasNext()); // exhausted. try { itr.next(); fail("Expecting " + NoSuchElementException.class); } catch (NoSuchElementException ex) { log.info("Ignoring expected exception: " + ex); } // make sure itr will not restart. assertFalse(itr.hasNext()); // make sure itr will not restart. try { itr.next(); fail("Expecting " + NoSuchElementException.class); } catch (NoSuchElementException ex) { log.info("Ignoring expected exception: " + ex); } } } /** * Stress test written in an attempt to find a spin lock in the reverse * cursor traversal. * <p> * Note: This test was in the jetty branch. I have picked it up and copied * it into the master. The version in the master should be preserved. * * @see <a href="http://trac.blazegraph.com/ticket/1078"> Possible tight loop * in cursor.prior() </a> */ public void test_reverse_with_branching_factor() { final Random r = new Random(); for (int bf = 32; bf < 1024; bf += r.nextInt(32)) { final IndexMetadata metadata = new IndexMetadata(UUID.randomUUID()); metadata.setBranchingFactor(bf); final BTree btree = BTree.create(new SimpleMemoryRawStore(), metadata); long ntuples = 0L; for (int i = 1; i < 2000; i++) { final String key = "key" + r.nextInt(); if (btree.contains(key)) continue; btree.insert(key, "value" + r.nextInt()); ntuples++; final ITupleCursor2<String> cursor = newCursor(btree, IRangeQuery.DEFAULT, null/* fromKey */, null/* toKey */); final ITupleIterator<String> itr = new Reverserator<String>( cursor); long count = 0; while (itr.hasNext()) { itr.next(); count++; } assertEquals(count, ntuples); } } } }