This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 103467
Collapse All | Expand All

(-)a/openide.text/test/unit/src/org/openide/text/UndoRedoWrappingCooperationTest.java (+561 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * Contributor(s):
25
 *
26
 * The Original Software is NetBeans. The Initial Developer of the Original
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
 * Microsystems, Inc. All Rights Reserved.
29
 *
30
 * If you wish your version of this file to be governed by only the CDDL
31
 * or only the GPL Version 2, indicate your decision by adding
32
 * "[Contributor] elects to include this software in this distribution
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
34
 * single choice of license, a recipient has the option to distribute
35
 * your version of this file under either the CDDL, the GPL Version 2 or
36
 * to extend the choice of license to its licensees as provided above.
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
38
 * Version 2 license, then the option applies only if the new code is
39
 * made subject to such option by the copyright holder.
40
 */
41
42
43
package org.openide.text;
44
45
46
47
import java.io.IOException;
48
import java.util.logging.Level;
49
import java.util.logging.Logger;
50
import javax.swing.event.UndoableEditEvent;
51
import javax.swing.event.UndoableEditListener;
52
import javax.swing.text.*;
53
import javax.swing.undo.CompoundEdit;
54
import javax.swing.undo.UndoableEdit;
55
import org.netbeans.junit.*;
56
import org.openide.awt.UndoRedo;
57
import org.openide.util.Exceptions;
58
59
/**
60
 * Testing CES's UndoGroupManager; BEGIN_COMIT_GROUP, END_COMIT_GROUP
61
 *
62
 * Also included are tests testSaveDocumentErrorCase and testRedoAfterSave.
63
 * They fail for some base CES functionality. They could be moved
64
 * to UndoRedoCooperationTest.
65
 *
66
 * @author  Ernie Rael
67
 */
68
public class UndoRedoWrappingCooperationTest extends NbTestCase implements CloneableEditorSupport.Env {
69
    static {
70
        System.setProperty("org.openide.windows.DummyWindowManager.VISIBLE", "false");
71
    }
72
    /** the support to work with */
73
    private CES support;
74
    // Env variables
75
    private String content = "Hello";
76
    private boolean valid = true;
77
    private boolean modified = false;
78
    /** if not null contains message why this document cannot be modified */
79
    private String cannotBeModified;
80
    private java.util.Date date = new java.util.Date ();
81
    private java.util.List/*<java.beans.PropertyChangeListener>*/ propL = new java.util.ArrayList ();
82
    private java.beans.VetoableChangeListener vetoL;
83
    
84
    /** Creates new TextTest */
85
    public UndoRedoWrappingCooperationTest (String s) {
86
        super(s);
87
    }
88
    
89
    protected javax.swing.text.EditorKit createEditorKit() {
90
        return new NbLikeEditorKit();
91
    }
92
93
    // Use these methods with the UndoRedoGroup patch
94
    CompoundEdit beginChunk(Document d) {
95
        // ur().beginUndoGroup();
96
        sendUndoableEdit(d, CloneableEditorSupport.BEGIN_COMIT_GROUP);
97
        return null;
98
    }
99
    
100
    void endChunk(Document d, CompoundEdit ce) {
101
        // ur().endUndoGroup();
102
        sendUndoableEdit(d, CloneableEditorSupport.END_COMIT_GROUP);
103
    }
104
105
    void sendUndoableEdit(Document d, UndoableEdit ue) {
106
        if(d instanceof AbstractDocument) {
107
            UndoableEditListener[] uels = ((AbstractDocument)d).getUndoableEditListeners();
108
            UndoableEditEvent ev = new UndoableEditEvent(d, ue);
109
            for(UndoableEditListener uel : uels) {
110
                uel.undoableEditHappened(ev);
111
            }
112
        }
113
    }
114
115
    // Use these methods with compound edit implementation
116
    // CompoundEdit beginChunk(Document d) {
117
    //     CompoundEdit ce = new CompoundEdit();
118
    //     support.getUndoRedo().undoableEditHappened
119
    //             (new UndoableEditEvent(d, ce));
120
    //     return ce;
121
    // }
122
123
    // void endChunk(Document d, CompoundEdit ce) {
124
    //     ce.end();
125
    // }
126
127
    UndoRedo.Manager ur() {
128
        return support.getUndoRedo();
129
    }
130
131
    protected void setUp () {
132
        support = new CES (this, org.openide.util.Lookup.EMPTY);
133
    }
134
135
    public void testTrivialChunk() throws Exception {
136
        content = "";
137
        StyledDocument d = support.openDocument();
138
139
        // same operations as testSingleChunk,
140
        // but don't test modified/canUndo/canRedo state
141
142
        CompoundEdit ce = beginChunk(d);
143
        d.insertString(d.getLength(), "a", null);
144
        d.insertString(d.getLength(), "b", null);
145
        endChunk(d, ce);
146
147
        assertEquals("data", "ab", d.getText(0, d.getLength()));
148
149
        ur().undo();
150
        assertEquals("after undo data", "", d.getText(0, d.getLength()));
151
152
        ur().redo();
153
        assertEquals("after redo data", "ab", d.getText(0, d.getLength()));
154
    }
155
156
    public void testSingleChunk() throws Exception {
157
        content = "";
158
        StyledDocument d = support.openDocument();
159
        assertFalse("initially: not modified", support.isModified());
160
        assertFalse("initially: no undo", ur().canUndo());
161
        assertFalse("initially: no redo", ur().canRedo());
162
163
        CompoundEdit ce = beginChunk(d);
164
        assertFalse("start chunk: not modified", support.isModified());
165
        assertFalse("start chunk: no undo", ur().canUndo());
166
        assertFalse("start chunk: no redo", ur().canRedo());
167
168
        d.insertString(d.getLength(), "a", null);
169
        assertTrue("insert: modified", support.isModified());
170
        assertTrue("insert: can undo", ur().canUndo());
171
        assertFalse("insert: no redo", ur().canRedo());
172
173
        d.insertString(d.getLength(), "b", null);
174
        endChunk(d, ce);
175
        assertEquals("chunk: data", "ab", d.getText(0, d.getLength()));
176
        assertTrue("endChunk: modified", support.isModified());
177
        assertTrue("endChunk: can undo", ur().canUndo());
178
        assertFalse("endChunk: no redo", ur().canRedo());
179
180
        ur().undo();
181
        assertEquals("after undo: data", "", d.getText(0, d.getLength()));
182
        assertFalse("undo: not modified", support.isModified());
183
        assertFalse("undo: no undo", ur().canUndo());
184
        assertTrue("undo: can redo", ur().canRedo());
185
186
        ur().redo();
187
        assertEquals("after redo: data", "ab", d.getText(0, d.getLength()));
188
        assertTrue("redo: modified", support.isModified());
189
        assertTrue("redo: can undo", ur().canUndo());
190
        assertFalse("redo: no redo", ur().canRedo());
191
    }
192
193
    /** this also tests mixing regular and chunks */
194
    public void testExtraEndChunk() throws Exception {
195
        content = "";
196
        StyledDocument d = support.openDocument();
197
198
        CompoundEdit ce = beginChunk(d);
199
200
        d.insertString(d.getLength(), "a", null);
201
        d.insertString(d.getLength(), "b", null);
202
203
        endChunk(d, ce);
204
        assertEquals("chunk: data", "ab", d.getText(0, d.getLength()));
205
206
        endChunk(d, ce);
207
        endChunk(d, ce);
208
209
        assertEquals("extraEnd: data", "ab", d.getText(0, d.getLength()));
210
        assertTrue("extraEnd: modified", support.isModified());
211
        assertTrue("extraEnd: can undo", ur().canUndo());
212
        assertFalse("extraEnd: no redo", ur().canRedo());
213
214
        d.insertString(d.getLength(), "c", null);
215
        d.insertString(d.getLength(), "d", null);
216
        endChunk(d, ce);
217
        assertEquals("extraEnd2: data", "abcd", d.getText(0, d.getLength()));
218
        ur().undo();
219
        endChunk(d, ce);
220
        assertEquals("undo1: data", "abc", d.getText(0, d.getLength()));
221
        ur().undo();
222
        assertEquals("undo2: data", "ab", d.getText(0, d.getLength()));
223
        ur().undo();
224
        endChunk(d, ce);
225
        assertEquals("undo3: data", "", d.getText(0, d.getLength()));
226
        ur().redo();
227
        assertEquals("redo1: data", "ab", d.getText(0, d.getLength()));
228
        ur().redo();
229
        endChunk(d, ce);
230
        assertEquals("redo2: data", "abc", d.getText(0, d.getLength()));
231
        ur().redo();
232
        assertEquals("redo3: data", "abcd", d.getText(0, d.getLength()));
233
    }
234
235
    public void testUndoRedoWhileActiveChunk() throws Exception {
236
        content = "";
237
        StyledDocument d = support.openDocument();
238
        CompoundEdit ce = beginChunk(d);
239
        d.insertString(d.getLength(), "a", null);
240
        d.insertString(d.getLength(), "b", null);
241
242
        assertEquals("before undo: data", "ab", d.getText(0, d.getLength()));
243
244
        ur().undo();
245
246
        // These asserts assume that an undo in the middle of a chunk
247
        // is an undo on the whole chunk so far.
248
249
        assertEquals("after undo: data", "", d.getText(0, d.getLength()));
250
        assertFalse("after undo: not modified", support.isModified());
251
        assertFalse("after undo: no undo", ur().canUndo());
252
        assertTrue("after undo: can redo", ur().canRedo());
253
254
        // note still in the chunk.
255
256
        ur().redo();
257
        assertEquals("after redo: data", "ab", d.getText(0, d.getLength()));
258
        assertTrue("after redo: modified", support.isModified());
259
        assertTrue("after redo: can undo", ur().canUndo());
260
        assertFalse("after redo: no redo", ur().canRedo());
261
262
        ur().undo(); 
263
        assertEquals("after undo: data", "", d.getText(0, d.getLength()));
264
265
        // note still in the chunk.
266
267
        d.insertString(d.getLength(), "c", null);
268
        d.insertString(d.getLength(), "d", null);
269
        endChunk(d, ce);
270
271
        assertEquals("after endChunk: data", "cd", d.getText(0, d.getLength()));
272
        assertTrue("after endChunk: modified", support.isModified());
273
        assertTrue("after endChunk: can undo", ur().canUndo());
274
        assertFalse("after endChunk: no redo", ur().canRedo());
275
276
        
277
        ur().undo();
278
        assertEquals("undo after endChunk: data", "", d.getText(0, d.getLength()));
279
        assertFalse("undo after endChunk: not modified", support.isModified());
280
        assertFalse("undo after endChunk: no undo", ur().canUndo());
281
        assertTrue("undo after endChunk: can redo", ur().canRedo());
282
    }
283
284
    public void testSaveDocumentWhileActiveChunkCommon(boolean doFailCase) throws Exception {
285
        content = "";
286
        StyledDocument d = support.openDocument();
287
        CompoundEdit ce = beginChunk(d);
288
        d.insertString(d.getLength(), "a", null);
289
        d.insertString(d.getLength(), "b", null);
290
291
        support.saveDocument (); // creates a separate undoable chunk
292
        assertFalse("save: not modified", support.isModified());
293
        assertTrue("save: can undo", ur().canUndo());
294
        assertFalse("save: no redo", ur().canRedo());
295
296
        d.insertString(d.getLength(), "c", null);
297
        d.insertString(d.getLength(), "d", null);
298
        endChunk(d, ce);
299
300
        assertEquals("insert, after save: data", "abcd", d.getText(0, d.getLength()));
301
        assertTrue("insert, after save: modified", support.isModified());
302
        assertTrue("insert, after save: can undo", ur().canUndo());
303
        assertFalse("insert, after save: no redo", ur().canRedo());
304
305
        ur().undo();
306
        assertEquals("undo, at save: data", "ab", d.getText(0, d.getLength()));
307
        assertFalse("undo, at save: not modified", support.isModified());
308
        assertTrue("undo, at save: can undo", ur().canUndo());
309
        assertTrue("undo, at save: can redo", ur().canRedo());
310
311
        ur().undo();
312
        assertEquals("undo, before save: data", "", d.getText(0, d.getLength()));
313
314
        if(doFailCase) {
315
            // ****************************************************************
316
            // CES BUG???
317
            assertTrue("undo, before save: modified", support.isModified());
318
            // ****************************************************************
319
        }
320
321
        assertFalse("undo, before save: can undo", ur().canUndo());
322
        assertTrue("undo, before save: can redo", ur().canRedo());
323
324
        ur().redo();
325
        assertEquals("redo, at save: data", "ab", d.getText(0, d.getLength()));
326
        assertFalse("redo, at save: not modified", support.isModified());
327
        assertTrue("redo, at save: can undo", ur().canUndo());
328
        assertTrue("redo, at save: can redo", ur().canRedo());
329
    }
330
331
    public void testSaveDocumentWhileActiveChunk() throws Exception {
332
        testSaveDocumentWhileActiveChunkCommon(false);
333
    }
334
335
    // This fails, below is "testSaveDocumentErrorCase" without chunking,
336
    // it also fails.
337
    // public void testSaveDocumentWhileActiveChunkErroCase() throws Exception {
338
    //     testSaveDocumentWhileActiveChunkCommon(true);
339
    // }
340
341
    public void testNestedChunks() throws Exception {
342
        content = "";
343
        StyledDocument d = support.openDocument();
344
        CompoundEdit ce1 = beginChunk(d);
345
        d.insertString(d.getLength(), "a", null);
346
        d.insertString(d.getLength(), "b", null);
347
348
        CompoundEdit ce2 = beginChunk(d); // creates a separate undoable chunk
349
350
        d.insertString(d.getLength(), "c", null);
351
        d.insertString(d.getLength(), "d", null);
352
353
        endChunk(d, ce1);
354
355
        d.insertString(d.getLength(), "e", null);
356
        d.insertString(d.getLength(), "f", null);
357
358
        endChunk(d, ce2);
359
360
        assertEquals("data", "abcdef", d.getText(0, d.getLength()));
361
362
        // following fails if nesting not supported
363
        ur().undo();
364
        assertEquals("undo1", "abcd", d.getText(0, d.getLength()));
365
366
        ur().undo();
367
        assertEquals("undo2", "ab", d.getText(0, d.getLength()));
368
369
        ur().undo();
370
        assertEquals("undo3", "", d.getText(0, d.getLength()));
371
    }
372
373
    // This is testSaveDocumentWhileActiveChunk WITHOUT chunking
374
    public void testSaveDocumentCommon(boolean doFailCase) throws Exception {
375
        content = "";
376
        StyledDocument d = support.openDocument();
377
        d.insertString(d.getLength(), "a", null);
378
379
        support.saveDocument (); // creates a separate undoable chunk
380
        assertFalse("save: not modified", support.isModified());
381
        assertTrue("save: can undo", ur().canUndo());
382
        assertFalse("save: no redo", ur().canRedo());
383
384
        d.insertString(d.getLength(), "b", null);
385
386
        assertEquals("insert, after save: data", "ab", d.getText(0, d.getLength()));
387
        assertTrue("insert, after save: modified", support.isModified());
388
        assertTrue("insert, after save: can undo", ur().canUndo());
389
        assertFalse("insert, after save: no redo", ur().canRedo());
390
391
        ur().undo();
392
        assertEquals("undo, at save: data", "a", d.getText(0, d.getLength()));
393
        assertFalse("undo, at save: not modified", support.isModified());
394
        assertTrue("undo, at save: can undo", ur().canUndo());
395
        assertTrue("undo, at save: can redo", ur().canRedo());
396
397
        ur().undo();
398
        assertEquals("undo, before save: data", "", d.getText(0, d.getLength()));
399
400
        if(doFailCase) {
401
            // ****************************************************************
402
            // CES BUG???
403
            assertTrue("undo, before save: modified", support.isModified());
404
            // ****************************************************************
405
        }
406
407
        assertFalse("undo, before save: can undo", ur().canUndo());
408
        assertTrue("undo, before save: can redo", ur().canRedo());
409
410
        ur().redo();
411
        assertEquals("redo, at save: data", "a", d.getText(0, d.getLength()));
412
        assertFalse("redo, at save: not modified", support.isModified());
413
        assertTrue("redo, at save: can undo", ur().canUndo());
414
        assertTrue("redo, at save: can redo", ur().canRedo());
415
    }
416
417
    public void testSaveDocument() throws Exception {
418
        testSaveDocumentCommon(false);
419
    }
420
421
    public void testSaveDocumentErrorCase() throws Exception {
422
        testSaveDocumentCommon(true);
423
    }
424
425
    public void testRedoAfterSave() throws Exception {
426
        content = "";
427
        StyledDocument d = support.openDocument();
428
        d.insertString(d.getLength(), "a", null);
429
430
        d.insertString(d.getLength(), "b", null);
431
432
        assertEquals("insert: data", "ab", d.getText(0, d.getLength()));
433
        assertTrue("insert: modified", support.isModified());
434
        assertTrue("insert: can undo", ur().canUndo());
435
        assertFalse("insert: no redo", ur().canRedo());
436
437
        ur().undo();
438
        assertEquals("undo: data", "a", d.getText(0, d.getLength()));
439
        assertTrue("undo: modified", support.isModified());
440
        assertTrue("undo: can undo", ur().canUndo());
441
        assertTrue("undo: can redo", ur().canRedo());
442
443
        support.saveDocument ();
444
        assertFalse("save: not modified", support.isModified());
445
        assertTrue("save: can undo", ur().canUndo());
446
        assertTrue("save: can redo", ur().canRedo());
447
448
        ur().redo();
449
        assertEquals("redo: data", "ab", d.getText(0, d.getLength()));
450
        assertTrue("redo: modified", support.isModified());
451
        assertTrue("redo: can undo", ur().canUndo());
452
        assertFalse("redo: no redo", ur().canRedo());
453
    }
454
    
455
    //
456
    // Implementation of the CloneableEditorSupport.Env
457
    //
458
    
459
    public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener l) {
460
        propL.add (l);
461
    }    
462
    public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener l) {
463
        propL.remove (l);
464
    }
