This commit is contained in:
Claudio Maggioni 2023-05-23 14:07:42 +02:00
parent a22f8bb6cb
commit 4c2bb34020
43 changed files with 1897 additions and 0 deletions

78
.gitignore vendored
View File

@ -2,3 +2,81 @@ artist.txt
.idea/
target/
*.iml
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

View File

@ -0,0 +1,30 @@
[
{
"operation": {
"classname": "comments.repository.MapCriticsRepository",
"name": "addComment",
"parameterTypes": [
"comments.model.Comment"
]
},
"identifiers": {
"parameters": [
"c"
],
"receiverName": "receiverObjectID",
"returnName": "methodResultID"
},
"throws": [
{
"exception": "java.lang.IllegalArgumentException",
"description": "@throws java.lang.IllegalArgumentException the comment is null.",
"guard": {
"condition": "c==null",
"description": "the comment is null."
}
}
],
"post": [],
"pre": []
}
]

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>es.us.aiss</groupId>
<artifactId>comments</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-core-spi</artifactId>
<version>4.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-spring-boot-starter</artifactId>
<version>4.8.0.Final</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.4.3</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.3.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.atlassian.oai</groupId>
<artifactId>swagger-request-validator-core</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>com.atlassian.oai</groupId>
<artifactId>swagger-request-validator-restassured</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.4.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>org.evosuite</groupId>
<artifactId>evosuite</artifactId>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/testing-tools/evosuite-1.2.0.jar</systemPath>
</dependency>
<dependency>
<groupId>org.evomaster</groupId>
<artifactId>evomaster-client-java-controller</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
</project>

View File

@ -0,0 +1,12 @@
package comments.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,32 @@
package comments.main;
import comments.resources.CommentResource;
import org.springframework.stereotype.Component;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
@Component
@ApplicationPath("/api")
public class CommentsAPIApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public CommentsAPIApplication() {
singletons.add(CommentResource.getInstance());
}
@Override
public Set<Class<?>> getClasses() {
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}

View File

