0001: /*
0002: This source file is part of Smyle, a database library.
0003: For up-to-date information, see http://www.drjava.de/smyle
0004: Copyright (C) 2001 Stefan Reich (doc@drjava.de)
0005:
0006: This library is free software; you can redistribute it and/or
0007: modify it under the terms of the GNU Lesser General Public
0008: License as published by the Free Software Foundation; either
0009: version 2.1 of the License, or (at your option) any later version.
0010:
0011: This library is distributed in the hope that it will be useful,
0012: but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: Lesser General Public License for more details.
0015:
0016: You should have received a copy of the GNU Lesser General Public
0017: License along with this library; if not, write to the Free Software
0018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0019:
0020: For full license text, see doc/license/lgpl.txt in this distribution
0021: */
0022:
0023: package drjava.smyle.tests;
0024:
0025: import java.io.*;
0026: import junit.framework.*;
0027: import java.util.*;
0028: import drjava.util.*;
0029: import drjava.gjutil.*;
0030: import drjava.smyle.*;
0031: import drjava.smyle.testtypes.*;
0032: import drjava.smyle.core.Disk;
0033: import drjava.smyle.core.FileSystemDisk;
0034: import drjava.smyle.core.DiskStore;
0035: import drjava.smyle.meta.*;
0036: import org.artsProject.mcop.*;
0037: import org.artsProject.mcop.core.*;
0038: import drjava.gjutil.Factory;
0039: import org.artsProject.util.*;
0040:
0041: public class StoreTest extends StoreTestBase {
0042: public StoreTest(String name) {
0043: super (name);
0044: }
0045:
0046: public static Test suite(final Factory<Store> storeCreator,
0047: final Factory<Store> storeOpener, final boolean canRotate) {
0048: return new FactoryTestSuite(StoreTest.class, new TestFactory() {
0049: public TestCase createTest(String name) {
0050: StoreTestBase test = new StoreTest(name);
0051: test.init(storeCreator, storeOpener, canRotate);
0052: return test;
0053: }
0054: });
0055: }
0056:
0057: public static TestSuite suite() {
0058: return new AggregatedTestSuite("Store Tests", new Test[] {
0059:
0060: // memory
0061:
0062: /*suite(new Factory<Store>() {
0063: public Store produce() {
0064: return new MemoryStore();
0065: }
0066: }, false),*/
0067:
0068: // disk
0069: suite(new Factory<Store>() {
0070: public Store produce() {
0071: Disk disk = new FileSystemDisk(new File(
0072: "temp/store"), false);
0073: disk.deleteEverything();
0074: return new DiskStore(disk);
0075: }
0076: }, new Factory<Store>() {
0077: public Store produce() {
0078: Disk disk = new FileSystemDisk(new File(
0079: "temp/store"), false);
0080: return new DiskStore(disk);
0081: }
0082: }, true),
0083:
0084: // remote
0085:
0086: /*suite(new Factory<Store>() {
0087: public Store produce() {
0088: Dispatcher serverDispatcher = new Dispatcher(null);
0089: serverDispatcher.becomeGlobalDispatcher();
0090: Store store = new MemoryStore();
0091: Dispatcher clientDispatcher = new Dispatcher(null);
0092: clientDispatcher.becomeGlobalDispatcher();
0093:
0094: return Store.Factory.fromReference(store._getObjectReference());
0095: }
0096: }, true)*/
0097: });
0098: }
0099:
0100: public void testEmptyTable() throws Exception {
0101: assertEquals(0, table.size());
0102: assertTrue(table.isEmpty());
0103: assertNull(table.first());
0104: }
0105:
0106: public void testStoreOneElement() throws Exception {
0107: table.add(john);
0108: assertEquals(1, table.size());
0109: assertTrue(!table.isEmpty());
0110: Person p = table.first();
0111: assertEquals(john, p);
0112: }
0113:
0114: public void testStoreOneElementCommit() throws Exception {
0115: table.add(john);
0116: commitAndGetNewSnapshot();
0117: assertEquals(1, table.size());
0118: Person p = table.first();
0119: assertEquals(john, p);
0120: }
0121:
0122: public void testRotateWithoutCommitEqualsRollback()
0123: throws Exception {
0124: if (!canRotate)
0125: return;
0126: table.add(john);
0127: rotate();
0128: assertEquals(0, table.size());
0129: }
0130:
0131: public void testStoreOneElementRotate() throws Exception {
0132: if (!canRotate)
0133: return;
0134: table.add(john);
0135: commitAndRotate();
0136: assertEquals(1, table.size());
0137: Person p = table.first();
0138: assertEquals(john, p);
0139: }
0140:
0141: public void testStoreTwoElements() throws Exception {
0142: table.add(john);
0143: table.add(anne);
0144: assertEquals(2, table.size());
0145: assertEquals(john, table.get(0));
0146: assertEquals(anne, table.get(1));
0147: }
0148:
0149: public void testSnapshotsAreIsolated() throws Exception {
0150: // forget mutable snapshot and acquire an immutable snapshot
0151: snapshot.forget();
0152: snapshot = store.snapshot();
0153: Table<Person> oldTable = snapshot.getTable("people", Person
0154: .getTypeInfo());
0155:
0156: getNewSnapshot();
0157: table.add(anne);
0158: snapshot.commit();
0159:
0160: assertEquals(0, oldTable.size());
0161:
0162: // assert immutable snapshots are always up-to-date
0163: // (ant not cached for too long)
0164: Snapshot newImmutable = store.snapshot();
0165: assertEquals(1, newImmutable.getTable("people",
0166: Person.getTypeInfo()).size());
0167: }
0168:
0169: public void testForgetImmutableSnapshot() throws Exception {
0170: // forget an immutable snapshot while mutable snaphot is open
0171: Snapshot immutableSnapshot = store.snapshot();
0172: immutableSnapshot.forget();
0173:
0174: snapshot.commit();
0175: }
0176:
0177: public void testInterleavedWrites() throws Exception {
0178: if (store.exclusiveWriteLocking())
0179: return; // Test makes no sense with exclusive locking
0180:
0181: Snapshot oldSnapshot = snapshot;
0182: Table<Person> oldTable = table;
0183: oldTable.add(john);
0184:
0185: getNewSnapshot();
0186: table.add(anne);
0187:
0188: // commit snapshot 1, then snapshot 2
0189:
0190: oldSnapshot.commit();
0191: try {
0192: store.logTo(null);
0193: snapshot.commit();
0194: fail("Exception expected");
0195: } catch (ConcurrentWriteException e) {
0196: // ok
0197: }
0198: }
0199:
0200: public void testNestedWrites() throws Exception {
0201: if (store.exclusiveWriteLocking())
0202: return; // Test makes no sense with exclusive locking
0203:
0204: Snapshot oldSnapshot = snapshot;
0205: Table<Person> oldTable = table;
0206: oldTable.add(john);
0207:
0208: getNewSnapshot();
0209: table.add(anne);
0210:
0211: // commit snapshot 2, then snapshot 1
0212:
0213: snapshot.commit();
0214: try {
0215: store.logTo(null);
0216: oldSnapshot.commit();
0217: fail("Exception expected");
0218: } catch (ConcurrentWriteException e) {
0219: // ok
0220: }
0221: }
0222:
0223: public void testFilter() throws Exception {
0224: table.add(john);
0225: table.add(anne);
0226:
0227: // catch-all filter, count()
0228:
0229: assertEquals(2, table.count(new Person_filter()));
0230:
0231: // find John by name, iterator()
0232:
0233: Person_filter filter = new Person_filter().nameEquals("John");
0234: Iterator<Person> i = table.iterator(filter);
0235: TestUtil.checkIterator(i, new Person[] { john });
0236:
0237: // test two-field filter, contains()
0238:
0239: filter = new Person_filter().nameEquals("Anne").ageEquals(29);
0240: assertTrue(!table.contains(filter));
0241: filter = new Person_filter().nameEquals("Anne").ageEquals(21);
0242: assertTrue(table.contains(filter));
0243:
0244: // test indexOf
0245:
0246: assertEquals(1, table.indexOf(new Person_filter()
0247: .nameEquals("Anne")));
0248: assertEquals(0, table.indexOf(new Person_filter()));
0249: assertEquals(-1, table.indexOf(new Person_filter()
0250: .ageEquals(99)));
0251:
0252: // test ...EqualsIgnoreCase
0253:
0254: filter = new Person_filter().nameEqualsIgnoreCase("aNne");
0255: assertEquals(1, table.count(filter));
0256:
0257: // test get
0258: assertEquals(anne, table.get(new Person_filter()
0259: .nameEquals("Anne")));
0260: assertEquals(null, table.get(new Person_filter()
0261: .nameEquals("Nico")));
0262:
0263: // test subList
0264: TestUtil.checkIterator(table.subList(
0265: new Person_filter().nameEquals("Anne")).iterator(),
0266: new Person[] { anne });
0267:
0268: // test null values
0269: assertEquals(null, table.get(new Person_filter()
0270: .nameEquals(null)));
0271: }
0272:
0273: /* XXX - hm, do we actually want to allow null in records and queries?
0274: public void testNullInFilter() throws Exception {
0275: Person nullPerson = new Person(null, 0);
0276:
0277: table.add(john);
0278: table.add(nullPerson);
0279:
0280: // test null in filter, first()
0281:
0282: assertEquals(nullPerson, table.first(new Person_filter().nameEquals(null)));
0283: }*/
0284:
0285: public void testTwoTablesRotate() throws Exception {
0286: Table<Person> boys = snapshot.getTable("boys", Person
0287: .getTypeInfo());
0288: Table<Person> girls = snapshot.getTable("girls", Person
0289: .getTypeInfo());
0290: boys.add(john);
0291: girls.add(anne);
0292: commitAndRotate();
0293:
0294: // acquire tables in different order than they were created (yes, we're mean)
0295: girls = snapshot.getTable("girls", Person.getTypeInfo());
0296: boys = snapshot.getTable("boys", Person.getTypeInfo());
0297:
0298: assertEquals("Boys", 1, boys.size());
0299: assertEquals("Girls", 1, girls.size());
0300: assertEquals("The boy", john, boys.first());
0301: assertEquals("The girl", anne, girls.first());
0302: }
0303:
0304: public void testRemoveRotate() throws Exception {
0305: try {
0306: table.add(john);
0307: table.add(anne);
0308: table.remove(john);
0309: commitAndRotate();
0310: assertEquals(1, table.size());
0311: assertEquals(anne, table.first());
0312: } catch (Exception e) {
0313: // Sometimes exceptions aren't displayed because of a subsequent exception in
0314: // tearDown(); so we display it here
0315: e.printStackTrace();
0316: throw e;
0317: }
0318: }
0319:
0320: public void testRemoveRotate2() throws Exception {
0321: table.add(john);
0322: table.add(anne);
0323: table.remove(anne);
0324: commitAndRotate();
0325: assertEquals(1, table.size());
0326: assertEquals(john, table.first());
0327: }
0328:
0329: public void testRotateRemove2() throws Exception {
0330: table.add(john);
0331: table.add(anne);
0332: commitAndRotate();
0333: table.remove(anne);
0334: assertEquals(1, table.size());
0335: assertEquals(john, table.first());
0336: }
0337:
0338: public void testAddAll() throws Exception {
0339: ArrayList<Person> v = new ArrayList<Person>();
0340: v.add(john);
0341: v.add(anne);
0342: table.addAll(v);
0343: assertEquals(2, table.size());
0344: assertEquals(john, table.get(0));
0345: assertEquals(anne, table.get(1));
0346: }
0347:
0348: public void testRetrieveSchema() throws Exception {
0349: rotate();
0350: TypeDef type = table.getSchema();
0351: assertEquals(new TypeDef("Person").contentsAdd(
0352: new TypeComponent("string", "name")).contentsAdd(
0353: new TypeComponent("long", "age")), type);
0354: }
0355:
0356: public void testSEEmptyTableConvertsToAnySchema() throws Exception {
0357: // do some operations on the table that end up with an empty table
0358: table.add(john);
0359: table.remove(john);
0360: snapshot.commit();
0361:
0362: // rotate store, load table with Song schema and add a song
0363: store.close();
0364: store = storeOpener.produce();
0365: snapshot = store.mutableSnapshot();
0366: Table<Song> table = snapshot.getTable("people", Song
0367: .getTypeInfo());
0368: table.add(constantSorrow);
0369: snapshot.commit();
0370:
0371: // assert song is still there
0372: snapshot = store.mutableSnapshot();
0373: table = snapshot.getTable("people", Song.getTypeInfo());
0374: assertEquals(constantSorrow, table.first());
0375: }
0376:
0377: public void testSECompletelyDifferentSchema() throws Exception {
0378: // add a person
0379: table.add(john);
0380: snapshot.commit();
0381:
0382: // rotate store, try to load table with Song schema
0383: store.close();
0384: store = storeOpener.produce();
0385: snapshot = store.mutableSnapshot();
0386: try {
0387: Table<Song> table = snapshot.getTable("people", Song
0388: .getTypeInfo());
0389: fail("No exception");
0390: } catch (SchemaChangeException e) {
0391: // ok
0392: }
0393: }
0394:
0395: public void testSEImpairedViewReadOnly() throws Exception {
0396: // add a person
0397: table.add(john);
0398: snapshot.commit();
0399:
0400: // rotate store, try to load table with subset schema
0401: store.close();
0402: store = storeOpener.produce();
0403: snapshot = store.mutableSnapshot();
0404: Table<JustName> table = snapshot.getTable("people", JustName
0405: .getTypeInfo());
0406:
0407: assertTableIsImmutable(table, ImmutableTableException.class,
0408: "age");
0409: }
0410:
0411: void assertTableIsImmutable(Table table, Class exceptionType,
0412: String messageSubstring) {
0413: for (int i = 0; i < 8; i++)
0414: try {
0415: switch (i) {
0416: case 0:
0417: table.add(null);
0418: break;
0419: case 1:
0420: table.removeAll((Filter) null);
0421: break;
0422: case 2:
0423: table.add(null);
0424: break;
0425: case 3:
0426: table.addAll(null);
0427: break;
0428: case 4:
0429: table.clear();
0430: break;
0431: case 5:
0432: table.remove(null);
0433: break;
0434: case 6:
0435: table.remove(0);
0436: break;
0437: case 7:
0438: table.set(0, null);
0439: break;
0440: }
0441: fail("No exception");
0442: } catch (SmyleException e) {
0443: // exception is ok
0444: assertTrue("Wrong exception type: " + e, exceptionType
0445: .isInstance(e));
0446: assertTrue("'" + e.getMessage() + "' should contain '"
0447: + messageSubstring + "'", e.getMessage()
0448: .indexOf(messageSubstring) >= 0);
0449: }
0450: }
0451:
0452: public void testImmutableSnapshot() throws Exception {
0453: Snapshot snapshot = store.snapshot();
0454:
0455: Table table = snapshot.getTable("people", Person.getTypeInfo());
0456: assertEquals(0, table.size());
0457:
0458: assertTableIsImmutable(table, ImmutableSnapshotException.class,
0459: "");
0460:
0461: // commit() and commitAndContinue() just does nothing on an immutable snapshot
0462: snapshot.commitAndContinue();
0463: snapshot.commit();
0464:
0465: /*for (int i = 0; i < 2; i++) try {
0466: switch (i) {
0467: case 0: snapshot.commit(); break;
0468: case 1: snapshot.commitAndContinue(); break;
0469: }
0470: fail("No exception");
0471: } catch (ImmutableSnapshotException e) {
0472: // ok
0473: }*/
0474: }
0475:
0476: public void testSEAddingFieldsOK() throws Exception {
0477: // add a person
0478: table.add(john);
0479: snapshot.commit();
0480:
0481: // rotate store, try to load table with extended schema
0482: store.close();
0483: store = storeOpener.produce();
0484: snapshot = store.mutableSnapshot();
0485: Table<ExtendedPerson> table = snapshot.getTable("people",
0486: ExtendedPerson.getTypeInfo());
0487:
0488: assertEquals(1, table.size());
0489: // male happens to be default gender (=0)
0490: assertEquals(new ExtendedPerson("John", 23, male), table
0491: .first());
0492:
0493: // add an (extended) row with non-default extended fields (gender in this case)
0494: ExtendedPerson lois = new ExtendedPerson("Lois", 27, female);
0495: table.add(lois);
0496: snapshot.commit();
0497:
0498: // rotate
0499: store.close();
0500: store = storeOpener.produce();
0501: snapshot = store.mutableSnapshot();
0502: table = snapshot.getTable("people", ExtendedPerson
0503: .getTypeInfo());
0504:
0505: // assert john and lois are still here
0506: assertEquals(new ExtendedPerson("John", 23, male), table
0507: .first());
0508: assertEquals(lois, table.get(1));
0509: }
0510:
0511: public void testSEAddingManyFieldsOK() throws Exception {
0512: // add a person
0513: table.add(john);
0514: snapshot.commit();
0515:
0516: // rotate store, try to load table with extended schema
0517: store.close();
0518: store = storeOpener.produce();
0519: snapshot = store.mutableSnapshot();
0520: Table<VeryExtendedPerson> table = snapshot.getTable("people",
0521: VeryExtendedPerson.getTypeInfo());
0522:
0523: assertEquals(1, table.size());
0524: // male happens to be default gender (=0)
0525: assertEquals(new VeryExtendedPerson(null, "John", 23, false,
0526: male), table.first());
0527:
0528: // add an (extended) row with non-default extended fields (gender in this case)
0529: VeryExtendedPerson lois = new VeryExtendedPerson("Mrs.",
0530: "Lois", 27, true, female).degreesAdd("Bachelor");
0531: table.add(lois);
0532: snapshot.commit();
0533:
0534: // rotate
0535: store.close();
0536: store = storeOpener.produce();
0537: snapshot = store.mutableSnapshot();
0538: table = snapshot.getTable("people", VeryExtendedPerson
0539: .getTypeInfo());
0540:
0541: // assert john and lois are still here
0542: assertEquals(new VeryExtendedPerson(null, "John", 23, false,
0543: male), table.first());
0544: assertEquals(lois, table.get(1));
0545: }
0546:
0547: public void testSEReorderedDataTypes() throws Exception {
0548: //store.setWriteLatency(0);
0549:
0550: DataTypes original = new DataTypes(true, 1, 2, "test",
0551: new JustName("john")).longsAdd(3).stringsAdd("test")
0552: .structsAdd(new JustName("anne"));
0553:
0554: ReorderedDataTypes reordered = new ReorderedDataTypes(
0555: new JustName("john"), "test", 2, 1, true).longsAdd(3)
0556: .stringsAdd("test").structsAdd(new JustName("anne"));
0557:
0558: // add a record
0559: {
0560: Table<DataTypes> table = snapshot.getTable("datatypes",
0561: DataTypes.getTypeInfo());
0562: table.add(original);
0563: }
0564:
0565: // commit, try to load table with modified schema
0566: commitAndGetNewSnapshot();
0567:
0568: {
0569: Table<ReorderedDataTypes> table = snapshot.getTable(
0570: "datatypes", ReorderedDataTypes.getTypeInfo());
0571: assertEquals(reordered, table.first());
0572:
0573: // add the same row again
0574: table.add(reordered);
0575: }
0576: snapshot.commit();
0577:
0578: // commit, load table with original schema
0579: rotate();
0580: Table<DataTypes> table = snapshot.getTable("datatypes",
0581: DataTypes.getTypeInfo());
0582:
0583: // assert both rows are ok
0584: assertEquals(original, table.get(0));
0585: assertEquals(original, table.get(1));
0586: }
0587:
0588: public void testSENested() throws Exception {
0589: Nested original = new Nested(new Person("John", 33), "what?");
0590: NestedX extended = new NestedX(
0591: new ExtendedPerson("John", 33, 0), "what?");
0592:
0593: // add a record
0594: {
0595: Table<Nested> table = snapshot.getTable("nested", Nested
0596: .getTypeInfo());
0597: table.add(original);
0598: }
0599:
0600: // commit, try to load table with modified schema
0601: commitAndGetNewSnapshot();
0602:
0603: {
0604: Table<NestedX> table = snapshot.getTable("nested", NestedX
0605: .getTypeInfo());
0606: assertEquals(extended, table.first());
0607:
0608: // add the same row again
0609: table.add(extended);
0610: }
0611: snapshot.commit();
0612:
0613: // commit, load table with original schema
0614: rotate();
0615: Table<Nested> table = snapshot.getTable("nested", Nested
0616: .getTypeInfo());
0617:
0618: // assert both rows are ok
0619: assertEquals(original, table.get(0));
0620: assertEquals(original, table.get(1));
0621: }
0622:
0623: public void testSERecursive() throws Exception {
0624: Recursive o1 = new Recursive(), o2 = new Recursive().recAdd(o1);
0625: RecursiveX n1 = new RecursiveX(), n2 = new RecursiveX()
0626: .recAdd(n1);
0627: RecursiveX x1 = new RecursiveX().x("x1"), x2 = new RecursiveX()
0628: .recAdd(x1).x("x2");
0629:
0630: // add a record
0631: {
0632: Table<Recursive> table = snapshot.getTable("recursive",
0633: Recursive.getTypeInfo());
0634: table.add(o2);
0635: }
0636:
0637: // commit, try to load table with modified schema
0638: commitAndGetNewSnapshot();
0639:
0640: {
0641: Table<RecursiveX> table = snapshot.getTable("recursive",
0642: RecursiveX.getTypeInfo());
0643: assertEquals(n2, table.first());
0644:
0645: table.add(x2);
0646: }
0647: snapshot.commit();
0648:
0649: // commit, load table with original schema
0650: rotate();
0651: Table<Recursive> table = snapshot.getTable("recursive",
0652: Recursive.getTypeInfo());
0653:
0654: // assert both rows are ok
0655: assertEquals(o2, table.get(0));
0656: assertEquals(o2, table.get(1));
0657: }
0658:
0659: public void testIterator() throws Exception {
0660: table.add(john);
0661: table.add(anne);
0662: Iterator<Person> i = table.iterator();
0663: TestUtil.checkIterator(i, new Person[] { john, anne });
0664: }
0665:
0666: public void testRemoveAllFilter() throws Exception {
0667: table.add(john);
0668: table.add(anne);
0669: table.removeAll(new Person_filter().nameEquals("Anne"));
0670: assertEquals(1, table.size());
0671: assertEquals(john, table.first());
0672: }
0673:
0674: public void testStoreDisabledAfterClose() throws Exception {
0675: store.close();
0676: try {
0677: for (int i = 0; i < 5; i++)
0678: try {
0679: switch (i) {
0680: // All the following operations must fail on a closed store
0681:
0682: case 0:
0683: store.close();
0684: break;
0685: case 1:
0686: store.snapshot();
0687: break;
0688: case 2:
0689: store.mutableSnapshot();
0690: break;
0691: case 3:
0692: snapshot.getTable("people", Person
0693: .getTypeInfo());
0694: break;
0695: case 4:
0696: snapshot.commit();
0697: break;
0698:
0699: // Note: We don't check Table methods; they may fail or not
0700: }
0701: fail("No exception (i=" + i + ")");
0702: } catch (ClosedStoreException e) {
0703: // ok
0704: }
0705:
0706: // assert Snapshot.forget() is still allowed
0707: snapshot.forget();
0708: } finally {
0709: store = null;
0710: }
0711: }
0712:
0713: public void testSnapshotDisabledAfterForget() throws Exception {
0714: snapshot.forget();
0715: assertSnapshotDisabled();
0716: }
0717:
0718: public void testSnapshotDisabledAfterCommit() throws Exception {
0719: snapshot.commit();
0720: assertSnapshotDisabled();
0721: }
0722:
0723: void assertSnapshotDisabled() throws Exception {
0724: for (int i = 0; i < 3; i++)
0725: try {
0726: switch (i) {
0727: // All the following operations must fail on a disabled snapshot
0728:
0729: case 0:
0730: snapshot.commit();
0731: break;
0732: case 1:
0733: snapshot.getTable("people", Person.getTypeInfo());
0734: break;
0735: case 2:
0736: snapshot.commitAndContinue();
0737: break;
0738:
0739: // Note: We don't check Table methods; they may fail or not
0740: }
0741: fail("No exception (i=" + i + ")");
0742: } catch (ClosedSnapshotException e) {
0743: // ok
0744: }
0745:
0746: snapshot.forget(); // should still be allowed
0747: }
0748:
0749: public void testCommitAndContinue() throws Exception {
0750: if (store.exclusiveWriteLocking())
0751: return;
0752:
0753: Snapshot oldSnapshot = snapshot;
0754: Table<Person> oldTable = table;
0755: oldTable.add(john);
0756: oldSnapshot.commitAndContinue();
0757:
0758: // assert snapshot was committed
0759: getNewSnapshot();
0760: assertEquals(john, table.first());
0761:
0762: // assert we can continue working with the snapshot
0763: oldTable.add(anne);
0764: oldSnapshot.commit();
0765: }
0766:
0767: public void testGetTableTwice() throws Exception {
0768: Table<Person> table1 = snapshot.getTable("sometable", Person
0769: .getTypeInfo());
0770: Table<Person> table2 = snapshot.getTable("sometable", Person
0771: .getTypeInfo());
0772: assertTrue(table1 == table2);
0773: }
0774:
0775: public void testUniqueValues() throws Exception {
0776: table.add(john);
0777: table.add(anne);
0778: table.add(jane);
0779: IntVector ageList = table.getUniqueValues(Person.f_age);
0780:
0781: assertEquals(2, ageList.size());
0782:
0783: // order doesn't matter
0784: assertTrue(ageList.contains(21));
0785: assertTrue(ageList.contains(23));
0786: }
0787:
0788: public void testUniqueValueCountsInt() throws Exception {
0789: table.add(john);
0790: table.add(anne);
0791: table.add(jane);
0792:
0793: // without filter
0794: Map<Integer, Integer> map = table
0795: .getUniqueValueCounts(Person.f_age);
0796: assertEquals(2, map.size());
0797: assertEquals(new Integer(1), map.get(new Integer(21)));
0798: assertEquals(new Integer(2), map.get(new Integer(23)));
0799:
0800: // with filter
0801: map = table.getUniqueValueCounts(Person.f_age,
0802: new Person_filter().nameEquals("John"));
0803: assertEquals(1, map.size());
0804: assertEquals(new Integer(1), map.get(new Integer(23)));
0805: }
0806:
0807: public void testUniqueValueCounts() throws Exception {
0808: table.add(john);
0809: table.add(oldJohn);
0810: table.add(anne);
0811:
0812: Map<String, Integer> map = table
0813: .getUniqueValueCounts(Person.f_name);
0814: assertEquals(2, map.size());
0815: assertEquals(new Integer(2), map.get("John"));
0816: assertEquals(new Integer(1), map.get("Anne"));
0817: }
0818:
0819: public void testIndexOf() throws Exception {
0820: table.add(john);
0821: table.add(anne);
0822: assertEquals(0, table.indexOf(john));
0823: assertEquals(1, table.indexOf(anne));
0824: assertEquals(-1, table.indexOf(jane));
0825: }
0826:
0827: public void testSet() throws Exception {
0828: table.add(john);
0829: table.add(anne);
0830: table.set(0, anne);
0831: table.set(1, john);
0832: assertEquals(anne, table.get(0));
0833: assertEquals(john, table.get(1));
0834: }
0835:
0836: public void testGetOrCreate() throws Exception {
0837: Person_filter filter = new Person_filter().nameEquals("John");
0838: assertEquals(new Person().name("John"), table
0839: .getOrCreate(filter));
0840: table.add(john);
0841: table.add(anne);
0842: assertEquals(john, table.getOrCreate(filter));
0843: }
0844:
0845: public void testPut() throws Exception {
0846: Person_filter filter = new Person_filter().nameEquals("John");
0847: table.put(filter, john);
0848: assertEquals(1, table.size());
0849: assertEquals(john, table.get(0));
0850:
0851: Person oldJohn = new Person().name("John").age(49);
0852: table.put(filter, oldJohn);
0853: assertEquals(1, table.size());
0854: assertEquals(oldJohn, table.get(0));
0855: }
0856:
0857: public void testFailSafeIterators() throws Exception {
0858: // modifications that cause iterators to fail
0859:
0860: ArrayList<Person> v = new ArrayList<Person>();
0861: v.add(anne);
0862:
0863: for (int i = 0; i < 5; i++) {
0864: table.clear();
0865: table.add(john);
0866: Iterator<Person> it = table.iterator();
0867: switch (i) {
0868: case 0:
0869: table.add(anne);
0870: break;
0871: case 1:
0872: table.addAll(v);
0873: break;
0874: case 2:
0875: table.clear();
0876: break;
0877: case 3:
0878: table.remove(john);
0879: break;
0880: case 4:
0881: table.remove(0);
0882: break;
0883: }
0884: assertIteratorFails(it);
0885: }
0886:
0887: // modifications that don't cause iterators to fail
0888:
0889: for (int i = 0; i < 2; i++) {
0890: table.clear();
0891: table.add(john);
0892: Iterator<Person> it = table.iterator();
0893: switch (i) {
0894: case 0:
0895: table.addAll(new ArrayList<Person>());
0896: break;
0897: case 1:
0898: table.remove(anne);
0899: break;
0900: }
0901: TestUtil.checkIterator(it, new Person[] { john });
0902: }
0903: }
0904:
0905: public void testIteratorNoticesReplacedElements() throws Exception {
0906: table.add(john);
0907: Iterator<Person> it = table.iterator();
0908: assertTrue(it.hasNext());
0909: table.set(0, anne);
0910: assertEquals(anne, it.next());
0911: }
0912:
0913: void assertIteratorFails(Iterator<Person> it) {
0914: for (int i = 0; i < 2; i++)
0915: try {
0916: switch (i) {
0917: // All the following operations must fail
0918:
0919: case 0:
0920: it.hasNext();
0921: break;
0922: case 1:
0923: it.next();
0924: break;
0925: case 2:
0926: it.remove();
0927: break;
0928: }
0929: fail("No exception (i=" + i + ")");
0930: } catch (ConcurrentModificationException e) {
0931: // ok
0932: }
0933: }
0934:
0935: public void testIteratorRemove() throws Exception {
0936: table.add(john);
0937: table.add(anne);
0938: Iterator<Person> it = table.iterator();
0939: assertEquals(john, it.next());
0940: it.remove();
0941: assertTrue(it.hasNext());
0942: assertEquals(anne, it.next());
0943: it.remove();
0944: assertTrue(!it.hasNext());
0945: assertEquals(0, table.size());
0946: }
0947:
0948: /** a thread that acquires a mutable snapshot and doesn't release it */
0949: class SnapshotKeeper extends Thread {
0950: Snapshot snapshot;
0951: Exception error;
0952:
0953: SnapshotKeeper() throws Exception {
0954: start();
0955: }
0956:
0957: void joinMe() throws Exception {
0958: join();
0959: if (error != null)
0960: throw error;
0961: }
0962:
0963: public void run() {
0964: try {
0965: snapshot = store.mutableSnapshot();
0966: } catch (Exception error) {
0967: this .error = error;
0968: }
0969: }
0970: }
0971:
0972: public void testWriteLockTimeout() throws Exception {
0973: snapshot.forget();
0974:
0975: SnapshotKeeper sk = new SnapshotKeeper();
0976: sk.joinMe();
0977:
0978: store.setTimeout(1); // timeout as quickly as possible
0979:
0980: try {
0981: store.logTo(null);
0982: Snapshot snapshot1 = store.mutableSnapshot();
0983: fail("No exception");
0984: } catch (TimeoutException e) {
0985: // ok
0986: }
0987: }
0988:
0989: public void testTwoThreadsWaitingForWriteLock() throws Exception {
0990: snapshot.forget();
0991:
0992: SnapshotKeeper sk1 = new SnapshotKeeper();
0993: sk1.joinMe();
0994: // sk1 now holds snapshot
0995:
0996: SnapshotKeeper sk2 = new SnapshotKeeper();
0997: SnapshotKeeper sk3 = new SnapshotKeeper();
0998: Thread.sleep(100); // should be enough for sk2 and sk3 to get into blocking mode
0999:
1000: sk1.snapshot.forget();
1001:
1002: // sk2 and sk3 should be able to acquire write lock now
1003: sk2.joinMe();
1004: Thread.sleep(100);
1005: sk2.snapshot.forget();
1006: sk3.joinMe();
1007: }
1008:
1009: public void testOnlyOneMutableSnapshotPerThread() throws Exception {
1010: if (!store.exclusiveWriteLocking())
1011: return;
1012:
1013: try {
1014: store.logTo(null);
1015: store.mutableSnapshot();
1016: fail("No exception");
1017: } catch (MultipleMutableSnapshotsException e) {
1018: // ok
1019: }
1020: }
1021:
1022: public void testOrderByInt() throws Exception {
1023: table.add(oldJohn);
1024: table.add(john);
1025: table.add(anne);
1026: table.add(jane);
1027: // john and jane have same age, asserts that duplicates are allowed
1028:
1029: Iterator<Person> i = table.iterator(new Person_filter()
1030: .orderByAge());
1031: assertTrue(i.hasNext());
1032: assertEquals(anne, i.next());
1033: assertTrue(i.hasNext());
1034: Person p = i.next();
1035:
1036: // order within same age is undefined
1037: if (p.equals(john))
1038: assertEquals(jane, i.next());
1039: else {
1040: assertEquals(jane, p);
1041: assertEquals(john, i.next());
1042: }
1043:
1044: TestUtil.checkIterator(i, new Person[] { oldJohn });
1045: }
1046:
1047: public void testOrderByString() throws Exception {
1048: table.add(john);
1049: table.add(jane);
1050:
1051: Iterator<Person> i = table.iterator(new Person_filter()
1052: .orderByName());
1053: TestUtil.checkIterator(i, new Person[] { jane, john });
1054: }
1055:
1056: public void testOrderByTwoFields() throws Exception {
1057: table.add(john);
1058: table.add(anne);
1059: table.add(jane);
1060:
1061: Iterator<Person> i = table.iterator(new Person_filter()
1062: .orderByAge().orderByName());
1063: TestUtil.checkIterator(i, new Person[] { anne, jane, john });
1064: }
1065:
1066: public void testOrderByLong() throws Exception {
1067: Table<DataTypes> table = snapshot.getTable("datatypes",
1068: DataTypes.getTypeInfo());
1069: DataTypes r1 = new DataTypes(), r2 = new DataTypes();
1070: r1.strct = new JustName();
1071: r2.strct = new JustName();
1072: r1.ll = 12345678901234L;
1073: r2.ll = -12345678901234L;
1074: table.add(r1);
1075: table.add(r2);
1076:
1077: Iterator<DataTypes> i = table.iterator(new DataTypes_filter()
1078: .orderByLl());
1079: TestUtil.checkIterator(i, new DataTypes[] { r2, r1 });
1080: }
1081:
1082: public void testOrderByReverse() throws Exception {
1083: table.add(john);
1084: table.add(jane);
1085:
1086: TestUtil.checkIterator(table.iterator(new Person_filter()
1087: .orderByName().reverse()), new Person[] { john, jane });
1088: TestUtil.checkIterator(table.iterator(new Person_filter()
1089: .reverse().orderByName()), new Person[] { john, jane });
1090: TestUtil.checkIterator(table.iterator(new Person_filter()
1091: .reverse().orderByName().reverse()), new Person[] {
1092: jane, john });
1093: }
1094:
1095: public void testAutoIncrement() throws Exception {
1096: table.setAutoIncrementField(Person.f_age);
1097: table.add(new Person("one", 0));
1098: table.add(0, new Person("five", 5));
1099: table.add(1, new Person("three", 3));
1100: table.add(new Person("six", 0));
1101: TestUtil.checkIterator(table.iterator(), new Person[] {
1102: new Person("five", 5), new Person("three", 3),
1103: new Person("one", 1), new Person("six", 6) });
1104:
1105: commitAndRotate();
1106: table.add(new Person("seven", 0));
1107: TestUtil.checkIterator(table.iterator(), new Person[] {
1108: new Person("five", 5), new Person("three", 3),
1109: new Person("one", 1), new Person("six", 6),
1110: new Person("seven", 7) });
1111: }
1112:
1113: public void testAutoIncrementOnExistingTable() throws Exception {
1114: table.add(new Person("six", 0));
1115: table.add(new Person("five", 5));
1116: table.setAutoIncrementField(Person.f_age);
1117: table.add(new Person("seven", 0));
1118: TestUtil.checkIterator(table.iterator(), new Person[] {
1119: new Person("six", 6), new Person("five", 5),
1120: new Person("seven", 7) });
1121: }
1122:
1123: // tests every possible char from 0000 to FFFF excluding
1124: // D800-DBFF (that doesn't work in UTF-8 for some reason and
1125: // doesn't seem to contain any defined characters anyway)
1126: public void testFullUnicodeRange() throws Exception {
1127: StringBuffer buf = new StringBuffer(65536);
1128: for (int i = 0; i < 65536; i++)
1129: if (i < 0xD800 || i >= 0xDC00)
1130: buf.append((char) i);
1131: String s = buf.toString();
1132: /*System.out.println("Chars: "+s.length());
1133: System.out.println("Bytes: "+MCOP.stringToBytes(s).length);
1134: String s2 = MCOP.bytesToString(MCOP.stringToBytes(s));
1135: System.out.println("Chars: "+s2.length());*/
1136: table.add(new Person(s, 0));
1137: String s2 = table.first().name;
1138: assertEquals(s.length(), s2.length());
1139: for (int i = 0; i < s.length(); i++) {
1140: /*if ((int) s.charAt(i) != (int) s2.charAt(i))
1141: System.out.println("Char #"+i+": "+(int) s.charAt(i)+" vs "+(int) s2.charAt(i));*/
1142: assertEquals("Char #" + i, (int) s.charAt(i), (int) s2
1143: .charAt(i));
1144: }
1145: }
1146:
1147: DataTypes dt = new DataTypes(true, 1, 2, "test", new JustName(
1148: "john")).longsAdd(3).stringsAdd("test").structsAdd(
1149: new JustName("anne"));
1150:
1151: public void testDataTypesFilter() throws Exception {
1152: Table<DataTypes> table = snapshot.getTable("dt", DataTypes
1153: .getTypeInfo());
1154: table.add(dt);
1155:
1156: for (int i = 0; i < 6; i++) {
1157: DataTypes_filter filter = new DataTypes_filter().bEquals(
1158: i != 1 ? true : false).lEquals(i != 2 ? 1 : 2)
1159: .llEquals(i != 3 ? 2 : 3).sEquals(
1160: i != 4 ? "test" : "x").strctEquals(
1161: i != 5 ? new JustName("john")
1162: : new JustName("jane"));
1163: assertEquals(i == 0, table.contains(filter));
1164: }
1165: }
1166:
1167: public void testNullElement() throws Exception {
1168: for (int i = 0; i < 2; i++)
1169: try {
1170: if (i == 0)
1171: table.add(null);
1172: else {
1173: table.add(john);
1174: table.set(0, null);
1175: }
1176: fail("No exception");
1177: } catch (NullPointerException e) {
1178: // ok
1179: }
1180: }
1181:
1182: public void testWrongElementClass() throws Exception {
1183: JustName badElement = new JustName();
1184:
1185: for (int i = 0; i < 2; i++)
1186: try {
1187: if (i == 0)
1188: ((Table) table).add(badElement);
1189: else {
1190: table.add(john);
1191: ((Table) table).set(0, badElement);
1192: }
1193: fail("No exception");
1194: } catch (ClassCastException e) {
1195: // ok
1196: }
1197: }
1198:
1199: public void testOptimize() throws Exception {
1200: store.optimize();
1201: rotate();
1202: }
1203: }
|