diff options
author | Taka Cho <takamune.cho@att.com> | 2021-02-19 09:00:43 -0500 |
---|---|---|
committer | Ajith Sreekumar <ajith.sreekumar@bell.ca> | 2021-02-19 17:41:43 +0000 |
commit | 2381590fc66aa088e0b016befaef09d21e618100 (patch) | |
tree | 6b307017031e92d0f6eb13b2461de1b212572364 /feature-server-pool/src/test | |
parent | 4d2730e9a66609f028dfa6289e035b1fe4924400 (diff) |
deprecate server-pool in droolspdp
deprecate server-pool in droolspdp
Issue-ID: POLICY-3079
Change-Id: Id25aea57cc4d119bba73de22c6dc77ab9a56c95f
Signed-off-by: Taka Cho <takamune.cho@att.com>
Diffstat (limited to 'feature-server-pool/src/test')
18 files changed, 0 insertions, 3429 deletions
diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/AdapterImpl.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/AdapterImpl.java deleted file mode 100644 index 865f4e90..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/AdapterImpl.java +++ /dev/null @@ -1,455 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpool; - -import static org.awaitility.Awaitility.await; - -import java.io.PrintStream; -import java.nio.file.Paths; -import java.util.Properties; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import org.kie.api.runtime.KieSession; -import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; -import org.onap.policy.common.endpoints.event.comm.TopicListener; -import org.onap.policy.drools.core.PolicyContainer; -import org.onap.policy.drools.core.PolicySession; -import org.onap.policy.drools.core.PolicySessionFeatureApiConstants; -import org.onap.policy.drools.serverpooltest.Adapter; -import org.onap.policy.drools.serverpooltest.BucketWrapper; -import org.onap.policy.drools.serverpooltest.ServerWrapper; -import org.onap.policy.drools.serverpooltest.TargetLockWrapper; -import org.onap.policy.drools.system.PolicyController; -import org.onap.policy.drools.system.PolicyEngineConstants; -import org.onap.policy.drools.util.KieUtils; -import org.onap.policy.drools.utils.PropertyUtil; -import org.powermock.reflect.Whitebox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class implements the 'Adapter' interface. There is one 'AdapterImpl' - * class for each simulated host, and one instance of each 'AdapterImpl' class. - */ -public class AdapterImpl extends Adapter { - private static Logger logger = LoggerFactory.getLogger(AdapterImpl.class); - /* - * Each 'AdapterImpl' instance has it's own class object, making it a - * singleton. There is only a single 'Adapter' class object, and all - * 'AdapterImpl' classes are derived from it. - * - * Sonar thinks this field isn't used. However, it's value is actually - * retrieved via Whitebox, below. Thus it is marked "protected" instead - * of "private" to avoid the sonar complaint. - */ - protected static AdapterImpl adapter = null; - - // this is the adapter index - private int index; - - // this will refer to the Drools session 'PolicyController' instance - private PolicyController policyController = null; - - // this will refer to the Drools session 'PolicySession' instance - private PolicySession policySession = null; - - // used by Drools session to signal back to Junit tests - private LinkedBlockingQueue<String> inotificationQueue = - new LinkedBlockingQueue<>(); - - // provides indirect references to a select set of static 'Server' methods - private static ServerWrapper.Static serverStatic = - new ServerWrapperImpl.Static(); - - // provides indirect references to a select set of static 'Bucket' methods - private static BucketWrapper.Static bucketStatic = - new BucketWrapperImpl.Static(); - - /** - * {@inheritDoc} - */ - @Override - public void init(int index) throws Exception { - adapter = this; - this.index = index; - - PolicyEngineConstants.getManager().configure(new Properties()); - PolicyEngineConstants.getManager().start(); - /* - * Note that this method does basically what - * 'FeatureServerPool.afterStart(PolicyEngine)' does, but allows us to - * specify different properties for each of the 6 simulated hosts - */ - logger.info("{}: Running: AdapterImpl.init({}), class hash code = {}", - this, index, AdapterImpl.class.hashCode()); - final String propertyFile = "src/test/resources/feature-server-pool-test.properties"; - Properties prop = PropertyUtil.getProperties(propertyFile); - if (System.getProperty("os.name").toLowerCase().indexOf("mac") < 0) { - // Window, Unix - String[] ipComponent = prop.getProperty("server.pool.server.ipAddress").split("[.]"); - String serverIP = ipComponent[0] + "." + ipComponent[1] + "." + ipComponent[2] + "." - + (Integer.parseInt(ipComponent[3]) + index); - prop.setProperty("server.pool.server.ipAddress", serverIP); - } else { - // Mac, use localhost and different ports - String port = Integer.toString(Integer.parseInt( - prop.getProperty("server.pool.server.port")) + index); - prop.setProperty("server.pool.server.port", port); - } - logger.info("server={}, serverIP={}, port={}", index, - prop.getProperty("server.pool.server.ipAddress"), - prop.getProperty("server.pool.server.port")); - - TargetLock.startup(); - Server.startup(prop); - - // use reflection to set private static field - // 'FeatureServerPool.droolsTimeoutMillis' - Whitebox.setInternalState(FeatureServerPool.class, "droolsTimeoutMillis", - ServerPoolProperties.DEFAULT_BUCKET_DROOLS_TIMEOUT); - - // use reflection to set private static field - // 'FeatureServerPool.timeToLiveSecond' - Whitebox.setInternalState(FeatureServerPool.class, "timeToLiveSecond", - String.valueOf(ServerPoolProperties.DEFAULT_BUCKET_TIME_TO_LIVE)); - - // use reflection to call private static method - // 'FeatureServerPool.buildKeywordTable()' - Whitebox.invokeMethod(FeatureServerPool.class, "buildKeywordTable"); - - Bucket.Backup.register(new FeatureServerPool.DroolsSessionBackup()); - Bucket.Backup.register(new TargetLock.LockBackup()); - - // dump out feature lists - logger.info("{}: ServerPoolApi features list: {}", - this, ServerPoolApi.impl.getList()); - logger.info("{}: PolicySessionFeatureApi features list: {}", - this, PolicySessionFeatureApiConstants.getImpl().getList()); - } - - /** - * {@inheritDoc} - */ - @Override - public void shutdown() { - policyController.stop(); - Server.shutdown(); - - PolicyEngineConstants.getManager().stop(); - PolicyEngineConstants.getManager().getExecutorService().shutdown(); - } - - /** - * {@inheritDoc} - */ - @Override - public LinkedBlockingQueue<String> notificationQueue() { - return inotificationQueue; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean waitForInit(long endTime) throws InterruptedException { - try { - // wait until a leader is elected - await().atMost(endTime - System.currentTimeMillis(), - TimeUnit.MILLISECONDS).until(() -> Leader.getLeader() != null); - - // wait for each bucket to have an owner - for (int i = 0; i < Bucket.BUCKETCOUNT; i += 1) { - Bucket bucket = Bucket.getBucket(i); - while (bucket.getOwner() == null) { - await().atMost(Math.min(endTime - System.currentTimeMillis(), 100L), TimeUnit.MILLISECONDS); - } - } - } catch (IllegalArgumentException e) { - // 'Thread.sleep()' was passed a negative time-out value -- - // time is up - logger.debug("AdapterImpl waitForInit error", e); - return false; - } - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper.Static getServerStatic() { - return serverStatic; - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getLeader() { - return ServerWrapperImpl.getWrapper(Leader.getLeader()); - } - - /** - * {@inheritDoc} - */ - @Override - public BucketWrapper.Static getBucketStatic() { - return bucketStatic; - } - - /** - * {@inheritDoc} - */ - @Override - public TargetLockWrapper newTargetLock( - String key, String ownerKey, TargetLockWrapper.Owner owner, boolean waitForLock) { - - return TargetLockWrapperImpl.newTargetLock(key, ownerKey, owner, waitForLock); - } - - /** - * {@inheritDoc} - */ - @Override - public TargetLockWrapper newTargetLock(String key, String ownerKey, TargetLockWrapper.Owner owner) { - return TargetLockWrapperImpl.newTargetLock(key, ownerKey, owner); - } - - /** - * {@inheritDoc} - */ - @Override - public void dumpLocks(PrintStream out, boolean detail) { - try { - TargetLock.DumpLocks.dumpLocks(out, detail); - } catch (Exception e) { - logger.error("{}: Exception in 'dumpLocks'", this, e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public String createController() { - Properties properties; - /* - * set the thread class loader to be the same as the one associated - * with the 'AdapterImpl' instance, so it will be inherited by any - * new threads created (the Drools session thread, in particular) - */ - ClassLoader saveClassLoader = - Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(AdapterImpl.class.getClassLoader()); - - try { - // build and install Drools artifact - KieUtils.installArtifact( - Paths.get("src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml").toFile(), - Paths.get("src/test/resources/drools-artifact-1.1/pom.xml").toFile(), - "src/main/resources/rules/org/onap/policy/drools/core/test/rules.drl", - Paths.get("src/test/resources/drools-artifact-1.1/src/main/resources/rules.drl").toFile()); - - // load properties from file - properties = PropertyUtil.getProperties("src/test/resources/TestController-controller.properties"); - } catch (Exception e) { - e.printStackTrace(); - Thread.currentThread().setContextClassLoader(saveClassLoader); - return e.toString(); - } - - StringBuilder sb = new StringBuilder(); - try { - // create and start 'PolicyController' - policyController = PolicyEngineConstants.getManager() - .createPolicyController("TestController", properties); - policyController.start(); - - // dump out container information (used for debugging tests) - sb.append("PolicyContainer count: ") - .append(PolicyContainer.getPolicyContainers().size()).append('\n'); - for (PolicyContainer policyContainer : - PolicyContainer.getPolicyContainers()) { - sb.append(" name = ") - .append(policyContainer.getName()) - .append('\n') - .append(" session count = ") - .append(policyContainer.getPolicySessions().size()) - .append('\n'); - for (PolicySession pc : policyContainer.getPolicySessions()) { - policySession = pc; - } - } - } finally { - Thread.currentThread().setContextClassLoader(saveClassLoader); - } - return sb.toString(); - } - - /** - * {@inheritDoc} - */ - @Override - public void sendEvent(String key) { - /* - * Note: the dumping out of package information was useful in tracking - * down strange Drools behavior that was eventually tied to the - * Drools class loader. - */ - logger.info("{}: Calling 'sendEvent': packages = {}", this, - policySession.getKieSession().getKieBase().getKiePackages()); - ((TopicListener) policyController).onTopicEvent( - CommInfrastructure.UEB, "JUNIT-TEST-TOPIC", - "{\"key\":\"" + key + "\"}"); - } - - /** - * {@inheritDoc} - */ - @Override - public KieSession getKieSession() { - return policySession == null ? null : policySession.getKieSession(); - } - - /** - * {@inheritDoc} - */ - @Override - public void insertDrools(Object object) { - if (policySession != null) { - /* - * this will eventually be changed to use the - * 'PolicySession.insertObject(...)' method - */ - new FeatureServerPool().insertDrools(policySession, object); - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isForeign(Object... objects) { - boolean rval = false; - ClassLoader myClassLoader = AdapterImpl.class.getClassLoader(); - for (Object o : objects) { - Class<?> clazz = o.getClass(); - ClassLoader objClassLoader = clazz.getClassLoader(); - - try { - if (myClassLoader != objClassLoader - && clazz != myClassLoader.loadClass(clazz.getName())) { - rval = true; - logger.info("{}: FOREIGN OBJECT ({}) - {}", - this, getAdapter(objClassLoader), o); - } - } catch (ClassNotFoundException e) { - rval = true; - logger.error("{}: FOREIGN OBJECT -- CLASS NOT FOUND ({}) - {}", - this, getAdapter(objClassLoader), o); - } - } - return rval; - } - - /** - * {@inheritDoc} - */ - @Override - public String findKey(String prefix, int startingIndex, ServerWrapper host) { - String rval = null; - - // try up to 10000 numeric values to locate one on a particular host - for (int i = 0; i < 10000; i += 1) { - // generate key, and see if it is on the desired server - String testString = prefix + (startingIndex + i); - if (ServerWrapperImpl.getWrapper( - Bucket.bucketToServer(Bucket.bucketNumber(testString))) == host) { - // we have one that works - rval = testString; - break; - } - } - return rval; - } - - /** - * {@inheritDoc} - */ - @Override - public String findKey(String prefix, int startingIndex) { - return findKey(prefix, startingIndex, serverStatic.getThisServer()); - } - - /** - * {@inheritDoc} - */ - @Override - public String findKey(String prefix) { - return findKey(prefix, 1, serverStatic.getThisServer()); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "AdapterImpl[" + index + "]"; - } - - /** - * Return an Adapter. - * - * @return the 'Adapter' instance associated with the ClassLoader associated - * with the current thread - */ - public static Adapter getAdapter() { - /* - * Note that 'return(adapter)' doesn't work as expected when called from - * within a 'Drools' session, because of the strange way that the Drools - * 'ClassLoader' works -- it bypasses 'AdapterClassLoader' when doing - * class lookups, even though it is the immediate parent of the Drools - * session class loader. - */ - return getAdapter(Thread.currentThread().getContextClassLoader()); - } - - /** - * Return an Adapter. - * - * @param classLoader a ClassLoader instance - * @return the 'Adapter' instance associated with the specified ClassLoader - */ - public static Adapter getAdapter(ClassLoader classLoader) { - try { - // locate the 'AdapterImpl' class associated with a particular - // 'ClassLoader' (which may be different from the current one) - Class<?> thisAdapterClass = - classLoader.loadClass("org.onap.policy.drools.serverpool.AdapterImpl"); - - // return the 'adapter' field value - return Whitebox.getInternalState(thisAdapterClass, "adapter"); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/BucketWrapperImpl.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/BucketWrapperImpl.java deleted file mode 100644 index ddd4d553..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/BucketWrapperImpl.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpool; - -import java.io.PrintStream; -import java.util.IdentityHashMap; -import org.onap.policy.drools.serverpooltest.BucketWrapper; -import org.onap.policy.drools.serverpooltest.ServerWrapper; - -/** - * This class implements the 'BucketWrapper' interface. There is one - * 'BucketWrapperImpl' class for each simulated host. - */ -public class BucketWrapperImpl implements BucketWrapper { - // this maps a 'Bucket' instance on this host to an associated wrapper - private static IdentityHashMap<Bucket, BucketWrapperImpl> bucketToWrapper = - new IdentityHashMap<>(); - - // this is the 'Bucket' instance associated with the wrapper - private Bucket bucket; - - /** - * This method maps a 'Bucket' instance into a 'BucketWrapperImpl' - * instance. The goal is to have only a single 'BucketWrapperImpl' instance - * for each 'Bucket' instance, so that testing for identity will work - * as expected. - * - * @param bucket the 'Bucket' instance - * @return the associated 'BucketWrapperImpl' instance - */ - static synchronized BucketWrapperImpl getWrapper(Bucket bucket) { - if (bucket == null) { - return null; - } - BucketWrapperImpl rval = bucketToWrapper.get(bucket); - if (rval == null) { - // a matching entry does not yet exist -- create one - rval = new BucketWrapperImpl(bucket); - bucketToWrapper.put(bucket, rval); - } - return rval; - } - - /** - * Constructor - initialize the 'bucket' field. - */ - BucketWrapperImpl(Bucket bucket) { - this.bucket = bucket; - } - - /** - * {@inheritDoc} - */ - @Override - public int getBucketNumber() { - return bucket.getIndex(); - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getOwner() { - return ServerWrapperImpl.getWrapper(bucket.getOwner()); - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getPrimaryBackup() { - return ServerWrapperImpl.getWrapper(bucket.getPrimaryBackup()); - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getSecondaryBackup() { - return ServerWrapperImpl.getWrapper(bucket.getSecondaryBackup()); - } - - /* ============================================================ */ - - /** - * This class implements the 'BucketWrapper.Static' interface. There is - * one 'BucketWrapperImpl.Static' class, and one instance for each - * simulated host - */ - public static class Static implements BucketWrapper.Static { - /** - * {@inheritDoc} - */ - @Override - public int getBucketCount() { - return Bucket.BUCKETCOUNT; - } - - /** - * {@inheritDoc} - */ - @Override - public int bucketNumber(String value) { - return Bucket.bucketNumber(value); - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper bucketToServer(int bucketNumber) { - return ServerWrapperImpl.getWrapper(Bucket.bucketToServer(bucketNumber)); - } - - /** - * {@inheritDoc} - */ - @Override - public BucketWrapper getBucket(int bucketNumber) { - return getWrapper(Bucket.getBucket(bucketNumber)); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isKeyOnThisServer(String key) { - return Bucket.isKeyOnThisServer(key); - } - - /** - * {@inheritDoc} - */ - @Override - public void moveBucket(PrintStream out, int bucketNumber, String newHostUuid) { - ClassLoader save = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader( - BucketWrapperImpl.class.getClassLoader()); - Bucket.moveBucket(out, bucketNumber, newHostUuid); - } finally { - Thread.currentThread().setContextClassLoader(save); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void dumpAdjuncts(PrintStream out) { - Bucket.dumpAdjuncts(out); - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/ServerWrapperImpl.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/ServerWrapperImpl.java deleted file mode 100644 index 031c3323..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/ServerWrapperImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpool; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.UUID; -import org.onap.policy.drools.serverpooltest.ServerWrapper; - -/** - * This class implements the 'ServerWrapper' interface. There is one - * 'ServerWrapperImpl' class for each simulated host. - */ -public class ServerWrapperImpl implements ServerWrapper { - // this maps a 'Server' instance on this host to an associated wrapper - private static IdentityHashMap<Server, ServerWrapperImpl> serverToWrapper = - new IdentityHashMap<>(); - - // this is the 'Server' instance associated with the wrapper - private Server server; - - /** - * This method maps a 'Server' instance into a 'ServerWrapperImpl' - * instance. The goal is to have only a single 'ServerWrapperImpl' instance - * for each 'Server' instance, so that testing for identity will work - * as expected. - * - * @param server the 'Server' instance - * @return the associated 'ServerWrapperImpl' instance - * ('null' if 'server' is 'null') - */ - static synchronized ServerWrapperImpl getWrapper(Server server) { - if (server == null) { - return null; - } - ServerWrapperImpl rval = serverToWrapper.computeIfAbsent(server, - (key) -> new ServerWrapperImpl(server)); - return rval; - } - - /** - * Constructor - initialize the 'server' field. - */ - private ServerWrapperImpl(Server server) { - this.server = server; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return server.toString(); - } - - /** - * {@inheritDoc} - */ - @Override - public UUID getUuid() { - return server.getUuid(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isActive() { - return server.isActive(); - } - - /* ============================================================ */ - - /** - * This class implements the 'ServerWrapper.Static' interface. There is - * one 'ServerWrapperImpl.Static' class, and one instance for each - * simulated host - */ - public static class Static implements ServerWrapper.Static { - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getThisServer() { - return getWrapper(Server.getThisServer()); - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getFirstServer() { - return getWrapper(Server.getFirstServer()); - } - - /** - * {@inheritDoc} - */ - @Override - public ServerWrapper getServer(UUID uuid) { - return getWrapper(Server.getServer(uuid)); - } - - /** - * {@inheritDoc} - */ - @Override - public int getServerCount() { - return Server.getServerCount(); - } - - /** - * {@inheritDoc} - */ - @Override - public Collection<ServerWrapper> getServers() { - // build an 'ArrayList' which mirrors the set of servers - ArrayList<ServerWrapper> rval = new ArrayList<>(Server.getServerCount()); - - for (Server server : Server.getServers()) { - rval.add(getWrapper(server)); - } - return rval; - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/TargetLockWrapperImpl.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/TargetLockWrapperImpl.java deleted file mode 100644 index e170975a..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpool/TargetLockWrapperImpl.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpool; - -import java.io.Serializable; -import org.onap.policy.drools.core.lock.Lock; -import org.onap.policy.drools.core.lock.LockCallback; -import org.onap.policy.drools.serverpooltest.TargetLockWrapper; - -/** - * This class implements the 'TargetLockWrapper' interface. There is one - * 'TargetLockWrapperImpl' class for each simulated host. - */ -public class TargetLockWrapperImpl implements TargetLockWrapper { - private static final long serialVersionUID = 1L; - - // this is the 'TargetLock' instance associated with the wrapper - private TargetLock targetLock; - - /** - * {@inheritDoc} - */ - @Override - public boolean free() { - return targetLock.free(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isActive() { - return targetLock.isActive(); - } - - /** - * {@inheritDoc} - */ - @Override - public State getState() { - return TargetLockWrapper.State.valueOf(targetLock.getState().toString()); - } - - /** - * {@inheritDoc} - */ - @Override - public String getOwnerKey() { - return targetLock.getOwnerKey(); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return "TLW-" - + String.valueOf(AdapterImpl.getAdapter(TargetLockWrapperImpl.class.getClassLoader())) - + "[" + targetLock.toString() + "]"; - } - - /** - * This method creates a new 'TargetLock'. Internally, an 'OwnerAdapter' - * instance is built as well, which translates the 'LockCallback' - * callbacks to 'TargetLockWrapper.Owner' callbacks. As with the call to - * 'new TargetLock(...)', it is possible for the callback occur before - * this method returns -- this can happen if the 'key' hashes to a bucket - * owned by the current host. - * - * @param key string key identifying the lock - * @param ownerKey string key identifying the owner, which must hash to - * a bucket owned by the current host (it is typically a 'RequestID') - * @param owner owner of the lock (will be notified when going from - * WAITING to ACTIVE) - * @param waitForLock this controls the behavior when 'key' is already - * locked - 'true' means wait for it to be freed, 'false' means fail - * @return a 'TargetLockWrapper' instance associated with the new - * 'TargetLock. - */ - static TargetLockWrapper newTargetLock( - String key, String ownerKey, TargetLockWrapper.Owner owner, boolean waitForLock) { - - TargetLockWrapperImpl rval = new TargetLockWrapperImpl(); - rval.targetLock = - new TargetLock(key, ownerKey, - TargetLockWrapperImpl.getOwnerAdapter(rval, owner), - waitForLock); - return rval; - } - - /** - * This method creates a new 'TargetLock'. Internally, an 'OwnerAdapter' - * instance is built as well, which translates the 'LockCallback' - * callbacks to 'TargetLockWrapper.Owner' callbacks. As with the call to - * 'new TargetLock(...)', it is possible for the callback occur before - * this method returns -- this can happen if the 'key' hashes to a bucket - * owned by the current host. - * - * @param key string key identifying the lock - * @param ownerKey string key identifying the owner, which must hash to - * a bucket owned by the current host (it is typically a 'RequestID') - * @param owner owner of the lock (will be notified when going from - * WAITING to ACTIVE) - * @return a 'TargetLockWrapper' instance associated with the new - * 'TargetLock. - */ - static TargetLockWrapper newTargetLock( - String key, String ownerKey, TargetLockWrapper.Owner owner) { - - TargetLockWrapperImpl rval = new TargetLockWrapperImpl(); - rval.targetLock = - new TargetLock(key, ownerKey, - TargetLockWrapperImpl.getOwnerAdapter(rval, owner)); - return rval; - } - - /* ============================================================ */ - - /** - * This method builds an adapter that implements the 'LockCallback' - * callback interface, translating it to 'TargetLockWrapper.Owner'. - * - * @param targetLock the TargetLockWrapper that is using this adapter - * @param owner the 'TargetLockWrapper.Owner' callback - * @return an adapter implementing the 'LockCallback' interface - * ('null' is returned if 'owner' is null -- this is an error condition, - * but is used to verify the error handling of the 'TargetLock' - * constructor. - */ - public static LockCallback getOwnerAdapter( - TargetLockWrapper targetLock, TargetLockWrapper.Owner owner) { - - return owner == null ? null : new OwnerAdapter(targetLock, owner); - } - - /** - * This class is an adapter that implements the 'LockCallback' callback - * interface, translating it to a 'TargetLockWrapper.Owner' callback. - */ - public static class OwnerAdapter implements LockCallback, Serializable { - private static final long serialVersionUID = 1L; - - // the 'TargetLockWrapper' instance to pass as an argument in the callback - TargetLockWrapper targetLock; - - // the 'TargetLockWrapper.Owner' callback - TargetLockWrapper.Owner owner; - - /** - * Constructor - initialize the adapter. - * - * @param targetLock this will be passed as an argument in the callback - * @param owner the object implementing the 'TargetLockWrapper.Owner' - * interface - */ - private OwnerAdapter(TargetLockWrapper targetLock, TargetLockWrapper.Owner owner) { - this.targetLock = targetLock; - this.owner = owner; - } - - /** - * {@inheritDoc} - */ - @Override - public void lockAvailable(Lock lock) { - // forward 'lockAvailable' callback - owner.lockAvailable(targetLock); - } - - /** - * {@inheritDoc} - */ - @Override - public void lockUnavailable(Lock lock) { - // forward 'lockUnavailable' callback - owner.lockUnavailable(targetLock); - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Adapter.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Adapter.java deleted file mode 100644 index 9fa54608..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Adapter.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import static org.junit.Assert.assertTrue; - -import java.io.File; -import java.io.PrintStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Properties; -import java.util.concurrent.LinkedBlockingQueue; -import org.kie.api.runtime.KieSession; -import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.drools.serverpool.Util; -import org.onap.policy.drools.utils.PropertyUtil; - -/** - * This is a common base class for 6 'AdapterImpl' instances, all running - * with their own copies of the server pool classes, and a number of the ONAP - * classes. The purpose is to simulate 6 separate hosts in a server pool. - * Note that there is potentially a 7th copy of any of these classes, which is - * the one loaded with the system class loader. Ideally, those classes - * shouldn't be referred to, but there were some problems during testing, - * where they unexpectedly were (prompting a change in - * 'ExtendedObjectInputStream'). This is referred to as the 'null' host, - * where the classes may exist, but have not gone through initialization. - */ -public abstract class Adapter { - // 'true' indicates that initialization is still needed - private static boolean initNeeded = true; - /* - * Each 'Adapter' instance is implemented by 'AdapterImpl', but loaded - * with a different class loader that provides each with a different copy - * of the set of classes with packages in the list below (see references to - * 'BlockingClassLoader'). - */ - public static Adapter[] adapters = new Adapter[6]; - - /** - * Ensure that all adapters have been initialized. - */ - public static void ensureInit() throws Exception { - synchronized (Adapter.class) { - if (initNeeded) { - initNeeded = false; - - // start DMAAP Simulator - new Thread(new Runnable() { - @Override - public void run() { - SimDmaap.start(); - } - }, "DMAAP Simulator").start(); - - // wait 200 millisecond to allow time for the port 3904 listener - final String propertyFile = "src/test/resources/feature-server-pool-test.properties"; - Properties prop = PropertyUtil.getProperties(propertyFile); - assertTrue(NetworkUtil.isTcpPortOpen(prop.getProperty("server.pool.discovery.servers"), - Integer.parseInt(prop.getProperty("server.pool.discovery.port")), 250, 200)); - - // build 'BlockingClassLoader' - BlockingClassLoader bcl = new BlockingClassLoader( - Adapter.class.getClassLoader(), - // All 'org.onap.policy.*' classes are adapter-specific, except - // for the exclusions listed below. - "org.onap.policy.*" - ); - bcl.addExclude("org.onap.policy.drools.core.DroolsRunnable"); - bcl.addExclude("org.onap.policy.drools.serverpooltest.*"); - - // build URL list for class loader - URL[] urls = {}; - - // iterate through 'adapter' entries - ClassLoader saveClassLoader = - Thread.currentThread().getContextClassLoader(); - if (saveClassLoader instanceof URLClassLoader) { - urls = ((URLClassLoader) saveClassLoader).getURLs(); - } else { - // the parent is not a 'URLClassLoader' -- - // try to get this information from 'java.class.path' - ArrayList<URL> tmpUrls = new ArrayList<>(); - for (String entry : System.getProperty("java.class.path").split( - File.pathSeparator)) { - if (new File(entry).isDirectory()) { - tmpUrls.add(new URL("file:" + entry + "/")); - } else { - tmpUrls.add(new URL("file:" + entry)); - } - } - urls = tmpUrls.toArray(new URL[0]); - } - try { - for (int i = 0; i < adapters.length; i += 1) { - /* - * Build a new 'ClassLoader' for this adapter. The - * 'ClassLoader' hierarchy is: - * - * AdapterClassLoader(one copy per Adapter) -> - * BlockingClassLoader -> - * base ClassLoader (with the complete URL list) - */ - ClassLoader classLoader = - new AdapterClassLoader(i, urls, bcl); - /* - * set the current thread class loader, which should be - * inherited by any child threads created during - * the initialization of the adapter - */ - Thread.currentThread().setContextClassLoader(classLoader); - - // now, build the adapter -- it is not just a new instance, - // but a new copy of class 'AdapterImpl' - Adapter adapter = (Adapter) classLoader.loadClass( - "org.onap.policy.drools.serverpool.AdapterImpl") - .getDeclaredConstructor() - .newInstance(); - - // initialize the adapter - adapter.init(i); - adapters[i] = adapter; - } - } finally { - // restore the class loader to that used during the Junit tests - Thread.currentThread().setContextClassLoader(saveClassLoader); - } - } - } - } - - /** - * Shut everything down. - */ - public static void ensureShutdown() { - for (Adapter adapter : adapters) { - adapter.shutdown(); - } - SimDmaap.stop(); - // not sure why the following is started - Util.shutdown(); - } - - /** - * Runs server pool initialization for a particular host. - * - * @param index the index of the adapter (0-5) - */ - public abstract void init(int index) throws Exception; - - /** - * Shuts down the server pool for this host. - */ - public abstract void shutdown(); - - /** - * Return a 'LinkedBlockingQueue' instance, which is used as a way for - * Drools code to signal back to running Junit tests. - * - * @return a 'LinkedBlockingQueue' instance, which is used as a way for - * Drools code to signal back to running Junit tests - */ - public abstract LinkedBlockingQueue<String> notificationQueue(); - - /** - * This method blocks and waits for all buckets to have owners, or for - * a timeout, whichever occurs first. - * - * @param endTime the point at which timeout occurs - * @return 'true' if all buckets have owners, 'false' if a timeout occurred - */ - public abstract boolean waitForInit(long endTime) throws InterruptedException; - - /** - * Return an object providing indirect references to a select set of - * static 'Server' methods. - * - * @return an object providing indirect references to a select set of - * static 'Server' methods - */ - public abstract ServerWrapper.Static getServerStatic(); - - /** - * Return an object providing an indirect reference to the lead 'Server' - * object. - * - * @return an object providing an indirect reference to the lead 'Server' - * object - */ - public abstract ServerWrapper getLeader(); - - /** - * Return an object providing indirect references to a select set of - * static 'Bucket' methods. - * - * @return an object providing indirect references to a select set of - * static 'Bucket' methods - */ - public abstract BucketWrapper.Static getBucketStatic(); - - /** - * Create a new 'TargetLock' instance, returning an indirect reference. - * - * @param key string key identifying the lock - * @param ownerKey string key identifying the owner, which must hash to - * a bucket owned by the current host (it is typically a 'RequestID') - * @param owner owner of the lock (will be notified when going from - * WAITING to ACTIVE) - * @param waitForLock this controls the behavior when 'key' is already - * locked - 'true' means wait for it to be freed, 'false' means fail - */ - public abstract TargetLockWrapper newTargetLock( - String key, String ownerKey, TargetLockWrapper.Owner owner, - boolean waitForLock); - - /** - * Create a new 'TargetLock' instance, returning an indirect reference. - * - * @param key string key identifying the lock - * @param ownerKey string key identifying the owner, which must hash to - * a bucket owned by the current host (it is typically a 'RequestID') - * @param owner owner of the lock (will be notified when going from - * WAITING to ACTIVE) - */ - public abstract TargetLockWrapper newTargetLock( - String key, String ownerKey, TargetLockWrapper.Owner owner); - - /** - * Call 'TargetLock.DumpLocks.dumpLocks' - * - * @param out where the output should be displayed - * @param detail 'true' provides additional bucket and host information - * (but abbreviates all UUIDs in order to avoid excessive - * line length) - */ - public abstract void dumpLocks(PrintStream out, boolean detail); - - /** - * Create and initialize PolicyController 'TestController', and start - * the associated Drools container and session. - * - * @return a string containing controller session information - */ - public abstract String createController(); - - /** - * Send an event in the form of a JSON message string. The message is - * sent to JUNIT-TEST-TOPIC, and the JSON object is converted to a - * 'TestDroolsObject' (all compatible with the Drools session created by - * 'createController'. - * - * @param key determines the bucket number, which affects which host the - * message is eventually routed to - */ - public abstract void sendEvent(String key); - - /** - * Return the one-and-only 'KieSession' on this host. - * - * @return the one-and-only 'KieSession' on this host - */ - public abstract KieSession getKieSession(); - - /** - * Insert an object into the one-and-only Drools session. - * - * @param object the object to insert - */ - public abstract void insertDrools(Object object); - - // some test utilities - - /** - * Determine whether any of the objects passed as parameters are of a class - * that belongs to different adapter. Print messages are displayed - * for any that do occur. - * - * @param objects one or more objects to be tested - * @return 'true' if one or more are foreign - */ - public abstract boolean isForeign(Object... objects); - - /** - * This method is used to generate keys that hash to a bucket associated - * with a particular server. The algorithm generates a key using 'prefix' - * concatenated with a numeric value, and searches for the first one on - * the desired host. It will try up to 10000 indices before giving up -- - * each host owns 1/6 of the buckets, should the 10000 number should be - * way more than enough. The tests are written with the assumption that - * a valid key will be returned, and 'NullPointerException' is an acceptable - * way to handle the situation if this doesn't work out somehow. - * - * @param prefix the first portion of the key - * @param startingIndex the first index to try - * @param host this indicates the 'Server' instance to locate, which must - * not be foreign to this adapter - * @return a key associated with 'host' ('null' if not found) - */ - public abstract String findKey(String prefix, int startingIndex, ServerWrapper host); - - /** - * Equivalent to 'findKey(prefix, startingIndex, THIS-SERVER)'. - * - * @param prefix the first portion of the key - * @param startingIndex the first index to try - * @return a key associated with 'host' ('null' if not found) - */ - public abstract String findKey(String prefix, int startingIndex); - - /** - * Equivalent to 'findKey(prefix, 1, THIS-SERVER)'. - * - * @param prefix the first portion of the key - * @return a key associated with 'host' ('null' if not found) - */ - public abstract String findKey(String prefix); - - /* ============================================================ */ - - /** - * This class is basically a 'URLClassLoader', but with a 'toString()' - * method that indicates the host and adapter number. - */ - public static class AdapterClassLoader extends URLClassLoader { - private int index; - - public AdapterClassLoader(int index, URL[] urls, ClassLoader parent) { - super(urls, parent); - this.index = index; - } - - @Override - public String toString() { - return "AdapterClassLoader(" + index + ")"; - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/BlockingClassLoader.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/BlockingClassLoader.java deleted file mode 100644 index a21f254d..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/BlockingClassLoader.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.NoSuchElementException; - -/** - * Ordinarily, a 'ClassLoader' first attempts to load a class via the - * parent 'ClassLoader'. If that fails, it attempts to load it "locally" - * by whatever mechanism the class loader supports. - * This 'ClassLoader' instance blocks attempts to load specific classes, - * throwing a 'ClassNotFoundException'. This doesn't seem useful on the - * surface, but it forces all child 'ClassLoader' instances to do the lookup - * themselves. In addition, each child 'ClassLoader' will have their own - * copy of the classes they load, providing a way to have multiple copies of - * the same class running within the same JVM. Each child 'ClassLoader' can - * be viewed as having a separate name space. - */ -public class BlockingClassLoader extends ClassLoader { - // these are the set of packages to block - private HashSet<String> packages; - - // these are the prefixes of class names to block - private ArrayList<String> prefixes; - - // these specific classes will not be blocked, even if they are in one - // of the packages indicated by 'packages' - private HashSet<String> excludes = new HashSet<String>(); - - // these are the prefixes of class names to exclude - private ArrayList<String> excludePrefixes = new ArrayList<>(); - - /** - * Constructor -- initialize the 'ClassLoader' and 'packages' variable. - * - * @param parent the parent ClassLoader - * @param packages variable number of packages to block - */ - public BlockingClassLoader(ClassLoader parent, String... packages) { - super(parent); - this.packages = new HashSet<>(); - this.prefixes = new ArrayList<>(); - for (String pkg : packages) { - if (pkg.endsWith("*")) { - prefixes.add(pkg.substring(0, pkg.length() - 1)); - } else { - this.packages.add(pkg); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - protected Class<?> findClass(String name) throws ClassNotFoundException { - // throws a 'ClassNotFoundException' if we are blocking this one - testClass(name); - - // not blocking this one -- pass it on to the superclass - return super.findClass(name); - } - - /** - * {@inheritDoc} - */ - @Override - public Enumeration<URL> getResources(String name) { - // in order to avoid replicated resources, we return an empty set - return new Enumeration<URL>() { - public boolean hasMoreElements() { - return false; - } - - public URL nextElement() { - throw new NoSuchElementException("'BlockingClassLoader' blocks duplicate resources"); - } - }; - } - - /** - * {@inheritDoc} - */ - @Override - public Class<?> loadClass(String name) throws ClassNotFoundException { - // throws a 'ClassNotFoundException' if we are blocking this one - testClass(name); - - // not blocking this one -- pass it on to the superclass - return super.loadClass(name); - } - - /** - * {@inheritDoc} - */ - @Override - protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { - // throws a 'ClassNotFoundException' if we are blocking this one - testClass(name); - - // not blocking this one -- pass it on to the superclass - return super.loadClass(name, resolve); - } - - /** - * Add an entry to the list of classes that should NOT be blocked. - * - * @param name the full name of a class that shouldn't be blocked - */ - public void addExclude(String name) { - if (name.endsWith("*")) { - excludePrefixes.add(name.substring(0, name.length() - 1)); - } else { - excludes.add(name); - } - } - - /** - * This method looks at a class name -- if it should be blocked, a - * 'ClassNotFoundException' is thrown. Otherwise, it does nothing. - * - * @param name the name of the class to be tested - * @throws ClassNotFoundException if this class should be blocked - */ - private void testClass(String name) throws ClassNotFoundException { - if (excludes.contains(name)) { - // allow this one - return; - } - - for (String prefix : excludePrefixes) { - if (name.startsWith(prefix)) { - // allow this one - return; - } - } - - // extract the package from the class name -- throw a - // 'ClassNotFoundException' if the package is in the list - // being blocked - int index = name.lastIndexOf('.'); - if (index >= 0) { - if (packages.contains(name.substring(0, index))) { - throw(new ClassNotFoundException(name)); - } - - for (String prefix : prefixes) { - if (name.startsWith(prefix)) { - throw(new ClassNotFoundException(name)); - } - } - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/BucketWrapper.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/BucketWrapper.java deleted file mode 100644 index 2628513c..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/BucketWrapper.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import java.io.PrintStream; - -/** - * This class provides base classes for accessing the various 'Bucket' - * classes. There is a separate copy of the 'Bucket' class for each - * adapter, and this wrapper was created to give them a common interface. - */ -public interface BucketWrapper { - /** - * This calls the 'Bucket.getBucketNumber()' method - * - * @return the bucket number - */ - public int getBucketNumber(); - - /** - * This calls the 'Bucket.getOwner()' method - * - * @return a 'ServerWrapper' instance that corresponds to the owner - * of the bucket ('null' if unassigned) - */ - public ServerWrapper getOwner(); - - /** - * This calls the 'Bucket.getPrimaryBackup()' method - * - * @return a 'ServerWrapper' instance that corresponds to the primary backup - * host for the bucket ('null' if unassigned) - */ - public ServerWrapper getPrimaryBackup(); - - /** - * This calls the 'Bucket.getPrimaryBackup()' method - * - * @return a 'ServerWrapper' instance that corresponds to the secondary - * backup host for the bucket ('null' if unassigned) - */ - public ServerWrapper getSecondaryBackup(); - - /* ============================================================ */ - - /** - * This class provides access to the static 'Bucket' methods. There are - * multiple 'Bucket' classes (one for each 'Adapter'), and each has - * a corresponding 'BucketWrapper.Static' instance. In other words, there - * is one 'Bucket.Static' instance for each simulated host. - */ - public interface Static { - /** - * This returns the value of 'Bucket.BUCKETCOUNT' - * - * @return the number of Bucket instances in the bucket table - */ - public int getBucketCount(); - - /** - * This calls the static 'Bucket.bucketNumber(String)' method - * - * @param value the keyword to be converted - * @return the bucket number - */ - public int bucketNumber(String value); - - /** - * This calls the static 'Bucket.bucketToServer(int)' method - * - * @param bucketNumber a bucket number in the range 0-1023 - * @return a 'ServerWrapper' for the server that currently handles the - * bucket, or 'null' if none is currently assigned - */ - public ServerWrapper bucketToServer(int bucketNumber); - - /** - * This calls the static 'Bucket.getBucket(int)' method - * - * @param bucketNumber a bucket number in the range 0-1023 - * @return A 'BucketWrapper' for the Bucket associated with - * this bucket number - */ - public BucketWrapper getBucket(int bucketNumber); - - /** - * This calls the static 'Bucket.isKeyOnThisServer(String)' method - * - * @param key the keyword to be hashed - * @return 'true' if the associated bucket is assigned to this server, - * 'false' if not - */ - public boolean isKeyOnThisServer(String key); - - /** - * This calls the static 'Bucket.moveBucket(PrintStream, int, String)' - * method (the one associated with the '/cmd/moveBucket' REST call). - * - * @param out the 'PrintStream' to use for displaying information - * @param bucketNumber the bucket number to be moved - * @param newHostUuid the UUID of the destination host (if 'null', a - * destination host will be chosen at random) - */ - public void moveBucket(PrintStream out, int bucketNumber, String newHostUuid); - - /** - * This calls the static 'Bucket.dumpAdjuncts(PrintStream)' method - * (the one associated with the '/cmd/dumpBucketAdjuncts' REST call). - * - * @param out the 'PrintStream' to use for displaying information - */ - public void dumpAdjuncts(PrintStream out); - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/ServerWrapper.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/ServerWrapper.java deleted file mode 100644 index e31a6817..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/ServerWrapper.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import java.util.Collection; -import java.util.UUID; - -/** - * This class provides base classes for accessing the various 'Server' - * classes. There is a separate copy of the 'Server' class for each - * adapter, and this wrapper was created to give them a common interface. - */ -public interface ServerWrapper { - /** - * This calls the 'Server.toString()' method - * - * @return a string of the form 'Server[UUID]' - */ - public String toString(); - - /** - * This calls the 'Server.getUuid()' method - * - * @return the UUID associated with this Server - */ - public UUID getUuid(); - - /** - * This calls the 'Server.isActive()' method - * - * @return 'true' if the this server is active, and 'false' if not - */ - public boolean isActive(); - - /* ============================================================ */ - - /** - * This class provides access to the static 'Server' methods. There are - * multiple 'Server' classes (one for each 'Adapter'), and each has - * a corresponding 'ServerWrapper.Static' instance. In other words, there - * is one 'Server.Static' instance for each simulated host. - */ - public interface Static { - /** - * This calls the static 'Server.getThisServer()' method - * - * @return a 'ServerWrapper' instance that corresponds to the Server - * instance associated with this simulated host - */ - public ServerWrapper getThisServer(); - - /** - * This calls the static 'Server.getFirstServer()' method - * - * @return a 'ServerWrapper' instance that corresponds to the first - * 'Server' instance in the 'servers' list (the one with the - * lowest UUID) - */ - public ServerWrapper getFirstServer(); - - /** - * This calls the static 'Server.getServer(UUID)' method - * - * @param uuid the key to the lookup - * @return a 'ServerWrapper' instance that corresponds to the associated - * 'Server' instance ('null' if none) - */ - public ServerWrapper getServer(UUID uuid); - - /** - * This calls the static 'Server.getServerCount()' method - * - * @return a count of the number of servers - */ - public int getServerCount(); - - /** - * This calls the static 'Server.getServers()' method - * - * @return the complete list of servers, each with a 'ServerWrapper' - * referring to the 'Server' - */ - public Collection<ServerWrapper> getServers(); - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/SimDmaap.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/SimDmaap.java deleted file mode 100644 index b1b86370..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/SimDmaap.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.onap.policy.drools.utils.PropertyUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class simulates a UEB/DMAAP server. - */ - -@Path("/") -public class SimDmaap { - private static Logger logger = LoggerFactory.getLogger(SimDmaap.class); - - // miscellaneous Jetty/Servlet parameters - private static ServletContextHandler context; - private static Server jettyServer; - private static ServerConnector connector; - private static ServletHolder holder; - - /** - * Do whatever needs to be done to start the server. I don't know exactly - * what abstractions the various pieces provide, but the following code - * ties the pieces together, and starts up the server. - */ - public static void start() { - try { - context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - - jettyServer = new Server(); - - connector = new ServerConnector(jettyServer); - connector.setName("simdmaap"); - connector.setReuseAddress(true); - final String propertyFile = "src/test/resources/feature-server-pool-test.properties"; - Properties prop = PropertyUtil.getProperties(propertyFile); - connector.setPort(Integer.parseInt(prop.getProperty("server.pool.discovery.port"))); - connector.setHost(prop.getProperty("server.pool.discovery.servers")); - - jettyServer.addConnector(connector); - jettyServer.setHandler(context); - - holder = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class.getName(), "/*"); - holder.setInitParameter( - "jersey.config.server.provider.classnames", SimDmaap.class.getName()); - - jettyServer.start(); - jettyServer.join(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Cleanly shut down the server. - */ - public static void stop() { - try { - if (jettyServer != null) { - jettyServer.stop(); - jettyServer = null; - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - /* ============================================================ */ - - // maps topic name to 'Topic' instance - static Map<String, Topic> topicTable = new ConcurrentHashMap<>(); - - /** - * Each instance of this class corresponds to a DMAAP or UEB topic. - */ - static class Topic { - // topic name - String topic; - - // maps group name into group instance - Map<String, Group> groupTable = new ConcurrentHashMap<>(); - - /** - * Create or get a Topic. - * - * @param name the topic name - * @return the associated Topic instance - */ - static Topic createOrGet(String name) { - // look up the topic name - Topic topicObj = topicTable.get(name); - if (topicObj == null) { - // no entry found -- the following will create one, without - // the need for explicit synchronization - topicTable.putIfAbsent(name, new Topic(name)); - topicObj = topicTable.get(name); - } - return topicObj; - } - - /** - * Constructor - initialize the 'topic' field. - * - * @param topic the topic name - */ - private Topic(String topic) { - this.topic = topic; - } - - /** - * Handle an incoming '/events/{topic}' POST REST message. - * - * @param the body of the REST message - * @return the appropriate JSON response - */ - String post(String data) { - // start of message processing - long startTime = System.currentTimeMillis(); - - // current and ending indices to the 'data' field - int cur = 0; - int end = data.length(); - - // the number of messages retrieved so far - int messageCount = 0; - - while (cur < end) { - /* - * The body of the message may consist of multiple JSON messages, - * each preceded by 3 integers separated by '.'. The second one - * is the length, in bytes (the third seems to be some kind of - * channel identifier). - */ - int leftBrace = data.indexOf('{', cur); - if (leftBrace < 0) { - // no more messages - break; - } - String[] prefix = data.substring(cur, leftBrace).split("\\."); - if (prefix.length == 3) { - try { - // determine length of message, and advance current position - int length = Integer.valueOf(prefix[1]); - cur = leftBrace + length; - /* - * extract message, and update count -- each double quote - * has a '\' character placed before it, so the overall - * message can be placed in double quotes, and parsed as - * a literal string - */ - String message = data.substring(leftBrace, cur) - .replace("\\", "\\\\").replace("\"", "\\\"") - .replace("\n", "\\n"); - messageCount += 1; - - // send to all listening groups - for (Group group : groupTable.values()) { - group.messages.add(message); - } - } catch (Exception e) { - logger.error("{}: {}", prefix[1], e); - break; - } - } else if (cur == 0) { - // there is only a single message -- extract it, and update count - String message = data.substring(leftBrace, end) - .replace("\\", "\\\\").replace("\"", "\\\"") - .replace("\n", "\\n"); - messageCount += 1; - - // send to all listening grops - for (Group group : groupTable.values()) { - group.messages.add(message); - } - break; - } else { - // don't know what this is -- toss it - break; - } - } - - // generate response message - long elapsedTime = System.currentTimeMillis() - startTime; - return "{\n" - + " \"count\": " + messageCount + ",\n" - + " \"serverTimeMs\": " + elapsedTime + "\n" - + "}"; - } - - /** - * read one or more incoming messages. - * - * @param group the 'consumerGroup' value - * @param timeout how long to wait for a message, in milliseconds - * @param limit the maximum number of messages to receive - * @return a JSON array, containing somewhere between 0 and 'limit' messages - */ - String get(String group, long timeout, int limit) throws InterruptedException { - // look up the group -- create one if it doesn't exist - Group groupObj = groupTable.get(group); - if (groupObj == null) { - // no entry found -- the following will create one, without - // the need for explicit synchronization - groupTable.putIfAbsent(group, new Group()); - groupObj = groupTable.get(group); - } - - // pass it on to the 'Group' instance - return groupObj.get(timeout, limit); - } - } - - /* ============================================================ */ - - /** - * Each instance of this class corresponds to a Consumer Group. - */ - static class Group { - // messages queued for this group - private BlockingQueue<String> messages = new LinkedBlockingQueue<>(); - - /** - * Retrieve messages sent to this group. - * - * @param timeout how long to wait for a message, in milliseconds - * @param limit the maximum number of messages to receive - * @return a JSON array, containing somewhere between 0 and 'limit' messages - */ - String get(long timeout, int limit) throws InterruptedException { - String message = messages.poll(timeout, TimeUnit.MILLISECONDS); - if (message == null) { - // timed out without messages - return "[]"; - } - - // use 'StringBuilder' to assemble the response -- add the first message - StringBuilder builder = new StringBuilder(); - builder.append("[\"").append(message); - - // add up to '<limit>-1' more messages - for (int i = 1; i < limit; i += 1) { - // fetch the next message -- don't wait if it isn't currently there - message = messages.poll(); - if (message == null) { - // no more currently available - break; - } - builder.append("\",\"").append(message); - } - builder.append("\"]"); - return builder.toString(); - } - } - - /* ============================================================ */ - - /** - * Incoming messages from the caller to the simulator. - */ - @POST - @Path("/events/{topic}") - @Consumes("application/cambria") - @Produces(MediaType.APPLICATION_JSON) - public String send(@PathParam("topic") String topic, - String data) { - logger.info("Send: topic={}", topic); - return Topic.createOrGet(topic).post(data); - } - - /** - * Send messages from the simulator to the caller. - */ - @GET - @Path("/events/{topic}/{group}/{id}") - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.APPLICATION_JSON) - public String receive(@PathParam("topic") String topic, - @PathParam("group") String group, - @PathParam("id") String id, - @QueryParam("timeout") long timeout, - @QueryParam("limit") int limit) - throws InterruptedException { - - logger.info("Receive: topic={}, group={}, id={}, timeout={}, limit={}", - topic, group, id, timeout, limit); - return Topic.createOrGet(topic).get(group, timeout, limit); - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/TargetLockWrapper.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/TargetLockWrapper.java deleted file mode 100644 index ce9f39e0..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/TargetLockWrapper.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import java.io.Serializable; - -/** - * This class provides base classes for accessing the various 'TargetLock' - * classes. There is a separate copy of the 'TargetLock' class for each - * adapter, and this wrapper was created to give them a common interface. - */ -public interface TargetLockWrapper extends Serializable { - /** - * There is a separate copy of 'TargetLock.State' for each adapter -- - * The 'TargetLockWrapper.getState()' maps these into a common - * 'TargetLockWrapper.State' enumeration. - */ - public enum State { - WAITING, ACTIVE, FREE, LOST - } - - /** - * This calls the 'TargetLock.free()' method - * - * @return 'true' if successful, 'false' if it was not locked, or there - * appears to be corruption in 'LocalLocks' tables - */ - public boolean free(); - - /** - * This calls the 'TargetLock.isActive()' method - * - * @return 'true' if the lock is in the ACTIVE state, and 'false' if not - */ - public boolean isActive(); - - /** - * This calls the 'TargetLock.getState()' method - * - * @return the current state of the lock, as a 'TargetLockWrapper.State' - */ - public State getState(); - - /** - * This calls the 'TargetLock.getOwnerKey()' method - * - * @return the owner key field - */ - public String getOwnerKey(); - - /** - * Return the value returned by 'TargetLock.toString()'. - * - * @return the value returned by 'TargetLock.toString()' - */ - public String toString(); - - /* ============================================================ */ - - /** - * This interface mimics the 'LockCallback' interface, with the - * exception that 'TargetLockWrapper' is used as the arguments to the - * callback methods. - */ - public static interface Owner { - /** - * Callback indicates the lock was successful. - * - * @param lock the 'TargetLockWrapper' instance - */ - public void lockAvailable(TargetLockWrapper lock); - - /** - * Callback indicates the lock request has failed. - * - * @param lock the 'TargetLockWrapper' instance - */ - public void lockUnavailable(TargetLockWrapper lock); - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Test1.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Test1.java deleted file mode 100644 index fe525788..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/Test1.java +++ /dev/null @@ -1,916 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.awaitility.Awaitility.await; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.io.Serializable; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import org.awaitility.Durations; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.kie.api.runtime.KieSession; -import org.onap.policy.drools.core.DroolsRunnable; -import org.onap.policy.drools.serverpool.BucketWrapperImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Test1 { - private static Logger logger = LoggerFactory.getLogger(Test1.class); - - // indicates that Drools containers need to be initialized - private static boolean needControllerInit = true; - - private static int initialCount = 0; - - private static int threadList(String header, boolean stackTrace) { - logger.info("***** threadList: {} *****", header); - Thread[] thr = new Thread[1000]; - int count = Thread.enumerate(thr); - - if (count > thr.length) { - count = thr.length; - } - for (int i = 0; i < count; i += 1) { - StringBuilder sb = new StringBuilder(); - sb.append(" ").append(thr[i]); - if (stackTrace) { - for (StackTraceElement ste : thr[i].getStackTrace()) { - sb.append("\n ").append(ste); - } - } - logger.info(sb.toString()); - } - logger.info("***** end threadList: {}, count = {} *****", header, count); - return count; - } - - /** - * Set up environment prior to running tests. - */ - @BeforeClass - public static void init() throws Exception { - initialCount = threadList("BeforeClass", false); - - // create 6 adapters, corresponding to 6 'Server' instances - Adapter.ensureInit(); - - // make sure initialization has completed - long endTime = System.currentTimeMillis() + 60000L; - for (Adapter adapter : Adapter.adapters) { - assertTrue(adapter.toString() + ": Bucket assignments incomplete", - adapter.waitForInit(endTime)); - } - } - - public static boolean verifyComplete() { - return Thread.enumerate(new Thread[initialCount + 1]) == initialCount; - } - - /** - * Clean up after tests have finished. - */ - @AfterClass - public static void finish() throws InterruptedException { - threadList("AfterClass", false); - if (needControllerInit) { - return; - } - // shut down Server Pools and DMAAP Simulator - Adapter.ensureShutdown(); - - // updates for persistence may still be in progress -- wait 5 seconds - threadList("AfterEnsureShutdown", false); - - try { - initialCount = initialCount + 1; // one for await thread - await().atMost(Durations.ONE_MINUTE) - .with().pollInterval(Durations.ONE_SECOND) - .until(() -> verifyComplete()); - } finally { - threadList("AfterSleep", true); - } - - // look at KieSession objects - for (Adapter adapter : Adapter.adapters) { - StringBuilder sb = new StringBuilder(); - sb.append(adapter.toString()) - .append(": ") - .append(adapter.getKieSession().getObjects().size()) - .append(" objects"); - for (Object o : adapter.getKieSession().getObjects()) { - sb.append("\n ").append(o); - } - LinkedBlockingQueue<String> lbq = adapter.notificationQueue(); - if (!lbq.isEmpty()) { - sb.append("\n") - .append(adapter.toString()) - .append(": ") - .append(lbq.size()) - .append(" queued entries"); - for (String string : lbq) { - sb.append("\n ").append(string); - } - } - logger.info(sb.toString()); - } - - // this was used during test debugging to verify that no adjuncts - // were created on the 'null' host -- there shouldn't be any - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bos, true); - new BucketWrapperImpl.Static().dumpAdjuncts(out); - logger.info(out.toString()); - } - - /** - * Initialize all Drools controllers, if needed. - */ - static void ensureControllersInitialized() { - if (needControllerInit) { - needControllerInit = false; - for (Adapter adapter : Adapter.adapters) { - String rval = adapter.createController(); - logger.info("{}: Got the following from PolicyController:\n{}", - adapter, rval); - } - } - } - - /** - * make sure all servers have agreed on a lead server. - */ - @Test - public void checkLeadServer() { - Adapter firstAdapter = Adapter.adapters[0]; - UUID leaderUuid = firstAdapter.getLeader().getUuid(); - for (Adapter adapter : Adapter.adapters) { - UUID uuid = adapter.getLeader().getUuid(); - assertEquals(adapter.toString(), leaderUuid, uuid); - } - } - - /** - * make sure all servers agree on bucket distribution. - */ - @Test - public void startup() throws Exception { - Adapter firstAdapter = Adapter.adapters[0]; - BucketWrapper.Static firstBucketStatic = firstAdapter.getBucketStatic(); - - for (Adapter adapter : Adapter.adapters) { - BucketWrapper.Static bucketStatic = adapter.getBucketStatic(); - if (adapter == firstAdapter) { - // make sure an owner and primary backup have been chosen - // for each bucket (secondary backups aren't implemented yet) - for (int i = 0; i < bucketStatic.getBucketCount(); i += 1) { - BucketWrapper bucket = bucketStatic.getBucket(i); - assertNotNull(bucket.getOwner()); - assertNotNull(bucket.getPrimaryBackup()); - } - } else { - // make sure the bucket assignments are consistent with - // the primary backup - for (int i = 0; i < bucketStatic.getBucketCount(); i += 1) { - BucketWrapper firstBucket = firstBucketStatic.getBucket(i); - BucketWrapper bucket = bucketStatic.getBucket(i); - assertEquals(firstBucket.getOwner().getUuid(), - bucket.getOwner().getUuid()); - assertEquals(firstBucket.getPrimaryBackup().getUuid(), - bucket.getPrimaryBackup().getUuid()); - } - } - } - } - - // test 'TargetLock' - @Test - public void testTargetLock() throws InterruptedException { - // test locks on different hosts - lockTests(Adapter.adapters[5], Adapter.adapters[0]); - - // test locks on the same host - lockTests(Adapter.adapters[2], Adapter.adapters[2]); - - Adapter adapter0 = Adapter.adapters[0]; - Adapter adapter5 = Adapter.adapters[5]; - String ownerKey = adapter0.findKey("owner"); - String key = adapter5.findKey("key"); - LockOwner owner = new LockOwner(); - - // some exceptions - Throwable thrown = catchThrowable(() -> { - adapter0.newTargetLock(null, ownerKey, owner); - }); - assertThat(thrown).isInstanceOf(IllegalArgumentException.class) - .hasNoCause() - .hasMessageContaining("TargetLock: 'key' can't be null"); - - thrown = catchThrowable(() -> { - adapter0.newTargetLock(key, null, owner); - }); - assertThat(thrown).isInstanceOf(IllegalArgumentException.class) - .hasNoCause() - .hasMessageContaining("TargetLock: 'ownerKey' can't be null"); - - thrown = catchThrowable(() -> { - adapter5.newTargetLock(key, ownerKey, owner); - }); - assertThat(thrown).isInstanceOf(IllegalArgumentException.class) - .hasNoCause() - .hasMessageContaining("not currently assigned to this server"); - - thrown = catchThrowable(() -> { - adapter0.newTargetLock(key, ownerKey, null); - }); - assertThat(thrown).isInstanceOf(IllegalArgumentException.class) - .hasNoCause() - .hasMessageContaining("TargetLock: 'owner' can't be null"); - } - - /** - * Run some 'TargetLock' tests. - * - * @param keyAdapter this is the adapter for the key, which determines - * where the server-side data will reside - * @param ownerAdapter this is the adapter associated with the requestor - */ - void lockTests(Adapter keyAdapter, Adapter ownerAdapter) throws InterruptedException { - // choose 'key' and 'ownerKey' values that map to buckets owned - // by their respective adapters - String key = keyAdapter.findKey("key"); - String ownerKey = ownerAdapter.findKey("owner"); - - // this receives and queues callback notifications - LockOwner owner = new LockOwner(); - - // first lock -- should succeed - TargetLockWrapper tl1 = ownerAdapter.newTargetLock(key, ownerKey, owner); - assertLockAvailable(owner, tl1); - //assertArrayEquals(new Object[] {"lockAvailable", tl1}, - // owner.poll(5, TimeUnit.SECONDS)); - assertNull(owner.poll()); - assertTrue(tl1.isActive()); - assertEquals(TargetLockWrapper.State.ACTIVE, tl1.getState()); - assertEquals(ownerKey, tl1.getOwnerKey()); - - // second lock -- should fail (lock in use) - TargetLockWrapper tl2 = - ownerAdapter.newTargetLock(key, ownerKey, owner, false); - assertLockUnavailable(owner, tl2); - - assertNull(owner.poll()); - assertFalse(tl2.isActive()); - assertEquals(TargetLockWrapper.State.FREE, tl2.getState()); - assertEquals(ownerKey, tl2.getOwnerKey()); - - // third and fourth locks -- should wait - TargetLockWrapper tl3 = ownerAdapter.newTargetLock(key, ownerKey, owner); - TargetLockWrapper tl4 = ownerAdapter.newTargetLock(key, ownerKey, owner); - assertNull(owner.poll(5, TimeUnit.SECONDS)); // nothing immediately - assertFalse(tl3.isActive()); - assertFalse(tl4.isActive()); - assertEquals(TargetLockWrapper.State.WAITING, tl3.getState()); - assertEquals(TargetLockWrapper.State.WAITING, tl4.getState()); - - // free third lock before ever getting a callback - assertTrue(tl3.free()); - assertFalse(tl3.isActive()); - assertEquals(TargetLockWrapper.State.FREE, tl3.getState()); - assertFalse(tl3.free()); - - // free first lock - assertTrue(tl1.free()); - assertFalse(tl1.isActive()); - assertEquals(TargetLockWrapper.State.FREE, tl1.getState()); - assertFalse(tl1.free()); // already free - - // fourth lock should be active now (or soon) - assertLockAvailable(owner, tl4); - assertNull(owner.poll()); - assertTrue(tl4.isActive()); - assertEquals(TargetLockWrapper.State.ACTIVE, tl4.getState()); - - // free fourth lock - assertTrue(tl4.free()); - assertFalse(tl4.isActive()); - assertEquals(TargetLockWrapper.State.FREE, tl4.getState()); - } - - /** - * Test sending of intra-server and inter-server messages. - */ - @Test - public void topicSendTests() throws InterruptedException { - ensureControllersInitialized(); - - // sender and receiver are the same - topicSendTest(Adapter.adapters[2], Adapter.adapters[2], false); - - // sender and receiver are different - topicSendTest(Adapter.adapters[5], Adapter.adapters[4], false); - } - - /** - * Send a message from 'sender' to 'receiver' -- the message is delivered - * as an incoming 'TopicListener' event, is processed by - * 'FeatureServerPool.beforeOffer' (PolicyControllerFeatureApi), which - * will route it based upon keyword. At the destination end, it should - * be converted to an instance of 'TestDroolsObject', and inserted into - * the Drools session. The associated Drools rule should fire, and the - * message is placed in the notification queue. The message is then - * retracted, unless the string 'SAVE' appears within the message, which - * is the case if the 'save' parameter is set. - * - * @param sender the adapter associated with the sending end - * @param receiver the adapter associated with the receiving end - * @param save if 'true' the message is not retracted, if 'false' it is - * retracted - */ - String topicSendTest(Adapter sender, Adapter receiver, boolean save) throws InterruptedException { - // generate base message -- include 'SAVE' in the message if 'save' is set - String message = "From " + sender.toString() + " to " - + receiver.toString(); - if (save) { - message += " (SAVE)"; - } - message += ": " + UUID.randomUUID().toString() + "."; - - // add a numeric suffix to the message, such that it will be routed - // to 'receiver' - message = receiver.findKey(message); - - // send the message - sender.sendEvent(message); - - // verify that it has been received - assertEquals(message, - receiver.notificationQueue().poll(60, TimeUnit.SECONDS)); - return message; - } - - /** - * Return the Adapter associated with the current lead server. - * - * @return the Adapter associated with the current lead server - * ('null' if there is no leader) - */ - private Adapter getLeader() { - for (Adapter adapter : Adapter.adapters) { - if (adapter.getLeader() == adapter.getServerStatic().getThisServer()) { - // we have located the leader - return adapter; - } - } - throw new AssertionError(); - } - - /** - * Test migration of sessions from one server to another. - */ - @Test - public void sessionMigrationTest() throws InterruptedException { - ensureControllersInitialized(); - - // select adapters for roles - Adapter sender = Adapter.adapters[1]; - Adapter receiver = Adapter.adapters[3]; - Adapter newReceiver = Adapter.adapters[5]; - - // determine current leader - Adapter leader = getLeader(); - - // send message from 'sender' to 'receiver', and save it - String message = topicSendTest(sender, receiver, true); - - // verify where the bucket is and is not - assertTrue(receiver.getBucketStatic().isKeyOnThisServer(message)); - assertFalse(newReceiver.getBucketStatic().isKeyOnThisServer(message)); - - // move to the new host - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bos, true); - leader.getBucketStatic().moveBucket( - out, receiver.getBucketStatic().bucketNumber(message), - newReceiver.getServerStatic().getThisServer().getUuid().toString()); - logger.info(bos.toString()); - - // poll up to 5 minutes for the bucket to be updated - TestDroolsObject matchingObject = new TestDroolsObject(message); - await().atMost(5, TimeUnit.MINUTES) - .with().pollInterval(Durations.ONE_SECOND) - .until(() -> (new ArrayList<Object>(newReceiver.getKieSession().getObjects()) - .contains(matchingObject))); - - // verify where the bucket is and is not - assertFalse(receiver.getBucketStatic().isKeyOnThisServer(message)); - assertTrue(newReceiver.getBucketStatic().isKeyOnThisServer(message)); - } - - /** - * Test migration of locks from one server to another. - */ - @Test - public void lockMigrationTest() throws InterruptedException { - ensureControllersInitialized(); - - // select adapters for roles -- '*Server' refers to the 'key' end, - // and '*Client' refers to the 'ownerKey' end - final Adapter oldServer = Adapter.adapters[0]; - final Adapter newServer = Adapter.adapters[1]; - final Adapter oldClient = Adapter.adapters[2]; - final Adapter newClient = Adapter.adapters[3]; - - // determine the current leader - final Adapter leader = getLeader(); - - // choose 'key' and 'ownerKey' values associated with - // 'oldServer' and 'oldClient', respectively - String key = oldServer.findKey("key"); - String ownerKey = oldClient.findKey("owner"); - LockOwner owner = new LockOwner(); - - // allocate lock 1 - TargetLockWrapper tl1 = oldClient.newTargetLock(key, ownerKey, owner); - assertLockAvailable(owner, tl1); - - // allocate a lock 2, which should be in the 'WAITING' state - TargetLockWrapper tl2 = oldClient.newTargetLock(key, ownerKey, owner); - assertNull(owner.poll(5, TimeUnit.SECONDS)); // nothing immediately - - // verify lock states - assertEquals(TargetLockWrapper.State.ACTIVE, tl1.getState()); - assertEquals(TargetLockWrapper.State.WAITING, tl2.getState()); - - // verify key buckets (before) - assertTrue(oldServer.getBucketStatic().isKeyOnThisServer(key)); - assertFalse(newServer.getBucketStatic().isKeyOnThisServer(key)); - - // move key buckets to new host (server side) - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - PrintStream out = new PrintStream(bos, true); - leader.getBucketStatic().moveBucket( - out, oldServer.getBucketStatic().bucketNumber(key), - newServer.getServerStatic().getThisServer().getUuid().toString()); - logger.info(bos.toString()); - - logger.debug("lock migration test - before: new isKeyOnThisServer: {}, " - + "old isKeyOnThisServer: {}, time: {}", - newServer.getBucketStatic().isKeyOnThisServer(key), - oldServer.getBucketStatic().isKeyOnThisServer(key), - new SimpleDateFormat("yyyy-MM-dd kk:mm:ss").format(new Date())); - - await().atMost(10000L, TimeUnit.MILLISECONDS).until(() -> - newServer.getBucketStatic().isKeyOnThisServer(key) - && oldServer.getBucketStatic().isKeyOnThisServer(key) == false); - - logger.debug("lock migration test - after : new isKeyOnThisServer: {}, " - + "old isKeyOnThisServer: {}, time: {}", - newServer.getBucketStatic().isKeyOnThisServer(key), - oldServer.getBucketStatic().isKeyOnThisServer(key), - new SimpleDateFormat("yyyy-MM-dd kk:mm:ss").format(new Date())); - - // verify key buckets (after) - assertFalse(oldServer.getBucketStatic().isKeyOnThisServer(key)); - assertTrue(newServer.getBucketStatic().isKeyOnThisServer(key)); - - // we should be able to free lock1 now, and lock2 should go active, - // indicating that the server side is still working - assertTrue(tl1.free()); - - assertLockAvailable(owner, tl2); - assertEquals(TargetLockWrapper.State.ACTIVE, tl2.getState()); - - // create a third lock - TargetLockWrapper tl3 = oldClient.newTargetLock(key, ownerKey, owner); - assertNull(owner.poll(5, TimeUnit.SECONDS)); // nothing immediately - assertEquals(TargetLockWrapper.State.WAITING, tl3.getState()); - - // insert active objects in Drools session, which is about to be moved - // (if we don't do this, the client objects won't be relocated) - oldClient.getKieSession().insert(new KeywordWrapper(ownerKey, "lmt.owner", owner)); - oldClient.getKieSession().insert(new KeywordWrapper(ownerKey, "lmt.tl2", tl2)); - oldClient.getKieSession().insert(new KeywordWrapper(ownerKey, "lmt.tl3", tl3)); - - // dumping out some state information as part of debugging -- - // I see no reason to remove it now - { - bos = new ByteArrayOutputStream(); - out = new PrintStream(bos, true); - out.println("BEFORE: tl2=" + tl2 + "\ntl3=" + tl3); - oldClient.dumpLocks(out, true); - oldClient.getBucketStatic().dumpAdjuncts(out); - logger.debug(bos.toString()); - } - - // don't need these any more -- we will get them back on the new host - tl1 = tl2 = tl3 = null; - owner = null; - - // verify ownerKey buckets (before) - assertTrue(oldClient.getBucketStatic().isKeyOnThisServer(ownerKey)); - assertFalse(newClient.getBucketStatic().isKeyOnThisServer(ownerKey)); - - // move ownerKey buckets to new host (client side) - bos = new ByteArrayOutputStream(); - out = new PrintStream(bos, true); - leader.getBucketStatic().moveBucket( - out, oldClient.getBucketStatic().bucketNumber(ownerKey), - newClient.getServerStatic().getThisServer().getUuid().toString()); - logger.info(bos.toString()); - - logger.debug("lock migration test2 - before: new isKeyOnThisServer: {}, " - + "old isKeyOnThisServer: {}, time: {}", - newClient.getBucketStatic().isKeyOnThisServer(ownerKey), - oldClient.getBucketStatic().isKeyOnThisServer(ownerKey), - new SimpleDateFormat("yyyy-MM-dd kk:mm:ss").format(new Date())); - - await().atMost(Durations.FIVE_SECONDS) - .with().pollInterval(Durations.ONE_HUNDRED_MILLISECONDS) - .until(() -> newClient.getBucketStatic().isKeyOnThisServer(ownerKey) - && oldClient.getBucketStatic().isKeyOnThisServer(ownerKey) == false); - - logger.debug("lock migration test2 - before: new isKeyOnThisServer: {}, " - + "old isKeyOnThisServer: {}, time: {}", - newClient.getBucketStatic().isKeyOnThisServer(ownerKey), - oldClient.getBucketStatic().isKeyOnThisServer(ownerKey), - new SimpleDateFormat("yyyy-MM-dd kk:mm:ss").format(new Date())); - - // verify ownerKey buckets (before) - assertFalse(oldClient.getBucketStatic().isKeyOnThisServer(ownerKey)); - assertTrue(newClient.getBucketStatic().isKeyOnThisServer(ownerKey)); - - // now, we need to locate 'tl2', 'tl3', and 'owner' in Drools memory - await().atMost(Durations.FIVE_SECONDS) - .with().pollInterval(Durations.ONE_SECOND) - .until(() -> newClient.getKieSession() != null); - KieSession kieSession = newClient.getKieSession(); - for (Object obj : new ArrayList<Object>(kieSession.getObjects())) { - if (obj instanceof KeywordWrapper) { - KeywordWrapper kw = (KeywordWrapper) obj; - - if ("lmt.owner".equals(kw.id)) { - owner = kw.getObject(LockOwner.class); - } else if ("lmt.tl2".equals(kw.id)) { - tl2 = kw.getObject(TargetLockWrapper.class); - } else if ("lmt.tl3".equals(kw.id)) { - tl3 = kw.getObject(TargetLockWrapper.class); - } - kieSession.delete(kieSession.getFactHandle(obj)); - } - } - - // make sure we found everything - assertNotNull(tl2); - assertNotNull(tl3); - assertNotNull(owner); - assertFalse(newClient.isForeign(tl2, tl3, owner)); - - // verify the states of 'tl2' and 'tl3' - assertEquals(TargetLockWrapper.State.ACTIVE, tl2.getState()); - assertEquals(TargetLockWrapper.State.WAITING, tl3.getState()); - - // dumping out some state information as part of debugging -- - // I see no reason to remove it now - { - bos = new ByteArrayOutputStream(); - out = new PrintStream(bos, true); - out.println("AFTER: tl2=" + tl2 + "\ntl3=" + tl3); - newClient.dumpLocks(out, true); - newClient.getBucketStatic().dumpAdjuncts(out); - logger.debug(bos.toString()); - } - - // now, we should be able to free 'tl2', and 'tl3' should go active - assertNull(owner.poll(5, TimeUnit.SECONDS)); // nothing immediately - assertTrue(tl2.free()); - - assertLockAvailable(owner, tl3); - assertEquals(TargetLockWrapper.State.ACTIVE, tl3.getState()); - assertTrue(tl3.free()); - } - - private void assertLockAvailable(LockOwner owner, TargetLockWrapper tl) { - AtomicReference<Object[]> objArray = new AtomicReference<>(); - await().atMost(300000, TimeUnit.MILLISECONDS).until(() -> { - objArray.set(owner.poll(5, TimeUnit.SECONDS)); - return objArray.get() != null; - }); - assertArrayEquals(new Object[] {"lockAvailable", tl}, objArray.get()); - } - - private void assertLockUnavailable(LockOwner owner, TargetLockWrapper tl) { - AtomicReference<Object[]> objArray = new AtomicReference<>(); - await().atMost(300000, TimeUnit.MILLISECONDS).until(() -> { - objArray.set(owner.poll(5, TimeUnit.SECONDS)); - return objArray.get() != null; - }); - assertArrayEquals(new Object[] {"lockUnavailable", tl}, objArray.get()); - } - - /** - * Test cleanup of locks that have been abandoned. - */ - @Test - public void abandonedLocks() throws InterruptedException { - // choose adapters - Adapter keyAdapter = Adapter.adapters[3]; - Adapter ownerAdapter = Adapter.adapters[4]; - - // generate compatible keys - String key = keyAdapter.findKey("abandonedLocks.key"); - String ownerKey = ownerAdapter.findKey("abandonedLocks.owner"); - - // receiver of callback notifications - LockOwner owner = new LockOwner(); - - // first lock -- should succeed - TargetLockWrapper tl1 = ownerAdapter.newTargetLock(key, ownerKey, owner); - //assertLockAvailable(owner, tl1); - assertArrayEquals(new Object[] {"lockAvailable", tl1}, - owner.poll(5, TimeUnit.SECONDS)); - - // second lock -- should wait - final TargetLockWrapper tl2 = ownerAdapter.newTargetLock(key, ownerKey, owner); - assertNull(owner.poll(5, TimeUnit.SECONDS)); // nothing immediately - - // abandon first lock, and do a GC cycle -- tl2 should go active - tl1 = null; - System.gc(); - //assertLockAvailable(owner, tl2); - assertArrayEquals(new Object[] {"lockAvailable", tl2}, - owner.poll(5, TimeUnit.SECONDS)); - assertTrue(tl2.isActive()); - assertEquals(TargetLockWrapper.State.ACTIVE, tl2.getState()); - - // free tl2 - assertTrue(tl2.free()); - assertFalse(tl2.isActive()); - assertEquals(TargetLockWrapper.State.FREE, tl2.getState()); - } - - /** - * Test locks within Drools sessions. - */ - @Test - public void locksWithinDrools() throws InterruptedException { - ensureControllersInitialized(); - - // choose adapters - Adapter keyAdapter = Adapter.adapters[3]; - Adapter ownerAdapter = Adapter.adapters[4]; - - // generate compatible keys - final String key = keyAdapter.findKey("locksWithinDrools.key"); - final String ownerKey = ownerAdapter.findKey("locksWithinDrools.owner"); - - // need a 'LockOwner' variant - final LockOwner owner = new LockOwner() { - private static final long serialVersionUID = 1L; - - /** - * {@inheritDoc} - */ - @Override - public void lockAvailable(TargetLockWrapper lock) { - // insert notification in 'LinkedBlockingQueue' - add(new Object[] {"lockAvailable", lock, Thread.currentThread()}); - } - - /** - * {@inheritDoc} - */ - @Override - public void lockUnavailable(TargetLockWrapper lock) { - // insert notification in 'LinkedBlockingQueue' - add(new Object[] {"lockUnavailable", lock, Thread.currentThread()}); - } - }; - - // generate first lock outside of Drools - final TargetLockWrapper tl1 = ownerAdapter.newTargetLock(key, ownerKey, owner); - Object[] response = owner.poll(5, TimeUnit.SECONDS); - assertNotNull(response); - assertEquals(3, response.length); - assertEquals("lockAvailable", response[0]); - assertEquals(tl1, response[1]); - - // now, generate one from within Drools - ownerAdapter.getKieSession().insert(new DroolsRunnable() { - @Override - public void run() { - // create lock, which should block - TargetLockWrapper tl2 = - ownerAdapter.newTargetLock(key, ownerKey, owner); - owner.add(new Object[] {"tl2Data", tl2, Thread.currentThread()}); - } - }); - - // fetch data from Drools thread - response = owner.poll(5, TimeUnit.SECONDS); - assertNotNull(response); - assertEquals(3, response.length); - assertEquals("tl2Data", response[0]); - - TargetLockWrapper tl2 = null; - Thread droolsThread = null; - - if (response[1] instanceof TargetLockWrapper) { - tl2 = (TargetLockWrapper) response[1]; - } - if (response[2] instanceof Thread) { - droolsThread = (Thread) response[2]; - } - - assertNotNull(tl2); - assertNotNull(droolsThread); - - // tl2 should still be waiting - assertNull(owner.poll(5, TimeUnit.SECONDS)); - assertFalse(tl2.isActive()); - assertEquals(TargetLockWrapper.State.WAITING, tl2.getState()); - - // free tl1 - assertTrue(tl1.free()); - - // verify that 'tl2' is now available, - // and the call back ran in the Drools thread - assertArrayEquals(new Object[] {"lockAvailable", tl2, droolsThread}, - owner.poll(5, TimeUnit.SECONDS)); - assertTrue(tl2.isActive()); - assertEquals(TargetLockWrapper.State.ACTIVE, tl2.getState()); - - // free tl2 - assertTrue(tl2.free()); - } - - /** - * Test insertion of objects into Drools memory. - */ - @Test - public void insertDrools() throws InterruptedException { - Adapter adapter1 = Adapter.adapters[1]; - final Adapter adapter2 = Adapter.adapters[2]; - - // check whether we can insert objects locally (adapter1 -> adapter1) - String key1 = adapter1.findKey("insertDrools1-"); - adapter1.insertDrools(new KeywordWrapper(key1, "insertDroolsLocal", null)); - - await().atMost(Durations.TEN_SECONDS) - .with().pollInterval(Durations.ONE_SECOND) - .until(() -> adapter1.getKieSession() != null); - - KieSession kieSession; - boolean found = false; - kieSession = adapter1.getKieSession(); - for (Object obj : new ArrayList<Object>(kieSession.getObjects())) { - if (obj instanceof KeywordWrapper - && "insertDroolsLocal".equals(((KeywordWrapper) obj).id)) { - found = true; - kieSession.delete(kieSession.getFactHandle(obj)); - break; - } - } - assertTrue(found); - - // check whether we can insert objects remotely (adapter1 -> adapter2) - String key2 = adapter2.findKey("insertDrools2-"); - adapter1.insertDrools(new KeywordWrapper(key2, "insertDroolsRemote", null)); - - // it would be nice to test for this, rather than sleep - await().atMost(Durations.FIVE_SECONDS) - .with().pollInterval(Durations.ONE_HUNDRED_MILLISECONDS) - .until(() -> adapter2.getKieSession() != null); - - found = false; - kieSession = adapter2.getKieSession(); - for (Object obj : new ArrayList<Object>(kieSession.getObjects())) { - if (obj instanceof KeywordWrapper - && "insertDroolsRemote".equals(((KeywordWrapper) obj).id)) { - found = true; - kieSession.delete(kieSession.getFactHandle(obj)); - break; - } - } - assertTrue(found); - } - - /* ============================================================ */ - - /** - * This class implements the 'LockCallback' interface, and - * makes callback responses available via a 'LinkedBlockingQueue'. - */ - public static class LockOwner extends LinkedBlockingQueue<Object[]> - implements TargetLockWrapper.Owner, Serializable { - - private static final long serialVersionUID = 1L; - - /** - * Constructor -- initialize the 'LinkedBlockingQueue'. - */ - public LockOwner() { - super(); - } - - /** - * {@inheritDoc} - */ - @Override - public void lockAvailable(TargetLockWrapper lock) { - // insert notification in 'LinkedBlockingQueue' - add(new Object[] {"lockAvailable", lock}); - } - - /** - * {@inheritDoc} - */ - @Override - public void lockUnavailable(TargetLockWrapper lock) { - // insert notification in 'LinkedBlockingQueue' - add(new Object[] {"lockUnavailable", lock}); - } - } - - /* ============================================================ */ - - /** - * This class is used to insert objects in Drools memory to support - * testing. - */ - public static class KeywordWrapper implements Serializable { - private static final long serialVersionUID = 1L; - - // this is the keyword, which determines the associated bucket, - // which then determines when this object is migrated - public String key; - - // this is an identifier, which can be used to select objects - // on the receiving end - public String id; - - // this is the object being wrapped - public Serializable obj; - - /** - * Constructor -- initialize fields. - * - * @param key keyword, which determines the associated bucket - * @param id string identifier, used to match objects from the sending - * to the receiving end - * @param obj the object being wrapped - */ - public KeywordWrapper(String key, String id, Serializable obj) { - this.key = key; - this.id = id; - this.obj = obj; - } - - /** - * This is used to extract objects on the receiving end. If the class - * matches, we get the expected object. If the class does not match, - * we get 'null', and the test should fail. - * - * @param clazz the expected class of the 'obj' field - * @return the object (if 'clazz' matches), 'null' if it does not - */ - public <T> T getObject(Class<T> clazz) { - return clazz.isInstance(obj) ? clazz.cast(obj) : null; - } - } -} diff --git a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/TestDroolsObject.java b/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/TestDroolsObject.java deleted file mode 100644 index a937680f..00000000 --- a/feature-server-pool/src/test/java/org/onap/policy/drools/serverpooltest/TestDroolsObject.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.drools.serverpooltest; - -import java.io.Serializable; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -/** - * Instances of this class can be inserted into a Drools session, and used - * to test things like message routing and bucket migration. - */ -@Getter -@Setter -@ToString -@EqualsAndHashCode -public class TestDroolsObject implements Serializable { - private static final long serialVersionUID = 1L; - - // determines the bucket number - private String key; - - /** - * Constructor - no key specified. - */ - public TestDroolsObject() { - this.key = null; - } - - /** - * Constructor - initialize the key. - * - * @param key key that is hashed to determine the bucket number - */ - public TestDroolsObject(String key) { - this.key = key; - } -} diff --git a/feature-server-pool/src/test/resources/TestController-controller.properties b/feature-server-pool/src/test/resources/TestController-controller.properties deleted file mode 100644 index 7d645588..00000000 --- a/feature-server-pool/src/test/resources/TestController-controller.properties +++ /dev/null @@ -1,13 +0,0 @@ -controller.name=TestController - -persistence.type=auto - -rules.artifactId=drools-artifact1 -rules.groupId=org.onap.policy.drools-pdp -rules.version=1.0.0 - -ueb.source.topics=JUNIT-TEST-TOPIC -ueb.source.topics.JUNIT-TEST-TOPIC.servers=127.0.0.1 -ueb.source.topics.JUNIT-TEST-TOPIC.events=org.onap.policy.drools.serverpooltest.TestDroolsObject -ueb.source.topics.JUNIT-TEST-TOPIC.events.org.onap.policy.drools.serverpooltest.TestDroolsObject.filter= -[?($.key =~ /.*/)]
\ No newline at end of file diff --git a/feature-server-pool/src/test/resources/drools-artifact-1.1/pom.xml b/feature-server-pool/src/test/resources/drools-artifact-1.1/pom.xml deleted file mode 100644 index e747e42b..00000000 --- a/feature-server-pool/src/test/resources/drools-artifact-1.1/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ============LICENSE_START======================================================= - feature-server-pool - ================================================================================ - Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - ================================================================================ - Licensed 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. - ============LICENSE_END========================================================= - --> - -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <groupId>org.onap.policy.drools-pdp</groupId> - <artifactId>drools-artifact1</artifactId> - <version>1.0.0</version> - <description>supports Junit tests in feature-server-pool</description> - -</project> diff --git a/feature-server-pool/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml b/feature-server-pool/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml deleted file mode 100644 index 1e447eb3..00000000 --- a/feature-server-pool/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ============LICENSE_START======================================================= - feature-server-pool - ================================================================================ - Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - ================================================================================ - Licensed 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. - ============LICENSE_END========================================================= - --> -<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> - <kbase name="rules"> - <ksession name="session1"/> - </kbase> -</kmodule> diff --git a/feature-server-pool/src/test/resources/drools-artifact-1.1/src/main/resources/rules.drl b/feature-server-pool/src/test/resources/drools-artifact-1.1/src/main/resources/rules.drl deleted file mode 100644 index 9591dee0..00000000 --- a/feature-server-pool/src/test/resources/drools-artifact-1.1/src/main/resources/rules.drl +++ /dev/null @@ -1,51 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * feature-server-pool - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ -package org.onap.policy.drools.serverpool.test; - -import org.onap.policy.drools.serverpool.AdapterImpl; -import org.onap.policy.drools.serverpooltest.Adapter; -import org.onap.policy.drools.serverpooltest.TestDroolsObject; - -rule "Initialization" - when - then - { - System.out.println("Initialization rule running"); - } -end - -rule "Receive 'TestDroolsObject'" - when - $object : TestDroolsObject() - then - { - Adapter adapter = AdapterImpl.getAdapter(); - String key = $object.getKey(); - System.out.println(adapter.toString() - + ": Received TestDroolsObject - key=" + key); - adapter.notificationQueue().add(key); - if (!key.contains("SAVE")) - { - // 'SAVE' keyword identifies messages that shouldn't be retracted - retract($object); - } - } -end - diff --git a/feature-server-pool/src/test/resources/feature-server-pool-test.properties b/feature-server-pool/src/test/resources/feature-server-pool-test.properties deleted file mode 100644 index 70fed3ff..00000000 --- a/feature-server-pool/src/test/resources/feature-server-pool-test.properties +++ /dev/null @@ -1,142 +0,0 @@ -### -# ============LICENSE_START======================================================= -# feature-server-pool -# ================================================================================ -# Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. -# ================================================================================ -# Licensed 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. -# ============LICENSE_END========================================================= -### - -# The following properties control the IP address and port that a given -# server binds to. The default will bind to all interfaces on the host, -# and choose a port number at random. - -server.pool.server.ipAddress=127.0.0.1 -server.pool.server.port=20000 - -# The following properties determine whether HTTPS is used -- note that HTTPS -# also requires that the 'java.net.ssl.*' parameters in 'system.properties' be -# specified, and the key store and trust store be configured, as appropriate. -server.pool.server.https= -server.pool.server.selfSignedCerts=false - -# The IP address and port that servers on the geo-redundant site -# should use to connect to servers on this site. -server.pool.server.site.ip= -server.pool.server.site.port= - -# A comma-separated list of host names -- if an entry is found that refers -# to an HTTP/HTTPS destination IP address, the host name will used as the -# destination, instead of the IP address -server.pool.server.hostlist= - -# The servers send 'pings' to each other once per main loop cycle. They -# also measure the gap between 'pings' from each server, and calculate -# an allowed time gap based upon this. 'server.pool.server.allowedGap' is the initial -# allowed gap prior to receiving any pings (default=30 seconds), and -# 'server.pool.server.adaptiveGapAdjust' is a value that is added to the calculated -# gap "just in case" (default=5 seconds) - -server.pool.server.allowedGap=30000 -server.pool.server.adaptiveGapAdjust=5000 - -# 'connectTimeout' and 'readTimeout' affect the client end of a REST -# connection (default=10 seconds each) - -server.pool.server.connectTimeout=10000 -server.pool.server.readTimeout=10000 - -# Each server has a thread pool per remote server, which is used when -# sending HTTP REST messages -- the following parameters determine the -# configuration. - -server.pool.server.threads.corePoolSize=5 -server.pool.server.threads.maximumPoolSize=10 -server.pool.server.threads.keepAliveTime=5000 - -# The server pool members use a UEB/DMAAP topic to connect with other -# servers in the pool. The following set of parameters are passed to -# the CambriaClient library, and are used in setting up the consumer and -# publisher ends of the connection. 'discovery.servers' and 'discovery.topic' -# are the minimum values that need to be specified. The last parameter in -# this set, 'discovery.publisherLoopCycleTime' isn't passed to the -# CambriaClient library; instead, it controls how frequently the 'ping' -# messages are sent out on this channel. Note that only the lead server -# keeps this channel open long-term. - -server.pool.discovery.servers=127.0.0.1 -server.pool.discovery.port=3904 -server.pool.discovery.topic=DISCOVERY-TOPIC -server.pool.discovery.username= -server.pool.discovery.password= -server.pool.discovery.https= -server.pool.discovery.apiKey= -server.pool.discovery.apiSecret= -#server.pool.discovery.publisherSocketTimeout=5000 -#server.pool.discovery.consumerSocketTimeout=70000 -server.pool.discovery.fetchTimeout=60000 -server.pool.discovery.fetchLimit=100 -server.pool.discovery.selfSignedCertificates=false -server.pool.discovery.publisherLoopCycleTime=5000 - -# The 'leader.*' parameters affect behavior during an election. The value of -# 'mainLoop.cycle' determines the actual time delay. 'leader.stableIdCycles' -# is the required minimum number of "stable" cycles before voting can start -# (in this case, "stable" means no servers added or failing). Once voting has -# started, "leader.stableVotingCycles' is the minimum number of "stable" -# cycles needed before declaring a winner (in this case, "stable" means no -# votes changing). - -server.pool.leader.stableIdleCycles=5 -server.pool.leader.stableVotingCycles=5 - -# The value of 'mainLoop.cycle' (default = 1 second) determines how frequently -# various events occur, such as the sending of 'ping' messages, and the -# duration of a "cycle" while voting for a lead server. - -server.pool.mainLoop.cycle=1000 - -# 'keyword.path' is used when looking for "keywords" within JSON messages. -# The first keyword located is hashed to determine which bucket to route -# through. - -keyword.path=requestID,CommonHeader.RequestID,body.output.common-header.request-id,result-info.request-id:uuid -# 'keyword.<CLASS-NAME>.lookup' is used to locate "keywords" within objects. -# The 'value' field contains a list of method calls or field names separated -# by '.' that are used to locate the keyword -# (e.g. 'method1().field2.method3()') - -keyword.java.lang.String.lookup=toString() -keyword.org.onap.policy.m2.base.Transaction.lookup=getRequestID() -keyword.org.onap.policy.controlloop.ControlLoopEvent.lookup=requestID -keyword.org.onap.policy.appclcm.LcmRequestWrapper.lookup=getBody().getCommonHeader().getRequestId() -keyword.org.onap.policy.appclcm.LcmResponseWrapper.lookup=getBody().getCommonHeader().getRequestId() -keyword.org.onap.policy.drools.serverpool.TargetLock.lookup=getOwnerKey() -keyword.org.onap.policy.drools.serverpooltest.TestDroolsObject.lookup=getKey() -keyword.org.onap.policy.drools.serverpooltest.Test1$KeywordWrapper.lookup=key - -# The following properties affect distributed 'TargetLock' behavior. -# -# server.pool.lock.ttl - controls how many hops a 'TargetLock' message can take -# server.pool.lock.audit.period - how frequently should the audit run? -# server.pool.lock.audit.gracePeriod - how long to wait after bucket reassignments -# before running the audit again -# server.pool.lock.audit.retryDelay - mismatches can occur due to the transient nature -# of the lock state: this property controls how long to wait before -# trying again - -server.pool.lock.ttl=3 -server.pool.lock.audit.period=300000 -server.pool.lock.audit.gracePeriod=60000 -server.pool.lock.audit.retryDelay=5000
\ No newline at end of file diff --git a/feature-server-pool/src/test/resources/logback-test.xml b/feature-server-pool/src/test/resources/logback-test.xml deleted file mode 100644 index 7df374fb..00000000 --- a/feature-server-pool/src/test/resources/logback-test.xml +++ /dev/null @@ -1,32 +0,0 @@ -<!-- - ============LICENSE_START======================================================= - ONAP - ================================================================================ - Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - ================================================================================ - Licensed 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. - ============LICENSE_END========================================================= - --> - -<!-- Controls the output of logs for JUnit tests --> - -<configuration> - <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%M:%line - %msg%n</pattern> - </encoder> - </appender> - <root level="WARN"> - <appender-ref ref="STDOUT" /> - </root> -</configuration> |