Package com.sun.jini.test.impl.norm

Source Code of com.sun.jini.test.impl.norm.LeaseExpirationTest$OurListener

/*
* 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 java.io.PrintWriter;
import com.sun.jini.qa.harness.TestException;
import com.sun.jini.qa.harness.QAConfig;

import java.rmi.MarshalledObject;
import java.rmi.RemoteException;

import net.jini.core.lease.Lease;

import net.jini.core.event.RemoteEvent;
import net.jini.core.event.EventRegistration;

import net.jini.lease.LeaseRenewalService;
import net.jini.lease.LeaseRenewalSet;
import net.jini.lease.ExpirationWarningEvent;

import com.sun.jini.test.share.TestBase;

/**
* Test creates a number of leases places them in a renewal set and lets
* the set's lease expire.  Fails if the leases it places in the set
* are renewed after the set expires.
*/
public class LeaseExpirationTest extends TestBase {

    /** Ammount of slop we are willing to tolerate around renewals */
    private long slop;

    /** Max renwal length to grant */
    private long renewGrant;

    /** Length of lease to ask for on set */
    private long setLeaseLength;

    /** Number of times to renew lease on set */
    private int setRenewals;

    /** Number of leases to place in set */
    private int leaseCount;

    /** If <code>true</code> we should register for expiration warning events */
    private boolean shouldRegister;

    /** Min warning time we will request if shouldRegister is true */
    private long minWarning;

    /** Should we try shuting down the service under test? */
    private boolean tryShutdown;

    /**
     * Listener for expiration warning events, also tracks when
     * the set lease should expire
     */
    private OurListener listener;

    /** The current expiration time of the set's lease */
    private long setLeaseCurrentExpiration;

    public void setup(QAConfig sysConfig) throws Exception {
  super.setup(sysConfig);
  this.parse();
    }

    /**
     * com.sun.jini.test.impl.norm.slop (long):
     *   Amount of slop in milliseconds we are willing to tolrate. 
     *   Renewals that take place up to slop milliseconds after the
     *   lease is sceduled to expire will not fail the test.
     * <p>
     * com.sun.jini.test.impl.norm.lease_length (long):
     *   Length of lease to ask for when creating the set.
     * <p>
     * com.sun.jini.test.impl.norm.set_renewals (int):
     *   Number of times to renew the lease on the set.
     * <p>
     * com.sun.jini.test.impl.norm.lease_count (int):
     *   Number of leases to create and place in set.
     * <p>
     * com.sun.jini.test.impl.norm.renew_grant (long):
     *   Length of max renewal grants in milliseconds.
     * <p>
     * com.sun.jini.test.impl.norm.warning (boolean):
     *   If used the test will register for expiration warning events.
     * <p>
     * com.sun.jini.test.impl.norm.min_warning (long):
     *   If warning is set the number of milliseconds before expiration
     *   we want a warning event.
     * <p>
     * com.sun.jini.test.impl.norm.tryShutdown (boolean):
     *   If used the test will kill the VM the service
     *   is running in after adding the client leases to the set and again
     *   after all the leases should have expired.
     */
    protected void parse() throws Exception {
  super.parse();
  slop = getConfig().getLongConfigVal(
            "com.sun.jini.test.impl.norm.slop", 5000);
  setLeaseLength = getConfig().getLongConfigVal(
            "com.sun.jini.test.impl.norm.lease_length", 60 * 1000);
  setRenewals = getConfig().getIntConfigVal(
            "com.sun.jini.test.impl.norm.set_renewals", 0);
  leaseCount = getConfig().getIntConfigVal(
            "com.sun.jini.test.impl.norm.lease_count", 10);
  renewGrant = getConfig().getLongConfigVal(
            "com.sun.jini.test.impl.norm.renew_grant", 10 * 1000);
  shouldRegister = getConfig().getBooleanConfigVal(
            "com.sun.jini.test.impl.norm.warning", false);
  minWarning = getConfig().getLongConfigVal(
            "com.sun.jini.test.impl.norm.min_warning", 10000);
  tryShutdown = getConfig().getBooleanConfigVal(
            "com.sun.jini.test.impl.norm.tryShutdown", false);
    }

