001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004:
005: package com.tctest.spring.integrationtests.tests;
006:
007: import com.tc.test.server.appserver.deployment.AbstractTwoServerDeploymentTest;
008: import com.tc.test.server.appserver.deployment.DeploymentBuilder;
009: import com.tc.test.server.appserver.deployment.TestCallback;
010: import com.tctest.spring.bean.IActiveBean;
011: import com.tctest.spring.integrationtests.SpringTwoServerTestSetup;
012:
013: import junit.framework.Test;
014:
015: /**
016: * LKC-1760: Test: thread coordination for spring beans
017: * https://jira.terracotta.lan/jira//browse/LKC-1760
018: *
019: * Test that thread coordination is working across two nodes
020: *
021: * Auto locks
022: * Named locks
023: *
024: * Locking on bean
025: * Locking on reference in bean (?????)
026: * wait/notify etc.
027: */
028: public class ThreadCoordinationTest extends
029: AbstractTwoServerDeploymentTest {
030:
031: private static final int MAX_NOTIFY_DELAY = 1;
032: private static final int MAX_REPLICATION_DELAY = 10;
033:
034: public void testAutolock() throws Throwable {
035: logger.info("Start testAutolock()");
036: checkThreadCoordination("beanWithAutolock");
037: logger.info("End testAutolock()");
038: }
039:
040: public void testNamedLock() throws Throwable {
041: logger.info("Start testNamedLock()");
042: checkThreadCoordination("beanWithNamedLock");
043: logger.info("End testNamedLock()");
044: }
045:
046: public void testWaitNotify() throws Throwable {
047: logger.info("Start testWaitNotify()");
048:
049: final IActiveBean bean1 = (IActiveBean) server0.getProxy(
050: IActiveBean.class, "beanWithWaitNotify");
051: final IActiveBean bean2 = (IActiveBean) server1.getProxy(
052: IActiveBean.class, "beanWithWaitNotify");
053:
054: bean1.start();
055: bean2.start();
056:
057: assertEquals("Preconditions " + getInfo(bean1, bean2), "0",
058: bean1.getValue());
059: assertEquals("Preconditions " + getInfo(bean1, bean2), "0",
060: bean2.getValue());
061:
062: // added this sleep to make sure the 2 running thread made to the wait().
063: Thread.sleep(1000L);
064:
065: bean1.setValue("1");
066: waitForSuccess(1, new TestCallback() {
067: public void check() throws Exception {
068: assertEquals("Expected update1: "
069: + getInfo(bean1, bean2), "2", bean1.getValue());
070: assertEquals("Expected update1: "
071: + getInfo(bean1, bean2), "2", bean2.getValue());
072:
073: }
074: });
075:
076: // added this sleep to make sure the 2 running thread made to the wait().
077: Thread.sleep(1000L);
078:
079: bean2.setValue("1");
080: waitForSuccess(MAX_NOTIFY_DELAY, new TestCallback() {
081: public void check() throws Exception {
082: assertEquals("Expected update2: "
083: + getInfo(bean1, bean2), "4", bean1.getValue());
084: assertEquals("Expected update2: "
085: + getInfo(bean1, bean2), "4", bean2.getValue());
086: }
087: });
088:
089: bean1.stop();
090: bean2.stop();
091:
092: logger.info("End testWaitNotify()");
093: }
094:
095: private void checkThreadCoordination(String beanName)
096: throws Throwable {
097: final IActiveBean bean1 = (IActiveBean) server0.getProxy(
098: IActiveBean.class, beanName);
099: final IActiveBean bean2 = (IActiveBean) server1.getProxy(
100: IActiveBean.class, beanName);
101:
102: bean1.setValue("1");
103:
104: bean1.start();
105: waitForSuccess(MAX_REPLICATION_DELAY, new TestCallback() {
106: public void check() throws Exception {
107: assertEquals("Expected update1 on bean1: "
108: + getInfo(bean1, bean2), "1", bean1.getValue());
109: }
110: });
111:
112: bean2.start();
113: Thread.sleep(1000L);
114:
115: waitForSuccess(5, new TestCallback() {
116: public void check() throws Exception {
117: assertEquals("Expected update1 on bean1: "
118: + getInfo(bean1, bean2), "1", bean1.getValue());
119: assertEquals("Expected update1 only on bean1: "
120: + getInfo(bean1, bean2), "0", bean2.getValue());
121: }
122: });
123:
124: bean1.stop();
125: waitForSuccess(5, new TestCallback() {
126: public void check() throws Exception {
127: assertEquals("Expected update1 on bean2: "
128: + getInfo(bean1, bean2), "1", bean2.getValue());
129: }
130: });
131:
132: bean1.start();
133: Thread.sleep(1000L);
134:
135: bean2.setValue("2");
136: waitForSuccess(5, new TestCallback() {
137: public void check() throws Exception {
138: assertEquals("Expected update2 on bean2: "
139: + getInfo(bean1, bean2), "2", bean2.getValue());
140: assertEquals("Expected update2 only on bean2: "
141: + getInfo(bean1, bean2), "1", bean1.getValue());
142: }
143: });
144:
145: bean2.stop();
146: waitForSuccess(5, new TestCallback() {
147: public void check() throws Exception {
148: assertEquals("Expected update2 on bean1: "
149: + getInfo(bean1, bean2), "2", bean1.getValue());
150: }
151: });
152:
153: bean1.stop();
154: }
155:
156: private String getInfo(IActiveBean bean1, IActiveBean bean2) {
157: return (bean1.isActive() ? "started" : "waiting") + ":"
158: + bean1.getValue() + "/"
159: + (bean2.isActive() ? "started" : "waiting") + ":"
160: + bean2.getValue();
161: }
162:
163: private static class ThreadCoordinationTestSetup extends
164: SpringTwoServerTestSetup {
165: private ThreadCoordinationTestSetup() {
166: super (
167: ThreadCoordinationTest.class,
168: "/tc-config-files/thread-coordination-tc-config.xml",
169: "thread-coordination-test");
170: }
171:
172: protected void configureWar(DeploymentBuilder builder) {
173: builder
174: .addBeanDefinitionFile("classpath:/com/tctest/spring/beanfactory-thread-coordination.xml");
175:
176: builder.addRemoteService("beanWithAutolock",
177: "beanWithAutolock", IActiveBean.class);
178: builder.addRemoteService("beanWithNamedLock",
179: "beanWithNamedLock", IActiveBean.class);
180: builder.addRemoteService("beanWithWaitNotify",
181: "beanWithWaitNotify", IActiveBean.class);
182: }
183:
184: }
185:
186: /**
187: * JUnit test loader entry point
188: */
189: public static Test suite() {
190: return new ThreadCoordinationTestSetup();
191: }
192:
193: }
|