View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar.cpptasks;
21  
22  import java.io.File;
23  import java.io.IOException;
24  
25  import org.apache.tools.ant.BuildException;
26  import org.apache.tools.ant.Project;
27  import org.apache.tools.ant.types.FlexInteger;
28  import org.apache.tools.ant.types.Reference;
29  
30  import com.github.maven_nar.cpptasks.compiler.CommandLineLinkerConfiguration;
31  import com.github.maven_nar.cpptasks.compiler.Linker;
32  import com.github.maven_nar.cpptasks.gcc.GccLinker;
33  import com.github.maven_nar.cpptasks.msvc.MsvcLinker;
34  import com.github.maven_nar.cpptasks.types.FlexLong;
35  import com.github.maven_nar.cpptasks.types.LibrarySet;
36  import com.github.maven_nar.cpptasks.types.LinkerArgument;
37  import com.github.maven_nar.cpptasks.types.SystemLibrarySet;
38  
39  /**
40   * Tests for LinkerDef class.
41   */
42  public final class TestLinkerDef extends TestProcessorDef {
43    /**
44     * Sets the name attribute.
45     *
46     * @param linker
47     *          linker defintion
48     * @param name
49     *          linker name
50     */
51    private static void setLinkerName(final LinkerDef linker, final String name) {
52      final LinkerEnum linkerName = new LinkerEnum();
53      linkerName.setValue(name);
54      linker.setName(linkerName);
55    }
56  
57    /**
58     * Constructor.
59     *
60     * @param name
61     *          test name
62     */
63    public TestLinkerDef(final String name) {
64      super(name);
65    }
66  
67    /**
68     * Creates a processor.
69     *
70     * @return new linker
71     */
72    @Override
73    protected ProcessorDef create() {
74      return new LinkerDef();
75    }
76  
77    /**
78     * Gets the command line arguments that appear before the filenames.
79     *
80     * @param processor
81     *          processor under test
82     * @return command line arguments
83     */
84    @Override
85    protected String[] getPreArguments(final ProcessorDef processor) {
86      return ((CommandLineLinkerConfiguration) getConfiguration(processor)).getPreArguments();
87    }
88  
89    /**
90     * Tests that the base attribute in the base linker is effective when
91     * creating the command line for a linker that extends it.
92     */
93    public void testExtendsBase() {
94      final LinkerDef baseLinker = new LinkerDef();
95      baseLinker.setBase(new FlexLong("10000"));
96      final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
97      setLinkerName(extendedLinker, "msvc");
98      final String[] preArgs = getPreArguments(extendedLinker);
99      assertEquals("/NOLOGO", preArgs[0]);
100     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
101     assertEquals("/INCREMENTAL:NO", preArgs[2]);
102     assertEquals("/BASE:0x2710", preArgs[3]);
103   }
104 
105   /**
106    * Tests that the classname attribute in the base linker is effective when
107    * creating the command line for a linker that extends it.
108    */
109   public void testExtendsClassname() {
110     final LinkerDef baseLinker = new LinkerDef();
111     baseLinker.setClassname("com.github.maven_nar.cpptasks.msvc.MsvcLinker");
112     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
113     extendedLinker.setBase(new FlexLong("10000"));
114     final String[] preArgs = getPreArguments(extendedLinker);
115     assertEquals("/NOLOGO", preArgs[0]);
116     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
117     assertEquals("/INCREMENTAL:NO", preArgs[2]);
118     assertEquals("/BASE:0x2710", preArgs[3]);
119   }
120 
121   /**
122    * Tests that the entry attribute in the base linker is effective when
123    * creating the command line for a linker that extends it.
124    */
125   public void testExtendsEntry() {
126     final LinkerDef baseLinker = new LinkerDef();
127     baseLinker.setEntry("foo");
128     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
129     final String[] preArgs = getPreArguments(extendedLinker);
130     assertEquals("-e", preArgs[0]);
131     assertEquals("foo", preArgs[1]);
132   }
133 
134   /**
135    * Tests that fileset's that appear in the base linker are effective when
136    * creating the command line for a linker that extends it.
137    * 
138    * @throws IOException
139    *           if unable to create or delete temporary file
140    */
141   public void testExtendsFileSet() throws IOException {
142     super.testExtendsFileSet(File.createTempFile("cpptaskstest", ".o"));
143   }
144 
145   /**
146    * Tests that the fixed attribute in the base linker is effective when
147    * creating the command line for a linker that extends it.
148    */
149   public void testExtendsFixed() {
150     final LinkerDef baseLinker = new LinkerDef();
151     baseLinker.setFixed(true);
152     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
153     setLinkerName(extendedLinker, "msvc");
154     final String[] preArgs = getPreArguments(extendedLinker);
155     assertEquals("/NOLOGO", preArgs[0]);
156     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
157     assertEquals("/INCREMENTAL:NO", preArgs[2]);
158     assertEquals("/FIXED", preArgs[3]);
159   }
160 
161   /**
162    * Tests that the incremental attribute in the base linker is effective when
163    * creating the command line for a linker that extends it.
164    */
165   public void testExtendsIncremental() {
166     final LinkerDef baseLinker = new LinkerDef();
167     baseLinker.setIncremental(true);
168     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
169     setLinkerName(extendedLinker, "msvc");
170     final String[] preArgs = getPreArguments(extendedLinker);
171     assertEquals("/NOLOGO", preArgs[0]);
172     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
173     assertEquals("/INCREMENTAL:YES", preArgs[2]);
174   }
175 
176   /**
177    * Tests that libset's that appear in the base linker are effective when
178    * creating the command line for a linker that extends it.
179    */
180   public void testExtendsLibSet() {
181     final LinkerDef baseLinker = new LinkerDef();
182     final LibrarySet libset = new LibrarySet();
183     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
184     libset.setProject(baseLinker.getProject());
185     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("advapi32");
186     libset.setLibs(libs);
187     baseLinker.addLibset(libset);
188     final CommandLineLinkerConfiguration config = (CommandLineLinkerConfiguration) getConfiguration(extendedLinker);
189     final String[] libnames = config.getLibraryNames();
190     assertEquals(1, libnames.length);
191     assertEquals("advapi32", libnames[0]);
192   }
193 
194   /**
195    * Tests that linkerarg's that appear in the base linker are effective when
196    * creating the command line for a linker that extends it.
197    */
198   public void testExtendsLinkerArgs() {
199     final LinkerDef baseLinker = new LinkerDef();
200     final LinkerArgument linkerArg = new LinkerArgument();
201     linkerArg.setValue("/base");
202     baseLinker.addConfiguredLinkerArg(linkerArg);
203     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
204     final String[] preArgs = getPreArguments(extendedLinker);
205     assertEquals(1, preArgs.length);
206     assertEquals("/base", preArgs[0]);
207   }
208 
209   /**
210    * Verify linkerarg's that appear in the base linker are effective when
211    * creating the command line for a linker that extends it, even if the
212    * linker is brought in through a reference.
213    */
214   public void testExtendsLinkerArgsViaReference() {
215     final Project project = new Project();
216     final LinkerDef baseLinker = new LinkerDef();
217     baseLinker.setProject(project);
218     baseLinker.setId("base");
219     project.addReference("base", baseLinker);
220     final LinkerArgument linkerArg = new LinkerArgument();
221     linkerArg.setValue("/base");
222     baseLinker.addConfiguredLinkerArg(linkerArg);
223 
224     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
225     extendedLinker.setProject(project);
226     extendedLinker.setId("extended");
227     project.addReference("extended", extendedLinker);
228 
229     final LinkerDef linkerRef = new LinkerDef();
230     linkerRef.setProject(project);
231     linkerRef.setRefid(new Reference(project, "extended"));
232     final String[] preArgs = getPreArguments(linkerRef);
233     assertEquals(1, preArgs.length);
234     assertEquals("/base", preArgs[0]);
235   }
236 
237   /**
238    * Tests that the map attribute in the base linker is effective when
239    * creating the command line for a linker that extends it.
240    */
241   public void testExtendsMap() {
242     final LinkerDef baseLinker = new LinkerDef();
243     baseLinker.setMap(true);
244     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
245     setLinkerName(extendedLinker, "msvc");
246     final String[] preArgs = getPreArguments(extendedLinker);
247     assertEquals("/NOLOGO", preArgs[0]);
248     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
249     assertEquals("/INCREMENTAL:NO", preArgs[2]);
250     assertEquals("/MAP", preArgs[3]);
251   }
252 
253   /**
254    * Tests that the name attribute in the base linker is effective when
255    * creating the command line for a linker that extends it.
256    */
257   public void testExtendsName() {
258     final LinkerDef baseLinker = new LinkerDef();
259     setLinkerName(baseLinker, "msvc");
260     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
261     extendedLinker.setBase(new FlexLong("10000"));
262     final String[] preArgs = getPreArguments(extendedLinker);
263     assertEquals("/NOLOGO", preArgs[0]);
264     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
265     assertEquals("/INCREMENTAL:NO", preArgs[2]);
266     assertEquals("/BASE:0x2710", preArgs[3]);
267   }
268 
269   /**
270    * Tests that the rebuild attribute in the base linker is effective when
271    * creating the command line for a linker that extends it.
272    */
273   public void testExtendsRebuild() {
274     testExtendsRebuild(new LinkerDef());
275   }
276 
277   /**
278    * Tests that the stack attribute in the base linker is effective when
279    * creating the command line for a linker that extends it.
280    */
281   public void testExtendsStack() {
282     final LinkerDef baseLinker = new LinkerDef();
283     baseLinker.setStack(new FlexInteger("10000"));
284     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
285     setLinkerName(extendedLinker, "msvc");
286     final String[] preArgs = getPreArguments(extendedLinker);
287     assertEquals("/NOLOGO", preArgs[0]);
288     assertEquals("/SUBSYSTEM:WINDOWS", preArgs[1]);
289     assertEquals("/INCREMENTAL:NO", preArgs[2]);
290     assertEquals("/STACK:0x2710", preArgs[3]);
291   }
292 
293   /**
294    * Tests that syslibset's that appear in the base linker are effective when
295    * creating the command line for a linker that extends it.
296    */
297   public void testExtendsSysLibSet() {
298     final LinkerDef baseLinker = new LinkerDef();
299     final SystemLibrarySet libset = new SystemLibrarySet();
300     final LinkerDef extendedLinker = (LinkerDef) createExtendedProcessorDef(baseLinker);
301     libset.setProject(baseLinker.getProject());
302     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("advapi32");
303     libset.setLibs(libs);
304     baseLinker.addSyslibset(libset);
305     final CommandLineLinkerConfiguration config = (CommandLineLinkerConfiguration) getConfiguration(extendedLinker);
306     final String[] libnames = config.getLibraryNames();
307     assertEquals(1, libnames.length);
308     assertEquals("advapi32", libnames[0]);
309   }
310 
311   /**
312    * Test if setting the classname attribute to the name of the GCC linker
313    * results in the singleton GCC linker.
314    */
315   public void testGetGcc() {
316     final LinkerDef linkerDef = (LinkerDef) create();
317     linkerDef.setClassname("com.github.maven_nar.cpptasks.gcc.GccLinker");
318     final Linker comp = (Linker) linkerDef.getProcessor();
319     assertNotNull(comp);
320     assertSame(GccLinker.getInstance(), comp);
321   }
322 
323   /**
324    * Test if setting the classname attribute to the name of the MSVC linker
325    * results in the singleton MSVC linker.
326    */
327   public void testGetMSVC() {
328     final LinkerDef linkerDef = (LinkerDef) create();
329     linkerDef.setClassname("com.github.maven_nar.cpptasks.msvc.MsvcLinker");
330     final Linker comp = (Linker) linkerDef.getProcessor();
331     assertNotNull(comp);
332     assertSame(MsvcLinker.getInstance(), comp);
333   }
334 
335   /**
336    * Tests if setting the classname attribute to an bogus classname results in
337    * a BuildException.
338    *
339    */
340   public void testUnknownClass() {
341     final LinkerDef linkerDef = (LinkerDef) create();
342     try {
343       linkerDef.setClassname("com.github.maven_nar.cpptasks.bogus.BogusLinker");
344     } catch (final BuildException ex) {
345       return;
346     }
347     fail("should have thrown exception");
348   }
349 
350   /**
351    * Tests if setting the classname to the name of a class that doesn't
352    * support Linker throws a BuildException.
353    *
354    */
355   public void testWrongType() {
356     final LinkerDef linkerDef = (LinkerDef) create();
357     try {
358       linkerDef.setClassname("com.github.maven_nar.cpptasks.CCTask");
359     } catch (final ClassCastException ex) {
360       return;
361     }
362     fail("should have thrown exception");
363   }
364 }