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: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.spi.project.support.ant;
043:
044: import java.io.File;
045: import java.io.FileOutputStream;
046: import java.io.OutputStream;
047: import org.netbeans.api.project.ProjectManager;
048: import org.netbeans.api.project.TestUtil;
049: import org.netbeans.api.queries.FileBuiltQuery;
050: import org.netbeans.junit.NbTestCase;
051: import org.netbeans.spi.queries.FileBuiltQueryImplementation;
052: import org.openide.filesystems.FileLock;
053: import org.openide.filesystems.FileObject;
054: import org.openide.filesystems.FileUtil;
055: import org.openide.loaders.DataObject;
056:
057: // XXX testChangesFromAntPropertyChanges
058: import org.openide.util.test.MockChangeListener;
059:
060: /**
061: * Test functionality of GlobFileBuiltQuery.
062: * @author Jesse Glick
063: */
064: public class GlobFileBuiltQueryTest extends NbTestCase {
065:
066: static {
067: TestUtil.setLookup(new Object[] { AntBasedTestUtil
068: .testAntBasedProjectType(), });
069: }
070:
071: public GlobFileBuiltQueryTest(String name) {
072: super (name);
073: }
074:
075: private FileObject scratch;
076: private FileObject prj;
077: private FileObject extsrc;
078: private FileObject extbuild;
079: private AntProjectHelper h;
080: private FileBuiltQueryImplementation fbqi;
081: private FileObject foo, bar, fooTest, baz, nonsense;
082: private FileBuiltQuery.Status fooStatus, barStatus, fooTestStatus,
083: bazStatus;
084:
085: protected void setUp() throws Exception {
086: super .setUp();
087: scratch = TestUtil.makeScratchDir(this );
088: prj = scratch.createFolder("prj");
089: h = ProjectGenerator.createProject(prj, "test");
090: extsrc = scratch.createFolder("extsrc");
091: extbuild = scratch.createFolder("extbuild");
092: EditableProperties ep = h
093: .getProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH);
094: ep.setProperty("src.dir", "src");
095: ep.setProperty("test.src.dir", "test/src");
096: ep.setProperty("ext.src.dir", "../extsrc");
097: ep.setProperty("build.classes.dir", "build/classes");
098: ep.setProperty("test.build.classes.dir", "build/test/classes");
099: ep.setProperty("ext.build.classes.dir", "../extbuild/classes");
100: h.putProperties(AntProjectHelper.PROJECT_PROPERTIES_PATH, ep);
101: ProjectManager.getDefault().saveProject(
102: ProjectManager.getDefault().findProject(prj));
103: foo = TestUtil.createFileFromContent(null, prj,
104: "src/pkg/Foo.java");
105: bar = TestUtil.createFileFromContent(null, prj,
106: "src/pkg/Bar.java");
107: fooTest = TestUtil.createFileFromContent(null, prj,
108: "test/src/pkg/FooTest.java");
109: baz = TestUtil.createFileFromContent(null, extsrc,
110: "pkg2/Baz.java");
111: nonsense = TestUtil.createFileFromContent(null, prj,
112: "misc-src/whatever/Nonsense.java");
113: fbqi = h.createGlobFileBuiltQuery(h
114: .getStandardPropertyEvaluator(), new String[] {
115: "${src.dir}/*.java", "${test.src.dir}/*.java",
116: "${ext.src.dir}/*.java", }, new String[] {
117: "${build.classes.dir}/*.class",
118: "${test.build.classes.dir}/*.class",
119: "${ext.build.classes.dir}/*.class", });
120: fooStatus = fbqi.getStatus(foo);
121: barStatus = fbqi.getStatus(bar);
122: fooTestStatus = fbqi.getStatus(fooTest);
123: bazStatus = fbqi.getStatus(baz);
124: }
125:
126: /** Enough time (millisec) for file timestamps to be different. */
127: private static final long PAUSE = 1500;
128:
129: public void testBasicFunctionality() throws Exception {
130: assertNotNull("have status for Foo.java", fooStatus);
131: assertNotNull("have status for Bar.java", barStatus);
132: assertNotNull("have status for FooTest.java", fooTestStatus);
133: assertNull("non-matching file ignored", fbqi
134: .getStatus(nonsense));
135: assertFalse("Foo.java not built", fooStatus.isBuilt());
136: assertFalse("Bar.java not built", barStatus.isBuilt());
137: assertFalse("FooTest.java not built", fooTestStatus.isBuilt());
138: FileObject fooClass = TestUtil.createFileFromContent(null, prj,
139: "build/classes/pkg/Foo.class");
140: assertTrue("Foo.java now built", fooStatus.isBuilt());
141: Thread.sleep(PAUSE);
142: TestUtil.createFileFromContent(null, prj, "src/pkg/Foo.java");
143: assertFalse("Foo.class out of date", fooStatus.isBuilt());
144: TestUtil.createFileFromContent(null, prj,
145: "build/classes/pkg/Foo.class");
146: assertTrue("Foo.class rebuilt", fooStatus.isBuilt());
147: fooClass.delete();
148: assertFalse("Foo.class deleted", fooStatus.isBuilt());
149: TestUtil.createFileFromContent(null, prj,
150: "build/test/classes/pkg/FooTest.class");
151: assertTrue("FooTest.java now built", fooTestStatus.isBuilt());
152: assertFalse("Bar.java still not built", barStatus.isBuilt());
153: TestUtil.createFileFromContent(null, prj,
154: "build/classes/pkg/Foo.class");
155: assertTrue("Foo.java built again", fooStatus.isBuilt());
156: DataObject.find(foo).setModified(true);
157: assertFalse("Foo.java modified", fooStatus.isBuilt());
158: DataObject.find(foo).setModified(false);
159: assertTrue("Foo.java unmodified again", fooStatus.isBuilt());
160: FileObject buildDir = prj.getFileObject("build");
161: assertNotNull("build dir exists", buildDir);
162: buildDir.delete();
163: assertFalse("Foo.java not built (build dir gone)", fooStatus
164: .isBuilt());
165: assertFalse("Bar.java still not built", barStatus.isBuilt());
166: assertFalse("FooTest.java not built (build dir gone)",
167: fooTestStatus.isBuilt());
168: // Just to check that you can delete a source file safely:
169: bar.delete();
170: barStatus.isBuilt();
171: }
172:
173: /** Maximum amount of time (in milliseconds) to wait for expected changes. */
174: private static final long WAIT = 10000;
175: /** Maximum amount of time (in milliseconds) to wait for unexpected changes. */
176: private static final long QUICK_WAIT = 500;
177:
178: public void testChangeFiring() throws Exception {
179: MockChangeListener fooL = new MockChangeListener();
180: fooStatus.addChangeListener(fooL);
181: MockChangeListener barL = new MockChangeListener();
182: barStatus.addChangeListener(barL);
183: MockChangeListener fooTestL = new MockChangeListener();
184: fooTestStatus.addChangeListener(fooTestL);
185: assertFalse("Foo.java not built", fooStatus.isBuilt());
186: FileObject fooClass = TestUtil.createFileFromContent(null, prj,
187: "build/classes/pkg/Foo.class");
188: fooL.msg("change in Foo.java").expectEvent(WAIT);
189: assertTrue("Foo.java now built", fooStatus.isBuilt());
190: fooL.msg("no more changes in Foo.java").expectNoEvents(
191: QUICK_WAIT);
192: fooClass.delete();
193: fooL.msg("change in Foo.java").expectEvent(WAIT);
194: assertFalse("Foo.java no longer built", fooStatus.isBuilt());
195: fooTestL.msg("no changes yet in FooTest.java").expectNoEvents(
196: QUICK_WAIT);
197: assertFalse("FooTest.java not yet built", fooTestStatus
198: .isBuilt());
199: FileObject fooTestClass = TestUtil.createFileFromContent(null,
200: prj, "build/test/classes/pkg/FooTest.class");
201: fooTestL.msg("change in FooTest.java").expectEvent(WAIT);
202: assertTrue("FooTest.java now built", fooTestStatus.isBuilt());
203: FileObject buildDir = prj.getFileObject("build");
204: assertNotNull("build dir exists", buildDir);
205: buildDir.delete();
206: fooL.msg("no change in Foo.java (still not built)")
207: .expectNoEvents(QUICK_WAIT);
208: assertFalse("Foo.java not built (build dir gone)", fooStatus
209: .isBuilt());
210: fooTestL.msg("got change in FooTest.java (build dir gone)")
211: .expectEvent(WAIT);
212: assertFalse("FooTest.java not built (build dir gone)",
213: fooTestStatus.isBuilt());
214: barL.msg("never got changes in Bar.java (never built)")
215: .expectNoEvents(QUICK_WAIT);
216: TestUtil.createFileFromContent(null, prj,
217: "build/classes/pkg/Foo.class");
218: fooL.msg("change in Foo.class").expectEvent(WAIT);
219: assertTrue("Foo.class created", fooStatus.isBuilt());
220: Thread.sleep(PAUSE);
221: TestUtil.createFileFromContent(null, prj, "src/pkg/Foo.java");
222: fooL.msg("change in Foo.java").expectEvent(WAIT);
223: assertFalse("Foo.class out of date", fooStatus.isBuilt());
224: TestUtil.createFileFromContent(null, prj,
225: "build/classes/pkg/Foo.class");
226: fooL.msg("touched Foo.class").expectEvent(WAIT);
227: assertTrue("Foo.class touched", fooStatus.isBuilt());
228: DataObject.find(foo).setModified(true);
229: fooL.msg("Foo.java modified in memory").expectEvent(WAIT);
230: assertFalse("Foo.java modified in memory", fooStatus.isBuilt());
231: DataObject.find(foo).setModified(false);
232: fooL.msg("Foo.java unmodified in memory").expectEvent(WAIT);
233: assertTrue("Foo.java unmodified again", fooStatus.isBuilt());
234: File buildF = new File(FileUtil.toFile(prj), "build");
235: assertTrue("build dir exists", buildF.isDirectory());
236: TestUtil.deleteRec(buildF);
237: assertFalse(buildF.getAbsolutePath() + " is gone", buildF
238: .exists());
239: prj.getFileSystem().refresh(false);
240: fooL.msg("build dir deleted").expectEvent(WAIT);
241: assertFalse("Foo.class gone (no build dir)", fooStatus
242: .isBuilt());
243: File pkg = new File(buildF, "classes/pkg".replace('/',
244: File.separatorChar));
245: File fooClassF = new File(pkg, "Foo.class");
246: //System.err.println("--> going to make " + fooClassF);
247: assertTrue("created " + pkg, pkg.mkdirs());
248: assertFalse("no such file yet: " + fooClassF, fooClassF
249: .exists());
250: OutputStream os = new FileOutputStream(fooClassF);
251: os.close();
252: prj.getFileSystem().refresh(false);
253: fooL.msg(fooClassF.getAbsolutePath() + " created on disk")
254: .expectEvent(WAIT);
255: assertTrue("Foo.class back", fooStatus.isBuilt());
256: Thread.sleep(PAUSE);
257: TestUtil.createFileFromContent(null, prj, "src/pkg/Foo.java");
258: fooL.msg("change in Foo.java").expectEvent(WAIT);
259: assertFalse("Foo.class out of date", fooStatus.isBuilt());
260: os = new FileOutputStream(fooClassF);
261: os.write(69); // force Mac OS X to update timestamp
262: os.close();
263: prj.getFileSystem().refresh(false);
264: fooL.msg("Foo.class recreated on disk").expectEvent(WAIT);
265: assertTrue("Foo.class touched", fooStatus.isBuilt());
266: }
267:
268: public void testExternalSourceRoots() throws Exception {
269: // Cf. #43609.
270: assertNotNull("have status for Baz.java", bazStatus);
271: MockChangeListener bazL = new MockChangeListener();
272: bazStatus.addChangeListener(bazL);
273: assertFalse("Baz.java not built", bazStatus.isBuilt());
274: FileObject bazClass = TestUtil.createFileFromContent(null,
275: extbuild, "classes/pkg2/Baz.class");
276: bazL.msg("got change").expectEvent(WAIT);
277: assertTrue("Baz.java now built", bazStatus.isBuilt());
278: Thread.sleep(PAUSE);
279: TestUtil.createFileFromContent(null, extsrc, "pkg2/Baz.java");
280: bazL.msg("got change").expectEvent(WAIT);
281: assertFalse("Baz.class out of date", bazStatus.isBuilt());
282: TestUtil.createFileFromContent(null, extbuild,
283: "classes/pkg2/Baz.class");
284: bazL.msg("got change").expectEvent(WAIT);
285: assertTrue("Baz.class rebuilt", bazStatus.isBuilt());
286: bazClass.delete();
287: bazL.msg("got change").expectEvent(WAIT);
288: assertFalse("Baz.class deleted", bazStatus.isBuilt());
289: TestUtil.createFileFromContent(null, extbuild,
290: "classes/pkg2/Baz.class");
291: bazL.msg("got change").expectEvent(WAIT);
292: assertTrue("Baz.java built again", bazStatus.isBuilt());
293: DataObject.find(baz).setModified(true);
294: bazL.msg("got change").expectEvent(WAIT);
295: assertFalse("Baz.java modified", bazStatus.isBuilt());
296: DataObject.find(baz).setModified(false);
297: bazL.msg("got change").expectEvent(WAIT);
298: assertTrue("Baz.java unmodified again", bazStatus.isBuilt());
299: extbuild.delete();
300: bazL.msg("got change").expectEvent(WAIT);
301: assertFalse("Baz.java not built (build dir gone)", bazStatus
302: .isBuilt());
303: }
304:
305: public void testFileRenames() throws Exception {
306: // Cf. #45694.
307: assertNotNull("have status for Foo.java", fooStatus);
308: MockChangeListener fooL = new MockChangeListener();
309: fooStatus.addChangeListener(fooL);
310: assertFalse("Foo.java not built", fooStatus.isBuilt());
311: FileObject fooClass = TestUtil.createFileFromContent(null, prj,
312: "build/classes/pkg/Foo.class");
313: fooL.msg("got change").expectEvent(WAIT);
314: assertTrue("Foo.java now built", fooStatus.isBuilt());
315: FileLock lock = foo.lock();
316: try {
317: foo.rename(lock, "Foo2", "java");
318: } finally {
319: lock.releaseLock();
320: }
321: fooL.msg("got change").expectEvent(WAIT);
322: assertFalse("Foo2.java no longer built", fooStatus.isBuilt());
323: fooClass = TestUtil.createFileFromContent(null, prj,
324: "build/classes/pkg/Foo2.class");
325: fooL.msg("got change").expectEvent(WAIT);
326: assertTrue("Now Foo2.java is built", fooStatus.isBuilt());
327: }
328:
329: /**See issue #66713.
330: */
331: public void testInvalidFile() throws Exception {
332: FileObject baz = TestUtil.createFileFromContent(null, prj,
333: "src/pkg/Baz.java");
334:
335: baz.delete();
336: assertNull(fbqi.getStatus(baz));
337: }
338:
339: }
|