~maxb/connectorj/5.0

« back to all changes in this revision

Viewing changes to connector-j/src/testsuite/simple/XATest.java

  • Committer: mmatthews
  • Date: 2007-10-11 20:04:05 UTC
  • Revision ID: svn-v3-trunk0:bce1ec22-edf6-0310-a851-a6aae2aa6c29:branches%2Fbranch_5_0:6637
Changed layout

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 Copyright (C) 2005 MySQL AB
3
 
 
4
 
 This program is free software; you can redistribute it and/or modify
5
 
 it under the terms of version 2 of the GNU General Public License as 
6
 
 published by the Free Software Foundation.
7
 
 
8
 
 There are special exceptions to the terms and conditions of the GPL 
9
 
 as it is applied to this software. View the full text of the 
10
 
 exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
11
 
 software distribution.
12
 
 
13
 
 This program is distributed in the hope that it will be useful,
14
 
 but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 GNU General Public License for more details.
17
 
 
18
 
 You should have received a copy of the GNU General Public License
19
 
 along with this program; if not, write to the Free Software
20
 
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 
 
22
 
*/
23
 
 
24
 
package testsuite.simple;
25
 
 
26
 
import java.io.ByteArrayOutputStream;
27
 
import java.io.DataOutputStream;
28
 
import java.io.IOException;
29
 
import java.rmi.server.UID;
30
 
import java.sql.Connection;
31
 
import java.sql.SQLException;
32
 
import java.sql.Savepoint;
33
 
 
34
 
import javax.sql.XAConnection;
35
 
import javax.transaction.xa.XAException;
36
 
import javax.transaction.xa.XAResource;
37
 
import javax.transaction.xa.Xid;
38
 
 
39
 
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
40
 
import com.mysql.jdbc.jdbc2.optional.MysqlXid;
41
 
 
42
 
import testsuite.BaseTestCase;
43
 
 
44
 
/**
45
 
 * Unit tests for our XA implementation.
46
 
 * 
47
 
 * @version $Id: $
48
 
 */
49
 
public class XATest extends BaseTestCase {
50
 
    MysqlXADataSource xaDs;
51
 
    
52
 
        public XATest(String name) {
53
 
                super(name);
54
 
                
55
 
                this.xaDs = new MysqlXADataSource();
56
 
                this.xaDs.setUrl(BaseTestCase.dbUrl);
57
 
                this.xaDs.setRollbackOnPooledClose(true);
58
 
        }
59
 
 
60
 
        /**
61
 
         * Tests that simple distributed transaction processing works as expected.
62
 
         * 
63
 
         * @throws Exception
64
 
         *             if the test fails.
65
 
         */
66
 
