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.types;
21  
22  import java.io.File;
23  import java.io.IOException;
24  
25  import junit.framework.TestCase;
26  
27  import org.apache.tools.ant.BuildException;
28  import org.apache.tools.ant.Project;
29  
30  import com.github.maven_nar.cpptasks.CUtil;
31  import com.github.maven_nar.cpptasks.MockBuildListener;
32  import com.github.maven_nar.cpptasks.MockFileCollector;
33  import com.github.maven_nar.cpptasks.compiler.Linker;
34  import com.github.maven_nar.cpptasks.msvc.MsvcLibrarian;
35  import com.github.maven_nar.cpptasks.msvc.MsvcLinker;
36  
37  /**
38   * Tests for the LibrarySet class.
39   */
40  public class TestLibrarySet extends TestCase {
41  
42    /**
43     * Constructor.
44     *
45     * @param name
46     *          test name
47     */
48    public TestLibrarySet(final String name) {
49      super(name);
50    }
51  
52    /**
53     * This test specifies a library pattern that should
54     * not match any available libraries and expects that
55     * a build exception will be raised.
56     *
57     * See bug 1380366
58     */
59    public final void testBadLibname() {
60      final LibrarySet libset = new LibrarySet();
61      final Project p = new Project();
62      final MockBuildListener listener = new MockBuildListener();
63      p.addBuildListener(listener);
64      libset.setProject(p);
65      // set libs to the file name without the suffix
66      final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("badlibname");
67      libset.setLibs(libs);
68  
69      //
70      // collect all files visited
71      final MockFileCollector collector = new MockFileCollector();
72      try {
73        libset.visitLibraries(p, MsvcLinker.getInstance(), new File[0], collector);
74      } catch (final BuildException ex) {
75        return;
76      }
77      //
78      // code around line 320 in LibrarySet that would throw BuildException
79      // (and prevent reaching this line) is disabled since logic for identifying
80      // missing libraries does not work reliably on non-Windows platforms
81      //
82      // fail("visitLibraries should throw exception due to unsatisifed libname");
83    }
84  
85    /**
86     * Evaluate isActive when "if" specifies a property that is set.
87     */
88    public final void testIsActive1() {
89      final LibrarySet libset = new LibrarySet();
90      final Project project = new Project();
91      project.setProperty("windows", "");
92      libset.setProject(project);
93      libset.setIf("windows");
94      final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("kernel32");
95      libset.setLibs(libs);
96      final boolean isActive = libset.isActive(project);
97      assertTrue(isActive);
98    }
99  
100   /**
101    * Evaluate isActive when "if" specifies a property whose value suggests the
102    * user thinks the value is significant.
103    *
104    */
105   public final void testIsActive2() {
106     final LibrarySet libset = new LibrarySet();
107     final Project project = new Project();
108     //
109     // setting the value to false should throw
110     // exception to warn user that they are misusing if
111     //
112     project.setProperty("windows", "false");
113     libset.setIf("windows");
114     try {
115       final boolean isActive = libset.isActive(project);
116     } catch (final BuildException ex) {
117       return;
118     }
119     fail();
120   }
121 
122   /**
123    * Evaluate isActive when "if" specifies a property that is not set.
124    */
125   public final void testIsActive3() {
126     final LibrarySet libset = new LibrarySet();
127     final Project project = new Project();
128     libset.setIf("windows");
129     final boolean isActive = libset.isActive(project);
130     assertTrue(!isActive);
131   }
132 
133   /**
134    * Evaluate isActive when "unless" specifies a property that is set.
135    *
136    */
137   public final void testIsActive4() {
138     final LibrarySet libset = new LibrarySet();
139     final Project project = new Project();
140     project.setProperty("windows", "");
141     libset.setUnless("windows");
142     final boolean isActive = libset.isActive(project);
143     assertTrue(!isActive);
144   }
145 
146   /**
147    * Evaluate isActive when "unless" specifies a property whose value suggests
148    * the user thinks the value is significant.
149    *
150    */
151   public final void testIsActive5() {
152     final LibrarySet libset = new LibrarySet();
153     final Project project = new Project();
154     //
155     // setting the value to false should throw
156     // exception to warn user that they are misusing if
157     //
158     project.setProperty("windows", "false");
159     libset.setUnless("windows");
160     try {
161       final boolean isActive = libset.isActive(project);
162     } catch (final BuildException ex) {
163       return;
164     }
165     fail();
166   }
167 
168   /**
169    * Evaluate isActive when "unless" specifies a property that is not set.
170    */
171   public final void testIsActive6() {
172     final LibrarySet libset = new LibrarySet();
173     final Project project = new Project();
174     libset.setProject(project);
175     libset.setUnless("windows");
176     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("kernel32");
177     libset.setLibs(libs);
178     final boolean isActive = libset.isActive(project);
179     assertTrue(isActive);
180   }
181 
182   /**
183    * The libs parameter should not end with .lib, .so, .a etc New behavior is
184    * to warn if it ends in a suspicious extension.
185    */
186   public final void testLibContainsDot() {
187     final LibrarySet libset = new LibrarySet();
188     final Project p = new Project();
189     final MockBuildListener listener = new MockBuildListener();
190     p.addBuildListener(listener);
191     libset.setProject(p);
192     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("mylib1.1");
193     libset.setLibs(libs);
194     assertEquals(0, listener.getMessageLoggedEvents().size());
195   }
196 
197   /**
198    * The libs parameter should not end with .lib, .so, .a (that is,
199    * should be kernel, not kernel.lib). Previously the libset would
200    * warn on configuration, now provides more feedback
201    * when library is not found.
202    */
203   public final void testLibContainsDotLib() {
204     final LibrarySet libset = new LibrarySet();
205     final Project p = new Project();
206     final MockBuildListener listener = new MockBuildListener();
207     p.addBuildListener(listener);
208     libset.setProject(p);
209     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("mylib1.lib");
210     libset.setLibs(libs);
211     assertEquals(0, listener.getMessageLoggedEvents().size());
212   }
213 
214   /**
215    * Use of a libset or syslibset without a libs attribute should log a
216    * warning message.
217    */
218   public final void testLibNotSpecified() {
219     final LibrarySet libset = new LibrarySet();
220     final Project p = new Project();
221     final MockBuildListener listener = new MockBuildListener();
222     p.addBuildListener(listener);
223     libset.setProject(p);
224     final boolean isActive = libset.isActive(p);
225     assertEquals(false, isActive);
226     assertEquals(1, listener.getMessageLoggedEvents().size());
227   }
228 
229   /**
230    * Run testVisitFiles with the MSVC Librarian
231    * expect one matching file.
232    *
233    * @throws IOException
234    *           if unable to create or delete temporary file
235    */
236   public final void testLibrarianVisitFiles() throws IOException {
237     final Linker linker = MsvcLibrarian.getInstance();
238     testVisitFiles(linker, 0);
239   }
240 
241   /**
242    * Run testVisitFiles with the MSVC Linker
243    * expect one matching file.
244    *
245    * @throws IOException
246    *           if unable to create or delete temporary file
247    */
248   public final void testLinkerVisitFiles() throws IOException {
249     final Linker linker = MsvcLinker.getInstance();
250     testVisitFiles(linker, 1);
251   }
252 
253   /**
254    * this threw an exception prior to 2002-09-05 and started to throw one
255    * again 2002-11-19 up to 2002-12-11.
256    */
257   public final void testShortLibName() {
258     final LibrarySet libset = new LibrarySet();
259     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("li");
260     libset.setProject(new Project());
261     libset.setLibs(libs);
262   }
263 
264   /**
265    * The libs parameter should contain not a lib prefix (that is,
266    * pthread not libpthread). Previously the libset would
267    * warn on configuration, now provides more feedback
268    * when library is not found.
269    */
270   public final void testStartsWithLib() {
271     final LibrarySet libset = new LibrarySet();
272     final Project p = new Project();
273     final MockBuildListener listener = new MockBuildListener();
274     p.addBuildListener(listener);
275     libset.setProject(p);
276     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder("libmylib1");
277     libset.setLibs(libs);
278     assertEquals(0, listener.getMessageLoggedEvents().size());
279   }
280 
281   /**
282    * This test creates two "fake" libraries in the temporary directory and
283    * check how many are visited.
284    *
285    * @param linker
286    *          linker
287    * @param expected
288    *          expected number of visited files
289    * @throws IOException
290    *           if unable to write to temporary directory or delete temporary
291    *           files
292    */
293   public final void testVisitFiles(final Linker linker, final int expected) throws IOException {
294     final LibrarySet libset = new LibrarySet();
295     final Project p = new Project();
296     final MockBuildListener listener = new MockBuildListener();
297     p.addBuildListener(listener);
298     libset.setProject(p);
299     //
300     // create temporary files named cpptasksXXXXX.lib
301     //
302     final File lib1 = File.createTempFile("cpptasks", ".lib");
303     String lib1Name = lib1.getName();
304     lib1Name = lib1Name.substring(0, lib1Name.indexOf(".lib"));
305     final File lib2 = File.createTempFile("cpptasks", ".lib");
306     final File baseDir = lib1.getParentFile();
307 
308     // set the dir attribute to the temporary directory
309     libset.setDir(baseDir);
310     // set libs to the file name without the suffix
311     final CUtil.StringArrayBuilder libs = new CUtil.StringArrayBuilder(lib1Name);
312     libset.setLibs(libs);
313 
314     //
315     // collect all files visited
316     final MockFileCollector collector = new MockFileCollector();
317     libset.visitLibraries(p, linker, new File[0], collector);
318 
319     //
320     // get the canonical paths for the initial and visited libraries
321     final String expectedCanonicalPath = lib1.getCanonicalPath();
322     String actualCanonicalPath = null;
323     if (collector.size() == 1) {
324       actualCanonicalPath = new File(collector.getBaseDir(0), collector.getFileName(0)).getCanonicalPath();
325     }
326     //
327     // delete the temporary files
328     lib1.delete();
329     lib2.delete();
330     // was there only one match
331     assertEquals(expected, collector.size());
332     if (expected == 1) {
333       // is its canonical path as expected
334       assertEquals(expectedCanonicalPath, actualCanonicalPath);
335     }
336   }
337 
338 }