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 (+563 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_COMMIT_GROUP, END_COMMIT_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_COMMIT_GROUP);
97
        return null;
98
    }
99
    
100
    void endChunk(Document d, CompoundEdit ce) {
101
        // ur().endUndoGroup();
102
        sendUndoableEdit(d, CloneableEditorSupport.END_COMMIT_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
    // NOTE: following fail is issue in CES
422
    public void testSaveDocumentErrorCase() throws Exception {
423
        testSaveDocumentCommon(true);
424
    }
425
426
    // NOTE: following fail is issue in CES
427
    public void testRedoAfterSave() throws Exception {
428
        content = "";
429
        StyledDocument d = support.openDocument();
430
        d.insertString(d.getLength(), "a", null);
431
432
        d.insertString(d.getLength(), "b", null);
433
434
        assertEquals("insert: data", "ab", d.getText(0, d.getLength()));
435
        assertTrue("insert: modified", support.isModified());
436
        assertTrue("insert: can undo", ur().canUndo());
437
        assertFalse("insert: no redo", ur().canRedo());
438
439
        ur().undo();
440
        assertEquals("undo: data", "a", d.getText(0, d.getLength()));
441
        assertTrue("undo: modified", support.isModified());
442
        assertTrue("undo: can undo", ur().canUndo());
443
        assertTrue("undo: can redo", ur().canRedo());
444
445
        support.saveDocument ();
446
        assertFalse("save: not modified", support.isModified());
447
        assertTrue("save: can undo", ur().canUndo());
448
        assertTrue("save: can redo", ur().canRedo());
449
450
        ur().redo();
451
        assertEquals("redo: data", "ab", d.getText(0, d.getLength()));
452
        assertTrue("redo: modified", support.isModified());
453
        assertTrue("redo: can undo", ur().canUndo());
454
        assertFalse("redo: no redo", ur().canRedo());
455
    }
456
    
457
    //
458
    // Implementation of the CloneableEditorSupport.Env
459
    //
460
    
461
    public synchronized void addPropertyChangeListener(java.beans.PropertyChangeListener l) {
462
        propL.add (l);
463
    }    
464
    public synchronized void removePropertyChangeListener(java.beans.PropertyChangeListener l) {
465
        propL.remove (l);
466
    }
467
    
468
    public synchronized void addVetoableChangeListener(java.beans.VetoableChangeListener l) {
469
        assertNull ("This is the first veto listener", vetoL);
470
        vetoL = l;
471
    }
472
    public void removeVetoableChangeListener(java.beans.VetoableChangeListener l) {
473
        assertEquals ("Removing the right veto one", vetoL, l);
474
        vetoL = null;
475
    }
476
    
477
    public org.openide.windows.CloneableOpenSupport findCloneableOpenSupport() {
478
        return support;
479
    }
480
    
481
    public String getMimeType() {
482
        return "text/plain";
483
    }
484
    
485
    public java.util.Date getTime() {
486
        return date;
487
    }
488
    
489
    public java.io.InputStream inputStream() throws java.io.IOException {
490
        return new java.io.ByteArrayInputStream (content.getBytes ());
491
    }
492
    public java.io.OutputStream outputStream() throws java.io.IOException {
493
        class ContentStream extends java.io.ByteArrayOutputStream {
494
            public void close () throws java.io.IOException {
495
                super.close ();
496
                content = new String (toByteArray ());
497
            }
498
        }
499
        
500
        return new ContentStream ();
501
    }
502
    
503
    public boolean isValid() {
504
        return valid;
505
    }
506
    
507
    public boolean isModified() {
508
        return modified;
509
    }
510
511
    public void markModified() throws java.io.IOException {
512
        if (cannotBeModified != null) {
513
            IOException e = new IOException ();
514
            Exceptions.attachLocalizedMessage(e, cannotBeModified);
515
            throw e;
516
        }
517
        
518
        modified = true;
519
    }
520
    
521
    public void unmarkModified() {
522
        modified = false;
523
    }
524
525
    /** Implementation of the CES */
526
    private final class CES extends CloneableEditorSupport {
527
        public boolean plain;
528
        
529
        
530
        public CES (Env env, org.openide.util.Lookup l) {
531
            super (env, l);
532
        }
533
        
534
        protected String messageName() {
535
            return "Name";
536
        }
537
        
538
        protected String messageOpened() {
539
            return "Opened";
540
        }
541
        
542
        protected String messageOpening() {
543
            return "Opening";
544
        }
545
        
546
        protected String messageSave() {
547
            return "Save";
548
        }
549
        
550
        protected String messageToolTip() {
551
            return "ToolTip";
552
        }        
553
554
        protected javax.swing.text.EditorKit createEditorKit() {
555
            if (plain) {
556
                return super.createEditorKit ();
557
            } else {
558
                return UndoRedoWrappingCooperationTest.this.createEditorKit ();
559
            }
560
        }
561
    } // end of CES
562
563
}

Return to bug 103467