        public void testCoordination() throws Exception {
67
 
                if (!versionMeetsMinimum(5, 0)) {
68
 
                        return;
69
 
                }
70
 
                
71
 
                createTable("testCoordination", "(field1 int) ENGINE=InnoDB");
72
 
                
73
 
                Connection conn1 = null;
74
 
                Connection conn2 = null;
75
 
                XAConnection xaConn1 = null;
76
 
                XAConnection xaConn2 = null;
77
 
                
78
 
                try {
79
 
                        xaConn1 = getXAConnection();
80
 
                        XAResource xaRes1 = xaConn1.getXAResource();
81
 
                        conn1 = xaConn1.getConnection();
82
 
                        
83
 
                        xaConn2 = getXAConnection();
84
 
                        XAResource xaRes2 = xaConn2.getXAResource();
85
 
                        conn2 = xaConn2.getConnection();
86
 
                        
87
 
                        Xid xid1 = createXid();
88
 
                        Xid xid2 = createXid(xid1);
89
 
                        
90
 
                        xaRes1.start(xid1, XAResource.TMNOFLAGS);
91
 
                        xaRes2.start(xid2, XAResource.TMNOFLAGS);
92
 
                        conn1.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (1)");
93
 
                        conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)");
94
 
                        xaRes1.end(xid1, XAResource.TMSUCCESS);
95
 
                        xaRes2.end(xid2, XAResource.TMSUCCESS);
96
 
                        
97
 
                        xaRes1.prepare(xid1);
98
 
                        xaRes2.prepare(xid2);
99
 
                        
100
 
                        xaRes1.commit(xid1, false);
101
 
                        xaRes2.commit(xid2, false);
102
 
                        
103
 
                        this.rs = this.stmt.executeQuery("SELECT field1 FROM testCoordination ORDER BY field1");
104
 
                        
105
 
                        assertTrue(this.rs.next());
106
 
                        assertEquals(1, this.rs.getInt(1));
107
 
                        
108
 
                        assertTrue(this.rs.next());
109
 
                        assertEquals(2, this.rs.getInt(1));
110
 
                        
111
 
                        this.stmt.executeUpdate("TRUNCATE TABLE testCoordination");
112
 
                        
113
 
                        //
114
 
                        // Now test rollback
115
 
                        //
116
 
                        
117
 
                        xid1 = createXid();
118
 
                        xid2 = createXid(xid1);
119
 
                        
120
 
                        xaRes1.start(xid1, XAResource.TMNOFLAGS);
121
 
                        xaRes2.start(xid2, XAResource.TMNOFLAGS);
122
 
                        conn1.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (1)");
123
 
                        
124
 
                        // ensure visibility
125
 
                        assertEquals("1", getSingleIndexedValueWithQuery(conn1, 1, "SELECT field1 FROM testCoordination WHERE field1=1").toString());
126
 
                        
127
 
                        conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)");
128
 
                        
129
 
                        // ensure visibility
130
 
                        assertEquals("2", getSingleIndexedValueWithQuery(conn2, 1, "SELECT field1 FROM testCoordination WHERE field1=2").toString());
131
 
                        
132
 
                        xaRes1.end(xid1, XAResource.TMSUCCESS);
133
 
                        xaRes2.end(xid2, XAResource.TMSUCCESS);
134
 
                        
135
 
                        xaRes1.prepare(xid1);
136
 
                        xaRes2.prepare(xid2);
137
 
                        
138
 
                        xaRes1.rollback(xid1);
139
 
                        xaRes2.rollback(xid2);
140
 
                        
141
 
                        this.rs = this.stmt.executeQuery("SELECT field1 FROM testCoordination ORDER BY field1");
142
 
                        
143
 
                        assertTrue(!this.rs.next());
144
 
                } finally {
145
 
                        if (conn1 != null) {
146
 
                                conn1.close();
147
 
                        }
148
 
                        
149
 
                        if (conn2 != null) {
150
 
                                conn2.close();
151
 
                        }
152
 
                        
153
 
                        if (xaConn1 != null) {
154
 
                                xaConn1.close();
155
 
                        }
156
 
                        
157
 
                        if (xaConn2 != null) {
158
 
                                xaConn2.close();
159
 
                        }
160
 
                }
161
 
        }
162
 
        
163
 
        protected XAConnection getXAConnection() throws Exception {
164
 
                return this.xaDs.getXAConnection();
165
 
        }
166
 
        
167
 
        /**
168
 
         * Tests that XA RECOVER works as expected.
169
 
         * 
170
 
         * @throws Exception
171
 
         *             if test fails
172
 
         */
173
 
        public void testRecover() throws Exception {
174
 
                if (!versionMeetsMinimum(5, 0)) {
175
 
                        return;
176
 
                }
177
 
 
178
 
                XAConnection xaConn = null, recoverConn = null;
179
 
                
180
 
                try {                   
181
 
                        xaConn = getXAConnection();
182
 
                        
183
 
                        Connection c = xaConn.getConnection();
184
 
                        Xid xid = createXid();
185
 
                        
186
 
                        XAResource xaRes = xaConn.getXAResource();
187
 
                        xaRes.start(xid, XAResource.TMNOFLAGS);
188
 
                        c.createStatement().executeQuery("SELECT 1");
189
 
                        xaRes.end(xid, XAResource.TMSUCCESS);
190
 
                        xaRes.prepare(xid);
191
 
                        
192
 
                        // Now try and recover
193
 
                        recoverConn = getXAConnection();
194
 
                        
195
 
                        XAResource recoverRes = recoverConn.getXAResource();
196
 
                        
197
 
                        Xid[] recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);
198
 
                        
199
 
                        assertTrue(recoveredXids != null);
200
 
                        assertTrue(recoveredXids.length > 0);
201
 
                        
202
 
                        boolean xidFound = false;
203
 
                        
204
 
                        for (int i = 0; i < recoveredXids.length; i++) {
205
 
                                if (recoveredXids[i] != null &&
206
 
                                        recoveredXids[i].equals(xid)) {
207
 
                                        xidFound = true;
208
 
                                        
209
 
                                        break;
210
 
                                }
211
 
                        }
212
 
                        
213
 
                        assertTrue(xidFound);
214
 
 
215
 
                        recoverRes = recoverConn.getXAResource();
216
 
 
217
 
                        recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN);
