Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 72c1cdda6f5138bccdc44dd4c9c65c6b048b48fb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/*******************************************************************************
 * Copyright (c) 2011, 2016 Broadcom Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * 		Broadcom Corporation - Initial API and implementation
 *******************************************************************************/

package org.eclipse.cdt.managedbuilder.testplugin;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
import org.eclipse.cdt.core.settings.model.ICProjectDescriptionManager;
import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.Job;

import junit.framework.TestCase;

/**
 * Abstract builder test which provides utility methods for:
 * <ul>
 * <li>Importing projects into the workspace</li>
 * <li>Adding expected resources to the delta verifier</li>
 * <li>Verifying the delta</li>
 * <li>Printing markers</li>
 * <li>Cleaning up the workspace at the end</li>
 * </ul>
 */
public abstract class AbstractBuilderTest extends TestCase {
	private static final boolean WINDOWS = java.io.File.separatorChar == '\\';

	static final String PATH = "builderTests";

	private String workspace;
	private List<IProject> projects;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		setAutoBuilding(false);
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		ResourceHelper.cleanUp(getName());
		// Bug 327126 Stop the indexer before tearing down so we don't deadlock
		Job.getJobManager().cancel(CCorePlugin.getPDOMManager());
		Job.getJobManager().join(CCorePlugin.getPDOMManager(), null);

