Package com.sun.jini.test.spec.lookupservice

Source Code of com.sun.jini.test.spec.lookupservice.QATestUtils

/*
* 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.spec.lookupservice;

import com.sun.jini.test.spec.lookupservice.attribute.Attr;
import com.sun.jini.test.spec.lookupservice.ServiceLeaseOverrideProvider;
import net.jini.core.lookup.ServiceEvent;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceRegistration;
import net.jini.core.lookup.ServiceID;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceMatches;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.core.entry.Entry;
import net.jini.lookup.entry.ServiceType;
import net.jini.core.lease.*;
import java.rmi.RemoteException;
import java.io.Serializable;
import java.io.IOException;
import java.util.Vector;
import java.util.HashMap;
import java.util.ArrayList;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

import com.sun.jini.qa.harness.QAConfig;
import com.sun.jini.qa.harness.TestException;
import com.sun.jini.qa.harness.QATest;

import java.util.logging.Logger;
import java.util.logging.Level;

/** Provides useful constants and utility methods and classes for all
*  classes of the Lookup component of the Jini System. Each field and
*  member class, and most methods, contained in this class is public
*  and static; this class does not need to be instantiated.
*
@see QATest
@see com.sun.jini.test.spec.lookupservice.QATestRegistrar
*/
public class QATestUtils {

    private static Logger logger =
  Logger.getLogger("com.sun.jini.qa.harness.test");

    /* Class constructor */
    public QATestUtils(){}

    /** The number of milliseconds in 1 second */
    public final static long N_MS_PER_SEC   = 1000;
    /** The number of seconds in 1 minute */
    public final static long N_SECS_PER_MIN = 60;
    /** The number of milliseconds in 1 minute */
    public final static long N_MS_PER_MIN   = N_MS_PER_SEC*N_SECS_PER_MIN;
    /** Strings describing event transition states used in debugging */
    public final static String[] trans_str = {"UNKNOWN",
                                              "MATCH_NOMATCH",
                                              "NOMATCH_MATCH",
                                              "UNKNOWN",
                                              "MATCH_MATCH"};

    /** Class which models an event "tuple" (service,attribute,transition).
     * 
     *  This class is used by some of the tests that wish to verify that the
     *  events received from the lookup service are the events expected;
     *  based on the templates used to register event notification requests.
     */
    public static class SrvcAttrTuple implements Serializable
    {
        static final long serialVersionUID = -8254953323094761933L;

        /** @serial */
        private Object srvcObj;
        /** @serial */
        private Object attrObj;
        /** @serial */
        private int transition;
        /** @serial */
        private ServiceItem[] srvcItems ;
        /** @serial */
        private Entry[][] attrs;

        /** Creates a SrvcAttrTuple with the given transition value.
         *  @param srvcItems the array of registered service items
         *  @param attrs array of Entry type elements containing attributes
         *  @param srvcObj the service component of the new tuple
         *  @param attrObj the attribute component of the new tuple
         *  @param transition the transition component of the new tuple
         */
        public SrvcAttrTuple(ServiceItem[] srvcItems,
                             Entry[][]     attrs,
                             Object        srvcObj,
                             Object        attrObj,
                             int           transition)
        {
            this.srvcItems  = srvcItems;
            this.attrs      = attrs;

            this.srvcObj    = srvcObj;
            this.attrObj    = attrObj;
            this.transition = transition;
        }

        /** Creates a SrvcAttrTuple with the "unknown" (0) transition value.
         *  @param srvcItems the array of registered service items
         *  @param attrs array of Entry type elements containing attributes
         *  @param srvcObj the service component of the new tuple
         *  @param attrObj the attribute component of the new tuple
         */
        public SrvcAttrTuple(ServiceItem[] srvcItems,
                             Entry[][]     attrs,
                             Object        srvcObj,
                             Object        attrObj)
        {
            this.srvcItems  = srvcItems;
            this.attrs      = attrs;

            this.srvcObj    = srvcObj;
            this.attrObj    = attrObj;
            this.transition = 0;
        }

        /** Creates a SrvcAttrTuple with the given transition value
         *  and null reference arrays of service items and attributes.
         *  @param srvcObj the service component of the new tuple
         *  @param attrObj the attribute component of the new tuple
         *  @param transition the transition component of the new tuple
         */
        public SrvcAttrTuple(Object srvcObj,
                             Object attrObj,
                             int    transition)
        {
            this.srvcItems  = null;
            this.attrs      = null;

            this.srvcObj    = srvcObj;
            this.attrObj    = attrObj;
            this.transition = transition;
        }

        /** Creates a SrvcAttrTuple with the "unknown" (0) transition value
         *  and null reference arrays of service items and attributes.
         *  @param srvcObj the service component of the new tuple
         *  @param attrObj the attribute component of the new tuple
         */
        public SrvcAttrTuple(Object srvcObj,
                             Object attrObj)
        {
            this.srvcItems  = null;
            this.attrs      = null;

            this.srvcObj    = srvcObj;
            this.attrObj    = attrObj;
            this.transition = 0;
        }

        /** Sets this tuple equal to the given tuple
         *  @param tuple the SrvcAttrTuple to set this tuple equal to
         */
        public void setEqualTo(SrvcAttrTuple tuple) {
            this.srvcItems  = tuple.srvcItems;
            this.attrs      = tuple.attrs;
            this.srvcObj    = tuple.srvcObj;
            this.attrObj    = tuple.attrObj;
            this.transition = tuple.transition;
        }

        /** Returns the array of service items associated with this tuple */
        public ServiceItem[] getSrvcItems() {
            return srvcItems;
        }

        /** Sets the reference to the array of service items associated with
         *  this tuple equal to the given reference
         *  @param srvcItems the new array of service items
         */
        public void setSrvcItems(ServiceItem[] srvcItems) {
            this.srvcItems = srvcItems;
        }

        /** Returns the array of attributes associated with this tuple */
        public Entry[][] getAttrs() {
            return attrs;
        }

        /** Sets the reference to the array of attributes associated with
         *  this tuple equal to the given reference
         *  @param attrs the new array-of-arrays of attributes
         */
        public void setAttrs(Entry[][] attrs) {
            this.attrs = attrs;
        }

        /** Returns the service item associated with this tuple */
        public Object getSrvcObj() {
            return srvcObj;
        }

        /** Sets the reference to the service item associated with
         *  this tuple equal to the given reference
         *  @param srvcObj the new service item
         */
        public void setSrvcObj(Object srvcObj) {
            this.srvcObj = srvcObj;
        }

        /** Returns the attribute associated with this tuple */
        public Object getAttrObj() {
            return attrObj;
        }

        /** Sets the reference to the attribute associated with
         *  this tuple equal to the given reference
         *  @param attrObj the new attribute
         */
        public void setAttrObj(Object attrObj) {
            this.attrObj = attrObj;
        }

        /** Returns the transition associated with this tuple */
        public int getTransition() {
            return transition;
        }

        /** Sets the transition associated with this tuple equal to the
         *  given transition
         *  @param transition the new transition value
         */
        public void setTransition(int transition) {
            this.transition = transition;
        }

        /** Determines if the given object is equal to this tuple; where
         *  two tuples are equal if their service items are equal, their
         *  attributes are equal and their transitions are equal.
         *  @param obj the tuple to compare to this tuple
         *  @return boolean
         */
        public boolean equals(Object obj) {
            int trans = ((SrvcAttrTuple)obj).getTransition();
            return ( (objEquals(obj)) && (this.transition == trans) );
        }