465
    
466
    public synchronized void addVetoableChangeListener(java.beans.VetoableChangeListener l) {
467
        assertNull ("This is the first veto listener", vetoL);
468
        vetoL = l;
469
    }
470
    public void removeVetoableChangeListener(java.beans.VetoableChangeListener l) {
471
        assertEquals ("Removing the right veto one", vetoL, l);
472
        vetoL = null;
473
    }
474
    
475
    public org.openide.windows.CloneableOpenSupport findCloneableOpenSupport() {
476
        return support;
477
    }
478
    
479
    public String getMimeType() {
480
        return "text/plain";
481
    }
482
    
483
    public java.util.Date getTime() {
484
        return date;
485
    }
486
    
487
    public java.io.InputStream inputStream() throws java.io.IOException {
488
        return new java.io.ByteArrayInputStream (content.getBytes ());
489
    }
490
    public java.io.OutputStream outputStream() throws java.io.IOException {
491
        class ContentStream extends java.io.ByteArrayOutputStream {
492
            public void close () throws java.io.IOException {
493
                super.close ();
494
                content = new String (toByteArray ());
495
            }
496
        }
497
        
498
        return new ContentStream ();
499
    }
500
    
501
    public boolean isValid() {
502
        return valid;
503
    }
504
    
505
    public boolean isModified() {
506
        return modified;
507
    }