		if (projects != null) {
			// Clean-up any projects we were using
			for (IProject project : projects) {
				project.delete(true, null);
			}
			projects.clear();
		}
	}

	/**
	 * Run a build of the specified kind, and verify that the resource changes that
	 * result match the expectations of the given verifier.
	 */
	protected void verifyBuild(final IProject project, final int kind, ResourceDeltaVerifier verifier)
			throws CoreException {
		verifyBuild(new IBuildConfiguration[] { project.getActiveBuildConfig() }, kind, verifier);
	}

	/**
	 * Build the specified configurations, and verify that the resource changes that
	 * result match the expectations of the given verifier.
	 */
	protected void verifyBuild(final IBuildConfiguration[] configs, final int kind, ResourceDeltaVerifier verifier)
			throws CoreException {
		getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, null);
		getWorkspace().addResourceChangeListener(verifier);
		try {
			// batch changes
			IWorkspaceRunnable body = new IWorkspaceRunnable() {
				@Override
				public void run(IProgressMonitor monitor) throws CoreException {
					getWorkspace().build(configs, kind, true, monitor);
				}
			};
			getWorkspace().run(body, null);
		} finally {
			assertTrue(verifier.getMessage(), verifier.isDeltaValid());
			getWorkspace().removeResourceChangeListener(verifier);
			printAllMarkers();
		}
	}

	/**
	 * Set the active configuration of a project by configuration name
	 */
	protected void setActiveConfigurationByName(IProject project, String cfgName) throws CoreException {
		ICProjectDescriptionManager mngr = CoreModel.getDefault().getProjectDescriptionManager();
		ICProjectDescription desc = mngr.getProjectDescription(project, true);
		ICConfigurationDescription cfg = desc.getConfigurationByName(cfgName);
		assertNotNull(cfg);
		desc.setActiveConfiguration(cfg);
		mngr.setProjectDescription(project, desc);
		// FIXME: enable when cdt.core knows about core.resources build configurations
		//		assertTrue(project.getActiveBuildConfig().getName().equals(cfg.getName()));
	}

	protected Collection<IResource> getProjectBuildExeResources(String projectName, String cfgName, String obj)
			throws CoreException {
		return getProjectBuildExeResources(projectName, cfgName, obj, true);
	}

	/**
	 * The externalBuilder is true for when makefiles are generated, or false for internal builder
	 */
	protected Collection<IResource> getProjectBuildExeResources(String projectName, String cfgName, String obj,
			boolean externalBuilder) throws CoreException {
		return getProjectBuildExeResources(projectName, cfgName, new String[] { obj }, externalBuilder);
	}

	protected Collection<IResource> getProjectBuildLibResources(String projectName, String cfgName, String obj)
			throws CoreException {
		return getProjectBuildLibResources(projectName, cfgName, new String[] { obj });
	}

	protected Collection<IResource> getProjectBuildSharedLibResources(String projectName, String cfgName, String obj)
			throws CoreException {
		return getProjectBuildSharedLibResources(projectName, cfgName, new String[] { obj });
	}

	protected IFile getProjectExe(String projectName, String cfgName) throws CoreException {
		IProject project = getWorkspace().getRoot().getProject(projectName);
		IFolder buildDir = project.getFolder(cfgName);
		return buildDir.getFile(projectName + (WINDOWS ? ".exe" : ""));
	}

	protected Collection<IResource> getProjectBuildExeResources(String projectName, String cfgName, String[] objs)
			throws CoreException {
		return getProjectBuildExeResources(projectName, cfgName, objs, true);
	}

	/**
	 * The externalBuilder is true for when makefiles are generated, or false for internal builder
	 */
	protected Collection<IResource> getProjectBuildExeResources(String projectName, String cfgName, String[] objs,
			boolean externalBuilder) throws CoreException {
		Collection<IResource> resources = getProjectBuildResources(projectName, cfgName, objs, externalBuilder);
		resources.add(getProjectExe(projectName, cfgName));
		return resources;
	}

	protected Collection<IResource> getProjectBuildLibResources(String projectName, String cfgName, String[] objs)
			throws CoreException {
		Collection<IResource> resources = getProjectBuildResources(projectName, cfgName, objs);
		IProject project = getWorkspace().getRoot().getProject(projectName);
		IFolder buildDir = project.getFolder(cfgName);
		resources.add(buildDir.getFile("lib" + projectName + ".a"));
		return resources;
	}

	protected Collection<IResource> getProjectBuildSharedLibResources(String projectName, String cfgName, String[] objs)
			throws CoreException {
		Collection<IResource> resources = getProjectBuildResources(projectName, cfgName, objs);
		IProject project = getWorkspace().getRoot().getProject(projectName);
		IFolder buildDir = project.getFolder(cfgName);
		resources.add(buildDir.getFile("lib" + projectName + ".so"));
		return resources;
	}

	/**
	 * Returns an array of resources expected to be generated by building a project configuration.
	 * The object files expected to be output can also be specified.
	 */
	protected Collection<IResource> getProjectBuildResources(String projectName, String cfgName, String[] objs)
			throws CoreException {
		return getProjectBuildResources(projectName, cfgName, objs, true);
	}

	/**
	 * Returns an array of resources expected to be generated by building a project configuration.
	 * The object files expected to be output can also be specified.
	 * The externalBuilder is true for when makefiles are generated, or false for internal builder
	 */
	protected Collection<IResource> getProjectBuildResources(String projectName, String cfgName, String[] objs,
			boolean externalBuilder) throws CoreException {
		IProject project = getWorkspace().getRoot().getProject(projectName);
		IFolder buildDir = project.getFolder(cfgName);
		Collection<IResource> resources = new LinkedHashSet<IResource>();
		resources.add(buildDir);
		if (externalBuilder) {
			resources.add(buildDir.getFile("makefile"));
			resources.add(buildDir.getFile("objects.mk"));
			resources.add(buildDir.getFile("sources.mk"));
		}
		for (String obj : objs) {
			if (externalBuilder) {
				resources.add(buildDir.getFile(obj + ".d"));
			}
			resources.add(buildDir.getFile(obj + ".o"));
			// Add subdir.mk in the same directory
			if (externalBuilder) {
				resources.add(buildDir.getFile(new Path(obj).removeLastSegments(1).append("subdir.mk")));
			}
			// If the parent of the obj doesn't exist, then ensure we're expecting that too...
			IPath p = new Path(obj).removeLastSegments(1);
			while (p.segmentCount() > 0) {
				IFolder folder = buildDir.getFolder(p);
				resources.add(folder);
				p = p.removeLastSegments(1);
			}
		}
		return resources;
	}

	public AbstractBuilderTest() {
		super();
	}

	public AbstractBuilderTest(String name) {
		super(name);
	}

	protected void setWorkspace(String name) {
		workspace = name;
		projects = new ArrayList<IProject>();
	}

	protected IProject loadProject(String name) throws CoreException {
		ManagedBuildTestHelper.loadProject(name, PATH + "/" + workspace);
		IProject project = getWorkspace().getRoot().getProject(name);
		assertTrue(project.exists());
		projects.add(project);
		project.refreshLocal(IResource.DEPTH_INFINITE, null);
		return project;
	}

	private List<IMarker> getAllMarkers() throws CoreException {
		List<IMarker> markers = new ArrayList<IMarker>();
		for (IProject project : projects)
			markers.addAll(Arrays
					.asList(project.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE)));
		return markers;
	}

	protected void printAllMarkers() throws CoreException {
		List<IMarker> markers = getAllMarkers();
		String[] attributes = new String[] { IMarker.LINE_NUMBER, IMarker.SEVERITY, IMarker.MESSAGE,
				IMarker.LOCATION /*, ICModelMarker.C_MODEL_MARKER_CONFIGURATION_NAME*/ };
		StringBuilder sb = new StringBuilder();
		for (IMarker m : markers) {
			// Project
			if (m.getResource().getProject() == null)
				sb.append("?");
			else
				sb.append(m.getResource().getProject().getName());
			// Resource workspace path
			sb.append(", "); //$NON-NLS-1$
			sb.append(m.getResource().getFullPath());
			Object[] attrs = m.getAttributes(attributes);
			sb.append(":"); //$NON-NLS-1$
			int i = 0;
			// line number
			if (attrs[i] != null)
				sb.append(" line ").append(attrs[i]); //$NON-NLS-1$
			// severity
			if (attrs[++i] != null) {
				switch ((Integer) attrs[i++]) {
				case IMarker.SEVERITY_ERROR:
					sb.append(" ERROR");
					break;
				case IMarker.SEVERITY_WARNING:
					sb.append(" WARNING");
					break;
				case IMarker.SEVERITY_INFO:
					sb.append(" INFO");
					break;
				}
			}
			// append the rest of the string fields
			do {
				if (attrs[i] != null)
					sb.append(' ').append(attrs[i]);
			} while (++i < attrs.length);
			// Finally print the string
			System.err.println(sb.toString());
			sb.setLength(0);
		}
	}

	protected void setAutoBuilding(boolean value) throws CoreException {
		IWorkspace workspace = getWorkspace();
		if (workspace.isAutoBuilding() == value)
			return;
		IWorkspaceDescription desc = workspace.getDescription();
		desc.setAutoBuilding(value);
		workspace.setDescription(desc);
	}

	protected IWorkspace getWorkspace() throws CoreException {
		return ResourcesPlugin.getWorkspace();
	}

}

Back to the top