1 /*
2 * ========================================================================
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. 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 *
19 * ========================================================================
20 */
21 package org.apache.cactus.integration.ant;
22
23 import java.net.URL;
24
25 import org.apache.cactus.container.ContainerRunner;
26 import org.apache.cactus.integration.ant.container.GenericContainer;
27 import org.apache.tools.ant.BuildException;
28 import org.apache.tools.ant.Task;
29 import org.codehaus.cargo.util.DefaultAntTaskFactory;
30 import org.codehaus.cargo.util.log.AntLogger;
31
32 /**
33 * Task to automate running in-container unit test. It has the following
34 * syntax when used in Ant :
35 * <code><pre>
36 * <runservertests testURL="&t;url>"
37 * starttarget="<start target name>"
38 * stoptarget="<stop target name>"
39 * testtarget="<test target name>"/>
40 * </pre></code>
41 * where <code><url></code> is the URL that is used by this task to
42 * ensure that the server is running. Indeed, the algorithm is as follow :
43 * <ul>
44 * <li>Checks if server is running by trying to open an HTTP connection to
45 * the URL,</li>
46 * <li>If it fails, call the start target and loop until the HTTP connection
47 * the URL can be established,</li>
48 * <li>Call the test target. This target is supposed to start the test,
49 * usually by running the junit Ant task,</li>
50 * <li>When the tests are finished, call the stop target to stop the server.
51 * Note: The stop target is called only if the server was not already running
52 * when this task was executed.</li>
53 * </ul>
54 *
55 * @since Cactus 1.5
56 * @version $Id: RunServerTestsTask.java 239003 2004-05-31 20:05:27Z vmassol $
57 */
58 public class RunServerTestsTask extends Task
59 {
60
61 // Instance Variables ------------------------------------------------------
62
63 /**
64 * The generic container.
65 */
66 private GenericContainer container = new GenericContainer();
67
68 /**
69 * The hook that is called when the tests should be run.
70 */
71 private GenericContainer.Hook testHook;
72
73 /**
74 * The URL that is continuously pinged to verify if the server is running.
75 */
76 private URL testURL;
77
78 /**
79 * Timeout after which we stop trying to connect to the test URL (in ms).
80 */
81 private long timeout = 180000;
82
83 // Task Implementation -----------------------------------------------------
84
85 /**
86 * {@inheritDoc}
87 * @see Task#execute()
88 */
89 public void execute() throws BuildException
90 {
91 if (!this.container.isStartUpSet())
92 {
93 throw new BuildException("You must specify either a nested [start] "
94 + "element or the [starttarget] attribute");
95 }
96
97 if (!this.container.isShutDownSet())
98 {
99 throw new BuildException("You must specify either a nested [stop] "
100 + "element or the [stoptarget] attribute");
101 }
102
103 if (this.testHook == null)
104 {
105 throw new BuildException("You must specify either a nested [test] "
106 + "element or the [testtarget] attribute");
107 }
108
109 // Verify that a test URL has been specified
110 if (this.testURL == null)
111 {
112 throw new BuildException(
113 "The [testurl] attribute must be specified");
114 }
115
116 this.container.setAntTaskFactory(new DefaultAntTaskFactory(
117 getProject(), getTaskName(),
118 getLocation(), getOwningTarget()));
119 ContainerRunner runner = new ContainerRunner(this.container);
120 runner.setLogger(new AntLogger(getProject()));
121 runner.setURL(this.testURL);
122 runner.setTimeout(this.timeout);
123 runner.startUpContainer();
124 try
125 {
126 this.testHook.execute();
127 }
128 finally
129 {
130 runner.shutDownContainer();
131 }
132 }
133
134 // Public Methods ----------------------------------------------------------
135
136 /**
137 * Creates a nested start element.
138 *
139 * @return The start element
140 */
141 public final GenericContainer.Hook createStart()
142 {
143 if (this.container.isStartUpSet())
144 {
145 throw new BuildException(
146 "This task supports only one nested [start] element");
147 }
148 return this.container.createStartUp();
149 }
150
151 /**
152 * Sets the target to call to start the server.
153 *
154 * @param theStartTarget the Ant target to call
155 */
156 public void setStartTarget(String theStartTarget)
157 {
158 if (this.container.isStartUpSet())
159 {
160 throw new BuildException("Either specify the [starttarget] "
161 + "attribute or the nested [start] element, but not both");
162 }
163 this.container.setStartUpTarget(theStartTarget);
164 }
165
166 /**
167 * Creates a nested stop element.
168 *
169 * @return The stop element
170 */
171 public final GenericContainer.Hook createStop()
172 {
173 if (this.container.isShutDownSet())
174 {
175 throw new BuildException(
176 "This task supports only one nested [stop] element");
177 }
178 return this.container.createShutDown();
179 }
180
181 /**
182 * Sets the target to call to stop the server.
183 *
184 * @param theStopTarget the Ant target to call
185 */
186 public void setStopTarget(String theStopTarget)
187 {
188 if (this.container.isShutDownSet())
189 {
190 throw new BuildException("Either specify the [stoptarget] "
191 + "attribute or the nested [stop] element, but not both");
192 }
193 this.container.setShutDownTarget(theStopTarget);
194 }
195
196 /**
197 * Creates a nested test element.
198 *
199 * @return The test element
200 */
201 public final GenericContainer.Hook createTest()
202 {
203 if (this.testHook != null)
204 {
205 throw new BuildException(
206 "This task supports only one nested [test] element");
207 }
208 this.testHook = container.new Hook();
209 return this.testHook;
210 }
211
212 /**
213 * Sets the target to call to run the tests.
214 *
215 * @param theTestTarget the Ant target to call
216 */
217 public void setTestTarget(String theTestTarget)
218 {
219 if (this.testHook != null)
220 {
221 throw new BuildException("Either specify the [testtarget] "
222 + "attribute or the nested [test] element, but not both");
223 }
224 this.testHook = container.new Hook();
225 this.testHook.setTarget(theTestTarget);
226 }
227
228 /**
229 * Sets the URL to call for testing if the server is running.
230 *
231 * @param theTestURL the test URL to ping
232 */
233 public void setTestURL(URL theTestURL)
234 {
235 this.testURL = theTestURL;
236 }
237
238 /**
239 * @param theTimeout the timeout after which we stop trying to call the test
240 * URL.
241 */
242 public void setTimeout(long theTimeout)
243 {
244 this.timeout = theTimeout;
245 }
246
247 }