diff --git a/.gitignore b/.gitignore index e1d8b8b3f44cf4c0bc1aa2835476cf71964c9c1f..75d7805acb9209fdd26a80be6ee94512bde06cb8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ #Maven target + +#General +bak diff --git a/README.md b/README.md index 13ec19926c4bc003da290b65a2686f9ca3088d6a..c8b071b9b4d7dd4fbd6061ca29c348e4eb679ded 100644 --- a/README.md +++ b/README.md @@ -42,22 +42,26 @@ Eclipse should then import 2 projects (`xcs-sample` and `domain`) ## Sample 1: Testing entities Using JUnit and Hamcrest, we will see how to test JPA entities or any other -basic Java class. +Java class. This libraries are the base for every test done in the application. -## Sample 2: Testing with test doubles -Coming soon.... +## Sample 2: Testing EJBs +Using Arquillian and Arquillian Persistence, the EJBs are tested. We wouldn't do +unit testing in this layer, as we don't want to mock the `EntityManager`. -## Sample 3: Testing EJBs -Coming soon... +In this layer we will use some workarounds to set the desired role and principal +in the tests. -## Sample 4: Testing JAX-RS -Coming soon... +## Sample 3: Testing with test doubles +Using EasyMock, we will mock the EJBs to test the REST classes isolated from the +underlying layer. -## Sample 5: Testing AngularJS -Coming soon... +## Sample 4: Testing JAX-RS +Using Arquillian REST Client, we will test the REST API accessing it as real +HTTP clients. -## Sample 6: Testing JSF -Coming soon... +## Sample 5: Testing JSF +Using Arquillian Drone, Arquillian Graphene and Selenium, we will test the JSF +web interface accessing it as real Web clients. -## Sample 7: Additional Testing Tools +## Sample 6: Additional Testing Tools Coming soon... diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java index c320166de8a39b660d66c61430482d4221b3f44b..e279bb1cdf2882a24a379324594e9692ece1cbc2 100644 --- a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Administrator.java @@ -4,6 +4,7 @@ import java.io.Serializable; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; +import javax.xml.bind.annotation.XmlRootElement; /** * An administrator of the application. @@ -12,6 +13,7 @@ import javax.persistence.Entity; */ @Entity @DiscriminatorValue("ADMIN") +@XmlRootElement(name = "admin", namespace = "http://entities.domain.xcs.esei.uvigo.es") public class Administrator extends User implements Serializable { private static final long serialVersionUID = 1L; diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java index 312bd79cb25f399de99d36efbcf98f7291e13ad4..decf5df4d3fbc37cdbcab3d1913f7c2804d73fe7 100644 --- a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Owner.java @@ -11,7 +11,9 @@ import java.util.Collection; import javax.persistence.CascadeType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.OneToMany; +import javax.xml.bind.annotation.XmlRootElement; /** * A pet owner. @@ -20,6 +22,7 @@ import javax.persistence.OneToMany; */ @Entity @DiscriminatorValue("OWNER") +@XmlRootElement(name = "owner", namespace = "http://entities.domain.xcs.esei.uvigo.es") public class Owner extends User implements Serializable { private static final long serialVersionUID = 1L; @@ -27,7 +30,8 @@ public class Owner extends User implements Serializable { mappedBy = "owner", targetEntity = Pet.class, cascade = CascadeType.ALL, - orphanRemoval = true + orphanRemoval = true, + fetch = FetchType.EAGER ) private Collection pets; diff --git a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java index 1f0996caae482b74a75859205412a21d9896ea22..0fe3e20c64f9aa3f25fa10a8a4edce5e6091c4fc 100644 --- a/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java +++ b/domain/src/main/java/es/uvigo/esei/xcs/domain/entities/Pet.java @@ -17,6 +17,10 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; /** * A pet. @@ -24,6 +28,8 @@ import javax.persistence.TemporalType; * @author Miguel Reboiro-Jato */ @Entity(name = "Pet") +@XmlRootElement(name = "pet", namespace = "http://entities.domain.xcs.esei.uvigo.es") +@XmlAccessorType(XmlAccessType.FIELD) public class Pet implements Serializable { private static final long serialVersionUID = 1L; @@ -43,7 +49,8 @@ public class Pet implements Serializable { private Date birth; @ManyToOne - @JoinColumn(name = "owner", referencedColumnName = "login") + @JoinColumn(name = "owner", referencedColumnName = "login", nullable = false) + @XmlTransient private Owner owner; // Required for JPA. diff --git a/pom.xml b/pom.xml index 662d4c3ad9f84ec2444cbee8ed30ac9e6bff8e39..f3223c75c32ee3c4d507f951bf5d109db085310c 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,9 @@ domain + tests service + rest @@ -24,6 +26,8 @@ 7.0 1.1.9.Final + 1.0.0.Alpha3 + 2.47.1 8.2.1.Final @@ -36,8 +40,8 @@ 5.1.21 1.5.10 3.4 - 1.0.0.CR4 - 4.1 + 3.0.13.Final + 2.1.0.Alpha2 1.1.0.Alpha1 @@ -61,6 +65,13 @@ pom import + + org.jboss.arquillian.selenium + selenium-bom + ${arquillian.selenium.version} + pom + import + @@ -73,6 +84,17 @@ service ${project.version} + + ${project.groupId} + rest + ${project.version} + + + ${project.groupId} + tests + ${project.version} + test + @@ -102,6 +124,23 @@ arquillian-persistence-dbunit ${arquillian.persistence.dbunit.version} + + org.jboss.arquillian.extension + arquillian-rest-client-impl-3x + ${arquillian.rest.version} + + + org.jboss.resteasy + resteasy-jackson-provider + ${resteasy.version} + test + + + org.jboss.arquillian.graphene + graphene-webdriver + ${graphene.webdrive.version} + pom + mysql mysql-connector-java @@ -132,17 +171,6 @@ wildfly-arquillian-container-embedded ${wildfly.version} - - - org.jboss.arquillian.container - arquillian-glassfish-embedded-3.1 - ${arquillian.glassfish.embedded.version} - - - org.glassfish.main.extras - glassfish-embedded-all - ${glassfish.embedded.all.version} - diff --git a/rest/.gitignore b/rest/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d --- /dev/null +++ b/rest/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/rest/pom.xml b/rest/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..001dee5c2ce9e1aa749412d85147ee6ab0e6c8ba --- /dev/null +++ b/rest/pom.xml @@ -0,0 +1,69 @@ + + 4.0.0 + + es.uvigo.esei.xcs + sample + 0.0.1-SNAPSHOT + + rest + war + + REST + XCS Sample - REST + + + + + javax + javaee-api + provided + + + es.uvigo.esei.xcs + service + + + + + es.uvigo.esei.xcs + tests + test + + + junit + junit + test + + + org.hamcrest + java-hamcrest + test + + + org.easymock + easymock + test + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.jboss.arquillian.extension + arquillian-persistence-dbunit + test + + + org.jboss.arquillian.extension + arquillian-rest-client-impl-3x + test + + + org.jboss.resteasy + resteasy-jackson-provider + test + + + \ No newline at end of file diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/CORSFilter.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/CORSFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..46038755585180c29740c4abbe859647f3ee34de --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/CORSFilter.java @@ -0,0 +1,21 @@ +package es.uvigo.esei.xcs.rest; + +import java.io.IOException; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.ext.Provider; + +@Provider +public class CORSFilter implements ContainerResponseFilter { + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext cres) + throws IOException { + cres.getHeaders().add("Access-Control-Allow-Origin", "*"); + cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); + cres.getHeaders().add("Access-Control-Allow-Credentials", "true"); + cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); + cres.getHeaders().add("Access-Control-Max-Age", "1209600"); + } +} \ No newline at end of file diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/IllegalArgumentExceptionMapper.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/IllegalArgumentExceptionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3fc49bd80960ac2e2a0c0ed22ac2aa2dcf23aa94 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/IllegalArgumentExceptionMapper.java @@ -0,0 +1,18 @@ +package es.uvigo.esei.xcs.rest; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +@Provider +public class IllegalArgumentExceptionMapper +implements ExceptionMapper { + @Override + public Response toResponse(IllegalArgumentException e) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(e.getMessage()) + .type(MediaType.TEXT_PLAIN) + .build(); + } +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java new file mode 100644 index 0000000000000000000000000000000000000000..6d92173c78d7c3983d70f81547270ce477541362 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/OwnerResource.java @@ -0,0 +1,145 @@ +package es.uvigo.esei.xcs.rest; + +import java.net.URI; + +import javax.ejb.EJB; +import javax.persistence.EntityExistsException; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import es.uvigo.esei.xcs.domain.entities.Owner; +import es.uvigo.esei.xcs.domain.entities.Pet; +import es.uvigo.esei.xcs.service.OwnerService; + +/** + * Resource that represents the owners in the application. + * + * @author Miguel Reboiro Jato + */ +@Path("owner") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class OwnerResource { + @EJB + private OwnerService service; + + @Context + private UriInfo uriInfo; + + /** + * Returns the owner identified by the login. + * + * @param login the login of an owner. + * @return an {@code OK} response containing the {@link Owner} with the + * provided login. + * @throws IllegalArgumentException if {@code login} is {@code null} or + * if it does not correspond with any owner. + */ + @Path("{login}") + @GET + public Response get(@PathParam("login") String login) { + if (login == null) + throw new IllegalArgumentException("login can't be null"); + + final Owner owner = this.service.get(login); + + if (owner == null) + throw new IllegalArgumentException("Owner not found: " + login); + else + return Response.ok(owner).build(); + } + + /** + * Returns the list of owners stored in the application. + * + * @return an {@code OK} response containing the list of owners stored in + * the application. + */ + @GET + public Response list() { + return Response.ok(this.service.list()).build(); + } + + /** + * Creates a new owner. This owner may include a list of pets, that will be + * also created. + * + * @param owner a new owner to be stored. + * @return a {@code CREATED} response with the URI of the new owner in the + * {@code Location} header. + * @throws IllegalArgumentException if owner is {@code null} or if an owner + * with the same login already exists. + */ + @POST + public Response create(Owner owner) { + // Pets are serialized without owner. + assignOwnerToPets(owner); + + try { + final Owner newOwner = this.service.create(owner); + final URI ownerUri = uriInfo.getAbsolutePathBuilder() + .path(newOwner.getLogin()) + .build(); + + return Response.created(ownerUri).build(); + } catch (EntityExistsException eee) { + throw new IllegalArgumentException("The owner already exists"); + } + } + + /** + * Updates an owner. This owner may include a list of pets, that will be + * also created or updated. If the owner does not exists it will be created. + * + * @param owner an owner to be updated. + * @return an empty {@code OK} response. + * @throws IllegalArgumentException if owner is {@code null}. + */ + @PUT + public Response update(Owner owner) { + // Pets are serialized without owner. + assignOwnerToPets(owner); + + this.service.update(owner); + + return Response.ok().build(); + } + + /** + * Deletes an owner. + * + * @param login the login of the owner to be deleted. + * @throws IllegalArgumentException if {@code login} is {@code null} or if + * it does not identifies a valid owner. + */ + @Path("{login}") + @DELETE + public Response delete(@PathParam("login") String login) { + if (login == null) + throw new IllegalArgumentException("login can't be null"); + + this.service.remove(login); + + return Response.ok().build(); + } + + private static void assignOwnerToPets(Owner owner) { + if (owner == null) + throw new IllegalArgumentException("owner can't be null"); + + for (Pet pet : owner.getPets()) { + if (pet.getOwner() != owner) + pet.setOwner(owner); + } + } +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java new file mode 100644 index 0000000000000000000000000000000000000000..55ac0f1877aca55fe444a4dbd5ac5a1e7ad376c4 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/PetResource.java @@ -0,0 +1,147 @@ +package es.uvigo.esei.xcs.rest; + +import java.net.URI; + +import javax.ejb.EJB; +import javax.ejb.EJBAccessException; +import javax.persistence.EntityExistsException; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import es.uvigo.esei.xcs.domain.entities.Pet; +import es.uvigo.esei.xcs.service.PetService; + +/** + * Resource that represents the pets in the application. + * + * @author Miguel Reboiro Jato + */ +@Path("pet") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class PetResource { + @EJB + private PetService service; + + @Context + private UriInfo uriInfo; + + /** + * Returns the owner identified by the login. + * + * @param id the identified of a pet. + * @return an {@code OK} response containing the {@link Pet} with the + * provided identifier. + * @throws SecurityException if the current owner does not owns the pet. + */ + @Path("{id}") + @GET + public Response get(@PathParam("id") int id) throws SecurityException { + try { + final Pet pet = this.service.get(id); + + if (pet == null) + throw new IllegalArgumentException("Pet not found: " + id); + else + return Response.ok(pet).build(); + } catch (EJBAccessException eae) { + throw new SecurityException(eae); + } + } + + /** + * Returns the complete list of pets of the current owner. + * + * @return an {@code OK} response containing the complete list of pets of + * the current owner. + */ + @GET + public Response list() { + return Response.ok(this.service.list()).build(); + } + + /** + * Creates a new pet owned by the current user. + * + * @param pet a new owner to be stored. + * @return a {@code CREATED} response with the URI of the new pet in the + * {@code Location} header. + * @throws IllegalArgumentException if pet is {@code null} or if a pet with + * the same identifier already exists. + * @throws SecurityException if the pet already has an owner and it is not + * the current user. If the pet has no owner, this exception will be never + * thrown. + */ + @POST + public Response create(Pet pet) throws SecurityException { + if (pet == null) + throw new IllegalArgumentException("pet can't be null"); + + try { + final Pet newPet = this.service.create(pet); + final URI petUri = uriInfo.getAbsolutePathBuilder() + .path(Integer.toString(newPet.getId())) + .build(); + + return Response.created(petUri).build(); + } catch (EntityExistsException eee) { + throw new IllegalArgumentException("The pet already exists"); + } catch (EJBAccessException eae) { + throw new SecurityException(eae); + } + } + + /** + * Updates the information of a pet. If the pet is not stored, it will be + * created. + * + * @param pet a pet to be updated. + * @return an empty {@code OK} response. + * @throws IllegalArgumentException if pet is {@code null} of it has no + * owner. + * @throws SecurityException if the pet's owner is not the current user. + */ + @PUT + public Response update(Pet pet) throws SecurityException { + if (pet == null) + throw new IllegalArgumentException("pet can't be null"); + + try { + this.service.update(pet); + + return Response.ok().build(); + } catch (EJBAccessException eae) { + throw new SecurityException(eae); + } + } + + /** + * Deletes a pet. + * + * @param id the identifier of the pet to be deleted. + * @throws IllegalArgumentException if there is no pet with the provided + * identifier. + * @throws SecurityException if the pet's owner is not the current user. + */ + @Path("{id}") + @DELETE + public Response delete(@PathParam("id") int id) throws SecurityException { + try { + this.service.remove(id); + + return Response.ok().build(); + } catch (EJBAccessException eae) { + throw new SecurityException(eae); + } + } +} diff --git a/rest/src/main/java/es/uvigo/esei/xcs/rest/SecurityExceptionMapper.java b/rest/src/main/java/es/uvigo/esei/xcs/rest/SecurityExceptionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..76edd1222299b8ca43678425f35a04947c618215 --- /dev/null +++ b/rest/src/main/java/es/uvigo/esei/xcs/rest/SecurityExceptionMapper.java @@ -0,0 +1,17 @@ +package es.uvigo.esei.xcs.rest; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +@Provider +public class SecurityExceptionMapper implements ExceptionMapper { + @Override + public Response toResponse(SecurityException e) { + return Response.status(Response.Status.FORBIDDEN) + .entity(e.getMessage()) + .type(MediaType.TEXT_PLAIN) + .build(); + } +} diff --git a/rest/src/main/resources/META-INF/persistence.xml b/rest/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f685f214faaa522c69be999f4de0320b14a29b2 --- /dev/null +++ b/rest/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,20 @@ + + + + java:jboss/datasources/xcs + + es.uvigo.esei.xcs.domain.entities.Owner + es.uvigo.esei.xcs.domain.entities.Pet + es.uvigo.esei.xcs.domain.entities.Administrator + false + + + + + + + \ No newline at end of file diff --git a/rest/src/main/webapp/WEB-INF/beans.xml b/rest/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000000000000000000000000000000000..2777559c2045ceee8c62d5f3c9dce7c25608eb39 --- /dev/null +++ b/rest/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/rest/src/main/webapp/WEB-INF/jboss-web.xml b/rest/src/main/webapp/WEB-INF/jboss-web.xml new file mode 100644 index 0000000000000000000000000000000000000000..68c92827d5a6f787d0e89d9f7f445097bd1ad261 --- /dev/null +++ b/rest/src/main/webapp/WEB-INF/jboss-web.xml @@ -0,0 +1,4 @@ + + + xcs-sample-security-domain + \ No newline at end of file diff --git a/rest/src/main/webapp/WEB-INF/web.xml b/rest/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8bf7f36d650eb9a181f2539fc7db84712c9ecaf --- /dev/null +++ b/rest/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,50 @@ + + Pet Store REST + + + javax.ws.rs.core.Application + /api/* + + + + + + admin + /api/owner/* + OPTIONS + + + ADMIN + + + + + + owner + /api/pet/* + OPTIONS + + + OWNER + + + + + + + ADMIN + + + + OWNER + + + + + BASIC + default + + \ No newline at end of file diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/GenericTypes.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/GenericTypes.java new file mode 100644 index 0000000000000000000000000000000000000000..655bb1699a282fdebd460d3ce77d2e463fadf02c --- /dev/null +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/GenericTypes.java @@ -0,0 +1,20 @@ +package es.uvigo.esei.xcs.rest; + +import java.util.List; + +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; + +import es.uvigo.esei.xcs.domain.entities.Owner; + +public final class GenericTypes { + private GenericTypes() {} + + public static class ListOwnerType extends GenericType> { + public static ListOwnerType INSTANCE = new ListOwnerType(); + + public static List readEntity(Response response) { + return response.readEntity(INSTANCE); + } + } +} diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java new file mode 100644 index 0000000000000000000000000000000000000000..45db6db750ea36b75aff8d77dfea95a8d763b98a --- /dev/null +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceRestTest.java @@ -0,0 +1,305 @@ +package es.uvigo.esei.xcs.rest; + +import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.containsOwnersInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwner; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.EXISTENT_LOGIN; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.NON_EXISTENT_LOGIN; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.OWNER_WITHOUT_PETS_LOGIN; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.OWNER_WITH_PETS_LOGIN; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithFreshPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithPersistentPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithoutPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owner; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owners; +import static javax.ws.rs.client.Entity.json; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.extension.rest.client.ArquillianResteasyResource; +import org.jboss.arquillian.extension.rest.client.Header; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.junit.InSequence; +import org.jboss.arquillian.persistence.Cleanup; +import org.jboss.arquillian.persistence.CleanupUsingScript; +import org.jboss.arquillian.persistence.ShouldMatchDataSet; +import org.jboss.arquillian.persistence.TestExecutionPhase; +import org.jboss.arquillian.persistence.UsingDataSet; +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import es.uvigo.esei.xcs.domain.entities.Owner; +import es.uvigo.esei.xcs.domain.entities.OwnersDataset; +import es.uvigo.esei.xcs.rest.GenericTypes.ListOwnerType; +import es.uvigo.esei.xcs.service.OwnerService; + +@RunWith(Arquillian.class) +public class OwnerResourceRestTest { + private final static String BASE_PATH = "api/owner/"; + private static final String BASIC_AUTHORIZATION = "Basic am9zZTpqb3NlcGFzcw="; + + @Deployment + public static Archive createDeployment() { + final WebArchive archive = ShrinkWrap.create(WebArchive.class, "test.war") + .addClass(OwnerResource.class) + .addClasses(CORSFilter.class, IllegalArgumentExceptionMapper.class, SecurityExceptionMapper.class) + .addPackage(OwnerService.class.getPackage()) + .addPackage(Owner.class.getPackage()) + .addAsResource("test-persistence.xml", "META-INF/persistence.xml") + .addAsWebInfResource("jboss-web.xml") + .addAsWebInfResource("web.xml") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + + return archive; + } + + @Test @InSequence(1) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeGet() {} + + @Test @InSequence(2) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testGet( + @ArquillianResteasyResource(BASE_PATH + EXISTENT_LOGIN) ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().get(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + + final Owner owner = response.readEntity(Owner.class); + final Owner expected = owner("pepe"); + + assertThat(owner, is(equalsToOwner(expected))); + } + + @Test @InSequence(3) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterGet() {} + + + + @Test @InSequence(4) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeGetNonExistent() {} + + @Test @InSequence(5) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testGetNonExistent( + @ArquillianResteasyResource(BASE_PATH + NON_EXISTENT_LOGIN) ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().get(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.BAD_REQUEST))); + } + + @Test @InSequence(6) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterGetNonExistent() {} + + + + @Test @InSequence(10) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeList() {} + + @Test @InSequence(11) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testList( + @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().get(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + + final List list = ListOwnerType.readEntity(response); + assertThat(list, containsOwnersInAnyOrder(owners())); + } + + @Test @InSequence(12) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterList() {} + + + + @Test @InSequence(20) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeCreate() {} + + @Test @InSequence(21) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testCreate( + @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget + ) throws Exception { + testCreateOwner(webTarget, newOwnerWithoutPets()); + } + + @Test @InSequence(22) + @ShouldMatchDataSet({"owners.xml", "owners-create-without-pets.xml"}) + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterCreate() {} + + + + @Test @InSequence(23) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeCreateWithPets() {} + + @Test @InSequence(24) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testCreateWithPets( + @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget + ) throws Exception { + testCreateOwner(webTarget, newOwnerWithFreshPets(), newOwnerWithPersistentPets()); + } + + @Test @InSequence(25) + @ShouldMatchDataSet({"owners.xml", "owners-create-with-pets.xml"}) + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterCreateWithPets() {} + + private void testCreateOwner(WebTarget webTarget, Owner newOwner) { + testCreateOwner(webTarget, newOwner, newOwner); + } + + private void testCreateOwner(WebTarget webTarget, Owner newOwner, Owner persistentOwner) { + final Response response = webTarget.request().post(json(newOwner)); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.CREATED))); + + final String location = response.getHeaderString("Location"); + + final Response responseGet = authorizedJsonRequestGet(location); + final Owner owner = responseGet.readEntity(Owner.class); + assertThat(owner, is(equalsToOwner(persistentOwner))); + } + + + + @Test @InSequence(30) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeUpdatePassword() {} + + @Test @InSequence(31) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testUpdatePassword( + @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget + ) throws Exception { + final Owner owner = OwnersDataset.anyOwner(); + owner.changePassword("newpassword"); + + final Response response = webTarget.request().put(json(owner)); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + } + + @Test @InSequence(32) + @ShouldMatchDataSet("owners-update-password.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterUpdatePassword() {} + + + + @Test @InSequence(40) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeDeleteWithoutPets() {} + + @Test @InSequence(41) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testDeleteWithoutPets( + @ArquillianResteasyResource(BASE_PATH + OWNER_WITHOUT_PETS_LOGIN) ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().delete(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + } + + @Test @InSequence(42) + @ShouldMatchDataSet("owners-remove-without-pets.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterDeleteWithoutPets() {} + + + + @Test @InSequence(43) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeDeleteWithPets() {} + + @Test @InSequence(44) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testDeleteWithPets( + @ArquillianResteasyResource(BASE_PATH + OWNER_WITH_PETS_LOGIN) ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().delete(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + } + + @Test @InSequence(45) + @ShouldMatchDataSet("owners-remove-with-pets.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterDeleteWithPets() {} + + + + @Test @InSequence(46) + @UsingDataSet("owners.xml") + @Cleanup(phase = TestExecutionPhase.NONE) + public void beforeDeleteNoLogin() {} + + @Test @InSequence(47) + @RunAsClient + @Header(name = "Authorization", value = BASIC_AUTHORIZATION) + public void testDeleteNoLogin( + @ArquillianResteasyResource(BASE_PATH) ResteasyWebTarget webTarget + ) throws Exception { + final Response response = webTarget.request().delete(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.METHOD_NOT_ALLOWED))); + } + + @Test @InSequence(48) + @ShouldMatchDataSet("owners.xml") + @CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" }) + public void afterDeleteNoLogin() {} + + + private static Response authorizedJsonRequestGet(String uri) { + return ClientBuilder.newClient().target(uri) + .request(MediaType.APPLICATION_JSON_TYPE) + .header("Authorization", BASIC_AUTHORIZATION) + .get(); + } +} diff --git a/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a635711892829804677d4bdcfa6c75bf6322a1b4 --- /dev/null +++ b/rest/src/test/java/es/uvigo/esei/xcs/rest/OwnerResourceUnitTest.java @@ -0,0 +1,198 @@ +package es.uvigo.esei.xcs.rest; + +import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.containsOwnersInAnyOrder; +import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwner; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyLogin; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyOwner; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithFreshPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithPersistentPets; +import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owners; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.junit.Assert.assertThat; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.easymock.EasyMockRunner; +import org.easymock.EasyMockSupport; +import org.easymock.Mock; +import org.easymock.TestSubject; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import es.uvigo.esei.xcs.domain.entities.Owner; +import es.uvigo.esei.xcs.domain.entities.OwnersDataset; +import es.uvigo.esei.xcs.service.OwnerService; + +@RunWith(EasyMockRunner.class) +public class OwnerResourceUnitTest extends EasyMockSupport { + @TestSubject + private OwnerResource resource = new OwnerResource(); + + @Mock + private OwnerService facade; + + @Mock + private UriInfo uriInfo; + + @Mock + private UriBuilder uriBuilder; + + @After + public void tearDown() throws Exception { + verifyAll(); + } + + @Test + public void testGet() { + final Owner owner = OwnersDataset.anyOwner(); + + expect(facade.get(owner.getLogin())) + .andReturn(owner); + + replayAll(); + + final Response response = resource.get(owner.getLogin()); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + assertThat(response.getEntity(), is(instanceOf(Owner.class))); + assertThat((Owner) response.getEntity(), is(equalsToOwner(owner))); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetNull() { + replayAll(); + + resource.get(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testGetMissing() { + final String login = anyLogin(); + + expect(facade.get(login)) + .andReturn(null); + + replayAll(); + + resource.get(login); + } + + @Test + @SuppressWarnings("unchecked") + public void testList() { + final Owner[] owners = owners(); + + expect(facade.list()) + .andReturn(asList(owners)); + + replayAll(); + + final Response response = resource.list(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + assertThat(response.getEntity(), is(instanceOf(List.class))); + assertThat((List) response.getEntity(), containsOwnersInAnyOrder(owners)); + } + + @Test + @SuppressWarnings("unchecked") + public void testListEmpty() { + expect(facade.list()) + .andReturn(emptyList()); + + replayAll(); + + final Response response = resource.list(); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + assertThat(response.getEntity(), is(instanceOf(List.class))); + assertThat((List) response.getEntity(), is(empty())); + } + + @Test + public void testCreate() throws Exception { + final Owner newOwner = newOwnerWithFreshPets(); + final Owner createdOwner = newOwnerWithPersistentPets(); + + final URI mockUri = new URI("http://host/api/owner/" + newOwner.getLogin()); + + expect(facade.create(newOwner)) + .andReturn(createdOwner); + + expect(uriInfo.getAbsolutePathBuilder()) + .andReturn(uriBuilder); + expect(uriBuilder.path(newOwner.getLogin())) + .andReturn(uriBuilder); + expect(uriBuilder.build()) + .andReturn(mockUri); + + replayAll(); + + final Response response = resource.create(newOwner); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.CREATED))); + assertThat(response.getHeaderString("Location"), is(equalTo(mockUri.toString()))); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateNull() { + replayAll(); + + resource.create(null); + } + + @Test + public void testUpdate() { + final Owner owner = anyOwner(); + + facade.update(owner); + + expectLastCall().andReturn(owner); + + replayAll(); + + final Response response = resource.update(owner); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + } + + @Test(expected = IllegalArgumentException.class) + public void testUpdateNull() { + replayAll(); + + resource.update(null); + } + + @Test + public void testDelete() { + final String login = OwnersDataset.anyLogin(); + + facade.remove(login); + + replayAll(); + + final Response response = resource.delete(login); + + assertThat(response.getStatusInfo(), is(equalTo(Response.Status.OK))); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeleteNull() { + replayAll(); + + resource.delete(null); + } +} diff --git a/rest/src/test/resources-wildfly-embedded-h2/beans.xml b/rest/src/test/resources-wildfly-embedded-h2/beans.xml new file mode 100644 index 0000000000000000000000000000000000000000..01d52d1a567d583d8353fdb98e65e827ff09ebac --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-h2/beans.xml @@ -0,0 +1,11 @@ + + + + es.uvigo.esei.xcs.service.util.security.TestPrincipal + + + diff --git a/rest/src/test/resources-wildfly-embedded-h2/cleanup-autoincrement.sql b/rest/src/test/resources-wildfly-embedded-h2/cleanup-autoincrement.sql new file mode 100644 index 0000000000000000000000000000000000000000..245049ca05efb8bd0cb20c838880162d9623d3e7 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-h2/cleanup-autoincrement.sql @@ -0,0 +1 @@ +ALTER TABLE Pet ALTER COLUMN id RESTART WITH 1; \ No newline at end of file diff --git a/rest/src/test/resources-wildfly-embedded-h2/jboss-web.xml b/rest/src/test/resources-wildfly-embedded-h2/jboss-web.xml new file mode 100644 index 0000000000000000000000000000000000000000..68c92827d5a6f787d0e89d9f7f445097bd1ad261 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-h2/jboss-web.xml @@ -0,0 +1,4 @@ + + + xcs-sample-security-domain + \ No newline at end of file diff --git a/rest/src/test/resources-wildfly-embedded-h2/standalone.xml b/rest/src/test/resources-wildfly-embedded-h2/standalone.xml new file mode 100644 index 0000000000000000000000000000000000000000..fd979b90f80cf7c8973b9e3615c217f8177f7f25 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-h2/standalone.xml @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + h2 + + sa + sa + + + + + org.h2.jdbcx.JdbcDataSource + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rest/src/test/resources-wildfly-embedded-h2/test-persistence.xml b/rest/src/test/resources-wildfly-embedded-h2/test-persistence.xml new file mode 100644 index 0000000000000000000000000000000000000000..ae6b5d32518772eaccca0143292dd26d1324aabf --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-h2/test-persistence.xml @@ -0,0 +1,17 @@ + + + + java:jboss/datasources/ExampleDS + + false + + + + + + + \ No newline at end of file diff --git a/rest/src/test/resources-wildfly-embedded-mysql/beans.xml b/rest/src/test/resources-wildfly-embedded-mysql/beans.xml new file mode 100644 index 0000000000000000000000000000000000000000..01d52d1a567d583d8353fdb98e65e827ff09ebac --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-mysql/beans.xml @@ -0,0 +1,11 @@ + + + + es.uvigo.esei.xcs.service.util.security.TestPrincipal + + + diff --git a/rest/src/test/resources-wildfly-embedded-mysql/cleanup-autoincrement.sql b/rest/src/test/resources-wildfly-embedded-mysql/cleanup-autoincrement.sql new file mode 100644 index 0000000000000000000000000000000000000000..a51d23be2cbb2664431732170bda027e04dda9d5 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-mysql/cleanup-autoincrement.sql @@ -0,0 +1 @@ +ALTER TABLE Pet AUTO_INCREMENT = 1; \ No newline at end of file diff --git a/rest/src/test/resources-wildfly-embedded-mysql/jboss-web.xml b/rest/src/test/resources-wildfly-embedded-mysql/jboss-web.xml new file mode 100644 index 0000000000000000000000000000000000000000..68c92827d5a6f787d0e89d9f7f445097bd1ad261 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-mysql/jboss-web.xml @@ -0,0 +1,4 @@ + + + xcs-sample-security-domain + \ No newline at end of file diff --git a/rest/src/test/resources-wildfly-embedded-mysql/mysql-ds.xml b/rest/src/test/resources-wildfly-embedded-mysql/mysql-ds.xml new file mode 100644 index 0000000000000000000000000000000000000000..e35c79b61bcb83eaddf8d22303e1eff0e3bbf450 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-mysql/mysql-ds.xml @@ -0,0 +1,17 @@ + + + + jdbc:mysql://localhost:3306/xcs + mysql-connector-java-${mysql.version}.jar + + 30 + + + xcs + xcs + + + + \ No newline at end of file diff --git a/rest/src/test/resources-wildfly-embedded-mysql/standalone.xml b/rest/src/test/resources-wildfly-embedded-mysql/standalone.xml new file mode 100644 index 0000000000000000000000000000000000000000..28088fde0c74abbb7ec04a1862e685f4ddf4e029 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-mysql/standalone.xml @@ -0,0 +1,415 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + h2 + + sa + sa + + + + + org.h2.jdbcx.JdbcDataSource + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/rest/src/test/resources-wildfly-embedded-mysql/test-persistence.xml b/rest/src/test/resources-wildfly-embedded-mysql/test-persistence.xml new file mode 100644 index 0000000000000000000000000000000000000000..1d6b2be6a710d0acf94eacf057af32d6b8849452 --- /dev/null +++ b/rest/src/test/resources-wildfly-embedded-mysql/test-persistence.xml @@ -0,0 +1,17 @@ + + + + java:jboss/datasources/xcs + + false + + + + + + + \ No newline at end of file diff --git a/rest/src/test/resources/arquillian.xml b/rest/src/test/resources/arquillian.xml new file mode 100644 index 0000000000000000000000000000000000000000..dd1edb85bb198089d0520d1404925b153f509638 --- /dev/null +++ b/rest/src/test/resources/arquillian.xml @@ -0,0 +1,25 @@ + + + + + CLEAN_INSERT + + + + + target/wildfly-${wildfly.version} + target/wildfly-${wildfly.version}/modules + + + + + + target/wildfly-${wildfly.version} + target/wildfly-${wildfly.version}/modules + + + \ No newline at end of file diff --git a/rest/src/test/resources/web.xml b/rest/src/test/resources/web.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8bf7f36d650eb9a181f2539fc7db84712c9ecaf --- /dev/null +++ b/rest/src/test/resources/web.xml @@ -0,0 +1,50 @@ + + Pet Store REST + + + javax.ws.rs.core.Application + /api/* + + + + + + admin + /api/owner/* + OPTIONS + + + ADMIN + + + + + + owner + /api/pet/* + OPTIONS + + + OWNER + + + + + + + ADMIN + + + + OWNER + + + + + BASIC + default + + \ No newline at end of file diff --git a/service/pom.xml b/service/pom.xml index e94ef22619df449c14a96469ae3eb0ac8f9718b6..65877b21349ac91367b64c58f3139e66dedbc4b2 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -25,6 +25,11 @@ + + es.uvigo.esei.xcs + tests + test + junit junit diff --git a/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java b/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java index f57aa2686e9fdccdb6585d33c2b7d2c077024f6e..37d29d165b4a2b23990270afd3b05b7ffeb7a071 100644 --- a/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java +++ b/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java @@ -89,7 +89,7 @@ public class PetService { * Updates the information of a pet. If the pet is not stored, it will be * created. * - * @param pet the pet to be updated. + * @param pet a pet to be updated. * @throws IllegalArgumentException if the pet has no owner. * @throws EJBAccessException if the pet's owner is not the current user. */ diff --git a/tests/pom.xml b/tests/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..b34c7e358fb617476df5044e04c04aab78ef5a39 --- /dev/null +++ b/tests/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + es.uvigo.esei.xcs + sample + 0.0.1-SNAPSHOT + + tests + jar + + Tests + XCS Sample - Test Utility Classes + + + + javax + javaee-api + compile + + + ${project.groupId} + domain + compile + + + junit + junit + compile + + + org.hamcrest + java-hamcrest + compile + + + diff --git a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java rename to tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToEntity.java diff --git a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java rename to tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToOwner.java diff --git a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java rename to tests/src/main/java/es/uvigo/esei/xcs/domain/entities/IsEqualsToPet.java diff --git a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java similarity index 77% rename from service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java rename to tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java index 6946a5146b7850e41da40b6de309eb3905cd6e06..2b4bf11962778151455588ed2d19b29d3fa37e7a 100644 --- a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java +++ b/tests/src/main/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java @@ -8,6 +8,11 @@ import java.util.Date; import java.util.Set; public class OwnersDataset { + public static final String EXISTENT_LOGIN = "pepe"; + public static final String NON_EXISTENT_LOGIN = "non-existent"; + public static final String OWNER_WITH_PETS_LOGIN = "juan"; + public static final String OWNER_WITHOUT_PETS_LOGIN = "lorena"; + public static Owner owner(String login) { return stream(owners()) .filter(owner -> owner.getLogin().equals(login)) @@ -32,9 +37,9 @@ public class OwnersDataset { public static Owner[] owners() { return new Owner[] { - new Owner("pepe", "pepepass", + new Owner(EXISTENT_LOGIN, "pepepass", new Pet(1, "Pepecat", AnimalType.CAT, new Date(946684861000L))), - new Owner("juan", "juanpass", + new Owner(OWNER_WITH_PETS_LOGIN, "juanpass", new Pet(2, "Max", AnimalType.CAT, new Date(946684861000L)), new Pet(3, "Juandog", AnimalType.DOG, new Date(946684861000L)) ), @@ -43,7 +48,7 @@ public class OwnersDataset { new Pet(5, "Max", AnimalType.DOG, new Date(946684861000L)), new Pet(6, "Anabird", AnimalType.BIRD, new Date(946684861000L)) ), - new Owner("lorena", "lorenapass") + new Owner(OWNER_WITHOUT_PETS_LOGIN, "lorenapass") }; } @@ -79,11 +84,11 @@ public class OwnersDataset { } public static Owner ownerWithPets() { - return owners()[1]; + return owner(OWNER_WITH_PETS_LOGIN); } public static Owner ownerWithoutPets() { - return owners()[3]; + return owner(OWNER_WITHOUT_PETS_LOGIN); } public static Pet anyPet() { @@ -98,14 +103,26 @@ public class OwnersDataset { return new Pet("Lorenacat", AnimalType.CAT, new Date(946684861000L), owner); } + public static String anyLogin() { + return EXISTENT_LOGIN; + } + public static String existentLogin() { - return "pepe"; + return EXISTENT_LOGIN; + } + + public static String nonExistentLogin() { + return NON_EXISTENT_LOGIN; } public static String existentPetName() { return "Pepecat"; } + public static String nonExistentPetName() { + return "NonExistentPet"; + } + public static int existentPetId() { return 2; } @@ -113,4 +130,9 @@ public class OwnersDataset { public static int nonExistentPetId() { return 1000000; } + + public static Owner nonExistentOwner() { + final String login = nonExistentLogin(); + return new Owner(login, login + "pass"); + } } diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java b/tests/src/main/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java rename to tests/src/main/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java b/tests/src/main/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java rename to tests/src/main/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java b/tests/src/main/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java rename to tests/src/main/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java b/tests/src/main/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java similarity index 100% rename from service/src/test/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java rename to tests/src/main/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java diff --git a/service/src/test/resources/datasets/owners-create-pet.xml b/tests/src/main/resources/datasets/owners-create-pet.xml similarity index 100% rename from service/src/test/resources/datasets/owners-create-pet.xml rename to tests/src/main/resources/datasets/owners-create-pet.xml diff --git a/service/src/test/resources/datasets/owners-create-with-pets.xml b/tests/src/main/resources/datasets/owners-create-with-pets.xml similarity index 100% rename from service/src/test/resources/datasets/owners-create-with-pets.xml rename to tests/src/main/resources/datasets/owners-create-with-pets.xml diff --git a/service/src/test/resources/datasets/owners-create-without-pets.xml b/tests/src/main/resources/datasets/owners-create-without-pets.xml similarity index 100% rename from service/src/test/resources/datasets/owners-create-without-pets.xml rename to tests/src/main/resources/datasets/owners-create-without-pets.xml diff --git a/service/src/test/resources/datasets/owners-remove-pet.xml b/tests/src/main/resources/datasets/owners-remove-pet.xml similarity index 100% rename from service/src/test/resources/datasets/owners-remove-pet.xml rename to tests/src/main/resources/datasets/owners-remove-pet.xml diff --git a/service/src/test/resources/datasets/owners-remove-with-pets.xml b/tests/src/main/resources/datasets/owners-remove-with-pets.xml similarity index 100% rename from service/src/test/resources/datasets/owners-remove-with-pets.xml rename to tests/src/main/resources/datasets/owners-remove-with-pets.xml diff --git a/service/src/test/resources/datasets/owners-remove-without-pets.xml b/tests/src/main/resources/datasets/owners-remove-without-pets.xml similarity index 100% rename from service/src/test/resources/datasets/owners-remove-without-pets.xml rename to tests/src/main/resources/datasets/owners-remove-without-pets.xml diff --git a/service/src/test/resources/datasets/owners-update-password.xml b/tests/src/main/resources/datasets/owners-update-password.xml similarity index 100% rename from service/src/test/resources/datasets/owners-update-password.xml rename to tests/src/main/resources/datasets/owners-update-password.xml diff --git a/service/src/test/resources/datasets/owners-update-pet.xml b/tests/src/main/resources/datasets/owners-update-pet.xml similarity index 100% rename from service/src/test/resources/datasets/owners-update-pet.xml rename to tests/src/main/resources/datasets/owners-update-pet.xml diff --git a/service/src/test/resources/datasets/owners.xml b/tests/src/main/resources/datasets/owners.xml similarity index 100% rename from service/src/test/resources/datasets/owners.xml rename to tests/src/main/resources/datasets/owners.xml diff --git a/service/src/test/resources/scripts/cleanup.sql b/tests/src/main/resources/scripts/cleanup.sql similarity index 100% rename from service/src/test/resources/scripts/cleanup.sql rename to tests/src/main/resources/scripts/cleanup.sql