        /** Determines if the service item and and the attribute of the
         *  given object are equal to the corresponding fields of this
         *  tuple; that is, this method ignores the transition values
         *  of the tuples.
         *  @param obj the tuple to compare to this tuple
         *  @return boolean
         */
        public boolean objEquals(Object obj) {
            if (this == obj) {
                return true;
            } else if ( (obj.getClass()).equals(SrvcAttrTuple.class) ) {
                if ((srvcItems == null)||(attrs == null)) {
                    return false;
    }
                int n=0;
                int k=0;
                Object srvc = ((SrvcAttrTuple)obj).getSrvcObj();
                Object attr = ((SrvcAttrTuple)obj).getAttrObj();
                try {
                    n = getSrvcIndx(this.srvcObj,srvcItems);
                    k = getAttrIndx(this.attrObj,attrs);
                    if (    ((srvcItems[n].service).equals(srvc))
                         && ((attrs[k][0]).equals(attr)) ) {
                        return true;
        } else {
                        return false;
        }
                } catch (ArrayIndexOutOfBoundsException e) {
                    return false;
    }
            } else {
                return false;
            }
        }
    }

    /** Steps through the given array of service items searching for the
     *  element that equals the given service item Object; returning the
     *  element index if a match is found and -1 otherwise
     *  @param obj service item object to search for
     *  @param srvcItems array of service items to search
     *  @return int (array index or -1 if no match found)
     */
    public static int getSrvcIndx(Object        obj,
                                  ServiceItem[] srvcItems) {
        try {
            int n;
      /* get the srvc instance the input Object corresponds to */
            for(n=0;n<srvcItems.length;n++) {
                if ( (srvcItems[n].service).equals(obj) ) {
                    break;
                }
            }
            if (n < srvcItems.length) {
                return n;
      } else {
                return -1;
      }
        } catch (ArrayIndexOutOfBoundsException e) {
           return -1;
        } catch (NullPointerException e) {
            return -1;
       }
    }

    /** Steps through the given array of attribute objects searching for
     *  the element that equals the given attribute Object; returning the
     *  element index if a match is found and -1 otherwise
     *  @param obj attribute object to search for
     *  @return int (array index or -1 if no match found)
     */
    public static int getAttrIndx(Object     obj,
                                  Entry[][]  attrs) {
        try {
            int n;
      /* get the attribute instance the input Object corresponds to */
            for(n=0;n<attrs.length;n++) {
                if ( (attrs[n][0]).equals(obj) ) {
                    break;
    }
         }
            if (n < attrs.length) {
                return n;
      } else {
                return -1;
      }
        } catch (ArrayIndexOutOfBoundsException e) {
           return -1;
        } catch (NullPointerException e) {
            return -1;
       }
    }

    /** Returns the current time in milliseconds
     *  @return long
     */
    public static long getCurTime() {
  return System.currentTimeMillis();
    }

    /** Creates an instance of the given (loaded) class object. This method
     *  assumes that the loaded class has a constructor with a single argument
     *  of type int That single int field of the new object will be
     *  initialized to the given value.
     *  @param classObj class type to instantiate
     *  @param instanceIndx value to which to initialize the class field
     *  @exception TestException usually indicates a failure
     *  @return java.lang.Object
     */
    public static Object createInstance(Class classObj,
                                        int   instanceIndx)
                                                         throws Exception
    {
        Class[] parameterTypes = { int.class };
      Constructor con = classObj.getConstructor(parameterTypes);
            return con.newInstance(new Object[]{new Integer(instanceIndx)});
    }

    /** Creates an instance of the given (loaded) class object. This method
     *  assumes that the loaded class has a constructor with a set of
     *  arguments corresponding to the contents of given array of Objects.
     *  The fields of the new object will be initialized to the values
     *  contained in the given array.
     *  @param classObj class type to instantiate
     *  @param constructorArgs array of Objects for field initialization
     *  @return java.lang.Object
     */
    public static Object createInstance(Class    classObj,
                                        Object[] constructorArgs)
                                                         throws Exception
    {
        Object o = null;
        if (constructorArgs == null) {
      o = classObj.newInstance();
        } else {
            Class[] constructorArgTypes = new Class[constructorArgs.length];
      for (int i=0;i<constructorArgs.length;i++) {
    constructorArgTypes[i] = constructorArgs[i].getClass();
      }
      Constructor con = classObj.getConstructor(constructorArgTypes);
      o = con.newInstance(constructorArgs);
  }
        return o;
    }

    /** Computes a wait duration based on the given "start" time, a desired
     *  increment (assuming instanteous time -- the given deltaT), and an
     *  adjustment to correct for compute time (the current time). A negative
     *  duration will be treated as an invalid -- or "unresolved" -- test
     *  case. If the duration is non-negative, then this method will sleep
     *  for that many milliseconds, and then return.
     *  @param baseT0 the start time
     *  @param deltaT time increment
     *  @exception TestException usually indicates a failure
     */
    public static void computeDurAndWait(long baseT0,
                                         long deltaT) throws Exception
    {
        long dur = baseT0 + deltaT - System.currentTimeMillis();
  if(dur > 0) {
      Thread.sleep(dur);
  } else {
            throw new TestException("Environment problem; this configuration"
                                    + " does not allow for the timing"
                                    + " assumptions made by the test");
                                   
  }
    }

    /** Sleeps for the given amount of milliseconds
     *  @param deltaT time in milliseconds to sleep
     */
    public static void waitDeltaT(long deltaT) throws Exception {
  Thread.sleep(deltaT);
    }

    /** Returns true if the input argument is even; false otherwise
     *  @param i integer to test for even or odd
     */
    public static boolean isEven(int i) {
        return ((i&1) == 1 ? false:true);
    }

    /** Determines if all of the expected (and no un-expected) events
     *  have arrived. The test in this method depends on the semantics of
     *  event-notification. That is, it will use the fact that if the events
     *  were generated for each service class in sequence (which they were),
     *  then the events will arrive in the same sequence. This means we can
     *  expect, when examining the event corresponding to index i, that the
     *  serviceID returned in the ServiceEvent should correspond to the i_th
     *  service registered. If it does not, then failure is declared.
     *
     *  This method is currently employed by the following test classes:
     *
     *                  NotifyOnAttrAdd
     *                  NotifyOnAttrMod
     *                  NotifyOnAttrDel
     *                  NotifyOnSrvcLeaseExpiration
     *
     *  @param eventVector vector containing the events to test
     *  @param nExpectedEvnts number of events expected
     *  @param expectedTransition the expected event transition
     *  @param serviceRegs array of ServiceRegistrations of each service
     *  @exception TestException usually indicates a failure
     */
    public static void verifyEventVector(Vector eventVector,
                                         int nExpectedEvnts,
                                         int expectedTransition,
                                         ServiceRegistration[] serviceRegs)
                                                         throws Exception
    {
        ServiceEvent evnt = null;
        if (eventVector.size() != nExpectedEvnts) {
            throw new TestException("# of Events Received ("+
                                             eventVector.size()+
                                             ") != # of Events Expected ("+
                                             nExpectedEvnts+")");
  } else {
            ServiceID evntSrvcID;
            ServiceID expdSrvcID;
            ServiceID handbackSrvcID;
      for(int i=0; i<eventVector.size(); i++) {
                evnt = (ServiceEvent)eventVector.elementAt(i);
                if (evnt == null) {
                    throw new TestException
                             ("null Event returned from Vector at element "+i);
       } else {
                    if (evnt.getTransition() != expectedTransition) {
      dumpEventIDs(eventVector, serviceRegs);
                        throw new TestException("Unexpected Transition returned ("+
            evnt.getTransition()+")");
        } else {
                        evntSrvcID = evnt.getServiceID();
                        expdSrvcID = serviceRegs[i].getServiceID();
                        if ( !(evntSrvcID.equals(expdSrvcID)) ) {
                            throw new TestException("Service ID Received ("+
                evntSrvcID+
                ") != Service ID Expected ("+
                expdSrvcID+")");
      } else {
          handbackSrvcID =
        (ServiceID)(evnt.getRegistrationObject().get());

          if ( !(handbackSrvcID.equals(expdSrvcID)) ) {
        throw new TestException
            ("Handback Service ID ("+
             handbackSrvcID+
             ") != Service ID Expected ("+
             expdSrvcID+")");
          }
      }
        }
    }
      }
  }
  verifyEventItems(eventVector);
    }

