Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/OneExpireOneNotTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/OneExpireOneNotTest.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/OneExpireOneNotTest.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/OneExpireOneNotTest.java Sun Oct 26 13:17:28 2014 @@ -1,253 +1,254 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.sun.jini.test.impl.norm; - -import java.util.logging.Level; - -import java.io.PrintWriter; - -import java.rmi.RemoteException; - -import net.jini.core.lease.Lease; - -import net.jini.lease.LeaseRenewalService; -import net.jini.lease.LeaseRenewalSet; - -import com.sun.jini.qa.harness.TestException; -import com.sun.jini.qa.harness.QAConfig; - -import com.sun.jini.qa.harness.QAConfig; -import com.sun.jini.qa.harness.QATestEnvironment; -import com.sun.jini.qa.harness.Test; - -import com.sun.jini.test.share.LeaseBackEndImpl; -import com.sun.jini.test.share.LeaseOwner; -import com.sun.jini.test.share.ForeverOwner; -import com.sun.jini.test.share.TrackingOwner; - -/** - * Try to make sure that client leases associated with a set that has - * expired do not affect client leases in a set that has not expired. - * Create two sets and a number of leases that can be batched together - * and expire at the same time as the sets. Place half the leases in - * one set and half in the other. Let one set expire. Make sure that - * leases in the expired set don't get renewed after the set expires, - * and that the other leases don't expire. - */ -public class OneExpireOneNotTest extends QATestEnvironment implements Test { - /** The service under test */ - private LeaseRenewalService lrs; - - /** the name of service for which these test are written */ - static protected final String SERVICE_NAME = - "net.jini.lease.LeaseRenewalService"; - - /** How long a lease to get on the expiring set */ - private long setDuration = 0; - - /** The time allowed for network transfers to take place */ - private long latencySlop = 0; - - /** The maximum time granted for a lease by a renew operation. */ - private long renewGrant = 0; - - /** Numbe of client leases to create */ - private int leaseCount = 0; - - /** - * Sets up the testing environment. - */ - public Test construct(QAConfig sysConfig) throws Exception { - - // mandatory call to parent - super.construct(sysConfig); - - // output the name of this test - logger.log(Level.FINE, "Test Name = " + this.getClass().getName()); - - // Announce where we are in the test - logger.log(Level.FINE, "OneExpireOneNotTest:In setup() method."); - - // capture an instance of the Properties file. - QAConfig config = (QAConfig)getConfig(); - - String property = "com.sun.jini.test.impl.norm.setDuration"; - setDuration = getConfig().getLongConfigVal(property, 120000); - - property = "com.sun.jini.test.impl.norm.renewGrant"; - renewGrant = getConfig().getLongConfigVal(property, 30000); - - property = "com.sun.jini.test.impl.norm.leaseCount"; - leaseCount = getConfig().getIntConfigVal(property, 40); - // Make leaseCount event so filling the sets is easer - if (leaseCount % 2 != 0) - leaseCount++; - - // capture the max time allowed for network transfer - property = "com.sun.jini.test.impl.norm.latencySlop"; - latencySlop = getConfig().getLongConfigVal(property, 2000); - - // Get an LRS - logger.log(Level.FINE, "Getting a " + SERVICE_NAME); - lrs = (LeaseRenewalService)getManager().startService(SERVICE_NAME); - return this; - } - - public void run() throws Exception { - // Announce where we are in the test - logger.log(Level.FINE, "OneExpireOneNotTest: In run() method."); - - long setCreation = System.currentTimeMillis(); - LeaseRenewalSet setExpire = lrs.createLeaseRenewalSet(setDuration); - setExpire = prepareSet(setExpire); - logger.log(Level.FINE, "OneExpireOneNotTest: Expire set created"); - LeaseRenewalSet setKeep = lrs.createLeaseRenewalSet(Lease.FOREVER); - setKeep = prepareSet(setKeep); - Lease expsLease = setExpire.getRenewalSetLease(); - expsLease = (Lease) getConfig().prepare( - "test.normLeasePreparer", expsLease); - - final LeaseBackEndImpl backend = new LeaseBackEndImpl(leaseCount); - backend.export(); - - for (int i=0; i<leaseCount; i+=2) { - long initExpiration = System.currentTimeMillis() + renewGrant; - LeaseOwner o = new ForeverOwner(initExpiration, renewGrant, - latencySlop, Lease.FOREVER, this, true, getConfig()); - Lease l = backend.newLease(o, initExpiration); - setKeep.renewFor(l, Lease.FOREVER); - - initExpiration = System.currentTimeMillis() + renewGrant; - o = new ExpiryOwner(initExpiration, renewGrant, - latencySlop, Lease.FOREVER, this, true, getConfig(), expsLease); - l = backend.newLease(o, initExpiration); - long delta = System.currentTimeMillis() - setCreation; - System.out.println("Delta => " + delta); - setExpire.renewFor(l, Lease.FOREVER); - } - - // Sleep until the first lease expires + its initial length, or we - // detect a failure - synchronized (this) { - while (true) { - LeaseOwner[] owners = backend.getOwners(); - - // See if there have been any failures - for (int i=0; i<owners.length; i++) { - final TrackingOwner owner = (TrackingOwner)owners[i]; - final String rslt = owner.didPass(); - if (rslt != null) { - throw new TestException( rslt); - } - } - - final long now = System.currentTimeMillis(); - - // If we have waited long enough break - if (now - expsLease.getExpiration() >= setDuration) - break; - - try { - wait(expsLease.getExpiration() - now + setDuration); - } catch (InterruptedException e) { - throw new TestException( - "Unexpected InterruptedException."); - } - } - } - } - - /** - * Subclass of forever owner that makes sure that the set - * containing the owned lease has not expired - */ - private class ExpiryOwner extends ForeverOwner { - - /** Lease of the set containing the lease we own */ - final private Lease renewalSetLease; - - /** - * Simple constructor - * @param initialExpiration Initial expiration time for lease. - * @param maxExtension Maximum time this owner will be willing to extend - * the lease - * @param slop Allowable variance from desired expiration when making a - * renewal request. - * @param desiredRenewal - * Expect value of the renewDuration parameter - * @param notifyOnFailure - * Object to notify if there is a failure - * @param isTwoArg Should the assocated lease be registered - * with the one or two arg form - * @param util QA harnss utility object - * @param renewalSetLease The lease of the renewal set the - * lease we are an owner of will be placed in - */ - public ExpiryOwner(long initialExpiration, long maxExtension, - long slop, long desiredRenewal, Object notifyOnFailure, - boolean isTwoArg, QAConfig config, Lease renewalSetLease) - { - super(initialExpiration, maxExtension, - slop, desiredRenewal, notifyOnFailure, isTwoArg, config); - this.renewalSetLease = renewalSetLease; - } - - // Inherit java doc from super type - protected boolean isValidExtension(long extension) { - // Check to make sure the set has not expired - boolean t = false; - synchronized (this){ - t = now - slop > renewalSetLease.getExpiration(); - } - if (t) { - // The set has expired, this renewal should not - // be happending - setRsltIfNeeded("Expire Owner:LRS asked for a renewal " + - "after renewal set expiration!"); - return false; - } - return super.isValidExtension(extension); - } - - /** - * Override to not flag a failure if the lease we own has - * expired and the the set's lease has as well. - */ - public synchronized String didPass() { - final String rslt = getRslt(); - if (rslt != null) - return rslt; - - final long now = System.currentTimeMillis(); - - if (renewalSetLease.getExpiration() < now) { - // We don't care it our lease has expired or not - return null; - } - - return super.didPass(); - } - } - - protected LeaseRenewalSet prepareSet(LeaseRenewalSet set) - throws TestException - { - Object s = getConfig().prepare("test.normRenewalSetPreparer", set); - return (LeaseRenewalSet) s; - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.sun.jini.test.impl.norm; + +import java.util.logging.Level; + +import java.io.PrintWriter; + +import java.rmi.RemoteException; + +import net.jini.core.lease.Lease; + +import net.jini.lease.LeaseRenewalService; +import net.jini.lease.LeaseRenewalSet; + +import com.sun.jini.qa.harness.TestException; +import com.sun.jini.qa.harness.QAConfig; + +import com.sun.jini.qa.harness.QAConfig; +import com.sun.jini.qa.harness.QATestEnvironment; +import com.sun.jini.qa.harness.Test; + +import com.sun.jini.test.share.LeaseBackEndImpl; +import com.sun.jini.test.share.LeaseOwner; +import com.sun.jini.test.share.ForeverOwner; +import com.sun.jini.test.share.TrackingOwner; + +/** + * Try to make sure that client leases associated with a set that has + * expired do not affect client leases in a set that has not expired. + * Create two sets and a number of leases that can be batched together + * and expire at the same time as the sets. Place half the leases in + * one set and half in the other. Let one set expire. Make sure that + * leases in the expired set don't get renewed after the set expires, + * and that the other leases don't expire. + */ +public class OneExpireOneNotTest extends QATestEnvironment implements Test { + /** The service under test */ + private LeaseRenewalService lrs; + + /** the name of service for which these test are written */ + static protected final String SERVICE_NAME = + "net.jini.lease.LeaseRenewalService"; + + /** How long a lease to get on the expiring set */ + private long setDuration = 0; + + /** The time allowed for network transfers to take place */ + private long latencySlop = 0; + + /** The maximum time granted for a lease by a renew operation. */ + private long renewGrant = 0; + + /** Numbe of client leases to create */ + private int leaseCount = 0; + + /** + * Sets up the testing environment. + */ + public Test construct(QAConfig sysConfig) throws Exception { + + // mandatory call to parent + super.construct(sysConfig); + + // output the name of this test + logger.log(Level.FINE, "Test Name = " + this.getClass().getName()); + + // Announce where we are in the test + logger.log(Level.FINE, "OneExpireOneNotTest:In setup() method."); + + // capture an instance of the Properties file. + QAConfig config = (QAConfig)getConfig(); + + String property = "com.sun.jini.test.impl.norm.setDuration"; + setDuration = getConfig().getLongConfigVal(property, 120000); + + property = "com.sun.jini.test.impl.norm.renewGrant"; + renewGrant = getConfig().getLongConfigVal(property, 30000); + + property = "com.sun.jini.test.impl.norm.leaseCount"; + leaseCount = getConfig().getIntConfigVal(property, 40); + // Make leaseCount event so filling the sets is easer + if (leaseCount % 2 != 0) + leaseCount++; + + // capture the max time allowed for network transfer + property = "com.sun.jini.test.impl.norm.latencySlop"; + latencySlop = getConfig().getLongConfigVal(property, 2000); + + // Get an LRS + logger.log(Level.FINE, "Getting a " + SERVICE_NAME); + lrs = (LeaseRenewalService)getManager().startService(SERVICE_NAME); + return this; + } + + public void run() throws Exception { + // Announce where we are in the test + logger.log(Level.FINE, "OneExpireOneNotTest: In run() method."); + + long setCreation = System.currentTimeMillis(); + LeaseRenewalSet setExpire = lrs.createLeaseRenewalSet(setDuration); + setExpire = prepareSet(setExpire); + logger.log(Level.FINE, "OneExpireOneNotTest: Expire set created"); + LeaseRenewalSet setKeep = lrs.createLeaseRenewalSet(Lease.FOREVER); + setKeep = prepareSet(setKeep); + Lease expsLease = setExpire.getRenewalSetLease(); + expsLease = (Lease) getConfig().prepare( + "test.normLeasePreparer", expsLease); + + final LeaseBackEndImpl backend = new LeaseBackEndImpl(leaseCount); + backend.export(); + + for (int i=0; i<leaseCount; i+=2) { + long initExpiration = System.currentTimeMillis() + renewGrant; + LeaseOwner o = new ForeverOwner(initExpiration, renewGrant, + latencySlop, Lease.FOREVER, this, true, getConfig()); + Lease l = backend.newLease(o, initExpiration); + setKeep.renewFor(l, Lease.FOREVER); + + initExpiration = System.currentTimeMillis() + renewGrant; + o = new ExpiryOwner(initExpiration, renewGrant, + latencySlop, Lease.FOREVER, this, true, getConfig(), expsLease); + l = backend.newLease(o, initExpiration); + long delta = System.currentTimeMillis() - setCreation; + System.out.println("Delta => " + delta); + setExpire.renewFor(l, Lease.FOREVER); + } + + // Sleep until the first lease expires + its initial length, or we + // detect a failure + synchronized (this) { + while (true) { + LeaseOwner[] owners = backend.getOwners(); + + // See if there have been any failures + for (int i=0; i<owners.length; i++) { + final TrackingOwner owner = (TrackingOwner)owners[i]; + final String rslt = owner.didPass(); + if (rslt != null) { + throw new TestException( rslt); + } + } + + final long now = System.currentTimeMillis(); + + // If we have waited long enough break + if (now - expsLease.getExpiration() >= setDuration) + break; + + try { + wait(expsLease.getExpiration() - now + setDuration); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TestException( + "Unexpected InterruptedException."); + } + } + } + } + + /** + * Subclass of forever owner that makes sure that the set + * containing the owned lease has not expired + */ + private class ExpiryOwner extends ForeverOwner { + + /** Lease of the set containing the lease we own */ + final private Lease renewalSetLease; + + /** + * Simple constructor + * @param initialExpiration Initial expiration time for lease. + * @param maxExtension Maximum time this owner will be willing to extend + * the lease + * @param slop Allowable variance from desired expiration when making a + * renewal request. + * @param desiredRenewal + * Expect value of the renewDuration parameter + * @param notifyOnFailure + * Object to notify if there is a failure + * @param isTwoArg Should the assocated lease be registered + * with the one or two arg form + * @param util QA harnss utility object + * @param renewalSetLease The lease of the renewal set the + * lease we are an owner of will be placed in + */ + public ExpiryOwner(long initialExpiration, long maxExtension, + long slop, long desiredRenewal, Object notifyOnFailure, + boolean isTwoArg, QAConfig config, Lease renewalSetLease) + { + super(initialExpiration, maxExtension, + slop, desiredRenewal, notifyOnFailure, isTwoArg, config); + this.renewalSetLease = renewalSetLease; + } + + // Inherit java doc from super type + protected boolean isValidExtension(long extension) { + // Check to make sure the set has not expired + boolean t = false; + synchronized (this){ + t = now - slop > renewalSetLease.getExpiration(); + } + if (t) { + // The set has expired, this renewal should not + // be happending + setRsltIfNeeded("Expire Owner:LRS asked for a renewal " + + "after renewal set expiration!"); + return false; + } + return super.isValidExtension(extension); + } + + /** + * Override to not flag a failure if the lease we own has + * expired and the the set's lease has as well. + */ + public synchronized String didPass() { + final String rslt = getRslt(); + if (rslt != null) + return rslt; + + final long now = System.currentTimeMillis(); + + if (renewalSetLease.getExpiration() < now) { + // We don't care it our lease has expired or not + return null; + } + + return super.didPass(); + } + } + + protected LeaseRenewalSet prepareSet(LeaseRenewalSet set) + throws TestException + { + Object s = getConfig().prepare("test.normRenewalSetPreparer", set); + return (LeaseRenewalSet) s; + } +}
Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/RenewAtTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/RenewAtTest.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/RenewAtTest.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/norm/RenewAtTest.java Sun Oct 26 13:17:28 2014 @@ -1,193 +1,194 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.sun.jini.test.impl.norm; - -import java.util.logging.Level; - -// Test harness specific classes -import com.sun.jini.qa.harness.QAConfig; -import com.sun.jini.qa.harness.Test; -import com.sun.jini.qa.harness.TestException; - -import net.jini.core.lease.Lease; - -import net.jini.lease.LeaseRenewalService; -import net.jini.lease.LeaseRenewalSet; - -import com.sun.jini.test.share.TestBase; - - -/** - * Test creates a lease a number of leases and adds them with - * diffrent desiered expiration and renew durations wait for - * some time and makes sure that only the leases that should - * have expired expire. - */ -public class RenewAtTest extends TestBase implements Test { - /** Ammount of slop we are willing to tolerate around renewals */ - private long slop; - - /** Should we try shuting down the service under test? */ - private boolean tryShutdown; - - public Test construct(QAConfig sysConfig) throws Exception { - super.construct(sysConfig); - this.parse(); - return this; - } - - /** - * Parse our args - * <DL> - * - * <DT>-slop <var>int</var><DD> Amount of slop in milliseconds we - * are willing to tolrate in renewal requests (compared to the ideal - * request) and in missing expirations. - * - * <DT>-tryShutdown <DD>If used the test will kill the VM the service - * is running in after adding the client lease to the set and again - * after removing the lease from the set. - * </DL> - */ - protected void parse() throws Exception { - super.parse(); - slop = getConfig().getLongConfigVal("slop", 5000); - tryShutdown = getConfig().getBooleanConfigVal("tryShutdown", false); - } - - /** - * Create a new RenewAtOwner - * @param initialDuration This inital duration the lease should have - * @param maxExtension Max renewal to grant - * @param desiredDuration Duration we want - * @param desiredRenewal Renewal LRS should request - */ - private RenewAtOwner createOwner(long initialDuration, long maxExtension, - long desiredDuration, long desiredRenewal) - { - final long now = System.currentTimeMillis(); - long desiredExpiration = desiredDuration + now; - - if (desiredDuration == Lease.FOREVER) { - desiredExpiration = Lease.FOREVER; - } - - return new RenewAtOwner(initialDuration + now, maxExtension, - desiredExpiration, slop, desiredRenewal, this); - } - - private void checkOwners(LeaseBackEndImpl home) throws TestException { - final LeaseOwner owners[] = home.getOwners(); - for (int i=0; i<owners.length; i++) { - final RenewAtOwner owner = (RenewAtOwner)owners[i]; - final String rslt = owner.didPass(); - if (rslt != null) { - throw new TestException(rslt); - } - } - } - - public void run() throws Exception { - specifyServices(new Class[]{LeaseRenewalService.class}); - LeaseRenewalService lrs = (LeaseRenewalService)services[0]; - LeaseRenewalSet set = lrs.createLeaseRenewalSet(Lease.FOREVER); - set = prepareSet(set); - addLease(prepareNormLease(set.getRenewalSetLease()), false); - - long now = System.currentTimeMillis(); - - // Add a local lease to get things primed - set.renewFor(LocalLease.getLocalLease(now + 600000, 600000, 1, 1), Lease.FOREVER); - - // Create the object that will serve as the landlord - final RenewAtOwner owners[] = new RenewAtOwner[8]; - final LeaseBackEndImpl home = new LeaseBackEndImpl(owners.length); - home.export(); - int j = 0; - - // Desired exp before end of test, desired renewal < max grant - owners[j++] = createOwner(60000, 60000, 300000, 30000); - - // Desired exp FOREVER, desired renewal = ANY - owners[j++] = createOwner(30000, 45000, Lease.FOREVER, Lease.ANY); - - // Desired exp FOREVER, desired renewal > max grant - owners[j++] = createOwner(45000, 45000, Lease.FOREVER, 60000); - - // Desired exp FOREVER, desired renewal < max grant - owners[j++] = createOwner(45000, 600000, Lease.FOREVER, 75000); - - // Desired exp < current exp - owners[j++] = createOwner(400000, 45000, 350000, 60000); - - // Desired exp after end of test, desired renewal < max grant - owners[j++] = createOwner(30000, 60000, 600000, 45000); - - // Desired exp after end of test, desired renewal > max grant - owners[j++] = createOwner(30000, 30000, 650000, 45000); - - // Desired exp before end of test, desired renewal > max grant - owners[j++] = createOwner(60000, 30000, 250000, 60000); - - for (int i=0; i<owners.length; i++) { - final RenewAtOwner owner = (RenewAtOwner)owners[i]; - - final Lease lease = home.newLease(owner, owner.getExpiration()); - set.renewFor(lease, owner.getDesiredDuration(), - owner.getDesiredRenewal()); - } - - if (tryShutdown) - shutdown(0); - - final long totalWait = 300000 + slop * 2; - boolean middleShutdown = false; - - synchronized (this) { - checkOwners(home); - final long start = System.currentTimeMillis(); - long elapsed = 0; - - while (elapsed < totalWait) { - try { - long waitFor = totalWait - elapsed; - - if (!middleShutdown && tryShutdown) - waitFor = totalWait/2 - elapsed; - - logger.log(Level.INFO, "Sleeping for " + waitFor); - wait(waitFor); - - if (!middleShutdown && tryShutdown) { - middleShutdown = true; - shutdown(0); - } - } catch (InterruptedException e) { - throw new TestException("wait interupted:" + e.getMessage()); - } - - checkOwners(home); - elapsed = System.currentTimeMillis() - start; - } - - checkOwners(home); - } - } -} - - +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.sun.jini.test.impl.norm; + +import java.util.logging.Level; + +// Test harness specific classes +import com.sun.jini.qa.harness.QAConfig; +import com.sun.jini.qa.harness.Test; +import com.sun.jini.qa.harness.TestException; + +import net.jini.core.lease.Lease; + +import net.jini.lease.LeaseRenewalService; +import net.jini.lease.LeaseRenewalSet; + +import com.sun.jini.test.share.TestBase; + + +/** + * Test creates a lease a number of leases and adds them with + * diffrent desiered expiration and renew durations wait for + * some time and makes sure that only the leases that should + * have expired expire. + */ +public class RenewAtTest extends TestBase implements Test { + /** Ammount of slop we are willing to tolerate around renewals */ + private long slop; + + /** Should we try shuting down the service under test? */ + private boolean tryShutdown; + + public Test construct(QAConfig sysConfig) throws Exception { + super.construct(sysConfig); + this.parse(); + return this; + } + + /** + * Parse our args + * <DL> + * + * <DT>-slop <var>int</var><DD> Amount of slop in milliseconds we + * are willing to tolrate in renewal requests (compared to the ideal + * request) and in missing expirations. + * + * <DT>-tryShutdown <DD>If used the test will kill the VM the service + * is running in after adding the client lease to the set and again + * after removing the lease from the set. + * </DL> + */ + protected void parse() throws Exception { + super.parse(); + slop = getConfig().getLongConfigVal("slop", 5000); + tryShutdown = getConfig().getBooleanConfigVal("tryShutdown", false); + } + + /** + * Create a new RenewAtOwner + * @param initialDuration This inital duration the lease should have + * @param maxExtension Max renewal to grant + * @param desiredDuration Duration we want + * @param desiredRenewal Renewal LRS should request + */ + private RenewAtOwner createOwner(long initialDuration, long maxExtension, + long desiredDuration, long desiredRenewal) + { + final long now = System.currentTimeMillis(); + long desiredExpiration = desiredDuration + now; + + if (desiredDuration == Lease.FOREVER) { + desiredExpiration = Lease.FOREVER; + } + + return new RenewAtOwner(initialDuration + now, maxExtension, + desiredExpiration, slop, desiredRenewal, this); + } + + private void checkOwners(LeaseBackEndImpl home) throws TestException { + final LeaseOwner owners[] = home.getOwners(); + for (int i=0; i<owners.length; i++) { + final RenewAtOwner owner = (RenewAtOwner)owners[i]; + final String rslt = owner.didPass(); + if (rslt != null) { + throw new TestException(rslt); + } + } + } + + public void run() throws Exception { + specifyServices(new Class[]{LeaseRenewalService.class}); + LeaseRenewalService lrs = (LeaseRenewalService)services[0]; + LeaseRenewalSet set = lrs.createLeaseRenewalSet(Lease.FOREVER); + set = prepareSet(set); + addLease(prepareNormLease(set.getRenewalSetLease()), false); + + long now = System.currentTimeMillis(); + + // Add a local lease to get things primed + set.renewFor(LocalLease.getLocalLease(now + 600000, 600000, 1, 1), Lease.FOREVER); + + // Create the object that will serve as the landlord + final RenewAtOwner owners[] = new RenewAtOwner[8]; + final LeaseBackEndImpl home = new LeaseBackEndImpl(owners.length); + home.export(); + int j = 0; + + // Desired exp before end of test, desired renewal < max grant + owners[j++] = createOwner(60000, 60000, 300000, 30000); + + // Desired exp FOREVER, desired renewal = ANY + owners[j++] = createOwner(30000, 45000, Lease.FOREVER, Lease.ANY); + + // Desired exp FOREVER, desired renewal > max grant + owners[j++] = createOwner(45000, 45000, Lease.FOREVER, 60000); + + // Desired exp FOREVER, desired renewal < max grant + owners[j++] = createOwner(45000, 600000, Lease.FOREVER, 75000); + + // Desired exp < current exp + owners[j++] = createOwner(400000, 45000, 350000, 60000); + + // Desired exp after end of test, desired renewal < max grant + owners[j++] = createOwner(30000, 60000, 600000, 45000); + + // Desired exp after end of test, desired renewal > max grant + owners[j++] = createOwner(30000, 30000, 650000, 45000); + + // Desired exp before end of test, desired renewal > max grant + owners[j++] = createOwner(60000, 30000, 250000, 60000); + + for (int i=0; i<owners.length; i++) { + final RenewAtOwner owner = (RenewAtOwner)owners[i]; + + final Lease lease = home.newLease(owner, owner.getExpiration()); + set.renewFor(lease, owner.getDesiredDuration(), + owner.getDesiredRenewal()); + } + + if (tryShutdown) + shutdown(0); + + final long totalWait = 300000 + slop * 2; + boolean middleShutdown = false; + + synchronized (this) { + checkOwners(home); + final long start = System.currentTimeMillis(); + long elapsed = 0; + + while (elapsed < totalWait) { + try { + long waitFor = totalWait - elapsed; + + if (!middleShutdown && tryShutdown) + waitFor = totalWait/2 - elapsed; + + logger.log(Level.INFO, "Sleeping for " + waitFor); + wait(waitFor); + + if (!middleShutdown && tryShutdown) { + middleShutdown = true; + shutdown(0); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TestException("wait interupted:" + e.getMessage()); + } + + checkOwners(home); + elapsed = System.currentTimeMillis() - start; + } + + checkOwners(home); + } + } +} + + Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/api/InterruptTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/api/InterruptTest.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/api/InterruptTest.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/api/InterruptTest.java Sun Oct 26 13:17:28 2014 @@ -1,95 +1,96 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.sun.jini.test.impl.outrigger.api; - -import java.util.logging.Level; - -// java classes -import java.rmi.RemoteException; - -// jini classes -import net.jini.space.JavaSpace; -import net.jini.admin.Administrable; - -// Test harness specific classes -import com.sun.jini.qa.harness.TestException; -import com.sun.jini.qa.harness.QAConfig; -import com.sun.jini.qa.harness.QATestEnvironment; - - - -// Shared classes -import com.sun.jini.qa.harness.Test; -import com.sun.jini.test.share.TestBase; - - -/** - * Test to make sure blocking reads can be interrupted - */ -public class InterruptTest extends TestBase implements Test { - - - private class ReadThread extends Thread { - Exception rslt = null; - JavaSpace space; - - ReadThread(JavaSpace s) { - super("ReadThread"); - space = s; - } - - public void run() { - try { - space.read(null, null, 10000); - } catch (InterruptedException e) { - rslt = e; - } catch (Exception e) { - rslt = e; - } - } - } - - public Test construct(QAConfig config) throws Exception { - super.construct(config); - super.parse(); - return this; - } - - public void run() throws Exception { - specifyServices(new Class[] {JavaSpace.class}); - final JavaSpace space = (JavaSpace) services[0]; - - // Kick of read in a seperate thread - ReadThread readThread = new ReadThread(space); - readThread.start(); - - Thread.sleep(5000); - readThread.interrupt(); - readThread.join(); - - if (readThread.rslt == null) { - throw new TestException("Read returned normally"); - } else if (readThread.rslt instanceof InterruptedException) { - return; - } else { - throw new TestException( - "Expected: InterruptedException. Returned: " - + readThread.rslt.getMessage()); - } - } -} +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.sun.jini.test.impl.outrigger.api; + +import java.util.logging.Level; + +// java classes +import java.rmi.RemoteException; + +// jini classes +import net.jini.space.JavaSpace; +import net.jini.admin.Administrable; + +// Test harness specific classes +import com.sun.jini.qa.harness.TestException; +import com.sun.jini.qa.harness.QAConfig; +import com.sun.jini.qa.harness.QATestEnvironment; + + + +// Shared classes +import com.sun.jini.qa.harness.Test; +import com.sun.jini.test.share.TestBase; + + +/** + * Test to make sure blocking reads can be interrupted + */ +public class InterruptTest extends TestBase implements Test { + + + private class ReadThread extends Thread { + Exception rslt = null; + JavaSpace space; + + ReadThread(JavaSpace s) { + super("ReadThread"); + space = s; + } + + public void run() { + try { + space.read(null, null, 10000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + rslt = e; + } catch (Exception e) { + rslt = e; + } + } + } + + public Test construct(QAConfig config) throws Exception { + super.construct(config); + super.parse(); + return this; + } + + public void run() throws Exception { + specifyServices(new Class[] {JavaSpace.class}); + final JavaSpace space = (JavaSpace) services[0]; + + // Kick of read in a seperate thread + ReadThread readThread = new ReadThread(space); + readThread.start(); + + Thread.sleep(5000); + readThread.interrupt(); + readThread.join(); + + if (readThread.rslt == null) { + throw new TestException("Read returned normally"); + } else if (readThread.rslt instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } else { + throw new TestException( + "Expected: InterruptedException. Returned: " + + readThread.rslt.getMessage()); + } + } +} Modified: river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/javaspace05/MutatingContentsTest.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/javaspace05/MutatingContentsTest.java?rev=1634322&r1=1634321&r2=1634322&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/javaspace05/MutatingContentsTest.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/qa/src/com/sun/jini/test/impl/outrigger/javaspace05/MutatingContentsTest.java Sun Oct 26 13:17:28 2014 @@ -1,494 +1,495 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.sun.jini.test.impl.outrigger.javaspace05; - -import com.sun.jini.qa.harness.Test; -import java.util.logging.Level; - -// Test harness specific classes -import com.sun.jini.qa.harness.TestException; - -// All other imports - -import java.util.Collection; -import java.util.List; -import java.util.LinkedList; -import java.util.ArrayList; -import java.util.Set; -import java.util.Iterator; -import java.util.Random; - -import net.jini.core.lease.Lease; -import net.jini.core.entry.Entry; -import net.jini.lease.LeaseRenewalManager; - -import net.jini.space.JavaSpace; -import net.jini.space.JavaSpace05; -import net.jini.space.MatchSet; - -import com.sun.jini.test.share.TestBase; - - -/** - * writes a configurable number of random entries and uses a - * configurable number of concurrent threads that perform a - * configurable number of contents calls using a random sets of - * templates. Additionally one thread is writing and taking random - * entries from the space concurrently with the contents calls. Each - * trail makes sure that all of the expected entries and only the - * expected entries come back - making allowances for entries that - * were added and removed during the course of the iteration. - */ -public class MutatingContentsTest extends TestBase implements Test { - final private static String configNameBase = - "com.sun.jini.test.impl.outrigger.javaspace05.MutatingContentsTest."; - - /** Space under test */ - public void run() throws Exception { - // Initialize our selves - - specifyServices(new Class[] { JavaSpace.class }); - final JavaSpace05 space = (JavaSpace05)services[0]; - - final int threadCount = - getConfig().getIntConfigVal(configNameBase + "threadCount", 5); - final int trials = - getConfig().getIntConfigVal(configNameBase + "trials", 10); - final int batchSize = - getConfig().getIntConfigVal(configNameBase + "batchSize", 100); - final int testSetSize = - getConfig().getIntConfigVal(configNameBase + "testSetSize", 1500); - - final LeaseRenewalManager lrm = new LeaseRenewalManager(); - - logger.log(Level.INFO, "threadCount = " + threadCount); - logger.log(Level.INFO, "trials = " + trials); - logger.log(Level.INFO, "batchSize = " + batchSize); - logger.log(Level.INFO, "testSetSize = " + testSetSize); - - - // Initialize the space - - logger.log(Level.INFO, "Writing test entries"); - - final List testSet = new java.util.LinkedList(); - for (int i=0; i<testSetSize; i++) - testSet.add(TestEntries.newEntry()); - - final Long maxValue = new Long(Lease.FOREVER); - for (Iterator i=testSet.iterator(); i.hasNext();) { - final List entries = new LinkedList(); - final List leases = new ArrayList(); - for (int j=0; j<100 && i.hasNext(); j++) { - entries.add(i.next()); - leases.add(maxValue); - } - - space.write(entries, null, leases); - } - - logger.log(Level.INFO, "Test entries writen"); - - - // Spawn the reader threads - logger.log(Level.INFO, "Spawning readers"); - - final ReaderThread[] threads = new ReaderThread[threadCount]; - for (int i=0; i<threads.length; i++) { - threads[i] = new ReaderThread(i, trials, batchSize, testSet, lrm, - space); - threads[i].start(); - } - - logger.log(Level.INFO, "Readers spawned"); - - logger.log(Level.INFO, "Spawning mutator"); - final MutatorThread mutator = new MutatorThread(testSet, threads, space); - mutator.start(); - logger.log(Level.INFO, "Mutator spawned"); - - for (int i=0; i<threads.length; i++) { - threads[i].join(); - } - - mutator.kill(); - mutator.join(); - - for (int i=0; i<threads.length; i++) { - final ReaderThread t = threads[i]; - t.getCompletionState(); - } - - mutator.getCompletionState(); - } - - /** - * Return a String which describes this test - */ - public String getDescription() { - return "Test Name = MuatatingContentsTest."; - } - - /** - * Return an array of String whose elements comprise the - * categories to which this test belongs. - */ - public String[] getCategories() { - return new String[] { - "outrigger" }; - } - - private static class MutatorThread extends Thread { - final private JavaSpace05 space; - final private List testSet; - final private Random random = new Random(); - final private ReaderThread[] readers; - final private int idealSize; - private Throwable completionState = null; - - private boolean done = false; - - synchronized void setCompletionState(Throwable v) { - if (completionState != null) - completionState = v; - } - - synchronized Exception getCompletionState() throws Exception { - if (completionState == null) return null; - - if (completionState instanceof Exception) - throw (Exception)completionState; - - if (completionState instanceof Error) - throw (Error)completionState; - - throw new AssertionError(completionState); - } - - - private MutatorThread(List testSet, ReaderThread[] readers, - JavaSpace05 space) - { - super("Mutator"); - this.space = space; - this.testSet = testSet; - this.readers = readers; - idealSize = testSet.size(); - } - - private synchronized void kill() { - done = true; - } - - public void run() { - while (true) { - try { - synchronized (this) { - if (done) - return; - } - - final int size = testSet.size(); - boolean doWrite; - if (size < idealSize * 0.66) - doWrite = true; - else if (size > idealSize * 1.33) - doWrite = false; - else - doWrite = random.nextBoolean(); - - if (doWrite) { - final TestEntry e = TestEntries.newEntry(); - for (int i=0; i<readers.length; i++) - readers[i].writen(e); - space.write((Entry)e, null, Long.MAX_VALUE); - testSet.add(e); - } else { - final int c = random.nextInt(size); - final TestEntry e = (TestEntry)testSet.remove(c); - for (int i=0; i<readers.length; i++) - readers[i].removed(e); - if (null == space.take((Entry)e, null, 0)) { - final String msg = getName() + " take returned null"; - logger.log(Level.INFO, msg); - setCompletionState(new TestException(msg)); - return; - } - } - } catch (Throwable t) { - final String msg = getName() + " failure in main loop"; - logger.log(Level.INFO, msg, t); - setCompletionState(new TestException(msg, t)); - return; - } - } - } - } - - private static class ReaderThread extends Thread { - final private LeaseRenewalManager lrm; - final private int batchSize; - final private Collection testSet; - final private int trails; - final private JavaSpace05 space; - private Throwable completionState = null; - - private LinkedList removals = new LinkedList(); - private LinkedList writes = new LinkedList(); - - private boolean waitingOnCommit = false; - - // Current trail - private int trailNumber = -1; - - private ReaderThread(int threadNum, int trails, int batchSize, - Collection testSet, LeaseRenewalManager lrm, - JavaSpace05 space) - { - super("ReaderThread-" + threadNum); - this.lrm = lrm; - this.batchSize = batchSize; - this.trails = trails; - this.testSet = new java.util.HashSet(testSet); - this.space = space; - } - - synchronized void setCompletionState(Throwable v) { - if (completionState == null) - completionState = v; - } - - synchronized Exception getCompletionState() throws Exception { - if (completionState == null) return null; - - if (completionState instanceof Exception) - throw (Exception)completionState; - - if (completionState instanceof Error) - throw (Error)completionState; - - throw new AssertionError(completionState); - } - - private String nameAndTrail() { - return getName() + ":trial:" + trailNumber + " "; - } - - private TestException failure(String msg) throws TestException { - msg = nameAndTrail() + msg; - logger.log(Level.INFO, msg); - throw new TestException(msg); - } - - private TestException failure(String msg, Throwable t) - throws TestException - { - msg = nameAndTrail() + msg; - logger.log(Level.INFO, msg, t); - throw new TestException(msg, t); - } - - private synchronized void removed(TestEntry e) { - removals.add(e); - if (waitingOnCommit) { - waitingOnCommit = false; - notifyAll(); - } - } - - private synchronized void writen(TestEntry e) { - writes.add(e); - if (waitingOnCommit) { - waitingOnCommit = false; - notifyAll(); - } - } - - public void run() { - try { - for (trailNumber=0; trailNumber<trails; trailNumber++) { - trail(); - } - } catch (TestException t) { - setCompletionState(t); - } catch (Throwable t) { - logger.log(Level.INFO, nameAndTrail() + "failed with", t); - setCompletionState(t); - } - } - - private void trail() throws TestException { - synchronized (this) { - while (waitingOnCommit) { - try { - wait(); - } catch (InterruptedException e) { - failure("interrupted", e); - return; - } - } - } - - logger.log(Level.INFO, nameAndTrail() + " starting trial "); - final Collection tmpls = TestEntries.newTemplates(); - final Set tbf = new java.util.HashSet(); - for (Iterator j=testSet.iterator(); j.hasNext();) { - final TestEntry e = (TestEntry)j.next(); - if (TestEntries.isMatch(tmpls, e)) { - tbf.add(e); - } - } - - logger.log(Level.INFO, - nameAndTrail() + "looking for " + tbf.size() + " entries"); - logger.log(Level.INFO, - nameAndTrail() + "using:" + TestEntries.toString(tmpls)); - - final MatchSet cr; - final Lease l; - TestEntry e; - try { - cr = space.contents(tmpls, null, 60000, Long.MAX_VALUE); - - l = cr.getLease(); - if (tbf.size() < batchSize && l != null) { - throw failure( - "failed! got lease, but should not have. tbf.size:" + - tbf.size()); - } else if (tbf.size() >= batchSize && l == null) { - throw failure( - "failed! did not get lease, but should have. tbf.size:" - + tbf.size()); - } - - if (l != null) { - lrm.renewFor(l, Long.MAX_VALUE, 60000, null); - } - - e = (TestEntry)cr.next(); - } catch (Throwable t) { - throw failure("failed with " + t + " during contents call phase", - t); - } - - final LinkedList notInTBF = new LinkedList(); - - while (e != null) { - if (!tbf.remove(e)) { - notInTBF.add(e); - - // Make sure all the extras match - boolean found = TestEntries.isMatch(tmpls, e); - if (!found) { - throw failure("failed. " + TestEntries.toString(e) + - " did not match any templates"); - } - } - - try { - e = (TestEntry)cr.next(); - } catch (Throwable t) { - throw failure("failed with " + t + " during next call", t); - } - } - - final LinkedList removals; - final LinkedList writes; - synchronized (this) { - removals = this.removals; - writes = this.writes; - this.removals = new LinkedList(); - this.writes = new LinkedList(); - waitingOnCommit = true; - } - - final int extras = notInTBF.size(); - final int missing = tbf.size(); - - /* Go through the entries that were written while we were - * going through the match set to see if any of them match - * the `extras' entries we found (all of the extra entries - * are in notInTBF). Also update the testSet - */ - while (!writes.isEmpty()) { - final TestEntry we = (TestEntry)writes.removeFirst(); - - // Make sure there are no dups in the ones we did - // not know were coming - if (writes.contains(we)) { - throw failure("failed." + TestEntries.toString(we) + - " returned by contents twice"); - } - - testSet.add(we); - notInTBF.remove(we); - } - - // After accounting for the concurrent writes, if notInTBF - // is still non-empty, we got something we should not have - if (!notInTBF.isEmpty()) { - for (Iterator j=notInTBF.iterator(); j.hasNext();) { - TestEntry ee = (TestEntry)j.next(); - logger.log(Level.INFO, nameAndTrail() + - TestEntries.toString(ee) + " not in tbf"); - } - - throw failure("Set of entries not found in TBF non-empty after " + - "accounting for concurrent writes"); - } - - /* Go through the entries that were taken while we were - * going through the match set to see if any of them match - * the missing matches that were in testSet, but we could - * not find. Along the way update testSet - */ - while (!removals.isEmpty()) { - final TestEntry re = (TestEntry)removals.removeFirst(); - if (!testSet.remove(re)) { - throw failure("Removed entry not in testSet", - new AssertionError()); - } - - tbf.remove(re); - } - - - // After account for concurrent takes, if tbf is still - // non-empty we did not get something we should have - if (!tbf.isEmpty()) { - final String msg = nameAndTrail() + "failed. tbf non-empty"; - logger.log(Level.INFO, msg); - logger.log(Level.INFO, TestEntries.toString(tbf)); - throw new TestException(msg); - } else { - logger.log(Level.INFO, nameAndTrail() + "success(" + - extras + " extras, " + missing + " missing)"); - } - - if (l != null) { - try { - lrm.cancel(l); - } catch (Throwable t) { - throw failure("failed with " + t + - " while canceling MatchSet lease", t); - } - } - } - } -} - +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.sun.jini.test.impl.outrigger.javaspace05; + +import com.sun.jini.qa.harness.Test; +import java.util.logging.Level; + +// Test harness specific classes +import com.sun.jini.qa.harness.TestException; + +// All other imports + +import java.util.Collection; +import java.util.List; +import java.util.LinkedList; +import java.util.ArrayList; +import java.util.Set; +import java.util.Iterator; +import java.util.Random; + +import net.jini.core.lease.Lease; +import net.jini.core.entry.Entry; +import net.jini.lease.LeaseRenewalManager; + +import net.jini.space.JavaSpace; +import net.jini.space.JavaSpace05; +import net.jini.space.MatchSet; + +import com.sun.jini.test.share.TestBase; + + +/** + * writes a configurable number of random entries and uses a + * configurable number of concurrent threads that perform a + * configurable number of contents calls using a random sets of + * templates. Additionally one thread is writing and taking random + * entries from the space concurrently with the contents calls. Each + * trail makes sure that all of the expected entries and only the + * expected entries come back - making allowances for entries that + * were added and removed during the course of the iteration. + */ +public class MutatingContentsTest extends TestBase implements Test { + final private static String configNameBase = + "com.sun.jini.test.impl.outrigger.javaspace05.MutatingContentsTest."; + + /** Space under test */ + public void run() throws Exception { + // Initialize our selves + + specifyServices(new Class[] { JavaSpace.class }); + final JavaSpace05 space = (JavaSpace05)services[0]; + + final int threadCount = + getConfig().getIntConfigVal(configNameBase + "threadCount", 5); + final int trials = + getConfig().getIntConfigVal(configNameBase + "trials", 10); + final int batchSize = + getConfig().getIntConfigVal(configNameBase + "batchSize", 100); + final int testSetSize = + getConfig().getIntConfigVal(configNameBase + "testSetSize", 1500); + + final LeaseRenewalManager lrm = new LeaseRenewalManager(); + + logger.log(Level.INFO, "threadCount = " + threadCount); + logger.log(Level.INFO, "trials = " + trials); + logger.log(Level.INFO, "batchSize = " + batchSize); + logger.log(Level.INFO, "testSetSize = " + testSetSize); + + + // Initialize the space + + logger.log(Level.INFO, "Writing test entries"); + + final List testSet = new java.util.LinkedList(); + for (int i=0; i<testSetSize; i++) + testSet.add(TestEntries.newEntry()); + + final Long maxValue = new Long(Lease.FOREVER); + for (Iterator i=testSet.iterator(); i.hasNext();) { + final List entries = new LinkedList(); + final List leases = new ArrayList(); + for (int j=0; j<100 && i.hasNext(); j++) { + entries.add(i.next()); + leases.add(maxValue); + } + + space.write(entries, null, leases); + } + + logger.log(Level.INFO, "Test entries writen"); + + + // Spawn the reader threads + logger.log(Level.INFO, "Spawning readers"); + + final ReaderThread[] threads = new ReaderThread[threadCount]; + for (int i=0; i<threads.length; i++) { + threads[i] = new ReaderThread(i, trials, batchSize, testSet, lrm, + space); + threads[i].start(); + } + + logger.log(Level.INFO, "Readers spawned"); + + logger.log(Level.INFO, "Spawning mutator"); + final MutatorThread mutator = new MutatorThread(testSet, threads, space); + mutator.start(); + logger.log(Level.INFO, "Mutator spawned"); + + for (int i=0; i<threads.length; i++) { + threads[i].join(); + } + + mutator.kill(); + mutator.join(); + + for (int i=0; i<threads.length; i++) { + final ReaderThread t = threads[i]; + t.getCompletionState(); + } + + mutator.getCompletionState(); + } + + /** + * Return a String which describes this test + */ + public String getDescription() { + return "Test Name = MuatatingContentsTest."; + } + + /** + * Return an array of String whose elements comprise the + * categories to which this test belongs. + */ + public String[] getCategories() { + return new String[] { + "outrigger" }; + } + + private static class MutatorThread extends Thread { + final private JavaSpace05 space; + final private List testSet; + final private Random random = new Random(); + final private ReaderThread[] readers; + final private int idealSize; + private Throwable completionState = null; + + private boolean done = false; + + synchronized void setCompletionState(Throwable v) { + if (completionState != null) + completionState = v; + } + + synchronized Exception getCompletionState() throws Exception { + if (completionState == null) return null; + + if (completionState instanceof Exception) + throw (Exception)completionState; + + if (completionState instanceof Error) + throw (Error)completionState; + + throw new AssertionError(completionState); + } + + + private MutatorThread(List testSet, ReaderThread[] readers, + JavaSpace05 space) + { + super("Mutator"); + this.space = space; + this.testSet = testSet; + this.readers = readers; + idealSize = testSet.size(); + } + + private synchronized void kill() { + done = true; + } + + public void run() { + while (true) { + try { + synchronized (this) { + if (done) + return; + } + + final int size = testSet.size(); + boolean doWrite; + if (size < idealSize * 0.66) + doWrite = true; + else if (size > idealSize * 1.33) + doWrite = false; + else + doWrite = random.nextBoolean(); + + if (doWrite) { + final TestEntry e = TestEntries.newEntry(); + for (int i=0; i<readers.length; i++) + readers[i].writen(e); + space.write((Entry)e, null, Long.MAX_VALUE); + testSet.add(e); + } else { + final int c = random.nextInt(size); + final TestEntry e = (TestEntry)testSet.remove(c); + for (int i=0; i<readers.length; i++) + readers[i].removed(e); + if (null == space.take((Entry)e, null, 0)) { + final String msg = getName() + " take returned null"; + logger.log(Level.INFO, msg); + setCompletionState(new TestException(msg)); + return; + } + } + } catch (Throwable t) { + final String msg = getName() + " failure in main loop"; + logger.log(Level.INFO, msg, t); + setCompletionState(new TestException(msg, t)); + return; + } + } + } + } + + private static class ReaderThread extends Thread { + final private LeaseRenewalManager lrm; + final private int batchSize; + final private Collection testSet; + final private int trails; + final private JavaSpace05 space; + private Throwable completionState = null; + + private LinkedList removals = new LinkedList(); + private LinkedList writes = new LinkedList(); + + private boolean waitingOnCommit = false; + + // Current trail + private int trailNumber = -1; + + private ReaderThread(int threadNum, int trails, int batchSize, + Collection testSet, LeaseRenewalManager lrm, + JavaSpace05 space) + { + super("ReaderThread-" + threadNum); + this.lrm = lrm; + this.batchSize = batchSize; + this.trails = trails; + this.testSet = new java.util.HashSet(testSet); + this.space = space; + } + + synchronized void setCompletionState(Throwable v) { + if (completionState == null) + completionState = v; + } + + synchronized Exception getCompletionState() throws Exception { + if (completionState == null) return null; + + if (completionState instanceof Exception) + throw (Exception)completionState; + + if (completionState instanceof Error) + throw (Error)completionState; + + throw new AssertionError(completionState); + } + + private String nameAndTrail() { + return getName() + ":trial:" + trailNumber + " "; + } + + private TestException failure(String msg) throws TestException { + msg = nameAndTrail() + msg; + logger.log(Level.INFO, msg); + throw new TestException(msg); + } + + private TestException failure(String msg, Throwable t) + throws TestException + { + msg = nameAndTrail() + msg; + logger.log(Level.INFO, msg, t); + throw new TestException(msg, t); + } + + private synchronized void removed(TestEntry e) { + removals.add(e); + if (waitingOnCommit) { + waitingOnCommit = false; + notifyAll(); + } + } + + private synchronized void writen(TestEntry e) { + writes.add(e); + if (waitingOnCommit) { + waitingOnCommit = false; + notifyAll(); + } + } + + public void run() { + try { + for (trailNumber=0; trailNumber<trails; trailNumber++) { + trail(); + } + } catch (TestException t) { + setCompletionState(t); + } catch (Throwable t) { + logger.log(Level.INFO, nameAndTrail() + "failed with", t); + setCompletionState(t); + } + } + + private void trail() throws TestException { + synchronized (this) { + while (waitingOnCommit) { + try { + wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + failure("interrupted", e); + return; + } + } + } + + logger.log(Level.INFO, nameAndTrail() + " starting trial "); + final Collection tmpls = TestEntries.newTemplates(); + final Set tbf = new java.util.HashSet(); + for (Iterator j=testSet.iterator(); j.hasNext();) { + final TestEntry e = (TestEntry)j.next(); + if (TestEntries.isMatch(tmpls, e)) { + tbf.add(e); + } + } + + logger.log(Level.INFO, + nameAndTrail() + "looking for " + tbf.size() + " entries"); + logger.log(Level.INFO, + nameAndTrail() + "using:" + TestEntries.toString(tmpls)); + + final MatchSet cr; + final Lease l; + TestEntry e; + try { + cr = space.contents(tmpls, null, 60000, Long.MAX_VALUE); + + l = cr.getLease(); + if (tbf.size() < batchSize && l != null) { + throw failure( + "failed! got lease, but should not have. tbf.size:" + + tbf.size()); + } else if (tbf.size() >= batchSize && l == null) { + throw failure( + "failed! did not get lease, but should have. tbf.size:" + + tbf.size()); + } + + if (l != null) { + lrm.renewFor(l, Long.MAX_VALUE, 60000, null); + } + + e = (TestEntry)cr.next(); + } catch (Throwable t) { + throw failure("failed with " + t + " during contents call phase", + t); + } + + final LinkedList notInTBF = new LinkedList(); + + while (e != null) { + if (!tbf.remove(e)) { + notInTBF.add(e); + + // Make sure all the extras match + boolean found = TestEntries.isMatch(tmpls, e); + if (!found) { + throw failure("failed. " + TestEntries.toString(e) + + " did not match any templates"); + } + } + + try { + e = (TestEntry)cr.next(); + } catch (Throwable t) { + throw failure("failed with " + t + " during next call", t); + } + } + + final LinkedList removals; + final LinkedList writes; + synchronized (this) { + removals = this.removals; + writes = this.writes; + this.removals = new LinkedList(); + this.writes = new LinkedList(); + waitingOnCommit = true; + } + + final int extras = notInTBF.size(); + final int missing = tbf.size(); + + /* Go through the entries that were written while we were + * going through the match set to see if any of them match + * the `extras' entries we found (all of the extra entries + * are in notInTBF). Also update the testSet + */ + while (!writes.isEmpty()) { + final TestEntry we = (TestEntry)writes.removeFirst(); + + // Make sure there are no dups in the ones we did + // not know were coming + if (writes.contains(we)) { + throw failure("failed." + TestEntries.toString(we) + + " returned by contents twice"); + } + + testSet.add(we); + notInTBF.remove(we); + } + + // After accounting for the concurrent writes, if notInTBF + // is still non-empty, we got something we should not have + if (!notInTBF.isEmpty()) { + for (Iterator j=notInTBF.iterator(); j.hasNext();) { + TestEntry ee = (TestEntry)j.next(); + logger.log(Level.INFO, nameAndTrail() + + TestEntries.toString(ee) + " not in tbf"); + } + + throw failure("Set of entries not found in TBF non-empty after " + + "accounting for concurrent writes"); + } + + /* Go through the entries that were taken while we were + * going through the match set to see if any of them match + * the missing matches that were in testSet, but we could + * not find. Along the way update testSet + */ + while (!removals.isEmpty()) { + final TestEntry re = (TestEntry)removals.removeFirst(); + if (!testSet.remove(re)) { + throw failure("Removed entry not in testSet", + new AssertionError()); + } + + tbf.remove(re); + } + + + // After account for concurrent takes, if tbf is still + // non-empty we did not get something we should have + if (!tbf.isEmpty()) { + final String msg = nameAndTrail() + "failed. tbf non-empty"; + logger.log(Level.INFO, msg); + logger.log(Level.INFO, TestEntries.toString(tbf)); + throw new TestException(msg); + } else { + logger.log(Level.INFO, nameAndTrail() + "success(" + + extras + " extras, " + missing + " missing)"); + } + + if (l != null) { + try { + lrm.cancel(l); + } catch (Throwable t) { + throw failure("failed with " + t + + " while canceling MatchSet lease", t); + } + } + } + } +} +
