View | Details | Raw Unified | Return to bug 93955 | Differences between
and this patch

Collapse All | Expand All

(-)leaks/org/eclipse/jdt/ui/tests/leaks/UndoManagerLeakTest.java (+1 lines)
Lines 72-77 Link Here
72
		internalTestRandomAccess();
72
		internalTestRandomAccess();
73
		internalTestRandomAccessAsCompound();
73
		internalTestRandomAccessAsCompound();
74
		
74
		
75
		fUndoManager.disconnect();
75
		fUndoManager= null;
76
		fUndoManager= null;
76
		
77
		
77
		fShell.dispose();
78
		fShell.dispose();
(-)ui/org/eclipse/jdt/ui/tests/LeakTestSuite.java (+2 lines)
Lines 14-19 Link Here
14
import junit.framework.TestSuite;
14
import junit.framework.TestSuite;
15
15
16
import org.eclipse.jdt.ui.tests.leaks.JavaLeakTest;
16
import org.eclipse.jdt.ui.tests.leaks.JavaLeakTest;
17
import org.eclipse.jdt.ui.tests.leaks.SharedUndoManagerLeakTest;
17
import org.eclipse.jdt.ui.tests.leaks.UndoManagerLeakTest;
18
import org.eclipse.jdt.ui.tests.leaks.UndoManagerLeakTest;
18
19
19
20
Lines 38-43 Link Here
38
	public LeakTestSuite() {
39
	public LeakTestSuite() {
39
		addTest(JavaLeakTest.suite());
40
		addTest(JavaLeakTest.suite());
40
		addTest(UndoManagerLeakTest.suite());
41
		addTest(UndoManagerLeakTest.suite());
42
		addTest(SharedUndoManagerLeakTest.suite());
41
	}
43
	}
42
	
44
	
