protected Result run() { getConnection().getCacheControl(null).flushSchemaCache(); IntegerProperty monLimit = MondrianProperties.instance().ResultLimit; int oldLimit = monLimit.get(); try { monLimit.set(this.resultLimit); Result result = executeQuery(query, con); // Check the number of positions on the last axis, which is // the ROWS axis in a 2 axis query. int numAxes = result.getAxes().length; Axis a = result.getAxes()[numAxes - 1]; final int positionCount = a.getPositions().size(); assertEquals(rowCount, positionCount); return result; } finally { monLimit.set(oldLimit); } }
/** * Checks that one can veto a property change. * * @param persistent Whether to make strong references to triggers, to prevent them from being * garbage collected * @param save Whether to keep a pointer to each trigger on the stack, to prevent them from being * garbage collected */ private void checkVetoChangeValue(final boolean persistent, boolean save) throws Exception { final MyProperties props = new MyProperties(); String path = "test.mondrian.properties.veto.change.value"; IntegerProperty intProp = new IntegerProperty(props, path, -1); assertTrue("Check property value NOT false", (intProp.get() == -1)); // now explicitly set the property props.setProperty(path, "-1"); String v = props.getProperty(path); assertTrue("Check property value is null", (v != null)); assertTrue("Check property value is -1", (Integer.decode(v).intValue() == -1)); final State3 state = new State3(); state.callCounter = 0; // Add a trigger. Keep it on the stack to prevent it from being // garbage-collected. final Trigger trigger1 = new Trigger() { public boolean isPersistent() { return persistent; } public int phase() { return Trigger.PRIMARY_PHASE; } public void execute(Property property, String value) { state.triggerCalled = true; state.triggerValue = value; } }; intProp.addTrigger(trigger1); SoftReference<Trigger> ref1 = new SoftReference<Trigger>(trigger1); final Trigger trigger2 = new Trigger() { public boolean isPersistent() { return persistent; } public int phase() { return Trigger.SECONDARY_PHASE; } public void execute(Property property, String value) throws VetoRT { // even numbers are rejected state.callCounter++; int ival = Integer.decode(value).intValue(); if ((ival % 2) == 0) { // throw on even throw new VetoRT("have a nice day"); } else { // ok } } }; intProp.addTrigger(trigger2); SoftReference<Trigger> ref2 = new SoftReference<Trigger>(trigger2); // Holder object prevents triggers from being garbage-collected even // if persistent=false. Object saver; if (save) { saver = new Trigger[] {trigger1, trigger2}; } else { saver = "dummy"; } for (int i = 0; i < 10; i++) { // reset values state.triggerCalled = false; state.triggerValue = null; boolean isEven = ((i % 2) == 0); try { props.setProperty(path, Integer.toString(i)); // If triggers have been gc'ed - only possible if persistent = // save = false - then we can't guarantee that state has been // changed. if (!persistent && !save && ((ref1.get() == null) || (ref2.get() == null))) { continue; } // should only be here if odd if (isEven) { fail("Did not pass odd number: " + i); } int val = Integer.decode(state.triggerValue).intValue(); assertTrue("Odd counter not value", (i == val)); } catch (Trigger.VetoRT ex) { // If triggers have been gc'ed - only possible if persistent = // save = false - then we can't guarantee that state has been // changed. if (!persistent && !save && ((ref1.get() == null) || (ref2.get() == null))) { continue; } // Trigger rejects even numbers so if even its ok if (!isEven) { fail("Did not reject even number: " + i); } int val = Integer.decode(state.triggerValue).intValue(); // the property value was reset to the previous value of "i" // so we add "1" to it to get the current value. if (i != (val + 1)) { fail("Even counter not value plus one: " + i + ", " + val); } } } // Refer to the saver object at the end of the routine so that it // cannot be garbage-collected. (Some VMs try to be smart.) assertTrue(saver != null); }