508
509
    public void markModified() throws java.io.IOException {
510
        if (cannotBeModified != null) {
511
            IOException e = new IOException ();
512
            Exceptions.attachLocalizedMessage(e, cannotBeModified);
513
            throw e;
514
        }
515
        
516
        modified = true;
517
    }
518
    
519
    public void unmarkModified() {
520
        modified = false;
521
    }
522
523
    /** Implementation of the CES */
524
    private final class CES extends CloneableEditorSupport {
525
        public boolean plain;
526
        
527
        
528
        public CES (Env env, org.openide.util.Lookup l) {
529
            super (env, l);
530
        }
531
        
532
        protected String messageName() {
533
            return "Name";
534
        }
535
        
536
        protected String messageOpened() {
537
            return "Opened";
538
        }
539
        
540
        protected String messageOpening() {
541
            return "Opening";
542
        }
543
        
544
        protected String messageSave() {
545
            return "Save";
546
        }
547
        
548
        protected String messageToolTip() {
549
            return "ToolTip";
550
        }        
551
552
        protected javax.swing.text.EditorKit createEditorKit() {
553
            if (plain) {
554
                return super.createEditorKit ();
555
            } else {
556
                return UndoRedoWrappingCooperationTest.this.createEditorKit ();
557
            }
558
        }
559
    } // end of CES
560
561
}

Return to bug 103467