@ -0,0 +1,113 @@
package comments.model;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import java.util.Objects;
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public class Comment {
private String id;
private String userName;
private String text;
private String date;
private String type; // Enum: Review, Request, Complain
public Comment(){}
public Comment(String userName, String text, String date, String type) {
this.userName=userName;
this.text = text;
this.date = date;
this.type = type;
}
public Comment(String id, String userName, String text, String date, String type) {
this.id=id;
this.userName=userName;
this.text = text;
this.date = date;
this.type = type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public int hashCode() {
int hash = 7;
hash = 29 * hash + Objects.hashCode(this.id);
hash = 29 * hash + Objects.hashCode(this.userName);
hash = 29 * hash + Objects.hashCode(this.text);
hash = 29 * hash + Objects.hashCode(this.date);
hash = 29 * hash + Objects.hashCode(this.type);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Comment other = (Comment) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
if (!Objects.equals(this.userName, other.userName)) {
return false;
}
if (!Objects.equals(this.text, other.text)) {
return false;
}
if (!Objects.equals(this.date, other.date)) {
return false;
}
if (!Objects.equals(this.type, other.type)) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,71 @@
package comments.model;
import java.util.ArrayList;
import java.util.List;
public class Profile {
private String userName;
private List<Comment> comments;
public Profile(){}
public Profile(String userName){
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> list){
this.comments=list;
}
public Comment getComment(String id){
if (comments==null)
return null;
Comment comment =null;
for(Comment c: comments)
if (c.getId().equals(id))
{
comment=c;
break;
}
return comment;
}
public void addComment(Comment c){
if(comments==null){
comments = new ArrayList<Comment>();
}
comments.add(c);
}
public void deleteComment(Comment c){
comments.remove(c);
}
public void deleteComment(String id){
Comment c = getComment(id);
if(c != null){
comments.remove(c);
}
}
public void deleteAllComments(){
comments.removeAll(comments);
}
}

View File

@ -0,0 +1,24 @@
package comments.repository;
import comments.model.Comment;
import comments.model.Profile;
import java.util.List;
public interface CriticsRepository {
/*Comments*/
public List<Comment> getAllComments();
public void addComment(Comment c);
public Comment getComment(String commentId);
public void deleteComment(String commentId);
public void updateComment(Comment c);
/*Profiles*/
public List<Profile> getAllProfiles();
public void addProfile(Profile p);
public Profile getProfile(String username);
public void deleteProfile(String username);
}

View File

@ -0,0 +1,208 @@
package comments.repository;
import comments.model.Comment;
import comments.model.Profile;
import java.time.LocalDateTime;
import java.util.*;
public class MapCriticsRepository implements CriticsRepository {
Map<String, Comment> commentMap;
Map<String, Profile> profileMap;
private static MapCriticsRepository instance = null;
private int index = 0;
public static MapCriticsRepository getInstance() {
if (instance == null) {
instance = new MapCriticsRepository();
instance.init();
}
return instance;
}
private void init() {
commentMap = new HashMap<String, Comment>();
profileMap = new HashMap<String, Profile>();
// Create Comments
Comment c1 = new Comment();
c1.setUserName("johnSmith");
c1.setText("Great book!");
c1.setType("Review");
c1.setDate("2017-02-16T20:44:53.950");
addComment(c1);
Comment c2 = new Comment();
c2.setUserName("johnSmith");
c2.setText("Original product but the quality is too low for the price");
c2.setType("Review");
c2.setDate("2017-06-16T20:44:53.950");
addComment(c2);
Comment c3 = new Comment();
c3.setUserName("johnSmith");
c3.setText("The product was delivered three days after the expected date.");
c3.setType("Complain");
c3.setDate("2017-06-16T20:48:53.950");
addComment(c3);
Comment c4 = new Comment();
c4.setUserName("oliviaClark");
c4.setText("I would love to see this product in pocket size");
c4.setType("Request");
c4.setDate("2015-01-16T20:44:53.950");
addComment(c4);
Comment c5 = new Comment();
c5.setUserName("oliviaClark");
c5.setText("Please, give me a call before the delivery");
c5.setType("Request");
c5.setDate("2015-06-22T20:12:45.950");
addComment(c5);
Comment c6 = new Comment();
c6.setUserName("gloriaCavanni");
c6.setText("I love the color and the shape of the cover");
c6.setType("Review");
c6.setDate("2020-11-16T20:44:53.950");
addComment(c6);
Comment c7 = new Comment();
c7.setUserName("markSpecter");
c7.setText("Adding a sim card slot would be a winner point!");
c7.setType("Request");
c7.setDate("1998-01-16T20:44:53.950");
addComment(c7);
Comment c8 = new Comment();
c8.setUserName("markSpecter");
c8.setText("Nice product, my kids love it.");
c8.setType("Review");
c8.setDate("2013-04-16T20:44:53.950");
addComment(c8);
Comment c9 = new Comment();
c9.setUserName("markSpecter");
c9.setText("Too bad, too late.");
c9.setType("Complain");
c9.setDate("2018-04-16T20:44:53.950");
addComment(c9);
Comment c10 = new Comment();
c10.setUserName("markSpecter");
c10.setText("It is bigger than it look in the image, but it does the work");
c10.setType("Review");
c10.setDate("2019-08-02T12:31:53.950");
addComment(c10);
Comment c11 = new Comment();
c11.setUserName("testUser");
c11.setText("This is a test comment");
c11.setType(null);
c11.setDate("2020-08-02T12:31:53.950");
addComment(c11);
}
/* Comments */
@Override
public List<Comment> getAllComments() {
List<Comment> comments = new ArrayList<Comment>(commentMap.values());
return comments;
}
/**
*
* @throws IllegalArgumentException if the comment is null
*/
@Override
public void addComment(Comment c) {
String id = "c" + index++;
if (profileMap.containsKey(c.getUserName())) {
profileMap.get(c.getUserName()).addComment(c);
} else {
Profile p = new Profile();
p.setUserName(c.getUserName());
p.addComment(c);
profileMap.put(p.getUserName(), p);
}
c.setId(id);
if (c.getDate() != null) {
c.setDate(c.getDate());
} else {
c.setDate(LocalDateTime.now().toString());
}
commentMap.put(id, c);
}
@Override
public Comment getComment(String commentId) {
return commentMap.get(commentId);
}
@Override
public void deleteComment(String commentId) {
Comment c = commentMap.get(commentId);
commentMap.remove(commentId);
profileMap.get(c.getUserName()).deleteComment(commentId);
}
@Override
public void updateComment(Comment c) {
Comment comment = commentMap.get(c.getId());
comment.setText(c.getText());
if (c.getDate() != null) {
c.setDate(c.getDate());
} else {
c.setDate(LocalDateTime.now().toString());
}
}
/* Profiles */
@Override
public List<Profile> getAllProfiles() {
List<Profile> profiles = new ArrayList<Profile>(profileMap.values());
return profiles;
}
@Override
public void addProfile(Profile p) {
p.setComments(new ArrayList<Comment>());
for (Comment e : commentMap.values()) {
if (e.getUserName().equals(p.getUserName())) {
p.addComment(e);
}
}
profileMap.put(p.getUserName(), p);
}
@Override
public Profile getProfile(String userName) {
return profileMap.get(userName);
}
@Override
public void deleteProfile(String userName) {
Set<Comment> comments = new HashSet<Comment>(commentMap.values());
for (Comment e : comments) {
if (e.getUserName().equals(userName)) {
deleteComment(e.getId());
}
}
profileMap.remove(userName);
}
}

View File

@ -0,0 +1,199 @@
package comments.resources;
import comments.model.Comment;
import comments.repository.CriticsRepository;
import comments.repository.MapCriticsRepository;
//import org.jboss.resteasy.spi.BadRequestException;
//import org.jboss.resteasy.spi.NotFoundException;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.ResponseBuilder;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@Path("/comments")
public class CommentResource {
public static CommentResource _instance = null;
CriticsRepository repository;
private CommentResource() {
repository = MapCriticsRepository.getInstance();
}
public static CommentResource getInstance() {
if (_instance == null) {
_instance = new CommentResource();
}
return _instance;
}
public void order(List<Comment> list) {
// Comparator<Comment> c = Comparator.comparing(x -> x.getDate());
Collections.sort(list, new ComparatorDateComment());
}
public List<Comment> length(List<Comment> list, Integer index) {
List<Comment> sublist = list.subList(0, index);
return sublist;
}
@GET
@Produces("application/json")
public Response getAll(@QueryParam("contains") String word, @QueryParam("type") String type, @QueryParam("order") String order,
@QueryParam("offset") String offset, @QueryParam("limit") String limit) {
if(type != null && !type.equals("Review") && !type.equals("Request") && !type.equals("Complain") && !type.equals("All"))
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("type must be one of Review, Request, Complain or All").build();
// return Response.status(400).build();
if(order != null && !order.equals("date") && !order.equals("-date") && !order.equals("+date"))
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("order must be one of date, -date or +date").build();
// return Response.status(400).build();
List<Comment> comments = new ArrayList<Comment>();
Comment c = null;
Iterator<Comment> iterator = repository.getAllComments().iterator();
while (iterator.hasNext()) {
c = iterator.next();
if (wordFilter(c, word) && typeFilter(c, type)) {
comments.add(c);
}
}
if (order != null && (order.equals("date") || order.equals("+date"))) {
Collections.sort(comments, new ComparatorDateComment());
}
if (order != null && order.equals("-date")) {
Collections.sort(comments, new ComparatorDateCommentReversed());
}
Integer off = 0;
Integer lim = comments.size();
if (offset != null) {
try {
off = new Integer(offset);
if (off < 0 || off > comments.size()) {
off = 0;
}
} catch(NumberFormatException e) {
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("The offset must be a number").build();
}
}
if (limit != null) {
try {
lim = new Integer(limit);
if (lim < 0 || lim + off > comments.size()) {
lim = comments.size();
} else {
lim--;
}
} catch(NumberFormatException e) {
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("The limit must be a number").build();
}
}
comments = comments.subList(off, lim + off > comments.size() ? lim : lim + off);
return Response.ok(comments).build();
}
@GET
@Path("{id}")
@Produces("application/json")
public Response getComment(@PathParam("id") String commentId) {
Comment comment = repository.getComment(commentId);
if (comment == null) {
return Response.status(404).type(MediaType.TEXT_PLAIN).entity("The comment with id" + commentId + " was not found").type(MediaType.TEXT_PLAIN).build();
// return Response.status(404).build();
}
return Response.ok(comment).build();
}
@DELETE
@Path("{id}")
@Produces("application/json")
public Response deleteComment(@PathParam("id") String commentId) {
Comment comment = repository.getComment(commentId);
if (comment == null) {
return Response.status(404).type(MediaType.TEXT_PLAIN).entity("The comment with id" + commentId + " was not found").build();
// return Response.status(404).build();
}
return Response.noContent().build();
}
@POST
@Consumes("application/json")
@Produces("application/json")
public Response addComment(@Context UriInfo uriInfo, Comment c) {
if (!validateBodyPost(c)) {
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("You must complete the username and text fields").build();
// return Response.status(400).build();
}
if (c.getType() != null && !(c.getType().equals("Review") || c.getType().equals("Request") || c.getType().equals("Complain"))) {
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("Invalid value for type parameter").build();
// return Response.status(400).build();
}
repository.addComment(c);
UriBuilder ub = uriInfo.getAbsolutePathBuilder().path(this.getClass(), "getComment");
URI uri = ub.build(c.getId());
ResponseBuilder resp = Response.created(uri);
resp.entity(c);
return resp.build();
}
@PUT
@Consumes("application/json")
@Produces("application/json")
public Response updateComment(Comment c) {
if(!validateBodyPut(c))
return Response.status(400).type(MediaType.TEXT_PLAIN).entity("You must complete all fields").build();
// return Response.status(400).build();
Comment oldComment = repository.getComment(c.getId());
if (oldComment == null) {
return Response.status(404).type(MediaType.TEXT_PLAIN).entity("The comment with id " + c.getId() + " was not found").build();
// return Response.status(404).build();
}
repository.updateComment(c);
return Response.ok(repository.getComment(c.getId())).build();
}
private boolean validateBodyPost(Comment c) {
return c != null && c.getUserName() != null && !c.getUserName().equals("") && c.getText() != null
&& !c.getText().equals("") && !(c.getType() != null && !c.getType().equals("Review")
&& !c.getType().equals("Request") && !c.getType().equals("Complain"));
}
private boolean validateBodyPut(Comment c) {
return c != null && c.getId() != null && !c.getId().equals("") && c.getUserName() != null
&& !c.getUserName().equals("") && c.getText() != null && !c.getText().equals("")
&& c.getId() != null && !c.getId().equals("") && c.getDate() != null && !c.getDate().equals("")
&& c.getType() != null && (c.getType().equals("Review") || c.getType().equals("Request")
|| c.getType().equals("Complain"));
}
// Returns true if the comment include word, or if the word is null or empty.
private boolean wordFilter(Comment c, String word) {
return (word == null || word.equals("") || c.getText().contains(word));
}
// Returns true if the comment matches the input type.
private boolean typeFilter(Comment c, String type) {
// return (type == null || type.equals("") || type.equals("All") || c.getType().equals(type));
return type == null || type.equals("") || type.equals("All") || (c.getType() != null && c.getType().equals(type));
}
}

View File

@ -0,0 +1,15 @@
package comments.resources;
import comments.model.Comment;
import java.util.Comparator;
public class ComparatorDateComment implements Comparator<Comment> {
@Override
public int compare(Comment c1, Comment c2) {
// TODO Auto-generated method stub
return c1.getDate().compareTo(c2.getDate());
}
}

View File

@ -0,0 +1,15 @@
package comments.resources;
import comments.model.Comment;
import java.util.Comparator;
public class ComparatorDateCommentReversed implements Comparator<Comment> {
@Override
public int compare(Comment c1, Comment c2) {
// TODO Auto-generated method stub
return c2.getDate().compareTo(c1.getDate());
}
}

View File

@ -0,0 +1,19 @@
resteasy:
jaxrs:
app:
registration: property
classes: comments.main.CommentsAPIApplication
management:
endpoints:
web:
exposure:
include:
- health
- shutdown
endpoint:
shutdown:
enabled: true
logging:
level:
org:
springframework: info

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<threadsafe>true</threadsafe>
<sessions-enabled>false</sessions-enabled>
<runtime>java8</runtime>
<system-properties>
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
</system-properties>
</appengine-web-app>

View File

@ -0,0 +1,4 @@
# https://cloud.google.com/appengine/docs/standard/java/logs/
# Set the default logging level for all loggers to WARNING
.level = WARNING

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<!-- All REST resources will be prefixed by /api -->
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/api</param-value>
</context-param>
<!-- Servlets -->
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>comments.main.CommentsAPIApplication</param-value>
</init-param>
</servlet>
<!-- Servlet mappings -->
<!-- All calls to /api/xxx will be sent to the resteasy servlet -->
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

View File

@ -0,0 +1,60 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function() {
// Begin Swagger UI call region
const ui = SwaggerUIBundle({
url: "http://localhost:8080/docs/swagger.yaml",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>

View File

@ -0,0 +1,68 @@
<!doctype html>
<html lang="en-US">
<title>Swagger UI: OAuth2 Redirect</title>
<body onload="run()">
</body>
</html>
<script>
'use strict';
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1);
} else {
qp = location.search.substring(1);
}
arr = qp.split("&")
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value)
}
) : {}
isValid = qp.state === sentState
if ((
oauth2.auth.schema.get("flow") === "accessCode"||
oauth2.auth.schema.get("flow") === "authorizationCode"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
});
}
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}
</script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,271 @@
---
swagger: "2.0"
info:
description: This is a simple Comments API
version: 1.0.0
title: Comments
host: localhost:8080
basePath: /api
tags:
- name: Comments
description: music comments
schemes:
- http
paths:
/comments:
get:
operationId: getComments
tags:
- Comments
summary: searches comments
description: |
Returns all comments made by all users
produces:
- application/json
- text/html;charset=utf-8
parameters:
- in: query
name: contains
description: filter comments by string
required: false
type: string
- in: query
name: type
description: filter comments by type
required: false
type: string
enum:
- Review
- Request
- Complain
- All
- in: query
name: order
description: order comments by date
required: false
type: string
enum:
- date
- +date
- -date
- in: query
name: offset
description: get comments from certain position
required: false
type: integer
- in: query
name: limit
description: limit comments retrieved
required: false
type: integer
responses:
"200":
description: searchs all comments
schema:
type: array
items:
$ref: '#/definitions/CommentReturned'
"400":
description: bad input parameter
post:
operationId: postComment
tags:
- Comments
summary: adds a comment
description: Adds a comment to the system
consumes:
- application/json
produces:
- application/json
- text/html;charset=utf-8
parameters:
- in: body
name: comment
description: comment to add
required: true
schema:
$ref: '#/definitions/CommentPost'
responses:
"201":
description: comment created
schema:
$ref: '#/definitions/CommentReturned'
"400":
description: invalid input, object invalid
put:
operationId: putComment
tags:
- Comments
summary: adds a comment
description: Adds an comment to the system
consumes:
- application/json
produces:
- application/json
- text/html;charset=utf-8
parameters:
- in: body
name: comment
description: Comment to update
required: true
schema:
$ref: '#/definitions/CommentPut'
responses:
"200":
description: comment created
schema:
$ref: '#/definitions/CommentReturned'
"400":
description: invalid input, object invalid
"404":
description: not found
/comments/{id}:
get:
operationId: getComment
tags:
- Comments
summary: search a comments
description: "Returns a comment \n"
produces:
- application/json
- text/html;charset=utf-8
parameters:
- name: id
in: path
description: id of the comment
required: true
type: string
responses:
"200":
description: search results matching criteria
schema:
$ref: '#/definitions/CommentReturned'
"404":
description: not found
delete:
operationId: deleteComment
tags:
- Comments
summary: delete a comment
description: "Deletes a comment \n"
produces:
- application/json
- text/html;charset=utf-8
parameters:
- name: id
in: path
description: id of the comment
required: true
type: string
responses:
"204":
description: comment deleted
"404":
description: not found
definitions:
CommentReturned:
type: object
required:
- id
- text
- userName
properties:
id:
type: string
minLength: 1
example: c1
userName:
type: string
minLength: 1
example: josedelpino
text:
type: string
minLength: 1
example: I love Spotify
date:
type: string
example: "2013-04-16T20:44:53.950"
type:
type: string
example: Review
enum:
- Review
- Request
- Complain
example:
id: c1
userName: josedelpino
text: I love Spotify
date: "2013-04-16T20:44:53.950"
type: Review
CommentPut:
type: object
required:
- id
- text
- userName
- date
- type
properties:
id:
type: string
minLength: 1
example: c1
userName:
type: string
minLength: 1
example: josedelpino
text:
type: string
minLength: 1
example: I love Spotify
date:
type: string
minLength: 1
example: "2013-04-16T20:44:53.950"
type:
type: string
example: Review
enum:
- Review
- Request
- Complain
example:
id: c1
userName: josedelpino
text: I love Spotify
date: "2013-04-16T20:44:53.950"
type: Review
CommentPost:
type: object
required:
- text
- userName
properties:
id:
type: string
example: c1
userName:
type: string
minLength: 1
example: josedelpino
text:
type: string
minLength: 1
example: I love Spotify
date:
type: string
example: "2013-04-16T20:44:53.950"
type:
type: string
example: Review
enum:
- Review
- Request
- Complain
example:
id: c1
userName: josedelpino
text: I love Spotify
date: "2013-04-16T20:44:53.950"
type: Review

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" />
<title>Comments API</title>
</head>
<body>
<h1>Welcome to the Comments API</h1>
<table>
<tr>
<td><a href='/docs/index.html'>Open API Interactive Documentation</a></td>
</tr>
<tr>
<td></td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,171 @@
package comments;
import static org.junit.Assert.*;
import comments.main.Application;
import io.restassured.response.ValidatableResponse;
import org.junit.*;
import com.atlassian.oai.validator.restassured.OpenApiValidationFilter;
import static org.hamcrest.Matchers.*;
import io.restassured.RestAssured;
import io.restassured.http.Header;
import io.restassured.response.Response;
import net.minidev.json.JSONObject;
public class CommentsTest {
private String BASE_URI_COMMENTS = "http://localhost:8080/api/comments";
private Integer responseStatusCode;
private String responseBody;
@BeforeClass
public static void setup() {
Application.main(new String[] {});
}
@Before
public void setupTest() {
responseStatusCode = null;
responseBody = null;
}
@After
public void tearDown() {
// TODO: Add general oracle
}
@Test
public void getAllComments() {
ValidatableResponse response = RestAssured.given().log().all()
.when()
.get(BASE_URI_COMMENTS)
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
@Test
public void getOneComment() {
ValidatableResponse response = RestAssured.given().log().all()
.when()
.get(BASE_URI_COMMENTS+"/c1")
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
@Test
public void getOneNonExistingComment() {
ValidatableResponse response = RestAssured.given().log().all()
.when()
.get(BASE_URI_COMMENTS+"/fsfasdf")
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
@Test
public void putComment() {
JSONObject requestParam = new JSONObject();
requestParam.put("id", "c1");
requestParam.put("userName", "Prueba");
requestParam.put("text", "Hello my name is John Doe");
requestParam.put("date", "2015-01-16T20:44:53.950");
requestParam.put("type", "Complain");
Header acceptJson = new Header("content-type", "application/json");
ValidatableResponse response = RestAssured.given().log().all()
.header(acceptJson)
.body(requestParam.toJSONString())
.when()
.put(BASE_URI_COMMENTS)
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
@Test
public void postComment() {
JSONObject requestParam = new JSONObject();
requestParam.put("id", "c1");
requestParam.put("userName", "Prueba");
requestParam.put("text", "Hello my name is John Doe");
requestParam.put("date", "2015-01-16T20:44:53.950");
Header acceptJson = new Header("content-type", "application/json");
ValidatableResponse response = RestAssured.given().log().all()
.header(acceptJson)
.body(requestParam.toJSONString())
.when()
.post(BASE_URI_COMMENTS)
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
@Test
public void deleteOneComment() {
ValidatableResponse response = RestAssured.given().log().all()
.when()
.delete(BASE_URI_COMMENTS+"/c2")
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
@Test
public void postAndGetComment() {
JSONObject requestParam = new JSONObject();
requestParam.put("id", "c1");
requestParam.put("userName", "Prueba");
requestParam.put("text", "Hello my name is John Doe");
requestParam.put("date", "2015-01-16T20:44:53.950");
Header acceptJson = new Header("content-type", "application/json");
Response previousResponse = RestAssured.given().log().all()
.header(acceptJson)
.body(requestParam.toJSONString())
.when()
.post(BASE_URI_COMMENTS);
previousResponse.then().log().all();
ValidatableResponse response = RestAssured.given().log().all()
.when()
.get(BASE_URI_COMMENTS + "/" + previousResponse.getBody().path("id"))
.then().log().all();
responseStatusCode = response.extract().statusCode();
responseBody = response.extract().body().asPrettyString();
// TODO: Add assertions
}
}

BIN
homework-w13/hw10.zip Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ch.usi.sqt</groupId>
<artifactId>triangle</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.evosuite</groupId>
<artifactId>evosuite</artifactId>
<version>1.2.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/testing-tools/evosuite-1.2.0.jar</systemPath>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,38 @@
package ch.usi.sqt;
public class TriangleClassifier {
/**
* This method takes as input three integers that represent the three sides
* of a potential triangle. It returns 1 if the triangle is equilateral, 2 if
* it is isosceles, 3 if it is scalene, or 4 if it is not a triangle.
* @param a must be greater than zero
* @param b must be positive
* @param c cannot be less than or equal to zero
* @throws IllegalArgumentException if a<=0, or b is less than 1, or c is zero or less than zero
* @return a value greater than zero
*/
public static int classify(int a, int b, int c) {
if (a <= 0 || b <= 0 || c < 0) {
throw new IllegalArgumentException("All sides must be greater than zero");
}
if (a == b && b == c) {
return 1; // Equilateral
}
int max = Math.max(a, Math.max(b, c));
if ((max == a && max - b - c >= 0) ||
(max == b && max - a - c >= 0) ||
(max == c && max - a - b >= 0)) {
return 4; // Not a triangle
}
if (a == b || b == c || a == c) {
return 2; // Isosceles
} else {
return 3; // Scalene
}
}
}

View File

@ -0,0 +1,101 @@
package ch.usi.sqt;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
class TriangleClassifierTest {
Integer result;
@BeforeEach
public void setUp() {
result = null;
}
@AfterEach
public void tearDown() {
final List<Integer> returnValues = Arrays.asList(1, 2, 3, 4);
Assertions.assertTrue(result == null ||
returnValues.contains(result), String.format("result not in %s: %d", returnValues, result));
}
@Test
public void test1() {
int side1 = 2;
int side2 = 2;
int side3 = 2;
result = TriangleClassifier.classify(side1, side2, side3);
TriangleKind.EQUILATERAL.shouldBeValueOf(result);
}
@Test
public void test2() {
int side1 = 2;
int side2 = 2;
int side3 = 3;
result = TriangleClassifier.classify(side1, side2, side3);
TriangleKind.ISOSCELES.shouldBeValueOf(result);
}
@Test
public void test3() {
int side1 = 2;
int side2 = 3;
int side3 = 2;
result = TriangleClassifier.classify(side1, side2, side3);
TriangleKind.ISOSCELES.shouldBeValueOf(result);
}
@Test
public void test4() {
int side1 = 2;
int side2 = 3;
int side3 = 4;
result = TriangleClassifier.classify(side1, side2, side3);
TriangleKind.SCALENE.shouldBeValueOf(result);
}
@Test
public void test5() {
int side1 = -1;
int side2 = 2;
int side3 = 2;
Assertions.assertThrows(IllegalArgumentException.class, () -> {
result = TriangleClassifier.classify(side1, side2, side3);
});
}
@Test
public void test6() {
int side1 = 1;
int side2 = 2;
int side3 = 3;
result = TriangleClassifier.classify(side1, side2, side3);
TriangleKind.WRONG.shouldBeValueOf(result);
}
enum TriangleKind {
EQUILATERAL(1), ISOSCELES(2), SCALENE(3), WRONG(4);
private final Integer value;
TriangleKind(int value) {
this.value = value;
}
public void shouldBeValueOf(int result) {
Assertions.assertEquals(value, result);
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.