    public static void dumpEventIDs(Vector eventVector,
                                    ServiceRegistration[] serviceRegs)
    {
        ServiceEvent evnt = null;
  ServiceID evntSrvcID;
  ServiceID expdSrvcID;
  ServiceID handbackSrvcID;
  for(int i=0; i<eventVector.size(); i++) {
      evnt = (ServiceEvent)eventVector.elementAt(i);
      evntSrvcID = evnt.getServiceID();
      expdSrvcID = serviceRegs[i].getServiceID();
      System.out.println("Expected ID = " + expdSrvcID + ", received ID = " + evntSrvcID);
  }
    }

    /** Verifies that the ServiceItem in each event is as expected.
     *  If there is no later event with the same service ID, then
     *  compare the item in the event with the current item in the
     *  lookup service.  If the item in the event is null, then the
     *  item must no longer exist in the lookup service, otherwise
     *  the item must exist in the lookup service and be equal to
     *  the one in the event.  We skip an event if there is a later
     *  event with the same service ID, as that means the state of
     *  the item recorded in the event was subsequently changed again.
     *
     *  @param eventVector vector containing the events to test
     *  @exception TestException usually indicates a failure
     */
    public static void verifyEventItems(Vector eventVector)
  throws Exception
    {
  ServiceTemplate tmpl = new ServiceTemplate(null, null, null);
    outer:
  for (int i = 0; i < eventVector.size(); i++) {
      ServiceEvent evnt = (ServiceEvent)eventVector.elementAt(i);
      for (int j = i + 1; j < eventVector.size(); j++) {
    ServiceEvent oevnt = (ServiceEvent)eventVector.elementAt(j);
    if (evnt.getServiceID().equals(oevnt.getServiceID()))
        continue outer;
      }
      ServiceItem item = evnt.getServiceItem();
      tmpl.serviceID = evnt.getServiceID();
      ServiceRegistrar proxy = (ServiceRegistrar)evnt.getSource();
      proxy = (ServiceRegistrar)
        QAConfig.getConfig().prepare("test.reggiePreparer",
                  proxy);
      ServiceMatches matches;
      matches = proxy.lookup(tmpl, 1);
      if (item == null) {
    if (matches.items.length != 0)
        throw new TestException(
            "verifyEventItems: event item is null, lookup returns non-null");
      } else {
    if (matches.items.length == 0)
        throw new TestException(
            "verifyEventItems: event item is non-null, lookup returns null");
    ServiceItem litem = matches.items[0];
    if (!item.service.equals(litem.service))
        throw new TestException(
            "verifyEventItems: event item service does not equal lookup value");
    if (!attrsEqual(item.attributeSets, litem.attributeSets))
         throw new TestException(
            "verifyEventItems: event item attrs do not equal lookup value");
      }
  }
    }

    /** Tests if two arrays of attribute sets are the same length and
     *  have equal elements, ignoring element ordering differences.
     *
     *  @param attrs1 an array of attribute sets
     *  @param attrs2 an array of attribute sets
     */
    public static boolean attrsEqual(Entry[] attrs1, Entry[] attrs2) {
  if (attrs1.length != attrs2.length)
      return false;
    outer:
  for (int i = 0; i < attrs1.length; i++) {
      for (int j = 0; j < attrs2.length; j++) {
    if (attrs1[i].equals(attrs2[j]))
        continue outer;
      }
      return false;
  }
  return true;
    }

