001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.test.standalone;
046:
047: import junit.framework.TestCase;
048: import org.apache.commons.logging.Log;
049: import org.apache.commons.logging.LogFactory;
050: import org.obe.client.api.xpdl.InvalidPackageException;
051: import org.obe.xpdl.model.pkg.XPDLPackage;
052: import org.obe.client.api.xpdl.PackageValidator;
053: import org.obe.client.api.xpdl.ValidationError;
054: import org.obe.xpdl.parser.XPDLParser;
055: import org.obe.xpdl.parser.XPDLParserException;
056: import org.obe.xpdl.parser.dom4j.Dom4JXPDLParser;
057:
058: import java.io.*;
059: import java.util.HashSet;
060: import java.util.Iterator;
061: import java.util.Set;
062: import java.util.TreeSet;
063:
064: /**
065: * @author Adrian Price
066: */
067: public class PackageValidatorTest extends TestCase {
068: private static final Log _logger = LogFactory
069: .getLog(PackageValidatorTest.class);
070: private static final String TEST_PACKAGE = "org/obe/test/standalone/PackageValidatorTest.xpdl";
071: private static final String[] _expectedErrors = {
072: "/Package[pkg-1]/Application[]/Id must be specified",
073: "/Package[pkg-1]/Application[zas.browser] is already defined. Remove the duplicate entity or assign it a unique ID.",
074: "/Package[pkg-1]/Application[zas.browser]/FormalParameter[URL] is already defined. Remove the duplicate entity or assign it a unique ID.",
075: "/Package[pkg-1]/Application[zas.browser]/FormalParameter[]/Id must be specified",
076: "/Package[pkg-1]/Script[text/xpath] is not a valid script declaration. The script type is an extended MIME Media Type and must start with \"text/x-\" or \"text/xml/x-\"",
077: "/Package[pkg-1]/TypeDeclaration[MyStringType] is already defined. Remove the duplicate entity or assign it a unique ID.",
078: "/Package[pkg-1]/TypeDeclaration[]/Id must be specified",
079: "/Package[pkg-1]/Workflow[wf-1] must have at least one exit activity (one with no efferent (outbound) transitions)",
080: "/Package[pkg-1]/Workflow[wf-1] must have at least one start activity (one with no afferent (inbound) transitions)",
081: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1] is already defined. Remove the duplicate entity or assign it a unique ID.",
082: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1] must have at least one exit activity (one with no efferent (outbound) transitions)",
083: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1] must have at least one start activity (one with no afferent (inbound) transitions)",
084: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/Implementation/Tool/Id must be specified",
085: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/Implementation/Tool[obe.assignProcessAttribute]/ActualParameter[attrName] references an undefined DataField[crapVar]",
086: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/Implementation/Tool[obe.crapProc] references an undefined Application[obe.crapProc]",
087: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/Implementation/Tool[obe.crapProc]/Type must be specified",
088: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/Implementation/Tool[obe.log] formal and actual parameter counts differ: expected <2>, actual <1>",
089: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/TransitionRestriction/Split[XOR] an OTHERWISE transition has already been defined",
090: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/TransitionRestriction/Split[XOR] does not reference Transition[t-2c]",
091: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-2]/TransitionRestriction/Split[XOR]/TransitionRef[t-2e] references non-efferent (outbound) Transition",
092: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3a]/Performer references an undefined Participant[French]",
093: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3c] is already defined. Remove the duplicate entity or assign it a unique ID.",
094: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3c]/Implementation/SubFlow[wf-2]/ActualParameter[curDate] references an undefined DataField[crapVar]",
095: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3c]/Implementation/SubFlow[wf-crap] references an undefined WorkflowProcess[wf-crap]",
096: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3c]/Performer references an undefined Participant[French]",
097: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3c]/Route cannot have a Performer",
098: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Transition[]/From references an undefined Activity[a-666]",
099: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Transition[]/Id must be specified",
100: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Transition[]/To references an undefined Activity[a-777]",
101: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Transition[t-3c] is already defined. Remove the duplicate entity or assign it a unique ID.",
102: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-0] has 3 regular efferent (outbound) transitions, and therefore requires a Split",
103: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-0]/TransitionRestriction TransitionRestrictions can only contain one join.",
104: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-1] has 2 afferent (inbound) transitions, and therefore requires a Join",
105: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-1]/Deadline can only have one synchronous deadline",
106: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-1]/Deadline is incompatible with Transition[t-1]/ExtendedAttribute[Execution]",
107: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-1]/Deadline/ExceptionName[Timeout1] is not handled by any efferent (outbound) transition",
108: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-1]/Deadline/ExceptionName[Timeout2] is not handled by any efferent (outbound) transition",
109: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-1]/Deadline/ExceptionName[Timeout3] is not handled by any efferent (outbound) transition",
110: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-5]/TransitionRestriction TransitionRestrictions can only contain one split in OBE (XPDL permits more, but does not define the semantics).",
111: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-5]/TransitionRestriction TransitionRestrictions can only contain one join.",
112: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-5]/TransitionRestriction/Split[XOR] does not reference Transition[t-11]",
113: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-5]/TransitionRestriction/Split[XOR] does not reference Transition[t-5]",
114: "/Package[pkg-1]/Workflow[wf-1]/Activity[a-9] has 2 afferent (inbound) transitions, and therefore requires a Join",
115: "/Package[pkg-1]/Workflow[wf-1]/ActivitySet[as-1]/Activity[a-3c] has 2 afferent (inbound) transitions, and therefore requires a Join",
116: "/Package[pkg-1]/Workflow[wf-1]/Application[]/Id must be specified",
117: "/Package[pkg-1]/Workflow[wf-1]/Application[obe.log] is already defined. Remove the duplicate entity or assign it a unique ID.",
118: "/Package[pkg-1]/Workflow[wf-1]/DataField[]/Id must be specified",
119: "/Package[pkg-1]/Workflow[wf-1]/DataField[performerVar] is already defined. Remove the duplicate entity or assign it a unique ID.",
120: "/Package[pkg-1]/Workflow[wf-1]/Participant[Scottish] is already defined. Remove the duplicate entity or assign it a unique ID.",
121: "/Package[pkg-1]/Workflow[wf-1]/Participant[Welsh] is already defined. Remove the duplicate entity or assign it a unique ID.",
122: "/Package[pkg-1]/Workflow[wf-1]/Participant[]/Id must be specified", };
123: private static final Set _expectedErrorSet = new HashSet();
124:
125: static {
126: for (int i = 0; i < _expectedErrors.length; i++)
127: _expectedErrorSet.add(_expectedErrors[i]);
128: }
129:
130: public PackageValidatorTest(String name) {
131: super (name);
132: }
133:
134: public void testValidate() throws IOException, XPDLParserException,
135: InvalidPackageException {
136:
137: String pkgContent = readFile(TEST_PACKAGE);
138: XPDLPackage pkg = readPackage(pkgContent);
139: PackageValidator validator = new PackageValidator();
140: ValidationError[] actualErrors = validator.validate(pkg, false);
141: assertNotNull(actualErrors);
142: Set actualErrorSet = new TreeSet();
143: for (int i = 0; i < actualErrors.length; i++)
144: actualErrorSet.add(actualErrors[i].getMessage());
145:
146: if (_expectedErrorSet.size() == actualErrorSet.size()
147: && _expectedErrorSet.equals(actualErrorSet)) {
148:
149: _logger.info("Correctly identified "
150: + _expectedErrorSet.size() + " errors");
151: if (_logger.isDebugEnabled()) {
152: int i = 1;
153: for (Iterator j = actualErrorSet.iterator(); j
154: .hasNext(); i++)
155: _logger.debug("Error " + i + ": " + j.next());
156: }
157: } else {
158: Set extraErrorSet = new TreeSet(actualErrorSet);
159: extraErrorSet.removeAll(_expectedErrorSet);
160: for (Iterator i = extraErrorSet.iterator(); i.hasNext();)
161: _logger.info("Extraneous error: " + i.next());
162: Set missingErrorSet = new TreeSet(_expectedErrorSet);
163: missingErrorSet.removeAll(actualErrorSet);
164: for (Iterator i = missingErrorSet.iterator(); i.hasNext();)
165: _logger.info("Unreported error: " + i.next());
166: fail("Extraneous and/or unreported errors");
167: }
168: }
169:
170: private static String readFile(String fileName) throws IOException {
171: ClassLoader cl = PackageValidatorTest.class.getClassLoader();
172: InputStream in = cl.getResourceAsStream(fileName);
173: Reader reader = new InputStreamReader(in);
174: StringBuffer sbuf = new StringBuffer();
175: char[] cbuf = new char[4096];
176: int offset = 0, count;
177: do {
178: count = reader.read(cbuf, offset, cbuf.length);
179: if (count > 0)
180: sbuf.append(cbuf, 0, count);
181: } while (count > 0);
182: in.close();
183: return sbuf.toString();
184: }
185:
186: private XPDLPackage readPackage(String content)
187: throws XPDLParserException, IOException {
188:
189: assertNotNull("Package content is null;", content);
190: XPDLParser parser = new Dom4JXPDLParser();
191: return parser.parse(new StringReader(content));
192: }
193: }
|