http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridAbstractLifecycleAwareSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridAbstractLifecycleAwareSelfTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridAbstractLifecycleAwareSelfTest.java new file mode 100644 index 0000000..a7c327d --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridAbstractLifecycleAwareSelfTest.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.common; + +import org.apache.ignite.*; +import org.apache.ignite.lifecycle.*; +import org.apache.ignite.resources.*; + +import java.util.*; +import java.util.concurrent.atomic.*; + +/** + * Base class for tests against {@link org.apache.ignite.lifecycle.LifecycleAware} support. + */ +public abstract class GridAbstractLifecycleAwareSelfTest extends GridCommonAbstractTest { + /** */ + protected Collection<TestLifecycleAware> lifecycleAwares = new ArrayList<>(); + + /** + */ + @SuppressWarnings("PublicInnerClass") + public static class TestLifecycleAware implements LifecycleAware { + /** */ + private AtomicInteger startCnt = new AtomicInteger(); + + /** */ + private AtomicInteger stopCnt = new AtomicInteger(); + + /** */ + @IgniteCacheNameResource + private String cacheName; + + /** */ + private final String expCacheName; + + /** + * @param expCacheName Expected injected cache name. + */ + public TestLifecycleAware(String expCacheName) { + this.expCacheName = expCacheName; + } + + /** {@inheritDoc} */ + @Override public void start() { + startCnt.incrementAndGet(); + + assertEquals("Unexpected cache name for " + this, expCacheName, cacheName); + } + + /** {@inheritDoc} */ + @Override public void stop() { + stopCnt.incrementAndGet(); + } + + /** + * @return Number of times {@link org.apache.ignite.lifecycle.LifecycleAware#start} was called. + */ + public int startCount() { + return startCnt.get(); + } + + /** + * @return Number of times {@link org.apache.ignite.lifecycle.LifecycleAware#stop} was called. + */ + public int stopCount() { + return stopCnt.get(); + } + + /** + * @param cacheName Cache name. + */ + public void cacheName(String cacheName) { + this.cacheName = cacheName; + } + } + + /** + * After grid start callback. + * @param ignite Grid. + */ + protected void afterGridStart(Ignite ignite) { + // No-op. + } + + /** + * @throws Exception If failed. + */ + public void testLifecycleAware() throws Exception { + Ignite ignite = startGrid(); + + afterGridStart(ignite); + + assertFalse(lifecycleAwares.isEmpty()); + + for (TestLifecycleAware lifecycleAware : lifecycleAwares) { + assertEquals("Unexpected start count for " + lifecycleAware, 1, lifecycleAware.startCount()); + assertEquals("Unexpected stop count for " + lifecycleAware, 0, lifecycleAware.stopCount()); + } + + try { + stopGrid(); + + for (TestLifecycleAware lifecycleAware : lifecycleAwares) { + assertEquals("Unexpected start count for " + lifecycleAware, 1, lifecycleAware.startCount()); + assertEquals("Unexpected stop count for " + lifecycleAware, 1, lifecycleAware.stopCount()); + } + } + finally { + lifecycleAwares.clear(); + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java new file mode 100644 index 0000000..9c0f6c9 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java @@ -0,0 +1,676 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.common; + +import org.apache.ignite.*; +import org.apache.ignite.cache.*; +import org.apache.ignite.cache.affinity.*; +import org.apache.ignite.cluster.*; +import org.apache.ignite.compute.*; +import org.apache.ignite.configuration.*; +import org.apache.ignite.events.*; +import org.apache.ignite.internal.*; +import org.apache.ignite.lang.*; +import org.apache.ignite.internal.processors.cache.distributed.dht.*; +import org.apache.ignite.internal.processors.cache.distributed.dht.colocated.*; +import org.apache.ignite.internal.processors.cache.distributed.near.*; +import org.apache.ignite.internal.processors.cache.local.*; +import org.apache.ignite.internal.util.typedef.*; +import org.apache.ignite.internal.util.typedef.internal.*; +import org.apache.ignite.testframework.*; +import org.apache.ignite.testframework.junits.*; +import org.jetbrains.annotations.*; + +import javax.net.ssl.*; +import java.util.*; + +import static org.apache.ignite.internal.processors.cache.GridCacheUtils.*; +import static org.apache.ignite.cache.GridCacheMode.*; +import static org.apache.ignite.cache.GridCachePreloadMode.*; + +/** + * Super class for all common tests. + */ +public abstract class GridCommonAbstractTest extends GridAbstractTest { + /** + * @param startGrid If {@code true}, then grid node will be auto-started. + */ + protected GridCommonAbstractTest(boolean startGrid) { + super(startGrid); + } + + /** */ + protected GridCommonAbstractTest() { + super(false); + } + + /** + * @param idx Grid index. + * @return Cache. + */ + protected <K, V> GridCache<K, V> cache(int idx) { + return grid(idx).cachex(); + } + + /** + * @param idx Grid index. + * @return Cache. + */ + protected <K, V> IgniteCache<K, V> jcache(int idx) { + return grid(idx).jcache(null); + } + + /** + * @param idx Grid index. + * @param name Cache name. + * @return Cache. + */ + protected <K, V> GridCache<K, V> cache(int idx, String name) { + return grid(idx).cachex(name); + } + + /** + * @return Cache. + */ + protected <K, V> GridCache<K, V> cache() { + return grid().cachex(); + } + + /** + * @return Cache. + */ + protected <K, V> IgniteCache<K, V> jcache() { + return grid().jcache(null); + } + + /** + * @return Cache. + */ + protected <K, V> GridLocalCache<K, V> local() { + return (GridLocalCache<K, V>)((GridKernal)grid()).<K, V>internalCache(); + } + + /** + * @param cache Cache. + * @return DHT cache. + */ + protected static <K, V> GridDhtCacheAdapter<K, V> dht(GridCacheProjection<K,V> cache) { + return nearEnabled(cache) ? near(cache).dht() : + ((GridKernal)cache.gridProjection().ignite()).<K, V>internalCache(cache.name()).context().dht(); + } + + /** + * @return DHT cache. + */ + protected <K, V> GridDhtCacheAdapter<K, V> dht() { + return this.<K, V>near().dht(); + } + + /** + * @param idx Grid index. + * @return DHT cache. + */ + protected <K, V> GridDhtCacheAdapter<K, V> dht(int idx) { + return this.<K, V>near(idx).dht(); + } + + /** + * @param idx Grid index. + * @param cache Cache name. + * @return DHT cache. + */ + protected <K, V> GridDhtCacheAdapter<K, V> dht(int idx, String cache) { + return this.<K, V>near(idx, cache).dht(); + } + + /** + * @param idx Grid index. + * @param cache Cache name. + * @return Colocated cache. + */ + protected <K, V> GridDhtColocatedCache<K, V> colocated(int idx, String cache) { + return (GridDhtColocatedCache<K, V>)((GridKernal)grid(idx)).internalCache(cache); + } + + /** + * @param cache Cache. + * @return {@code True} if near cache is enabled. + */ + protected static <K, V> boolean nearEnabled(GridCacheProjection<K,V> cache) { + CacheConfiguration cfg = ((GridKernal)cache.gridProjection().ignite()). + <K, V>internalCache(cache.name()).context().config(); + + return isNearEnabled(cfg); + } + + /** + * @param cache Cache. + * @return Near cache. + */ + protected static <K, V> GridNearCacheAdapter<K, V> near(GridCacheProjection<K,V> cache) { + return ((GridKernal)cache.gridProjection().ignite()).<K, V>internalCache(cache.name()).context().near(); + } + + /** + * @param cache Cache. + * @return Colocated cache. + */ + protected static <K, V> GridDhtColocatedCache<K, V> colocated(GridCacheProjection<K,V> cache) { + return ((GridKernal)cache.gridProjection().ignite()).<K, V>internalCache(cache.name()).context().colocated(); + } + + /** + * @return Near cache. + */ + protected <K, V> GridNearCacheAdapter<K, V> near() { + return ((GridKernal)grid()).<K, V>internalCache().context().near(); + } + + /** + * @param idx Grid index. + * @return Near cache. + */ + protected <K, V> GridNearCacheAdapter<K, V> near(int idx) { + return ((GridKernal)grid(idx)).<K, V>internalCache().context().near(); + } + + /** + * @param idx Grid index. + * @return Colocated cache. + */ + protected <K, V> GridDhtColocatedCache<K, V> colocated(int idx) { + return (GridDhtColocatedCache<K, V>)((GridKernal)grid(idx)).<K, V>internalCache(); + } + + /** + * @param idx Grid index. + * @param cache Cache name. + * @return Near cache. + */ + protected <K, V> GridNearCacheAdapter<K, V> near(int idx, String cache) { + return ((GridKernal)grid(idx)).<K, V>internalCache(cache).context().near(); + } + + /** {@inheritDoc} */ + @Override protected final boolean isJunitFrameworkClass() { + return true; + } + + /** {@inheritDoc} */ + @Override protected final void setUp() throws Exception { + // Disable SSL hostname verifier. + HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { + @Override public boolean verify(String s, SSLSession sslSes) { + return true; + } + }); + + getTestCounters().incrementStarted(); + + super.setUp(); + } + + /** {@inheritDoc} */ + @Override protected final void tearDown() throws Exception { + getTestCounters().incrementStopped(); + + super.tearDown(); + } + + /** {@inheritDoc} */ + @Override protected final Ignite startGridsMultiThreaded(int cnt) throws Exception { + Ignite g = super.startGridsMultiThreaded(cnt); + + awaitPartitionMapExchange(); + + return g; + } + + /** + * @throws InterruptedException If interrupted. + */ + @SuppressWarnings("BusyWait") + protected void awaitPartitionMapExchange() throws InterruptedException { + for (Ignite g : G.allGrids()) { + for (GridCache<?, ?> c : ((GridEx)g).cachesx()) { + CacheConfiguration cfg = c.configuration(); + + if (cfg.getCacheMode() == PARTITIONED && cfg.getPreloadMode() != NONE && g.cluster().nodes().size() > 1) { + GridCacheAffinityFunction aff = cfg.getAffinity(); + + GridDhtCacheAdapter<?, ?> dht = dht(c); + + GridDhtPartitionTopology<?, ?> top = dht.topology(); + + for (int p = 0; p < aff.partitions(); p++) { + long start = 0; + + for (int i = 0; ; i++) { + // Must map on updated version of topology. + Collection<ClusterNode> affNodes = c.affinity().mapPartitionToPrimaryAndBackups(p); + + int exp = affNodes.size(); + + Collection<ClusterNode> owners = top.nodes(p, -1); + + int actual = owners.size(); + + if (affNodes.size() != owners.size() || !affNodes.containsAll(owners)) { + LT.warn(log(), null, "Waiting for topology map update [grid=" + g.name() + + ", p=" + p + ", nodes=" + exp + ", owners=" + actual + + ", affNodes=" + affNodes + ", owners=" + owners + + ", locNode=" + g.cluster().localNode().id() + ']'); + + if (i == 0) + start = System.currentTimeMillis(); + + Thread.sleep(200); // Busy wait. + + continue; + } + + if (i > 0) + log().warning("Finished waiting for topology map update [grid=" + g.name() + + ", p=" + p + ", duration=" + (System.currentTimeMillis() - start) + "ms]"); + + break; + } + } + } + } + } + } + + /** + * @param cache Cache. + * @return Key for which given cache is primary. + * @throws IgniteCheckedException If failed. + */ + protected Integer primaryKey(GridCacheProjection<?, ?> cache) + throws IgniteCheckedException { + return primaryKeys(cache, 1, 1).get(0); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @return Collection of keys for which given cache is primary. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> primaryKeys(GridCacheProjection<?, ?> cache, int cnt) + throws IgniteCheckedException { + return primaryKeys(cache, cnt, 1); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is primary. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> primaryKeys(GridCacheProjection<?, ?> cache, int cnt, int startFrom) + throws IgniteCheckedException { + assert cnt > 0 : cnt; + + List<Integer> found = new ArrayList<>(cnt); + + ClusterNode locNode = cache.gridProjection().ignite().cluster().localNode(); + + GridCacheAffinity<Integer> aff = cache.<Integer, Object>cache().affinity(); + + for (int i = startFrom; i < startFrom + 100_000; i++) { + Integer key = i; + + if (aff.isPrimary(locNode, key)) { + found.add(key); + + if (found.size() == cnt) + return found; + } + } + + throw new IgniteCheckedException("Unable to find " + cnt + " keys as primary for cache."); + } + + /** + * @param cache Cache. + * @return Key for which given cache is backup. + * @throws IgniteCheckedException If failed. + */ + protected Integer backupKey(GridCacheProjection<?, ?> cache) + throws IgniteCheckedException { + return backupKeys(cache, 1, 1).get(0); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @return Collection of keys for which given cache is backup. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> backupKeys(GridCacheProjection<?, ?> cache, int cnt) + throws IgniteCheckedException { + return backupKeys(cache, cnt, 1); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is backup. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> backupKeys(GridCacheProjection<?, ?> cache, int cnt, int startFrom) + throws IgniteCheckedException { + assert cnt > 0 : cnt; + + List<Integer> found = new ArrayList<>(cnt); + + ClusterNode locNode = cache.gridProjection().ignite().cluster().localNode(); + + GridCacheAffinity<Integer> aff = cache.<Integer, Object>cache().affinity(); + + for (int i = startFrom; i < startFrom + 100_000; i++) { + Integer key = i; + + if (aff.isBackup(locNode, key)) { + found.add(key); + + if (found.size() == cnt) + return found; + } + } + + throw new IgniteCheckedException("Unable to find " + cnt + " keys as backup for cache."); + } + + /** + * @param cache Cache. + * @return Keys for which given cache is neither primary nor backup. + * @throws IgniteCheckedException If failed. + */ + protected Integer nearKey(GridCacheProjection<?, ?> cache) + throws IgniteCheckedException { + return nearKeys(cache, 1, 1).get(0); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @return Collection of keys for which given cache is neither primary nor backup. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> nearKeys(GridCacheProjection<?, ?> cache, int cnt) + throws IgniteCheckedException { + return nearKeys(cache, cnt, 1); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is neither primary nor backup. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> nearKeys(GridCacheProjection<?, ?> cache, int cnt, int startFrom) + throws IgniteCheckedException { + assert cnt > 0 : cnt; + + List<Integer> found = new ArrayList<>(cnt); + + ClusterNode locNode = cache.gridProjection().ignite().cluster().localNode(); + + GridCacheAffinity<Integer> aff = cache.<Integer, Object>cache().affinity(); + + for (int i = startFrom; i < startFrom + 100_000; i++) { + Integer key = i; + + if (!aff.isPrimaryOrBackup(locNode, key)) { + found.add(key); + + if (found.size() == cnt) + return found; + } + } + + throw new IgniteCheckedException("Unable to find " + cnt + " keys as backup for cache."); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is primary. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> primaryKeys(IgniteCache<?, ?> cache, int cnt, int startFrom) + throws IgniteCheckedException { + GridCacheProjection<?, ?> prj = GridTestUtils.getFieldValue(cache, "delegate"); + + return primaryKeys(prj, cnt, startFrom); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is backup. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> backupKeys(IgniteCache<?, ?> cache, int cnt, int startFrom) + throws IgniteCheckedException { + GridCacheProjection<?, ?> prj = GridTestUtils.getFieldValue(cache, "delegate"); + + return backupKeys(prj, cnt, startFrom); + } + + /** + * @param cache Cache. + * @param cnt Keys count. + * @param startFrom Start value for keys search. + * @return Collection of keys for which given cache is neither primary nor backup. + * @throws IgniteCheckedException If failed. + */ + protected List<Integer> nearKeys(IgniteCache<?, ?> cache, int cnt, int startFrom) + throws IgniteCheckedException { + GridCacheProjection<?, ?> prj = GridTestUtils.getFieldValue(cache, "delegate"); + + return nearKeys(prj, cnt, startFrom); + } + + /** + * @param key Key. + * @param cacheName Cache name. + * @return Cache. + */ + protected <K, V> IgniteCache<K, V> primaryCache(Object key, @Nullable String cacheName) { + ClusterNode node = grid(0).cache(cacheName).affinity().mapKeyToNode(key); + + assertNotNull(node); + + return grid((String)node.attribute(GridNodeAttributes.ATTR_GRID_NAME)).jcache(cacheName); + } + + /** + * @param cache Cache. + * @return Collection of keys for which given cache is primary. + * @throws IgniteCheckedException If failed. + */ + protected Integer primaryKey(IgniteCache<?, ?> cache) + throws IgniteCheckedException { + GridCacheProjection<?, ?> prj = GridTestUtils.getFieldValue(cache, "delegate"); + + return primaryKey(prj); + } + + /** + * @param cache Cache. + * @return Keys for which given cache is backup. + * @throws IgniteCheckedException If failed. + */ + protected Integer backupKey(IgniteCache<?, ?> cache) + throws IgniteCheckedException { + GridCacheProjection<?, ?> prj = GridTestUtils.getFieldValue(cache, "delegate"); + + return backupKey(prj); + } + + /** + * @param cache Cache. + * @return Key for which given cache is neither primary nor backup. + * @throws IgniteCheckedException If failed. + */ + protected Integer nearKey(IgniteCache<?, ?> cache) + throws IgniteCheckedException { + GridCacheProjection<?, ?> prj = GridTestUtils.getFieldValue(cache, "delegate"); + + return nearKey(prj); + } + + /** + * @param comp Compute. + * @param task Task. + * @param arg Task argument. + * @return Task future. + * @throws IgniteCheckedException If failed. + */ + protected <R> ComputeTaskFuture<R> executeAsync(IgniteCompute comp, ComputeTask task, @Nullable Object arg) + throws IgniteCheckedException { + comp = comp.enableAsync(); + + assertNull(comp.execute(task, arg)); + + ComputeTaskFuture<R> fut = comp.future(); + + assertNotNull(fut); + + return fut; + } + + /** + * @param comp Compute. + * @param taskName Task name. + * @param arg Task argument. + * @return Task future. + * @throws IgniteCheckedException If failed. + */ + protected <R> ComputeTaskFuture<R> executeAsync(IgniteCompute comp, String taskName, @Nullable Object arg) + throws IgniteCheckedException { + comp = comp.enableAsync(); + + assertNull(comp.execute(taskName, arg)); + + ComputeTaskFuture<R> fut = comp.future(); + + assertNotNull(fut); + + return fut; + } + + /** + * @param comp Compute. + * @param taskCls Task class. + * @param arg Task argument. + * @return Task future. + * @throws IgniteCheckedException If failed. + */ + @SuppressWarnings("unchecked") + protected <R> ComputeTaskFuture<R> executeAsync(IgniteCompute comp, Class taskCls, @Nullable Object arg) + throws IgniteCheckedException { + comp = comp.enableAsync(); + + assertNull(comp.execute(taskCls, arg)); + + ComputeTaskFuture<R> fut = comp.future(); + + assertNotNull(fut); + + return fut; + } + + /** + * @param evts Events. + * @param filter Filter. + * @param types Events types. + * @return Future. + * @throws IgniteCheckedException If failed. + */ + protected <T extends IgniteEvent> IgniteFuture<T> waitForLocalEvent(IgniteEvents evts, + @Nullable IgnitePredicate<T> filter, @Nullable int... types) throws IgniteCheckedException { + evts = evts.enableAsync(); + + assertTrue(evts.isAsync()); + + assertNull(evts.waitForLocal(filter, types)); + + IgniteFuture<T> fut = evts.future(); + + assertNotNull(fut); + + return fut; + } + + /** + * @param ignite Grid. + * @return {@link org.apache.ignite.IgniteCompute} for given grid's local node. + */ + protected IgniteCompute forLocal(Ignite ignite) { + return ignite.compute(ignite.cluster().forLocal()); + } + + /** + * @param prj Projection. + * @return {@link org.apache.ignite.IgniteCompute} for given projection. + */ + protected IgniteCompute compute(ClusterGroup prj) { + return prj.ignite().compute(prj); + } + + /** + * @param prj Projection. + * @return {@link org.apache.ignite.IgniteMessaging} for given projection. + */ + protected IgniteMessaging message(ClusterGroup prj) { + return prj.ignite().message(prj); + } + + /** + * @param prj Projection. + * @return {@link org.apache.ignite.IgniteMessaging} for given projection. + */ + protected IgniteEvents events(ClusterGroup prj) { + return prj.ignite().events(prj); + } + + /** + * @param cfg Configuration. + * @param cacheName Cache name. + * @return Cache configuration. + */ + protected CacheConfiguration cacheConfiguration(IgniteConfiguration cfg, String cacheName) { + for (CacheConfiguration ccfg : cfg.getCacheConfiguration()) { + if (F.eq(cacheName, ccfg.getName())) + return ccfg; + } + + fail("Failed to find cache configuration for cache: " + cacheName); + + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonTest.java new file mode 100644 index 0000000..6553ba2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonTest.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.common; + +import java.lang.annotation.*; + +/** + * Base class for all tests. + */ +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface GridCommonTest { + /** + * Optional group this test belongs to. + * + * @return Test group. + */ + public String group() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/package.html ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/package.html b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/package.html new file mode 100644 index 0000000..1f85ff2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/package.html @@ -0,0 +1,23 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<body> + <!-- Package description. --> + Contains internal tests or test related classes and interfaces. +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridLog4jRollingFileAppender.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridLog4jRollingFileAppender.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridLog4jRollingFileAppender.java new file mode 100644 index 0000000..7be2574 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridLog4jRollingFileAppender.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.logger; + +import org.apache.ignite.*; +import org.apache.ignite.logger.*; +import org.apache.log4j.*; +import org.apache.ignite.internal.util.typedef.internal.*; + +import java.io.*; +import java.util.*; + +/** + * Log4J {@link org.apache.log4j.RollingFileAppender} with added support for grid node IDs. + */ +public class GridLog4jRollingFileAppender extends RollingFileAppender implements IgniteLoggerNodeIdAware { + /** Node ID. */ + private UUID nodeId; + + /** Basic log file name. */ + private String baseFileName; + + /** + * Default constructor (does not do anything). + */ + public GridLog4jRollingFileAppender() { + init(); + } + + /** + * Instantiate a FileAppender with given parameters. + * + * @param layout Layout. + * @param filename File name. + * @throws java.io.IOException If failed. + */ + public GridLog4jRollingFileAppender(Layout layout, String filename) throws IOException { + super(layout, filename); + + init(); + } + + /** + * Instantiate a FileAppender with given parameters. + * + * @param layout Layout. + * @param filename File name. + * @param append Append flag. + * @throws java.io.IOException If failed. + */ + public GridLog4jRollingFileAppender(Layout layout, String filename, boolean append) throws IOException { + super(layout, filename, append); + + init(); + } + + /** + * Initializes appender. + */ + private void init() { + GridTestLog4jLogger.addAppender(this); + } + + /** {@inheritDoc} */ + @SuppressWarnings("NonPrivateFieldAccessedInSynchronizedContext") + @Override public synchronized void setNodeId(UUID nodeId) { + A.notNull(nodeId, "nodeId"); + + this.nodeId = nodeId; + + if (fileName != null) { // fileName could be null if GRIDGAIN_HOME is not defined. + if (baseFileName == null) + baseFileName = fileName; + + fileName = U.nodeIdLogFileName(nodeId, baseFileName); + } + else { + String tmpDir = IgniteSystemProperties.getString("java.io.tmpdir"); + + if (tmpDir != null) { + baseFileName = new File(tmpDir, "gridgain.log").getAbsolutePath(); + + fileName = U.nodeIdLogFileName(nodeId, baseFileName); + } + } + } + + /** {@inheritDoc} */ + @Override public synchronized UUID getNodeId() { + return nodeId; + } + + /** {@inheritDoc} */ + @Override public synchronized void setFile(String fileName, boolean fileAppend, boolean bufIO, int bufSize) + throws IOException { + if (nodeId != null) + super.setFile(fileName, fileAppend, bufIO, bufSize); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridTestLog4jLogger.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridTestLog4jLogger.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridTestLog4jLogger.java new file mode 100644 index 0000000..4c27791 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/logger/GridTestLog4jLogger.java @@ -0,0 +1,514 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.logger; + +import org.apache.ignite.*; +import org.apache.ignite.internal.util.*; +import org.apache.ignite.lang.*; +import org.apache.ignite.logger.*; +import org.apache.log4j.*; +import org.apache.log4j.varia.*; +import org.apache.log4j.xml.*; +import org.apache.ignite.internal.util.tostring.*; +import org.apache.ignite.internal.util.typedef.*; +import org.apache.ignite.internal.util.typedef.internal.*; +import org.jetbrains.annotations.*; + +import java.io.*; +import java.net.*; +import java.util.*; + +import static org.apache.ignite.IgniteSystemProperties.*; + +/** + * Log4j-based implementation for logging. This logger should be used + * by loaders that have prefer <a target=_new href="http://logging.apache.org/log4j/docs/">log4j</a>-based logging. + * <p> + * Here is a typical example of configuring log4j logger in GridGain configuration file: + * <pre name="code" class="xml"> + * <property name="gridLogger"> + * <bean class="org.gridgain.grid.logger.log4j.GridLog4jLogger"> + * <constructor-arg type="java.lang.String" value="config/gridgain-log4j.xml"/> + * </bean> + * </property> + * </pre> + * and from your code: + * <pre name="code" class="java"> + * GridConfiguration cfg = new GridConfiguration(); + * ... + * URL xml = U.resolveGridGainUrl("config/custom-log4j.xml"); + * GridLogger log = new GridLog4jLogger(xml); + * ... + * cfg.setGridLogger(log); + * </pre> + * + * Please take a look at <a target=_new href="http://logging.apache.org/log4j/1.2/index.html>Apache Log4j 1.2</a> + * for additional information. + * <p> + * It's recommended to use GridGain logger injection instead of using/instantiating + * logger in your task/job code. See {@link org.apache.ignite.resources.IgniteLoggerResource} annotation about logger + * injection. + */ +public class GridTestLog4jLogger implements IgniteLogger, IgniteLoggerNodeIdAware { + /** */ + private static final long serialVersionUID = 0L; + + /** Appenders. */ + private static Collection<FileAppender> fileAppenders = new GridConcurrentHashSet<>(); + + /** */ + private static volatile boolean inited; + + /** */ + private static volatile boolean quiet0; + + /** */ + private static final Object mux = new Object(); + + /** Logger implementation. */ + @GridToStringExclude + @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") + private Logger impl; + + /** Path to configuration file. */ + private final String path; + + /** Quiet flag. */ + private final boolean quiet; + + /** Node ID. */ + private UUID nodeId; + + /** + * Creates new logger and automatically detects if root logger already + * has appenders configured. If it does not, the root logger will be + * configured with default appender (analogous to calling + * {@link #GridTestLog4jLogger(boolean) GridLog4jLogger(boolean)} + * with parameter {@code true}, otherwise, existing appenders will be used (analogous + * to calling {@link #GridTestLog4jLogger(boolean) GridLog4jLogger(boolean)} + * with parameter {@code false}). + */ + public GridTestLog4jLogger() { + this(!isConfigured()); + } + + /** + * Creates new logger. If initialize parameter is {@code true} the Log4j + * logger will be initialized with default console appender and {@code INFO} + * log level. + * + * @param init If {@code true}, then a default console appender with + * following pattern layout will be created: {@code %d{ABSOLUTE} %-5p [%c{1}] %m%n}. + * If {@code false}, then no implicit initialization will take place, + * and {@code Log4j} should be configured prior to calling this + * constructor. + */ + public GridTestLog4jLogger(boolean init) { + impl = Logger.getRootLogger(); + + if (init) { + // Implementation has already been inited, passing NULL. + addConsoleAppenderIfNeeded(Level.INFO, null); + + quiet = quiet0; + } + else + quiet = true; + + path = null; + } + + /** + * Creates new logger with given implementation. + * + * @param impl Log4j implementation to use. + */ + public GridTestLog4jLogger(final Logger impl) { + assert impl != null; + + path = null; + + addConsoleAppenderIfNeeded(null, new C1<Boolean, Logger>() { + @Override public Logger apply(Boolean init) { + return impl; + } + }); + + quiet = quiet0; + } + + /** + * Creates new logger with given configuration {@code path}. + * + * @param path Path to log4j configuration XML file. + * @throws IgniteCheckedException Thrown in case logger can't be created. + */ + public GridTestLog4jLogger(String path) throws IgniteCheckedException { + if (path == null) + throw new IgniteCheckedException("Configuration XML file for Log4j must be specified."); + + this.path = path; + + final URL cfgUrl = U.resolveGridGainUrl(path); + + if (cfgUrl == null) + throw new IgniteCheckedException("Log4j configuration path was not found: " + path); + + addConsoleAppenderIfNeeded(null, new C1<Boolean, Logger>() { + @Override public Logger apply(Boolean init) { + if (init) + DOMConfigurator.configure(cfgUrl); + + return Logger.getRootLogger(); + } + }); + + quiet = quiet0; + } + + /** + * Creates new logger with given configuration {@code cfgFile}. + * + * @param cfgFile Log4j configuration XML file. + * @throws IgniteCheckedException Thrown in case logger can't be created. + */ + public GridTestLog4jLogger(File cfgFile) throws IgniteCheckedException { + if (cfgFile == null) + throw new IgniteCheckedException("Configuration XML file for Log4j must be specified."); + + if (!cfgFile.exists() || cfgFile.isDirectory()) + throw new IgniteCheckedException("Log4j configuration path was not found or is a directory: " + cfgFile); + + path = cfgFile.getAbsolutePath(); + + addConsoleAppenderIfNeeded(null, new C1<Boolean, Logger>() { + @Override public Logger apply(Boolean init) { + if (init) + DOMConfigurator.configure(path); + + return Logger.getRootLogger(); + } + }); + + quiet = quiet0; + } + + /** + * Creates new logger with given configuration {@code cfgUrl}. + * + * @param cfgUrl URL for Log4j configuration XML file. + * @throws IgniteCheckedException Thrown in case logger can't be created. + */ + public GridTestLog4jLogger(final URL cfgUrl) throws IgniteCheckedException { + if (cfgUrl == null) + throw new IgniteCheckedException("Configuration XML file for Log4j must be specified."); + + path = null; + + addConsoleAppenderIfNeeded(null, new C1<Boolean, Logger>() { + @Override public Logger apply(Boolean init) { + if (init) + DOMConfigurator.configure(cfgUrl); + + return Logger.getRootLogger(); + } + }); + + quiet = quiet0; + } + + /** + * Checks if Log4j is already configured within this VM or not. + * + * @return {@code True} if log4j was already configured, {@code false} otherwise. + */ + public static boolean isConfigured() { + return Logger.getRootLogger().getAllAppenders().hasMoreElements(); + } + + /** + * Sets level for internal log4j implementation. + * + * @param level Log level to set. + */ + public void setLevel(Level level) { + impl.setLevel(level); + } + + /** {@inheritDoc} */ + @Nullable @Override public String fileName() { + FileAppender fapp = F.first(fileAppenders); + + return fapp != null ? fapp.getFile() : null; + } + + /** + * Adds console appender when needed with some default logging settings. + * + * @param logLevel Optional log level. + * @param implInitC Optional log implementation init closure. + */ + private void addConsoleAppenderIfNeeded(@Nullable Level logLevel, + @Nullable IgniteClosure<Boolean, Logger> implInitC) { + if (inited) { + if (implInitC != null) + // Do not init. + impl = implInitC.apply(false); + + return; + } + + synchronized (mux) { + if (inited) { + if (implInitC != null) + // Do not init. + impl = implInitC.apply(false); + + return; + } + + if (implInitC != null) + // Init logger impl. + impl = implInitC.apply(true); + + boolean quiet = Boolean.valueOf(System.getProperty(GG_QUIET, "true")); + + boolean consoleAppenderFound = false; + Category rootCategory = null; + ConsoleAppender errAppender = null; + + for (Category l = impl; l != null; ) { + if (!consoleAppenderFound) { + for (Enumeration appenders = l.getAllAppenders(); appenders.hasMoreElements(); ) { + Appender appender = (Appender)appenders.nextElement(); + + if (appender instanceof ConsoleAppender) { + if ("CONSOLE_ERR".equals(appender.getName())) { + // Treat CONSOLE_ERR appender as a system one and don't count it. + errAppender = (ConsoleAppender)appender; + + continue; + } + + consoleAppenderFound = true; + + break; + } + } + } + + if (l.getParent() == null) { + rootCategory = l; + + break; + } + else + l = l.getParent(); + } + + if (consoleAppenderFound && quiet) + // User configured console appender, but log is quiet. + quiet = false; + + if (!consoleAppenderFound && !quiet && Boolean.valueOf(System.getProperty(GG_CONSOLE_APPENDER, "true"))) { + // Console appender not found => we've looked through all categories up to root. + assert rootCategory != null; + + // User launched gridgain in verbose mode and did not add console appender with INFO level + // to configuration and did not set GG_CONSOLE_APPENDER to false. + if (errAppender != null) { + rootCategory.addAppender(createConsoleAppender(Level.INFO)); + + if (errAppender.getThreshold() == Level.ERROR) + errAppender.setThreshold(Level.WARN); + } + else + // No error console appender => create console appender with no level limit. + rootCategory.addAppender(createConsoleAppender(Level.OFF)); + + if (logLevel != null) + impl.setLevel(logLevel); + } + + quiet0 = quiet; + inited = true; + } + } + + /** + * Creates console appender with some reasonable default logging settings. + * + * @param maxLevel Max logging level. + * @return New console appender. + */ + private Appender createConsoleAppender(Level maxLevel) { + String fmt = "[%d{ABSOLUTE}][%-5p][%t][%c{1}] %m%n"; + + // Configure output that should go to System.out + Appender app = new ConsoleAppender(new PatternLayout(fmt), ConsoleAppender.SYSTEM_OUT); + + LevelRangeFilter lvlFilter = new LevelRangeFilter(); + + lvlFilter.setLevelMin(Level.TRACE); + lvlFilter.setLevelMax(maxLevel); + + app.addFilter(lvlFilter); + + return app; + } + + /** + * Adds file appender. + * + * @param a Appender. + */ + public static void addAppender(FileAppender a) { + A.notNull(a, "a"); + + fileAppenders.add(a); + } + + /** + * Removes file appender. + * + * @param a Appender. + */ + public static void removeAppender(FileAppender a) { + A.notNull(a, "a"); + + fileAppenders.remove(a); + } + + /** {@inheritDoc} */ + @Override public void setNodeId(UUID nodeId) { + A.notNull(nodeId, "nodeId"); + + this.nodeId = nodeId; + + for (FileAppender a : fileAppenders) { + if (a instanceof IgniteLoggerNodeIdAware) { + ((IgniteLoggerNodeIdAware)a).setNodeId(nodeId); + + a.activateOptions(); + } + } + } + + /** {@inheritDoc} */ + @Override public UUID getNodeId() { + return nodeId; + } + + /** + * Gets files for all registered file appenders. + * + * @return List of files. + */ + public static Collection<String> logFiles() { + Collection<String> res = new ArrayList<>(fileAppenders.size()); + + for (FileAppender a : fileAppenders) + res.add(a.getFile()); + + return res; + } + + /** + * Gets {@link org.apache.ignite.IgniteLogger} wrapper around log4j logger for the given + * category. If category is {@code null}, then root logger is returned. If + * category is an instance of {@link Class} then {@code (Class)ctgr).getName()} + * is used as category name. + * + * @param ctgr {@inheritDoc} + * @return {@link org.apache.ignite.IgniteLogger} wrapper around log4j logger. + */ + @Override public GridTestLog4jLogger getLogger(Object ctgr) { + return new GridTestLog4jLogger(ctgr == null ? Logger.getRootLogger() : + ctgr instanceof Class ? Logger.getLogger(((Class<?>)ctgr).getName()) : + Logger.getLogger(ctgr.toString())); + } + + /** {@inheritDoc} */ + @Override public void trace(String msg) { + if (!impl.isTraceEnabled()) + warning("Logging at TRACE level without checking if TRACE level is enabled: " + msg); + + impl.trace(msg); + } + + /** {@inheritDoc} */ + @Override public void debug(String msg) { + if (!impl.isDebugEnabled()) + warning("Logging at DEBUG level without checking if DEBUG level is enabled: " + msg); + + impl.debug(msg); + } + + /** {@inheritDoc} */ + @Override public void info(String msg) { + if (!impl.isInfoEnabled()) + warning("Logging at INFO level without checking if INFO level is enabled: " + msg); + + impl.info(msg); + } + + /** {@inheritDoc} */ + @Override public void warning(String msg) { + impl.warn(msg); + } + + /** {@inheritDoc} */ + @Override public void warning(String msg, @Nullable Throwable e) { + impl.warn(msg, e); + } + + /** {@inheritDoc} */ + @Override public void error(String msg) { + impl.error(msg); + } + + /** {@inheritDoc} */ + @Override public void error(String msg, @Nullable Throwable e) { + impl.error(msg, e); + } + + /** {@inheritDoc} */ + @Override public boolean isTraceEnabled() { + return impl.isTraceEnabled(); + } + + /** {@inheritDoc} */ + @Override public boolean isDebugEnabled() { + return impl.isDebugEnabled(); + } + + /** {@inheritDoc} */ + @Override public boolean isInfoEnabled() { + return impl.isInfoEnabled(); + } + + /** {@inheritDoc} */ + @Override public boolean isQuiet() { + return quiet; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(GridTestLog4jLogger.class, this); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/package.html ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/package.html b/modules/core/src/test/java/org/apache/ignite/testframework/junits/package.html new file mode 100644 index 0000000..135eb1a --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/package.html @@ -0,0 +1,24 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<body> + <!-- Package description. --> + Contains internal tests or test related classes and interfaces. +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractConfigTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractConfigTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractConfigTest.java new file mode 100644 index 0000000..91087bc --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractConfigTest.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.spi; + +import org.apache.ignite.spi.*; +import org.apache.ignite.spi.discovery.*; +import org.jetbrains.annotations.*; + +import java.lang.reflect.*; + +/** + * Base class for SPI configuration tests. + * @param <T> Type of tested SPI. + */ +public abstract class GridSpiAbstractConfigTest<T extends IgniteSpi> extends GridSpiAbstractTest<T> { + /** Default constructor. */ + protected GridSpiAbstractConfigTest() { + super(false); + } + + /** + * Checks that unacceptable property value prevents SPI from being started. + * + * @param spi Spi to test property on. + * @param propName name of property to check. + * @param val An illegal value. + * @throws Exception If check failed. + */ + protected void checkNegativeSpiProperty(IgniteSpi spi, String propName, @Nullable Object val) throws Exception { + checkNegativeSpiProperty(spi, propName, val, true); + } + + /** + * Checks that unacceptable property value prevents SPI from being started. + * + * @param spi Spi to test property on. + * @param propName name of property to check. + * @param val An illegal value. + * @param checkExMsg If {@code true} then additional info will be added to failure. + * @throws Exception If check failed. + */ + protected void checkNegativeSpiProperty(IgniteSpi spi, String propName, Object val, boolean checkExMsg) + throws Exception { + assert spi != null; + assert propName != null; + + getTestData().getTestResources().inject(spi); + + String mtdName = "set" + propName.substring(0, 1).toUpperCase() + propName.substring(1); + + Method mtd = null; + + for (Method m : spi.getClass().getMethods()) + if (m.getName().equals(mtdName)) { + mtd = m; + + break; + } + + assert mtd != null : "The setter is not found for property: " + propName; + + boolean err = false; + + try { + mtd.invoke(spi, val); + } + catch (InvocationTargetException e) { + info("SPI property setter thrown exception: " + e); + + if (e.getCause() instanceof IllegalArgumentException) + err = true; + else + throw e; + } + + if (!err) + try { + if (!(spi instanceof DiscoverySpi)) + spi.getNodeAttributes(); + + spi.spiStart(getTestGridName()); + } + catch (IgniteSpiException e) { + info("SPI start thrown exception: " + e); + + if (checkExMsg) + assert e.getMessage().contains("SPI parameter failed condition check: ") : + "SPI has returned wrong exception message [propName=" + propName + ", msg=" + e + ']'; + + err = true; + } + + assert err : "No check for property [property=" + propName +", value=" + val + ']'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractTest.java new file mode 100644 index 0000000..2d5108f --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiAbstractTest.java @@ -0,0 +1,692 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.spi; + +import org.apache.ignite.cluster.*; +import org.apache.ignite.internal.*; +import org.apache.ignite.product.*; +import org.apache.ignite.spi.*; +import org.apache.ignite.internal.managers.security.*; +import org.apache.ignite.plugin.security.*; +import org.apache.ignite.spi.communication.*; +import org.apache.ignite.spi.communication.tcp.*; +import org.apache.ignite.spi.discovery.*; +import org.apache.ignite.spi.discovery.tcp.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*; +import org.apache.ignite.internal.util.typedef.internal.*; +import org.apache.ignite.testframework.*; +import org.apache.ignite.testframework.junits.*; +import org.apache.ignite.testframework.junits.spi.GridSpiTestConfig.*; +import org.jetbrains.annotations.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +import static org.apache.ignite.product.IgniteProductVersion.*; + +/** + * Base SPI test class. + * @param <T> SPI implementation class. + */ +@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"}) +public abstract class GridSpiAbstractTest<T extends IgniteSpi> extends GridAbstractTest { + /** */ + private static final IgniteProductVersion VERSION = fromString("99.99.99"); + + /** */ + private static final Map<Class<?>, TestData<?>> tests = new ConcurrentHashMap<>(); + + /** */ + private final boolean autoStart; + + /** Original context classloader. */ + private ClassLoader cl; + + /** */ + protected GridSpiAbstractTest() { + super(false); + + autoStart = true; + } + + /** + * @param autoStart Start automatically. + */ + protected GridSpiAbstractTest(boolean autoStart) { + super(false); + + this.autoStart = autoStart; + } + + /** {@inheritDoc} */ + @Override protected final boolean isJunitFrameworkClass() { + return true; + } + + /** + * @return Test data. + */ + @SuppressWarnings({"unchecked"}) + protected TestData<T> getTestData() { + TestData<T> data = (TestData<T>)tests.get(getClass()); + + if (data == null) + tests.put(getClass(), data = new TestData<>()); + + return data; + } + + /** + * @throws Exception If failed. + */ + private void resetTestData() throws Exception { + tests.put(getClass(), new TestData<T>()); + } + + /** + * @throws Exception If failed. + */ + @Override protected final void setUp() throws Exception { + // Need to change classloader here, although it also handled in the parent class + // the current test initialisation procedure doesn't allow us to setUp the parent first. + cl = Thread.currentThread().getContextClassLoader(); + + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + + TestCounters cntrs = getTestCounters(); + + if (cntrs.isReset()) + cntrs.reset(); + + cntrs.incrementStarted(); + + if (autoStart && isFirstTest()) { + GridSpiTest spiTest = GridTestUtils.getAnnotation(getClass(), GridSpiTest.class); + + assert spiTest != null; + + beforeSpiStarted(); + + if (spiTest.trigger()) + spiStart(); + + info("==== Started spi test [test=" + getClass().getSimpleName() + "] ===="); + } + + super.setUp(); + } + + /** + * @throws Exception If failed. + */ + protected void beforeSpiStarted() throws Exception { + // No-op. + } + + /** {@inheritDoc} */ + @Override protected final GridTestResources getTestResources() { + return getTestData().getTestResources(); + } + + /** + * @throws Exception If failed. + */ + @SuppressWarnings({"unchecked", "CastToIncompatibleInterface", "InstanceofIncompatibleInterface"}) + protected final void spiStart() throws Exception { + GridSpiTest spiTest = GridTestUtils.getAnnotation(getClass(), GridSpiTest.class); + + assert spiTest != null; + + T spi = (T)spiTest.spi().newInstance(); + + // Set spi into test data. + getTestData().setSpi(spi); + + if (!(spi instanceof DiscoverySpi)) { + if (spiTest.triggerDiscovery()) + configureDiscovery(spiTest); + } + else + getTestData().setDiscoverySpi((DiscoverySpi)spi); + + getTestResources().inject(spi); + + spiConfigure(spi); + + Map<String, Object> attrs = spi.getNodeAttributes(); + + // Set up SPI class name and SPI version. + Map<String, Serializable> spiAttrs = initSpiClassAndVersionAttributes(spi); + + if (attrs != null) + getTestData().getAttributes().putAll(attrs); + + if (spiAttrs != null) + getTestData().getAttributes().putAll(spiAttrs); + + Map<String, Serializable> nodeAttrs = getNodeAttributes(); + + if (nodeAttrs != null) + getTestData().getAttributes().putAll(nodeAttrs); + + DiscoverySpi discoSpi = getTestData().getDiscoverySpi(); + + if (spiTest.triggerDiscovery() && !getTestData().isDiscoveryTest()) { + getTestData().getAttributes().putAll( + initSpiClassAndVersionAttributes(discoSpi)); + + // Set all local node attributes into discovery SPI. + discoSpi.setNodeAttributes(getTestData().getAttributes(), VERSION); + + discoSpi.setMetricsProvider(createMetricsProvider()); + + discoSpi.setDataExchange(new DiscoverySpiDataExchange() { + @Override public List<Object> collect(UUID nodeId) { + return new ArrayList<>(); + } + + @Override public void onExchange(List<Object> data) { + } + }); + + try { + spiStart(discoSpi); + } + catch (Exception e) { + spiStop(discoSpi); + + throw e; + } + } + + if (spi instanceof DiscoverySpi) { + getTestData().getAttributes().putAll(initSpiClassAndVersionAttributes(spi)); + + ((DiscoverySpi)spi).setNodeAttributes(getTestData().getAttributes(), VERSION); + + ((DiscoverySpi)spi).setMetricsProvider(createMetricsProvider()); + } + + try { + spiStart(spi); + } + catch (Exception e) { + spiStop(spi); + + if (discoSpi != null && !discoSpi.equals(spi)) + spiStop(discoSpi); + + afterSpiStopped(); + + throw e; + } + + // Initialize SPI context. + getTestData().setSpiContext(initSpiContext()); + + // Initialize discovery SPI only once. + if (discoSpi != null && !discoSpi.equals(spi)) + discoSpi.onContextInitialized(getSpiContext()); + + spi.onContextInitialized(getTestData().getSpiContext()); + } + + /** + * @return SPI context. + * @throws Exception If anything failed. + */ + protected GridSpiTestContext initSpiContext() throws Exception { + GridSpiTestContext spiCtx = new GridSpiTestContext(); + + if (getTestData().getDiscoverySpi() != null) { + spiCtx.setLocalNode(getTestData().getDiscoverySpi().getLocalNode()); + + for (ClusterNode node : getTestData().getDiscoverySpi().getRemoteNodes()) + spiCtx.addNode(node); + } + else { + GridTestNode node = new GridTestNode(UUID.randomUUID()); + + spiCtx.setLocalNode(node); + + if (getSpi() != null) { + // Set up SPI class name and SPI version. + Map<String, Serializable> attrs = initSpiClassAndVersionAttributes(getSpi()); + + for (Map.Entry<String, Serializable> entry: attrs.entrySet()) + node.addAttribute(entry.getKey(), entry.getValue()); + } + } + + return spiCtx; + } + + /** + * @param spi SPI to create attributes for. + * @return Map of attributes. + */ + private Map<String, Serializable> initSpiClassAndVersionAttributes(IgniteSpi spi) { + Map<String, Serializable> attrs = new HashMap<>(); + + attrs.put(U.spiAttribute(spi, GridNodeAttributes.ATTR_SPI_CLASS), spi.getClass().getName()); + + return attrs; + } + + /** + * @return SPI context. + * @throws Exception If anything failed. + */ + protected final GridSpiTestContext getSpiContext() throws Exception { + return getTestData().getSpiContext(); + } + + /** + * @param spiTest SPI test annotation. + * @throws Exception If anything failed. + */ + private void configureDiscovery(GridSpiTest spiTest) throws Exception { + DiscoverySpi discoSpi = spiTest.discoverySpi().newInstance(); + + if (discoSpi instanceof TcpDiscoverySpi) { + TcpDiscoverySpi tcpDisco = (TcpDiscoverySpi)discoSpi; + + tcpDisco.setIpFinder(new TcpDiscoveryVmIpFinder(true)); + } + + getTestData().setDiscoverySpi(discoSpi); + + getTestResources().inject(discoSpi); + + discoSpi.setAuthenticator(new DiscoverySpiNodeAuthenticator() { + @Override public GridSecurityContext authenticateNode(ClusterNode n, GridSecurityCredentials cred) { + GridSecuritySubjectAdapter subj = new GridSecuritySubjectAdapter( + GridSecuritySubjectType.REMOTE_NODE, n.id()); + + subj.permissions(new GridAllowAllPermissionSet()); + + return new GridSecurityContext(subj); + } + + @Override public boolean isGlobalNodeAuthentication() { + return false; + } + }); + + configure(discoSpi); + + if (discoSpi.getNodeAttributes() != null) + getTestData().getAttributes().putAll(discoSpi.getNodeAttributes()); + } + + /** + * Creates metrics provider just for testing purposes. The provider + * will not return valid node metrics. + * + * @return Dummy metrics provider. + */ + protected DiscoveryMetricsProvider createMetricsProvider() { + return new DiscoveryMetricsProvider() { + /** {@inheritDoc} */ + @Override public ClusterNodeMetrics getMetrics() { return new DiscoveryNodeMetricsAdapter(); } + }; + } + + /** + * @param spi SPI. + * @throws Exception If failed. + */ + protected void spiConfigure(T spi) throws Exception { + configure(spi); + } + + /** + * @param spi SPI. + * @throws Exception If failed. + * @throws IllegalAccessException If failed. + * @throws InvocationTargetException If failed. + */ + private void configure(IgniteSpi spi) throws Exception { + // Inject Configuration. + for (Method m : getClass().getMethods()) { + GridSpiTestConfig cfg = m.getAnnotation(GridSpiTestConfig.class); + + if (cfg != null) { + if (getTestData().isDiscoveryTest() || + (cfg.type() != ConfigType.DISCOVERY && !(spi instanceof DiscoverySpi)) || + (cfg.type() != ConfigType.SELF && spi instanceof DiscoverySpi)) { + assert m.getName().startsWith("get") : "Test configuration must be a getter [method=" + + m.getName() + ']'; + + // Determine getter name. + String name = cfg.setterName(); + + if (name == null || name.isEmpty()) + name = 's' + m.getName().substring(1); + + Method setter = getMethod(spi.getClass(), name); + + assert setter != null : "Spi does not have setter for configuration property [spi=" + + spi.getClass().getName() + ", config-prop=" + name + ']'; + + // Inject configuration parameter into spi. + setter.invoke(spi, m.invoke(this)); + } + } + } + + // Our SPI tests should not have the same parameters otherwise they + // will find each other. + if (spi instanceof TcpCommunicationSpi) + ((TcpCommunicationSpi)spi).setLocalPort(GridTestUtils.getNextCommPort(getClass())); + + if (spi instanceof TcpDiscoverySpi) { + TcpDiscoveryIpFinder ipFinder = ((TcpDiscoverySpi)spi).getIpFinder(); + + if (ipFinder instanceof TcpDiscoveryMulticastIpFinder) { + String mcastAddr = GridTestUtils.getNextMulticastGroup(getClass()); + + if (mcastAddr != null && !mcastAddr.isEmpty()) { + ((TcpDiscoveryMulticastIpFinder)ipFinder).setMulticastGroup(mcastAddr); + ((TcpDiscoveryMulticastIpFinder)ipFinder).setMulticastPort( + GridTestUtils.getNextMulticastPort(getClass())); + } + } + } + } + + /** + * @param spi SPI. + * @throws Exception If failed. + */ + protected void spiStart(IgniteSpi spi) throws Exception { + U.setWorkDirectory(null, U.getGridGainHome()); + + // Start SPI with unique grid name. + spi.spiStart(getTestGridName()); + + info("SPI started [spi=" + spi.getClass() + ']'); + } + + /** + * @return Fully initialized and started SPI implementation. + */ + protected final T getSpi() { + return getTestData().getSpi(); + } + + /** + * Gets class of the SPI implementation. + * + * @return Class of the SPI implementation. + */ + @SuppressWarnings({"unchecked"}) + protected final Class<? extends T> getSpiClass() { + GridSpiTest spiTest = GridTestUtils.getAnnotation(getClass(), GridSpiTest.class); + + assert spiTest != null; + + return (Class<? extends T>)spiTest.spi(); + } + + /** + * @return Node UUID. + * @throws Exception If failed. + */ + protected UUID getNodeId() throws Exception { + return getTestResources().getNodeId(); + } + + /** + * @return Discovery SPI. + * @throws Exception If failed. + */ + @Nullable protected final DiscoverySpi getDiscoverySpi() throws Exception { + if (getTestData() != null) + return getTestData().getDiscoverySpi(); + + return null; + } + + /** + * Override this method for put local node attributes to discovery SPI. + * + * @return Always {@code null}. + */ + @Nullable protected Map<String, Serializable> getNodeAttributes() { + return null; + } + + /** + * @throws Exception If failed. + */ + @Override protected final void tearDown() throws Exception { + getTestCounters().incrementStopped(); + + boolean wasLast = isLastTest(); + + super.tearDown(); + + if (autoStart && wasLast) { + GridSpiTest spiTest = GridTestUtils.getAnnotation(getClass(), GridSpiTest.class); + + assert spiTest != null; + + if (spiTest.trigger()) { + spiStop(); + + afterSpiStopped(); + } + + info("==== Stopped spi test [test=" + getClass().getSimpleName() + "] ===="); + } + + Thread.currentThread().setContextClassLoader(cl); + } + + /** + * @throws Exception If failed.. + */ + protected void afterSpiStopped() throws Exception { + // No-op. + } + + /** + * @throws Exception If failed. + */ + protected final void spiStop() throws Exception { + TestData<T> testData = getTestData(); + + if (testData.getSpi() == null) + return; + + testData.getSpi().onContextDestroyed(); + + spiStop(testData.getSpi()); + + GridSpiTest spiTest = GridTestUtils.getAnnotation(getClass(), GridSpiTest.class); + + assert spiTest != null; + + if (!testData.isDiscoveryTest() && spiTest.triggerDiscovery()) { + testData.getDiscoverySpi().onContextDestroyed(); + + spiStop(testData.getDiscoverySpi()); + } + + getTestResources().stopThreads(); + + resetTestData(); + } + + /** + * @param spi SPI. + * @throws Exception If failed. + */ + protected void spiStop(IgniteSpi spi) throws Exception { + spi.spiStop(); + + info("SPI stopped [spi=" + spi.getClass().getName() + ']'); + } + + /** + * @param cls Class. + * @param name Method name. + * @return Method. + */ + @Nullable private Method getMethod(Class<?> cls, String name) { + for (; !cls.equals(Object.class); cls = cls.getSuperclass()) { + for (Method m : cls.getMethods()) { + if (m.getName().equals(name)) + return m; + } + } + + return null; + } + + /** + * + * @param <T> SPI implementation class. + */ + protected static class TestData<T> { + /** */ + private T spi; + + /** */ + private DiscoverySpi discoSpi; + + /** */ + private CommunicationSpi commSpi; + + /** */ + private GridSpiTestContext spiCtx; + + /** */ + private Map<String, Object> allAttrs = new HashMap<>(); + + /** */ + private GridTestResources rsrcs = new GridTestResources(); + + /** + * + */ + TestData() { + // No-op. + } + + /** + * @return Test resources. + * + */ + public GridTestResources getTestResources() { + return rsrcs; + } + + /** + * @return {@code true} in case it is a discovery test. + */ + @SuppressWarnings({"ObjectEquality"}) + public boolean isDiscoveryTest() { + return spi == discoSpi; + } + + /** + * @return {@code true} in case it is a communication test. + */ + @SuppressWarnings({"ObjectEquality"}) + public boolean isCommunicationTest() { + return spi == commSpi; + } + + /** + * @return SPI. + */ + public T getSpi() { + return spi; + } + + /** + * @param spi SPI. + */ + public void setSpi(T spi) { + this.spi = spi; + } + + /** + * @param commSpi Communication SPI. + */ + public void setCommSpi(CommunicationSpi commSpi) { + this.commSpi = commSpi; + } + + /** + * @return Attributes. + */ + public Map<String, Object> getAttributes() { + return allAttrs; + } + + /** + * @param allAttrs Attributes. + */ + public void setAllAttrs(Map<String, Object> allAttrs) { + this.allAttrs = allAttrs; + } + + /** + * @return Discovery SPI. + */ + public DiscoverySpi getDiscoverySpi() { + return discoSpi; + } + + /** + * @param discoSpi Discovery SPI. + */ + public void setDiscoverySpi(DiscoverySpi discoSpi) { + this.discoSpi = discoSpi; + } + + /** + * @return SPI context. + */ + public GridSpiTestContext getSpiContext() { + return spiCtx; + } + + /** + * @param spiCtx SPI context. + */ + public void setSpiContext(GridSpiTestContext spiCtx) { + this.spiCtx = spiCtx; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return getClass().getSimpleName() + + " [spi=" + spi + + ", discoSpi=" + discoSpi + + ", allAttrs=" + allAttrs + ']'; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTest.java new file mode 100644 index 0000000..162855d --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.spi; + +import org.apache.ignite.spi.*; +import org.apache.ignite.spi.discovery.*; +import org.apache.ignite.spi.discovery.tcp.*; + +import java.lang.annotation.*; + +/** + * Annotates all tests in SPI test framework. Provides implementation class of the SPI and + * optional dependencies. + */ +@SuppressWarnings({"JavaDoc"}) +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface GridSpiTest { + /** + * Mandatory implementation class for SPI. + */ + public Class<? extends IgniteSpi> spi(); + + /** + * Flag indicating whether SPI should be automatically started. + */ + public boolean trigger() default true; + + /** + * Flag indicating whether discovery SPI should be automatically started. + */ + public boolean triggerDiscovery() default false; + + /** + * Optional discovery SPI property to specify which SPI to use for discovering other nodes. + * This property is ignored if the spi being tested is an implementation of {@link org.apache.ignite.spi.discovery.DiscoverySpi} or + * {@link #triggerDiscovery()} is set to {@code false}. + */ + public Class<? extends DiscoverySpi> discoverySpi() default TcpDiscoverySpi.class; + + /** + * Optional group this test belongs to. + */ + public String group() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTestConfig.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTestConfig.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTestConfig.java new file mode 100644 index 0000000..d60cb48 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/GridSpiTestConfig.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.testframework.junits.spi; + +import java.lang.annotation.*; + +/** + * Annotates a getter method value of which is used to configure implementation SPI. + */ +@SuppressWarnings({"JavaDoc"}) +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +public @interface GridSpiTestConfig { + /** */ + @SuppressWarnings({"PublicInnerClass"}) + public enum ConfigType { + /** */ + SELF, + + /** */ + DISCOVERY, + + /** */ + BOTH + } + + /** */ + @SuppressWarnings({"JavaDoc"}) ConfigType type() default ConfigType.SELF; + + /** */ + String setterName() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/package.html ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/package.html b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/package.html new file mode 100644 index 0000000..1f85ff2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/spi/package.html @@ -0,0 +1,23 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<body> + <!-- Package description. --> + Contains internal tests or test related classes and interfaces. +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/bd28003b/modules/core/src/test/java/org/apache/ignite/testframework/package.html ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/package.html b/modules/core/src/test/java/org/apache/ignite/testframework/package.html new file mode 100644 index 0000000..1f85ff2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testframework/package.html @@ -0,0 +1,23 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<body> + <!-- Package description. --> + Contains internal tests or test related classes and interfaces. +</body> +</html>