001: /*
002: (c) Copyright 2001, 2002, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: All rights reserved.
004: [See end of file]
005: $Id: testWriterAndReader.java,v 1.44 2008/01/02 12:06:48 andy_seaborne Exp $
006: */
007:
008: package com.hp.hpl.jena.xmloutput.test;
009:
010: import java.io.*;
011: import java.util.Random;
012: import java.util.Vector;
013:
014: import junit.framework.Test;
015: import junit.framework.TestSuite;
016:
017: import org.apache.commons.logging.Log;
018: import org.apache.commons.logging.LogFactory;
019:
020: import com.hp.hpl.jena.rdf.model.Model;
021: import com.hp.hpl.jena.rdf.model.Property;
022: import com.hp.hpl.jena.rdf.model.RDFErrorHandler;
023: import com.hp.hpl.jena.rdf.model.RDFNode;
024: import com.hp.hpl.jena.rdf.model.RDFReader;
025: import com.hp.hpl.jena.rdf.model.RDFWriter;
026: import com.hp.hpl.jena.rdf.model.Resource;
027: import com.hp.hpl.jena.rdf.model.Statement;
028: import com.hp.hpl.jena.rdf.model.StmtIterator;
029: import com.hp.hpl.jena.rdf.model.test.ModelTestBase;
030: import com.hp.hpl.jena.shared.JenaException;
031: import com.hp.hpl.jena.vocabulary.DAML_OIL;
032: import com.hp.hpl.jena.vocabulary.RDFSyntax;
033:
034: /**
035: * This will test any Writer and Reader pair.
036: * It writes out a random model, and reads it back in.
037: * The test fails if the models are not 'the same'.
038: * Quite what 'the same' means is debatable.
039: * @author jjc
040:
041: * @version Release='$Name: $' Revision='$Revision: 1.44 $' Date='$Date: 2008/01/02 12:06:48 $'
042: */
043: public class testWriterAndReader extends ModelTestBase implements
044: RDFErrorHandler {
045: static private boolean showProgress = false;
046: //static private boolean errorDetail = false;
047: static private int firstTest = 4;
048: static private int lastTest = 9;
049: static private int repetitionsJ = 6;
050:
051: protected static Log logger = LogFactory
052: .getLog(testWriterAndReader.class);
053:
054: final String lang;
055:
056: final int fileNumber;
057:
058: final int options;
059:
060: String test;
061:
062: testWriterAndReader(String name, String lang, int fileNumber) {
063: this (name, lang, fileNumber, 0);
064: }
065:
066: testWriterAndReader(String name, String lang, int fileNumber,
067: int options) {
068: super (name);
069: this .lang = lang;
070: this .fileNumber = fileNumber;
071: this .options = options;
072: }
073:
074: public String toString() {
075: return getName() + " " + lang + " t" + fileNumber + "000.rdf"
076: + (options != 0 ? ("[" + options + "]") : "");
077: }
078:
079: static Test suiteN_TRIPLE() {
080: return baseSuite("N-TRIPLE");
081: }
082:
083: static TestSuite suiteXML() {
084: TestSuite baseTests = baseSuite("RDF/XML");
085: baseTests.addTestSuite(TestXMLFeatures_XML.class);
086: baseTests.addTest(addXMLtests("RDF/XML", false));
087: return baseTests;
088: }
089:
090: static Test suiteXML_ABBREV() {
091: TestSuite suite = baseSuite("RDF/XML-ABBREV");
092: suite.addTestSuite(TestXMLFeatures_XML_ABBREV.class);
093: suite.addTestSuite(TestXMLAbbrev.class);
094: suite.addTest(addXMLtests("RDF/XML-ABBREV", false));
095: return suite;
096: }
097:
098: public static TestSuite repeatedAbbrevSuite() {
099: TestSuite suite = baseSuite("RDF/XML-ABBREV");
100: suite.addTestSuite(TestXMLFeatures_XML_ABBREV.class);
101: suite.addTestSuite(TestXMLAbbrev.class);
102: suite.addTest(addXMLtests("RDF/XML-ABBREV", true));
103: return suite;
104: }
105:
106: static TestSuite baseSuite(String lang) {
107: TestSuite langsuite = new TestSuite();
108: langsuite.setName(lang);
109: langsuite.addTest(new testWriterInterface("testWriting", lang));
110: langsuite.addTest(new testWriterInterface("testLineSeparator",
111: lang));
112: return langsuite;
113: }
114:
115: public static class TestXMLFeatures_XML extends TestXMLFeatures {
116: public TestXMLFeatures_XML(String name) {
117: super (name, "RDF/XML");
118: }
119: }
120:
121: public static class TestXMLFeatures_XML_ABBREV extends
122: TestXMLFeatures {
123: public TestXMLFeatures_XML_ABBREV(String name) {
124: super (name, "RDF/XML-ABBREV");
125: }
126: }
127:
128: static private boolean nBits(int i, int[] ok) {
129: int bitCount = 0;
130: while (i > 0) {
131: if ((i & 1) == 1)
132: bitCount += 1;
133: i >>= 1;
134: }
135: for (int j = 0; j < ok.length; j += 1)
136: if (bitCount == ok[j])
137: return true;
138: return false;
139: }
140:
141: private static TestSuite addXMLtests(String lang, boolean lots) {
142: TestSuite suite = new TestSuite();
143: int optionLimit = (lang.equals("RDF/XML-ABBREV") ? 1 << blockRules.length
144: : 2);
145: for (int fileNumber = firstTest; fileNumber <= lastTest; fileNumber++) {
146: suite.addTest(new testWriterAndReader("testRandom", lang,
147: fileNumber));
148: suite.addTest(new testWriterAndReader("testLongId", lang,
149: fileNumber));
150: for (int optionMask = 1; optionMask < optionLimit; optionMask += 1) {
151: if (lots
152: || nBits(optionMask, new int[] { 1, /* 2,3,4,5, */
153: 6, 7 }))
154: suite.addTest(createTestOptions(lang, fileNumber,
155: optionMask));
156: }
157: }
158: return suite;
159: }
160:
161: private static testWriterAndReader createTestOptions(String lang,
162: int fileNumber, int optionMask) {
163: return new testWriterAndReader("testOptions " + fileNumber
164: + " " + optionMask, lang, fileNumber, optionMask) {
165: public void runTest() throws IOException {
166: testOptions();
167: }
168: };
169: }
170:
171: public void testRandom() throws IOException {
172: doTest(new String[] {}, new Object[] {});
173: }
174:
175: public void testLongId() throws IOException {
176: doTest(new String[] { "longId" }, new Object[] { Boolean.TRUE });
177: }
178:
179: static Resource[] blockRules = {
180: RDFSyntax.parseTypeLiteralPropertyElt,
181: RDFSyntax.parseTypeCollectionPropertyElt,
182: RDFSyntax.propertyAttr, RDFSyntax.sectionReification,
183: RDFSyntax.sectionListExpand,
184: RDFSyntax.parseTypeResourcePropertyElt, DAML_OIL.collection };
185:
186: public void testOptions() throws IOException {
187: Vector v = new Vector();
188: for (int i = 0; i < blockRules.length; i += 1) {
189: if ((options & (1 << i)) != 0)
190: v.add(blockRules[i]);
191: }
192: Resource blocked[] = new Resource[v.size()];
193: v.copyInto(blocked);
194: doTest(new String[] { "blockRules" },
195: new Resource[][] { blocked });
196: }
197:
198: public void doTest(String[] propNames, Object[] propVals)
199: throws IOException {
200: test(lang, 35, 1, propNames, propVals);
201: }
202:
203: static final String baseUris[] = { "http://foo.com/Hello",
204: "http://foo.com/Hello",
205: "http://daml.umbc.edu/ontologies/calendar-ont",
206: "http://www.daml.org/2001/03/daml+oil-ex" };
207:
208: ByteArrayOutputStream tmpOut;
209:
210: /**
211: * @param rwLang Use Writer for this lang
212: * @param seed A seed for the random number generator
213: * @param variationMax Number of random variations
214: * @param wopName Property names to set on Writer
215: * @param wopVal Property values to set on Writer
216: */
217: public void test(String rwLang, int seed, int variationMax,
218: String[] wopName, Object[] wopVal) throws IOException {
219:
220: Model m1 = createMemModel();
221: test = "testWriterAndReader lang=" + rwLang + " seed=" + seed;
222: String filebase = "testing/regression/testWriterAndReader/";
223: if (showProgress)
224: System.out.println("Beginning " + test);
225: Random random = new Random(seed);
226:
227: RDFReader rdfRdr = m1.getReader(rwLang);
228: RDFWriter rdfWtr = m1.getWriter(rwLang);
229:
230: setWriterOptionsAndHandlers(wopName, wopVal, rdfRdr, rdfWtr);
231: for (int variationIndex = 0; variationIndex < variationMax; variationIndex++)
232: testVariation(filebase, random, rdfRdr, rdfWtr);
233: if (showProgress)
234: System.out.println("End of " + test);
235: }
236:
237: /**
238: @param wopName
239: @param wopVal
240: @param rdfRdr
241: @param rdfWtr
242: */
243: private void setWriterOptionsAndHandlers(String[] wopName,
244: Object[] wopVal, RDFReader rdfRdr, RDFWriter rdfWtr) {
245: rdfRdr.setErrorHandler(this );
246: rdfWtr.setErrorHandler(this );
247: if (wopName != null)
248: for (int i = 0; i < wopName.length; i++)
249: rdfWtr.setProperty(wopName[i], wopVal[i]);
250: }
251:
252: /**
253: @param filebase
254: @param random
255: @param rdfRdr
256: @param rdfWtr
257: @throws FileNotFoundException
258: @throws IOException
259: */
260: private void testVariation(String filebase, Random random,
261: RDFReader rdfRdr, RDFWriter rdfWtr)
262: throws FileNotFoundException, IOException {
263: Model m1 = createMemModel();
264: Model m2;
265: String fileName = "t" + (fileNumber * 1000) + ".rdf";
266: String baseUriRead;
267: if (fileNumber < baseUris.length)
268: baseUriRead = baseUris[fileNumber];
269: else
270: baseUriRead = "http://foo.com/Hello";
271: InputStream rdr = new FileInputStream(filebase + fileName);
272: m1.read(rdr, baseUriRead);
273: rdr.close();
274: for (int j = 0; j < repetitionsJ; j++) {
275:
276: String baseUriWrite = j % 2 == 0 ? baseUriRead
277: : "http://bar.com/irrelevant";
278: int cn = (int) m1.size();
279: if ((j % 2) == 0 && j > 0)
280: prune(m1, random, 1 + cn / 10);
281: if ((j % 2) == 0 && j > 0)
282: expand(m1, random, 1 + cn / 10);
283:
284: tmpOut = new ByteArrayOutputStream();
285: rdfWtr.write(m1, tmpOut, baseUriWrite);
286: tmpOut.flush();
287: tmpOut.close();
288: m2 = createMemModel();
289: //empty(m2);
290:
291: InputStream in = new ByteArrayInputStream(tmpOut
292: .toByteArray());
293: rdfRdr.read(m2, in, baseUriWrite);
294: in.close();
295: Model s1 = m1;
296: Model s2 = m2;
297: /*
298: System.err.println("m1:");
299: m1.write(System.err,"N-TRIPLE");
300: System.err.println("m2:");
301:
302: m2.write(System.err,"N-TRIPLE");
303: System.err.println("=");
304: */
305: // assertTrue(
306: // "Comparison of file written out, and file read in.",
307: // s1.isIsomorphicWith(s2));
308: assertIsoModels(
309: "Comparison of file written out, and file read in.",
310: s1, s2);
311: // Free resources explicitily.
312: tmpOut.reset();
313: tmpOut = null;
314: }
315: if (showProgress) {
316: System.out.print("+");
317: System.out.flush();
318: }
319: }
320:
321: static boolean linuxFileDeleteErrorFlag = false;
322:
323: /**Deletes count edges from m chosen by random.
324: * @param count The number of statements to delete.
325: * @param m A model with more than count statements.
326: */
327: private void prune(Model m, Random random, int count) {
328: // System.out.println("Pruning from " + (int)m.size() + " by " + cnt );
329: Statement toRemove[] = new Statement[count];
330: int sz = (int) m.size();
331: StmtIterator ss = m.listStatements();
332: try {
333: for (int i = 0; i < count; i++)
334: toRemove[i] = ss.nextStatement();
335: while (ss.hasNext()) {
336: int ix = random.nextInt(sz);
337: if (ix < count)
338: toRemove[ix] = ss.nextStatement();
339: }
340: } finally {
341: ss.close();
342: }
343: for (int i = 0; i < count; i++)
344: m.remove(toRemove[i]);
345: // System.out.println("Reduced to " + (int)m.size() );
346: }
347:
348: /**
349: * Adds count edges to m chosen by random.
350: *
351: * @param count The number of statements to add.
352: * @param m A model with more than cnt statements.
353: */
354: private void expand(Model m, Random random, int count) {
355: // System.out.println("Expanding from " + (int)m.size() + " by " + cnt );
356: Resource subject[] = new Resource[count];
357: Property predicate[] = new Property[count];
358: RDFNode object[] = new RDFNode[count];
359: int sz = (int) m.size();
360: StmtIterator ss = m.listStatements();
361: try {
362: for (int i = 0; i < count; i++) {
363: Statement s = ss.nextStatement();
364: subject[i] = s.getSubject();
365: predicate[i] = s.getPredicate();
366: object[i] = s.getObject();
367: }
368: while (ss.hasNext()) {
369: Statement s = ss.nextStatement();
370: Resource subj = s.getSubject();
371: RDFNode obj = s.getObject();
372: int ix = random.nextInt(sz);
373: if (ix < count)
374: subject[ix] = subj;
375: ix = random.nextInt(sz);
376: if (ix < count)
377: object[ix] = subj;
378: ix = random.nextInt(sz);
379: if (ix < count)
380: predicate[ix] = s.getPredicate();
381: ix = random.nextInt(sz);
382: if (ix < count)
383: object[ix] = obj;
384: if (obj instanceof Resource) {
385: ix = random.nextInt(sz);
386: if (ix < count)
387: subject[ix] = (Resource) obj;
388: }
389: }
390: } finally {
391: ss.close();
392: }
393: for (int i = 0; i < count; i++)
394: m.add(subject[i], predicate[i], object[i]);
395: // System.out.println("Expanded to " + (int)m.size() );
396: }
397:
398: /** report a warning
399: * @param e an exception representing the error
400: */
401: public void warning(Exception e) {
402: // logger.warn( toString() + " " + e.getMessage(), e );
403: System.out.println(new String(tmpOut.toString()));
404:
405: throw new JenaException(e);
406: }
407:
408: public void error(Exception e) {
409: fail(e.getMessage());
410: }
411:
412: public void fatalError(Exception e) {
413: error(e);
414: throw new JenaException(e);
415: }
416:
417: }
418:
419: /*
420: * (c) Copyright 2001,2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
421: * All rights reserved.
422: *
423: * Redistribution and use in source and binary forms, with or without
424: * modification, are permitted provided that the following conditions
425: * are met:
426: * 1. Redistributions of source code must retain the above copyright
427: * notice, this list of conditions and the following disclaimer.
428: * 2. Redistributions in binary form must reproduce the above copyright
429: * notice, this list of conditions and the following disclaimer in the
430: * documentation and/or other materials provided with the distribution.
431: * 3. The name of the author may not be used to endorse or promote products
432: * derived from this software without specific prior written permission.
433:
434: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
435: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
436: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
437: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
438: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
439: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
440: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
441: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
442: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
443: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
444: *
445: * $Id: testWriterAndReader.java,v 1.44 2008/01/02 12:06:48 andy_seaborne Exp $
446: */
|