    public void run() throws Exception {
  specifyServices(new Class[]{LeaseRenewalService.class});
  final LeaseRenewalService lrs = (LeaseRenewalService)services[0];
  LeaseRenewalSet set = lrs.createLeaseRenewalSet(setLeaseLength);
  set = prepareSet(set);
  final Lease setLease = prepareNormLease(set.getRenewalSetLease());
  setLeaseCurrentExpiration = setLease.getExpiration();
  addLease(setLease, true);

  listener = new OurListener(setLease, setRenewals);

  // If we need to register for warning events
  if (shouldRegister) {     
      logger.log(Level.INFO, "Registering for warning events");

      final MarshalledObject handback =
    new MarshalledObject(new Long(348));
      EventRegistration reg = set.setExpirationWarningListener(
                listener, minWarning, handback);
            reg = prepareNormEventRegistration(reg);

      if (!set.equals(reg.getSource())) {
    throw new TestException(
                    "Source object in event registration is not set");
            }
      if (reg.getID() != LeaseRenewalSet.EXPIRATION_WARNING_EVENT_ID){
    throw new TestException(
                    "Event ID in registration is not correct");
            }
      if (!reg.getLease().equals(
                prepareNormLease(set.getRenewalSetLease())))
            {
    throw new TestException(
                    "Lease in registration is not correct");
            }
      listener.setRegInfo(reg, handback);
  }

  // Create owners and leases
  final LeaseBackEndImpl home = new LeaseBackEndImpl(leaseCount);
  for (int i = 0; i < leaseCount; i++) {
      final long now = System.currentTimeMillis();
      final long initExp = now + renewGrant;
      final OurOwner owner = new OurOwner(initExp);
      final Lease l = home.newLease(owner, initExp);
      set.renewFor(l, Lease.FOREVER, Lease.ANY);
  }

        if (tryShutdown) {
            logger.log(Level.INFO, "Shuting down at: "
                + System.currentTimeMillis() + " milliseconds");
            shutdown(0);
        }

  if (!listener.waitExpire((1+setRenewals) * (setLeaseLength+slop))) {
      throw new TestException(
                "The expected number of expiration warning events did "
    + "not occur in the alloted time");
        }

  // Wait for the leases that we put in the set to expire
  long sleepTime = renewGrant * 2;
  logger.log(Level.INFO, "Sleeping for " + sleepTime + "ms to let our leases"
                + "expire and give renewals time to propagate");
  Thread.sleep(sleepTime);

        if (tryShutdown) {
            logger.log(Level.INFO, "Shuting down at: "
                + System.currentTimeMillis() + " milliseconds");
            shutdown(0);
      logger.log(Level.INFO, "Sleeping for " + sleepTime + "ms to let our leases"
                + "expire and give renewals time to propagate (again)");
      Thread.sleep(sleepTime);
  }

  // Ask each of the owner if there were any problems
  LeaseOwner owners[] = home.getOwners();
  for (int i = 0; i < owners.length; i++) {
      final OurOwner owner = (OurOwner)owners[i];
      final String result = owner.didPass();
      if (result != null) {
    throw new TestException(result);
      }         
  }

  // Ask the listener if there were any problems
  final String result = listener.didPass();
  if (result != null) {
      throw new TestException(result);
  }
    }


    private class OurOwner extends BaseOwner {
  private OurOwner(long initialExpiration) {
      super(initialExpiration,
      LeaseExpirationTest.this.renewGrant,
      Lease.FOREVER, LeaseExpirationTest.this.slop,
      Lease.ANY, LeaseExpirationTest.this);
  }

  /**
   * Check not only for the right extension, but also
   * if the set's lease should have expired by now
   */
  boolean isValidExtension(long extension) {
      if (listener.isPast(now)) {
    setRsltIfNeeded("Service renewed lease after set expired, " +
         listener.howPast(now) + " ms late");
      }
      if (extension != Lease.ANY) {
    setRsltIfNeeded("Service asked for an extension of " +
        extension + ", not Lease.ANY");
    return false;
      }
      return true;
  }

  boolean isTwoArg() {return false;}

  /**
   * Return null if we dected no error, and a disciptive string otherwise
   */
  String didPass() {
      if (rslt != null) {
    return rslt;
            }

      // It is ok if the lease has expired, however, it should
      // not expire before the set's lease did.
      synchronized (this) {
    if (expiration < setLeaseCurrentExpiration)
        rslt = "Lease expired before the set did";
      }
      return rslt;     
  }
    }


    private class OurListener extends RemoteListener {
  /** Event registration we are expecting events from  */
  private EventRegistration registation;

  /** Handback object we expect to see */
  private MarshalledObject handback;

  /** Set to a discriptive non-null value if there is an error */
  private String result = null;

  /** Lease on renewal set */
  private Lease setLease;

  /** Set after last renewal to the expiration time */
  private long setExpiration = -1;

  /** semaphore that tracks how many renewals we have left */
  private Semaphore renewalsLeft;
 
  /**
   * Simple constructor
   * @param setLease The lease on the set
   * @param renewals number of times to renew the set's lease
   */
  private OurListener(Lease setLease, int renewals)
      throws RemoteException
  {
      this.setLease = setLease;
      renewalsLeft = new Semaphore(renewals);
      if (renewalsLeft.get() == 0) {
    setExpiration = setLease.getExpiration();
      }
  }

