001: /*
002: * (c) Copyright 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: * [See end of file]
004: */
005:
006: package com.hp.hpl.jena.rdf.arp.states.test;
007:
008: import java.io.FileWriter;
009: import java.io.IOException;
010: import java.lang.reflect.InvocationTargetException;
011: import java.util.Comparator;
012: import java.util.HashMap;
013: import java.util.Iterator;
014: import java.util.Map;
015: import java.util.Random;
016: import java.util.Set;
017: import java.util.TreeSet;
018:
019: import org.xml.sax.Attributes;
020: import org.xml.sax.SAXParseException;
021:
022: import com.hp.hpl.jena.rdf.arp.ARPErrorNumbers;
023: import com.hp.hpl.jena.rdf.arp.impl.AbsXMLContext;
024: import com.hp.hpl.jena.rdf.arp.impl.AttributeLexer;
025: import com.hp.hpl.jena.rdf.arp.impl.Names;
026: import com.hp.hpl.jena.rdf.arp.impl.URIReference;
027: import com.hp.hpl.jena.rdf.arp.impl.XMLBaselessContext;
028: import com.hp.hpl.jena.rdf.arp.impl.XMLContext;
029: import com.hp.hpl.jena.rdf.arp.impl.XMLHandler;
030: import com.hp.hpl.jena.rdf.arp.states.AbsXMLLiteral;
031: import com.hp.hpl.jena.rdf.arp.states.DAMLCollection;
032: import com.hp.hpl.jena.rdf.arp.states.FrameI;
033: import com.hp.hpl.jena.rdf.arp.states.HasSubjectFrameI;
034: import com.hp.hpl.jena.rdf.arp.states.InnerXMLLiteral;
035: import com.hp.hpl.jena.rdf.arp.states.LookingForRDF;
036: import com.hp.hpl.jena.rdf.arp.states.OuterXMLLiteral;
037: import com.hp.hpl.jena.rdf.arp.states.RDFCollection;
038: import com.hp.hpl.jena.rdf.arp.states.WantEmpty;
039: import com.hp.hpl.jena.rdf.arp.states.WantLiteralValueOrDescription;
040: import com.hp.hpl.jena.rdf.arp.states.WantPropertyElement;
041: import com.hp.hpl.jena.rdf.arp.states.WantTopLevelDescription;
042: import com.hp.hpl.jena.rdf.arp.states.WantTypedLiteral;
043: import com.hp.hpl.jena.rdf.arp.states.WantsObjectFrameI;
044:
045: /**
046: * For each state s, for each element-attribute event e1, - test s, e1 - if s,
047: * e1 is not an error + test s, e1; Description; test s,e1, eg:prop; test s, e1,
048: * end; for each element-attribute event e2 + test s, e1, e2 if s, e1, e2 is not
049: * an error
050: *
051: * @author Jeremy J. Carroll
052: *
053: */
054: public class TestData implements ARPErrorNumbers {
055:
056: // TODO: not for 2.3. get rid of short names all together, not good idea.
057:
058: private static final URIReference foo = URIReference
059: .createNoChecks("http://foo/");
060: private static final URIReference bar = URIReference
061: .createNoChecks("http://bar/");
062:
063: static TestHandler xmlHandler = new TestHandler();
064: // static {
065: // try {
066: // xmlHandler.initParse("http://example.org/", "");
067: // } catch (SAXParseException e) {
068: // e.printStackTrace();
069: // }
070: //
071: // }
072: static String dataFile = "testing/arp/state.txt";
073: static AbsXMLContext xmlContext;
074:
075: static {
076: try {
077: xmlContext = new XMLBaselessContext(xmlHandler,
078: ERR_RESOLVING_AGAINST_RELATIVE_BASE).withBase(
079: xmlHandler, "http://example.org/base/");
080: } catch (SAXParseException e) {
081: throw new RuntimeException(e);
082: }
083: }
084: static TestFrame testFrame = new TestFrame(xmlHandler, xmlContext);
085:
086: static char white[] = { 32, 32, 32, 32, 32 };
087:
088: static char black[] = { 97, 98, 99, 100, 101 };
089:
090: private static final AttrEvent xmlSpace = new AttrEvent(QName
091: .xml("space"));
092: static Event allEvents[] = { new ElementEvent(QName.rdf("li")),
093: new ElementEvent(QName.rdf("Description")),
094: new ElementEvent("F", QName.rdf("RDF")),
095: new ElementEvent(QName.eg("Goo")),
096: new AttrEvent(QName.xml("base")),
097: new AttrEvent("g", QName.xml("lang"), "en"),
098: new AttrEvent(QName.eg("foo")), xmlSpace,
099: new AttrEvent("B", QName.rdf("bagID"), "en"),
100: new AttrEvent(QName.rdf("about")),
101: new AttrEvent("h", QName.rdf("aboutEach"), "en"),
102: new AttrEvent("H", QName.rdf("aboutEachPrefix"), "en"),
103: new AttrEvent(QName.rdf("ID")),
104: new AttrEvent(QName.rdf("nodeID")),
105: new AttrEvent(QName.rdf("resource")),
106: new AttrEvent(QName.rdf("type")),
107: new AttrEvent(QName.rdf("datatype")),
108: new AttrEvent("C", QName.rdf("parseType"), "Collection"),
109: new AttrEvent("L", QName.rdf("parseType"), "Literal"),
110: new AttrEvent("R", QName.rdf("parseType"), "Resource"),
111: new InternalEvent("e", "</end>") {
112: FrameI apply(FrameI from, Attributes att)
113: throws SAXParseException {
114: from.endElement();
115: return from.getParent();
116: }
117: }, new InternalEvent("O", "object") {
118: FrameI apply(FrameI from, Attributes att) {
119: ((WantsObjectFrameI) from).theObject(foo);
120: return from;
121: }
122: }, new InternalEvent("W", "white") {
123: FrameI apply(FrameI from, Attributes att)
124: throws SAXParseException {
125: from.characters(white, 0, 5);
126: return from;
127: }
128: }, new InternalEvent("Q", "'abcde'") {
129: FrameI apply(FrameI from, Attributes att)
130: throws SAXParseException {
131: from.characters(black, 0, 5);
132: return from;
133: }
134: }, new InternalEvent("P", "pred-object") {
135: FrameI apply(FrameI from, Attributes att) {
136: ((HasSubjectFrameI) from).aPredAndObj(foo, bar);
137: return from;
138: }
139: }, };
140:
141: static Map short2Event = new HashMap();
142: static {
143: for (int i = 0; i < allEvents.length; i++) {
144: String key = allEvents[i].oneChar;
145: if (short2Event.get(key) != null)
146: System.err.println("Duplicate event code: " + key);
147: short2Event.put(key, allEvents[i]);
148: }
149: }
150: static Map state2Name = new HashMap();
151:
152: static Map state2ShortName = new HashMap();
153:
154: static Map shortName2State = new HashMap();
155:
156: static Map state2Args = new HashMap();
157:
158: static void add(String sh, String nm, Class f, Object args[]) {
159: state2Name.put(f, nm);
160: sh = getSimpleName(f);
161: if (shortName2State.get(sh) != null) {
162: System.err.println("Duplicate: " + sh);
163: }
164: state2Args.put(f, args);
165: shortName2State.put(sh, f);
166: state2ShortName.put(f, sh);
167: }
168:
169: private static String getSimpleName(Class f) {
170: return XMLHandler.getSimpleName(f);
171: }
172:
173: static AttributeLexer ap = new AttributeLexer(testFrame, 0, 0);
174: static {
175: add("ix", "inner-xml-literal", InnerXMLLiteral.class,
176: new Object[] { testFrame, "foo", testFrame.namespaces });
177: add("xl", "xml-literal", OuterXMLLiteral.class, new Object[] {
178: testFrame, xmlContext });
179: add("ip", "vanilla-prop-elt",
180: WantLiteralValueOrDescription.class, new Object[] {
181: testFrame, xmlContext });
182: add("tl", "typed-literal", WantTypedLiteral.class,
183: new Object[] { testFrame, "http://ex/dt", xmlContext });
184: add("dl", "daml:collection", DAMLCollection.class,
185: new Object[] { testFrame, xmlContext });
186: add("cl", "collection", RDFCollection.class, new Object[] {
187: testFrame, xmlContext });
188: add("tp", "top-level", WantTopLevelDescription.class,
189: new Object[] { testFrame, ap });
190: add("em", "empty-prop-elt", WantEmpty.class, new Object[] {
191: testFrame, xmlContext });
192: add("de", "inside-Description", WantPropertyElement.class,
193: new Object[] { testFrame, xmlContext });
194: add("RD", "looking-for-RDF", LookingForRDF.class, new Object[] {
195: testFrame, ap });
196: }
197:
198: int localCount;
199:
200: int globalCount;
201:
202: private EventList eventList = new EventList();
203:
204: public TestData() {
205: super ();
206: }
207:
208: // String characters[] = {
209: // "G",
210: // "G e",
211: // "G e G",
212: // "Q",
213: // "Q G",
214: // "Q e",
215: // "e",
216: // "P",
217: // "O",
218: // };
219: String characters[] = { "<eg:Goo>", "<eg:Goo> </end>",
220: "<eg:Goo> </end> <eg:Goo>", "'abcde'", "'abcde' <eg:Goo>",
221: "'abcde' </end>", "</end>", "pred-object", "object", };
222:
223: boolean inCharacterize = false;
224:
225: void characterize(Class f) {
226: inCharacterize = true;
227: int sz = eventList.size;
228: StringBuffer rslt = new StringBuffer();
229: String skip = null;
230: eventList.test(f);
231: rslt.append(eventListName(f, null));
232: rslt.append(" $ " + testInfo(f) + " {");
233: if (eventList.testResult.getClass() != LookingForRDF.class)
234:
235: for (int i = 0; i < characters.length; i++) {
236: if (skip != null && characters[i].startsWith(skip))
237: continue;
238: skip = null;
239: addEvents(characters[i]);
240: rslt.append(" " + characters[i] + " $ ");
241: boolean testV = eventList.test(f);
242: rslt.append(testInfo(f) + " ;");
243: eventList.size = sz;
244: if (!testV) {
245: skip = characters[i];
246: continue;
247: }
248: }
249: rslt.append(" }");
250: data.add(rslt.toString());
251: inCharacterize = false;
252: }
253:
254: private String eventListName(Class f, Class f2) {
255: StringBuffer rslt = new StringBuffer();
256: rslt.append(stateName(f, f2));
257: for (int i = 0; i < eventList.size; i++) {
258: rslt.append(' ');
259: rslt.append(eventList.events[i].oneChar);
260: }
261: return rslt.toString();
262: }
263:
264: private String stateName(Class f, Class f2) {
265: return f == f2 ? "*" : (String) state2ShortName.get(f);
266: }
267:
268: private void addEvents(String string) {
269: String all[] = string.split(" ");
270: for (int i = 0; i < all.length; i++) {
271: eventList.add((Event) short2Event.get(all[i]));
272: }
273: }
274:
275: private String testInfo(Class f) {
276: return eventList.testFailure ? (eventList.testException ? "!"
277: : "?") : (stateName(eventList.testResult.getClass(), f)
278: + " " + xmlHandler.info() + " " + testFrame.info());
279: }
280:
281: static Class tryClasses[] = { FrameI.class, AbsXMLLiteral.class,
282: HasSubjectFrameI.class, WantsObjectFrameI.class };
283:
284: static FrameI create(Class cl) throws InstantiationException,
285: IllegalAccessException, InvocationTargetException {
286: FrameI frame = null;
287: Object args[] = (Object[]) state2Args.get(cl);
288: Class types[] = new Class[args.length];
289: for (int i = 1; i < args.length; i++) {
290: types[i] = args[i].getClass();
291: if (types[i] == XMLContext.class)
292: types[i] = AbsXMLContext.class;
293: }
294: if (cl == InnerXMLLiteral.class)
295: types[2] = Map.class;
296: for (int j = 0; j < tryClasses.length; j++) {
297: types[0] = tryClasses[j];
298:
299: try {
300: frame = (FrameI) cl.getConstructor(types).newInstance(
301: args);
302: break;
303: } catch (NoSuchMethodException e) {
304: continue;
305: }
306: }
307: return frame;
308: }
309:
310: void expand(Class f) {
311: if (AbsXMLLiteral.class.isAssignableFrom(f))
312: return;
313: if (randomPurgeXMLAttrs())
314: return;
315: localCount++;
316: globalCount++;
317: if (localCount % 20000 == 0)
318: stats(f);
319: if (!eventList.test(f)) {
320: if (!shorterTestFails(f))
321: data.add(eventListName(f, null) + " $ " + testInfo(f));
322: return;
323: }
324: characterize(f);
325: if (eventList.size >= (AbsXMLLiteral.class.isAssignableFrom(f) ? 3
326: : eventList.testResult instanceof LookingForRDF ? 2 : 8))
327: return;
328: for (int i = 0; i < allEvents.length; i++) {
329: if (allEvents[i].isAttribute()) {
330: Event e = eventList.last();
331: if (!(e.isElement() || (e.isAttribute() && e.hashCode() < allEvents[i]
332: .hashCode())))
333: continue;
334: } else if (true) {
335: continue;
336: }
337: eventList.add(allEvents[i]);
338: expand(f);
339: eventList.pop();
340: }
341: }
342:
343: private Random dice = new Random(23);
344:
345: private boolean randomPurgeXMLAttrs() {
346: int weight = 0;
347: eventList.rewind();
348: while (eventList.hasNext()) {
349: Event e = eventList.next();
350: if (e == xmlSpace)
351: weight += 2;
352: else if (e.isAttribute()
353: && ((AttrEvent) e).q.uri.equals(Names.xmlns))
354: weight++;
355: }
356: while (weight-- > 0)
357: if (dice.nextBoolean())
358: return true;
359: return false;
360: }
361:
362: private boolean shorterTestFails(Class f) {
363: if (eventList.size <= 2)
364: return false;
365: for (int i = 1; i < eventList.size - 1; i++) {
366: EventList copy = eventList.copy();
367: copy.delete(i);
368: if (!copy.test(f))
369: return true;
370: }
371: return false;
372: }
373:
374: Set data = new TreeSet(new Comparator() {
375: public int compare(Object arg1, Object arg2) {
376: StringBuffer b1 = new StringBuffer((String) arg1).reverse();
377: StringBuffer b2 = new StringBuffer((String) arg2).reverse();
378: return b1.toString().compareTo(b2.toString());
379: }
380: });
381:
382: void stats(Class f) {
383: if (false)
384: System.out.println(state2ShortName.get(f) + ":"
385: + state2Name.get(f) + ":" + getSimpleName(f) + " "
386: + localCount + "/" + globalCount);
387:
388: }
389:
390: void test1() throws IOException {
391: Iterator it = state2Name.keySet().iterator();
392: while (it.hasNext()) {
393: Class f = (Class) it.next();
394: // System.out.println(state2ShortName.get(f) + ":" + state2Name.get(f)
395: // + ":" + f.getSimpleName());
396: localCount = 0;
397: for (int i = 0; i < allEvents.length; i++) {
398: if (allEvents[i].isElement()) {
399: eventList.clear();
400: eventList.add(allEvents[i]);
401: expand(f);
402: }
403: }
404: stats(f);
405: }
406: FileWriter fw = new FileWriter(dataFile);
407: it = data.iterator();
408: while (it.hasNext()) {
409: fw.write((String) it.next());
410: fw.write('\n');
411: }
412: fw.close();
413: }
414:
415: static public void main(String args[]) throws IOException {
416: long start = System.currentTimeMillis();
417: new TestData().test1();
418: System.out
419: .println((System.currentTimeMillis() - start) + " ms");
420: }
421:
422: public static String stateLongName(String sh) {
423: return (String) state2Name.get(shortName2State.get(sh));
424: }
425:
426: public static Class toState(String sh) {
427: return (Class) shortName2State.get(sh);
428: }
429:
430: }
431:
432: /*
433: * (c) Copyright 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP All rights
434: * reserved.
435: *
436: * Redistribution and use in source and binary forms, with or without
437: * modification, are permitted provided that the following conditions are met:
438: * 1. Redistributions of source code must retain the above copyright notice,
439: * this list of conditions and the following disclaimer. 2. Redistributions in
440: * binary form must reproduce the above copyright notice, this list of
441: * conditions and the following disclaimer in the documentation and/or other
442: * materials provided with the distribution. 3. The name of the author may not
443: * be used to endorse or promote products derived from this software without
444: * specific prior written permission.
445: *
446: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
447: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
448: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
449: * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
450: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
451: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
452: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
453: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
454: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
455: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
456: */
|