001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.client.integration;
007
008import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
009import static javax.ws.rs.core.Response.Status.CREATED;
010import static javax.ws.rs.core.Response.Status.NO_CONTENT;
011import static org.fcrepo.client.FcrepoClient.TRANSACTION_ENDPOINT;
012import static org.junit.Assert.assertEquals;
013import static org.junit.Assert.assertNotNull;
014import static org.junit.Assert.assertTrue;
015
016import java.io.IOException;
017import java.net.URI;
018import java.time.Instant;
019import java.time.ZoneId;
020import java.time.format.DateTimeFormatter;
021import java.util.UUID;
022
023
024import org.fcrepo.client.FcrepoClient;
025import org.fcrepo.client.FedoraHeaderConstants;
026import org.junit.AfterClass;
027import org.junit.BeforeClass;
028import org.junit.Test;
029
030/**
031 * Tests against the Fedora Transaction API
032 *
033 * @author mikejritter
034 */
035public class FcrepoTransactionIT extends AbstractResourceIT {
036
037    private static FcrepoClient client;
038
039    private static final String FEDORA_ADMIN = "fedoraAdmin";
040    private static final DateTimeFormatter FORMATTER = RFC_1123_DATE_TIME.withZone(ZoneId.of("UTC"));
041
042    @BeforeClass
043    public static void beforeClass() {
044        client = FcrepoClient.client()
045                             .credentials(FEDORA_ADMIN, FEDORA_ADMIN)
046                             .authScope(HOSTNAME)
047                             .build();
048    }
049
050    @AfterClass
051    public static void afterClass() throws IOException {
052        client.close();
053    }
054
055    @Test
056    public void testStartWithTxEndpoint() throws Exception {
057        try (final var txClient = client.startTransactionClient(new URI(SERVER_ADDRESS + TRANSACTION_ENDPOINT))) {
058            final var txURI = txClient.getTransactionURI();
059            assertNotNull(txURI);
060        }
061    }
062
063    @Test
064    public void testTransactionCommit() throws Exception {
065        try (final var txClient = client.startTransactionClient(new URI(SERVER_ADDRESS))) {
066            final var txURI = txClient.getTransactionURI();
067
068            // create a container
069            final var container = UUID.randomUUID().toString();
070            try (final var response = txClient.put(new URI(SERVER_ADDRESS + container)).perform()) {
071                assertEquals(CREATED.getStatusCode(), response.getStatusCode());
072                assertNotNull(response.getTransactionUri());
073                assertEquals(txURI, response.getTransactionUri());
074            }
075
076            // commit tx
077            try (final var response = txClient.commit().perform()) {
078                assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode());
079            }
080        }
081    }
082
083    @Test
084    public void testTransactionKeepAlive() throws Exception {
085        final String expiry;
086        final URI location;
087
088        try (final var txClient = client.startTransactionClient(new URI(SERVER_ADDRESS))) {
089            location = txClient.getTransactionURI();
090            assertNotNull(location);
091
092            // the initial transaction currently returns Expires rather than Atomic-Expires
093            try (var response = txClient.status().perform()) {
094                expiry = response.getHeaderValue(FedoraHeaderConstants.ATOMIC_EXPIRES);
095                assertNotNull(expiry);
096            }
097
098            // perform the keep-alive
099            try (final var response = txClient.keepAlive().perform()) {
100                assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode());
101
102                final var expiryFromStatus = response.getHeaderValue(FedoraHeaderConstants.ATOMIC_EXPIRES);
103                assertNotNull(expiryFromStatus);
104
105                final var initialExpiration = Instant.from(FORMATTER.parse(expiry));
106                final var updatedExpiration = Instant.from(FORMATTER.parse(expiryFromStatus));
107                assertTrue(initialExpiration.isBefore(updatedExpiration));
108            }
109        }
110    }
111
112    @Test
113    public void testTransactionStatus() throws Exception {
114        final URI location;
115
116        try (final var txClient = client.startTransactionClient(new URI(SERVER_ADDRESS))) {
117            location = txClient.getTransactionURI();
118            assertNotNull(location);
119
120            try (final var response = txClient.status().perform()) {
121                assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode());
122
123                final var expiryFromStatus = response.getHeaderValue(FedoraHeaderConstants.ATOMIC_EXPIRES);
124                assertNotNull(expiryFromStatus);
125            }
126        }
127    }
128
129    @Test
130    public void testTransactionRollback() throws Exception {
131        final URI location;
132
133        try (final var txClient = client.startTransactionClient(new URI(SERVER_ADDRESS))) {
134            location = txClient.getTransactionURI();
135            assertNotNull(location);
136
137            try (final var response = txClient.rollback().perform()) {
138                assertEquals(NO_CONTENT.getStatusCode(), response.getStatusCode());
139            }
140        }
141    }
142
143}