    /** Performs a simple lookup and a match lookup using only the serviceID
     *  @param srvcItems array of registered service items
     *  @param templates array of used input to lookup()
     *  @param proxy proxy of Registrar through which lookup is performed
     *  @exception TestException usually indicates a failure
     */
    public static void doLookup(ServiceItem[] srvcItems,
                                ServiceTemplate[] templates,
        ServiceRegistrar proxythrows Exception
    {
        Object serviceObj = null;
        ServiceMatches matches = null;
        for (int i=0; i<templates.length; i++) {
      serviceObj = proxy.lookup(templates[i]);
            if (!srvcItems[i].service.equals(serviceObj)) {
                throw new TestException("srvcItems["+i+
          "] != serviceObj returned by lookup()");
      }

      matches = proxy.lookup(templates[i],Integer.MAX_VALUE);
            if (matches.totalMatches != 1) {
                throw new TestException
        ("totalMatches != EXPECTED_N_MATCHES");
      } else {
                if (!srvcItems[i].service.equals(matches.items[0].service)) {
                    throw new TestException("srvcItems["+i+
              "] != items[0].service returned by lookup()");
    }
      }
  }
    }

    /** Steps through the given array of leases, comparing each element's
     *  lease expiration against the given minimum lease expiration; a
     *  failure exception will be thrown if any of the lease expirations
     *  is less than the minimum expiration
     *  @param leases array of lease objects corresponding to each service
     *  @param minExpiration minimum lease expiration time
     *  @exception TestException usually indicates a failure
     *  @see net.jini.core.lease.Lease
     */
    public static void verifyLeases(Lease[] leases,
                                    long minExpirationthrows Exception
    {
  for(int i=0; i<leases.length; i++) {
      if(leases[i].getExpiration() < minExpiration) {
                throw new TestException("verifyLeases: expiration of lease ["
          +i+"] ("+leases[i].getExpiration()+
          " ms) < expected min expiration ("
          +minExpiration+" ms)");
      } else {
    minExpiration = leases[i].getExpiration();
      }
  }
    }

    /** Steps through the given array of leases, renewing each element's
     *  lease with the given lease duration value
     *  @param leases array of lease objects corresponding to each service
     *  @param leaseDuration lease duration to request in renewal
     *  @exception TestException usually indicates a failure
     *  @see net.jini.core.lease.Lease
     */
    public static void doRenewLease(Lease[] leases,
                                    long leaseDuration) throws Exception
    {
        for(int i=0; i< leases.length; i++ ) {
      leases[i].renew(leaseDuration);
  }
    }

    /** Steps through the given array of service items, searching for the
     *  element that equals the given Object; returning the index of the
     *  matching element or -1 if no match is found
     *  @param srvcObj service item to search for
     *  @param srvcItems array of service items to search through
     *  @see net.jini.core.lookup.ServiceItem
     */
    public static int srvcIndxFrmSimpleLookup( Object        srvcObj,
                                               ServiceItem[] srvcItems ) {
        int indx = -1;
        for (int j=0;((indx==-1)&&(j<srvcItems.length)); j++) {
            if ((srvcItems[j].service.equals(srvcObj))) {
               indx  = j;
      }
  }
        return indx;
    }

    /** Inserts the given value into the given histogram.
     * 
     *  Note that the method that calls this method must create the
     *  histogram. If the histogram is null, then this method will throw
     *  a NullPointerException
     *  @param value value to place in the histogram
     *  @param histogram HashMap representing the histogram
     */
    public static void srvcHistogram( int value,
                                      HashMap histogram ) {
        Integer histKey = new Integer(value);
        Integer histVal = (Integer)histogram.get(histKey);
        int newHistVal = ( (histVal==null) ? 1 : 1+histVal.intValue() );
        Integer newValue = new Integer(newHistVal);
        histogram.put(histKey,newValue);
    }

    /** Returns the value of the largest key index in the given histogram
     *  @param histogram HashMap representing the histogram
     *  @return int
     */
    public static int getMaxKeyHistogram( HashMap histogram ) {
        int maxKey = 0;
        int counter = 0;
        if ( histogram != null ) {
            int hSize = histogram.size();
      for ( int i=0; counter < hSize; i++ ) {
          if (histogram.get(new Integer(i)) != null) {
                    counter++;
                    if (counter >= hSize) {
                        maxKey = i;
        }
    }
      }
  }
        return maxKey;
    }

    /** Prints the values of the given histogram to stdout (for debugging)
     *  @param histogram HashMap representing the histogram
     */
    public static void displayHistogram( HashMap histogram ) {
  if ( histogram != null ) {
      for ( int i=0; i <= getMaxKeyHistogram(histogram); i++ ) {
                System.out.println("histogram("+i+") = "
                                          +histogram.get(new Integer(i)));
      }
  }
    }

    /** Disregarding order, verify that the given set of class types is
     *  equal to the given set of type descriptors. For the case where
     *  the classType is assignable to net.jini.lookup.entry.ServiceType,
     *  it is only required that the class associated with the typeDescriptor
     *  also is assignable to net.jini.lookup.entry. This is to handle
     *  the case where the actual class is
     *  com.sun.jini.lookup.entry.BasicServiceType,
     *  which may be preferred. This would case an 'equals' comparison to fail.
     *  In addition, a special case involves a check for the reggie proxy class.
     *  Since the proxy used is configuration dependent, if a typeDescriptor
     *  has the value "com.sun.jini.reggie.RegistrarProxy", then equality
     *  will be satisfied if a classType can be found whose getName method
     *  returns either "com.sun.jini.reggie.RegistrarProxy" or
     *  "com.sun.jini.reggie.ConstrainableRegistrarProxy"
     *
     *  This method is currently employed by the following test classes:
     *
     *                  GetServiceTypesEmpty
     *                  GetServiceTypesClass
     *                  GetServiceTypesAttr
     *
     *  @param classTypes array of class types
     *  @param typeDescriptors array of class name descriptors
     *  @exception TestException usually indicates a failure
     */
    public static boolean classTypesEqualTypeDescriptors
                                            ( Class[] classTypes,
                                              String[] typeDescriptors )
    {
        if (typeDescriptors == null) {
            return (classTypes == null);
  }
  if (classTypes == null) {
      logger.log(Level.INFO, "classTypes is null");
  }
        if (classTypes.length != typeDescriptors.length) {
      logger.log(Level.INFO, "classTypes != typeDescriptors");
      for (int i = 0; i < classTypes.length; i++) {
    logger.log(Level.INFO,
         "classTypes[ " + i + "] = " + classTypes[i]);
      }
      for (int i = 0; i < typeDescriptors.length; i++) {
    logger.log(Level.INFO,
         "typeDescriptors[ " + i + "] = "
         + typeDescriptors[i]);
      }
            return false;
  }
  String reggieProxy = "com.sun.jini.reggie.RegistrarProxy";
  String cReggieProxy = "com.sun.jini.reggie.ConstrainableRegistrarProxy";
        iLoop:
            for (int i=0; i<classTypes.length; i++) {
                for (int j=0;(j<typeDescriptors.length); j++) {
        try {
      Class c = Class.forName(typeDescriptors[j]);
                        if (classTypes[i].equals(c)) {
                            continue iLoop;
                  }
      Class serviceTypeClass = ServiceType.class;
                        if (serviceTypeClass.isAssignableFrom(classTypes[i])) {
          if (serviceTypeClass.isAssignableFrom(c)) {
              continue iLoop;
          }
      }
      if (typeDescriptors[j].equals(reggieProxy)) {
          if (classTypes[i].getName().equals(reggieProxy)
           || classTypes[i].getName().equals(cReggieProxy)) {
        continue iLoop;
          }
      }
        } catch (ClassNotFoundException e) {
      if (classTypes[i].getName().equals(typeDescriptors[j])) {
          continue iLoop;
      }
      if (typeDescriptors[j].equals(reggieProxy)) {
          if (classTypes[i].getName().equals(reggieProxy)
           || classTypes[i].getName().equals(cReggieProxy)) {
        continue iLoop;
          }
      }
      logger.log(Level.INFO,
           "Could not find service type class named "
           + typeDescriptors[j]);
        }
          }
          logger.log(Level.INFO,
         "Could not find match for classTypes = "
         + classTypes[i]);
                return false;
            }
        return true; /* success */
    }

    /** Returns the number of classes in the chain of super classes of the
     *  given Object; up to, but not including, the Object class itself
     *  @param obj the Object to analyze for super classes
     *  @exception TestException usually indicates a failure
     *  @return int
     */
    public static int getNSuperClasses(Object obj) {
        int n = 0;
        try {
            Class superClass = obj.getClass().getSuperclass();
            while(true) {
                if( !(superClass.getSuperclass() == null) ) {
                    n++;
                    superClass = superClass.getSuperclass();
             } else {
                    return n;
          }
      }
        } catch (NullPointerException e) {
            return 0;
        }
    }

    /** Returns the nth super class in the chain of super classes of the
     *  given Object; returns null if the given value of n is invalid.
     *  @param obj the Object to analyze for super classes
     *  @param n super class "index" to return
     *  @exception TestException usually indicates a failure
     *  @return int
     */
    public static Object getNthSuperClass(Object obj, int n) {
        int totalN;
        Class superClass = null;
        try {
            totalN = getNSuperClasses(obj);
            if ((totalN > 0)&&(n>0)&&(n<=totalN)) {
                superClass = obj.getClass().getSuperclass();
                for(int i=1;i<n;i++) {
                    superClass = superClass.getSuperclass();
                }
                return (Object)superClass;
      } else {
                return null;
      }
        } catch (NullPointerException e) {
            return null;
        }
    }

    /** Returns true if the given attribute objects match, else returns false
     *  Note that the order of the input Objects is NOT important
     *  @param attrObj0 first attribute object to compare
     *  @param attrObj1 second attribute object to compare
     *  @exception TestException usually indicates a failure
     *  @return boolean
     */
    public static boolean attrsMatch(Object attrObj0, Object attrObj1) {
        Object sObj = null;
        Object cObj  = null;
        if ( attrObj0.equals(attrObj1) ) {
            return true;
  } else if ( (attrObj0.getClass()).equals((attrObj1).getClass()) ) {
            return false;
  } else {
      if ((attrObj0.getClass()).isAssignableFrom(attrObj1.getClass())) {
                /* cast attrObj1 to super class attrObj0 */
                sObj = attrObj0;
                cObj = attrObj1;
      } else if
               ((attrObj1.getClass()).isAssignableFrom(attrObj0.getClass())) {
                /* cast attrObj0 to super class attrObj1 */
                sObj = attrObj1;
                cObj = attrObj0;
      } else {
                return false;
      }
            return ((Attr)sObj).matches(cObj);
  }
    }

    /** Returns true if the given attribute objects match, else returns false
     *  Note that the order of the input Objects IS important
     *  @param attrObj0 first attribute object to compare
     *  @param attrObj1 second attribute object to compare
     *  @param orderImportant true or false
     *  @exception TestException usually indicates a failure
     *  @return boolean
     */
    public static boolean attrsMatch(Object attrObj0,
                                     Object attrObj1,
                                     boolean orderImportant)
    {
        if (!orderImportant) {
            return attrsMatch(attrObj0,attrObj1);
  } else {
            if ( attrObj0.equals(attrObj1) ) {
                return true;
      } else if ( (attrObj0.getClass()).equals((attrObj1).getClass()) ) {
                return true;
         } else if((attrObj0.getClass()).isAssignableFrom
                                                        (attrObj1.getClass())){
                return ((Attr)attrObj0).matches(attrObj1);
      } else {
                return false;
      }
  }
    }

    /** Initializes the given SrvcAttrTuple state array element at the two
     *  given index values to the corresponding values contained in the
     *  arguments named srvcItems and attrs
     *
     *  This method is currently employed by the following test classes:
     *
     *                  NotifyOnComboAttrAddNull
     *                  NotifyOnComboAttrAddNonNull
     *                  NotifyOnComboAttrModNull
     *                  NotifyOnComboAttrModNonNull
     *                  NotifyOnComboAttrDelNull
     *                  NotifyOnComboAttrDelNonNull
     *                  NotifyOnComboSrvcLeaseExp
     *
     *  @param srvcIndx index of the service item
     *  @param attrIndx index of the attribute
     *  @param superChainLen length of the service super class "chain"
     *  @param srvcItems array of registered services
     *  @param srvcsForEquals array of instantiated services for comparison
     *  @param attrs array-of-arrays of attribute objects for matching
     *  @param state the state array of tuples
     *  @exception TestException usually indicates a failure
     *  @see net.jini.core.lookup.ServiceItem
     */
    public static void initStateTupleArray
                                        (int srvcIndx,
                                         int attrIndx,
                                         int superChainLen,
                                         ServiceItem[] srvcItems,
                                         ServiceItem[] srvcsForEquals,
                                         Entry[][] attrs,
                                         SrvcAttrTuple[][][] state)
  throws Exception
    {
        state[srvcIndx][attrIndx][0]
                               = new SrvcAttrTuple(srvcsForEquals,
                                                   attrs,
                                                   srvcItems[srvcIndx].service,
                                                   attrs[attrIndx][0]);

        Class superClass = null;
        superClass = (srvcItems[srvcIndx].service).getClass().getSuperclass();
        for(int i=1;i<superChainLen;i++) {
            if( !(superClass.getSuperclass() == null) ) {
                state[srvcIndx][attrIndx][i] =
                         new SrvcAttrTuple(srvcsForEquals,attrs,
                                           createInstance(superClass,srvcIndx),
                                           attrs[attrIndx][0]);
                superClass = superClass.getSuperclass();
      } else {
                state[srvcIndx][attrIndx][i] =
                             new SrvcAttrTuple(srvcsForEquals,attrs,
                                               createInstance(superClass,null),
                                               attrs[attrIndx][0]);
                return;
      }
  }
    }

    /** Initializes all of the elements in the given SrvcAttrTuple array to
     *  null for the attribute component of the Tuple; and to the
     *  corresponding service item for the service component
     *
     *  This method is currently employed by the following test classes:
     *
     *                  NotifyOnComboAttrAddNull
     *                  NotifyOnComboAttrAddNonNull
     *                  NotifyOnComboSrvcReg
     *
     *  @param srvcItems array of registered services
     *  @param srvcsForEquals array of instantiated services for comparison
     *  @param attrs array-of-arrays of attribute objects for matching
     *  @param state the state array of tuples
     *  @exception TestException usually indicates a failure
     *  @see net.jini.core.lookup.ServiceItem
     *  @see net.jini.core.entry.Entry
     */
    public static void initStateTupleArray
                                        (ServiceItem[] srvcItems,
                                         ServiceItem[] srvcsForEquals,
                                         Entry[][] attrs,
                                         SrvcAttrTuple[][][] state)
  throws Exception
    {
        for(int i=0;i<state.length;i++) {
            jLoop:
            for(int j=0;j<state[i].length;j++) {
                state[i][j][0] = new SrvcAttrTuple(srvcsForEquals,attrs,
                                                   srvcItems[i].service,null);
                Class superClass = null;
                superClass = (srvcItems[i].service).getClass().getSuperclass();
                for(int k=1;k<state[i][j].length;k++) {
                    if( !(superClass.getSuperclass() == null) ) {
                        state[i][j][k] = new SrvcAttrTuple
                                                 (srvcsForEquals,attrs,
                                                  createInstance(superClass,i),
                                                  null);
                            superClass = superClass.getSuperclass();
        } else {
                        state[i][j][k] = new SrvcAttrTuple
                                              (srvcsForEquals,attrs,
                                               createInstance(superClass,null),
                                               null);
                        continue jLoop;
        }
    }
      }
  }
    }

    /** Retrieves the chain of super classes of the given object; up to, but
     *  not including, the Object class itself. Returns a vector containing
     *  initialized instances of each class in the chain (including
     *  the instance of the given object itself).
     *
     *  Note: this method is specific to the set of test service classes
     *        that are registered during any typical lookup test. Thus,
     *        this method should be invoked only on objects that belong to
     *        a chain of classes contained in the set of test services;
     *        that is, the input object, as well as each of the super
     *        classes in the chain have a constructor that requires a
     *        single argument of type int.
     *
     *  @param obj object that is analyzed for its super classes
     *  @param srvcItems array of registered services
     *  @exception TestException usually indicates a failure
     *  @return java.util.Vector
     *  @see net.jini.core.lookup.ServiceItem
     */
    public static Vector getSrvcSupersVector(Object        obj,
                                             ServiceItem[] srvcItems)
  throws Exception
    {
        int n;
        Class superClass = null;
        Vector objSupers = new Vector();
        objSupers.addElement(obj);
        superClass = obj.getClass().getSuperclass();
        while(true) {
            if( !(superClass.getSuperclass() == null) ) {
                for(n=0;n<srvcItems.length;n++) {
                    if (superClass.isInstance(srvcItems[n].service) ) {
                        break;
        }
    }
                objSupers.addElement(createInstance(superClass,n));
                superClass = superClass.getSuperclass();
      } else {
                return objSupers;
      }
  }
    }

    /** Retrieves the chain of super classes of the input object; up to, but
     *  not including, the Object class itself. Returns a vector containing
     *  non-initialized instances of each class in the chain (including
     *  the instance of the input object itself).
     *
     *  Note: this method should be invoked only on objects that have
     *        super classes containing no-arg constructors.
     *
     *  @param obj object that is analyzed for its super classes
     *  @exception TestException usually indicates a failure
     *  @return java.util.Vector
     */
    public static Vector getNoArgSupersVector(Object obj) throws Exception {
        Class superClass = null;
        Vector objSupers = new Vector();
        objSupers.addElement(obj);
        superClass = obj.getClass().getSuperclass();
        while(true) {
            if( !(superClass.getSuperclass() == null) ) {
    objSupers.addElement( superClass.newInstance() );
                superClass = superClass.getSuperclass();
      } else {
                return objSupers;
      }
  }
    }

    /** From the assumption that the addition, modification or deletion
     *  of an attribute of one of the registered service classes will
     *  result in one or more events being generated by the lookup service,
     *  this method "predicts" all of the service/attribute "pairs"
     *  corresponding to the set of events that will be generated from
     *  the "base" pair represented by the input srvcObj/attrObj pair.
     *  The number and "cause" of these events is dependent on the
     *  contents of the template or templates used to register the event
     *  notification requests with lookup. This method assumes that an
     *  event was registered using a template containing the class of
     *  both the input srvcObj argument and the attrObj argument. 
     *
     *  That is, given the template/event-registration-request assumption
     *  just described, if attrObj is added to, modified on, or deleted from
     *  srvcObj, then an event will be generated for each service/attribute
     *  pair in the lookup service which also matches one of the templates.
     *
     *  This method will populate the given tuples vector with the set of
     *  service/attribute/transition "tuples" corresponding to the events
     *  expected to be generated when the srvcObj's state is modified
     *  The tuples vector will contain all of the tuples that have accumulated
     *  over the life of the current test run. Thus, because that vector
     *  contains all of the expected pairs generated by previous calls to
     *  this method, the tuples vector must be created and maintained --
     *  outside of this method -- by the invoking class.
     *
     *  This method is currently employed by the following test classes:
     *
     *                  NotifyOnComboAttrAddNull
     *                  NotifyOnComboAttrAddNonNull
     *                  NotifyOnComboAttrModNull
     *                  NotifyOnComboAttrModNonNull
     *                  NotifyOnComboAttrDelNull
     *                  NotifyOnComboAttrDelNonNull
     *                  NotifyOnComboSrvcReg
     *                  NotifyOnComboSrvcLeaseExp
     *
     *  @param srvcObj object whose state has changed
     *  @param srvcItems array of registered services
     *  @param srvcsForEquals array of instantiated services for comparison
     *  @param attrs array-of-arrays of attribute objects for matching
     *  @param nSrvcsPerClass number of service instances per class type
     *  @param template template to use for matching
     *  @param preEventState the state array of tuples prior to the event
     *  @param postEventState the state array of tuples after the event
     *  @param tuples vector in which the expected tuples are accumulated
     *  @exception TestException usually indicates a failure
     *  @see net.jini.core.lookup.ServiceItem
     *  @see net.jini.core.entry.Entry
     */
    public static void setExpectedEvents(Object srvcObj,
                                         ServiceItem[] srvcItems,
                                         ServiceItem[] srvcsForEquals,
                                         Entry[][] attrs,
                                         int nSrvcsPerClass,
                                         ServiceTemplate[][] template,
                                         SrvcAttrTuple[][][] preEventState,
                                         SrvcAttrTuple[][][] postEventState,
                                         Vector tuples)
                                                        throws Exception
    {
        int i=0;
        int j=0;
        int n=0;
        SrvcAttrTuple tmplTuple;
        Vector srvcSupers = new Vector();
  int s0 = getSrvcIndx(srvcObj,srvcItems);
  int nAttrs = preEventState[0].length;
  int trans;
  int newSrvcIndx;
  ServiceTemplate srvcTmpl;
  for(j=0;j<nAttrs;j++) {
      srvcTmpl = template[s0/nSrvcsPerClass][j];
      for(i=0;i<(srvcTmpl.serviceTypes).length;i++) {
    tmplTuple = new SrvcAttrTuple
        ( srvcsForEquals,attrs,
          createInstance(srvcTmpl.serviceTypes[i],s0),
          (srvcTmpl).attributeSetTemplates[0] );

    if (  ((preEventState[s0][j][i]).getAttrObj() == null)
          &&((postEventState[s0][j][i]).getAttrObj()!= null))
        {
            /* attribute addition */
                        if ( (postEventState[s0][j][i]).objEquals(tmplTuple) )
          {
        trans = ServiceRegistrar.TRANSITION_NOMATCH_MATCH;

        (preEventState[s0][j][i]).setEqualTo
            (postEventState[s0][j][i]);
        newSrvcIndx = ((s0/nSrvcsPerClass)*nSrvcsPerClass)
            -(nSrvcsPerClass*i);
        tuples.addElement(new SrvcAttrTuple
            (srvcsForEquals,attrs,
             srvcItems[newSrvcIndx].service,
             attrs[j][0],
             trans));
          } else {
        break;
          }
        } else if( ((preEventState[s0][j][i]).getAttrObj() != null)
             &&((postEventState[s0][j][i]).getAttrObj()== null))
      {
          /* attribute deletion */
          if ( (preEventState[s0][j][i]).objEquals(tmplTuple) ) {
        trans = ServiceRegistrar.TRANSITION_MATCH_NOMATCH;

        (preEventState[s0][j][i]).setEqualTo
            (postEventState[s0][j][i]);
        newSrvcIndx = ((s0/nSrvcsPerClass)*nSrvcsPerClass)
            -(nSrvcsPerClass*i);

        tuples.addElement(new SrvcAttrTuple
            (srvcsForEquals,attrs,
             srvcItems[newSrvcIndx].service,
             attrs[j][0],
             trans));
          } else {
        break;
          }
      } else if( ((preEventState[s0][j][i]).getAttrObj() != null)
           &&((postEventState[s0][j][i]).getAttrObj()!= null))
          {
        /* attribute modification */
        if ((postEventState[s0][j][i]).objEquals(tmplTuple)) {

            if ((postEventState[s0][j][i]).objEquals
          (preEventState[s0][j][i]))
          {
              trans
            = ServiceRegistrar.TRANSITION_MATCH_MATCH;
          } else {
              trans
            = ServiceRegistrar.TRANSITION_NOMATCH_MATCH;

              (preEventState[s0][j][i]).setEqualTo
            (postEventState[s0][j][i]);
          }
            newSrvcIndx =((s0/nSrvcsPerClass)*nSrvcsPerClass)
          -(nSrvcsPerClass*i);

            tuples.addElement(new SrvcAttrTuple
          (srvcsForEquals,attrs,
           srvcItems[newSrvcIndx].service,
           attrs[j][0],
           trans));
        } else {
            break;
        }
          }
      }
  }

    }

    /** From the assumption that an event was registered using a template
     *  containing the class of both the input srvcObj argument and the
     *  attrObj argument, this method "predicts" all of the service/attribute
     *  "pairs" corresponding to the set of events that will be generated
     *  from the "base" pair represented by the input srvcObj/attrObj pair.
     *
     *  This method will populate the given tuples vector with the set of
     *  service/attribute/transition "tuples" corresponding to the events
     *  expected to be generated when the srvcObj's state is modified
     *  The tuples vector will contain all of the tuples that have accumulated
     *  over the life of the current test run. Thus, because that vector
     *  contains all of the expected pairs generated by previous calls to
     *  this method, the tuples vector must be created and maintained --
     *  outside of this method -- by the invoking class.
     *
     *  This method is currently employed by the following test classes:
     *
     *                  NotifyOnEntryAttrSrvcReg
     *                  NotifyOnEntryAttrAddNull
     *                  NotifyOnEntryAttrAddNonNull
     *
     *  @param srvcIndx index into the template corresponding to the service
     *  @param srvcItems array of registered services
     *  @param srvcsForEquals array of instantiated services for comparison
     *  @param attrs array-of-arrays of attribute objects for matching
     *  @param template template to use for matching
     *  @param state the state array of tuples after the event
     *  @param tuples vector in which the expected tuples are accumulated
     *  @exception TestException usually indicates a failure
     *  @see net.jini.core.lookup.ServiceItem
     *  @see net.jini.core.entry.Entry
     */
    public static void setExpectedEvents(int srvcIndx,
                                         ServiceItem[] srvcItems,
                                         ServiceItem[] srvcsForEquals,
                                         Entry[][] attrs,
                                         ServiceTemplate[] template,
                                         SrvcAttrTuple[][][] state,
                                         Vector tuples)
                                                        throws Exception
    {
        int trans = ServiceRegistrar.TRANSITION_NOMATCH_MATCH;
        Object tmplAttr = (template[srvcIndx]).attributeSetTemplates[0];

        for(int i=0;i<state.length;i++) {
            for(int j=0;j<state[i].length;j++) {
                if (state[i][j][0] != null) {
                    Object stateAttr = (state[i][j][0]).getAttrObj();
                    if (stateAttr != null) {
                        if (attrsMatch(stateAttr,tmplAttr,true)) {
                            tuples.addElement(new SrvcAttrTuple
                                               (srvcsForEquals,attrs,
                                                (state[i][j][0]).getSrvcObj(),
                                                stateAttr,
                                                trans));
            }
        }
    }
      }
  }
    }

    /** Compares the number and content of the given set of expected events
     *  to the given set of received events; where the event information
     *  is stored in the given vectors as objects of class type SrvcAttrTuple
     *  @param receivedTuples array of received event tuples
     *  @param expectedTuples array of expected event tuples
     *  @param maxWaitTime maximum number of milliseconds to wait for events
     *  @param showTime true/false: write elapsed time to standard output
     *  @exception TestException usually indicates a failure
     */
    public static void verifyEventTuples(Vector  receivedTuples,
                                         Vector  expectedTuples,
                                         long    maxWaitTime,
                                         boolean showTime)
                                                         throws Exception
    {
        int i,j;
        long waitDeltaT = N_MS_PER_MIN;
        long nMsWaited  = waitDeltaT;
        /* give the Listener a chance to collect all events */
        while(true) {
      try {
                Thread.sleep(waitDeltaT);
      } catch (InterruptedException e) { }
            if (showTime) {
                System.out.println("Total Time: "
                                   +(nMsWaited/N_MS_PER_MIN)+
                                   " mins");
      }
            if (receivedTuples.size() != expectedTuples.size()) {
          if (nMsWaited < maxWaitTime) {
                    nMsWaited = nMsWaited + waitDeltaT;
    } else {
                    throw new TestException
                     ("# of Events Received ("+receivedTuples.size()+
                      ") != # of Events Expected ("+expectedTuples.size()+")");
    }
      } else {
                break;
      }
  }
        if (showTime) {
            System.out.println("\n# of Events Expected = "
                               +expectedTuples.size());
            System.out.println("# of Events Received = "
                               +receivedTuples.size()+"\n");
            System.out.println
                           ("# of seconds each event took to arrive (approx): "
                   +(N_MS_PER_SEC*receivedTuples.size())/nMsWaited+
                            " secs\n");
            System.out.println
                       ("Comparing Received Events to Expected Events ...\n");
  }
        verifyEventTupleContent(receivedTuples,expectedTuples);
    }

    /** Compares the number and content of the given set of expected events
     *  to the given set of received events; where the event information
     *  is stored in the given vectors as objects of class type SrvcAttrTuple
     *  @param receivedTuples array of received event tuples
     *  @param expectedTuples array of expected event tuples
     *  @param maxWaitTime maximum number of milliseconds to wait for events
     *  @exception TestException usually indicates a failure
     */
    public static void verifyEventTuples(Vector  receivedTuples,
                                         Vector  expectedTuples,
                                         long    maxWaitTime)
                                                         throws Exception
    {
        int i,j;
        long waitDeltaT = N_MS_PER_MIN;
        long nMsWaited  = waitDeltaT;
        /* give the Listener a chance to collect all events */
        while(true) {
      try {
                Thread.sleep(waitDeltaT);
      } catch (InterruptedException e) { }
            if (receivedTuples.size() != expectedTuples.size()) {
          if (nMsWaited < maxWaitTime) {
                    nMsWaited = nMsWaited + waitDeltaT;
    } else {
                    throw new TestException
                     ("# of Events Received ("+receivedTuples.size()+
                      ") != # of Events Expected ("+expectedTuples.size()+")");
    }
      } else {
                break;
      }
  }
        verifyEventTupleContent(receivedTuples,expectedTuples);
    }

    /** Based on the number of service class instances and the number of
     *  attributes per service participating in the current test run,
     *  this method computes and returns the maximum number of milliseconds
     *  to wait for all events to arrive from the lookup service before
     *  attempting to verify the events.
     *  @param nSrvcs total number of service instances registered
     *  @param nAttrs total number of attribute instances
     *  @return long
     */
    public static long getMaxNMsToWaitForEvents(int nSrvcs,
                                                int nAttrs) {
        long maxTime = 10*nSrvcs*nAttrs*N_MS_PER_SEC;
        if (maxTime < N_MS_PER_MIN) {
            maxTime = N_MS_PER_MIN;
  }
        return maxTime;
    }

    /** Based on the number of service class instances and the number of
     *  attributes per service participating in the current test run,
     *  this method computes and returns the maximum number of milliseconds
     *  to wait for all events to arrive from the lookup service before
     *  attempting to verify the events.
     *  @param nSrvcs total number of service instances registered
     *  @param nAttrs total number of attribute instances
     *  @param showTime true/false: write elapsed time to standard output
     *  @return long
     */
    public static long getMaxNMsToWaitForEvents(int nSrvcs,
                                                int nAttrs,
                                                boolean showTime) {
        long maxTime = getMaxNMsToWaitForEvents(nSrvcs,nAttrs);
        if (showTime) {
            System.out.println("\nmaxNMsToWaitForEvents = "
                               +(maxTime/N_MS_PER_MIN)+" mins");
  }
        return maxTime;
    }

    /** This method sets values for the maximum duration of all service
     *  and event leases.
     *  @param sysConfig the test config object
     *  @param leaseDuration maximum service lease duration and event lease
     *         duration in milliseconds
     */
    public static void setLeaseDuration(QAConfig sysConfig,
                                        long leaseDuration)
    {
        setLeaseDuration(sysConfig,leaseDuration,leaseDuration);
    }

    /** This method sets values for the maximum duration of all service
     *  and event leases.
     *  @param sysConfig the test config object
     *  @param serviceLeaseDuration maximum service lease duration
     *         in milliseconds
     *  @param eventLeaseDuration maximum event lease duration
     *         in milliseconds
     */
    public static void setLeaseDuration(QAConfig sysConfig,
                                        long serviceLeaseDuration,
                                        long eventLeaseDuration)
    {
        sysConfig.addOverrideProvider(new ServiceLeaseOverrideProvider(
            sysConfig, serviceLeaseDuration, eventLeaseDuration));
    }

    /** Prints the fields of each element (tuple) of the given tuples vector.
     *  Each element of the vector must be an instance of the class
     *  SrvcAttrTuple. This method is intended to be used only for
     *  debugging.
     *  @param tuples vector in which the expected tuples are accumulated
     */
    public static void displayTuples(Vector tuples) {
        System.out.println
          ("\n--------------------------------------------------------------");
        int i=0;
        Object tupleSrvc;
        Object tupleAttr;
        int trans;
  try {
            for(i=0;i<tuples.size();i++) {
                tupleSrvc
                     = ((SrvcAttrTuple)tuples.get(i)).getSrvcObj();
                tupleAttr
                     = ((SrvcAttrTuple)tuples.get(i)).getAttrObj();
                trans
                  = ((SrvcAttrTuple)tuples.get(i)).getTransition();
                System.out.println("srvcObj    = "+tupleSrvc);
                System.out.println("attrObj    = "+tupleAttr);
                System.out.println("Transition = "+trans_str[trans]);
                if(i<(tuples.size()-1))System.out.println(" ");
            }
  } catch (ClassCastException e) {
            System.out.println
                   ("displayTuples: ClassCastException (element at index i="+i+
                    " can NOT be cast to type SrvcAttrTuple)");
  } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println
                   ("displayTuples: ArrayIndexOutOfBoundsException (i="+i+")");
  }
        System.out.println
          ("--------------------------------------------------------------\n");
    }

    /** Check if an array contains the object. return true if it contains */
    public static boolean isArrayContain(Object a[], Object o) {
  for(int i=0; i<a.length; i++)
      if (a[i].equals(o) )
    return true;
  return false;
    }

    /** Prints the fields of each element (tuple) of the given state array.
     *  Each element of the array must be an instance of the class
     *  SrvcAttrTuple. This method is intended to be used only for
     *  debugging.
     *  @param state array of state tuples
     */
    private static void displayTuples(SrvcAttrTuple[][][] state) {
        System.out.println
          ("\n--------------------------------------------------------------");
        int i=0;
        int j=0;
        int k=0;
        Object tupleSrvc;
        Object tupleAttr;
        int trans;
  try {
            for(i=0;i<state.length;i++) {
                for(j=0;j<(state[i]).length;j++) {
                    for(k=0;k<(state[i][j]).length;k++) {
                        tupleSrvc
                    = ((SrvcAttrTuple)state[i][j][k]).getSrvcObj();
                        tupleAttr
                    = ((SrvcAttrTuple)state[i][j][k]).getAttrObj();
                        trans
                    = ((SrvcAttrTuple)state[i][j][k]).getTransition();
                        System.out.println("srvcObj    = "+tupleSrvc);
                        System.out.println("attrObj    = "+tupleAttr);
                        System.out.println("Transition = "+trans_str[trans]);
                    if(k<(state[i][j]).length-1)System.out.println(" ");
        }
                    if(j<(state[i]).length-1)System.out.println(" ");
                }
                if(i<state.length-1)System.out.println(" ");
            }
  } catch (ClassCastException e) {
            System.out.println
                        ("displayTuples: ClassCastException (element at i="+i+
                         ",j="+j+" can NOT be cast to type SrvcAttrTuple)");
  } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println
                   ("displayTuples: ArrayIndexOutOfBoundsException (i="+i+
                                                                  ",j="+j+")");
  }
        System.out.println
          ("--------------------------------------------------------------\n");
    }

