package org.simantics.db.tests.regression.bugs; import org.junit.Test; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.WriteOnlyGraph; import org.simantics.db.common.request.WriteOnlyResultRequest; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.AssumptionException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.InvalidResourceReferenceException; import org.simantics.db.impl.query.QuerySupport; import org.simantics.db.service.SerialisationSupport; import org.simantics.db.service.XSupport; import org.simantics.db.testing.cases.FreshDatabaseTest; public class Issue3108Test1 extends FreshDatabaseTest { private static final boolean DEBUG = false; static class TestGetResourceId extends WriteRequest { final int key; public TestGetResourceId(int clusterIndex, int resourceIndex) { this.key = (clusterIndex << 16) + resourceIndex; } @SuppressWarnings("deprecation") // Using createRandomAccessId to simulate error while loading non existing cluster. @Override public void perform(WriteGraph graph) throws DatabaseException { SerialisationSupport ss = graph.getService(SerialisationSupport.class); QuerySupport gs = graph.getService(QuerySupport.class); Resource r = gs.getResource(key); try { // This used to throw RuntimeDatabaseException when loading illegal cluster failed // but now the implementation has changed and this does not try to load cluster. // long id = r.getResourceId(); // if (0 == id) // throw new AssumptionException("Illegal resource returned zero as expected."); if (DEBUG) System.out.println("DEBBUG: resource key=" + key + " r="+ r); ss.getResourceSerializer().createRandomAccessId(r); } catch (InvalidResourceReferenceException e) { if (DEBUG) System.out.println("Catched InvalidResourceReferenceException:" + e.getMessage()); throw new AssumptionException("Illegal resource threw runtime error.", e); } } } @Test public void testIssue3108Test1() throws Exception { final Session session = getSession(); // This simulates the situation in Apros bug 4210. // We have an illegal entry in cluster table and we want to handle it // gracefully. boolean exceptionThrown = false; try { XSupport xs = (XSupport)session.getService(XSupport.class); long illegalClusterId1 = 666666; int clusterIndex = xs.corruptClusterTable(illegalClusterId1); session.syncRequest(new TestGetResourceId(clusterIndex, 666)); } catch (Exception e) { exceptionThrown = true; if (DEBUG) System.out.println("Catched Exception as excepected:" + e.getMessage()); } catch (Throwable e) { fail("Write transaction threw an unknown exception " + e); } assertTrue("Failed to throw exception as expected.", exceptionThrown); // Here we have an illegal resource id without proxy in cluster table. exceptionThrown = false; try { session.syncRequest(new TestGetResourceId(666, 666)); } catch (AssumptionException e) { exceptionThrown = true; if (DEBUG) System.out.println("Catched AssumptionException as excepected:" + e.getMessage()); } catch (Throwable e) { fail("Write transaction threw an unknown exception " + e); } assertTrue("Failed to throw exception as expected.", exceptionThrown); // Here we have an illegal resource index with valid cluster proxy. // Note that in this case the invalid resource index is not reported. try { session.syncRequest(new TestGetResourceId(1, 6666)); } catch (Throwable e) { fail("Write transaction threw an unknown exception " + e); } } static class TestWriteOnly extends WriteOnlyResultRequest { public long id = 0; public int key = 0; @Override public Long perform(WriteOnlyGraph graph) throws DatabaseException { graph.flushCluster(); XSupport xs = (XSupport)graph.getService(XSupport.class); xs.setClusterStreamOff(true); Resource r = graph.newResource(); id = r.getResourceId(); SerialisationSupport ss = graph.getService(SerialisationSupport.class); key = ss.getTransientId(id); xs.setClusterStreamOff(false); return id; } } }