KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > util > TestUtils


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: TestUtils.java,v 1.75 2006/10/30 21:14:54 bostic Exp $
7  */

8
9 package com.sleepycat.je.util;
10
11 import java.io.File JavaDoc;
12 import java.io.FileInputStream JavaDoc;
13 import java.io.FileOutputStream JavaDoc;
14 import java.io.FilenameFilter JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.io.OutputStream JavaDoc;
18 import java.text.NumberFormat JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Random JavaDoc;
21
22 import junit.framework.TestCase;
23
24 import com.sleepycat.je.Cursor;
25 import com.sleepycat.je.Database;
26 import com.sleepycat.je.DatabaseException;
27 import com.sleepycat.je.DbInternal;
28 import com.sleepycat.je.DbTestProxy;
29 import com.sleepycat.je.Environment;
30 import com.sleepycat.je.EnvironmentConfig;
31 import com.sleepycat.je.StatsConfig;
32 import com.sleepycat.je.dbi.CursorImpl;
33 import com.sleepycat.je.dbi.EnvironmentImpl;
34 import com.sleepycat.je.dbi.INList;
35 import com.sleepycat.je.latch.LatchSupport;
36 import com.sleepycat.je.log.FileManager;
37 import com.sleepycat.je.tree.BIN;
38 import com.sleepycat.je.tree.ChildReference;
39 import com.sleepycat.je.tree.IN;
40 import com.sleepycat.je.tree.SearchResult;
41 import com.sleepycat.je.tree.Tree;
42 import com.sleepycat.je.tree.WithRootLatched;
43
44 public class TestUtils {
45     public static String JavaDoc DEST_DIR = "testdestdir";
46     public static String JavaDoc NO_SYNC = "txnnosync";
47     public static String JavaDoc LONG_TEST = "longtest";
48
49     public static final String JavaDoc LOG_FILE_NAME = "00000000.jdb";
50
51     public static final StatsConfig FAST_STATS;
52
53     static {
54         FAST_STATS = new StatsConfig();
55         FAST_STATS.setFast(true);
56     }
57     
58     private static final boolean DEBUG = true;
59     private static Random JavaDoc rnd = new Random JavaDoc();
60
61     public void debugMsg(String JavaDoc message) {
62
63         if (DEBUG) {
64             System.out.println
65         (Thread.currentThread().toString() + " " + message);
66         }
67     }
68
69     static public void setRandomSeed(int seed) {
70
71         rnd = new Random JavaDoc(seed);
72     }
73
74     static public void generateRandomAlphaBytes(byte[] bytes) {
75
76         byte[] aAndZ = "AZ".getBytes();
77         int range = aAndZ[1] - aAndZ[0] + 1;
78
79         for (int i = 0; i < bytes.length; i++) {
80             bytes[i] = (byte) (rnd.nextInt(range) + aAndZ[0]);
81         }
82     }
83
84     static public void checkLatchCount() {
85         TestCase.assertTrue(LatchSupport.countLatchesHeld() == 0);
86     }
87
88     static public void printLatchCount(String JavaDoc msg) {
89         System.out.println(msg + " : " + LatchSupport.countLatchesHeld());
90     }
91
92     static public void printLatches(String JavaDoc msg) {
93         System.out.println(msg + " : ");
94         LatchSupport.dumpLatchesHeld();
95     }
96
97     /**
98      * Generate a synthetic base 26 four byte alpha key from an int.
99      * The bytes of the key are between 'A' and 'Z', inclusive. 0 maps
100      * to 'AAAA', 1 to 'AAAB', etc.
101      */

102     static public int alphaKey(int i) {
103
104         int ret = 0;
105         for (int j = 0; j < 4; j++) {
106             byte b = (byte) (i % 26);
107             ret <<= 8;
108             ret |= (b + 65);
109             i /= 26;
110         }
111
112         return ret;
113     }
114
115     /**
116      * Marshall an unsigned int (long) into a four byte buffer.
117      */

118     static public void putUnsignedInt(byte[] buf, long value) {
119
120         int i = 0;
121         buf[i++] = (byte) (value >>> 0);
122         buf[i++] = (byte) (value >>> 8);
123         buf[i++] = (byte) (value >>> 16);
124         buf[i] = (byte) (value >>> 24);
125     }
126
127     /**
128      * All flavors of removeLogFiles should check if the remove has been
129      * disabled. (Used for debugging, so that the tester can dump the
130      * log file.
131      */

132     private static boolean removeDisabled() {
133
134         String JavaDoc doRemove = System.getProperty("removeLogFiles");
135         return ((doRemove != null) && doRemove.equalsIgnoreCase("false"));
136     }
137
138     /**
139      * Remove je log files from the home directory. Will be disabled
140      * if the unit test is run with -DremoveLogFiles=false
141      * @param msg prefix to append to error messages
142      * @param envFile environment directory
143      */

144     public static void removeLogFiles(String JavaDoc msg,
145                                       File JavaDoc envFile,
146                                       boolean checkRemove)
147         throws IOException JavaDoc {
148
149         removeFiles(msg, envFile, FileManager.JE_SUFFIX, checkRemove);
150     }
151
152     /**
153      * Remove files with this suffix from the je home directory
154      * @param msg prefix to append to error messages
155      * @param envFile environment directory
156      * @param suffix files with this suffix will be removed
157      */

158     public static void removeFiles(String JavaDoc msg,
159                    File JavaDoc envFile,
160                    String JavaDoc suffix)
161         throws IOException JavaDoc {
162
163         removeFiles(msg, envFile, suffix, false);
164     }
165
166     /**
167      * Remove files with this suffix from the je home directory
168      * @param msg prefix to append to error messages
169      * @param envFile environment directory
170      * @param suffix files with this suffix will be removed
171      * @param checkRemove if true, check the -DremoveLogFiles system
172      * property before removing.
173      */

174     public static void removeFiles(String JavaDoc msg,
175                                    File JavaDoc envFile,
176                                    String JavaDoc suffix,
177                                    boolean checkRemove)
178         throws IOException JavaDoc {
179
180         if (checkRemove && removeDisabled()) {
181             return;
182         }
183
184     String JavaDoc[] suffixes = new String JavaDoc[] { suffix };
185         String JavaDoc[] names = FileManager.listFiles(envFile, suffixes);
186
187         /* Clean up any target files in this directory. */
188         for (int i = 0; i < names.length; i++) {
189             File JavaDoc oldFile = new File JavaDoc(envFile, names[i]);
190             boolean done = oldFile.delete();
191             assert done :
192                 msg + " couldn't delete " + names[i] + " out of " +
193                 names[names.length - 1];
194             oldFile = null;
195         }
196     }
197
198     /**
199      * Remove files with the pattern indicated by the filename filter from the
200      * environment home directory.
201      * Note that BadFileFilter looks for this pattern: NNNNNNNN.bad.#
202      * InfoFileFilter looks for this pattern: je.info.#
203      * @param envFile environment directory
204      */

205     public static void removeFiles(File JavaDoc envFile, FilenameFilter JavaDoc filter)
206         throws IOException JavaDoc {
207
208         if (removeDisabled()) {
209             return;
210         }
211
212         File JavaDoc[] targetFiles = envFile.listFiles(filter);
213
214         // Clean up any target files in this directory
215
for (int i = 0; i < targetFiles.length; i++) {
216             boolean done = targetFiles[i].delete();
217             if (!done) {
218                 System.out.println
219             ("Warning, couldn't delete "
220              + targetFiles[i]
221              + " out of "
222              + targetFiles[targetFiles.length - 1]);
223             }
224         }
225     }
226
227     /**
228      * Copies all files in fromDir to toDir. Does not copy subdirectories.
229      */

230     public static void copyFiles(File JavaDoc fromDir, File JavaDoc toDir)
231         throws IOException JavaDoc {
232
233         String JavaDoc[] names = fromDir.list();
234         if (names != null) {
235             for (int i = 0; i < names.length; i += 1) {
236                 File JavaDoc fromFile = new File JavaDoc(fromDir, names[i]);
237                 if (fromFile.isDirectory()) {
238                     continue;
239                 }
240                 File JavaDoc toFile = new File JavaDoc(toDir, names[i]);
241                 int len = (int) fromFile.length();
242                 byte[] data = new byte[len];
243                 FileInputStream JavaDoc fis = null;
244                 FileOutputStream JavaDoc fos = null;
245                 try {
246                     fis = new FileInputStream JavaDoc(fromFile);
247                     fos = new FileOutputStream JavaDoc(toFile);
248                     fis.read(data);
249                     fos.write(data);
250                 } finally {
251                     if (fis != null) {
252                         fis.close();
253                     }
254                     if (fos != null) {
255                         fos.close();
256                     }
257                 }
258             }
259         }
260     }
261
262     /**
263      * Useful utility for generating byte arrays with a known order.
264      * Vary the length just to introduce more variability.
265      * @return a byte array of length val % 100 with the value of "val"
266      */

267     public static byte[] getTestArray(int val) {
268
269         int length = val % 10;
270         length = length < 4 ? 4 : length;
271         byte[] test = new byte[length];
272         test[3] = (byte) ((val >>> 0) & 0xff);
273         test[2] = (byte) ((val >>> 8) & 0xff);
274         test[1] = (byte) ((val >>> 16) & 0xff);
275         test[0] = (byte) ((val >>> 24) & 0xff);
276         return test;
277     }
278
279     /**
280      * Return the value of a test data array generated with getTestArray
281      * as an int
282      */

283     public static int getTestVal(byte[] testArray) {
284
285         int val = 0;
286         val |= (testArray[3] & 0xff);
287         val |= ((testArray[2] & 0xff) << 8);
288         val |= ((testArray[1] & 0xff) << 16);
289         val |= ((testArray[0] & 0xff) << 24);
290         return val;
291     }
292
293     /**
294      * @return length and data of a byte array, printed as decimal numbers
295      */

296     public static String JavaDoc dumpByteArray(byte[] b) {
297
298         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
299         sb.append("<byteArray len = ");
300         sb.append(b.length);
301         sb.append(" data = \"");
302         for (int i = 0; i < b.length; i++) {
303             sb.append(b[i]).append(",");
304         }
305         sb.append("\"/>");
306         return sb.toString();
307     }
308
309     /**
310      * @return a copy of the passed in byte array
311      */

312     public static byte[] byteArrayCopy(byte[] ba) {
313
314         int len = ba.length;
315         byte[] ret = new byte[len];
316         System.arraycopy(ba, 0, ret, 0, len);
317         return ret;
318     }
319
320     /*
321      * Check that the stored memory count for all INs on the inlist
322      * matches their computed count. The environment mem usage check
323      * may be run with assertions or not.
324      *
325      * In a multithreaded environment (or one with daemons running),
326      * you can't be sure that the cached size will equal the calculated size.
327      *
328      * Nodes, txns, and locks are all counted within the memory budget.
329      */

330     public static long validateNodeMemUsage(EnvironmentImpl envImpl,
331                                             boolean assertOnError)
332         throws DatabaseException {
333
334         long total = tallyNodeMemUsage(envImpl);
335         long nodeCacheUsage = envImpl.getMemoryBudget().getTreeMemoryUsage();
336         NumberFormat JavaDoc formatter = NumberFormat.getNumberInstance();
337         if (assertOnError) {
338             assert (total==nodeCacheUsage) :
339                   "calculatedTotal=" + formatter.format(total) +
340                   " envCacheUsage=" + formatter.format(nodeCacheUsage);
341         } else {
342             if (DEBUG) {
343                 if (nodeCacheUsage != total) {
344                     long diff = Math.abs(nodeCacheUsage - total);
345                     if ((diff / nodeCacheUsage) > .05) {
346                         System.out.println("calculatedTotal=" +
347                                            formatter.format(total) +
348                                            " envCacheUsage=" +
349                                            formatter.format(nodeCacheUsage));
350                     }
351                 }
352             }
353         }
354
355         return nodeCacheUsage;
356     }
357
358     public static long tallyNodeMemUsage(EnvironmentImpl envImpl)
359         throws DatabaseException {
360
361         INList inList = envImpl.getInMemoryINs();
362         inList.latchMajor();
363         long total = 0;
364         try {
365             Iterator JavaDoc iter = inList.iterator();
366             while (iter.hasNext()) {
367                 IN in = (IN) iter.next();
368                 in.latch();
369                 try {
370                     assert in.verifyMemorySize():
371                         "in nodeId=" + in.getNodeId() +
372                         ' ' + in.getClass().getName();
373                     total += in.getInMemorySize();
374                 } finally {
375                     in.releaseLatch();
376                 }
377             }
378         } finally {
379             inList.releaseMajorLatch();
380         }
381         return total;
382     }
383
384     /**
385      * Called by each unit test to enforce isolation level settings specified
386      * in the isolationLevel system property. Other system properties or
387      * default settings may be applied in the future.
388      */

389     public static EnvironmentConfig initEnvConfig() {
390
391         EnvironmentConfig config = new EnvironmentConfig();
392         String JavaDoc val = System.getProperty("isolationLevel");
393         if (val != null && val.length() > 0) {
394             if ("serializable".equals(val)) {
395                 config.setTxnSerializableIsolation(true);
396             } else if ("readCommitted".equals(val)) {
397                 DbInternal.setTxnReadCommitted(config, true);
398             } else {
399                 throw new IllegalArgumentException JavaDoc
400                     ("Unknown isolationLevel system property value: " + val);
401             }
402         }
403         return config;
404     }
405     
406     /**
407      * If a unit test needs to override the isolation level, it should call
408      * this method after calling initEnvConfig.
409      */

410     public static void clearIsolationLevel(EnvironmentConfig config) {
411         DbInternal.setTxnReadCommitted(config, false);
412         config.setTxnSerializableIsolation(false);
413     }
414
415     /**
416      * Loads the given resource relative to the given class, and copies it to
417      * log file zero in the given directory.
418      */

419     public static void loadLog(Class JavaDoc cls, String JavaDoc resourceName, File JavaDoc envHome)
420         throws IOException JavaDoc {
421
422         File JavaDoc logFile = new File JavaDoc(envHome, LOG_FILE_NAME);
423         InputStream JavaDoc is = cls.getResourceAsStream(resourceName);
424         OutputStream JavaDoc os = new FileOutputStream JavaDoc(logFile);
425         byte[] buf = new byte[is.available()];
426         int len = is.read(buf);
427         if (buf.length != len) {
428             throw new IllegalStateException JavaDoc();
429         }
430         os.write(buf, 0, len);
431         is.close();
432         os.close();
433     }
434
435     /**
436      * Logs the BIN at the cursor provisionally and the parent IN
437      * non-provisionally. Used to simulate a partial checkpoint or eviction.
438      */

439     public static void logBINAndIN(Environment env, Cursor cursor)
440         throws DatabaseException {
441
442         BIN bin = getBIN(cursor);
443         Tree tree = bin.getDatabase().getTree();
444
445
446         /* Log the BIN and update its parent entry. */
447         bin.latch();
448         SearchResult result = tree.getParentINForChildIN(bin, true, true);
449         assert result.parent != null;
450         assert result.exactParentFound;
451         IN binParent = result.parent;
452         long binLsn = logIN(env, bin, true, binParent);
453         binParent.updateEntry(result.index, bin, binLsn);
454         result.parent.releaseLatch();
455
456         /* Log the BIN parent and update its parent entry. */
457         binParent.latch();
458         result = tree.getParentINForChildIN(binParent, true, true);
459         IN inParent = null;
460         if (result.parent != null) {
461             result.parent.releaseLatch();
462             assert result.exactParentFound;
463             inParent = result.parent;
464         inParent.latch();
465         }
466         final long inLsn = logIN(env, binParent, false, null);
467         if (inParent != null) {
468             inParent.updateEntry(result.index, binParent, inLsn);
469         inParent.releaseLatch();
470         } else {
471             tree.withRootLatchedExclusive(new WithRootLatched() {
472                 public IN doWork(ChildReference root)
473                     throws DatabaseException {
474                     root.setLsn(inLsn);
475                     return null;
476                 }
477             });
478         }
479     }
480
481     /**
482      * Logs the given IN.
483      */

484     public static long logIN(Environment env,
485                              IN in,
486                              boolean provisional,
487                              IN parent)
488         throws DatabaseException {
489
490         EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
491         in.latch();
492         long lsn;
493         if (provisional) {
494             lsn = in.log(envImpl.getLogManager(),
495                      false, // allowDeltas
496
true, // isProvisional
497
false, // proactiveMigration
498
false, // backgroundIO
499
parent);// provisional parent
500
} else {
501             lsn = in.log(envImpl.getLogManager());
502         }
503         in.releaseLatch();
504         return lsn;
505     }
506
507     /**
508      * Returns the parent IN of the given BIN.
509      */

510     public static IN getIN(BIN bin)
511         throws DatabaseException {
512
513         Tree tree = bin.getDatabase().getTree();
514         bin.latch();
515         SearchResult result = tree.getParentINForChildIN(bin, true, true);
516         assert result.parent != null;
517         result.parent.releaseLatch();
518         assert result.exactParentFound;
519         return result.parent;
520     }
521
522     /**
523      * Returns the target BIN for the given cursor.
524      */

525     public static BIN getBIN(Cursor cursor)
526         throws DatabaseException {
527
528         CursorImpl impl = DbTestProxy.dbcGetCursorImpl(cursor);
529         BIN bin = impl.getDupBIN();
530         if (bin == null) {
531             bin = impl.getBIN();
532             assert bin != null;
533         }
534         return bin;
535     }
536
537     /**
538      * Assert if the tree is not this deep. Use to ensure that data setups
539      * are as expected.
540      */

541     public static boolean checkTreeDepth(Database db, int desiredDepth)
542         throws DatabaseException {
543
544         Tree tree = DbInternal.dbGetDatabaseImpl(db).getTree();
545         IN rootIN = tree.getRootIN(false /* update generation */);
546         int level = 0;
547         if (rootIN != null) {
548             level = rootIN.getLevel() & IN.LEVEL_MASK;
549             rootIN.releaseLatch();
550         }
551
552         return (desiredDepth == level);
553     }
554
555     /**
556      * @return true if long running tests are enabled.
557      */

558     static public boolean runLongTests() {
559         String JavaDoc longTestProp = System.getProperty(TestUtils.LONG_TEST);
560         if ((longTestProp != null) &&
561             longTestProp.equalsIgnoreCase("true")) {
562             return true;
563         } else {
564             return false;
565         }
566     }
567
568     /**
569      * Skip over the JE version number at the start of the exception
570      * message for tests which are looking for a specific message.
571      */

572     public static String JavaDoc skipVersion(Exception JavaDoc e) {
573         int versionHeaderLen = DatabaseException.getVersionHeader().length();
574         return (e.getMessage().substring(versionHeaderLen));
575     }
576 }
577
Popular Tags