001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * If you wish your version of this file to be governed by only the CDDL
025: * or only the GPL Version 2, indicate your decision by adding
026: * "[Contributor] elects to include this software in this distribution
027: * under the [CDDL or GPL Version 2] license." If you do not indicate a
028: * single choice of license, a recipient has the option to distribute
029: * your version of this file under either the CDDL, the GPL Version 2 or
030: * to extend the choice of license to its licensees as provided above.
031: * However, if you add GPL Version 2 code and therefore, elected the GPL
032: * Version 2 license, then the option applies only if the new code is
033: * made subject to such option by the copyright holder.
034: *
035: * Contributor(s):
036: *
037: * Portions Copyrighted 2008 Sun Microsystems, Inc.
038: */
039:
040: package org.netbeans;
041:
042: import java.io.DataOutputStream;
043: import java.io.File;
044: import java.io.IOException;
045: import java.io.InputStream;
046: import java.nio.ByteBuffer;
047: import java.nio.MappedByteBuffer;
048: import java.util.LinkedList;
049: import java.util.concurrent.Semaphore;
050: import java.util.logging.Level;
051: import java.util.logging.Logger;
052: import junit.framework.Test;
053: import org.netbeans.junit.Log;
054: import org.netbeans.junit.NbTestCase;
055: import org.netbeans.junit.NbTestSuite;
056:
057: /**
058: *
059: * @author Jaroslav Tulach <jaroslav.tulach@netbeans.org>
060: */
061: public class StampsTest extends NbTestCase {
062: private File userdir;
063: private File ide;
064: private File platform;
065: private File install;
066:
067: public static Test suite() {
068: // return new StampsTest("testFastWhenShutdown");
069: return new NbTestSuite(StampsTest.class);
070: }
071:
072: public StampsTest(String testName) {
073: super (testName);
074: }
075:
076: @Override
077: protected void setUp() throws Exception {
078: clearWorkDir();
079:
080: install = new File(getWorkDir(), "install");
081: platform = new File(install, "platform7");
082: ide = new File(install, "ide8");
083: userdir = new File(getWorkDir(), "tmp");
084:
085: System.setProperty("netbeans.home", platform.getPath());
086: System.setProperty("netbeans.dirs", ide.getPath());
087: System.setProperty("netbeans.user", userdir.getPath());
088:
089: createModule("org.openide.awt", platform, 50000L);
090: createModule("org.openide.nodes", platform, 60000L);
091: createModule("org.netbeans.api.languages", ide, 90000L);
092: createModule("org.netbeans.modules.logmanagement", userdir,
093: 10000L);
094:
095: Stamps.main("reset");
096:
097: Thread.sleep(100);
098:
099: Logger l = Logger.getLogger("org");
100: l.setLevel(Level.OFF);
101: l.setUseParentHandlers(false);
102: }
103:
104: @Override
105: protected void tearDown() throws Exception {
106: super .tearDown();
107: }
108:
109: public void testEmpty() {
110: Stamps.getModulesJARs().waitFor(false);
111: }
112:
113: public void testGenerateTimeStamps() {
114: long stamp = Stamps.moduleJARs();
115: assertEquals("Timestamp is taken from api.languages module",
116: 90000L, stamp);
117:
118: assertStamp(60000L, platform, false, true);
119: assertStamp(90000L, ide, false, true);
120: assertStamp(-1L, userdir, false, false);
121:
122: Stamps.main("reset");
123:
124: CountingSecurityManager.initialize(install.getPath());
125:
126: long newStamp = Stamps.moduleJARs();
127:
128: CountingSecurityManager.assertCounts(
129: "Just two accesses installation", 2);
130: assertEquals("Stamps are the same", stamp, newStamp);
131:
132: assertStamp(60000L, platform, false, true);
133: assertStamp(90000L, ide, false, true);
134: assertStamp(-1L, userdir, false, false);
135:
136: Stamps.main("reset");
137: CountingSecurityManager.initialize(new File(userdir, "var")
138: .getPath());
139: long newStamp2 = Stamps.moduleJARs();
140:
141: CountingSecurityManager.assertCounts(
142: "Just two accesses to cache", 2);
143: assertEquals("Stamps are the same", stamp, newStamp2);
144: }
145:
146: public void testWriteToCache() throws Exception {
147: final Stamps s = Stamps.getModulesJARs();
148:
149: assertNull(s.asByteBuffer("mycache.dat"));
150: assertNull(s.asStream("mycache.dat"));
151:
152: class Up implements Stamps.Updater {
153:
154: public void flushCaches(DataOutputStream os)
155: throws IOException {
156: os.writeInt(1);
157: os.writeInt(2);
158: os.writeShort(2);
159: }
160:
161: public void cacheReady() {
162: assertNotNull("stream can be obtained", s
163: .asStream("mycache.dat"));
164: }
165:
166: }
167: Up updater = new Up();
168:
169: s.scheduleSave(updater, "mycache.dat", false);
170:
171: assertNull(s.asByteBuffer("mycache.dat"));
172: assertNull(s.asStream("mycache.dat"));
173:
174: s.waitFor(false);
175:
176: ByteBuffer bb;
177: InputStream is;
178: assertNotNull(bb = s.asByteBuffer("mycache.dat"));
179: assertNotNull(is = s.asStream("mycache.dat"));
180:
181: assertEquals("10 bytes", 10, bb.remaining());
182: assertEquals("10 bytes stream", 10, is.available());
183: is.close();
184: bb.clear();
185:
186: s.discardCaches();
187:
188: assertNull(s.asByteBuffer("mycache.dat"));
189: assertNull(s.asStream("mycache.dat"));
190: }
191:
192: public void testAppendToCache() throws Exception {
193: final Stamps s = Stamps.getModulesJARs();
194:
195: assertNull(s.asByteBuffer("mycache.dat"));
196: assertNull(s.asStream("mycache.dat"));
197:
198: class Up implements Stamps.Updater {
199:
200: public void flushCaches(DataOutputStream os)
201: throws IOException {
202: os.writeInt(1);
203: os.writeInt(2);
204: os.writeShort(2);
205: }
206:
207: public void cacheReady() {
208: assertNotNull("stream can be obtained", s
209: .asStream("mycache.dat"));
210: }
211:
212: }
213: Up updater = new Up();
214:
215: s.scheduleSave(updater, "mycache.dat", true);
216:
217: assertNull(s.asByteBuffer("mycache.dat"));
218: assertNull(s.asStream("mycache.dat"));
219:
220: s.waitFor(false);
221:
222: {
223: ByteBuffer bb;
224: InputStream is;
225: assertNotNull(bb = s.asByteBuffer("mycache.dat"));
226: assertNotNull(is = s.asStream("mycache.dat"));
227:
228: assertEquals("10 bytes", 10, bb.remaining());
229: assertEquals("10 bytes stream", 10, is.available());
230:
231: is.close();
232: bb.clear();
233: }
234:
235: s.scheduleSave(updater, "mycache.dat", true);
236:
237: s.waitFor(false);
238:
239: {
240: ByteBuffer bb;
241: assertNotNull(bb = s.asByteBuffer("mycache.dat"));
242:
243: assertEquals("appened bytes", 20, bb.remaining());
244:
245: bb.clear();
246: }
247:
248: }
249:
250: public void testFastWhenShutdown() throws Exception {
251: Stamps s = Stamps.getModulesJARs();
252:
253: assertNull(s.asByteBuffer("mycache.dat"));
254: assertNull(s.asStream("mycache.dat"));
255:
256: class Up implements Stamps.Updater {
257: volatile boolean finished;
258:
259: public void flushCaches(DataOutputStream os)
260: throws IOException {
261: byte[] arr = new byte[4096];
262: for (int i = 0; i < 10000; i++) {
263: long previous = System.currentTimeMillis();
264: os.write(arr);
265: synchronized (this ) {
266: notifyAll();
267: }
268: }
269: finished = true;
270: }
271:
272: public void cacheReady() {
273: }
274:
275: }
276: Up updater = new Up();
277:
278: s.scheduleSave(updater, "mycache.dat", false);
279:
280: long now = System.currentTimeMillis();
281: s.flush(1000);
282: synchronized (updater) {
283: updater.wait();
284: }
285: long diff = System.currentTimeMillis() - now;
286: if (diff < 800) {
287: fail("Updating shall start after 1s, not sooner: " + diff);
288: }
289: s.waitFor(false);
290:
291: assertTrue("Save is done", updater.finished);
292: }
293:
294: public void testWriteToCacheWithError() {
295: Stamps s = Stamps.getModulesJARs();
296:
297: assertNull(s.asByteBuffer("mycache.dat"));
298: assertNull(s.asStream("mycache.dat"));
299:
300: class Up implements Stamps.Updater {
301: boolean called;
302:
303: public void flushCaches(DataOutputStream os)
304: throws IOException {
305: throw new IOException("Not supported yet.");
306: }
307:
308: public void cacheReady() {
309: called = true;
310: }
311:
312: }
313: Up updater = new Up();
314:
315: s.scheduleSave(updater, "mycache.dat", false);
316:
317: assertNull(s.asByteBuffer("mycache.dat"));
318: assertNull(s.asStream("mycache.dat"));
319:
320: CharSequence log = Log.enable("org.netbeans", Level.WARNING);
321: s.waitFor(false);
322:
323: assertNull(s.asByteBuffer("mycache.dat"));
324: assertNull(s.asStream("mycache.dat"));
325:
326: if (log.length() < 10) {
327: fail("There should be a warning written to log:\n" + log);
328: }
329:
330: assertFalse("cache ready not called", updater.called);
331: }
332:
333: public void testCanHaveSubdirs() {
334: final Stamps s = Stamps.getModulesJARs();
335:
336: assertNull(s.asByteBuffer("mydir/mycache.dat"));
337:
338: class Up implements Stamps.Updater {
339: boolean called;
340:
341: public void flushCaches(DataOutputStream os)
342: throws IOException {
343: os.write(1);
344: }
345:
346: public void cacheReady() {
347: assertTrue("Now the cache can be accessed", s
348: .exists("mydir/mycache.dat"));
349: called = true;
350: }
351:
352: }
353: Up updater = new Up();
354:
355: s.scheduleSave(updater, "mydir/mycache.dat", false);
356: s.waitFor(false);
357:
358: File userDir = new File(System.getProperty("netbeans.user"));
359: File my = new File(new File(new File(new File(userDir, "var"),
360: "cache"), "mydir"), "mycache.dat");
361:
362: assertTrue("file created", my.canRead());
363: assertEquals("size 1", 1, my.length());
364:
365: assertTrue("cache was ready", updater.called);
366: }
367:
368: public void testShutdownAndThenNoNotify() {
369: final Stamps s = Stamps.getModulesJARs();
370:
371: assertNull(s.asByteBuffer("mydir/mycache.dat"));
372:
373: class Up implements Stamps.Updater {
374: boolean called;
375:
376: public void flushCaches(DataOutputStream os)
377: throws IOException {
378: os.write(1);
379: }
380:
381: public void cacheReady() {
382: called = true;
383: }
384:
385: }
386: Up updater = new Up();
387:
388: s.scheduleSave(updater, "mydir/mycache.dat", false);
389: s.flush(10000);
390: s.shutdown();
391:
392: File userDir = new File(System.getProperty("netbeans.user"));
393: File my = new File(new File(new File(new File(userDir, "var"),
394: "cache"), "mydir"), "mycache.dat");
395:
396: assertTrue("file created", my.canRead());
397: assertEquals("size 1", 1, my.length());
398:
399: assertFalse("cache was not called, due to shutdown",
400: updater.called);
401: }
402:
403: public void testJustOnce() {
404: final Stamps s = Stamps.getModulesJARs();
405:
406: assertNull(s.asByteBuffer("mydir/mycache.dat"));
407:
408: class Up implements Stamps.Updater {
409: int cnt;
410:
411: public void flushCaches(DataOutputStream os)
412: throws IOException {
413:
414: assertNull("Now it is null", s
415: .asStream("mydir/mycache.dat"));
416:
417: os.write(1);
418: cnt++;
419: if (cnt == 2) {
420: fail("Can save just once");
421: }
422: }
423:
424: public void cacheReady() {
425: }
426:
427: }
428: Up updater = new Up();
429:
430: s.scheduleSave(updater, "mydir/mycache.dat", false);
431: s.scheduleSave(updater, "mydir/mycache.dat", false);
432:
433: s.waitFor(false);
434:
435: assertEquals("only once", 1, updater.cnt);
436:
437: s.scheduleSave(updater, "mydir/mycache.dat", false);
438: assertNull("Now it is null as well", s
439: .asStream("mydir/mycache.dat"));
440: updater.cnt = 0;
441: s.waitFor(false);
442:
443: assertNotNull("Returns value again", s
444: .asStream("mydir/mycache.dat"));
445: assertEquals("only once", 1, updater.cnt);
446:
447: }
448:
449: public void testParael() throws InterruptedException {
450: final Stamps s = Stamps.getModulesJARs();
451:
452: assertNull(s.asMappedByteBuffer("mydir/mycache.dat"));
453:
454: class Up implements Stamps.Updater, Runnable {
455: int ready;
456: int cnt;
457: Semaphore flushing = new Semaphore(0);
458: Semaphore scheduled = new Semaphore(0);
459:
460: public void flushCaches(DataOutputStream os)
461: throws IOException {
462: int what = cnt++;
463: if (what == 0) {
464: flushing.release();
465: scheduled.acquireUninterruptibly();
466: }
467: for (int i = 0; i < 1024 * 1024; i++) {
468: os.write(what);
469: }
470: }
471:
472: public void run() {
473: flushing.acquireUninterruptibly();
474: s.scheduleSave(this , "mydir/mycache.dat", false);
475: scheduled.release();
476: assertFalse(s.exists("mydir/mycache.dat"));
477: s.waitFor(false);
478: }
479:
480: public void cacheReady() {
481: ready++;
482: }
483: }
484: Up updater = new Up();
485:
486: s.scheduleSave(updater, "mydir/mycache.dat", false);
487:
488: Thread t = new Thread(updater, "fast flush");
489: t.start();
490: // slow flush
491: s.flush(50);
492: t.join();
493:
494: assertEquals("run twice", 2, updater.cnt);
495: assertEquals("but just once ready", 1, updater.ready);
496:
497: MappedByteBuffer mmap = s
498: .asMappedByteBuffer("mydir/mycache.dat");
499: {
500: assertEquals("1mb", 1024 * 1024, mmap.remaining());
501: int r = 0;
502: while (mmap.remaining() > 0) {
503: assertEquals("Value " + r + " OK: ", 1, mmap.get());
504: r++;
505: }
506: }
507:
508: s.scheduleSave(updater, "mydir/mycache.dat", false);
509: assertNull("Now it is null as well", s
510: .asStream("mydir/mycache.dat"));
511: s.waitFor(false);
512:
513: MappedByteBuffer mmap2 = s
514: .asMappedByteBuffer("mydir/mycache.dat");
515: assertNotNull(mmap2);
516:
517: {
518: assertEquals("1mb", 1024 * 1024, mmap2.remaining());
519: int r = 0;
520: while (mmap2.remaining() > 0) {
521: assertEquals("Value2 " + r + " OK: ", 2, mmap2.get());
522: r++;
523: }
524: }
525: }
526:
527: private static void assertStamp(long expectedValue, File cluster,
528: boolean global, boolean local) {
529: File globalStamp = new File(cluster, ".lastModified");
530:
531: File userDir = new File(System.getProperty("netbeans.user"));
532: File localStamp = new File(new File(new File(new File(userDir,
533: "var"), "cache"), "lastModified"), cluster.getName());
534:
535: if (global) {
536: assertTrue("File shall exist: " + globalStamp, globalStamp
537: .exists());
538: assertEquals("Modification time is good " + globalStamp,
539: expectedValue, globalStamp.lastModified());
540: } else {
541: assertFalse("File shall not exist: " + globalStamp,
542: globalStamp.exists());
543: }
544:
545: if (local) {
546: assertTrue("File shall exist: " + localStamp, localStamp
547: .exists());
548: assertEquals("Modification time is good " + localStamp,
549: expectedValue, localStamp.lastModified());
550: } else {
551: assertFalse("File shall not exist: " + localStamp,
552: localStamp.exists());
553: }
554:
555: }
556:
557: private void createModule(String cnb, File cluster, long accesTime)
558: throws IOException {
559: String dashes = cnb.replace('.', '-');
560:
561: File config = new File(new File(new File(cluster, "config"),
562: "Modules"), dashes + ".xml");
563: File jar = new File(new File(cluster, "modules"), dashes
564: + ".jar");
565:
566: config.getParentFile().mkdirs();
567: jar.getParentFile().mkdirs();
568:
569: config.createNewFile();
570: jar.createNewFile();
571: config.setLastModified(accesTime);
572: jar.setLastModified(accesTime);
573: }
574:
575: }
|