    /*  Compares the content of the given set of expected events to the given
     *  set of received events (this method is shared by the overloaded
     *  versions of the method verifyEventTuples)
     */
    private static void verifyEventTupleContent(Vector  receivedTuples,
                                                Vector  expectedTuples)
                                                         throws Exception
    {
        int i,j;
        iLoop:
        for(i=0; i<receivedTuples.size(); i++) {
      /*  step through the vector containing the expected tuples
             *  if the current received tuple is not in the set of
             *  expected tuples, declare failure
             */
           for(j=0;j<expectedTuples.size();j++) {
                if((receivedTuples.get(i)).equals(expectedTuples.get(j))) {
                    expectedTuples.removeElementAt(j);
                    continue iLoop;
    }
      }
            throw new TestException
                   ("Received an UNEXPECTED Event\nSrvc  = "
                    +(((SrvcAttrTuple)receivedTuples.get(i)).getSrvcObj())+
                    ",\nAttr  = "
                    +(((SrvcAttrTuple)receivedTuples.get(i)).getAttrObj())+
                    ",\nTrans = "
                    +(((SrvcAttrTuple)receivedTuples.get(i)).getTransition()));
        }
    }

    /** Removes any repeated elements from the ArrayList and then compares
     *  the String elements in the array to the String elements in ArrayList.
     *  Returns true if the sets are equal in size and if each element in
     *  one set is equal to one element in the other set; returns false
     *  otherwise.
     *
     *  This method is currently employed by the following test classes:
     *
     *                  SimpleAddMemberGroups
     *                  SimpleSetMemberGroups
     *                  SimpleRemoveMemberGroups
     *
     *  @param returnedGroups array of String elements from getMemberGroups
     *  @param expectedGroups ArrayList of expected String elements
     */
    public static boolean groupsAreEqual(String[] returnedGroups,
                                         ArrayList expectedGroups) {
        ArrayList filteredList = removeRepeatedElems(expectedGroups);
        if (returnedGroups.length != filteredList.size()) {
            return false;
  }
  iLoop:
        for(int i=0;i<filteredList.size();i++) {
            for(int j=0;j<returnedGroups.length;j++) {
                if (returnedGroups[j].equals((String)(filteredList.get(i)))) {
                    continue iLoop;
    }
      }
            return false;
        }
        return true;
    }