  /**
   * Set the registion and handback so we can do basic error checking
   */
  private void setRegInfo(EventRegistration er, MarshalledObject hb) {
      registation = er;
      handback = hb;
  }

  /**
   * Are we past the time when we should not be reciving events and
   * lease renewals.
   * @param now The current time
   */
  private synchronized boolean isPast(long now) {
      if (setExpiration > 0) {
    return now > setExpiration + slop;
            }
      return false;
  }

  /**
   * Return the diffrence between when the last action should have
   * be taken by the test and now
   */
  private synchronized long howPast(long now) {
      return setExpiration - now;
  }

  /**
   * Set result string if it is not already set
   */
  private void setRsltIfNeeded(String newResult) {
      if (result == null) {
    result = newResult;
      }
  }

  /**
   * Block until the set's lease should have expired
   * @param timeout maximum time to wait for all of the
   *                renewal calls to occur.
   * @return false if the timeout expires and true otherwise
   * @throws InterruptedException if this thread is interupted
   */
  private boolean waitExpire(long timeout) throws InterruptedException {
      final int count = renewalsLeft.waitOnZero(timeout);

      if (count != 0)
    return false;

      final long now = System.currentTimeMillis();
      synchronized (this) {
    if (setExpiration > now) {
        logger.log(Level.INFO, "Waiting for " + (setExpiration - now)
                        + " ms for set lease to expire");
        wait(setExpiration - now);
                }
      }
      return true;
  }
 
  /**
   * @return null if we detected no error; a descriptive string otherwise
   */
  private String didPass() {
      if (renewalsLeft.get() != 0) {
    setRsltIfNeeded("Did not receive enough warning events");
      }
      return result;
  }

  public void notify(RemoteEvent theEvent) {
      logger.log(Level.INFO, "Recived event");

      if (registation == null) {
    logger.log(Level.INFO, "OurListener not initialized");
    setRsltIfNeeded("TEST CODE ERROR: Event received before " +
        "OurListener was fully initialized");
    return;
      }
                    
      // check source
      if (!theEvent.getSource().equals(registation.getSource())) {
    logger.log(Level.INFO, "Soruce miss-match");
    setRsltIfNeeded("Service sent event with wrong source");
    return;
      }

      // Check event ID
      if (theEvent.getID() != registation.getID()) {
    logger.log(Level.INFO, "Event ID miss-match");
    setRsltIfNeeded("Service sent event with wrong event ID");
    return;
      }

      final long now = System.currentTimeMillis();     
      final long predicted = setLeaseCurrentExpiration - minWarning;
      final long diff = Math.abs(now - predicted);
      if (diff > slop) {
    logger.log(Level.INFO, "Event recived outside window");
    setRsltIfNeeded("Warning event was received at " + now +
        "; should have been received at " + predicted +
        " (a diff of " + diff + "ms");
    return;
      }

      if (isPast(now)) {
    logger.log(Level.INFO, "Event recived after lease expiration");
    setRsltIfNeeded("Warning event received after lease should " +
        "have expired (" + howPast(now) + " ms late)");

    return;
      }

      // Check Lease and type of event
      try {
    final ExpirationWarningEvent ewe =
        (ExpirationWarningEvent)theEvent;
    final Lease eventLease =
                    prepareNormLease(ewe.getRenewalSetLease());

    if (!setLease.equals(eventLease)) {
        logger.log(Level.INFO, "Lease miss-match");
        setRsltIfNeeded("Lease in warning event did not " +
            "match set lease");
        return;
    }

    final long expDiff =
        Math.abs(setLeaseCurrentExpiration -
           eventLease.getExpiration());

    if (expDiff > slop) {
        logger.log(Level.INFO, "Lease in event has wrong expiration time" +
       " has " + eventLease.getExpiration() + " should " +
       " have " + setLeaseCurrentExpiration + "a delta of " +
       expDiff);
        setRsltIfNeeded("Lease in event had wrong expiration " +
            "time (" + expDiff + "ms off)");
        return;
    }

    // deal with renewing the lease
    if (renewalsLeft.get() > 0) {
        logger.log(Level.INFO, "Renewing set lease");
        eventLease.renew(setLeaseLength);
        setLeaseCurrentExpiration = eventLease.getExpiration();

        if (renewalsLeft.get() == 1) {
      synchronized (this) {
          setExpiration = eventLease.getExpiration();
      }
        }

        renewalsLeft.dec();
    }
      } catch (ClassCastException e) {
    setRsltIfNeeded("Event was not of type ExpirationWarningEvent");
    return;
      } catch (Exception e) {
    e.printStackTrace();
    setRsltIfNeeded("Recived exception durring renewal " +
        e.getMessage());
    return;
      }
  }
    }

}
TOP

Related Classes of com.sun.jini.test.impl.norm.LeaseExpirationTest$OurListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.