001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.camel;
019
020import static java.util.Collections.emptyMap;
021import static java.util.Collections.singletonList;
022import static java.util.Collections.singletonMap;
023import static org.junit.Assert.assertEquals;
024import static org.junit.Assert.assertFalse;
025import static org.junit.Assert.assertNull;
026import static org.junit.Assert.assertTrue;
027import static org.mockito.Matchers.any;
028import static org.mockito.Matchers.eq;
029import static org.mockito.Mockito.when;
030
031import java.io.InputStream;
032import java.net.URI;
033import java.util.List;
034
035import org.fcrepo.client.FcrepoClient;
036import org.fcrepo.client.FcrepoOperationFailedException;
037import org.fcrepo.client.FcrepoResponse;
038import org.fcrepo.client.GetBuilder;
039import org.fcrepo.client.HeadBuilder;
040import org.fcrepo.client.PostBuilder;
041import org.junit.Before;
042import org.junit.Test;
043import org.junit.runner.RunWith;
044import org.mockito.Mock;
045import org.mockito.runners.MockitoJUnitRunner;
046import org.springframework.transaction.CannotCreateTransactionException;
047import org.springframework.transaction.TransactionDefinition;
048import org.springframework.transaction.TransactionSystemException;
049import org.springframework.transaction.support.DefaultTransactionDefinition;
050import org.springframework.transaction.support.DefaultTransactionStatus;
051import org.springframework.transaction.support.TransactionTemplate;
052
053/**
054 * @author Aaron Coburn
055 */
056@RunWith(MockitoJUnitRunner.class)
057public class FcrepoTransactionManagerTest {
058
059    @Mock
060    private FcrepoClient mockClient;
061
062    @Mock
063    private PostBuilder mockPostBuilder, mockPostBuilder2;
064
065    @Mock
066    private GetBuilder mockGetBuilder;
067
068    @Mock
069    private HeadBuilder mockHeadBuilder;
070
071    @Before
072    @SuppressWarnings("unchecked")
073    public void setUp() throws Exception {
074        when(mockClient.head(any(URI.class))).thenReturn(mockHeadBuilder);
075        when(mockClient.get(any(URI.class))).thenReturn(mockGetBuilder);
076        when(mockGetBuilder.accept(any(String.class))).thenReturn(mockGetBuilder);
077        when(mockGetBuilder.preferMinimal()).thenReturn(mockGetBuilder);
078        when(mockGetBuilder.preferRepresentation(any(List.class), any(List.class))).thenReturn(mockGetBuilder);
079        when(mockClient.post(any(URI.class))).thenReturn(mockPostBuilder);
080        when(mockPostBuilder.body(any(InputStream.class), any(String.class))).thenReturn(mockPostBuilder);
081        when(mockPostBuilder2.body(any(InputStream.class), any(String.class))).thenReturn(mockPostBuilder2);
082    }
083
084    @Test
085    public void testProperties() {
086        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
087        final String baseUrl = "http://localhost:8080/rest";
088        final String authUsername = "foo";
089        final String authPassword = "bar";
090        final String authHost = "baz";
091        final String transactionId = "1234567890";
092
093        assertNull(txMgr.getAuthUsername());
094        assertNull(txMgr.getAuthPassword());
095        assertNull(txMgr.getAuthHost());
096        assertNull(txMgr.getBaseUrl());
097
098        txMgr.setBaseUrl(baseUrl);
099        txMgr.setAuthUsername(authUsername);
100        txMgr.setAuthPassword(authPassword);
101        txMgr.setAuthHost(authHost);
102
103        assertEquals(baseUrl, txMgr.getBaseUrl());
104        assertEquals(authUsername, txMgr.getAuthUsername());
105        assertEquals(authPassword, txMgr.getAuthPassword());
106        assertEquals(authHost, txMgr.getAuthHost());
107    }
108
109    @Test
110    public void testTransactionCommit() throws FcrepoOperationFailedException {
111        final String baseUrl = "http://localhost:8080/rest";
112        final String tx = "tx:1234567890";
113        final URI commitUri = URI.create(baseUrl + "/" + tx + FcrepoConstants.COMMIT);
114        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
115        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
116        txMgr.setBaseUrl(baseUrl);
117        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
118
119        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
120        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
121                TransactionDefinition.PROPAGATION_REQUIRED);
122
123        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
124        transactionTemplate.afterPropertiesSet();
125
126        when(mockClient.post(eq(beginUri))).thenReturn(mockPostBuilder);
127        when(mockClient.post(eq(commitUri))).thenReturn(mockPostBuilder2);
128        when(mockPostBuilder.perform()).thenReturn(
129                new FcrepoResponse(beginUri, 201, singletonMap("Location", singletonList(baseUrl + "/" + tx)), null));
130        when(mockPostBuilder2.perform()).thenReturn(
131                new FcrepoResponse(commitUri, 201, emptyMap(), null));
132
133        DefaultTransactionStatus status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
134        FcrepoTransactionObject txObj = (FcrepoTransactionObject)status.getTransaction();
135
136        assertEquals(tx, txObj.getSessionId());
137        assertFalse(status.isCompleted());
138
139        status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
140
141        txMgr.commit(status);
142
143        txObj = (FcrepoTransactionObject)status.getTransaction();
144
145        assertNull(txObj.getSessionId());
146        assertTrue(status.isCompleted());
147    }
148
149    @Test
150    public void testTransactionRollback() throws FcrepoOperationFailedException {
151        final String baseUrl = "http://localhost:8080/rest";
152        final String tx = "tx:1234567890";
153        final URI commitUri = URI.create(baseUrl + "/" + tx + FcrepoConstants.COMMIT);
154        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
155        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
156        txMgr.setBaseUrl(baseUrl);
157        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
158
159        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
160        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
161                TransactionDefinition.PROPAGATION_REQUIRED);
162
163        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
164        transactionTemplate.afterPropertiesSet();
165
166        when(mockClient.post(eq(beginUri))).thenReturn(mockPostBuilder);
167        when(mockClient.post(eq(commitUri))).thenReturn(mockPostBuilder2);
168        when(mockPostBuilder.perform()).thenReturn(
169                new FcrepoResponse(beginUri, 201, singletonMap("Location", singletonList(baseUrl + "/" + tx)), null));
170        when(mockPostBuilder2.perform()).thenReturn(
171                new FcrepoResponse(commitUri, 201, emptyMap(), null));
172
173        DefaultTransactionStatus status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
174        FcrepoTransactionObject txObj = (FcrepoTransactionObject)status.getTransaction();
175
176        assertEquals(tx, txObj.getSessionId());
177        assertFalse(status.isCompleted());
178
179        status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
180
181        txMgr.rollback(status);
182
183        txObj = (FcrepoTransactionObject)status.getTransaction();
184
185        assertNull(txObj.getSessionId());
186        assertTrue(status.isCompleted());
187    }
188
189    @Test (expected = CannotCreateTransactionException.class)
190    public void testTransactionBeginError() throws FcrepoOperationFailedException {
191        final String baseUrl = "http://localhost:8080/rest";
192        final String tx = "tx:1234567890";
193        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
194        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
195        txMgr.setBaseUrl(baseUrl);
196        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
197
198        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
199        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
200                TransactionDefinition.PROPAGATION_REQUIRED);
201
202        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
203        transactionTemplate.afterPropertiesSet();
204
205        when(mockPostBuilder.perform()).thenThrow(
206                new FcrepoOperationFailedException(beginUri, 400, "Bad Request"));
207
208        txMgr.getTransaction(txDef);
209    }
210
211    @Test (expected = CannotCreateTransactionException.class)
212    public void testTransactionBeginNoLocationError() throws FcrepoOperationFailedException {
213        final String baseUrl = "http://localhost:8080/rest";
214        final String tx = "tx:1234567890";
215        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
216        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
217        txMgr.setBaseUrl(baseUrl);
218        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
219
220        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
221        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
222                TransactionDefinition.PROPAGATION_REQUIRED);
223
224        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
225        transactionTemplate.afterPropertiesSet();
226
227        when(mockPostBuilder.perform()).thenReturn(
228                new FcrepoResponse(beginUri, 201, emptyMap(), null));
229
230        txMgr.getTransaction(txDef);
231    }
232
233    @Test (expected = CannotCreateTransactionException.class)
234    public void testTransactionNullResponseError() throws FcrepoOperationFailedException {
235        final String baseUrl = "http://localhost:8080/rest";
236        final String tx = "tx:1234567890";
237        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
238        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
239        txMgr.setBaseUrl(baseUrl);
240        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
241
242        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
243        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
244                TransactionDefinition.PROPAGATION_REQUIRED);
245
246        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
247        transactionTemplate.afterPropertiesSet();
248
249        when(mockPostBuilder.perform()).thenReturn(null);
250
251        txMgr.getTransaction(txDef);
252    }
253
254    @Test (expected = TransactionSystemException.class)
255    public void testTransactionCommitError() throws FcrepoOperationFailedException {
256        final String baseUrl = "http://localhost:8080/rest";
257        final String tx = "tx:1234567890";
258        final URI commitUri = URI.create(baseUrl + "/" + tx + FcrepoConstants.COMMIT);
259        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
260        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
261        txMgr.setBaseUrl(baseUrl);
262        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
263
264        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
265        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
266                TransactionDefinition.PROPAGATION_REQUIRED);
267
268        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
269        transactionTemplate.afterPropertiesSet();
270
271        when(mockClient.post(eq(beginUri))).thenReturn(mockPostBuilder);
272        when(mockClient.post(eq(commitUri))).thenReturn(mockPostBuilder2);
273        when(mockPostBuilder.perform()).thenReturn(
274                new FcrepoResponse(beginUri, 201, singletonMap("Location", singletonList(baseUrl + "/" + tx)), null));
275        when(mockPostBuilder2.perform()).thenThrow(
276                new FcrepoOperationFailedException(commitUri, 400, "Bad Request"));
277
278        DefaultTransactionStatus status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
279
280        final FcrepoTransactionObject txObj = (FcrepoTransactionObject)status.getTransaction();
281        assertEquals(tx, txObj.getSessionId());
282        assertFalse(status.isCompleted());
283
284        status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
285        txMgr.commit(status);
286    }
287
288    @Test (expected = TransactionSystemException.class)
289    public void testTransactionRollbackError() throws FcrepoOperationFailedException {
290        final String baseUrl = "http://localhost:8080/rest";
291        final String tx = "tx:1234567890";
292        final URI rollbackUri = URI.create(baseUrl + "/" + tx + FcrepoConstants.ROLLBACK);
293        final URI beginUri = URI.create(baseUrl + FcrepoConstants.TRANSACTION);
294        final FcrepoTransactionManager txMgr = new FcrepoTransactionManager();
295        txMgr.setBaseUrl(baseUrl);
296        TestUtils.setField(txMgr, "fcrepoClient", mockClient);
297
298        final TransactionTemplate transactionTemplate = new TransactionTemplate(txMgr);
299        final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(
300                TransactionDefinition.PROPAGATION_REQUIRED);
301
302        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
303        transactionTemplate.afterPropertiesSet();
304
305        when(mockClient.post(eq(beginUri))).thenReturn(mockPostBuilder);
306        when(mockClient.post(eq(rollbackUri))).thenReturn(mockPostBuilder2);
307        when(mockPostBuilder.perform()).thenReturn(
308                new FcrepoResponse(beginUri, 201, singletonMap("Location", singletonList(baseUrl + "/" + tx)), null));
309        when(mockPostBuilder2.perform()).thenThrow(
310                new FcrepoOperationFailedException(rollbackUri, 400, "Bad Request"));
311
312        DefaultTransactionStatus status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
313
314        final FcrepoTransactionObject txObj = (FcrepoTransactionObject)status.getTransaction();
315        assertEquals(tx, txObj.getSessionId());
316        assertFalse(status.isCompleted());
317
318        status = (DefaultTransactionStatus)txMgr.getTransaction(txDef);
319        txMgr.rollback(status);
320    }
321}