    /** Removes any repeated elements from the input ArrayList; returns
     *  a new ArrayList containing all unique elements from the input list.
     *
     *  This method is currently employed by the following test classes:
     *
     *                  SimpleAddMemberGroups
     *                  SimpleSetMemberGroups
     *                  SimpleRemoveMemberGroups
     *
     *  @param list ArrayList of String elements
     */
    public static ArrayList removeRepeatedElems(ArrayList list) {
        ArrayList newList = new ArrayList();
        iLoop:
        for(int i=0;i<list.size();i++) {
            String str = (String)(list.get(i));
            for(int j=0; j<newList.size();j++) {
                if (str.equals((String)(newList.get(j)))) {
                    continue iLoop;
    }
      }
            newList.add(str);
        }
        return newList;
    }

    /** Removes all elements of the String array from the ArrayList; returns
     *  a new ArrayList containing the elements of the original ArrayList
     *  minus elements from the String array.
     *
     *  This method is currently employed by the following test classes:
     *
     *                  SimpleRemoveMemberGroups
     *
     *  @param list ArrayList of String elements
     *  @param strArray array of String elements
     */
    public static ArrayList removeListFromArray(ArrayList list,
                                                String[] strArray) {
        ArrayList newList = new ArrayList();
        iLoop:
        for(int i=0;i<list.size();i++) {
            String str = (String)(list.get(i));
            for(int j=0;j<strArray.length;j++) {
                if (str.equals(strArray[j])) {
                    continue iLoop;
    }
      }
            newList.add(str);
        }
        return newList;
    }

