0001: /*BEGIN_COPYRIGHT_BLOCK
0002: *
0003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
0004: * All rights reserved.
0005: *
0006: * Redistribution and use in source and binary forms, with or without
0007: * modification, are permitted provided that the following conditions are met:
0008: * * Redistributions of source code must retain the above copyright
0009: * notice, this list of conditions and the following disclaimer.
0010: * * Redistributions in binary form must reproduce the above copyright
0011: * notice, this list of conditions and the following disclaimer in the
0012: * documentation and/or other materials provided with the distribution.
0013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
0014: * names of its contributors may be used to endorse or promote products
0015: * derived from this software without specific prior written permission.
0016: *
0017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0028: *
0029: * This software is Open Source Initiative approved Open Source Software.
0030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
0031: *
0032: * This file is part of DrJava. Download the current version of this project
0033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
0034: *
0035: * END_COPYRIGHT_BLOCK*/
0036:
0037: package edu.rice.cs.drjava.model;
0038:
0039: import java.io.*;
0040:
0041: import java.util.List;
0042: import javax.swing.text.BadLocationException;
0043:
0044: import edu.rice.cs.plt.io.IOUtil;
0045: import edu.rice.cs.util.FileOpenSelector;
0046: import edu.rice.cs.util.Log;
0047: import edu.rice.cs.util.OperationCanceledException;
0048: import edu.rice.cs.util.StringOps;
0049: import edu.rice.cs.util.UnexpectedException;
0050: import edu.rice.cs.util.text.ConsoleDocument;
0051: import edu.rice.cs.util.text.EditDocumentException;
0052: import edu.rice.cs.util.swing.Utilities;
0053: import edu.rice.cs.drjava.model.repl.*;
0054: import edu.rice.cs.drjava.DrJava;
0055: import edu.rice.cs.drjava.config.OptionConstants;
0056:
0057: /** Test I/O functions of the global model.
0058: * @version $Id: GlobalModelIOTest.java 4255 2007-08-28 19:17:37Z mgricken $
0059: */
0060: public final class GlobalModelIOTest extends GlobalModelTestCase
0061: implements OptionConstants {
0062:
0063: // _log is inherited from GlobalModelTestCase
0064:
0065: /** Creates a new document, modifies it, and then does the same with a second document, checking for inteference. */
0066: public void testMultipleFiles() throws BadLocationException {
0067: assertNumOpenDocs(1);
0068:
0069: OpenDefinitionsDocument doc1 = setupDocument(FOO_TEXT);
0070: assertNumOpenDocs(2);
0071:
0072: // Create a second, empty document
0073: OpenDefinitionsDocument doc2 = _model.newFile();
0074: assertNumOpenDocs(3);
0075: assertModified(true, doc1);
0076: assertModified(false, doc2);
0077: assertContents(FOO_TEXT, doc1);
0078: assertLength(0, doc2);
0079:
0080: // Modify second document
0081: changeDocumentText(BAR_TEXT, doc2);
0082: assertModified(true, doc2);
0083: assertContents(FOO_TEXT, doc1);
0084: assertContents(BAR_TEXT, doc2);
0085:
0086: _log.log(this + ".testMultipleFiles() completed");
0087: }
0088:
0089: /** Opens several documents and ensures that the array returned by the model is correct and in the right order. */
0090: public void testMultipleFilesArray() throws BadLocationException {
0091: OpenDefinitionsDocument doc1, doc2, doc3;
0092: doc1 = setupDocument(FOO_TEXT);
0093: doc2 = setupDocument(BAR_TEXT);
0094: doc3 = setupDocument(FOO_TEXT);
0095: assertNumOpenDocs(4);
0096:
0097: List<OpenDefinitionsDocument> docs = _model
0098: .getSortedOpenDefinitionsDocuments();
0099: assertEquals("size of document array", 4, docs.size());
0100:
0101: assertEquals("document 1", doc1, docs.get(1));
0102: assertEquals("document 2", doc2, docs.get(2));
0103: assertEquals("document 3", doc3, docs.get(3));
0104:
0105: _log.log(this + ".testMultipleFilesArray() completed");
0106: }
0107:
0108: /** Ensures closing documents works correctly. */
0109: public void testCloseMultipleFiles() throws BadLocationException {
0110: assertNumOpenDocs(1);
0111: OpenDefinitionsDocument doc1 = setupDocument(FOO_TEXT);
0112: assertNumOpenDocs(2);
0113: OpenDefinitionsDocument doc2 = setupDocument(BAR_TEXT);
0114: assertNumOpenDocs(3);
0115:
0116: _model.closeFile(doc1);
0117: assertNumOpenDocs(2);
0118:
0119: List<OpenDefinitionsDocument> docs = _model
0120: .getSortedOpenDefinitionsDocuments();
0121: assertEquals("size of document array", 2, docs.size());
0122: assertContents(BAR_TEXT, docs.get(1));
0123:
0124: _model.closeFile(doc2);
0125: assertNumOpenDocs(1);
0126: docs = _model.getOpenDefinitionsDocuments();
0127: assertEquals("size of document array", 1, docs.size());
0128:
0129: _log.log(this + ".testCloseMultipleFiles() completed");
0130: }
0131:
0132: /** Creates a new document, modifies it, then allows it to be closed, ignoring the changes made. */
0133: public void testCloseFileAllowAbandon() throws BadLocationException {
0134: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0135:
0136: // Try to close and check for proper events
0137: TestListener listener = new TestIOListener() {
0138: public synchronized boolean canAbandonFile(
0139: OpenDefinitionsDocument doc) {
0140: canAbandonCount++;
0141: return true; // yes allow the abandon
0142: }
0143: };
0144:
0145: _model.addListener(listener);
0146: _model.closeFile(doc);
0147: listener.assertAbandonCount(1);
0148: listener.assertCloseCount(1); // closed one document
0149: listener.assertOpenCount(0);
0150:
0151: _log.log("testCloseFileAllowAbandon completed");
0152: }
0153:
0154: /** Creates a new document, modifies it, but disallows a call to close it without saving changes. */
0155: public void testCloseFileDisallowAbandon()
0156: throws BadLocationException {
0157: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0158:
0159: TestListener listener = new TestIOListener() {
0160: public synchronized boolean canAbandonFile(
0161: OpenDefinitionsDocument doc) {
0162: canAbandonCount++;
0163: return false; // no, don't abandon our document!!!
0164: }
0165: };
0166:
0167: _model.addListener(listener);
0168: _model.closeFile(doc);
0169: listener.assertAbandonCount(1);
0170: listener.assertCloseCount(0);
0171: listener.assertOpenCount(0);
0172:
0173: _log.log("testCloseFileDisallowAbandon completed");
0174: }
0175:
0176: /** Opens a file. */
0177: public void testOpenRealFile() throws BadLocationException,
0178: IOException {
0179: final File tempFile = writeToNewTempFile(BAR_TEXT);
0180:
0181: TestListener listener = new TestFileIOListener(tempFile);
0182:
0183: _model.addListener(listener);
0184: try {
0185: OpenDefinitionsDocument doc = _model
0186: .openFile(new FileSelector(tempFile));
0187: listener.assertOpenCount(1);
0188: listener.assertCloseCount(1); // Untitled document is closed when doc is opened
0189: assertModified(false, doc);
0190: assertContents(BAR_TEXT, doc);
0191: } catch (AlreadyOpenException aoe) {
0192: // Should not be open
0193: fail("File was already open!");
0194: } catch (OperationCanceledException oce) {
0195: // Should not be canceled
0196: fail("Open was unexpectedly canceled!");
0197: }
0198:
0199: _log.log("testOpenRealFile completed");
0200: }
0201:
0202: /** Initiates a file open, but cancels. */
0203: public void testCancelOpenFile() throws BadLocationException,
0204: IOException {
0205:
0206: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0207: assertNumOpenDocs(2);
0208:
0209: TestListener listener = new TestIOListener() {
0210: public synchronized boolean canAbandonFile(
0211: OpenDefinitionsDocument doc) {
0212: canAbandonCount++;
0213: return true; // yes allow the abandon
0214: }
0215: };
0216:
0217: _model.addListener(listener);
0218: try {
0219: //OpenDefinitionsDocument newDoc =
0220: _model.openFile(new CancelingSelector());
0221: } catch (AlreadyOpenException aoe) {
0222: // Should not be open
0223: fail("File was already open!");
0224: } catch (OperationCanceledException oce) {
0225: // we expect this to be thrown
0226: } finally {
0227: assertNumOpenDocs(2);
0228: listener.assertOpenCount(0);
0229: listener.assertCloseCount(0);
0230:
0231: List<OpenDefinitionsDocument> docs = _model
0232: .getOpenDefinitionsDocuments();
0233: doc = docs.get(1);
0234: assertModified(true, doc);
0235: assertContents(FOO_TEXT, doc);
0236: }
0237:
0238: _log.log("testCancelOpenFile completed");
0239: }
0240:
0241: /** Attempts to open a non-existent file. */
0242: public void testOpenNonexistentFile() throws IOException {
0243: _model.addListener(new TestListener());
0244:
0245: OpenDefinitionsDocument doc = null;
0246:
0247: try {
0248: doc = _model.openFile(new FileSelector(
0249: new File("fake-file")));
0250: fail("IO exception was not thrown!");
0251: } catch (FileNotFoundException fnf) {
0252: // As we hoped, the file was not found
0253: } catch (AlreadyOpenException aoe) {
0254: // Should not be open
0255: fail("File was already open!");
0256: } catch (OperationCanceledException oce) {
0257: // Should not be canceled
0258: fail("Open was unexpectedly canceled!");
0259: }
0260:
0261: assertEquals("non-existant file", doc, null);
0262:
0263: _log.log("testOpenNonexistentFile completed");
0264: }
0265:
0266: /** Attempts to reopen an already open file. */
0267: public void testReopenFile() throws BadLocationException,
0268: IOException {
0269: final File tempFile = writeToNewTempFile(BAR_TEXT);
0270:
0271: TestListener listener = new TestFileIOListener(tempFile);
0272:
0273: _model.addListener(listener);
0274: try {
0275: OpenDefinitionsDocument doc = _model
0276: .openFile(new FileSelector(tempFile));
0277: listener.assertOpenCount(1);
0278: listener.assertCloseCount(1); // Untitled document closed when doc is opened
0279: assertModified(false, doc);
0280: assertContents(BAR_TEXT, doc);
0281: } catch (AlreadyOpenException aoe) {
0282: // Should not be open
0283: fail("File was already open!");
0284: } catch (OperationCanceledException oce) {
0285: // Should not be canceled
0286: fail("Open was unexpectedly canceled!");
0287: }
0288:
0289: // Now reopen
0290: try {
0291: //OpenDefinitionsDocument doc2 =
0292: _model.openFile(new FileSelector(tempFile));
0293: fail("file should already be open");
0294: } catch (AlreadyOpenException aoe) {
0295: // Should not be open
0296: listener.assertOpenCount(1);
0297: listener.assertCloseCount(1);
0298: } catch (OperationCanceledException oce) {
0299: // Should not be canceled
0300: fail("Open was unexpectedly canceled!");
0301: }
0302:
0303: // Now reopen same file with a different path
0304: // eg. /tmp/MyFile -> /tmp/./MyFile
0305: try {
0306: File parent = tempFile.getParentFile();
0307: String dotSlash = "."
0308: + System.getProperty("file.separator");
0309: parent = new File(parent, dotSlash);
0310: File sameFile = new File(parent, tempFile.getName());
0311: //OpenDefinitionsDocument doc2 =
0312: _model.openFile(new FileSelector(sameFile));
0313: fail("file should already be open");
0314: } catch (AlreadyOpenException aoe) {
0315: // Should not be open
0316: listener.assertOpenCount(1);
0317: } catch (OperationCanceledException oce) {
0318: // Should not be canceled
0319: fail("Open was unexpectedly canceled!");
0320: }
0321: _log.log("testReopenFile completed");
0322: }
0323:
0324: /** Opens multiple files. */
0325: public void testOpenMultipleFiles() throws BadLocationException,
0326: IOException {
0327: final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0328: final File tempFile2 = writeToNewTempFile(BAR_TEXT);
0329:
0330: TestListener listener = new TestIOListener() {
0331: public void fileOpened(OpenDefinitionsDocument doc) {
0332: super .fileOpened(doc);
0333: File file = null;
0334: try {
0335: file = doc.getFile();
0336: } catch (FileMovedException fme) {
0337: fail("file does not exist");
0338: } // We know file should exist
0339: if (tempFile1.equals(file))
0340: assertEquals("file to open", IOUtil
0341: .attemptCanonicalFile(tempFile1), IOUtil
0342: .attemptCanonicalFile(file));
0343: else
0344: assertEquals("file to open", IOUtil
0345: .attemptCanonicalFile(tempFile2), IOUtil
0346: .attemptCanonicalFile(file));
0347: }
0348: };
0349:
0350: _model.addListener(listener);
0351: try {
0352: OpenDefinitionsDocument[] docs = _model
0353: .openFiles(new FileSelector(tempFile1, tempFile2));
0354: listener.assertOpenCount(2);
0355: listener.assertCloseCount(1); // closed Untitled document
0356: assertEquals("Number of docs returned", docs.length, 2);
0357: assertModified(false, docs[0]);
0358: assertContents(FOO_TEXT, docs[0]);
0359: assertModified(false, docs[1]);
0360: assertContents(BAR_TEXT, docs[1]);
0361: } catch (AlreadyOpenException aoe) {
0362: // Should not be open
0363: fail("File was already open!");
0364: } catch (OperationCanceledException oce) {
0365: // Should not be canceled
0366: fail("Open was unexpectedly canceled!");
0367: }
0368: listener.assertOpenCount(2);
0369: List<OpenDefinitionsDocument> docs = _model
0370: .getSortedOpenDefinitionsDocuments();
0371: assertEquals("size of document array", 2, docs.size());
0372: assertContents(FOO_TEXT, docs.get(0));
0373: assertContents(BAR_TEXT, docs.get(1));
0374:
0375: _log.log("testOpenMultipleFiles completed");
0376:
0377: }
0378:
0379: /** Initiates a file open, but cancels. */
0380: public void testCancelOpenMultipleFiles()
0381: throws BadLocationException, IOException {
0382:
0383: OpenDefinitionsDocument doc1 = setupDocument(FOO_TEXT);
0384: OpenDefinitionsDocument doc2 = setupDocument(BAR_TEXT);
0385: assertNumOpenDocs(3);
0386:
0387: TestListener listener = new TestIOListener() {
0388: public synchronized boolean canAbandonFile(
0389: OpenDefinitionsDocument doc) {
0390: canAbandonCount++;
0391: return true; // yes allow the abandon
0392: }
0393: };
0394:
0395: _model.addListener(listener);
0396: try {
0397: //OpenDefinitionsDocument newDoc =
0398: _model.openFiles(new CancelingSelector());
0399: } catch (AlreadyOpenException aoe) {
0400: // Should not be open
0401: fail("File was already open!");
0402: } catch (OperationCanceledException oce) {
0403: // we expect this to be thrown
0404: } finally {
0405: assertNumOpenDocs(3);
0406: listener.assertOpenCount(0);
0407: listener.assertCloseCount(0);
0408:
0409: List<OpenDefinitionsDocument> docs = _model
0410: .getSortedOpenDefinitionsDocuments();
0411: doc1 = docs.get(1);
0412: assertModified(true, doc1);
0413: assertContents(FOO_TEXT, doc1);
0414:
0415: doc2 = docs.get(2);
0416: assertModified(true, doc2);
0417: assertContents(BAR_TEXT, doc2);
0418: }
0419:
0420: _log.log("testCancelOpenMultipleFiles completed");
0421: }
0422:
0423: /** Attempts to open a non-existent file. */
0424: public void testOpenMultipleNonexistentFiles() throws IOException {
0425:
0426: final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0427:
0428: //TestListener listener = new TestListener();
0429: TestListener listener = new TestFileIOListener(tempFile1) {
0430: public synchronized void filesNotFound(File... f) {
0431: fileNotFoundCount++;
0432: }
0433: };
0434:
0435: _model.addListener(listener);
0436:
0437: OpenDefinitionsDocument[] docs = null;
0438: try {
0439: docs = _model.openFiles(new FileSelector(tempFile1,
0440: new File("fake-file")));
0441: } catch (FileNotFoundException fnf) {
0442: fail("FileNotFound exception was not thrown!");
0443: } // Should not have moved
0444: catch (AlreadyOpenException aoe) {
0445: fail("File was already open!");
0446: } // Should not be open
0447: catch (OperationCanceledException oce) {
0448: fail("Open was unexpectedly canceled!");
0449: } // Should not be canceled
0450: assertTrue("one file was opened", docs != null
0451: && docs.length == 1);
0452: listener.assertOpenCount(1);
0453: listener.assertCloseCount(1); // closed Untitled document
0454: listener.assertFileNotFoundCount(1);
0455:
0456: _log.log("testOpenMultipleNonexistentFiles completed");
0457: }
0458:
0459: /** Error checking for openening multiple files checks for null and an array w/null. */
0460: public void testOpenMultipleFilesError() {
0461:
0462: OpenDefinitionsDocument[] docs = null;
0463: //final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0464:
0465: try {
0466: docs = _model.openFiles(new FileOpenSelector() {
0467: public File[] getFiles() {
0468: return new File[] { null };
0469: }
0470: });
0471: fail("IO exception was not thrown!");
0472: } catch (IOException e) { /* As we expected, the file was not found */
0473: } catch (Exception e) {
0474: fail("Unexpectedly exception caught!");
0475: }
0476:
0477: try {
0478: docs = _model.openFiles(new FileOpenSelector() {
0479: public File[] getFiles() {
0480: return null;
0481: }
0482: });
0483:
0484: fail("IO exception was not thrown!");
0485: } catch (IOException e) { /* As we expected, the file was not found. */
0486: } catch (Exception e) {
0487: fail("Unexpectedly exception caught!");
0488: }
0489:
0490: assertTrue("non-existent file", docs == null);
0491:
0492: _log.log("testOpenMultipleFilesError completed");
0493: }
0494:
0495: /** Force a file to be opened with getDocumentforFile. */
0496: public void testForceFileOpen() throws BadLocationException,
0497: IOException, OperationCanceledException,
0498: AlreadyOpenException {
0499:
0500: final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0501: final File tempFile2 = writeToNewTempFile(BAR_TEXT);
0502: // don't catch and fail!
0503:
0504: TestListener listener = new TestIOListener();
0505:
0506: _model.addListener(listener);
0507: // Open file 1
0508: OpenDefinitionsDocument doc = _model.openFile(new FileSelector(
0509: tempFile1));
0510: listener.assertOpenCount(1);
0511: listener.assertCloseCount(1); // closed Untitled document
0512: assertModified(false, doc);
0513: assertContents(FOO_TEXT, doc);
0514:
0515: // Get file 1
0516: OpenDefinitionsDocument doc1 = _model
0517: .getDocumentForFile(tempFile1);
0518: listener.assertOpenCount(1);
0519: listener.assertCloseCount(1); // closed Untitled document
0520: assertEquals("opened document", doc, doc1);
0521: assertContents(FOO_TEXT, doc1);
0522:
0523: // Get file 2, forcing it to be opened
0524: OpenDefinitionsDocument doc2 = _model
0525: .getDocumentForFile(tempFile2);
0526: listener.assertOpenCount(2);
0527: listener.assertCloseCount(1); // closed Untitled document
0528: assertContents(BAR_TEXT, doc2);
0529: }
0530:
0531: /** Attempts to make the first save of a document, but cancels instead. */
0532: public void testCancelFirstSave() throws BadLocationException,
0533: IOException {
0534: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0535:
0536: // No need to override methods since no events should be fired
0537: _model.addListener(new TestListener());
0538:
0539: boolean saved = doc.saveFile(new CancelingSelector());
0540: assertTrue("doc should not have been saved", !saved);
0541: assertModified(true, doc);
0542: assertContents(FOO_TEXT, doc);
0543:
0544: _log.log("testForceFileOpen completed");
0545: }
0546:
0547: /** Makes a first save of the current document. */
0548: public void testRealSaveFirstSave() throws BadLocationException,
0549: IOException {
0550: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0551: final File file = tempFile();
0552:
0553: TestListener listener = new TestListener() {
0554: public void fileSaved(OpenDefinitionsDocument doc) {
0555: File f = null;
0556: try {
0557: f = doc.getFile();
0558: } catch (FileMovedException fme) {
0559: fail("file does not exist");
0560: } // We know file should exist
0561: try {
0562: assertEquals("saved file name", file
0563: .getCanonicalFile(), f.getCanonicalFile());
0564: synchronized (this ) {
0565: saveCount++;
0566: }
0567: } catch (IOException ioe) {
0568: fail("could not get canonical file");
0569: }
0570: }
0571: };
0572:
0573: _model.addListener(listener);
0574:
0575: doc.saveFile(new FileSelector(file));
0576: listener.assertSaveCount(1);
0577: assertModified(false, doc);
0578: assertContents(FOO_TEXT, doc);
0579:
0580: assertEquals("contents of saved file", FOO_TEXT, IOUtil
0581: .toString(file));
0582:
0583: _log.log("testRealSaveFirstSave completed");
0584: }
0585:
0586: /** Saves a file already saved and overwrites its contents. */
0587: public void testSaveAlreadySaved() throws BadLocationException,
0588: IOException {
0589: //disable file backups, remember original setting
0590: Boolean backupStatus = DrJava.getConfig().getSetting(
0591: BACKUP_FILES);
0592: DrJava.getConfig().setSetting(BACKUP_FILES, Boolean.FALSE);
0593:
0594: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0595: final File file = tempFile();
0596:
0597: // No listeners here -- other tests ensure the first save works
0598: doc.saveFile(new FileSelector(file));
0599: assertModified(false, doc);
0600: assertContents(FOO_TEXT, doc);
0601: assertEquals("contents of saved file", FOO_TEXT, IOUtil
0602: .toString(file));
0603:
0604: // Listener to use on future saves
0605: TestListener listener = new TestListener() {
0606: public void fileSaved(OpenDefinitionsDocument doc) {
0607: File f = null;
0608: try {
0609: f = doc.getFile();
0610: } catch (FileMovedException fme) {
0611: fail("file does not exist");
0612: } // We know file should exist
0613: try {
0614: assertEquals("saved file", file.getCanonicalFile(),
0615: f.getCanonicalFile());
0616: synchronized (this ) {
0617: saveCount++;
0618: }
0619: } catch (IOException ioe) {
0620: fail("could not get canonical file");
0621: }
0622: }
0623: };
0624:
0625: File backup = new File(file.getPath() + "~");
0626: backup.delete();
0627:
0628: _model.addListener(listener);
0629:
0630: // Muck up the document
0631: changeDocumentText(BAR_TEXT, doc);
0632:
0633: // Save over top of the previous file
0634: doc.saveFile(new FileSelector(file));
0635:
0636: Utilities.clearEventQueue();
0637: listener.assertSaveCount(1);
0638: assertEquals("contents of saved file 2nd write", BAR_TEXT,
0639: IOUtil.toString(file));
0640: assertFalse("no backup was made", backup.exists());
0641:
0642: //enable file backups
0643: DrJava.getConfig().setSetting(BACKUP_FILES, Boolean.TRUE);
0644:
0645: // Muck up the document
0646: changeDocumentText(FOO_TEXT, doc);
0647: Utilities.clearEventQueue();
0648:
0649: // Save over top of the previous file
0650: doc.saveFile(new FileSelector(file));
0651:
0652: Utilities.clearEventQueue();
0653: listener.assertSaveCount(2);
0654: assertEquals("contents of saved file 3rd write", FOO_TEXT,
0655: IOUtil.toString(file));
0656: assertEquals("contents of backup file 3rd write", BAR_TEXT,
0657: IOUtil.toString(backup));
0658:
0659: /* Set the config back to the original option */
0660: DrJava.getConfig().setSetting(BACKUP_FILES, backupStatus);
0661:
0662: _log.log("testSaveAlreadySaved completed");
0663: }
0664:
0665: /** Saves the document with FOO_TEXT and then saves over the old text, passing in a CancelingSelector
0666: * to cancel if we are asked for a new file name. Confirms that no cancellation happens (since the
0667: * file is already saved.
0668: */
0669: public void testCancelSaveAlreadySaved()
0670: throws BadLocationException, IOException {
0671: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0672: final File file = tempFile();
0673:
0674: // No listeners here -- other tests ensure the first save works
0675: doc.saveFile(new FileSelector(file));
0676: assertModified(false, doc);
0677: assertContents(FOO_TEXT, doc);
0678: assertEquals("contents of saved file", FOO_TEXT, IOUtil
0679: .toString(file));
0680:
0681: TestListener listener = new TestListener() {
0682: public void fileSaved(OpenDefinitionsDocument doc) {
0683: File f = null;
0684: try {
0685: f = doc.getFile();
0686: } catch (FileMovedException fme) {
0687: fail("file does not exist"); /* We know file should exist */
0688: }
0689: try {
0690: assertEquals("saved file", file.getCanonicalFile(),
0691: f.getCanonicalFile());
0692: synchronized (this ) {
0693: saveCount++;
0694: }
0695: } catch (IOException ioe) {
0696: fail("could not get canonical file");
0697: }
0698: }
0699: };
0700:
0701: _model.addListener(listener);
0702:
0703: // Muck up the document
0704: changeDocumentText(BAR_TEXT, doc);
0705:
0706: doc.saveFile(new CancelingSelector());
0707:
0708: // The file should have saved on top of the old text anyhow.
0709: // The canceling selector should never have been called.
0710: listener.assertSaveCount(1);
0711: assertModified(false, doc);
0712: assertContents(BAR_TEXT, doc);
0713:
0714: assertEquals("contents of saved file", BAR_TEXT, IOUtil
0715: .toString(file));
0716:
0717: _log.log("testCancelSaveAlreadySaved completed");
0718: }
0719:
0720: /** Make sure that saveAs doesn't save if we cancel! */
0721: public void testCancelSaveAsAlreadySaved()
0722: throws BadLocationException, IOException {
0723: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0724: final File file = tempFile();
0725:
0726: // No listeners here -- other tests ensure the first save works
0727: doc.saveFile(new FileSelector(file));
0728: assertModified(false, doc);
0729: assertContents(FOO_TEXT, doc);
0730: assertEquals("contents of saved file", FOO_TEXT, IOUtil
0731: .toString(file));
0732:
0733: // No events better be fired!
0734: _model.addListener(new TestListener());
0735:
0736: // Muck up the document
0737: changeDocumentText(BAR_TEXT, doc);
0738:
0739: doc.saveFileAs(new CancelingSelector());
0740:
0741: assertEquals("contents of saved file", FOO_TEXT, IOUtil
0742: .toString(file));
0743:
0744: _log.log("testCancelSaveAsAlreadySaved completed");
0745: }
0746:
0747: /** Ensures that saveAs saves to a different file. */
0748: public void testSaveAsAlreadySaved() throws BadLocationException,
0749: IOException {
0750: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0751: final File file1 = tempFile();
0752: final File file2 = tempFile();
0753:
0754: // No listeners here -- other tests ensure the first save works
0755: doc.saveFile(new FileSelector(file1));
0756: assertModified(false, doc);
0757: assertContents(FOO_TEXT, doc);
0758: assertEquals("contents of saved file", FOO_TEXT, IOUtil
0759: .toString(file1));
0760:
0761: // Make sure we save now to the new file name
0762: TestListener listener = new TestListener() {
0763: public void fileSaved(OpenDefinitionsDocument doc) {
0764: File f = null;
0765: try {
0766: f = doc.getFile();
0767: } catch (FileMovedException fme) {
0768: fail("file does not exist"); /* We know file should exist */
0769: }
0770: try {
0771: assertEquals("saved file",
0772: file2.getCanonicalFile(), f
0773: .getCanonicalFile());
0774: synchronized (this ) {
0775: saveCount++;
0776: }
0777: } catch (IOException ioe) {
0778: fail("could not get canonical file");
0779: }
0780: }
0781: };
0782:
0783: _model.addListener(listener);
0784:
0785: // Muck up the document
0786: changeDocumentText(BAR_TEXT, doc);
0787:
0788: doc.saveFileAs(new FileSelector(file2));
0789:
0790: assertEquals("contents of saved file1", FOO_TEXT, IOUtil
0791: .toString(file1));
0792:
0793: assertEquals("contents of saved file2", BAR_TEXT, IOUtil
0794: .toString(file2));
0795:
0796: _log.log("testSaveAsAlreadySaved completed");
0797: }
0798:
0799: public void testSaveAsExistsForOverwrite()
0800: throws BadLocationException, IOException {
0801:
0802: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
0803: final File file1 = tempFile();
0804: try {
0805: doc.saveFileAs(new WarningFileSelector(file1));
0806: fail("Did not ask to verify overwrite as expected");
0807: } catch (OverwriteException e1) { /* Good behavior for file saving ... */
0808: }
0809:
0810: _log.log("testSaveAsExistsForOverwrite completed");
0811: }
0812:
0813: public void testSaveAsExistsAndOpen() throws BadLocationException,
0814: IOException {
0815: OpenDefinitionsDocument doc1, doc2;
0816: final File file1, file2;
0817:
0818: file1 = tempFile(1);
0819: doc1 = _model.getDocumentForFile(file1);
0820: changeDocumentText(FOO_TEXT, doc1);
0821: doc1.saveFileAs(new FileSelector(file1));
0822:
0823: file2 = tempFile(2);
0824: doc2 = _model.getDocumentForFile(file2);
0825: changeDocumentText(BAR_TEXT, doc2);
0826:
0827: try {
0828: doc2.saveFileAs(new WarningFileSelector(file1));
0829: fail("Did not warn of open file as expected");
0830: } catch (OpenWarningException e) { /* Good behavior for file saving ... */
0831: }
0832:
0833: _log.log("testSaveAsExistsAndOpen completed");
0834: }
0835:
0836: /** Ensures that all open files are saved in appropriate order, i.e., even with BAR file as active document, save all
0837: * should first prompt to save FOO, then BAR.
0838: */
0839: public void testSaveAllSaveCorrectFiles()
0840: throws BadLocationException, IOException {
0841: OpenDefinitionsDocument fooDoc = setupDocument(FOO_TEXT);
0842: OpenDefinitionsDocument barDoc = setupDocument(BAR_TEXT);
0843: OpenDefinitionsDocument trdDoc = setupDocument("third document contents");
0844: final File file1 = tempFile();
0845: final File file2 = tempFile();
0846: final File file3 = tempFile();
0847: fooDoc.setFile(file1);
0848: barDoc.setFile(file2);
0849: trdDoc.setFile(file3);
0850:
0851: // None of these documents has been entered in the _documentsRepos
0852:
0853: // check.
0854: FileSelector fs = new FileSelector(file1);
0855:
0856: _model.saveAllFiles(fs); // this should save the files as file1,file2,file3 respectively
0857:
0858: assertEquals("contents of saved file1", FOO_TEXT, IOUtil
0859: .toString(file1));
0860: assertEquals("contents of saved file2", BAR_TEXT, IOUtil
0861: .toString(file2));
0862: assertEquals("contents of saved file3",
0863: "third document contents", IOUtil.toString(file3));
0864:
0865: _log.log("testSaveAllSaveCorrectFiles completed");
0866: }
0867:
0868: /** Forces a file to be opened with getDocumentforFile. */
0869: public void testRevertFile() throws BadLocationException,
0870: IOException, OperationCanceledException,
0871: AlreadyOpenException {
0872:
0873: final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0874: // don't catch and fail!
0875:
0876: TestListener listener = new TestIOListener();
0877:
0878: _model.addListener(listener);
0879: // Open file 1
0880: OpenDefinitionsDocument doc = _model.openFile(new FileSelector(
0881: tempFile1));
0882: listener.assertOpenCount(1);
0883: listener.assertCloseCount(1); // closed Untitled document
0884: assertModified(false, doc);
0885: assertContents(FOO_TEXT, doc);
0886:
0887: assertEquals("original doc unmodified", doc
0888: .isModifiedSinceSave(), false);
0889: changeDocumentText(BAR_TEXT, doc);
0890: assertEquals("doc now modified", doc.isModifiedSinceSave(),
0891: true);
0892: tempFile1.delete();
0893: try {
0894: doc.revertFile();
0895: fail("File should not be on disk.");
0896: } catch (FileMovedException fme) {
0897: // Revert should not take place because file is not there.
0898: }
0899: assertEquals("doc NOT reverted", doc.isModifiedSinceSave(),
0900: true);
0901: assertContents(BAR_TEXT, doc);
0902:
0903: _log.log("testRevertFile completed");
0904: }
0905:
0906: public void testModifiedByOther() throws BadLocationException,
0907: IOException, OperationCanceledException,
0908: AlreadyOpenException, InterruptedException {
0909:
0910: final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0911: // don't catch and fail!
0912:
0913: TestListener listener = new TestIOListener() {
0914: public synchronized void fileReverted(
0915: OpenDefinitionsDocument doc) {
0916: fileRevertedCount++;
0917: }
0918:
0919: public synchronized boolean shouldRevertFile(
0920: OpenDefinitionsDocument doc) {
0921: shouldRevertFileCount++;
0922: return true;
0923: }
0924: };
0925:
0926: _model.addListener(listener);
0927: // Open file 1
0928: OpenDefinitionsDocument doc = _model.openFile(new FileSelector(
0929: tempFile1));
0930: listener.assertShouldRevertFileCount(0);
0931: listener.assertFileRevertedCount(0);
0932: assertModified(false, doc);
0933:
0934: doc.revertIfModifiedOnDisk();
0935:
0936: listener.assertShouldRevertFileCount(0);
0937: listener.assertFileRevertedCount(0);
0938: synchronized (tempFile1) {
0939: tempFile1.wait(2000);
0940: }
0941:
0942: String s = "THIS IS ONLY A TEST";
0943: IOUtil.writeStringToFile(tempFile1, s);
0944: assertEquals("contents of saved file", s, IOUtil
0945: .toString(tempFile1));
0946:
0947: tempFile1.setLastModified((new java.util.Date()).getTime());
0948:
0949: assertTrue("modified on disk1", doc.modifiedOnDisk());
0950: boolean res = doc.revertIfModifiedOnDisk();
0951: assertTrue("file reverted", res);
0952:
0953: listener.assertShouldRevertFileCount(1);
0954: listener.assertFileRevertedCount(1);
0955: assertContents(s, doc);
0956:
0957: _log.log("testModifiedByOther completed");
0958: }
0959:
0960: public void testModifiedByOtherFalse() throws BadLocationException,
0961: IOException, OperationCanceledException,
0962: AlreadyOpenException, InterruptedException {
0963: final File tempFile1 = writeToNewTempFile(FOO_TEXT);
0964: // don't catch and fail!
0965:
0966: final TestListener listener = new TestIOListener() {
0967: public synchronized void fileReverted(
0968: OpenDefinitionsDocument doc) {
0969: fileRevertedCount++;
0970: }
0971:
0972: public synchronized boolean shouldRevertFile(
0973: OpenDefinitionsDocument doc) {
0974: shouldRevertFileCount++;
0975: return false;
0976: }
0977: };
0978:
0979: _model.addListener(listener);
0980: // Open file 1
0981: OpenDefinitionsDocument doc = _model.openFile(new FileSelector(
0982: tempFile1));
0983: listener.assertShouldRevertFileCount(0);
0984: listener.assertFileRevertedCount(0);
0985: assertModified(false, doc);
0986:
0987: doc.revertIfModifiedOnDisk();
0988: listener.assertShouldRevertFileCount(0);
0989: listener.assertFileRevertedCount(0);
0990:
0991: synchronized (tempFile1) {
0992: tempFile1.wait(2000);
0993: }
0994:
0995: String s = "THIS IS ONLY A TEST";
0996: IOUtil.writeStringToFile(tempFile1, s);
0997: assertEquals("contents of saved file", s, IOUtil
0998: .toString(tempFile1));
0999:
1000: assertTrue("modified on disk1", doc.modifiedOnDisk());
1001: boolean reverted = doc.revertIfModifiedOnDisk();
1002: assertTrue("modified on disk", reverted == false);
1003: listener.assertShouldRevertFileCount(1);
1004: listener.assertFileRevertedCount(0);
1005: assertContents(FOO_TEXT, doc);
1006:
1007: _log.log("testModifiedByOtherFalse completed");
1008: }
1009:
1010: /** Interprets some statements, saves the history, clears the history, then loads the history. */
1011: public void testSaveClearAndLoadHistory()
1012: throws EditDocumentException, IOException,
1013: InterruptedException {
1014: String newLine = StringOps.EOL;
1015: InteractionListener listener = new InteractionListener();
1016:
1017: _model.addListener(listener);
1018: File f = tempFile();
1019: FileSelector fs = new FileSelector(f);
1020: String s1 = "int x = 5;";
1021: String s2 = "System.out.println(\"x = \" + x)";
1022: String s3 = "int y;" + newLine + "int z;";
1023: listener.assertInteractionStartCount(0);
1024: listener.assertInteractionEndCount(0);
1025:
1026: interpretIgnoreResult(s1);
1027: listener.waitInteractionDone();
1028:
1029: listener.assertInteractionEndCount(1);
1030: listener.assertInteractionStartCount(1);
1031:
1032: listener.logInteractionStart();
1033: interpretIgnoreResult(s2);
1034: listener.waitInteractionDone();
1035:
1036: listener.logInteractionStart();
1037: interpretIgnoreResult(s3);
1038: listener.waitInteractionDone();
1039:
1040: // check that the history contains the correct value
1041: assertEquals(
1042: "History and getHistoryAsString should be the same.",
1043: s1 + newLine + s2 + newLine + s3 + newLine, _model
1044: .getHistoryAsString());
1045: String delim = History.INTERACTION_SEPARATOR + newLine;
1046: assertEquals(
1047: "History and getHistoryAsStringWithSemicolons don't match up correctly.",
1048: s1 + delim + s2 + delim + s3 + delim, _model
1049: .getHistoryAsStringWithSemicolons());
1050: listener.assertInteractionEndCount(3);
1051: listener.assertInteractionStartCount(3);
1052: _model.saveHistory(fs);
1053:
1054: // check that the file contains the correct value
1055: assertEquals("contents of saved file",
1056: History.HISTORY_FORMAT_VERSION_2 + s1 + delim + s2
1057: + delim + s3 + delim, IOUtil.toString(f));
1058:
1059: _model.clearHistory();
1060: // confirm that the history is clear
1061: assertEquals("History is not clear", "", _model
1062: .getHistoryAsString());
1063:
1064: listener.logInteractionStart();
1065: _model.loadHistory(fs);
1066: listener.waitInteractionDone();
1067:
1068: // check that output of loaded history is correct
1069: ConsoleDocument con = _model.getConsoleDocument();
1070: assertEquals("Output of loaded history is not correct",
1071: "x = 5", con.getDocText(0, con.getLength()).trim());
1072: listener.assertInteractionStartCount(4);
1073: listener.assertInteractionEndCount(4);
1074: _model.removeListener(listener);
1075:
1076: _log.log("testSaveClearAndLoadHistory completed");
1077: }
1078:
1079: /**
1080: * Loads two history files, one whose statements end in semicolons, and one whose statements do not.
1081: * Makes sure that it doesn't matter.
1082: */
1083: public void testLoadHistoryWithAndWithoutSemicolons()
1084: throws IOException, EditDocumentException,
1085: InterruptedException {
1086:
1087: InteractionListener listener = new InteractionListener();
1088: _model.addListener(listener);
1089: File f1 = tempFile(1);
1090: File f2 = tempFile(2);
1091: FileSelector fs1 = new FileSelector(f1);
1092: FileSelector fs2 = new FileSelector(f2);
1093: String s1 = "int x = 5;";
1094: String s2 = "System.out.println(\"x = \" + x)";
1095: String s3 = "x = 5;";
1096: String s4 = "System.out.println(\"x = \" + x)";
1097: IOUtil.writeStringToFile(f1, s1 + '\n' + s2 + '\n');
1098: IOUtil.writeStringToFile(f2, s3 + '\n' + s4 + '\n');
1099:
1100: listener.assertInteractionStartCount(0);
1101: _model.loadHistory(fs1);
1102: listener.waitInteractionDone();
1103:
1104: listener.logInteractionStart();
1105: _model.loadHistory(fs2);
1106: listener.waitInteractionDone();
1107:
1108: // check that output of loaded history is correct
1109: ConsoleDocument con = _model.getConsoleDocument();
1110: assertEquals("Output of loaded history is not correct: "
1111: + con.getDocText(0, con.getLength()).trim(), "x = 5"
1112: + StringOps.EOL + "x = 5", con.getDocText(0,
1113: con.getLength()).trim());
1114:
1115: _log.log("testLoadHistoryWithAndWithoutSemicolons completed");
1116: }
1117:
1118: /** Test for the possibility that the file has been moved or deleted
1119: * since it was last referenced
1120: */
1121: public void testFileMovedWhenTriedToSave()
1122: throws BadLocationException, IOException {
1123:
1124: OpenDefinitionsDocument doc = setupDocument(FOO_TEXT);
1125: final File file = tempFile();
1126:
1127: doc.saveFile(new FileSelector(file));
1128:
1129: TestListener listener = new TestListener();
1130:
1131: _model.addListener(listener);
1132:
1133: file.delete();
1134: changeDocumentText(BAR_TEXT, doc);
1135: try {
1136: doc.saveFile(new WarningFileSelector(file));
1137: fail("Save file should have thrown an exception");
1138: } catch (GlobalModelTestCase.FileMovedWarningException fme) {
1139: // this is expected to occur:
1140: // WarningFileSelector throws it in shouldSaveAfterFileMoved()
1141: }
1142:
1143: assertModified(true, doc);
1144: assertContents(BAR_TEXT, doc);
1145:
1146: _log.log("testFileMovedWhenTriedToSave completed");
1147: }
1148:
1149: /** Tests that input can be written to and read from the console correctly. */
1150: public void testConsoleInput() throws EditDocumentException {
1151: _model.getInteractionsModel().setInputListener(
1152: new InputListener() {
1153: int n = 0;
1154:
1155: public String getConsoleInput() {
1156: n++;
1157: if (n > 1)
1158: throw new IllegalStateException(
1159: "Input should only be requested once!");
1160: return "input\n"; // '\n' is used becuae this input is generated by Swing processing of keystrokes
1161: }
1162: });
1163:
1164: String result = interpret("System.in.read()");
1165: String expected = /* DefaultInteractionsModel.INPUT_REQUIRED_MESSAGE + */String
1166: .valueOf((int) 'i');
1167: assertEquals(
1168: "read() should prompt for input and return the first byte of \"input\"",
1169: expected, result);
1170:
1171: interpret("import java.io.*;");
1172: interpret("br = new BufferedReader(new InputStreamReader(System.in))");
1173: result = interpret("br.readLine()");
1174: assertEquals(
1175: "readLine() should return the rest of \"input\" without prompting for input",
1176: "\"nput\"", result);
1177:
1178: _log.log("testConsoleInput completed");
1179: }
1180:
1181: class TestIOListener extends TestListener {
1182: public synchronized void fileOpened(OpenDefinitionsDocument doc) {
1183: openCount++;
1184: }
1185:
1186: public synchronized void fileClosed(OpenDefinitionsDocument doc) {
1187: closeCount++;
1188: }
1189: }
1190:
1191: class TestFileIOListener extends TestIOListener {
1192: File _expected;
1193:
1194: TestFileIOListener(File f) {
1195: _expected = f;
1196: }
1197:
1198: public void fileOpened(OpenDefinitionsDocument doc) {
1199: super .fileOpened(doc);
1200: File file = null;
1201: try {
1202: file = doc.getFile();
1203: } catch (FileMovedException fme) {
1204: fail("file does not exist");
1205: } // We know file should exist
1206: assertEquals("file to open", IOUtil
1207: .attemptCanonicalFile(_expected), IOUtil
1208: .attemptCanonicalFile(file));
1209: }
1210: }
1211: }
|