001: /*
002: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: [See end of file]
004: $Id: TestPackage.java,v 1.22 2008/01/02 12:06:35 andy_seaborne Exp $
005: */
006: /*
007: * EnhancedTestSuite.java
008: *
009: * Created on 27 November 2002, 04:53
010: */
011:
012: package com.hp.hpl.jena.enhanced.test;
013:
014: import com.hp.hpl.jena.graph.*;
015: import com.hp.hpl.jena.graph.test.*;
016: import com.hp.hpl.jena.rdf.model.*;
017: import com.hp.hpl.jena.enhanced.*;
018:
019: import junit.framework.*;
020:
021: /**
022: * These tests give a small version of a model-like interface
023: {@link TestModel} with different views
024: * over the nodes in the graph {@link TestSubject},
025: *{@link TestProperty} {@link TestObject}
026: *Any node can be any one of these three, but the interface only works
027: *if the node is the subject, property or object, respectively,
028: of some triple in the graph.
029: *There are two implementations of the three interfaces. We use four
030: * different
031: *personalities, in the tests, from various combinations of the implementation
032: *classes with the interface classes. A more realistic test would be a basic set
033: *of interfaces with implementations, and then some more extended interfaces and
034: *implementations which can work together.
035: *
036: *These tests only test EnhNode polymorphism and not EnhGraph polymorphism.
037: *EnhGraph polymorphism currently will not work.
038: *(For Jena2.0 I am imagining that there will be ModelCom and DAMLModelImpl as
039: *the only two implementations, and they can inherit one from the other).
040: * @author jjc
041: */
042: public class TestPackage extends GraphTestBase {
043:
044: static final private GraphPersonality split = new GraphPersonality();
045:
046: static final private GraphPersonality combo = new GraphPersonality();
047:
048: static final private GraphPersonality bitOfBoth = new GraphPersonality();
049: static final private GraphPersonality broken = new GraphPersonality();
050: static {
051: // Setting up the personalities, involves registering how
052: // each interface is implemented by default.
053: // Note this does not guarantee that the only implementations
054: // of each interface will be the one specified.
055: // See bitOfBoth.
056: split.add(TestObject.class, TestObjectImpl.factory);
057: split.add(TestSubject.class, TestSubjectImpl.factory);
058: split.add(TestProperty.class, TestPropertyImpl.factory);
059:
060: combo.add(TestObject.class, TestAllImpl.factory);
061: combo.add(TestSubject.class, TestAllImpl.factory);
062: combo.add(TestProperty.class, TestAllImpl.factory);
063:
064: bitOfBoth.add(TestObject.class, TestObjectImpl.factory);
065: bitOfBoth.add(TestSubject.class, TestSubjectImpl.factory);
066: bitOfBoth.add(TestProperty.class, TestAllImpl.factory);
067:
068: // broken is misconfigured and must throw an exception.
069: broken.add(TestObject.class, TestObjectImpl.factory);
070: broken.add(TestSubject.class, TestSubjectImpl.factory);
071: broken.add(TestProperty.class, TestObjectImpl.factory);
072: }
073:
074: /** Creates a new instance of EnhancedTestSuite */
075: public TestPackage(String name) {
076: super (name);
077: }
078:
079: public static TestSuite suite() {
080: return new TestSuite(TestPackage.class);
081: }
082:
083: /**
084: test that equals works on an EnhNode (after hedgehog introduced FrontsNode
085: it didn't).
086: */
087: public void testEquals() {
088: EnhNode a = new EnhNode(NodeCreateUtils.create("eg:example"),
089: null);
090: assertEquals(a, a);
091: }
092:
093: /**
094: * View n as intf. This is supported iff rslt.
095: */
096: private static void miniAsSupports(String title, TestNode n,
097: Class intf, boolean rslt) {
098: assertTrue(title + ":sanity", n instanceof Polymorphic);
099:
100: // It is always possible to view any node with any interface.
101: TestNode as1 = (TestNode) ((EnhNode) n).viewAs(intf);
102: TestNode as2 = (TestNode) ((EnhNode) n).viewAs(intf);
103:
104: // caching should ensure we get the same result both times.
105: assertTrue(title + ":idempotency", as1 == as2);
106:
107: // Whether the interface is actually useable depends on the underlying
108: // graph. This factoid is the rslt parameter.
109: assertEquals(title + ":support", rslt, ((EnhNode) as1)
110: .supports(intf));
111: }
112:
113: private static void oneNodeAsSupports(String title, TestNode n,
114: boolean rslts[]) {
115: // Try n with all three interfaces.
116: miniAsSupports(title + "/TestSubject", n, TestSubject.class,
117: rslts[0]);
118: miniAsSupports(title + "/TestProperty", n, TestProperty.class,
119: rslts[1]);
120: miniAsSupports(title + "/TestObject", n, TestObject.class,
121: rslts[2]);
122: }
123:
124: private static void manyNodeAsSupports(String title, TestNode n[],
125: boolean rslts[][]) {
126: // Try each n with each interface.
127: for (int i = 0; i < n.length; i++) {
128: oneNodeAsSupports(title + "[" + i + "]", n[i], rslts[i]);
129: }
130: }
131:
132: /** This test show the basic format of an enhanced test.
133: * This test access data in an enhanced fashion.
134: * All modifications are done through the underlying graph.
135: * The methods tested are as and supports.
136: */
137: private static void basic(String title, Personality p) {
138: Graph g = Factory.createGraphMem();
139: TestModel model = new TestModelImpl(g, p);
140: // create some data
141: graphAdd(g, "x R y;");
142:
143: // The graph has three nodes, extract them as TestNode's,
144: // using the minimalist ModelAPI.
145: TestNode nodes[] = new TestNode[] { model.aSubject(),
146: model.aProperty(), model.anObject() };
147:
148: // Run the basic tests.
149: manyNodeAsSupports(title + "(a)", nodes, new boolean[][] {
150: new boolean[] { true, false, false }, // nodes[0] is subj, but not prop, or obj
151: new boolean[] { false, true, false },
152: new boolean[] { false, false, true } });
153:
154: graphAdd(g, "y R x;");
155:
156: // The expected results are now different.
157: // (A node is appropriate for the TestSubject interface if it is
158: // the subject of some triple in the graph, so the third node
159: // can now be a TestSubject).
160: manyNodeAsSupports(title + "(b)", nodes, new boolean[][] {
161: new boolean[] { true, false, true }, // nodes[0] is subj and obj, but not prop
162: new boolean[] { false, true, false },
163: new boolean[] { true, false, true } });
164:
165: g.delete(triple("x R y"));
166:
167: // The expected results are now different again.
168: // (A node is appropriate for the TestSubject interface if it is
169: // the subject of some triple in the graph, so the third node
170: // can now be a TestSubject).
171:
172: manyNodeAsSupports(title + "(c)", nodes, new boolean[][] {
173: new boolean[] { false, false, true },
174: new boolean[] { false, true, false },
175: new boolean[] { true, false, false } });
176:
177: }
178:
179: /**
180: Would like to get rid of these, but the abstraction is hard to find at the
181: moment. At least they're now just local to this test class.
182: */
183: static final int S = 1;
184: static final int P = 2;
185: static final int O = 3;
186:
187: // This is like the earlier test: miniAsSupports (the last part of it).
188: // However, this time instead of asking whether the interface will work
189: // or not, we just try it.
190: // Obviously sometimes it is broken, which should be reported using
191: // an IllegalStateException.
192: private void canImplement(String title, TestNode n, int wh,
193: boolean rslt) {
194: try {
195: switch (wh) {
196: case S:
197: n.asSubject().aProperty();
198: break;
199: case P:
200: n.asProperty().anObject();
201: break;
202: case O:
203: n.asObject().aSubject();
204: break;
205: }
206: assertTrue("IllegalStateException expected.", rslt);
207: } catch (IllegalStateException e) {
208: assertFalse("IllegalStateException at the wrong time.",
209: rslt);
210: }
211: }
212:
213: private void canImplement(String title, TestNode n, boolean rslts[]) {
214: canImplement(title + "/TestSubject", n, S, rslts[0]);
215: canImplement(title + "/TestProperty", n, P, rslts[1]);
216: canImplement(title + "/TestObject", n, O, rslts[2]);
217: }
218:
219: private void canImplement(String title, TestNode n[],
220: boolean rslts[][]) {
221: for (int i = 0; i < n.length; i++) {
222: canImplement(title + "[" + i + "]", n[i], rslts[i]);
223: }
224: }
225:
226: private void follow(String title, Personality p) {
227: Graph g = Factory.createGraphMem();
228: TestModel model = new TestModelImpl(g, p);
229: // create some data
230: graphAdd(g, "a b c;");
231: TestNode nodes[] = new TestNode[] { model.aSubject(),
232: model.aProperty(), model.anObject() };
233:
234: // Similar to the basic test.
235: canImplement(title + "(a)", nodes, new boolean[][] {
236: new boolean[] { true, false, false },
237: new boolean[] { false, true, false },
238: new boolean[] { false, false, true } });
239:
240: graphAdd(g, "b a c;");
241:
242: // Again like in the basic test the triples have now changed,
243: // so different methods will now work.
244: canImplement(title + "(b)", nodes, new boolean[][] {
245: new boolean[] { true, true, false },
246: new boolean[] { true, true, false },
247: new boolean[] { false, false, true } });
248:
249: g.delete(triple("a b c"));
250:
251: // Again like in the basic test the triples have now changed,
252: // so different methods will now work.
253: canImplement(title + "(c)", nodes, new boolean[][] {
254: new boolean[] { false, true, false },
255: new boolean[] { true, false, false },
256: new boolean[] { false, false, true } });
257:
258: // Another twist.
259: canImplement(title + "(c)", new TestNode[] {
260: nodes[1].asSubject().aProperty(),
261: nodes[2].asObject().aSubject(),
262: nodes[0].asProperty().anObject() }, new boolean[][] {
263: new boolean[] { false, true, false },
264: new boolean[] { true, false, false },
265: new boolean[] { false, false, true } });
266: assertTrue("Model cache test",
267: nodes[0].asProperty().anObject() == nodes[2]);
268: }
269:
270: private void cache(String title, Personality p) {
271: Graph g = Factory.createGraphMem();
272: TestModel model = new TestModelImpl(g, p);
273: // create some data
274: graphAdd(g, "a b a;");
275:
276: // get the same node in two different ways.
277: assertTrue("Caching is on",
278: model.aSubject().asObject() == model.anObject());
279:
280: ((TestModelImpl) model).getNodeCacheControl().setEnabled(false);
281:
282: // get the same node in two different ways; if there isn't any caching
283: // then we reconstruct the node.
284: assertFalse("Caching is off", model.aSubject() == model
285: .anObject());
286:
287: }
288:
289: public static void testSplitBasic() {
290: basic("Split: ", split);
291: }
292:
293: public static void testComboBasic() {
294: basic("Combo: ", combo);
295: }
296:
297: public void testSplitFollow() {
298: follow("Split: ", split);
299: }
300:
301: public void testComboFollow() {
302: follow("Combo: ", combo);
303: }
304:
305: public void testSplitCache() {
306: cache("Split: ", split);
307: }
308:
309: public void testComboCache() {
310: cache("Combo: ", combo);
311: }
312:
313: public static void testBitOfBothBasic() {
314: basic("bob: ", bitOfBoth);
315: }
316:
317: public void testBitOfBothFollow() {
318: follow("bob: ", bitOfBoth);
319: }
320:
321: public void testBitOfBothCache() {
322: cache("bob: ", bitOfBoth);
323: }
324:
325: public static void testBitOfBothSurprise() {
326: // bitOfBoth is a surprising personality ...
327: // we can have two different java objects implementing the same interface.
328:
329: Graph g = Factory.createGraphMem();
330: TestModel model = new TestModelImpl(g, bitOfBoth);
331: // create some data
332: graphAdd(g, "a a a;");
333: TestSubject testSubjectImpl = model.aSubject();
334: assertTrue("BitOfBoth makes subjects using TestSubjectImpl",
335: testSubjectImpl instanceof TestSubjectImpl);
336: TestProperty testAllImpl = testSubjectImpl.aProperty();
337: assertTrue("BitOfBoth makes properties using TestAllImpl",
338: testAllImpl instanceof TestAllImpl);
339: assertTrue(
340: "turning a TestAllImpl into a TestSubject is a no-op",
341: testAllImpl == testAllImpl.asSubject());
342: assertTrue(
343: "turning a TestAllImpl into a TestSubject is a no-op",
344: testSubjectImpl != testAllImpl.asSubject());
345: assertTrue(
346: "turning a TestAllImpl into a TestSubject is a no-op",
347: testSubjectImpl.asSubject() != testSubjectImpl
348: .asSubject().asProperty().asSubject());
349:
350: }
351:
352: public static void testBrokenBasic() {
353: try {
354: // Any of the tests ought to work up and til the point
355: // that they don't. At that point they need to detect the
356: // error and throw the PersonalityConfigException.
357: basic("Broken: ", broken);
358: fail("broken is a misconfigured personality, but it wasn't detected.");
359: } catch (PersonalityConfigException e) {
360:
361: }
362: }
363:
364: static class Example {
365: static final Implementation factory = new Implementation() {
366: public EnhNode wrap(Node n, EnhGraph g) {
367: return new EnhNode(n, g);
368: }
369:
370: public boolean canWrap(Node n, EnhGraph g) {
371: return n.isURI();
372: }
373: };
374: }
375:
376: public void testSimple() {
377: Graph g = Factory.createGraphMem();
378: Personality ours = BuiltinPersonalities.model.copy().add(
379: Example.class, Example.factory);
380: EnhGraph eg = new EnhGraph(g, ours);
381: Node n = Node.createURI("spoo:bar");
382: EnhNode eNode = new EnhNode(Node.createURI("spoo:bar"), eg);
383: EnhNode eBlank = new EnhNode(Node.createAnon(), eg);
384: assertTrue("URI node can be an Example", eNode
385: .supports(Example.class));
386: assertFalse("Blank node cannot be an Example", eBlank
387: .supports(Example.class));
388: }
389:
390: static class AnotherExample {
391: static final Implementation factory = new Implementation() {
392: public EnhNode wrap(Node n, EnhGraph g) {
393: return new EnhNode(n, g);
394: }
395:
396: public boolean canWrap(Node n, EnhGraph g) {
397: return n.isURI();
398: }
399: };
400: }
401:
402: public void testAlreadyLinkedViewException() {
403: Graph g = Factory.createGraphMem();
404: Personality ours = BuiltinPersonalities.model.copy().add(
405: Example.class, Example.factory);
406: EnhGraph eg = new EnhGraph(g, ours);
407: Node n = NodeCreateUtils.create("spoo:bar");
408: EnhNode eNode = new EnhNode(n, eg);
409: eNode.viewAs(Example.class);
410: try {
411: eNode.addView(eNode);
412: fail("should raise an AlreadyLinkedViewException ");
413: } catch (AlreadyLinkedViewException e) {
414: }
415: }
416:
417: /**
418: Test that an attempt to polymorph an enhanced node into a class that isn't
419: supported by the enhanced graph generates an UnsupportedPolymorphism
420: exception.
421: */
422: public void testNullPointerTrap() {
423: EnhGraph eg = new EnhGraph(Factory.createGraphMem(),
424: BuiltinPersonalities.model);
425: Node n = NodeCreateUtils.create("eh:something");
426: EnhNode en = new EnhNode(n, eg);
427: try {
428: en.as(TestPackage.class);
429: fail("oops");
430: } catch (UnsupportedPolymorphismException e) {
431: assertEquals(en, e.getBadNode());
432: assertTrue("exception should have cuplprit graph", eg == e
433: .getBadGraph());
434: assertTrue("exception should have culprit class",
435: TestPackage.class == e.getBadClass());
436: }
437: }
438:
439: public void testNullPointerTrapInCanSupport() {
440: EnhGraph eg = new EnhGraph(Factory.createGraphMem(),
441: BuiltinPersonalities.model);
442: Node n = NodeCreateUtils.create("eh:something");
443: EnhNode en = new EnhNode(n, eg);
444: assertFalse(en.canAs(Integer.class));
445: }
446:
447: public void testAsToOwnClassWithNoModel() {
448: Resource r = ResourceFactory.createResource();
449: assertEquals(null, r.getModel());
450: assertTrue(r.canAs(Resource.class));
451: assertSame(r, r.as(Resource.class));
452: }
453:
454: public void testCanAsReturnsFalseIfNoModel() {
455: Resource r = ResourceFactory.createResource();
456: assertEquals(false, r.canAs(Example.class));
457: }
458:
459: public void testAsThrowsPolymorphismExceptionIfNoModel() {
460: Resource r = ResourceFactory.createResource();
461: try {
462: r.as(Example.class);
463: fail("should throw UnsupportedPolymorphismException");
464: } catch (UnsupportedPolymorphismException e) {
465: assertEquals(null, e.getBadGraph());
466: assertEquals(Example.class, e.getBadClass());
467: }
468: }
469:
470: }
471:
472: /*
473: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
474: All rights reserved.
475:
476: Redistribution and use in source and binary forms, with or without
477: modification, are permitted provided that the following conditions
478: are met:
479:
480: 1. Redistributions of source code must retain the above copyright
481: notice, this list of conditions and the following disclaimer.
482:
483: 2. Redistributions in binary form must reproduce the above copyright
484: notice, this list of conditions and the following disclaimer in the
485: documentation and/or other materials provided with the distribution.
486:
487: 3. The name of the author may not be used to endorse or promote products
488: derived from this software without specific prior written permission.
489:
490: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
491: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
492: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
493: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
494: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
495: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
496: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
497: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
498: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
499: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
500: */
|