    /** Prints the elements of the input String array.
     * 
     *  This method is intended to be used only for debugging.
     *  @param strArray array of String elements
     */
    public static void displayStringArray(String[] strArray) {
        System.out.println(" ");
        for(int i=0;i<strArray.length;i++) {
      if ((i>=0)&&(i<=9)) {
                System.out.println("["+i+"]   = "+strArray[i]);
            } else if ((i>=10)&&(i<=99)) {
                System.out.println("["+i+"]  = "+strArray[i]);
         } else {
                System.out.println("["+i+"] = "+strArray[i]);
            }
  }
    }

    /** Prints the elements of the input ArrayList.
     * 
     *  Each element of the ArrayList must be of type String. This method
     *  is intended to be used only for debugging.
     *  @param list ArrayList of String elements
     */
    public static void displayStringArrayList(ArrayList list) {
        System.out.println(" ");
        for(int i=0;i<list.size();i++) {
      if ((i>=0)&&(i<=9)) {
                System.out.println("["+i+"]   = "+(String)(list.get(i)));
            } else if ((i>=10)&&(i<=99)) {
                System.out.println("["+i+"]  = "+(String)(list.get(i)));
         } else {
                System.out.println("["+i+"] = "+(String)(list.get(i)));
            }
  }
    }

    /** Determines if the input Objects are equal; where equality is defined
     *  by Class equality and field equality. A special case is subclasses
     *  of net.jini.lookup.entry.ServiceType. If both objects are assignable
     *  to ServiceType, then class equality is not required. This is necessary
     *  to handle the case where com.sun.jini.lookup.entry.BasicServiceType
     *  is being compared, and one of the object was obtained from a preferred
     *  class loader.
     *
     *  @param obj0 the to compare to obj1 for equality
     *  @param obj1 the to compare to obj0 for equality
     *  @return boolean
     */
    public static boolean objsAreEqual(Object obj0, Object obj1) {
        Class obj0Class = (obj0).getClass();
        Class obj1Class = (obj1).getClass();
        if (!(obj1Class.equals(obj0Class))) {
            Class st = net.jini.lookup.entry.ServiceType.class;
      if (!st.isAssignableFrom(obj0Class)
                || !st.isAssignableFrom(obj1Class)) {
                return false;
            }
        }
        Field[] obj0Fields = obj0Class.getFields();
        Field[] obj1Fields = obj1Class.getFields();
        try {
      jLoop:
            for(int j=0;j<obj0Fields.length;j++) {
                String name0 = (obj0Fields[j]).getName();
                for(int k=0;k<obj1Fields.length;k++) {
                    String name1 = (obj1Fields[k]).getName();
                    if (name0.equals(name1)) {
                        Object field0 = (obj0Fields[j]).get(obj0);
                        Object field1 = (obj1Fields[k]).get(obj1);
      if (field0 == null) {
          if (field1 != null)
        return false;
          continue jLoop;
      } else if (field0.equals(field1)) {
                            continue jLoop;
                        } else {
                            return false;
                        }
        }
    }
                return false;
            }
        } catch (IllegalAccessException e) {
            return false;
  }
        return true;
    }
}
TOP

Related Classes of com.sun.jini.test.spec.lookupservice.QATestUtils

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.