001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.test;
022:
023: import java.lang.reflect.*;
024:
025: import com.db4o.*;
026: import com.db4o.config.*;
027: import com.db4o.ext.*;
028: import com.db4o.foundation.*;
029: import com.db4o.internal.*;
030: import com.db4o.test.types.*;
031:
032: /**
033: * The original old regression test, without any S.O.D.A. functionality.
034: * Tests will be slowly migrated to AllTests.java.
035: */
036: public class Regression {
037:
038: /**
039: * uses a small subset of classes
040: * see method testClasses at the end of this file
041: */
042: private static final boolean DEBUG = false;
043:
044: /** no comparisons, used to time performance only */
045: private static final boolean PROFILE_ONLY = false;
046:
047: /** number of regression runs */
048: private static final int RUNS = 1;
049:
050: /** run the default JDK1 test on all classes */
051: private static final boolean DEFAULT = true;
052:
053: /** run JDK2 tests */
054: private static final boolean JDK2 = true;
055:
056: /** number of thread regression runs */
057: protected static final int THREAD_RUNS = 300;
058:
059: /**
060: * runs the thread test
061: * For a real thread test run, set DEFAULT and JDK 2 to false
062: * Increase runs to a higher value
063: */
064: private static final boolean THREADS = false;
065:
066: /** the number of RUNS or THREAD_RUNS between commits */
067: private static final int COMMIT_AFTER = 5;
068:
069: /** log class name of current test class */
070: private static final boolean LOG_CLASS_NAMES = true;
071:
072: public static void main(String[] args) {
073:
074: new java.io.File(FILE).delete();
075:
076: Db4o.configure().messageLevel(-1);
077: // Db4o.configure().exceptionsOnNotStorable(true);
078:
079: // Db4o.licensedTo("tobi@db4o.com");
080: // Db4o.configure().password("Houilo7");
081: // Db4o.configure().encrypt(true);
082:
083: new Regression().run();
084: }
085:
086: public void run() {
087: if (isJDK2() && JDK2) {
088: Thread.currentThread().setName("JDK2 Regression Test");
089: try {
090: Regression regression2 = (Regression) Class.forName(
091: "com.db4o.test.test2.Regression2")
092: .newInstance();
093: run1(regression2.testClasses());
094: } catch (Exception e) {
095: e.printStackTrace();
096: }
097: }
098: if (DEFAULT) {
099: Thread.currentThread().setName("Default Regression Test");
100: run1(testClasses());
101: }
102:
103: if (THREADS) {
104: try {
105: threadsSharp = true;
106: new Thread(new Thread1(this )).start();
107: Thread.sleep(100);
108: // the server socket neads a little time to come up
109: new Thread(new Thread2(this )).start();
110: Thread.sleep(100);
111: new Thread(new Thread3(this )).start();
112:
113: // We don't want to run out of main to allow sequential
114: // execution of Ant tasks.
115: do {
116: Cool.sleepIgnoringInterruption(300);
117: } while (threadsSharp);
118:
119: } catch (Exception e) {
120: e.printStackTrace();
121: }
122: } else {
123: completed();
124: }
125: }
126:
127: public void run1(RTestable[] clazzes) {
128: openedThreads++;
129: long time = System.currentTimeMillis();
130: mainLoop(clazzes);
131: time = System.currentTimeMillis() - time;
132: System.out.println("\n" + Thread.currentThread().getName()
133: + ": " + time + " ms.");
134: returnedThreads++;
135: if (returnedThreads >= openedThreads) {
136: if (errors.length() == 0) {
137: ObjectContainer con = open();
138: int objectCount = con.get(null).size();
139: closeAllButMemoryFile(con);
140: System.out
141: .println(PROFILE_ONLY ? "Profile run completed."
142: : "Regression Test Passed. "
143: + objectCount + " objects.");
144: } else {
145: System.out.println("!!! Regression Test Failed. !!!");
146: }
147: System.out.println(Db4o.version());
148: System.out.println(errors);
149: if (threadsSharp) {
150: if (openDelegate != null) {
151: openDelegate.completed();
152: }
153: threadsSharp = false;
154: }
155: }
156: }
157:
158: public void mainLoop(RTestable[] clazzes) {
159: int commitCounter = 0;
160: int run = 0;
161: ObjectContainer con = open();
162: for (int k = 0; k < runs(); k++) {
163: run++;
164: System.out.println(Thread.currentThread().getName()
165: + " Run:" + run);
166: closeFile = false;
167: for (int i = 0; i < 2; i++) {
168: for (int j = 0; j < clazzes.length; j++) {
169: if (!clazzes[j].jdk2() || isJDK2()) {
170: con = cycle(con, clazzes[j], run);
171: }
172: }
173: closeFile = true;
174: }
175: commitCounter++;
176: if (commitCounter > COMMIT_AFTER) {
177: con.commit();
178: commitCounter = 0;
179: }
180: }
181:
182: if (closeFile()) {
183: close(con);
184: con = open();
185: }
186:
187: // check for no duplicates
188: StoredClass[] intClasses = con.ext().storedClasses();
189: String[] noDuplicates = new String[intClasses.length];
190: for (int i = 0; i < intClasses.length; i++) {
191: noDuplicates[i] = intClasses[i].getName();
192: }
193: for (int i = 0; i < noDuplicates.length; i++) {
194: for (int j = i + 1; j < noDuplicates.length; j++) {
195: if (noDuplicates[i].equals(noDuplicates[j])) {
196: addError("Duplicate class definition: "
197: + noDuplicates[i]);
198: }
199: }
200: }
201: closeAllButMemoryFile(con);
202: }
203:
204: ObjectContainer cycle(ObjectContainer con, RTestable clazz,
205: int a_run) {
206: if (LOG_CLASS_NAMES) {
207: System.out.println("Testing class: "
208: + clazz.getClass().getName());
209: }
210: if (clazz.jdk2() && (!isJDK2())) {
211: return con;
212: }
213: Object obj = clazz.newInstance();
214: con = reOpen(con);
215:
216: // remove all
217: Object get = clazz.newInstance();
218: con.deactivate(get, Integer.MAX_VALUE);
219: ObjectSet set = con.get(get);
220: while (set.hasNext()) {
221: con.delete(set.next());
222: }
223:
224: // STEP1 add one object
225: clazz.set(obj, 1);
226: con.set(obj);
227: specificTest(clazz, con, ONE);
228: con = reOpen(con);
229:
230: // The check here has proved invaluable multiple times.
231: // Don't delete the uncommented code.
232:
233: // set = con.get(null);
234: // System.out.println(set.size());
235: // while(set.hasNext()){
236: // Logger.log(con, set.next());
237: // }
238:
239: // check 1, retrieving no members set
240: compare(con, get, clazz, 1, 1);
241:
242: // update 1, retrieving all members set
243: clazz.set(get, 1);
244: compare(con, get, clazz, 1, 1);
245: con = reOpen(con);
246:
247: // add 4
248: for (int i = 0; i < 4; i++) {
249: obj = clazz.newInstance();
250: clazz.set(obj, 1);
251: con.set(obj);
252: }
253: con = reOpen(con);
254:
255: // check 5
256: compare(con, get, clazz, 1, 5);
257: specificTest(clazz, con, FIVE);
258: con = reOpen(con);
259:
260: // delete 1
261: set = con.get(get);
262: obj = set.next();
263: con.delete(obj);
264: con = reOpen(con);
265:
266: // check 4
267: compare(con, get, clazz, 1, 4);
268: specificTest(clazz, con, DELETED);
269: con = reOpen(con);
270:
271: // update 1
272: set = con.get(get);
273: obj = set.next();
274: clazz.set(obj, 2);
275: con.set(obj);
276: con = reOpen(con);
277:
278: // Defragment test
279: //
280: // if(closeFile()){
281: // con.close();
282: // new Defragment().run(FILE, true);
283: // configure();
284: // con = open();
285: // }
286:
287: // check 3
288: compare(con, get, clazz, 1, 3);
289: specificTest(clazz, con, SAME);
290: con = reOpen(con);
291:
292: // check 1
293: clazz.set(get, 2);
294: compare(con, get, clazz, 2, 1);
295: specificTest(clazz, con, UPDATED);
296: con = reOpen(con);
297:
298: if (clazz.ver3()) {
299:
300: // update another 1 with ver3
301: set = con.get(get);
302: obj = set.next();
303: clazz.set(obj, 3);
304: con.set(obj);
305: con = reOpen(con);
306:
307: // check 2
308: clazz.set(get, 1);
309: compare(con, get, clazz, 1, 3);
310: specificTest(clazz, con, SAME);
311: con = reOpen(con);
312:
313: // check 1
314: clazz.set(get, 3);
315: compare(con, get, clazz, 3, 1);
316: specificTest(clazz, con, UPDATED);
317: con = reOpen(con);
318: }
319:
320: return con;
321: }
322:
323: public void completed() {
324: // virtual
325: }
326:
327: public void compare(ObjectContainer con, Object get,
328: RTestable clazz, int ver, int count) {
329: ObjectSet set = con.get(get);
330: if (!PROFILE_ONLY) {
331: set.reset();
332: if (set.size() == count) {
333: while (set.hasNext()) {
334: Object res = set.next();
335: clazz.compare(con, res, ver);
336: if (DEACTIVATE) {
337: con.deactivate(res, 1);
338: con.activate(res, Integer.MAX_VALUE);
339: clazz.compare(con, res, ver);
340: }
341: }
342: } else {
343: Regression.addError(clazz.getClass().getName()
344: + ":offcount:expected" + count + ":actual:"
345: + set.size());
346: }
347: }
348: }
349:
350: void specificTest(Object clazz, ObjectContainer con, int step) {
351: String methodName = "specific";
352: Class[] parameterClasses = { ObjectContainer.class,
353: Integer.TYPE };
354: try {
355: Method method = clazz.getClass().getMethod(methodName,
356: parameterClasses);
357: if (method != null) {
358: method.invoke(clazz, new Object[] { con,
359: new Integer(step) });
360: }
361: } catch (Exception e) {
362: }
363: }
364:
365: public ObjectContainer open() {
366: return openContainer();
367: }
368:
369: public static void configure() {
370: Configuration config = Db4o.configure();
371: // Set ActivationDepth deep enough for Recursive classes.
372: config.activationDepth(12);
373: ObjectClass oc = config.objectClass("com.db4o.test.DeepUpdate");
374: oc.updateDepth(2);
375: oc = config.objectClass("com.db4o.test.CustomConstructor");
376: oc.translate(new TCustomConstructor());
377: oc = config.objectClass("com.db4o.test.Debug");
378: oc.updateDepth(5);
379: }
380:
381: public ObjectContainer openContainer() {
382: if (openDelegate != null) {
383: return openDelegate.openContainer();
384: }
385: configure();
386: return Db4o.openFile(FILE);
387: }
388:
389: public void close(ObjectContainer con) {
390: if (openDelegate != null) {
391: openDelegate.close(con);
392: }
393: if (closeFile()) {
394: con.close();
395: }
396: }
397:
398: protected int runs() {
399: return RUNS;
400: }
401:
402: protected void closeAllButMemoryFile(ObjectContainer con) {
403: if (openDelegate != null) {
404: openDelegate.closeAllButMemoryFile(con);
405: } else {
406: con.close();
407: }
408: }
409:
410: protected boolean closeFile() {
411: return closeFile;
412: }
413:
414: public ObjectContainer reOpen(ObjectContainer con) {
415: if (closeFile()) {
416: close(con);
417: return open();
418: }
419: return con;
420: }
421:
422: Object newInstance(Class a_class) {
423: try {
424: return a_class.newInstance();
425: } catch (Throwable t) {
426: try {
427: Constructor[] constructors = a_class
428: .getDeclaredConstructors();
429: for (int i = 0; i < constructors.length; i++) {
430: try {
431: if (Platform4.canSetAccessible()) {
432: Platform4.setAccessible(constructors[i]);
433: }
434:
435: Class[] pTypes = constructors[i]
436: .getParameterTypes();
437: Object[] parms = new Object[constructors[i]
438: .getParameterTypes().length];
439: for (int j = 0; j < parms.length; j++) {
440: for (int k = 0; k < simpleNullWrappers.length; k++) {
441: if (pTypes[j] == simpleClasses[k]) {
442: parms[j] = simpleNullWrappers[k];
443: break;
444: }
445: }
446: }
447: Object res = constructors[i].newInstance(parms);
448: if (res != null) {
449: return res;
450: }
451: } catch (Exception exc) {
452: System.out.println(exc.getClass().getName());
453: System.out.println(exc.getMessage());
454: }
455: }
456: } catch (Exception ex) {
457: }
458: System.out.println("NewInstance failed:"
459: + a_class.getName());
460: return null;
461: }
462: }
463:
464: boolean isJDK2() {
465: return Platform4.jdk().ver() >= 2;
466: }
467:
468: // The following errors are expected.
469: // They occur due to the fact that:
470: // - Byte Objects will be instantiated even if the stored Byte object was null
471: // - the "Empty" objects does not change on update
472: // - the RecursiveTyped objects create more instances of themselves than would be expected
473: static String[] expectedErrors = {
474: "1e3==null:com.db4o.test.types.ArrayTypedPrivate:oByte:",
475: "1e0==null:com.db4o.test.types.ArrayTypedPrivate:nByte:",
476: "1e3==null:com.db4o.test.types.ArrayTypedPublic:oByte:",
477: "1e0==null:com.db4o.test.types.ArrayTypedPublic:nByte:",
478: "com.db4o.test.types.Empty:offcount:expected3:actual:4",
479: "com.db4o.test.types.Empty:offcount:expected1:actual:4",
480: "f1==null:com.db4o.test.types.MasterMonster:ooo:nByte:",
481: "1e3==null:com.db4o.test.types.MasterMonster:ooo:oByte:",
482: "1e0==null:com.db4o.test.types.MasterMonster:ooo:nByte:",
483: "com.db4o.test.types.RecursiveTypedPrivate:offcount:expected1:actual:11",
484: "com.db4o.test.types.RecursiveUnTypedPrivate:offcount:expected1:actual:11",
485: "com.db4o.test.types.RecursiveTypedPublic:offcount:expected1:actual:11",
486: "com.db4o.test.types.RecursiveUnTypedPublic:offcount:expected1:actual:11",
487: "f1==null:com.db4o.test.types.TypedPrivate:nByte:",
488: "f1==null:com.db4o.test.types.TypedPublic:nByte:" };
489:
490: static Object[] simpleNullWrappers = { new Integer(0), new Long(0),
491: new Character((char) 0), new Double(0), new Float(0),
492: new Boolean(false), new Short((short) 0),
493: new Byte((byte) 0) };
494:
495: static Class[] simpleClasses = { Integer.TYPE, Long.TYPE,
496: Character.TYPE, Double.TYPE, Float.TYPE, Boolean.TYPE,
497: Short.TYPE, Byte.TYPE };
498:
499: public static final int ONE = 1;
500: public static final int FIVE = 5;
501: public static final int DELETED = 4;
502: public static final int SAME = 3;
503: public static final int UPDATED = 0;
504:
505: public synchronized static void addError(String err) {
506: for (int i = 0; i < expectedErrors.length; i++) {
507: if (err.equals(expectedErrors[i])) {
508: return;
509: }
510: }
511: errors = errors + err + System.getProperty("line.separator");
512: }
513:
514: public static final boolean DEACTIVATE = false;
515: public static String FILE = "regression.yap";
516: protected Regression openDelegate;
517: private static String errors = "";
518: private static int openedThreads = 0;
519: private static int returnedThreads = 0;
520: private static boolean threadsSharp = false;
521:
522: private boolean closeFile;
523:
524: public static RTestable[] allClasses() {
525: return new RTestable[] { new ArrayInObjectPrivate(),
526: new ArrayInObjectPublic(),
527: new ArrayMixedInObjectPrivate(),
528: new ArrayMixedInObjectPublic(),
529: new ArrayMixedTypedPrivate(),
530: new ArrayMixedTypedPublic(),
531: new ArrayNDimensionalPrivate(),
532: new ArrayNDimensionalPublic(), new ArrayTypedPrivate(),
533: new ArrayTypedPublic(), new ArrayUntypedPrivate(),
534: new ArrayUntypedPublic(), new BiParentTypedPrivate(),
535: new BiParentTypedPublic(),
536: new BiParentUnTypedPrivate(),
537: new BiParentUnTypedPublic(), new DeepUpdate(),
538: new Empty(), new InterfacePrivate(),
539: new InterfacePublic(), new ObjectSimplePrivate(),
540: new ObjectSimplePublic(), new ParameterConstructor(0),
541: PrivateConstructor.construct(),
542: new RecursiveTypedPrivate(),
543: new RecursiveTypedPublic(),
544: new RecursiveUnTypedPrivate(),
545: new RecursiveUnTypedPublic(), new RHashtable(),
546: new RProperties(), new RStack(), new RVector(),
547: new SelfReference(), new TypedPrivate(),
548: new TypedPublic(), new UntypedPrivate(),
549: new UntypedPublic()
550: // new MasterMonster()
551: };
552: }
553:
554: public RTestable[] testClasses() {
555: if (!DEBUG) {
556: return allClasses();
557: }
558: return new RTestable[] { new UntypedDebug()
559: // new RStack(),
560: // new RVector(),
561: // new SelfReference(),
562: };
563: }
564:
565: }
|