218
 
 
219
 
                        assertTrue(recoveredXids != null);
220
 
                        assertTrue(recoveredXids.length > 0);
221
 
 
222
 
                        xidFound = false;
223
 
 
224
 
                        for (int i = 0; i < recoveredXids.length; i++) {
225
 
                                if (recoveredXids[i] != null &&
226
 
                                                recoveredXids[i].equals(xid)) {
227
 
                                        xidFound = true;
228
 
 
229
 
                                        break;
230
 
                                }
231
 
                        }
232
 
 
233
 
                        assertTrue(xidFound);
234
 
                                
235
 
                        // Test flags
236
 
                        recoverRes.recover(XAResource.TMSTARTRSCAN);
237
 
                        recoverRes.recover(XAResource.TMENDRSCAN);
238
 
                        recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);
239
 
                        
240
 
                        // This should fail
241
 
                        try {
242
 
                                recoverRes.recover(XAResource.TMSUCCESS);
243
 
                                fail("XAException should have been thrown");
244
 
                        } catch (XAException xaEx) {
245
 
                                assertEquals(XAException.XAER_INVAL, xaEx.errorCode);
246
 
                        }
247
 
                } finally {
248
 
                        if (xaConn != null) {
249
 
                                xaConn.close();
250
 
                        }
251
 
                        
252
 
                        if (recoverConn != null) {
253
 
                                recoverConn.close();
254
 
                        }
255
 
                }
256
 
        }
257
 
 
258
 
        /**
259
 
         * Tests operation of local transactions on XAConnections when global
260
 
         * transactions are in or not in progress (follows from BUG#17401).
261
 
         * 
262
 
         * @throws Exception
263
 
         *             if the testcase fails
264
 
         */
