source: release-kits/wirk3/ant-scripts/tasks/antelope/src/ise/antelope/tasks/Assert.java@ 15023

Last change on this file since 15023 was 15023, checked in by oranfry, 16 years ago

did the bulk of the work on wirk3

File size: 18.4 KB
Line 
1/*
2* The Apache Software License, Version 1.1
3*
4* Copyright (c) 2001-2002 The Apache Software Foundation. All rights
5* reserved.
6*
7* Redistribution and use in source and binary forms, with or without
8* modification, are permitted provided that the following conditions
9* are met:
10*
11* 1. Redistributions of source code must retain the above copyright
12* notice, this list of conditions and the following disclaimer.
13*
14* 2. Redistributions in binary form must reproduce the above copyright
15* notice, this list of conditions and the following disclaimer in
16* the documentation and/or other materials provided with the
17* distribution.
18*
19* 3. The end-user documentation included with the redistribution, if
20* any, must include the following acknowlegement:
21* "This product includes software developed by the
22* Apache Software Foundation (http://www.apache.org/)."
23* Alternately, this acknowlegement may appear in the software itself,
24* if and wherever such third-party acknowlegements normally appear.
25*
26* 4. The names "The Jakarta Project", "Ant", and "Apache Software
27* Foundation" must not be used to endorse or promote products derived
28* from this software without prior written permission. For written
29* permission, please contact [email protected].
30*
31* 5. Products derived from this software may not be called "Apache"
32* nor may "Apache" appear in their names without prior written
33* permission of the Apache Group.
34*
35* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46* SUCH DAMAGE.
47* ====================================================================
48*
49* This software consists of voluntary contributions made by many
50* individuals on behalf of the Apache Software Foundation. For more
51* information on the Apache Software Foundation, please see
52* <http://www.apache.org/>.
53*/
54package ise.antelope.tasks;
55
56
57import java.util.Enumeration;
58import java.util.Vector;
59
60import org.apache.tools.ant.BuildException;
61import org.apache.tools.ant.Project;
62import org.apache.tools.ant.Task;
63import org.apache.tools.ant.TaskContainer;
64import org.apache.tools.ant.types.EnumeratedAttribute;
65
66
67/**
68 * Based on the Sequential task. Similar to Java's 'assert' keyword, verifies
69 * that a given property has a given value. Throws a BuildException if the
70 * property value is not as expected or the property does not exist. <p>
71 *
72 * Also like Java's 'assert' keyword, the Assert task must be 'turned on' using
73 * the property "ant.enable.asserts". If not set, or is set to false, the Assert
74 * task works exactly like the Sequential task. <p>
75 *
76 * Can hold other tasks including Assert. Attributes:
77 * <ul>
78 * <li> name - the name of a property. Required.</li>
79 * <li> exists - boolean, if true, throws BuildException if the property does
80 * not exist. Optional, default is true.</li>
81 * <li> value - the expected value of a property. Implies 'exists'. Throws
82 * BuildException if the actual value is not the same as this value. Optional.
83 * </li>
84 * <li> execute - boolean, if true, execute any contained tasks. Optional,
85 * default is true. Can also be set globally by setting the value of
86 * "assert.execute" to true or false. The local setting overrides the global
87 * setting.</li> <p>
88 *
89 * The assert task supports a single nested BooleanCondition task, otherwise,
90 * the assert task does not support any nested elements apart from Ant tasks.
91 * Any valid Ant task may be embedded within the assert task.</p>
92 *
93 * @author Dale Anson, [email protected]
94 * @version $Revision: 1.5 $
95 * @since Ant 1.5
96 */
97public class Assert extends Task implements TaskContainer {
98
99 // attribute storage
100 private boolean failOnError = true;
101 private boolean failOnErrorSetByUser = false;
102 private String execute = null;
103 private boolean exists = true;
104 private String value = null;
105 private String name = null;
106 private String message = "";
107 private int level = AssertException.ERROR;
108
109 // to hold optional nested boolean task
110 private Task condition_task = null;
111
112 // vector to hold any nested tasks
113 private Vector tasks = new Vector();
114
115 /**
116 * Set the name of the property to test. Required.
117 *
118 * @param name the name of the property to test.
119 */
120 public void setName(String name) {
121 this.name = name;
122 }
123
124 /**
125 * Set the expected value of the property. Implies 'exists'. Throws
126 * BuildException if the actual value is not the same as this value.
127 * Optional.
128 *
129 * @param value the expected value of the property.
130 */
131 public void setValue(String value) {
132 this.value = value;
133 }
134
135 /**
136 * Set a specific message to include in the output in the event this assert
137 * fails.
138 *
139 * @param msg the message to include
140 */
141 public void setMessage(String msg) {
142 if (msg == null)
143 return;
144 this.message = msg;
145 }
146
147
148 /**
149 * Set the 'exists' attribute. If true, throws BuildException if the
150 * property does not exist. Optional, default is true.
151 *
152 * @param exists Ant boolean, whether the value must exist.
153 */
154 public void setExists(String exists) {
155 this.exists = getProject().toBoolean(exists);
156 }
157
158 /**
159 * Ant boolean, if true, execute any contained tasks. Optional, default is
160 * true. Can also be set globally by setting the value of "assert.execute"
161 * to true or false. The local setting overrides the global setting.
162 *
163 * @param execute Ant boolean, whether to execute contained tasks.
164 */
165 public void setExecute(String execute) {
166 this.execute = execute;
167 }
168
169 /**
170 * Ant boolean, stop the build process if the assertion fails. Defaults to
171 * true. Setting this to false is contrary to the intented use of
172 * assertions, but may be useful in certain situations.
173 *
174 * @param fail Ant boolean, whether to stop the build on assertion error.
175 */
176 public void setFailonerror(boolean fail) {
177 failOnError = fail;
178 failOnErrorSetByUser = true;
179 }
180
181 /**
182 * Sets the assertion level. This is like message level or debug level,
183 * valid values are "error" (the default), "warning", "info", and "debug".
184 * Setting the level to "warning", "info", or "debug" will force the
185 * fail on error setting to false.
186 * @param assertlevel one of "error", "warning", "info", or "debug" levels.
187 */
188 public void setLevel(AssertLevel assertlevel) {
189 level = assertlevel.indexOfValue(assertlevel.getValue());
190 }
191
192 /**
193 * Override {@link org.apache.tools.ant.Task#maybeConfigure maybeConfigure}
194 * in a way that leaves the nested tasks unconfigured until they get
195 * executed.
196 *
197 * @exception BuildException Description of Exception
198 * @since Ant 1.5
199 */
200 public void maybeConfigure() throws BuildException {
201 if (isInvalid()) {
202 super.maybeConfigure();
203 }
204 else {
205 getRuntimeConfigurableWrapper().maybeConfigure(getProject(), false);
206 }
207 }
208
209 /**
210 * Add a nested task to execute. <p>
211 *
212 * @param task Nested task to execute. <p>
213 */
214 public void addTask(Task task) {
215 if (task instanceof BooleanConditionTask) {
216 if (condition_task == null) {
217 condition_task = task;
218 return;
219 }
220 else {
221 throw new BuildException("Only one <bool> or <condition> allowed per Assert.");
222 }
223 }
224 tasks.addElement(task);
225 }
226
227 /**
228 * Adds a feature to the Bool attribute of the Assert object
229 *
230 * @param boolTask The feature to be added to the Bool attribute
231 */
232 public void addBool(BooleanConditionTask boolTask) {
233 addTask(boolTask);
234 }
235
236 /**
237 * Execute this task and all nested Tasks.
238 *
239 * @exception BuildException Description of Exception
240 */
241 public void execute() throws BuildException {
242 // adjust failOnError depending on level and user setting
243 if (!failOnErrorSetByUser) {
244 switch (level) {
245 default: // error
246 failOnError = true;
247 break;
248 case 2: // warning
249 case 3: // info
250 case 4: // debug
251 failOnError = false;
252 break;
253 }
254 }
255
256 // check for global 'ant.enable.asserts' property -- if this isn't set or
257 // is set to false, just run the nested tasks and skip the assertion
258 // testing.
259 String use_asserts = getProject().getProperty("ant.enable.asserts");
260 if (use_asserts == null || !getProject().toBoolean(use_asserts)) {
261 executeNestedTasks();
262 return;
263 }
264
265 if (condition_task == null) {
266 // check for the required name attribute
267 if (name == null || name.equals(""))
268 throw new BuildException("The 'name' attribute is required.");
269
270 // get the property value from the project
271 String prop_value = getProject().getProperty(name);
272
273 // check if the property exists
274 if (exists && prop_value == null) {
275 String msg = "Assertion failed: Property '" + name + "' doesn't exist in this project.\n" + message;
276 if (failOnError)
277 throw new BuildException(msg);
278 else
279 log(msg, Project.MSG_WARN);
280 }
281 else if (!exists && prop_value != null) {
282 String msg = "Assertion failed: Property '" + name + "' exists in this project, but shouldn't.\n" + message;
283 if (failOnError)
284 throw new BuildException(msg);
285 else
286 log(msg, Project.MSG_WARN);
287 }
288
289 // do the actual assert checks...
290 // check that the property has the right value
291 if (value != null) {
292 if (prop_value == null) {
293 String msg = "Assertion failed: Expected '" + value + "', but was null\n" + message;
294 if (failOnError)
295 throw new AssertException(msg, level);
296 else
297 log(msg, Project.MSG_WARN);
298 }
299 else if (prop_value != null) {
300 // check if this is a boolean value
301 String b = prop_value.toLowerCase();
302 boolean have_boolean = false;
303 if (b.equals("on") || b.equals("yes") || b.equals("true") ||
304 b.equals("off") || b.equals("no") || b.equals("false"))
305 have_boolean = true;
306
307 if (have_boolean) {
308 // convert 'value' to boolean and compare
309 boolean prop_bvalue = getProject().toBoolean(prop_value);
310 boolean bvalue = getProject().toBoolean(value);
311 if (prop_bvalue != bvalue) {
312 String msg = "Assertion failed: Expected '" + bvalue + "', but was '" + prop_bvalue + "'.\n" + message;
313 if (failOnError)
314 throw new AssertException(msg, level);
315 else
316 log(msg, Project.MSG_WARN);
317 }
318 }
319 else if (!prop_value.equals(value)) {
320 // property values are different
321 String msg = "Assertion failed: Expected '" + value + "', but was '" + prop_value + "'.\n" + message;
322 if (failOnError)
323 throw new AssertException(msg, level);
324 else
325 log(msg, Project.MSG_WARN);
326 }
327 }
328 }
329 }
330 else {
331 // have nested condition
332 if (!((BooleanConditionTask) condition_task).eval()) {
333 if (message == null)
334 message = "Assertion failed.";
335 if (failOnError)
336 throw new AssertException(message, level);
337 else
338 log(message, Project.MSG_WARN);
339 }
340 }
341
342 // execute all nested tasks
343 boolean do_execute = true;
344 if (execute == null) {
345 execute = getProject().getProperty("assert.execute");
346 if (execute != null)
347 do_execute = getProject().toBoolean(execute);
348 }
349 else {
350 do_execute = getProject().toBoolean(execute);
351 }
352 if (do_execute) {
353 executeNestedTasks();
354 }
355 }
356
357 /** Execute all nested tasks. */
358 private void executeNestedTasks() {
359 for (Enumeration e = tasks.elements(); e.hasMoreElements(); ) {
360 Task task = (Task) e.nextElement();
361 task.perform();
362 }
363 }
364
365 // testing
366 /**
367 * Description of the Method
368 *
369 * @return Description of the Returned Value
370 */
371 public static int runTests() {
372 // set up a project
373 org.apache.tools.ant.Project p = new org.apache.tools.ant.Project();
374 Assert ass = new Assert();
375 ass.setProject(p);
376
377 // set up a property
378 String test_property = "test_property";
379 String test_value = "test_value";
380
381 // enable asserts so the tests can run
382 p.setProperty("ant.enable.asserts", "true");
383
384 // count the number of tests ran
385 int num_tests = 0;
386
387 // run some tests --
388 // 1. check that task fails if name is missing -- name is required
389 try {
390 ass.execute();
391 throw new RuntimeException("test 1 failed.");
392 }
393 catch (Exception e) {
394 ++num_tests;
395 }
396
397 // 2. check that task fails if name is given but is not in project --
398 // this is one of the main uses of Assert, to verify that a property exists.
399 // The default setting of 'exists' is true so doesn't need to be set
400 // explicitly.
401 try {
402 ass.setName(test_property);
403 ass.execute();
404 throw new RuntimeException("test 2 test failed.");
405 }
406 catch (Exception e) {
407 ++num_tests;
408 }
409
410 // 3. test that task passes if name is given and is in project -- again
411 // this is one of the main uses of Assert, to verify that a property exists.
412 // The default setting of 'exists' is true so doesn't need to be set
413 // explicitly.
414 try {
415 p.setProperty(test_property, test_value);
416 ass.setName(test_property);
417 ass.execute();
418 ++num_tests;
419 }
420 catch (Exception e) {
421 throw new RuntimeException("test 3 test failed:\n" + e.getMessage());
422 }
423
424 // 4. test that task passes if name is given, the property doesn't exist in
425 // the project, and exists is false. This is another main use case --
426 // checking that a property is not set.
427 try {
428 ass.setExists("false");
429 ass.execute();
430 throw new RuntimeException("test 4 failed");
431 }
432 catch (Exception e) {
433 ++num_tests;
434 }
435
436 // 5. test that task passes if property is set with the correct value --
437 // this is another main use case -- checking that a property exists with the
438 // right value.
439 try {
440 ass.setExists("true"); // true is default value
441 ass.setValue(test_value);
442 ass.execute();
443 ++num_tests;
444 }
445 catch (Exception e) {
446 throw new RuntimeException("test 5 failed\n" + e.getMessage());
447 }
448
449 // 6. test that task failed if property is incorrect -- this is the inverse
450 // test of #5.
451 try {
452 ass.setValue("blah");
453 ass.execute();
454 throw new RuntimeException("test 6 failed");
455 }
456 catch (Exception e) {
457 ++num_tests;
458 }
459
460 // 7, 8, 9. test that task passes if property is boolean -- make sure that
461 // the property can be set to 'true', 'on', or 'yes' and will evaluate
462 // correctly regardless.
463 try {
464 ass.setExists("true"); // true is default value
465
466 // set project propert to "true"
467 p.setProperty("boolean prop", "true");
468 ass.setName("boolean prop");
469
470 // test "true", "on", and "yes" all work. Ant doesn't care about case
471 // on these values
472 ass.setValue("tRue");
473 ass.execute();
474 ++num_tests;
475 ass.setValue("on");
476 ass.execute();
477 ++num_tests;
478 ass.setValue("Yes");
479 ass.execute();
480 ++num_tests;
481 }
482 catch (Exception e) {
483 throw new RuntimeException("test 7 failed\n" + e.getMessage());
484 }
485
486 // 10. test that failonerror works when false.
487 try {
488 ass.setValue("blah");
489 ass.setFailonerror(false);
490 ass.execute();
491 ++num_tests;
492 }
493 catch (Exception e) {
494 throw new RuntimeException("test 10 failed");
495 }
496
497 // 11. test that failonerror works when true.
498 try {
499 ass.setValue("blah");
500 ass.setFailonerror(true);
501 ass.execute();
502 throw new RuntimeException("test 11 failed");
503 }
504 catch (Exception e) {
505 ++num_tests;
506 }
507
508 return num_tests;
509 }
510
511 /**
512 * The main program for the Assert class
513 *
514 * @param args The command line arguments
515 */
516 public static void main(String[] args) {
517 int num_tests = Assert.runTests();
518 System.out.println("Ran " + num_tests + " tests, all passed.");
519 }
520}
521
Note: See TracBrowser for help on using the repository browser.