IGNITE-3041: Implement config variations test for IgniteServices
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6e1d45e8 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6e1d45e8 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6e1d45e8 Branch: refs/heads/ignite-2788 Commit: 6e1d45e83b91b9dda78c5f6ac6ed4f2726aba787 Parents: 2699235 Author: sboikov <[email protected]> Authored: Fri Apr 29 12:21:02 2016 +0300 Committer: shtykh_roman <[email protected]> Committed: Fri May 13 16:11:16 2016 +0900 ---------------------------------------------------------------------- ...gniteServiceConfigVariationsFullApiTest.java | 350 +++++++++++++++++++ .../configvariations/VariationsTestsConfig.java | 2 +- .../IgniteConfigVariationsAbstractTest.java | 72 +++- ...ServiceConfigVariationsFullApiTestSuite.java | 92 +++++ 4 files changed, 507 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/6e1d45e8/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceConfigVariationsFullApiTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceConfigVariationsFullApiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceConfigVariationsFullApiTest.java new file mode 100644 index 0000000..4e6d1e6 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/IgniteServiceConfigVariationsFullApiTest.java @@ -0,0 +1,350 @@ +/* + * 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.internal.processors.service; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Serializable; +import java.util.concurrent.ThreadLocalRandom; +import javax.cache.configuration.Factory; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.IgniteServices; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryReader; +import org.apache.ignite.binary.BinaryWriter; +import org.apache.ignite.binary.Binarylizable; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.services.Service; +import org.apache.ignite.services.ServiceConfiguration; +import org.apache.ignite.services.ServiceContext; +import org.apache.ignite.testframework.configvariations.Parameters; +import org.apache.ignite.testframework.junits.IgniteConfigVariationsAbstractTest; + +/** + * Full API services test. + */ +public class IgniteServiceConfigVariationsFullApiTest extends IgniteConfigVariationsAbstractTest { + /** Test service name. */ + private static final String SERVICE_NAME = "testService"; + + /** Test service name. */ + private static final String CACHE_NAME = "testCache"; + + /** */ + protected static final int CLIENT_NODE_IDX_2 = 4; + + /** Test object id counter. */ + private static int cntr; + + /** Callable factories. */ + @SuppressWarnings("unchecked") + private static final Factory[] serviceFactories = new Factory[] { + Parameters.factory(TestServiceImpl.class), + Parameters.factory(TestServiceImplExternalizable.class), + Parameters.factory(TestServiceImplBinarylizable.class) + }; + + /** {@inheritDoc} */ + @Override protected boolean expectedClient(String testGridName) { + int i = testsCfg.gridCount(); + + if (i < 5) + return super.expectedClient(testGridName); + + // Use two client nodes if grid index 5 or greater. + return getTestGridName(CLIENT_NODE_IDX).equals(testGridName) + || getTestGridName(CLIENT_NODE_IDX_2).equals(testGridName); + } + + /** + * Test node singleton deployment + * + * @throws Exception If failed. + */ + public void testNodeSingletonDeploy() throws Exception { + runInAllDataModes(new ServiceTestRunnable(true, new DeployClosure() { + @Override public void run(IgniteServices services, String svcName, TestService svc) { + services.deployNodeSingleton(svcName, (Service)svc); + } + })); + } + + /** + * Test cluster singleton deployment + * + * @throws Exception If failed. + */ + public void testClusterSingletonDeploy() throws Exception { + runInAllDataModes(new ServiceTestRunnable(false, new DeployClosure() { + @Override public void run(IgniteServices services, String svcName, TestService svc) { + services.deployClusterSingleton(svcName, (Service)svc); + } + })); + } + + /** + * Test key affinity deployment + * + * @throws Exception If failed. + */ + public void testKeyAffinityDeploy() throws Exception { + runInAllDataModes(new ServiceTestRunnable(false, new DeployClosure() { + @Override public void run(IgniteServices services, String svcName, TestService svc) { + IgniteCache<Object, Object> cache = grid(testedNodeIdx).getOrCreateCache(CACHE_NAME); + + services.deployKeyAffinitySingleton(svcName, (Service)svc, cache.getName(), "1"); + } + })); + } + + /** + * Tests multiple deployment + * + * @throws Exception If failed. + */ + public void testMultipleDeploy() throws Exception { + runInAllDataModes(new ServiceTestRunnable(true, new DeployClosure() { + @Override public void run(IgniteServices services, String svcName, TestService svc) { + services.deployMultiple(svcName, (Service)svc, 0, 1); + } + })); + } + + /** + * Tests deployment. + * + * @throws Exception If failed. + */ + public void testDeploy() throws Exception { + runInAllDataModes(new ServiceTestRunnable(false, new DeployClosure() { + @Override public void run(IgniteServices services, String svcName, TestService svc) { + services.deployClusterSingleton(svcName, (Service)svc); + + ServiceConfiguration cfg = new ServiceConfiguration(); + + cfg.setName(svcName); + + cfg.setService((Service)svc); + + cfg.setTotalCount(1); + + cfg.setMaxPerNodeCount(1); + + cfg.setNodeFilter(services.clusterGroup().predicate()); + + services.deploy(cfg); + } + })); + } + + /** + * Service test closure + */ + private class ServiceTestRunnable implements TestRunnable { + /** Sticky. */ + private final boolean sticky; + + /** Deploy closure */ + private final DeployClosure deployC; + + /** + * Default constructor. + * + * @param sticky Sticky flag. + * @param deployC Closure. + */ + public ServiceTestRunnable(boolean sticky, DeployClosure deployC) { + this.sticky = sticky; + + this.deployC = deployC; + } + + /** {@inheritDoc} */ + @Override public void run() throws Exception { + for (Factory factory : serviceFactories) + testService((TestService)factory.create(), sticky, deployC); + } + } + + /** + * + */ + interface DeployClosure { + /** + * @param services Services. + * @param svcName Service name. + * @param svc Service. + */ + void run(IgniteServices services, String svcName, TestService svc); + } + + /** + * Tests deployment and contract. + * + * @param svc Service. + * @param sticky Sticky. + * @param deployC Closure. + * @throws Exception If failed. + */ + protected void testService(TestService svc, boolean sticky, DeployClosure deployC) throws Exception { + IgniteEx ignite = testedGrid(); + + IgniteServices services = ignite.services(); + + Object expected = value(++cntr); + + // Put value for testing Service instance serialization. + svc.setValue(expected); + + deployC.run(services, SERVICE_NAME, svc); + + // Expect correct value from local instance. + assertEquals(expected, svc.getValue()); + + // Use stickiness to make sure data will be fetched from the same instance. + TestService proxy = services.serviceProxy(SERVICE_NAME, TestService.class, sticky); + + // Expect that correct value is returned from deployed instance. + assertEquals(expected, proxy.getValue()); + + expected = value(++cntr); + + // Change value. + proxy.setValue(expected); + + // Expect correct value after being read back. + int r = 1000; + + while(r-- > 0) + assertEquals(expected, proxy.getValue()); + + assertEquals("Expected 1 deployed service", 1, services.serviceDescriptors().size()); + + // Randomize stop method invocation + boolean tmp = ThreadLocalRandom.current().nextBoolean(); + + if (tmp) + services.cancelAll(); + else + services.cancel(SERVICE_NAME); + } + + /** + * Test service + */ + public interface TestService { + /** + * @param o argument to set. + */ + void setValue(Object o); + + /** + * @return Argument + * @throws Exception If failed. + */ + Object getValue() throws Exception; + } + + /** + * Implementation for {@link TestService} + */ + public static class TestServiceImpl implements Service, TestService, Serializable { + /** Test value. */ + protected Object val; + + /** + * Default constructor. + */ + public TestServiceImpl() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public Object getValue() throws Exception { + return val; + } + + /** {@inheritDoc} */ + @Override public void cancel(ServiceContext ctx) { + // No-op + } + + /** {@inheritDoc} */ + @Override public void init(ServiceContext ctx) throws Exception { + // No-op + } + + /** {@inheritDoc} */ + @Override public void execute(ServiceContext ctx) throws Exception { + // No-op + } + + /** {@inheritDoc} */ + public void setValue(Object val) { + this.val = val; + } + } + + /** + * Echo service, externalizable object + */ + @SuppressWarnings({"PublicInnerClass"}) + public static class TestServiceImplExternalizable extends TestServiceImpl implements Externalizable { + /** + * Default constructor. + */ + public TestServiceImplExternalizable() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + val = in.readObject(); + } + } + + /** + * Echo service, binarylizable object + */ + @SuppressWarnings({"PublicInnerClass"}) + public static class TestServiceImplBinarylizable extends TestServiceImpl implements Binarylizable { + /** + * Default constructor. + */ + public TestServiceImplBinarylizable() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException { + writer.writeObject("arg", val); + } + + /** {@inheritDoc} */ + @Override public void readBinary(BinaryReader reader) throws BinaryObjectException { + val = reader.readObject("arg"); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/6e1d45e8/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/VariationsTestsConfig.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/VariationsTestsConfig.java b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/VariationsTestsConfig.java index 7bcfc7f..929b0c8 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/VariationsTestsConfig.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/VariationsTestsConfig.java @@ -70,7 +70,7 @@ public class VariationsTestsConfig { * @param factory Factory. * @param desc Config description. * @param stopNodes Stope nodes. - * @param gridCnt Grdi count. + * @param gridCnt Grid count. */ public VariationsTestsConfig( ConfigFactory factory, http://git-wip-us.apache.org/repos/asf/ignite/blob/6e1d45e8/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java index 258eba8..3b8c046 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteConfigVariationsAbstractTest.java @@ -27,6 +27,10 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import org.apache.commons.io.FileUtils; import org.apache.ignite.Ignition; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.binary.BinaryReader; +import org.apache.ignite.binary.BinaryWriter; +import org.apache.ignite.binary.Binarylizable; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteEx; import org.apache.ignite.internal.util.typedef.internal.U; @@ -200,12 +204,12 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr for (int i = 0; i < DataMode.values().length; i++) { dataMode = DataMode.values()[i]; - if ((getConfiguration().getMarshaller() instanceof JdkMarshaller) - && (dataMode == DataMode.PLANE_OBJECT)) { - info("Skip test for JdkMarshaller & PLANE_OBJECT data mode"); + if (!isCompatible()) { + info("Skipping test in data mode: " + dataMode); + continue; } - + info("Running test in data mode: " + dataMode); if (i != 0) @@ -250,6 +254,8 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr return new ExternalizableObject(keyId); case PLANE_OBJECT: return new TestObject(keyId); + case BINARILIZABLE: + return new BinarylizableObject(keyId); default: throw new IllegalArgumentException("mode: " + mode); } @@ -279,6 +285,8 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr return new ExternalizableObject(idx); case PLANE_OBJECT: return new TestObject(idx); + case BINARILIZABLE: + return new BinarylizableObject(idx); default: throw new IllegalArgumentException("mode: " + mode); } @@ -395,7 +403,7 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr /** * Default constructor. */ - public ExternalizableObject() { + ExternalizableObject() { super(-1); } @@ -422,6 +430,37 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr } /** + * + */ + public static class BinarylizableObject extends TestObject implements Binarylizable { + /** + * Default constructor. + */ + public BinarylizableObject() { + super(-1); + } + + /** + * @param val Value. + */ + public BinarylizableObject(int val) { + super(val); + } + + @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException { + writer.writeInt("val", val); + writer.writeString("strVal", strVal); + writer.writeEnum("enumVal", enumVal); + } + + @Override public void readBinary(BinaryReader reader) throws BinaryObjectException { + val = reader.readInt("val"); + strVal = reader.readString("strVal"); + enumVal = reader.readEnum("enumVal"); + } + } + + /** * Data mode. */ public enum DataMode { @@ -432,7 +471,10 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr EXTERNALIZABLE, /** Objects without Serializable and Externalizable. */ - PLANE_OBJECT + PLANE_OBJECT, + + /** Binarylizable objects. Compatible only with binary marshaller */ + BINARILIZABLE } /** @@ -452,10 +494,24 @@ public abstract class IgniteConfigVariationsAbstractTest extends GridCommonAbstr /** * */ - public static interface TestRunnable { + public interface TestRunnable { /** * @throws Exception If failed. */ - public void run() throws Exception; + void run() throws Exception; + } + + /** + * Check test compatibility with current data mode + * @return true if incompatible + * @throws Exception + */ + protected boolean isCompatible() throws Exception { + switch (dataMode) { + case BINARILIZABLE: + case PLANE_OBJECT: + return !(getConfiguration().getMarshaller() instanceof JdkMarshaller); + } + return false; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/6e1d45e8/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceConfigVariationsFullApiTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceConfigVariationsFullApiTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceConfigVariationsFullApiTestSuite.java new file mode 100644 index 0000000..328ae8d --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteServiceConfigVariationsFullApiTestSuite.java @@ -0,0 +1,92 @@ +/* + * 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.testsuites; + +import junit.framework.TestSuite; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.binary.BinaryMarshaller; +import org.apache.ignite.internal.processors.service.IgniteServiceConfigVariationsFullApiTest; +import org.apache.ignite.marshaller.jdk.JdkMarshaller; +import org.apache.ignite.testframework.configvariations.ConfigParameter; +import org.apache.ignite.testframework.configvariations.ConfigVariations; +import org.apache.ignite.testframework.configvariations.ConfigVariationsTestSuiteBuilder; +import org.apache.ignite.testframework.configvariations.Parameters; + +/** + * Full API service test suit. + */ +public class IgniteServiceConfigVariationsFullApiTestSuite extends TestSuite { + /** */ + @SuppressWarnings("unchecked") + private static final ConfigParameter<IgniteConfiguration>[][] PARAMS = new ConfigParameter[][] { + Parameters.objectParameters("setMarshaller", + Parameters.factory(JdkMarshaller.class), + Parameters.factory(BinaryMarshaller.class), + ConfigVariations.optimizedMarshallerFactory() + ), + + Parameters.booleanParameters("setPeerClassLoadingEnabled") + }; + + /** + * @return Compute API test suite. + * @throws Exception If failed. + */ + public static TestSuite suite() throws Exception { + TestSuite suite = new TestSuite("Service Deployment New Full API Test Suite"); + + suite.addTest(new ConfigVariationsTestSuiteBuilder( + "Single server", + IgniteServiceConfigVariationsFullApiTest.class) + .igniteParams(PARAMS) + .gridsCount(1) + .build()); + + // Tests run on server (node#0) & client(node#1). + suite.addTest(new ConfigVariationsTestSuiteBuilder( + "1 server, 1 client", + IgniteServiceConfigVariationsFullApiTest.class) + .igniteParams(PARAMS) + .gridsCount(2) + .testedNodesCount(2) + .withClients() + .build()); + + // Tests run on servers (node#0,node#2,node#3) & client(node#1). + suite.addTest(new ConfigVariationsTestSuiteBuilder( + "3 servers, 1 client", + IgniteServiceConfigVariationsFullApiTest.class) + .igniteParams(PARAMS) + .gridsCount(4) + .testedNodesCount(2) + .withClients() + .build()); + + // Tests run on servers (node#0,node#2,node#3) & client(node#1,node#4). + suite.addTest(new ConfigVariationsTestSuiteBuilder( + "3 servers, 2 clients", + IgniteServiceConfigVariationsFullApiTest.class) + .igniteParams(PARAMS) + .gridsCount(5) + .testedNodesCount(2) + .withClients() + .build()); + + return suite; + } +} \ No newline at end of file