265
 
        public void testLocalTransaction() throws Exception {
266
 
 
267
 
                if (!versionMeetsMinimum(5, 0) || isRunningOnJdk131()) {
268
 
                        return;
269
 
                }
270
 
 
271
 
                createTable("testLocalTransaction", "(field1 int) ENGINE=InnoDB");
272
 
 
273
 
                Connection conn1 = null;
274
 
 
275
 
                XAConnection xaConn1 = null;
276
 
 
277
 
                try {
278
 
                        xaConn1 = getXAConnection();
279
 
                        XAResource xaRes1 = xaConn1.getXAResource();
280
 
                        conn1 = xaConn1.getConnection();
281
 
                        assertEquals(false, conn1.getAutoCommit());
282
 
                        conn1.setAutoCommit(true);
283
 
                        conn1.createStatement().executeUpdate(
284
 
                                        "INSERT INTO testLocalTransaction VALUES (1)");
285
 
                        assertEquals("1", getSingleIndexedValueWithQuery(conn1, 1,
286
 
                                        "SELECT field1 FROM testLocalTransaction").toString());
287
 
 
288
 
                        conn1.createStatement().executeUpdate(
289
 
                                        "TRUNCATE TABLE testLocalTransaction");
290
 
                        conn1.setAutoCommit(false);
291
 
                        conn1.createStatement().executeUpdate(
292
 
                                        "INSERT INTO testLocalTransaction VALUES (2)");
293
 
                        assertEquals("2", getSingleIndexedValueWithQuery(conn1, 1,
294
 
                                        "SELECT field1 FROM testLocalTransaction").toString());
295
 
                        conn1.rollback();
296
 
                        assertEquals(0, getRowCount("testLocalTransaction"));
297
 
 
298
 
                        conn1.createStatement().executeUpdate(
299
 
                                        "INSERT INTO testLocalTransaction VALUES (3)");
300
 
                        assertEquals("3", getSingleIndexedValueWithQuery(conn1, 1,
301
 
                                        "SELECT field1 FROM testLocalTransaction").toString());
302
 
                        conn1.commit();
303
 
                        assertEquals("3", getSingleIndexedValueWithQuery(conn1, 1,
304
 
                                        "SELECT field1 FROM testLocalTransaction").toString());
305
 
                        conn1.commit();
306
 
                        
307
 
                        Savepoint sp = conn1.setSavepoint();
308
 
                        conn1.rollback(sp);
309
 
                        sp = conn1.setSavepoint("abcd");
310
 
                        conn1.rollback(sp);
311
 
                        Savepoint spSaved = sp;
312
 
                        
313
 
                        Xid xid = createXid();
314
 
                        xaRes1.start(xid, XAResource.TMNOFLAGS);
315
 
 
316
 
                        try {
317
 
                                try {
318
 
                                        conn1.setAutoCommit(true);
319
 
                                } catch (SQLException sqlEx) {
320
 
                                        // we expect an exception here
321
 
                                        assertEquals("2D000", sqlEx.getSQLState());
322
 
                                }
323
 
 
324
 
                                try {
325
 
                                        conn1.commit();
326
 
                                } catch (SQLException sqlEx) {
327
 
                                        // we expect an exception here
328
 
                                        assertEquals("2D000", sqlEx.getSQLState());
329
 
                                }
330
 
 
331
 
                                try {
332
 
                                        conn1.rollback();
333
 
                                } catch (SQLException sqlEx) {
334
 
                                        // we expect an exception here
335
 
                                        assertEquals("2D000", sqlEx.getSQLState());
336
 
                                }
337
 
                                
338
 
                                try {
339
 
                                        sp = conn1.setSavepoint();
340
 
                                } catch (SQLException sqlEx) {
341
 
                                        // we expect an exception here
342
 
                                        assertEquals("2D000", sqlEx.getSQLState());
343
 
                                }
344
 
                        
345
 
                                try {
346
 
                                        conn1.rollback(spSaved);
347
 
                                } catch (SQLException sqlEx) {
348
 
                                        // we expect an exception here
349
 
                                        assertEquals("2D000", sqlEx.getSQLState());
350
 
                                }
351
 
                                
352
 
                                try {
353
 
                                        sp = conn1.setSavepoint("abcd");
354
 
                                } catch (SQLException sqlEx) {
355
 
                                        // we expect an exception here
356
 
                                        assertEquals("2D000", sqlEx.getSQLState());
357
 
                                }
358
 
                                
359
 
                                try {
360
 
                                        conn1.rollback(spSaved);
361
 
                                } catch (SQLException sqlEx) {
362
 
                                        // we expect an exception here
363
 
                                        assertEquals("2D000", sqlEx.getSQLState());
364
 
                                }
365
 
                        } finally {
366
 
                                xaRes1.forget(xid);
367
 
                        }
368
 
                } finally {
369
 
                        if (xaConn1 != null) {
370
 
                                xaConn1.close();
371
 
                        }
372
 
                }
373
 
        }
