001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.drjava.model.definitions.reducedmodel;
038:
039: import junit.framework.*;
040:
041: /**
042: * Test the interactions between double quotes and backslashes.
043: * @version $Id: BackSlashTest.java 4255 2007-08-28 19:17:37Z mgricken $
044: */
045: public final class BackSlashTest extends BraceReductionTestCase
046: implements ReducedModelStates {
047:
048: protected ReducedModelControl model0;
049: protected ReducedModelControl model1;
050: protected ReducedModelControl model2;
051:
052: /**
053: * Initializes the reduced models used in the tests.
054: */
055: protected void setUp() throws Exception {
056: super .setUp();
057: model0 = new ReducedModelControl();
058: model1 = new ReducedModelControl();
059: model2 = new ReducedModelControl();
060: }
061:
062: /**
063: * Creates a test suite for JUnit to use.
064: * @return a test suite for JUnit
065: */
066: public static Test suite() {
067: return new TestSuite(BackSlashTest.class);
068: }
069:
070: /**
071: * Convenience function to insert a number of non-special characters into a reduced model.
072: * @param model the model being modified
073: * @param size the number of characters being inserted
074: */
075: protected void insertGap(BraceReduction model, int size) {
076: for (int i = 0; i < size; i++) {
077: model.insertChar(' ');
078: }
079: }
080:
081: /**
082: * Tests the relationship between backslash characters and quote characters.
083: * It focuses on the case where the backslash is inserted first before the quote.
084: */
085: public void testInsideQuotePrevious() {
086: model1.insertChar('\"');
087: model1.insertChar('\\');
088: model1.insertChar('\"');
089: model1.move(-2);
090: // "#\"
091: assertEquals("#0.0", "\\\"", model1.currentToken().getType());
092: assertEquals("#0.1", INSIDE_DOUBLE_QUOTE,
093: stateOfCurrentToken(model1));
094: model1.move(2);
095: model1.insertChar('\"');
096: model1.move(-1);
097: // "\"#"
098: assertEquals("#1.0", "\"", model1.currentToken().getType());
099: assertEquals("#1.1", FREE, stateOfCurrentToken(model1));
100: assertTrue("#1.2", model1.currentToken().isClosed());
101: model1.move(1);
102: model1.insertChar('\"');
103: model1.insertChar('\\');
104: model1.insertChar('\\');
105: model1.move(-2);
106: // "\"""#\\
107: assertEquals("#2.0", "\\\\", model1.currentToken().getType());
108: assertEquals("#2.1", INSIDE_DOUBLE_QUOTE,
109: stateOfCurrentToken(model1));
110: model1.move(2);
111: model1.insertChar('\\');
112: model1.move(-1);
113: // "\"""\\#\
114: assertEquals("#3.0", "\\", model1.currentToken().getType());
115: assertEquals("#3.1", INSIDE_DOUBLE_QUOTE,
116: stateOfCurrentToken(model1));
117: model1.move(1);
118: model1.insertChar('\"');
119: model1.move(-1);
120: // "\"""\\\#"
121: assertEquals("#4.0", "\\\"", model1.currentToken().getType());
122: assertEquals("#4.1", INSIDE_DOUBLE_QUOTE,
123: stateOfCurrentToken(model1));
124: }
125:
126: /**
127: * Tests the relationship between backslashes and quotes.
128: * Focuses on the case where a backslash is inserted and turns a regular quote
129: * into an escaped quote.
130: */
131: public void testInsideQuoteNext() {
132: model1.insertChar('\"');
133: model1.insertChar('\"');
134: model1.move(-1);
135: model1.insertChar('\\');
136: assertEquals("#0.0", "\\\"", model1.currentToken().getType());
137: assertEquals("#0.1", INSIDE_DOUBLE_QUOTE,
138: stateOfCurrentToken(model1));
139: assertEquals("#0.2", 1, model1.getBlockOffset());
140: model1.move(1);
141: model1.insertChar('\"');
142: model1.move(-1);
143: assertEquals("#1.0", "\"", model1.currentToken().getType());
144: assertEquals("#1.1", FREE, stateOfCurrentToken(model1));
145: assertTrue("#1.2", model1.currentToken().isClosed());
146: model1.move(1);
147: model1.insertChar('\"');
148: model1.insertChar('\\');
149: model1.move(-1);
150: model1.insertChar('\\');
151: assertEquals("#2.0", "\\\\", model1.currentToken().getType());
152: assertEquals("#2.1", INSIDE_DOUBLE_QUOTE,
153: stateOfCurrentToken(model1));
154: assertEquals("#2.2", 6, model1.absOffset());
155: model1.move(-2);
156: model1.insertChar('{');
157: model1.move(-1);
158: assertEquals("#3.0", "{", model1.currentToken().getType());
159: assertEquals("#3.1", FREE, stateOfCurrentToken(model1));
160: model1.move(1);
161: model1.move(3);
162: model1.insertChar('\"');
163: model1.move(-1);
164: assertEquals("#4.0", "\"", model1.currentToken().getType());
165: assertEquals("#4.1", FREE, stateOfCurrentToken(model1));
166: assertTrue("#4.2", model1.currentToken().isClosed());
167: model1.insertChar('\\');
168: assertEquals("#5.0", "\\\"", model1.currentToken().getType());
169: assertEquals("#5.1", INSIDE_DOUBLE_QUOTE,
170: stateOfCurrentToken(model1));
171: assertEquals("#5.2", 1, model1.getBlockOffset());
172: }
173:
174: /**
175: * Tests the case when a backslash is inserted before two backslashes.
176: * The existing double escape is broken and the first two backslashes become
177: * a double escape with the third backslash ending up alone.
178: */
179: public void testBackSlashBeforeDoubleEscape() {
180: model1.insertChar('\\');
181: model1.insertChar('\\');
182: model1.move(-2);
183: model1.insertChar('\\');
184: assertEquals("#0.0", "\\\\", model1.currentToken().getType());
185: assertEquals("#0.1", 2, model1.currentToken().getSize());
186: model1.move(1);
187: assertEquals("#0.2", "\\", model1.currentToken().getType());
188: model2.insertChar('\\');
189: model2.insertChar('\"');
190: model2.move(-2);
191: model2.insertChar('\\');
192: assertEquals("#1.0", "\\\\", model2.currentToken().getType());
193: assertEquals("#1.1", 1, model2.absOffset());
194: model2.move(1);
195: assertEquals("#1.2", "\"", model2.currentToken().getType());
196: }
197:
198: /**
199: * Tests the case where a backslash breaks up two backslashes together.
200: * The newly inserted backslash and the first backslash form a new double escape
201: * and the second backslash in the previous double escape becomes free.
202: */
203: public void testInsertBetweenDoubleEscape() {
204: model1.insertChar('\\');
205: model1.insertChar('\\');
206: model1.move(-1);
207: model1.insertChar('\\');
208: model1.move(-2);
209: assertEquals("#0.0", "\\\\", model1.currentToken().getType());
210: model1.move(2);
211: assertEquals("#0.1", "\\", model1.currentToken().getType());
212: model2.insertChar('\\');
213: model2.insertChar('\"');
214: model2.move(-1);
215: model2.insertChar('\\');
216: model2.move(-2);
217: assertEquals("#1.0", "\\\\", model2.currentToken().getType());
218: model2.move(2);
219: assertEquals("#1.1", "\"", model2.currentToken().getType());
220: model0.insertChar('\\');
221: model0.insertChar('\\');
222: model0.move(-1);
223: model0.insertChar(')');
224: model0.move(-2);
225: assertEquals("#2.0", "\\", model0.currentToken().getType());
226: model0.move(1);
227: assertEquals("#2.1", ")", model0.currentToken().getType());
228: model0.move(1);
229: assertEquals("#2.2", "\\", model0.currentToken().getType());
230: model0.move(1);
231: model0.delete(-3);
232: model0.insertChar('\\');
233: model0.insertChar('\"');
234: model0.move(-1);
235: model0.insertChar(')');
236: model0.move(-2);
237: assertEquals("#3.0", "\\", model0.currentToken().getType());
238: model0.move(1);
239: assertEquals("#3.1", ")", model0.currentToken().getType());
240: model0.move(1);
241: assertEquals("#3.2", "\"", model0.currentToken().getType());
242: }
243:
244: /**
245: * Tests the case where deletion combines a backslash and a quote or two backslashes.
246: * The deletion of characters in between the two special characters brings them together
247: * and unites them into a 2-character special token.
248: */
249: public void testDeleteAndCombine() {
250: model0.insertChar('\\');
251: insertGap(model0, 2);
252: model0.insertChar('\"');
253: model0.move(-1);
254: assertEquals("#0.0", "\"", model0.currentToken().getType());
255: model0.delete(-2);
256: assertEquals("#1.0", "\\\"", model0.currentToken().getType());
257: assertEquals("#1.1", 1, model0.absOffset());
258: model0.delete(1);
259: insertGap(model0, 2);
260: model0.insertChar('\\');
261: model0.move(-1);
262: assertEquals("#2.0", "\\", model0.currentToken().getType());
263: model0.delete(-2);
264: assertEquals("#3.0", "\\\\", model0.currentToken().getType());
265: assertEquals("#3.1", 2, model0.currentToken().getSize());
266: }
267:
268: /**
269: * Tests more of the same sort of cases as found in testDeleteAndCombine().
270: */
271: public void testDeleteAndCombine2() {
272: model0.insertChar('\\');
273: model0.insertChar('\"');
274: model0.move(-1);
275: model0.delete(-1);
276: assertEquals("#0.0", "\"", model0.currentToken().getType());
277: assertEquals("#0.1", FREE, model0.getStateAtCurrent());
278: model1.insertChar('\\');
279: model1.insertChar('\\');
280: model1.delete(-1);
281: model1.move(-1);
282: assertEquals("#1.0", "\\", model1.currentToken().getType());
283: model1.move(1);
284: model1.insertChar('\\');
285: model1.move(-1);
286: model1.delete(-1);
287: assertEquals("#2.0", "\\", model1.currentToken().getType());
288: }
289:
290: /**
291: * More of the same sort of cases as found in testDeleteAndCombine().
292: */
293: public void testDeleteAndCombine3() {
294: model0.insertChar('\\');
295: model0.insertChar('\\');
296: insertGap(model0, 3);
297: model0.insertChar('\\');
298: model0.move(-1);
299: model0.delete(-4);
300: assertEquals("#0.0", "\\\\", model0.currentToken().getType());
301: assertEquals("#0.1", 1, model0.absOffset());
302: model1.insertChar('\\');
303: insertGap(model1, 3);
304: model1.insertChar('\\');
305: model1.insertChar('\"');
306: model1.move(-1);
307: model1.delete(-4);
308: assertEquals("#1.0", "\\\"", model1.currentToken().getType());
309: assertEquals("#1.1", 1, model1.absOffset());
310: }
311:
312: /**
313: * Tests cases where a long chain of backslashes and quotes can be all altered with a simple
314: * insertion or deletion of a special character.
315: */
316: public void testChainEffect() {
317: model0.insertChar('\"');
318: model0.insertChar('\\');
319: model0.insertChar('\"');
320: model0.insertChar('\"');
321: model0.insertChar('\"');
322: model0.insertChar('\\');
323: model0.insertChar('\"');
324: model0.insertChar('\"');
325: model0.insertChar('\"');
326: model0.insertChar('\\');
327: model0.insertChar('\"');
328: model0.insertChar('\"');
329: // "\"""\"""\""#
330: model0.move(-1);
331: assertEquals("#0.0", "\"", model0.currentToken().getType());
332: assertTrue("#0.1", model0.currentToken().isClosed());
333: model0.move(-2);
334: // "\"""\"""#\""
335: assertEquals("#1.0", "\\\"", model0.currentToken().getType());
336: assertEquals("#1.1", INSIDE_DOUBLE_QUOTE,
337: stateOfCurrentToken(model0));
338: model0.move(-1);
339: assertEquals("#1.2", "\"", model0.currentToken().getType());
340: assertEquals("#1.3", FREE, stateOfCurrentToken(model0));
341: assertTrue("#1.4", model0.currentToken().isOpen());
342: model0.move(1);
343: model0.insertChar('\\');
344: // "\"""\"""\#\""
345: assertEquals("#2.0", "\\\\", model0.currentToken().getType());
346: assertEquals("#2.1", INSIDE_DOUBLE_QUOTE,
347: stateOfCurrentToken(model0));
348: assertEquals("#2.2", 10, model0.absOffset());
349: model0.move(-2);
350: assertEquals("#2.3", "\"", model0.currentToken().getType());
351: assertEquals("#2.4", FREE, stateOfCurrentToken(model0));
352: assertTrue("#2.5", model0.currentToken().isOpen());
353: model0.move(3);
354: assertEquals("#2.6", "\"", model0.currentToken().getType());
355: assertEquals("#2.7", FREE, stateOfCurrentToken(model0));
356: assertTrue("#2.8", model0.currentToken().isClosed());
357: model0.move(-1);
358: model0.insertChar('\"');
359: // "\"""\"""\"#\""
360: assertEquals("#3.0", "\\\"", model0.currentToken().getType());
361: assertEquals("#3.1", INSIDE_DOUBLE_QUOTE,
362: stateOfCurrentToken(model0));
363: assertEquals("#3.2", 11, model0.absOffset());
364: model0.move(-2);
365: assertEquals("#3.3", "\\\"", model0.currentToken().getType());
366: assertEquals("#3.4", INSIDE_DOUBLE_QUOTE,
367: stateOfCurrentToken(model0));
368: model0.move(4);
369: assertEquals("#3.5", "\"", model0.currentToken().getType());
370: assertEquals("#3.6", FREE, stateOfCurrentToken(model0));
371: assertTrue("#3.7", model0.currentToken().isClosed());
372: model0.move(-12);
373: // "#\"""\"""\"\""
374: model0.delete(1);
375: // "#"""\"""\"\""
376: model0.move(-1);
377: // #""""\"""\"\""
378: assertEquals("#4.0", "\"", model0.currentToken().getType());
379: assertTrue("#4.1", model0.currentToken().isOpen());
380: assertEquals("#4.2", FREE, stateOfCurrentToken(model0));
381: model0.move(1);
382: // "#"""\"""\"\""
383: assertEquals("#4.3", "\"", model0.currentToken().getType());
384: assertTrue("#4.4", model0.currentToken().isClosed());
385: assertEquals("#4.5", FREE, stateOfCurrentToken(model0));
386: model0.move(1);
387: // ""#""\"""\"\""
388: assertEquals("#5.0", "\"", model0.currentToken().getType());
389: assertTrue("#5.1", model0.currentToken().isOpen());
390: assertEquals("#5.2", FREE, stateOfCurrentToken(model0));
391: model0.move(1);
392: // """#"\"""\"\""
393: assertEquals("#5.3", "\"", model0.currentToken().getType());
394: assertTrue("#5.4", model0.currentToken().isClosed());
395: assertEquals("#5.5", FREE, stateOfCurrentToken(model0));
396: model0.move(1);
397: // """"#\"""\"\""
398: assertEquals("#5.6", "\\\"", model0.currentToken().getType());
399: assertEquals("#5.7", FREE, stateOfCurrentToken(model0));
400: model0.move(2);
401: // """"\"#""\"\""
402: assertEquals("#6.0", "\"", model0.currentToken().getType());
403: assertTrue("#6.1", model0.currentToken().isOpen());
404: assertEquals("#6.2", FREE, stateOfCurrentToken(model0));
405: model0.move(1);
406: // """"\""#"\"\""
407: assertEquals("#6.3", "\"", model0.currentToken().getType());
408: assertTrue("#6.4", model0.currentToken().isClosed());
409: assertEquals("#6.5", FREE, stateOfCurrentToken(model0));
410: model0.move(1);
411: // """"\"""#\"\""
412: assertEquals("#6.6", "\\\"", model0.currentToken().getType());
413: assertEquals("#6.7", FREE, stateOfCurrentToken(model0));
414: model0.move(2);
415: // """"\"""\"#\""
416: assertEquals("#6.0", "\\\"", model0.currentToken().getType());
417: assertEquals("#6.1", FREE, stateOfCurrentToken(model0));
418: model0.move(2);
419: // """"\"""\"\"#"
420: assertEquals("#6.2", "\"", model0.currentToken().getType());
421: assertTrue("#6.3", model0.currentToken().isOpen());
422: assertEquals("#6.4", FREE, stateOfCurrentToken(model0));
423: }
424: }
|