You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by rk...@apache.org on 2013/05/16 01:07:37 UTC

svn commit: r1483122 [1/2] - in /oozie/trunk: ./ core/src/main/java/org/apache/oozie/ core/src/main/java/org/apache/oozie/action/ssh/ core/src/main/java/org/apache/oozie/util/ core/src/test/java/org/apache/oozie/ core/src/test/java/org/apache/oozie/ser...

Author: rkanter
Date: Wed May 15 23:07:36 2013
New Revision: 1483122

URL: http://svn.apache.org/r1483122
Log:
OOZIE-1327 enhance unit-test coverage of package org.apache.oozie (iveselovsky via rkanter)

Added:
    oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleEngineSimple.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleJobBean.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineSimple.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineStreamLog.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorJobBean.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestLocalOozieClientCoord.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestSLAEventBean.java
    oozie/trunk/core/src/test/java/org/apache/oozie/TestV1JobsServletBundleEngine.java
    oozie/trunk/core/src/test/java/org/apache/oozie/servlet/TestV1JobServletBundleEngine.java
Modified:
    oozie/trunk/core/src/main/java/org/apache/oozie/BundleActionId.java
    oozie/trunk/core/src/main/java/org/apache/oozie/BundleEngine.java
    oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
    oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorJobBean.java
    oozie/trunk/core/src/main/java/org/apache/oozie/SLAEventBean.java
    oozie/trunk/core/src/main/java/org/apache/oozie/action/ssh/SshActionExecutor.java
    oozie/trunk/core/src/main/java/org/apache/oozie/util/CoordActionsInDateRange.java
    oozie/trunk/core/src/main/java/org/apache/oozie/util/XLogStreamer.java
    oozie/trunk/core/src/test/java/org/apache/oozie/test/XDataTestCase.java
    oozie/trunk/release-log.txt

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/BundleActionId.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/BundleActionId.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/BundleActionId.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/BundleActionId.java Wed May 15 23:07:36 2013
@@ -1,112 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.oozie;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import javax.persistence.Embeddable;
-
-import org.apache.hadoop.io.Writable;
-import org.apache.oozie.util.WritableUtils;
-
-/**
- * The composite primary key for the BundleActionBean Entity.
- */
-@Embeddable
-public class BundleActionId implements Writable {
-    private String bundleId = null;
-    private String coordName = null;
-
-    /**
-     * Set the Bundle Id
-     *
-     * @param bundleId the bundleId to set
-     */
-    public void setBundleId(String bundleId) {
-        this.bundleId = bundleId;
-    }
-
-    /**
-     * Return the Bundle Id.
-     *
-     * @return the bundleId
-     */
-    public String getBundleId() {
-        return bundleId;
-    }
-
-    /**
-     * Set the coordinator name
-     *
-     * @param coordName the coordName to set
-     */
-    public void setCoordName(String coordName) {
-        this.coordName = coordName;
-    }
-
-    /**
-     * Return the coordinator name
-     *
-     * @return the coordName
-     */
-    public String getCoordName() {
-        return coordName;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        return new String(bundleId + coordName).hashCode();
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof BundleActionId) {
-            return bundleId.equals(((BundleActionId) obj).getBundleId())
-                    && coordName.equals(((BundleActionId) obj).getCoordName());
-        }
-        else {
-            return false;
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.hadoop.io.Writable#readFields(java.io.DataInput)
-     */
-    @Override
-    public void readFields(DataInput dataInput) throws IOException {
-        setBundleId(WritableUtils.readStr(dataInput));
-        setCoordName(WritableUtils.readStr(dataInput));
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.hadoop.io.Writable#write(java.io.DataOutput)
-     */
-    @Override
-    public void write(DataOutput dataOutput) throws IOException {
-        WritableUtils.writeStr(dataOutput, getBundleId());
-        WritableUtils.writeStr(dataOutput, getCoordName());
-    }
-}

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/BundleEngine.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/BundleEngine.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/BundleEngine.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/BundleEngine.java Wed May 15 23:07:36 2013
@@ -55,6 +55,8 @@ import org.apache.oozie.util.ParamChecke
 import org.apache.oozie.util.XLog;
 import org.apache.oozie.util.XLogStreamer;
 
+import com.google.common.annotations.VisibleForTesting;
+
 public class BundleEngine extends BaseEngine {
     /**
      * Create a system Bundle engine, with no user and no group.
@@ -323,7 +325,8 @@ public class BundleEngine extends BaseEn
      * @return filter key and value map
      * @throws CoordinatorEngineException thrown if failed to parse filter string
      */
-    private Map<String, List<String>> parseFilter(String filter) throws BundleEngineException {
+    @VisibleForTesting
+    Map<String, List<String>> parseFilter(String filter) throws BundleEngineException {
         Map<String, List<String>> map = new HashMap<String, List<String>>();
         if (filter != null) {
             StringTokenizer st = new StringTokenizer(filter, ";");

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorEngine.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorEngine.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorEngine.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorEngine.java Wed May 15 23:07:36 2013
@@ -24,10 +24,12 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.StringTokenizer;
+
 import org.apache.hadoop.conf.Configuration;
 import org.apache.oozie.client.CoordinatorAction;
 import org.apache.oozie.client.CoordinatorJob;
@@ -52,6 +54,8 @@ import org.apache.oozie.util.ParamChecke
 import org.apache.oozie.util.XLog;
 import org.apache.oozie.util.XLogStreamer;
 
+import com.google.common.annotations.VisibleForTesting;
+
 public class CoordinatorEngine extends BaseEngine {
     private static XLog LOG = XLog.getLog(CoordinatorEngine.class);
 
@@ -97,7 +101,7 @@ public class CoordinatorEngine extends B
      */
     private CoordinatorJobBean getCoordJobWithNoActionInfo(String jobId) throws BaseEngineException {
         try {
-			return new CoordJobXCommand(jobId).call();
+            return new CoordJobXCommand(jobId).call();
         }
         catch (CommandException ex) {
             throw new BaseEngineException(ex);
@@ -111,7 +115,7 @@ public class CoordinatorEngine extends B
      */
     public CoordinatorActionBean getCoordAction(String actionId) throws BaseEngineException {
         try {
-			return new CoordActionInfoXCommand(actionId).call();
+            return new CoordActionInfoXCommand(actionId).call();
         }
         catch (CommandException ex) {
             throw new BaseEngineException(ex);
@@ -126,7 +130,7 @@ public class CoordinatorEngine extends B
     @Override
     public CoordinatorJobBean getCoordJob(String jobId) throws BaseEngineException {
         try {
-			return new CoordJobXCommand(jobId).call();
+            return new CoordJobXCommand(jobId).call();
         }
         catch (CommandException ex) {
             throw new BaseEngineException(ex);
@@ -142,8 +146,8 @@ public class CoordinatorEngine extends B
     public CoordinatorJobBean getCoordJob(String jobId, String filter, int start, int length) throws BaseEngineException {
         List<String> filterList = parseStatusFilter(filter);
         try {
-			return new CoordJobXCommand(jobId, filterList, start, length)
-					.call();
+            return new CoordJobXCommand(jobId, filterList, start, length)
+                    .call();
         }
         catch (CommandException ex) {
             throw new BaseEngineException(ex);
@@ -168,7 +172,7 @@ public class CoordinatorEngine extends B
     @Override
     public void kill(String jobId) throws CoordinatorEngineException {
         try {
-			new CoordKillXCommand(jobId).call();
+            new CoordKillXCommand(jobId).call();
             LOG.info("User " + user + " killed the Coordinator job " + jobId);
         }
         catch (CommandException e) {
@@ -209,8 +213,8 @@ public class CoordinatorEngine extends B
     public CoordinatorActionInfo reRun(String jobId, String rerunType, String scope, boolean refresh, boolean noCleanup)
             throws BaseEngineException {
         try {
-			return new CoordRerunXCommand(jobId, rerunType, scope, refresh,
-					noCleanup).call();
+            return new CoordRerunXCommand(jobId, rerunType, scope, refresh,
+                    noCleanup).call();
         }
         catch (CommandException ex) {
             throw new BaseEngineException(ex);
@@ -225,7 +229,7 @@ public class CoordinatorEngine extends B
     @Override
     public void resume(String jobId) throws CoordinatorEngineException {
         try {
-			new CoordResumeXCommand(jobId).call();
+            new CoordResumeXCommand(jobId).call();
         }
         catch (CommandException e) {
             throw new CoordinatorEngineException(e);
@@ -271,7 +275,8 @@ public class CoordinatorEngine extends B
         if (logRetrievalScope != null && logRetrievalType != null) {
             // if coordinator action logs are to be retrieved based on action id range
             if (logRetrievalType.equals(RestConstants.JOB_LOG_ACTION)) {
-                Set<String> actions = new HashSet<String>();
+                // Use set implementation that maintains order or elements to achieve reproducibility:
+                Set<String> actionSet = new LinkedHashSet<String>();
                 String[] list = logRetrievalScope.split(",");
                 for (String s : list) {
                     s = s.trim();
@@ -299,7 +304,7 @@ public class CoordinatorEngine extends B
                             throw new CommandException(ErrorCode.E0302, "format is wrong for action's range '" + s + "'");
                         }
                         for (int i = start; i <= end; i++) {
-                            actions.add(jobId + "@" + i);
+                            actionSet.add(jobId + "@" + i);
                         }
                     }
                     else {
@@ -310,11 +315,11 @@ public class CoordinatorEngine extends B
                             throw new CommandException(ErrorCode.E0302, "format is wrong for action id'" + s
                                     + "'. Integer only.");
                         }
-                        actions.add(jobId + "@" + s);
+                        actionSet.add(jobId + "@" + s);
                     }
                 }
 
-                Iterator<String> actionsIterator = actions.iterator();
+                Iterator<String> actionsIterator = actionSet.iterator();
                 StringBuilder orSeparatedActions = new StringBuilder("");
                 boolean orRequired = false;
                 while (actionsIterator.hasNext()) {
@@ -324,7 +329,7 @@ public class CoordinatorEngine extends B
                     orSeparatedActions.append(actionsIterator.next().toString());
                     orRequired = true;
                 }
-                if (actions.size() > 1 && orRequired) {
+                if (actionSet.size() > 1 && orRequired) {
                     orSeparatedActions.insert(0, "(");
                     orSeparatedActions.append(")");
                 }
@@ -370,9 +375,9 @@ public class CoordinatorEngine extends B
     @Override
     public String submitJob(Configuration conf, boolean startJob) throws CoordinatorEngineException {
         try {
-			CoordSubmitXCommand submit = new CoordSubmitXCommand(conf,
-					getAuthToken());
-			return submit.call();
+            CoordSubmitXCommand submit = new CoordSubmitXCommand(conf,
+                    getAuthToken());
+            return submit.call();
         }
         catch (CommandException ex) {
             throw new CoordinatorEngineException(ex);
@@ -388,9 +393,9 @@ public class CoordinatorEngine extends B
     @Override
     public String dryRunSubmit(Configuration conf) throws CoordinatorEngineException {
         try {
-			CoordSubmitXCommand submit = new CoordSubmitXCommand(true, conf,
-					getAuthToken());
-			return submit.call();
+            CoordSubmitXCommand submit = new CoordSubmitXCommand(true, conf,
+                    getAuthToken());
+            return submit.call();
         }
         catch (CommandException ex) {
             throw new CoordinatorEngineException(ex);
@@ -405,7 +410,7 @@ public class CoordinatorEngine extends B
     @Override
     public void suspend(String jobId) throws CoordinatorEngineException {
         try {
-			new CoordSuspendXCommand(jobId).call();
+            new CoordSuspendXCommand(jobId).call();
         }
         catch (CommandException e) {
             throw new CoordinatorEngineException(e);
@@ -456,7 +461,7 @@ public class CoordinatorEngine extends B
         Map<String, List<String>> filterList = parseFilter(filter);
 
         try {
-			return new CoordJobsXCommand(filterList, start, len).call();
+            return new CoordJobsXCommand(filterList, start, len).call();
         }
         catch (CommandException ex) {
             throw new CoordinatorEngineException(ex);
@@ -489,7 +494,7 @@ public class CoordinatorEngine extends B
                             }
                             // Check for incorrect status value
                             throw new CoordinatorEngineException(ErrorCode.E0421, filter, XLog.format(
-                                    "invalid status value [{0}]." + " Valid status values are: [{1}]", statusValue, validStatusList));
+                                "invalid status value [{0}]." + " Valid status values are: [{1}]", statusValue, validStatusList));
                         }
                         filterList.add(statusValue);
                     } else {
@@ -511,7 +516,8 @@ public class CoordinatorEngine extends B
      * @return Map<String, List<String>>
      * @throws CoordinatorEngineException
      */
-    private Map<String, List<String>> parseFilter(String filter) throws CoordinatorEngineException {
+    @VisibleForTesting
+    Map<String, List<String>> parseFilter(String filter) throws CoordinatorEngineException {
         Map<String, List<String>> map = new HashMap<String, List<String>>();
         boolean isTimeUnitSpecified = false;
         String timeUnit = "MINUTE";

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorJobBean.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorJobBean.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorJobBean.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/CoordinatorJobBean.java Wed May 15 23:07:36 2013
@@ -461,7 +461,7 @@ public class CoordinatorJobBean extends 
         setTimeUnit(CoordinatorJob.Timeunit.valueOf(WritableUtils.readStr(dataInput)));
         setTimeZone(WritableUtils.readStr(dataInput));
         setConcurrency(dataInput.readInt());
-        setExecutionOrder(Execution.valueOf(WritableUtils.readStr(dataInput)));
+        setExecution(Execution.valueOf(WritableUtils.readStr(dataInput)));
 
         long d = dataInput.readLong();
         if (d != -1) {

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/SLAEventBean.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/SLAEventBean.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/SLAEventBean.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/SLAEventBean.java Wed May 15 23:07:36 2013
@@ -21,9 +21,7 @@ import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.text.MessageFormat;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
 
 import javax.persistence.Basic;
 import javax.persistence.Column;
@@ -32,13 +30,10 @@ import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
 
 import org.apache.hadoop.io.Writable;
-import org.apache.oozie.client.SLAEvent;
 import org.apache.oozie.client.rest.JsonSLAEvent;
 import org.apache.oozie.util.DateUtils;
 import org.apache.oozie.util.XLog;
 import org.jdom.Element;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
 
 @Entity
 @NamedQueries({
@@ -183,39 +178,6 @@ public class SLAEventBean extends JsonSL
         return MessageFormat.format("Event id[{0}] status[{1}]", getEvent_id(), getJobStatus());
     }
 
-    /**
-     * Convert a SLAEvent list into a JSONArray.
-     *
-     * @param SLAEVent list.
-     * @param timeZoneId time zone to use for dates in the JSON array.
-     * @return the corresponding JSON array.
-     */
-    @SuppressWarnings("unchecked")
-    public static JSONArray toJSONArray(List<? extends SLAEventBean> events, String timeZoneId) {
-        JSONArray array = new JSONArray();
-        if (events != null) {
-            for (JsonSLAEvent node : events) {
-                array.add(node.toJSONObject(timeZoneId));
-            }
-        }
-        return array;
-    }
-
-    /**
-     * Convert a JSONArray into a SLAEvent list.
-     *
-     * @param array JSON array.
-     * @return the corresponding SLA event list.
-     */
-    @SuppressWarnings("unchecked")
-    public static List<SLAEvent> fromJSONArray(JSONArray array) {
-        List<SLAEvent> list = new ArrayList<SLAEvent>();
-        for (Object obj : array) {
-            list.add(new JsonSLAEvent((JSONObject) obj));
-        }
-        return list;
-    }
-
     public Element toXml() {
         Element retElem = null;
         if (getJobStatus() == Status.CREATED) {
@@ -285,12 +247,6 @@ public class SLAEventBean extends JsonSL
         return e;
     }
 
-    private Element createATagElement(String tag, Element content) {
-        Element e = new Element(tag);
-        e.addContent(content);
-        return e;
-    }
-
     private String getDateString(Date d) {
         try {
             return DateUtils.formatDateOozieTZ(d);

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/action/ssh/SshActionExecutor.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/action/ssh/SshActionExecutor.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/action/ssh/SshActionExecutor.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/action/ssh/SshActionExecutor.java Wed May 15 23:07:36 2013
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -492,7 +492,8 @@ public class SshActionExecutor extends A
     private void initSshScripts() {
         String dirLocation = Services.get().getRuntimeDir() + "/ssh";
         File path = new File(dirLocation);
-        if (!path.mkdirs()) {
+        path.mkdirs();
+        if (!path.exists()) {
             throw new RuntimeException(XLog.format("Not able to create required directory {0}", dirLocation));
         }
         try {
@@ -586,17 +587,17 @@ public class SshActionExecutor extends A
                                 } // Permission denied while connecting
                                 else {
                                     if (errorMessage.contains("Permission denied")) {
-                                        throw new ActionExecutorException(ActionExecutorException.ErrorType.NON_TRANSIENT, ERR_AUTH_FAILED, ex
-                                                .getMessage(), ex);
+                                        throw new ActionExecutorException(ActionExecutorException.ErrorType.NON_TRANSIENT,
+                                                ERR_AUTH_FAILED, ex.getMessage(), ex);
                                     } // Permission denied while executing
                                     else {
                                         if (errorMessage.contains(": Permission denied")) {
-                                            throw new ActionExecutorException(ActionExecutorException.ErrorType.NON_TRANSIENT, ERR_NO_EXEC_PERM, ex
-                                                    .getMessage(), ex);
+                                            throw new ActionExecutorException(ActionExecutorException.ErrorType.NON_TRANSIENT,
+                                                    ERR_NO_EXEC_PERM, ex.getMessage(), ex);
                                         }
                                         else {
-                                            throw new ActionExecutorException(ActionExecutorException.ErrorType.ERROR, ERR_UNKNOWN_ERROR, ex
-                                                    .getMessage(), ex);
+                                            throw new ActionExecutorException(ActionExecutorException.ErrorType.ERROR,
+                                                    ERR_UNKNOWN_ERROR, ex.getMessage(), ex);
                                         }
                                     }
                                 }
@@ -631,7 +632,8 @@ public class SshActionExecutor extends A
             if (host.contains("@")) {
                 if (!host.toLowerCase().startsWith(oozieUser + "@")) {
                     throw new ActionExecutorException(ActionExecutorException.ErrorType.ERROR, ERR_USER_MISMATCH,
-                                                      XLog.format("user mismatch between oozie user [{0}] and ssh host [{1}]", oozieUser, host));
+                                                      XLog.format("user mismatch between oozie user [{0}] and ssh host [{1}]",
+                                                              oozieUser, host));
                 }
             }
             else {
@@ -641,6 +643,7 @@ public class SshActionExecutor extends A
         return host;
     }
 
+    @Override
     public boolean isCompleted(String externalStatus) {
         return true;
     }

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/util/CoordActionsInDateRange.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/util/CoordActionsInDateRange.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/util/CoordActionsInDateRange.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/util/CoordActionsInDateRange.java Wed May 15 23:07:36 2013
@@ -21,7 +21,7 @@ package org.apache.oozie.util;
 import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -45,7 +45,8 @@ public class CoordActionsInDateRange {
      * Get the list of Coordinator action Ids for given date ranges
      *
      * @param jobId coordinator job id
-     * @param scope the date range for log. format is comma-separated list of date ranges. Each date range element is specified with two dates separated by '::'
+     * @param scope the date range for log. format is comma-separated list of date ranges.
+     * Each date range element is specified with two dates separated by '::'
      * @return the list of coordinator action Ids for the date range
      *
      * Internally involves a database operation by invoking method 'getActionIdsFromDateRange'.
@@ -53,7 +54,8 @@ public class CoordActionsInDateRange {
     public static List<String> getCoordActionIdsFromDates(String jobId, String scope) throws XException {
         ParamChecker.notEmpty(jobId, "jobId");
         ParamChecker.notEmpty(scope, "scope");
-        Set<String> actionSet = new HashSet<String>();
+        // Use an ordered set to achieve reproducible behavior.
+        Set<String> actionSet = new LinkedHashSet<String>();
         String[] list = scope.split(",");
         for (String s : list) {
             s = s.trim();
@@ -79,7 +81,9 @@ public class CoordActionsInDateRange {
             String[] dateRange = range.split("::");
             // This block checks for errors in the format of specifying date range
             if (dateRange.length != 2) {
-                throw new XException(ErrorCode.E0308, "'" + range + "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
+                throw new XException(ErrorCode.E0308, "'" + range +
+                    "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
+
             }
             Date start;
             Date end;
@@ -92,7 +96,8 @@ public class CoordActionsInDateRange {
                 throw new XException(ErrorCode.E0308, "Error in parsing start or end date. " + dx);
             }
             if (start.after(end)) {
-                throw new XException(ErrorCode.E0308, "'" + range + "'. Start date '" + start + "' is older than end date: '" + end + "'");
+                throw new XException(ErrorCode.E0308, "'" + range + "'. Start date '" + start + "' is older than end date: '" + end
+                        + "'");
             }
             List<CoordinatorActionBean> listOfActions = getActionsFromDateRange(jobId, start, end);
             return listOfActions;
@@ -109,7 +114,9 @@ public class CoordActionsInDateRange {
             String[] dateRange = range.split("::");
             // This block checks for errors in the format of specifying date range
             if (dateRange.length != 2) {
-                throw new XException(ErrorCode.E0308, "'" + range + "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
+                throw new XException(ErrorCode.E0308, "'" + range
+                  + "'. Date value expected on both sides of the scope resolution operator '::' to signify start and end of range");
+
             }
             Date start;
             Date end;
@@ -122,7 +129,8 @@ public class CoordActionsInDateRange {
                 throw new XException(ErrorCode.E0308, "Error in parsing start or end date. " + dx);
             }
             if (start.after(end)) {
-                throw new XException(ErrorCode.E0308, "'" + range + "'. Start date '" + start + "' is older than end date: '" + end + "'");
+                throw new XException(ErrorCode.E0308, "'" + range + "'. Start date '" + start + "' is older than end date: '" + end
++ "'");
             }
             List<String> list = null;
             JPAService jpaService = Services.get().get(JPAService.class);

Modified: oozie/trunk/core/src/main/java/org/apache/oozie/util/XLogStreamer.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/main/java/org/apache/oozie/util/XLogStreamer.java?rev=1483122&r1=1483121&r2=1483122&view=diff
==============================================================================
--- oozie/trunk/core/src/main/java/org/apache/oozie/util/XLogStreamer.java (original)
+++ oozie/trunk/core/src/main/java/org/apache/oozie/util/XLogStreamer.java Wed May 15 23:07:36 2013
@@ -33,6 +33,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.zip.GZIPInputStream;
 
+import com.google.common.annotations.VisibleForTesting;
+
 /**
  * XLogStreamer streams the given log file to logWriter after applying the given filter.
  */
@@ -46,7 +48,7 @@ public class XLogStreamer {
      */
     public static class Filter {
         private Map<String, Integer> logLevels;
-        private Map<String, String> filterParams;
+        private final Map<String, String> filterParams;
         private static List<String> parameters = new ArrayList<String>();
         private boolean noFilter;
         private Pattern filterPattern;
@@ -172,6 +174,11 @@ public class XLogStreamer {
         public static void reset() {
             parameters.clear();
         }
+
+        @VisibleForTesting
+        public final Map<String, String> getFilterParams() {
+          return filterParams;
+        }
     }
 
     private String logFile;
@@ -312,7 +319,7 @@ public class XLogStreamer {
         Collections.sort(fileList);
         return fileList;
     }
-    
+
     /**
      * This pattern matches the end of a gzip filename to have a format like "-YYYY-MM-dd-HH.gz" with capturing groups for each part
      * of the date
@@ -330,7 +337,7 @@ public class XLogStreamer {
     private long getGZFileCreationTime(String fileName, long startTime, long endTime) {
         // Default return value of -1 to exclude the file
         long returnVal = -1;
-        
+
         // Include oozie.log as oozie.log.gz if it is accidentally GZipped
         if (fileName.equals("oozie.log.gz")) {
             LOG.warn("oozie.log has been GZipped, which is unexpected");

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleEngineSimple.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleEngineSimple.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleEngineSimple.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleEngineSimple.java Wed May 15 23:07:36 2013
@@ -0,0 +1,191 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import junit.framework.TestCase;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.oozie.client.CoordinatorJob;
+import org.apache.oozie.client.WorkflowJob;
+import org.apache.oozie.client.rest.BulkResponseImpl;
+
+/**
+ * Test non-argument constructor and methods of {@link BundleEngine} that either throw exceptions or return null.
+ * {@link BundleEngineException} covered as well.
+ */
+public class TestBundleEngineSimple extends TestCase {
+
+    public void testGetCoordJob1() {
+        BundleEngine be = new BundleEngine();
+        try {
+            CoordinatorJob cj = be.getCoordJob("foo");
+            fail("Expected BundleEngineException was not thrown.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0301, bee.getErrorCode());
+        }
+    }
+
+    public void testGetCoordJob4() {
+        BundleEngine be = new BundleEngine();
+        try {
+            CoordinatorJob cj = be.getCoordJob("foo", "filter", 0, 1);
+            fail("Expected BundleEngineException was not thrown.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0301, bee.getErrorCode());
+        }
+    }
+
+    public void testGetJob1() {
+        BundleEngine be = new BundleEngine();
+        try {
+            WorkflowJob wj = be.getJob("foo");
+            fail("Expected BundleEngineException was not thrown.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0301, bee.getErrorCode());
+        }
+    }
+
+    public void testGetJob3() {
+        BundleEngine be = new BundleEngine();
+        try {
+            WorkflowJob wj = be.getJob("foo", 0, 1);
+            fail("Expected BundleEngineException was not thrown.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0301, bee.getErrorCode());
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testReRun2() {
+        BundleEngine be = new BundleEngine();
+        try {
+            Configuration c = new Configuration();
+            be.reRun("foo", c);
+            fail("Expected BundleEngineException was not thrown.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0301, bee.getErrorCode());
+        }
+    }
+
+    public void testGetJobForExternalId() throws BundleEngineException {
+        BundleEngine be = new BundleEngine();
+        String job = be.getJobIdForExternalId("externalFoo");
+        assertNull(job);
+    }
+
+    /**
+     * Test negative cases of the filter parsing by
+     * {@link BundleEngine#parseFilter(String)}.
+     */
+    public void testParseFilterNegative() {
+        BundleEngine be = new BundleEngine();
+        // no eq sign in token:
+        try {
+            be.parseFilter("winniethepooh");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // incorrect key=value pair syntax:
+        try {
+            be.parseFilter("xx=yy=zz");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // unknown key in key=value pair:
+        try {
+            be.parseFilter("foo=moo");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // incorrect "status" key value:
+        try {
+            be.parseFilter("status=foo");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+    }
+
+    /**
+     * Test negative cases of method
+     * {@link BundleEngine#parseBulkFilter(String)}
+     */
+    public void testParseBulkFilterNegative() {
+        // incorrect key=value pair syntax:
+        try {
+            BundleEngine.parseBulkFilter("xx=yy=zz");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(bee.toString(), ErrorCode.E0420, bee.getErrorCode());
+        }
+        // no eq sign in token:
+        try {
+            BundleEngine.parseBulkFilter("winniethepooh");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(bee.toString(), ErrorCode.E0420, bee.getErrorCode());
+        }
+        // one of the values is a whitespace:
+        try {
+            BundleEngine.parseBulkFilter(BulkResponseImpl.BULK_FILTER_BUNDLE_NAME + "=aaa, ,bbb");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(bee.toString(), ErrorCode.E0420, bee.getErrorCode());
+        }
+        // unparseable time value:
+        try {
+            BundleEngine.parseBulkFilter(BulkResponseImpl.BULK_FILTER_START_CREATED_EPOCH + "=blah-blah");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(bee.toString(), ErrorCode.E0420, bee.getErrorCode());
+        }
+        // incorrect status:
+        try {
+            BundleEngine.parseBulkFilter(BulkResponseImpl.BULK_FILTER_STATUS + "=foo");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(bee.toString(), ErrorCode.E0420, bee.getErrorCode());
+        }
+        // filter does not contain "BulkResponseImpl.BULK_FILTER_BUNDLE_NAME" field:
+        try {
+            BundleEngine.parseBulkFilter(BulkResponseImpl.BULK_FILTER_LEVEL + "=foo");
+            fail("BundleEngineException expected.");
+        }
+        catch (BundleEngineException bee) {
+            assertEquals(bee.toString(), ErrorCode.E0305, bee.getErrorCode());
+        }
+    }
+
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleJobBean.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleJobBean.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleJobBean.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestBundleJobBean.java Wed May 15 23:07:36 2013
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Date;
+
+import org.apache.oozie.client.BundleJob.Timeunit;
+import org.apache.oozie.client.Job.Status;
+import org.apache.oozie.test.XTestCase;
+import org.apache.oozie.util.DateUtils;
+
+public class TestBundleJobBean extends XTestCase {
+
+    private static final Date ct = new Date(1L);
+    private static final Date et = new Date(2L);
+    private static final Date st = new Date(3L);
+    private static final Date kt = new Date(4L);
+    private static final Date lmt = new Date(5L);
+    private static final Date pt = new Date(7L);
+    private static final Date spt = new Date(8L);
+
+    private void set(BundleJobBean bean) {
+        bean.setAppName("an");
+        bean.setAppPath("ap");
+        bean.setAuthToken("at");
+        bean.setConf("c");
+        bean.setConsoleUrl("cu");
+        bean.setCreatedTime(ct);
+        bean.setEndTime(et);
+        bean.setEndTimestamp(DateUtils.convertDateToTimestamp(et));
+        bean.setExternalId("ei");
+        bean.setGroup("group");
+        bean.setId("id");
+        bean.setJobXml("jx");
+        bean.setKickoffTime(kt);
+        bean.setKickoffTimestamp(DateUtils.convertDateToTimestamp(kt));
+        bean.setLastModifiedTime(lmt);
+        bean.setLastModifiedTimestamp(DateUtils.convertDateToTimestamp(lmt));
+        bean.setOrigJobXml("ojx");
+        bean.setPauseTime(pt);
+        bean.setPending();
+        bean.setStartTime(st);
+        bean.setStartTimestamp(DateUtils.convertDateToTimestamp(st));
+        bean.setStatus(Status.KILLED);
+        bean.setSuspendedTime(spt);
+        bean.setSuspendedTimestamp(DateUtils.convertDateToTimestamp(spt));
+        bean.setTimeOut(11);
+        bean.setTimeUnit(Timeunit.MINUTE);
+        bean.setUser("u");
+    }
+
+    /**
+     * Test {@link BundleJobBean} get- and set- methods.
+     */
+    public void testSetGet() {
+        final BundleJobBean bean = new BundleJobBean();
+        set(bean);
+        _testGet(bean, true);
+    }
+
+    @SuppressWarnings("deprecation")
+    private void _testGet(BundleJobBean bean, boolean checkAllFields) {
+        assertEquals("an", bean.getAppName());
+        assertEquals("ap", bean.getAppPath());
+        if (checkAllFields) {
+            assertEquals("at", bean.getAuthToken());
+        }
+        assertEquals("c", bean.getConf());
+        if (checkAllFields) {
+            assertEquals("cu", bean.getConsoleUrl());
+            assertEquals(ct, bean.getCreatedTime());
+        }
+        assertEquals(et, bean.getEndTime());
+        assertEquals(DateUtils.convertDateToTimestamp(et), bean.getEndTimestamp());
+        assertEquals("ei", bean.getExternalId());
+        assertEquals("group", bean.getGroup());
+        assertEquals("id", bean.getId());
+        if (checkAllFields) {
+            assertEquals("jx", bean.getJobXml());
+        }
+        assertEquals(kt, bean.getKickoffTime());
+        assertEquals(DateUtils.convertDateToTimestamp(kt), bean.getKickoffTimestamp());
+        if (checkAllFields) {
+            assertEquals(lmt, bean.getLastModifiedTime());
+            assertEquals(DateUtils.convertDateToTimestamp(lmt), bean.getLastModifiedTimestamp());
+        }
+        if (checkAllFields) {
+            assertEquals("ojx", bean.getOrigJobXml());
+            assertEquals(pt, bean.getPauseTime());
+            assertEquals(true, bean.isPending());
+        }
+        assertEquals(st, bean.getStartTime());
+        assertEquals(Status.KILLED, bean.getStatus());
+        if (checkAllFields) {
+            assertEquals(DateUtils.convertDateToTimestamp(spt), bean.getSuspendedTimestamp());
+        }
+        assertEquals(11, bean.getTimeout());
+        assertEquals(Timeunit.MINUTE, bean.getTimeUnit());
+        assertEquals("u", bean.getUser());
+    }
+
+    /**
+     * Test {@link BundleJobBean} serialization and deserialization.
+     */
+    public void testSerialization() throws IOException {
+        final BundleJobBean bean = new BundleJobBean();
+
+        set(bean);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        DataOutputStream dos = new DataOutputStream(baos);
+        bean.write(dos);
+        dos.close();
+
+        final BundleJobBean bean2 = new BundleJobBean();
+        bean2.readFields(new DataInputStream(new ByteArrayInputStream(baos.toByteArray())));
+
+        _testGet(bean2, false);
+    }
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineSimple.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineSimple.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineSimple.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineSimple.java Wed May 15 23:07:36 2013
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.oozie.service.Services;
+import org.apache.oozie.test.XTestCase;
+import org.junit.Test;
+
+public class TestCoordinatorEngineSimple extends XTestCase {
+
+    private Services services;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        services = new Services();
+        services.init();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        services.destroy();
+        super.tearDown();
+    }
+
+    @Test
+    public void testParseFilterNegative() throws CoordinatorEngineException {
+        final CoordinatorEngine ce = new CoordinatorEngine();
+
+        // null argument:
+        Map<String, List<String>> map = ce.parseFilter(null);
+        assertNotNull(map);
+        assertEquals(0, map.size());
+
+        // empty String:
+        map = ce.parseFilter("");
+        assertNotNull(map);
+        assertEquals(0, map.size());
+
+        // no eq sign in token:
+        try {
+            ce.parseFilter("winniethepooh");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // incorrect k=v:
+        try {
+            map = ce.parseFilter("kk=vv=zz");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException cee) {
+            assertEquals(ErrorCode.E0420, cee.getErrorCode());
+        }
+        // unknown key in key=value pair:
+        try {
+            ce.parseFilter("foo=moo");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // incorrect "status" key value:
+        try {
+            ce.parseFilter("status=foo");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // unparseable "frequency" value:
+        try {
+            ce.parseFilter("FreQuency=foo");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // unparseable "unit" value:
+        try {
+            ce.parseFilter("UniT=foo");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+        // "unit" specified, but "frequency" is not:
+        try {
+            ce.parseFilter("unit=minutes");
+            fail("CoordinatorEngineException expected.");
+        }
+        catch (CoordinatorEngineException bee) {
+            assertEquals(ErrorCode.E0420, bee.getErrorCode());
+        }
+    }
+
+    @Test
+    public void testParseFilterPositive() throws CoordinatorEngineException {
+        final CoordinatorEngine ce = new CoordinatorEngine();
+
+        Map<String, List<String>> map = ce.parseFilter("frequency=5;unit=hours;user=foo;status=FAILED");
+        assertEquals(4, map.size());
+        assertEquals("300", map.get("frequency").get(0));
+        assertEquals("MINUTE", map.get("unit").get(0));
+        assertEquals("foo", map.get("user").get(0));
+        assertEquals("FAILED", map.get("status").get(0));
+    }
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineStreamLog.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineStreamLog.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineStreamLog.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorEngineStreamLog.java Wed May 15 23:07:36 2013
@@ -0,0 +1,238 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.oozie.client.CoordinatorAction;
+import org.apache.oozie.client.OozieClient;
+import org.apache.oozie.client.rest.RestConstants;
+import org.apache.oozie.service.DagXLogInfoService;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.service.XLogService;
+import org.apache.oozie.test.XFsTestCase;
+import org.apache.oozie.util.DateUtils;
+import org.apache.oozie.util.IOUtils;
+import org.apache.oozie.util.XConfiguration;
+import org.apache.oozie.util.XLogStreamer.Filter;
+
+public class TestCoordinatorEngineStreamLog extends XFsTestCase {
+    private Services services;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        services = new Services();
+        services.init();
+        cleanUpDBTables();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        services.destroy();
+        super.tearDown();
+    }
+
+    private void writeToFile(String appXml, String appPath) throws Exception {
+        File wf = new File(new URI(appPath).getPath());
+        PrintWriter out = null;
+        try {
+            out = new PrintWriter(new FileWriter(wf));
+            out.println(appXml);
+        }
+        catch (IOException iex) {
+            throw iex;
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    static class DummyXLogService extends XLogService {
+        Filter filter;
+
+        @Override
+        public void streamLog(Filter filter1, Date startTime, Date endTime, Writer writer) throws IOException {
+            filter = filter1;
+        }
+    }
+
+    private CoordinatorEngine createCoordinatorEngine() {
+        return new CoordinatorEngine(getTestUser(), "UNIT_TESTING");
+    }
+
+    /**
+     * The log streaming itself is tested in
+     * {@link org.apache.oozie.service.TestXLogService}. Here we test only the
+     * fields that are injected into
+     * {@link org.apache.oozie.util.XLogStreamer.Filter} upon
+     * {@link CoordinatorEngine#streamLog(String, Writer)} invocation.
+     */
+    public void testStreamLog2() throws Exception {
+        CoordinatorEngine ce = createCoordinatorEngine();
+        String jobId = runJobsImpl(ce);
+        ce.streamLog(jobId, new StringWriter()/* writer is unused */);
+
+        DummyXLogService service = (DummyXLogService) services.get(XLogService.class);
+        Filter filter = service.filter;
+
+        assertEquals(filter.getFilterParams().get(DagXLogInfoService.JOB), jobId);
+    }
+
+    /**
+     * Test method org.apache.oozie.CoordinatorEngine.streamLog(String, String,
+     * String, Writer) with null 2nd and 3rd arguments.
+     */
+    public void testStreamLog4NullNull() throws Exception {
+        CoordinatorEngine ce = createCoordinatorEngine();
+        String jobId = runJobsImpl(ce);
+        ce.streamLog(jobId, null, null, new StringWriter()/* writer is unused */);
+
+        DummyXLogService service = (DummyXLogService) services.get(XLogService.class);
+        Filter filter = service.filter;
+
+        assertEquals(filter.getFilterParams().get(DagXLogInfoService.JOB), jobId);
+    }
+
+    /**
+     * Test method org.apache.oozie.CoordinatorEngine.streamLog(String, String,
+     * String, Writer) with RestConstants.JOB_LOG_ACTION and non-null 2nd
+     * argument.
+     */
+    public void testStreamLog4JobLogAction() throws Exception {
+        CoordinatorEngine ce = createCoordinatorEngine();
+        String jobId = runJobsImpl(ce);
+
+        ce.streamLog(jobId, "678, 123-127, 946", RestConstants.JOB_LOG_ACTION, new StringWriter()/* unused */);
+
+        DummyXLogService service = (DummyXLogService) services.get(XLogService.class);
+        Filter filter = service.filter;
+
+        assertEquals(jobId, filter.getFilterParams().get(DagXLogInfoService.JOB));
+        assertEquals("(" + jobId + "@678|" + jobId + "@123|" + jobId + "@124|" + jobId + "@125|" + jobId + "@126|" + jobId
+                + "@127|" + jobId + "@946)", filter.getFilterParams().get(DagXLogInfoService.ACTION));
+    }
+
+    /**
+     * Test method org.apache.oozie.CoordinatorEngine.streamLog(String, String,
+     * String, Writer) with RestConstants.JOB_LOG_DATE.
+     */
+    public void testStreamLog4JobLogDate() throws Exception {
+        CoordinatorEngine ce = createCoordinatorEngine();
+        final String jobId = runJobsImpl(ce);
+
+        CoordinatorJobBean cjb = ce.getCoordJob(jobId);
+        Date createdDate = cjb.getCreatedTime();
+        Date endDate = new Date();
+        assertTrue(endDate.after(createdDate));
+
+        long middle = (createdDate.getTime() + endDate.getTime()) / 2;
+        Date middleDate = new Date(middle);
+
+        ce.streamLog(jobId, DateUtils.formatDateOozieTZ(createdDate) + "::" + DateUtils.formatDateOozieTZ(middleDate) + ","
+                + DateUtils.formatDateOozieTZ(middleDate) + "::" + DateUtils.formatDateOozieTZ(endDate),
+                RestConstants.JOB_LOG_DATE, new StringWriter()/* unused */);
+
+        DummyXLogService service = (DummyXLogService) services.get(XLogService.class);
+        Filter filter = service.filter;
+
+        assertEquals(jobId, filter.getFilterParams().get(DagXLogInfoService.JOB));
+        final String action = filter.getFilterParams().get(DagXLogInfoService.ACTION);
+        assertEquals("(" + jobId + "@1|" + jobId + "@2)", action);
+    }
+
+    private String runJobsImpl(final CoordinatorEngine ce) throws Exception {
+        services.setService(DummyXLogService.class);
+        // need to re-define the parameters that are cleared upon the service reset:
+        new DagXLogInfoService().init(services);
+        services.init();
+
+        Configuration conf = new XConfiguration();
+
+        final String appPath = "file://" + getTestCaseDir() + File.separator + "coordinator.xml";
+        final long now = System.currentTimeMillis();
+        final String start = DateUtils.formatDateOozieTZ(new Date(now));
+        long e = now + 1000 * 119;
+        final String end = DateUtils.formatDateOozieTZ(new Date(e));
+
+        String wfXml = IOUtils.getResourceAsString("wf-no-op.xml", -1);
+        writeToFile(wfXml, getFsTestCaseDir(), "workflow.xml");
+
+        String appXml = "<coordinator-app name=\"NAME\" frequency=\"${coord:minutes(1)}\" start=\"" + start + "\" end=\"" + end
+                + "\" timezone=\"UTC\" " + "xmlns=\"uri:oozie:coordinator:0.1\"> " + "<controls> " + "  <timeout>10</timeout> "
+                + "  <concurrency>1</concurrency> " + "  <execution>LIFO</execution> " + "</controls> " + "<action> "
+                + "  <workflow> " + "  <app-path>" + getFsTestCaseDir() + "/workflow.xml</app-path>"
+                + "  <configuration> <property> <name>inputA</name> <value>valueA</value> </property> "
+                + "  <property> <name>inputB</name> <value>valueB</value> " + "  </property></configuration> " + "</workflow>"
+                + "</action> " + "</coordinator-app>";
+        writeToFile(appXml, appPath);
+        conf.set(OozieClient.COORDINATOR_APP_PATH, appPath);
+        conf.set(OozieClient.USER_NAME, getTestUser());
+
+        final String jobId = ce.submitJob(conf, true);
+        waitFor(1000 * 119, new Predicate() {
+            @Override
+            public boolean evaluate() throws Exception {
+                try {
+                    List<CoordinatorAction> actions = ce.getCoordJob(jobId).getActions();
+                    if (actions.size() < 1) {
+                        return false;
+                    }
+                    for (CoordinatorAction action : actions) {
+                        CoordinatorAction.Status actionStatus = action.getStatus();
+                        if (actionStatus != CoordinatorAction.Status.SUCCEEDED) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+                catch (Exception ex) {
+                    ex.printStackTrace();
+                    return false;
+                }
+            }
+        });
+        // Assert all the actions are succeeded (useful for waitFor() timeout case):
+        final List<CoordinatorAction> actions = ce.getCoordJob(jobId).getActions();
+        for (CoordinatorAction action: actions) {
+          assertEquals(CoordinatorAction.Status.SUCCEEDED, action.getStatus());
+        }
+        return jobId;
+    }
+
+    private void writeToFile(String content, Path appPath, String fileName) throws IOException {
+        FileSystem fs = getFileSystem();
+        Writer writer = new OutputStreamWriter(fs.create(new Path(appPath, fileName), true));
+        writer.write(content);
+        writer.close();
+    }
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorJobBean.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorJobBean.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorJobBean.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestCoordinatorJobBean.java Wed May 15 23:07:36 2013
@@ -0,0 +1,182 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.oozie.client.CoordinatorJob.Execution;
+import org.apache.oozie.client.CoordinatorJob.Timeunit;
+import org.apache.oozie.client.Job.Status;
+import org.apache.oozie.client.rest.JsonCoordinatorAction;
+import org.apache.oozie.test.XTestCase;
+import org.apache.oozie.util.DateUtils;
+
+public class TestCoordinatorJobBean extends XTestCase {
+
+    private static final Date ct = new Date(1L);
+    private static final Date et = new Date(2L);
+    private static final Date st = new Date(3L);
+    private static final Date lat = new Date(4L);
+    private static final Date lmt = new Date(5L);
+    private static final Date nmt = new Date(6L);
+    private static final Date pt = new Date(7L);
+    private static final Date spt = new Date(8L);
+    private static final List<? extends JsonCoordinatorAction> actionList = Collections.singletonList(new CoordinatorActionBean());
+    private static final Execution execution = Execution.LIFO;
+
+    private void set(CoordinatorJobBean bean) {
+        bean.setActions(actionList);
+        bean.setAppName("an");
+        bean.setAppNamespace("ans");
+        bean.setAppPath("ap");
+        bean.setAuthToken("at");
+        bean.setBundleId("bi");
+        bean.setConcurrency(2);
+        bean.setConf("c");
+        bean.setConsoleUrl("cu");
+        bean.setCreatedTime(ct);
+        bean.setDoneMaterialization();
+        bean.setEndTime(et);
+        bean.setEndTimestamp(DateUtils.convertDateToTimestamp(et));
+        bean.setExecution(execution);
+        bean.setExecutionOrder(execution);
+        bean.setExternalId("ei");
+        bean.setFrequency(3);
+        bean.setGroup("group");
+        bean.setId("id");
+        bean.setJobXml("jx");
+        bean.setLastActionNumber(4);
+        bean.setLastActionTime(lat);
+        bean.setLastActionTimestamp(DateUtils.convertDateToTimestamp(lat));
+        bean.setLastModifiedTime(lmt);
+        bean.setLastModifiedTimestamp(DateUtils.convertDateToTimestamp(lmt));
+        bean.setMatThrottling(10);
+        bean.setNextMaterializedTime(nmt);
+        bean.setNextMaterializedTimestamp(DateUtils.convertDateToTimestamp(nmt));
+        bean.setOrigJobXml("ojx");
+        bean.setPauseTime(pt);
+        bean.setPending();
+        bean.setSlaXml("sx");
+        bean.setStartTime(st);
+        bean.setStartTimestamp(DateUtils.convertDateToTimestamp(st));
+        bean.setStatus(Status.KILLED);
+        bean.setSuspendedTime(spt);
+        bean.setSuspendedTimestamp(DateUtils.convertDateToTimestamp(spt));
+        bean.setTimeout(11);
+        bean.setTimeUnit(Timeunit.MINUTE);
+        bean.setTimeZone("GMT");
+        bean.setUser("u");
+    }
+
+    /**
+     * Test {@link CoordinatorJobBean} get- and set- methods.
+     */
+    public void testSetGet() {
+        final CoordinatorJobBean bean = new CoordinatorJobBean();
+        set(bean);
+        _testGet(bean, true);
+    }
+
+    private void _testGet(CoordinatorJobBean bean, boolean checkDeserialization) {
+        if (checkDeserialization) {
+            assertEquals(actionList, bean.getActions());
+        }
+        assertEquals("an", bean.getAppName());
+        assertEquals("ans", bean.getAppNamespace());
+        assertEquals("ap", bean.getAppPath());
+        if (checkDeserialization) {
+            assertEquals("at", bean.getAuthToken());
+            assertEquals("bi", bean.getBundleId());
+        }
+        assertEquals(2, bean.getConcurrency());
+        assertEquals("c", bean.getConf());
+        if (checkDeserialization) {
+            assertEquals("cu", bean.getConsoleUrl());
+            assertEquals(ct, bean.getCreatedTime());
+        }
+        assertEquals(true, bean.isDoneMaterialization());
+        assertEquals(et, bean.getEndTime());
+        assertEquals(DateUtils.convertDateToTimestamp(et), bean.getEndTimestamp());
+        if (checkDeserialization) {
+            assertEquals(execution.toString(), bean.getExecution());
+        }
+        assertEquals(execution, bean.getExecutionOrder());
+        assertEquals("ei", bean.getExternalId());
+        assertEquals(3, bean.getFrequency());
+        assertEquals("group", bean.getGroup());
+        assertEquals("id", bean.getId());
+        if (checkDeserialization) {
+            assertEquals("jx", bean.getJobXml());
+            assertEquals(4, bean.getLastActionNumber());
+        }
+        assertEquals(lat, bean.getLastActionTime());
+        assertEquals(DateUtils.convertDateToTimestamp(lat), bean.getLastActionTimestamp());
+        if (checkDeserialization) {
+            assertEquals(lmt, bean.getLastModifiedTime());
+            assertEquals(DateUtils.convertDateToTimestamp(lmt), bean.getLastModifiedTimestamp());
+        }
+        assertEquals(10, bean.getMatThrottling());
+        assertEquals(nmt, bean.getNextMaterializedTime());
+        assertEquals(DateUtils.convertDateToTimestamp(nmt), bean.getNextMaterializedTimestamp());
+        if (checkDeserialization) {
+            assertEquals("ojx", bean.getOrigJobXml());
+            assertEquals(pt, bean.getPauseTime());
+        }
+        assertEquals(true, bean.isPending());
+        if (checkDeserialization) {
+            assertEquals("sx", bean.getSlaXml());
+        }
+        assertEquals(st, bean.getStartTime());
+        assertEquals(DateUtils.convertDateToTimestamp(st), bean.getStartTimestamp());
+        assertEquals(Status.KILLED, bean.getStatus());
+        if (checkDeserialization) {
+            assertEquals(spt, bean.getSuspendedTime());
+            assertEquals(DateUtils.convertDateToTimestamp(spt), bean.getSuspendedTimestamp());
+        }
+        assertEquals(11, bean.getTimeout());
+        assertEquals(Timeunit.MINUTE, bean.getTimeUnit());
+        assertEquals("GMT", bean.getTimeZone());
+        assertEquals("u", bean.getUser());
+    }
+
+    /**
+     * Test {@link CoordinatorJobBean} serialization and deserialization.
+     */
+    public void testSerialization() throws IOException {
+        final CoordinatorJobBean bean = new CoordinatorJobBean();
+
+        set(bean);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        DataOutputStream dos = new DataOutputStream(baos);
+        bean.write(dos);
+        dos.close();
+
+        final CoordinatorJobBean bean2 = new CoordinatorJobBean();
+        bean2.readFields(new DataInputStream(new ByteArrayInputStream(baos.toByteArray())));
+
+        _testGet(bean2, false);
+    }
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestLocalOozieClientCoord.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestLocalOozieClientCoord.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestLocalOozieClientCoord.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestLocalOozieClientCoord.java Wed May 15 23:07:36 2013
@@ -0,0 +1,195 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+
+import org.apache.oozie.client.CoordinatorJob;
+import org.apache.oozie.client.OozieClient;
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.local.LocalOozie;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.test.XDataTestCase;
+
+public class TestLocalOozieClientCoord extends XDataTestCase {
+
+    private Services services;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        /*
+         * DB cleanup below is needed to clean up the job records possibly left by previously executed tests.
+         * For example, such records are left by test org.apache.oozie.executor.jpa.TestCoordActionUpdateJPAExecutor.
+         * Note that by default Oozie tests are executed in "filesystem" (in fact, arbitrary) order. This way problems caused
+         * by left records can be flaky (not reproduced constantly).
+         * Services re-init is needed for the DB cleanup.
+         */
+        services = new Services();
+        services.init();
+        cleanUpDBTables();
+
+        LocalOozie.start();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        LocalOozie.stop();
+        services.destroy();
+        super.tearDown();
+    }
+
+    public void testGetOozieUrl() {
+        OozieClient client = LocalOozie.getCoordClient();
+        assertEquals("localoozie", client.getOozieUrl());
+    }
+
+    public void testGetProtocolUrl() throws OozieClientException {
+        OozieClient client = LocalOozie.getCoordClient();
+        assertEquals("localoozie", client.getProtocolUrl());
+    }
+
+    public void testValidateWSVersion() throws OozieClientException {
+        OozieClient client = LocalOozie.getCoordClient();
+        client.validateWSVersion();
+    }
+
+    public void testHeaderMethods() {
+        OozieClient client = LocalOozie.getCoordClient();
+        client.setHeader("h", "v");
+        assertNull(client.getHeader("h"));
+        Iterator<String> hit = client.getHeaderNames();
+        assertFalse(hit.hasNext());
+        try {
+            hit.next();
+            fail("NoSuchElementException expected.");
+        }
+        catch (NoSuchElementException nsee) {
+            // expected
+        }
+        client.removeHeader("h");
+        assertNull(client.getHeader("h"));
+    }
+
+    public void testGetJobsInfo() {
+        OozieClient client = LocalOozie.getCoordClient();
+        try {
+            client.getJobsInfo("foo");
+            fail("OozieClientException expected.");
+        }
+        catch (OozieClientException oce) {
+            assertEquals(ErrorCode.E0301.toString(), oce.getErrorCode());
+        }
+        try {
+            client.getJobsInfo("foo", 0, 5);
+            fail("OozieClientException expected.");
+        }
+        catch (OozieClientException oce) {
+            assertEquals(ErrorCode.E0301.toString(), oce.getErrorCode());
+        }
+        try {
+            client.getJobInfo("foo-id");
+            fail("OozieClientException expected.");
+        }
+        catch (OozieClientException oce) {
+            assertEquals(ErrorCode.E0301.toString(), oce.getErrorCode());
+        }
+    }
+
+    public void testReRun2() {
+        OozieClient client = LocalOozie.getCoordClient();
+        try {
+            client.reRun("foo-id", client.createConfiguration());
+            fail("OozieClientException expected.");
+        }
+        catch (OozieClientException oce) {
+            assertEquals(ErrorCode.E0301.toString(), oce.getErrorCode());
+        }
+    }
+
+    private void writeToFile(String appXml, String appPath) throws Exception {
+        File wf = new File(new URI(appPath).getPath());
+        PrintWriter out = null;
+        try {
+            out = new PrintWriter(new FileWriter(wf));
+            out.println(appXml);
+        }
+        catch (IOException iex) {
+            throw iex;
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    public void testJobMethods() throws Exception {
+        final OozieClient client = LocalOozie.getCoordClient();
+
+        // Just in case, check that there are no Coord job records left by previous tests:
+        List<CoordinatorJob> list0 = client.getCoordJobsInfo("", 1, 100);
+        assertEquals(0, list0.size());
+
+        Properties conf = client.createConfiguration();
+
+        String appPath = "file://" + getTestCaseDir() + File.separator + "coordinator.xml";
+        String appXml = "<coordinator-app name=\"NAME\" frequency=\"${coord:minutes(20)}\" "
+                + "start=\"2009-02-01T01:00Z\" end=\"2009-02-03T23:59Z\" timezone=\"UTC\" "
+                + "xmlns=\"uri:oozie:coordinator:0.1\"> <controls> <timeout>10</timeout> <concurrency>1</concurrency> "
+                + "<execution>LIFO</execution> </controls> <datasets> "
+                + "<dataset name=\"a\" frequency=\"${coord:minutes(20)}\" initial-instance=\"2009-02-01T01:00Z\" "
+                + "timezone=\"UTC\"> <uri-template>file:///tmp/coord/workflows/${YEAR}/${DAY}</uri-template> </dataset> "
+                + "<dataset name=\"local_a\" frequency=\"${coord:minutes(20)}\" initial-instance=\"2009-02-01T01:00Z\" "
+                + "timezone=\"UTC\"> <uri-template>file:///tmp/coord/workflows/${YEAR}/${DAY}</uri-template> </dataset> "
+                + "</datasets> <input-events> "
+                + "<data-in name=\"A\" dataset=\"a\"> <instance>${coord:latest(0)}</instance> </data-in>  " + "</input-events> "
+                + "<output-events> <data-out name=\"LOCAL_A\" dataset=\"local_a\"> "
+                + "<instance>${coord:current(-1)}</instance> </data-out> </output-events> <action> <workflow> "
+                + "<app-path>hdfs:///tmp/workflows/</app-path> "
+                + "<configuration> <property> <name>inputA</name> <value>${coord:dataIn('A')}</value> </property> "
+                + "<property> <name>inputB</name> <value>${coord:dataOut('LOCAL_A')}</value> "
+                + "</property></configuration> </workflow> </action> </coordinator-app>";
+        writeToFile(appXml, appPath);
+
+        conf.setProperty(OozieClient.COORDINATOR_APP_PATH, appPath);
+        String jobId0 = client.submit(conf);
+        client.kill(jobId0);
+
+        String jobId = client.run(conf);
+        client.suspend(jobId);
+        client.resume(jobId);
+        client.kill(jobId);
+
+        CoordinatorJob job = client.getCoordJobInfo(jobId);
+        String appName = job.getAppName();
+        assertEquals("NAME", appName);
+
+        List<CoordinatorJob> list = client.getCoordJobsInfo("", 1, 5);
+        assertEquals(2, list.size());
+    }
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestSLAEventBean.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestSLAEventBean.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestSLAEventBean.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestSLAEventBean.java Wed May 15 23:07:36 2013
@@ -0,0 +1,132 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.util.Date;
+
+import org.apache.oozie.test.XTestCase;
+import org.apache.oozie.util.DateUtils;
+import org.apache.oozie.util.XmlUtils;
+import org.jdom.Element;
+
+public class TestSLAEventBean extends XTestCase {
+
+    private static final Date ee = new Date(1L);
+    private static final Date es = new Date(2L);
+    private static final Date st = new Date(3L);
+
+    @SuppressWarnings("deprecation")
+    private void set(SLAEventBean bean) {
+        bean.setAlertContact("ac");
+        bean.setAlertFrequency("af");
+        bean.setAlertPercentage("ap");
+        bean.setAppName("an");
+        bean.setAppType(org.apache.oozie.client.SLAEvent.SlaAppType.WORKFLOW_ACTION);
+        bean.setAppTypeStr("WORKFLOW_ACTION");
+        bean.setDevContact("dc");
+        bean.setEvent_id(1L);
+        bean.setEventType("et");
+        bean.setExpectedEnd(ee);
+        bean.setExpectedStart(es);
+        bean.setGroupName("gn");
+        bean.setJobData("jd");
+        bean.setJobStatus(org.apache.oozie.client.SLAEvent.Status.STARTED);
+        bean.setJobStatusStr("STARTED");
+        bean.setNotificationMsg("nm");
+        bean.setParentClientId("pci");
+        bean.setParentSlaId("psi");
+        bean.setQaContact("qc");
+        bean.setSeContact("sc");
+        bean.setSlaId("si");
+        bean.setStatusTimestamp(st);
+        bean.setUpstreamApps("ua");
+        bean.setUser("u");
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testSetGet() {
+        final SLAEventBean bean = new SLAEventBean();
+
+        set(bean);
+
+        assertEquals("ac", bean.getAlertContact());
+        assertEquals("af", bean.getAlertFrequency());
+        assertEquals("ap", bean.getAlertPercentage());
+        assertEquals("an", bean.getAppName());
+        assertTrue(org.apache.oozie.client.SLAEvent.SlaAppType.WORKFLOW_ACTION
+            == bean.getAppType());
+        assertEquals("WORKFLOW_ACTION", bean.getAppTypeStr());
+        assertEquals("dc", bean.getDevContact());
+        assertEquals(1L, bean.getEvent_id());
+        assertEquals("et", bean.getEventType());
+        assertEquals("gn", bean.getGroupName());
+        assertEquals("jd", bean.getJobData());
+        assertEquals("STARTED", bean.getJobStatusStr());
+        assertEquals("nm", bean.getNotificationMsg());
+        assertEquals("pci", bean.getParentClientId());
+        assertEquals("psi", bean.getParentSlaId());
+        assertEquals("qc", bean.getQaContact());
+        assertEquals("sc", bean.getSeContact());
+        assertEquals("si", bean.getSlaId());
+        assertEquals("ua", bean.getUpstreamApps());
+        assertEquals("u", bean.getUser());
+
+        assertEquals(ee, bean.getExpectedEnd());
+        assertEquals(es, bean.getExpectedStart());
+        assertEquals(st, bean.getStatusTimestamp());
+
+        assertEquals(DateUtils.convertDateToTimestamp(st), bean.getStatusTimestampTS());
+        assertEquals(DateUtils.convertDateToTimestamp(ee), bean.getExpectedEndTS());
+        assertEquals(DateUtils.convertDateToTimestamp(es), bean.getExpectedStartTS());
+    }
+
+    public void testToXmlStatusEvent() {
+        final SLAEventBean bean = new SLAEventBean();
+        set(bean);
+        Element el = bean.toXml();
+        String actualXml = XmlUtils.prettyPrint(el).toString();
+        assertEquals("<event>\r\n" + "  <sequence-id>1</sequence-id>\r\n" + "  <status>\r\n" + "    <sla-id>si</sla-id>\r\n"
+                + "    <status-timestamp>1970-01-01T00:00Z</status-timestamp>\r\n" + "    <job-status>STARTED</job-status>\r\n"
+                + "    <job-data>jd</job-data>\r\n" + "    <user>u</user>\r\n" + "    <group>gn</group>\r\n"
+                + "    <app-name>an</app-name>\r\n" + "  </status>\r\n" + "</event>", actualXml);
+    }
+
+    @SuppressWarnings("deprecation")
+    public void testToXmlRegistrationEvent() {
+        final SLAEventBean bean = new SLAEventBean();
+        set(bean);
+        // Set "CREATED" status to get the event of registration kind:
+        bean.setJobStatus(org.apache.oozie.client.SLAEvent.Status.CREATED);
+        Element el = bean.toXml();
+        String actualXml = XmlUtils.prettyPrint(el).toString();
+        System.out.println(actualXml);
+        assertEquals("<event>\r\n" + "  <sequence-id>1</sequence-id>\r\n" + "  <registration>\r\n" + "    <sla-id>si</sla-id>\r\n"
+                + "    <app-type>WORKFLOW_ACTION</app-type>\r\n" + "    <app-name>an</app-name>\r\n" + "    <user>u</user>\r\n"
+                + "    <group>gn</group>\r\n" + "    <parent-sla-id>psi</parent-sla-id>\r\n"
+                + "    <expected-start>1970-01-01T00:00Z</expected-start>\r\n"
+                + "    <expected-end>1970-01-01T00:00Z</expected-end>\r\n"
+                + "    <status-timestamp>1970-01-01T00:00Z</status-timestamp>\r\n"
+                + "    <notification-msg>nm</notification-msg>\r\n" + "    <alert-contact>ac</alert-contact>\r\n"
+                + "    <dev-contact>dc</dev-contact>\r\n" + "    <qa-contact>qc</qa-contact>\r\n"
+                + "    <se-contact>sc</se-contact>\r\n" + "    <alert-percentage>ap</alert-percentage>\r\n"
+                + "    <alert-frequency>af</alert-frequency>\r\n" + "    <upstream-apps>ua</upstream-apps>\r\n"
+                + "    <job-status>CREATED</job-status>\r\n" + "    <job-data>jd</job-data>\r\n" + "  </registration>\r\n"
+                + "</event>", actualXml);
+    }
+
+}

Added: oozie/trunk/core/src/test/java/org/apache/oozie/TestV1JobsServletBundleEngine.java
URL: http://svn.apache.org/viewvc/oozie/trunk/core/src/test/java/org/apache/oozie/TestV1JobsServletBundleEngine.java?rev=1483122&view=auto
==============================================================================
--- oozie/trunk/core/src/test/java/org/apache/oozie/TestV1JobsServletBundleEngine.java (added)
+++ oozie/trunk/core/src/test/java/org/apache/oozie/TestV1JobsServletBundleEngine.java Wed May 15 23:07:36 2013
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie;
+
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.oozie.BundleJobBean;
+import org.apache.oozie.client.Job;
+import org.apache.oozie.client.OozieClient;
+import org.apache.oozie.client.rest.RestConstants;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.service.UUIDService;
+import org.apache.oozie.servlet.DagServletTestCase;
+import org.apache.oozie.servlet.MockDagEngineService;
+import org.apache.oozie.servlet.V1JobsServlet;
+import org.apache.oozie.test.XDataTestCase;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.junit.Ignore;
+
+public class TestV1JobsServletBundleEngine extends DagServletTestCase {
+    static {
+        new V1JobsServlet();
+    }
+
+    private static final boolean IS_SECURITY_ENABLED = false;
+
+    private Services services;
+
+    /**
+     * This class is needed in order to reuse some methods of class {@link XDataTestCase}. We cannot directly extend it there as
+     * we extend {@link DagServletTestCase}. Anonymous inner class is also not an option since we cannot assign it an annotation.
+     * The @Ignore annotation is needed to prevent JUnit from recognizing this inner class as a test.
+     */
+    @Ignore
+    private static class XDataTestCase1 extends XDataTestCase {
+    }
+
+    private final XDataTestCase1 xDataTestCase = new XDataTestCase1();
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        xDataTestCase.setName(getName());
+        xDataTestCase.setUpPub();
+
+        new Services().init();
+        services = Services.get();
+        services.setService(UUIDService.class);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (services != null) {
+            services.destroy();
+        }
+        xDataTestCase.tearDownPub();
+        super.tearDown();
+    }
+
+    /**
+     * Tests method {@link BundleEngine#getBundleJobs(String, int, int)}. Also
+     * tests positive cases of the filter parsing by
+     * {@link BundleEngine#parseFilter(String)}.
+     */
+    public void testGetBundleJobs() throws Exception {
+        final BundleJobBean bundleJobBean = xDataTestCase.addRecordToBundleJobTable(Job.Status.PREP, false);
+
+        runTest("/v1/jobs", V1JobsServlet.class, IS_SECURITY_ENABLED, new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                MockDagEngineService.reset();
+
+                Map<String, String> params = new HashMap<String, String>();
+                params.put(RestConstants.JOBTYPE_PARAM, "bundle");
+                params.put(RestConstants.JOBS_FILTER_PARAM, OozieClient.FILTER_STATUS + "=PREP;" + OozieClient.FILTER_NAME
+                        + "=BUNDLE-TEST;" + OozieClient.FILTER_USER + "=" + getTestUser());
+
+                URL url = createURL("", params);
+                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+                conn.setRequestMethod("GET");
+                assertEquals(HttpServletResponse.SC_OK, conn.getResponseCode());
+                assertTrue(conn.getHeaderField("content-type").startsWith(RestConstants.JSON_CONTENT_TYPE));
+
+                JSONObject json = (JSONObject) JSONValue.parse(new InputStreamReader(conn.getInputStream()));
+
+                assertEquals(Long.valueOf(1L), json.get("total"));
+                JSONArray array = (JSONArray) json.get("bundlejobs");
+                JSONObject jo = (JSONObject) array.get(0);
+                assertEquals(bundleJobBean.getId(), jo.get("bundleJobId"));
+
+                return null;
+            }
+        });
+    }
+
+}