374
 
        
375
 
        public void testSuspendableTx() throws Exception {
376
 
                if (!versionMeetsMinimum(5, 0) || isRunningOnJdk131()) {
377
 
                        return;
378
 
                }
379
 
                
380
 
                Connection conn1 = null;
381
 
 
382
 
                MysqlXADataSource suspXaDs = new MysqlXADataSource();
383
 
                suspXaDs.setUrl(BaseTestCase.dbUrl);
384
 
                suspXaDs.setPinGlobalTxToPhysicalConnection(true);
385
 
                suspXaDs.setRollbackOnPooledClose(true);
386
 
                
387
 
                XAConnection xaConn1 = null;
388
 
                
389
 
                Xid xid = createXid();
390
 
                
391
 
                try {
392
 
                        /*
393
 
                                -- works using RESUME
394
 
                                xa start 0x123,0x456;
395
 
                                select * from foo;
396
 
                                xa end 0x123,0x456;
397
 
                                xa start 0x123,0x456 resume;
398
 
                                select * from foo;
399
 
                                xa end 0x123,0x456;
400
 
                                xa commit 0x123,0x456 one phase;
401
 
                         */
402
 
                        
403
 
                        xaConn1 = suspXaDs.getXAConnection();
404
 
                        XAResource xaRes1 = xaConn1.getXAResource();
405
 
                        conn1 = xaConn1.getConnection();
406
 
                        xaRes1.start(xid, XAResource.TMNOFLAGS);
407
 
                        conn1.createStatement().executeQuery("SELECT 1");
408
 
                        xaRes1.end(xid, XAResource.TMSUCCESS);
409
 
                        xaRes1.start(xid, XAResource.TMRESUME);
410
 
                        conn1.createStatement().executeQuery("SELECT 1");
411
 
                        xaRes1.end(xid, XAResource.TMSUCCESS);
412
 
                        xaRes1.commit(xid, true);
413
 
                        
414
 
                        xaConn1.close();
415
 
                        
416
 
                        /*
417
 
 
418
 
                                -- fails using JOIN
419
 
                                xa start 0x123,0x456;
420
 
                                select * from foo;
421
 
                                xa end 0x123,0x456;
422
 
                                xa start 0x123,0x456 join;
423
 
                                select * from foo;
424
 
                                xa end 0x123,0x456;
425
 
                                xa commit 0x123,0x456 one phase;
426
 
                                */
427
 
                
428
 
                        xaConn1 = suspXaDs.getXAConnection();
429
 
                        xaRes1 = xaConn1.getXAResource();
430
 
                        conn1 = xaConn1.getConnection();
431
 
                        xaRes1.start(xid, XAResource.TMNOFLAGS);
432
 
                        conn1.createStatement().executeQuery("SELECT 1");
433
 
                        xaRes1.end(xid, XAResource.TMSUCCESS);
434
 
                        xaRes1.start(xid, XAResource.TMJOIN);
435
 
                        conn1.createStatement().executeQuery("SELECT 1");
436
 
                        xaRes1.end(xid, XAResource.TMSUCCESS);
437
 
                        xaRes1.commit(xid, true);
438
 
                } finally {
439
 
                        if (xaConn1 != null) {
440
 
                                xaConn1.close();
441
 
                        }
442
 
                }
443
 
        }
444
 
 
445
 
        private Xid createXid() throws IOException {
446
 
                ByteArrayOutputStream gtridOut = new ByteArrayOutputStream();
447
 
                DataOutputStream dataOut = new DataOutputStream(gtridOut);
448
 
                new UID().write(dataOut);
449
 
                
450
 
                final byte[] gtrid = gtridOut.toByteArray();
451
 
                
452
 
                ByteArrayOutputStream bqualOut = new ByteArrayOutputStream();
453
 
                dataOut = new DataOutputStream(bqualOut);
454
 
                
455
 
                new UID().write(dataOut);
456
 
                
457
 
                final byte[] bqual = bqualOut.toByteArray();
458
 
                
459
 
                Xid xid = new MysqlXid(gtrid, bqual, 3306);
460
 
                return xid;
461
 
        }
462
 
 
463
 
        private Xid createXid(Xid xidToBranch) throws IOException {
464
 
                ByteArrayOutputStream bqualOut = new ByteArrayOutputStream();
465
 
                DataOutputStream dataOut = new DataOutputStream(bqualOut);
466
 
                
467
 
                new UID().write(dataOut);
468
 
                
469
 
                final byte[] bqual = bqualOut.toByteArray();
470
 
                
471
 
                Xid xid = new MysqlXid(xidToBranch.getGlobalTransactionId(), bqual, 3306);
472
 
                
473
 
                return xid;
474
 
        }
475
 
}