43
}
45
}
(-)leaks/org/eclipse/jdt/ui/tests/leaks/SharedUndoManagerLeakTest.java (+269 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.ui.tests.leaks;
12
13
import junit.framework.Test;
14
import junit.framework.TestSuite;
15
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.widgets.Shell;
18
19
import org.eclipse.jface.text.BadLocationException;
20
import org.eclipse.jface.text.Document;
21
import org.eclipse.jface.text.DocumentUndoManager;
22
import org.eclipse.jface.text.IDocument;
23
import org.eclipse.jface.text.ITextViewer;
24
import org.eclipse.jface.text.IUndoManager;
25
import org.eclipse.jface.text.Position;
26
import org.eclipse.jface.text.SharedDocumentUndoManager;
27
import org.eclipse.jface.text.TextViewer;
28
29
import org.eclipse.jdt.ui.leaktest.LeakTestCase;
30
import org.eclipse.jdt.ui.leaktest.LeakTestSetup;
31
32
/**
33
 * Test for leaks in SharedDocumentUndoManager.
34
 * 
35
 * @since 3.2
36
 */
37
public class SharedUndoManagerLeakTest extends LeakTestCase {
38
39
	/** The maximum undo level. */
40
	private static final int MAX_UNDO_LEVEL = 256;
41
	
42
	/** The shell. */
43
	private Shell fShell;
44
	/** The text viewer. */
45
	private ITextViewer fTextViewer;
46
	/** The undo manager. */
47
	private IUndoManager fUndoManager;
48
49
	public static Test suite() {
50
		return new LeakTestSetup(new TestSuite(SharedUndoManagerLeakTest.class));
51
	}
52
	
53
	/*
54
	 * @see TestCase#TestCase(String)
55
	 */
56
	public SharedUndoManagerLeakTest(final String name) {
57
		super(name);	
58
	}
59
	
60
	/*
61
	 *  @see TestCase#setUp()
62
	 */
63
	protected void setUp() {
64
		fShell= new Shell();	
65
		fUndoManager= new SharedDocumentUndoManager(MAX_UNDO_LEVEL);
66
		fTextViewer= new TextViewer(fShell, SWT.NONE);
67
		fTextViewer.setUndoManager(fUndoManager);
68
		fUndoManager.connect(fTextViewer);
69
	}
70
	
71
	public void testLeak() throws Exception{
72
		// There is always a document instance around, hence a DocumentUndoManager.
73
		// So count instances first.
74
		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=61432
75
		int instanceCount = getInstanceCount(DocumentUndoManager.class);
76
		internalTestConvertLineDelimiters();
77
		internalTestRandomAccess();
78
		internalTestRandomAccessAsCompound();
79
		
80
		fUndoManager.disconnect();
81
		fUndoManager= null;
82
		
83
		fShell.dispose();
84
		fShell= null;
85
		
86
		fTextViewer= null;
87
		
88
		assertInstanceCount(TextViewer.class, 0);
89
		assertInstanceCount(SharedDocumentUndoManager.class, 0);
90
		assertInstanceCount(getSharedUndoManagersInnerClass("TextInputListener"), 0);
91
		assertInstanceCount(getSharedUndoManagersInnerClass("DocumentUndoListener"), 0);
92
		assertInstanceCount(getSharedUndoManagersInnerClass("KeyAndMouseListener"), 0);
93
94
		assertInstanceCount(DocumentUndoManager.class, instanceCount);
95
		assertInstanceCount(getDocumentUndoManagersInnerClass("DocumentListener"), 0);
96
		assertInstanceCount(getDocumentUndoManagersInnerClass("HistoryListener"), 0);
97
		
98
	}
99
	
100
	private Class getSharedUndoManagersInnerClass(String className) {
101
		try {
102
			return Class.forName("org.eclipse.jface.text.SharedDocumentUndoManager$" + className, true, getClass().getClassLoader());
103
		} catch (ClassNotFoundException e) {
104
			fail();
105
			return null;
106
		}
107
	}
108
	
109
	private Class getDocumentUndoManagersInnerClass(String className) {
110
		try {
111
			return Class.forName("org.eclipse.jface.text.DocumentUndoManager$" + className, true, getClass().getClassLoader());
112
		} catch (ClassNotFoundException e) {
113
			fail();
114
			return null;
115
		}
116
	}
117
118
119
	/**
120
	 * Test for line delimiter conversion.
121
	 */	
122
	private void internalTestConvertLineDelimiters() {
123
		final String original= "a\r\nb\r\n";
124
		final IDocument document= new Document(original);		
125
		fTextViewer.setDocument(document);
126
		
127
		try {
128
			document.replace(1, 2, "\n");
129
			document.replace(3, 2, "\n");
130
		} catch (BadLocationException e) {
131
			assertTrue(false);
132
		}
133
		
134
		assertTrue(fUndoManager.undoable());
135
		fUndoManager.undo();
136
		assertTrue(fUndoManager.undoable());
137
		fUndoManager.undo();
138
139
		final String reverted= document.get();
140
		
141
		assertEquals(original, reverted);
142
	}
143
144
	/**
145
	 * Randomly applies document changes.
146
	 */
147
	private void internalTestRandomAccess() {
148
		final int RANDOM_STRING_LENGTH= 50;
149
		final int RANDOM_REPLACE_COUNT= 100;
150
		
151
		assertTrue(RANDOM_REPLACE_COUNT >= 1);
152
		assertTrue(RANDOM_REPLACE_COUNT <= MAX_UNDO_LEVEL);
153
		
154
		String original= createRandomString(RANDOM_STRING_LENGTH);
155
		final IDocument document= new Document(original);
156
		fTextViewer.setDocument(document);
157
	
158
		doChange(document, RANDOM_REPLACE_COUNT);
159
		
160
		assertTrue(fUndoManager.undoable());
161
		while (fUndoManager.undoable())
162
			fUndoManager.undo();
163
			
164
		final String reverted= document.get();
165
166
		assertEquals(original, reverted);
167
	}
168
	
169
	private void doChange(IDocument document, int count) {
170
		try {
171
			for (int i= 0; i < count; i++) {
172
				final Position position= createRandomPositionPoisson(document.getLength());
173
				final String string= createRandomStringPoisson(4);
174
				document.replace(position.getOffset(), position.getLength(), string);
175
			}
176
		} catch (BadLocationException e) {
177
			assertTrue(false);
178
		}
179
	}
180
	
181
	private void internalTestRandomAccessAsCompound() {
182
		final int RANDOM_STRING_LENGTH= 50;
183
		final int RANDOM_REPLACE_COUNT= 100;
184
		
185
		assertTrue(RANDOM_REPLACE_COUNT >= 1);
186
		assertTrue(RANDOM_REPLACE_COUNT <= MAX_UNDO_LEVEL);
187
		
188
		String original= createRandomString(RANDOM_STRING_LENGTH);
189
		final IDocument document= new Document(original);
190
		fTextViewer.setDocument(document);
191
192
		fUndoManager.beginCompoundChange();		
193
		doChange(document, RANDOM_REPLACE_COUNT);
194
		fUndoManager.endCompoundChange();
195
196
		assertTrue(fUndoManager.undoable());
197
		while (fUndoManager.undoable())
198
			fUndoManager.undo();
199
		assertTrue(!fUndoManager.undoable());
200
			
201
		final String reverted= document.get();
202
203
		assertEquals(original, reverted);		
204
	}
205
206
	private static String createRandomString(int length) {
207
		final StringBuffer buffer= new StringBuffer();
208
		
209
		for (int i= 0; i < length; i++)
210
			buffer.append(getRandomCharacter());
211
212
		return buffer.toString();
213
	}
214
	
215
	private static final char getRandomCharacter() {
216
//		return Math.random() < 0.5
217
//			? '\r'
218
//			: '\n';
219
					
220
		// XXX must include \r, \n, \t
221
		return (char) (32 + 95 * Math.random());
222
	}
223
	
224
	private static String createRandomStringPoisson(int mean) {
225
		final int length= getRandomPoissonValue(2);
226
		return createRandomString(length);
227
	}
228
	
229
	private static Position createRandomPositionPoisson(int documentLength) {
230
231
		final float random= (float) Math.random();
232
		final int offset= (int) (random * (documentLength + 1));
233
234
		int length= getRandomPoissonValue(2);
235
		if (offset + length > documentLength)
236
			length= documentLength - offset;
237
			
238
		return new Position(offset, length);
239
	}
240
	
241
	private static int getRandomPoissonValue(int mean) {
242
		final int MAX_VALUE= 10;
243
244
		final float random= (float) Math.random();
245
		float probability= 0;
246
		int i= 0;
247
		while (probability < 1 && i < MAX_VALUE) {
248
			probability += getPoissonDistribution(mean, i);
249
			if (random <= probability)
250
				break;
251
			i++;
252
		}		
253
		return i;
254
	}
255
256
	private static float getPoissonDistribution(float lambda, int k) {
257
		return (float) (Math.exp(-lambda) * Math.pow(lambda, k) / faculty(k));
258
	}
259
	
260
	/**
261
	 * Returns the faculty of k.
262
	 */
263
	private static final int faculty(int k) {
264
		return k == 0
265
			? 1
266
			: k * faculty(k - 1);
267
	}
268
	
269
}

Return to bug 93955