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: package com.tc.test.transactions;
005:
006: import com.tc.test.TCTestCase;
007: import com.tc.util.TCAssertionError;
008:
009: /**
010: * Unit test for {@link StandardTransactionalObject}.
011: */
012: public class StandardTransactionalObjectTest extends TCTestCase {
013:
014: private TransactionalObject trans;
015:
016: public void setUp() throws Exception {
017: this .trans = new StandardTransactionalObject("test-object",
018: "foo");
019: }
020:
021: /**
022: * This tests for a very specific case, where we could end up GCing old data that we might need later — this is
023: * what the GC slop in {@link StandardTransactionalObject} is for.
024: */
025: public void testMixedSpecifiedAndUnspecifiedTimes()
026: throws Exception {
027: TransactionalObject.Context write6615 = this .trans
028: .startWrite("6615");
029: this .trans.endWrite(write6615);
030:
031: Thread.sleep(100);
032:
033: TransactionalObject.Context write6616 = this .trans
034: .startWrite("6616");
035:
036: Thread.sleep(100);
037:
038: long readTime = System.currentTimeMillis();
039:
040: Thread.sleep(100);
041:
042: this .trans.endWrite(write6616);
043:
044: Thread.sleep(100);
045:
046: TransactionalObject.Context read = this .trans.startRead();
047: this .trans.endRead(read, "6616");
048:
049: read = this .trans.startRead(readTime);
050: this .trans.endRead(read, "6615");
051: }
052:
053: public void xtestSimpleWrites() throws Exception {
054: checkValues(new String[] { "foo" }, new String[] { "bar",
055: "baz", "quux" });
056:
057: StandardTransactionalObject.Context context1 = this .trans
058: .startWrite("bar");
059: checkValues(new String[] { "foo", "bar" }, new String[] {
060: "baz", "quux" });
061:
062: this .trans.endWrite(context1);
063: checkValues(new String[] { "bar" }, new String[] { "foo",
064: "baz", "quux" });
065:
066: context1 = this .trans.startWrite("foo");
067: StandardTransactionalObject.Context context2 = this .trans
068: .startWrite("baz");
069:
070: checkValues(new String[] { "foo", "bar", "baz" },
071: new String[] { "quux" });
072: this .trans.endWrite(context1);
073: checkValues(new String[] { "foo", "baz" }, new String[] {
074: "bar", "quux" });
075: this .trans.endWrite(context2);
076: checkValues(new String[] { "foo", "baz" }, new String[] {
077: "bar", "quux" });
078: }
079:
080: public void xtestInterlacedReads() {
081: this .trans = new StandardTransactionalObject("test-object", 0,
082: "foo", 1000);
083:
084: StandardTransactionalObject.Context readContext1 = this .trans
085: .startRead(1020);
086: StandardTransactionalObject.Context readContext1b = this .trans
087: .startRead(1020);
088: StandardTransactionalObject.Context readContext1c = this .trans
089: .startRead(1020);
090: StandardTransactionalObject.Context writeContext1 = this .trans
091: .startWrite("bar", 1040);
092: StandardTransactionalObject.Context readContext2 = this .trans
093: .startRead(1060);
094: StandardTransactionalObject.Context readContext2b = this .trans
095: .startRead(1060);
096: StandardTransactionalObject.Context readContext2c = this .trans
097: .startRead(1060);
098: StandardTransactionalObject.Context writeContext2 = this .trans
099: .startWrite("baz", 1080);
100: StandardTransactionalObject.Context readContext3 = this .trans
101: .startRead(1100);
102: StandardTransactionalObject.Context readContext3b = this .trans
103: .startRead(1100);
104: StandardTransactionalObject.Context readContext3c = this .trans
105: .startRead(1100);
106:
107: checkValues(readContext1, 1020, new String[] { "foo" },
108: new String[] { "bar", "baz" });
109: checkValues(readContext1, 1030, new String[] { "foo" },
110: new String[] { "bar", "baz" });
111: checkValues(readContext1, 1039, new String[] { "foo" },
112: new String[] { "bar", "baz" });
113: checkValues(readContext1, 1040, new String[] { "foo", "bar" },
114: new String[] { "baz" });
115: checkValues(readContext1, 1079, new String[] { "foo", "bar" },
116: new String[] { "baz" });
117: checkValues(readContext1, 1080, new String[] { "foo", "bar",
118: "baz" }, new String[] {});
119: checkValues(readContext1, 1120, new String[] { "foo", "bar",
120: "baz" }, new String[] {});
121:
122: checkValues(readContext2, 1060, new String[] { "foo", "bar" },
123: new String[] { "baz" });
124: checkValues(readContext2, 1079, new String[] { "foo", "bar" },
125: new String[] { "baz" });
126: checkValues(readContext2, 1080, new String[] { "foo", "bar",
127: "baz" }, new String[] {});
128: checkValues(readContext2, 1120, new String[] { "foo", "bar",
129: "baz" }, new String[] {});
130:
131: checkValues(readContext3, 1100, new String[] { "foo", "bar",
132: "baz" }, new String[] {});
133:
134: this .trans.endWrite(writeContext1, 1140);
135:
136: checkValues(readContext1b, 1160, new String[] { "foo", "bar",
137: "baz" }, new String[] {});
138: checkValues(readContext2b, 1160, new String[] { "foo", "bar",
139: "baz" }, new String[] {});
140: checkValues(readContext3b, 1160, new String[] { "foo", "bar",
141: "baz" }, new String[] {});
142:
143: this .trans.endWrite(writeContext2, 1180);
144:
145: checkValues(readContext1c, 1200, new String[] { "foo", "bar",
146: "baz" }, new String[] {});
147: checkValues(readContext2c, 1200, new String[] { "foo", "bar",
148: "baz" }, new String[] {});
149: checkValues(readContext3c, 1200, new String[] { "foo", "bar",
150: "baz" }, new String[] {});
151:
152: StandardTransactionalObject.Context readContext4 = this .trans
153: .startRead(1180);
154:
155: checkValues(readContext4, 1180, new String[] { "bar", "baz" },
156: new String[] { "foo" });
157: }
158:
159: public void xtestSlop() throws Exception {
160: this .trans = new StandardTransactionalObject("test-object",
161: 100, "foo", 1000);
162:
163: StandardTransactionalObject.Context context1 = this .trans
164: .startWrite("bar", 1050);
165: checkValues(1050, new String[] { "foo", "bar" }, new String[] {
166: "baz", "quux" });
167: this .trans.endWrite(context1, 1070);
168:
169: checkValues(1070, new String[] { "foo", "bar" }, new String[] {
170: "baz", "quux" });
171: checkValues(1100, new String[] { "foo", "bar" }, new String[] {
172: "baz", "quux" });
173: checkValues(1169, new String[] { "foo", "bar" }, new String[] {
174: "baz", "quux" });
175: checkValues(1170, new String[] { "foo", "bar" }, new String[] {
176: "baz", "quux" });
177: checkValues(1171, new String[] { "bar" }, new String[] { "foo",
178: "baz", "quux" });
179: checkValues(1500, new String[] { "bar" }, new String[] { "foo",
180: "baz", "quux" });
181:
182: context1 = this .trans.startWrite("baz", 2000);
183: checkValues(2000, new String[] { "bar", "baz" }, new String[] {
184: "foo", "quux" });
185: checkValues(2050, new String[] { "bar", "baz" }, new String[] {
186: "foo", "quux" });
187: checkValues(2150, new String[] { "bar", "baz" }, new String[] {
188: "foo", "quux" });
189: StandardTransactionalObject.Context context2 = this .trans
190: .startWrite("quux", 2200);
191:
192: checkValues(2200, new String[] { "bar", "baz", "quux" },
193: new String[] { "foo" });
194: checkValues(2300, new String[] { "bar", "baz", "quux" },
195: new String[] { "foo" });
196: checkValues(2400, new String[] { "bar", "baz", "quux" },
197: new String[] { "foo" });
198:
199: this .trans.endWrite(context2, 2500);
200: checkValues(2500, new String[] { "bar", "baz", "quux" },
201: new String[] { "foo" });
202: checkValues(2599, new String[] { "bar", "baz", "quux" },
203: new String[] { "foo" });
204: checkValues(2600, new String[] { "bar", "baz", "quux" },
205: new String[] { "foo" });
206: checkValues(2601, new String[] { "baz", "quux" }, new String[] {
207: "foo", "bar" });
208:
209: this .trans.endWrite(context1, 2800);
210: checkValues(2800, new String[] { "baz", "quux" }, new String[] {
211: "foo", "bar" });
212: checkValues(2801, new String[] { "baz", "quux" }, new String[] {
213: "foo", "bar" });
214: checkValues(2900, new String[] { "baz", "quux" }, new String[] {
215: "foo", "bar" });
216:
217: // This is important: because we can't actually know which write happened first, it needs to keep returning both
218: // values.
219: checkValues(2901, new String[] { "baz", "quux" }, new String[] {
220: "foo", "bar" });
221: checkValues(5000, new String[] { "baz", "quux" }, new String[] {
222: "foo", "bar" });
223: }
224:
225: private void checkValues(String[] accepted, String[] notAccepted) {
226: checkValues(System.currentTimeMillis(), accepted, notAccepted);
227: }
228:
229: private void checkValues(long when, String[] accepted,
230: String[] notAccepted) {
231: checkValues(this .trans.startRead(when), when, accepted,
232: notAccepted);
233: }
234:
235: private void checkValues(
236: StandardTransactionalObject.Context context, long when,
237: String[] accepted, String[] notAccepted) {
238: for (int i = 0; i < accepted.length; ++i) {
239: this .trans.endRead(context, accepted[i], when);
240: }
241:
242: for (int i = 0; i < notAccepted.length; ++i) {
243: try {
244: this .trans.endRead(context, notAccepted[i], when);
245: fail("Didn't get TCAE on endRead with bad value");
246: } catch (TCAssertionError tcae) {
247: // ok
248: }
249: }
250:
251: }
252:
253: }
|