diff --git a/.travis.yml b/.travis.yml index d9f33d9..455ca3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,12 @@ addons: sonarqube: organization: flux-coordinator +services: + - mongodb + +before_script: + - sleep 15 + script: - sbt ++$TRAVIS_SCALA_VERSION test - sonar-scanner diff --git a/app/actors/measurements/MeasurementActor.java b/app/actors/measurements/MeasurementActor.java new file mode 100644 index 0000000..0c994a0 --- /dev/null +++ b/app/actors/measurements/MeasurementActor.java @@ -0,0 +1,34 @@ +package actors.measurements; + +import akka.actor.AbstractActor; +import akka.actor.ActorRef; +import akka.actor.Props; +import models.Reading; + +public class MeasurementActor extends AbstractActor { + // HACK: ELU Had to make the Actor Ref public static, until I find a way to find the actor inside the actorsystem (and tell him something). + public static ActorRef out; + + public static Props props(ActorRef out) { + return Props.create(MeasurementActor.class, out); + } + + public MeasurementActor(final ActorRef out) { + MeasurementActor.out = out; + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(Reading.class, putReading -> { + out.tell(putReading, self()); + }) + .build(); + } + + @Override + public void postStop() throws Exception { + super.postStop(); + out = null; + } +} diff --git a/app/controllers/AdminController.java b/app/controllers/AdminController.java index 2ce3efd..d00ede1 100644 --- a/app/controllers/AdminController.java +++ b/app/controllers/AdminController.java @@ -2,6 +2,7 @@ import com.google.inject.Inject; import models.MeasurementMetadata; +import models.MeasurementReadings; import models.Project; import org.bson.types.ObjectId; import play.mvc.Controller; @@ -10,13 +11,14 @@ import repositories.measurements.MeasurementsRepository; import repositories.projects.ProjectsRepository; +import java.util.ArrayList; import java.util.List; public class AdminController extends Controller { private static final int AMOUNT_OF_PROJECTS = 10; private static final int AMOUNT_OF_ROOMS_PER_PROJECT = 5; private static final int AMOUNT_OF_MEASUREMENTS_PER_ROOM = 10; - private static final int AMOUNT_OF_READINGS_PER_MEASUREMENT = 100; + private static final int AMOUNT_OF_READINGS_PER_MEASUREMENT = 1; private final ProjectsRepository projectsRepository; private final MeasurementsRepository measurementsRepository; @@ -29,21 +31,24 @@ public AdminController(final ProjectsRepository projectsRepository, final Measur public Result resetData() { this.projectsRepository.resetRepository(); - this.measurementsRepository.resetRepository(); - final List projects = DataGenerator.generateProjects(AMOUNT_OF_PROJECTS, AMOUNT_OF_ROOMS_PER_PROJECT); - - - projects.forEach(this.projectsRepository::addProject); - this.projectsRepository.getProjects().forEachRemaining(project -> { - project.getRooms().forEach(room -> { - final List roomMeasurements = DataGenerator.generateMeasurements(AMOUNT_OF_MEASUREMENTS_PER_ROOM); - roomMeasurements.forEach(measurementMetadata -> { - final ObjectId measurementId = this.projectsRepository.addMeasurement(project.getProjectId(), room.getName(), measurementMetadata); - this.measurementsRepository.addReadings(measurementId, DataGenerator.generateReadings(AMOUNT_OF_READINGS_PER_MEASUREMENT)); - }); - }); - }); + final List measurementReadings = new ArrayList<>(AMOUNT_OF_PROJECTS * AMOUNT_OF_ROOMS_PER_PROJECT * AMOUNT_OF_MEASUREMENTS_PER_ROOM); + + projects.parallelStream() + .forEach(project -> project.getRooms().forEach(room -> { + final List roomMeasurements = DataGenerator.generateMeasurements(AMOUNT_OF_MEASUREMENTS_PER_ROOM); + roomMeasurements.forEach(measurementMetadata -> { + room.getMeasurements().add(measurementMetadata); + final MeasurementReadings readings = new MeasurementReadings(); + readings.setMeasurementId(measurementMetadata.getMeasurementId()); + readings.getReadings().addAll(DataGenerator.generateReadings(AMOUNT_OF_READINGS_PER_MEASUREMENT)); + measurementReadings.add(readings); + }); + }) + ); + + projectsRepository.addProjects(projects); + measurementsRepository.addMeasurements(measurementReadings); return ok("Created " + AMOUNT_OF_PROJECTS + " projects with " + AMOUNT_OF_ROOMS_PER_PROJECT + " rooms each," + " " + AMOUNT_OF_MEASUREMENTS_PER_ROOM + " measurements per room" + diff --git a/app/controllers/MeasurementsController.java b/app/controllers/MeasurementsController.java index c88be3a..dc743d6 100644 --- a/app/controllers/MeasurementsController.java +++ b/app/controllers/MeasurementsController.java @@ -1,24 +1,24 @@ package controllers; -import com.fasterxml.jackson.core.type.TypeReference; +import actors.measurements.MeasurementActor; +import akka.actor.ActorRef; +import akka.actor.ActorSystem; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectReader; -import java.io.IOException; import models.MeasurementReadings; import models.Reading; import org.bson.types.ObjectId; import play.Logger; import play.libs.Json; import play.libs.concurrent.HttpExecutionContext; -import play.mvc.BodyParser; -import play.mvc.Controller; -import play.mvc.Result; -import play.mvc.Results; +import play.libs.streams.ActorFlow; +import play.mvc.*; import repositories.measurements.MeasurementsRepository; import javax.inject.Inject; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -27,13 +27,19 @@ public class MeasurementsController extends Controller { private final HttpExecutionContext httpExecutionContext; private final MeasurementsRepository measurementsRepository; + private final ActorSystem actorSystem; + private final Materializer materializer; private MeasurementReadings activeMeasurement; + private Flow measurementStreamFlow; @Inject - public MeasurementsController(final HttpExecutionContext httpExecutionContext, final MeasurementsRepository measurementsRepository) { + public MeasurementsController(final HttpExecutionContext httpExecutionContext, final MeasurementsRepository measurementsRepository, + final ActorSystem actorSystem, final Materializer materializer) { this.httpExecutionContext = httpExecutionContext; this.measurementsRepository = measurementsRepository; + this.actorSystem = actorSystem; + this.materializer = materializer; } public CompletionStage getMeasurementById(final String measurementId) { @@ -98,9 +104,11 @@ public Result stopMeasurement() { return ok(); } - public Result isMeasurementActive() { + public Result getActiveMeasurement() { if(this.activeMeasurement != null){ - return Results.ok(); + final MeasurementReadings activeMeasurement = this.measurementsRepository + .getMeasurementReadingsById(this.activeMeasurement.getMeasurementId()); + return Results.ok(Json.toJson(activeMeasurement)); } return Results.noContent(); } @@ -109,20 +117,27 @@ public Result isMeasurementActive() { public CompletableFuture addReading() { return CompletableFuture.supplyAsync(() -> { if(this.activeMeasurement == null) { - return Results.badRequest(); + return Results.noContent(); } try { final JsonNode json = request().body().asJson(); - final ObjectMapper mapper = new ObjectMapper(); - final ObjectReader reader = mapper.readerFor(new TypeReference>() {}); - final List readings = reader.readValue(json); + final Reading[] array = Json.fromJson(json, Reading[].class); + final List readings = new ArrayList<>(Arrays.asList(array)); measurementsRepository.addReadings(activeMeasurement.getMeasurementId(), readings); - } catch (IOException ex) { + if(measurementStreamFlow != null && MeasurementActor.out != null) { + MeasurementActor.out.tell(Json.toJson(readings), ActorRef.noSender()); + } + return ok(); + } + catch (final Exception ex) { Logger.error("Error while adding new readings to measurement" + this.activeMeasurement.getMeasurementId(), ex); return badRequest("Error while adding new readings."); } - - return Results.ok(); }, httpExecutionContext.current()); } + + public WebSocket streamMeasurements() { + measurementStreamFlow = ActorFlow.actorRef(MeasurementActor::props, actorSystem, materializer); + return WebSocket.Json.accept(request -> measurementStreamFlow); + } } \ No newline at end of file diff --git a/app/controllers/ProjectsController.java b/app/controllers/ProjectsController.java index 21f3725..7a02a01 100644 --- a/app/controllers/ProjectsController.java +++ b/app/controllers/ProjectsController.java @@ -9,7 +9,6 @@ import play.mvc.BodyParser; import play.mvc.Controller; import play.mvc.Result; -import repositories.generator.DataGenerator; import repositories.projects.ProjectsRepository; import javax.inject.Inject; diff --git a/app/models/MeasurementReadings.java b/app/models/MeasurementReadings.java index b67abce..cb7ba29 100644 --- a/app/models/MeasurementReadings.java +++ b/app/models/MeasurementReadings.java @@ -1,6 +1,5 @@ package models; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.bson.codecs.pojo.annotations.BsonId; diff --git a/app/models/Project.java b/app/models/Project.java index e80e948..3b61853 100644 --- a/app/models/Project.java +++ b/app/models/Project.java @@ -1,6 +1,5 @@ package models; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import org.bson.codecs.pojo.annotations.BsonId; diff --git a/app/repositories/generator/DataGenerator.java b/app/repositories/generator/DataGenerator.java index 6757ff7..7167ea8 100644 --- a/app/repositories/generator/DataGenerator.java +++ b/app/repositories/generator/DataGenerator.java @@ -1,6 +1,7 @@ package repositories.generator; import models.*; +import org.bson.types.ObjectId; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -13,7 +14,9 @@ * Helper class to generate data more easily. */ public class DataGenerator { - private final static Random random = new Random(); + private static final Random random = new Random(); + + private DataGenerator() { } public static List generateProjects(final int amountOfProjects, final int roomsPerProject) { try { @@ -33,7 +36,7 @@ public static Project generateProject(final int rooms) { try { final Project project = new Project(); - project.setName("Project-" + Math.abs(random.nextInt())); + project.setName("Project-" + random.nextInt(Integer.MAX_VALUE)); project.setDescription("This is an example project and was automatically generated on " + getLocalDateTime() + "."); project.setRooms(generateRooms(rooms)); @@ -61,7 +64,7 @@ public static Room generateRoom() { try { final Room room = new Room(); - room.setName("Room-" + Math.abs(random.nextInt())); + room.setName("Room-" + random.nextInt(Integer.MAX_VALUE)); room.setDescription("This is an example room and was automatically generated on " + getLocalDateTime() + "."); room.setLength(random.nextDouble() * 100); room.setWidth(random.nextDouble() * 100); @@ -122,7 +125,7 @@ public static AnchorPosition generateAnchorPosition() { try { final AnchorPosition position = new AnchorPosition(); - position.setName("Anker-" + Math.abs(random.nextInt())); + position.setName("Anker-" + random.nextInt(Integer.MAX_VALUE)); position.setXPosition(random.nextDouble()); position.setYPosition(random.nextDouble()); position.setZPosition(random.nextDouble()); @@ -139,6 +142,7 @@ public static MeasurementMetadata generateMeasurementMetadata() { try { final MeasurementMetadata measurementMetadata = new MeasurementMetadata(); + measurementMetadata.setMeasurementId(new ObjectId()); measurementMetadata.setCreator("Generated"); measurementMetadata.setDescription("Generated automatically"); measurementMetadata.setName("AutoGenenerated" + random.nextInt()); diff --git a/app/repositories/measurements/MeasurementsRepository.java b/app/repositories/measurements/MeasurementsRepository.java index fc02a4b..964f301 100644 --- a/app/repositories/measurements/MeasurementsRepository.java +++ b/app/repositories/measurements/MeasurementsRepository.java @@ -1,6 +1,5 @@ package repositories.measurements; -import models.MeasurementMetadata; import models.MeasurementReadings; import models.Reading; import org.bson.types.ObjectId; @@ -19,4 +18,6 @@ public interface MeasurementsRepository { void addReadings(final ObjectId measurementId, final List readings); void resetRepository(); + + void addMeasurements(final List measurementReadings); } diff --git a/app/repositories/measurements/MeasurementsRepositoryMock.java b/app/repositories/measurements/MeasurementsRepositoryMock.java index cb05f51..55d1bd8 100644 --- a/app/repositories/measurements/MeasurementsRepositoryMock.java +++ b/app/repositories/measurements/MeasurementsRepositoryMock.java @@ -1,11 +1,9 @@ package repositories.measurements; import com.google.inject.Singleton; -import models.MeasurementMetadata; import models.MeasurementReadings; import models.Reading; import org.bson.types.ObjectId; -import repositories.generator.DataGenerator; import java.util.ArrayList; import java.util.Iterator; @@ -47,12 +45,15 @@ public void addReadings(final ObjectId measurementId, final List readin final Optional measurementReadings = readingsList.parallelStream() .filter(m -> m.getMeasurementId().equals(measurementId)) .findAny(); - - measurementReadings.get().getReadings().addAll(readings); + measurementReadings.orElseThrow(() -> new NullPointerException("Measurement to add the reading was not found.")).getReadings().addAll(readings); } - @Override public void resetRepository() { this.readingsList.clear(); } + + @Override + public void addMeasurements(final List measurementReadings) { + this.readingsList.addAll(measurementReadings); + } } diff --git a/app/repositories/measurements/MeasurementsRepositoryMongo.java b/app/repositories/measurements/MeasurementsRepositoryMongo.java index 176328d..f6ec0be 100644 --- a/app/repositories/measurements/MeasurementsRepositoryMongo.java +++ b/app/repositories/measurements/MeasurementsRepositoryMongo.java @@ -17,8 +17,8 @@ @Singleton public class MeasurementsRepositoryMongo implements MeasurementsRepository { - private final static String DATABASE_NAME = "flux"; - private final static String COLLECTION_NAME = "measurements"; + private static final String DATABASE_NAME = "flux"; + private static final String COLLECTION_NAME = "measurements"; private final MongoClient mongoClient; @@ -45,7 +45,7 @@ public MeasurementReadings getMeasurementReadingsById(final ObjectId measurement @Override public ObjectId addMeasurement(final MeasurementReadings readings) { - if(readings.getMeasurementId() != null) { + if(readings.getMeasurementId() == null) { readings.setMeasurementId(new ObjectId()); } getCollection().insertOne(readings); @@ -62,4 +62,9 @@ public void resetRepository() { getCollection().drop(); this.mongoClient.getDatabase(DATABASE_NAME).createCollection(COLLECTION_NAME); } + + @Override + public void addMeasurements(final List measurementReadings) { + this.getCollection().insertMany(measurementReadings); + } } diff --git a/app/repositories/projects/ProjectsRepository.java b/app/repositories/projects/ProjectsRepository.java index 08e69b1..b47a4de 100644 --- a/app/repositories/projects/ProjectsRepository.java +++ b/app/repositories/projects/ProjectsRepository.java @@ -2,7 +2,6 @@ import models.MeasurementMetadata; import models.Project; -import models.Reading; import org.bson.types.ObjectId; import java.util.Iterator; @@ -13,6 +12,8 @@ public interface ProjectsRepository { ObjectId addProject(final Project project); + void addProjects(final List projects); + Project getProjectById(final ObjectId projectId); ObjectId addMeasurement(final ObjectId projectId, final String roomName, final MeasurementMetadata measurementMetadata); diff --git a/app/repositories/projects/ProjectsRepositoryMock.java b/app/repositories/projects/ProjectsRepositoryMock.java index 77ec634..7bc055a 100644 --- a/app/repositories/projects/ProjectsRepositoryMock.java +++ b/app/repositories/projects/ProjectsRepositoryMock.java @@ -5,24 +5,21 @@ import models.Project; import models.Room; import org.bson.types.ObjectId; -import repositories.generator.DataGenerator; import repositories.measurements.MeasurementsRepository; import javax.inject.Inject; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Optional; public class ProjectsRepositoryMock implements ProjectsRepository { - private final static int AMOUNT_OF_PROJECTS = 10; - private final static int AMOUNT_OF_ROOMS_PER_PROJECT = 5; - private final List projects; private final MeasurementsRepository measurementsRepository; @Inject public ProjectsRepositoryMock(final MeasurementsRepository measurementsRepository) { - this.projects = DataGenerator.generateProjects(AMOUNT_OF_PROJECTS, AMOUNT_OF_ROOMS_PER_PROJECT); + this.projects = new ArrayList<>(); this.measurementsRepository = measurementsRepository; } @@ -33,10 +30,16 @@ public Iterator getProjects() { @Override public ObjectId addProject(final Project project) { - final ObjectId newId = new ObjectId(); - project.setProjectId(newId); + if(project.getProjectId() == null) { + project.setProjectId(new ObjectId()); + } this.projects.add(project); - return newId; + return project.getProjectId(); + } + + @Override + public void addProjects(List projects) { + this.projects.addAll(projects); } @Override @@ -59,8 +62,7 @@ public ObjectId addMeasurement(final ObjectId projectId, final String roomName, final MeasurementReadings measurementReadings = new MeasurementReadings(); measurementReadings.setMeasurementId(measurementId); - //noinspection ConstantConditions - room.get().getMeasurements().add(measurementMetadata); + room.orElseThrow(() -> new NullPointerException("Room to add the measurement into was not found.")).getMeasurements().add(measurementMetadata); measurementsRepository.addMeasurement(measurementReadings); return measurementId; } @@ -73,5 +75,6 @@ public long countProjects() { @Override public void resetRepository() { this.projects.clear(); + this.measurementsRepository.resetRepository(); } } diff --git a/app/repositories/projects/ProjectsRepositoryMongo.java b/app/repositories/projects/ProjectsRepositoryMongo.java index e03c2bd..6891805 100644 --- a/app/repositories/projects/ProjectsRepositoryMongo.java +++ b/app/repositories/projects/ProjectsRepositoryMongo.java @@ -10,23 +10,27 @@ import models.Room; import org.bson.Document; import org.bson.types.ObjectId; +import repositories.measurements.MeasurementsRepository; import javax.inject.Inject; import java.util.Iterator; +import java.util.List; import java.util.Optional; import static com.mongodb.client.model.Filters.eq; public class ProjectsRepositoryMongo implements ProjectsRepository { - private final static String DATABASE_NAME = "flux"; - private final static String PROJECTS_COLLECTION_NAME = "projects"; - private final static String MEASUREMENT_COLLECTION_NAME = "measurements"; + private static final String DATABASE_NAME = "flux"; + private static final String PROJECTS_COLLECTION_NAME = "projects"; + private static final String MEASUREMENT_COLLECTION_NAME = "measurements"; private final MongoClient mongoClient; + private final MeasurementsRepository measurementsRepository; @Inject - public ProjectsRepositoryMongo(final MongoClient mongoClient) { + public ProjectsRepositoryMongo(final MongoClient mongoClient, final MeasurementsRepository measurementsRepository) { this.mongoClient = mongoClient; + this.measurementsRepository = measurementsRepository; } private MongoCollection getProjectsCollection() { @@ -46,10 +50,15 @@ public Iterator getProjects() { @Override public ObjectId addProject(final Project project) { - final ObjectId newId = new ObjectId(); - project.setProjectId(newId); + if(project.getProjectId() == null) { + project.setProjectId(new ObjectId()); + } getProjectsCollection().insertOne(project); - return newId; + return project.getProjectId(); + } + + public void addProjects(final List projects) { + getProjectsCollection().insertMany(projects); } @Override @@ -66,8 +75,7 @@ public ObjectId addMeasurement(final ObjectId projectId, final String roomName, final ObjectId measurementId = new ObjectId(); measurementMetadata.setMeasurementId(measurementId); - //noinspection ConstantConditions (We want to throw here!) - roomOptional.get().getMeasurements().add(measurementMetadata); + roomOptional.orElseThrow(() -> new NullPointerException("There was no room to add the measurement")).getMeasurements().add(measurementMetadata); final MeasurementReadings measurementReadings = new MeasurementReadings(); measurementReadings.setMeasurementId(measurementId); @@ -96,6 +104,7 @@ public long countProjects() { @Override public void resetRepository() { + this.measurementsRepository.resetRepository(); getProjectsCollection().drop(); this.mongoClient.getDatabase(DATABASE_NAME).createCollection(PROJECTS_COLLECTION_NAME); } diff --git a/conf/routes b/conf/routes index e24d38e..257d420 100644 --- a/conf/routes +++ b/conf/routes @@ -8,13 +8,14 @@ GET /reset controllers.AdminController.resetDat GET /projects controllers.ProjectsController.getProjects(limit: Int ?=5) POST /projects controllers.ProjectsController.addProject GET /projects/:projectId controllers.ProjectsController.getProjectById(projectId: String) -GET /measurements/active controllers.MeasurementsController.isMeasurementActive +GET /measurements/active controllers.MeasurementsController.getActiveMeasurement GET /measurements/:measurementId controllers.MeasurementsController.getMeasurementById(measurementId : String) GET /measurements controllers.MeasurementsController.getMeasurements(limit: Int ?=5) POST /measurements controllers.MeasurementsController.createMeasurement PUT /measurements/active/:measurementId controllers.MeasurementsController.startMeasurement(measurementId : String) DELETE /measurements/active controllers.MeasurementsController.stopMeasurement POST /measurements/active/readings controllers.MeasurementsController.addReading +GET /streamMeasurements controllers.MeasurementsController.streamMeasurements # Map static resources from the /public folder to the /assets URL path -GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) +GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) diff --git a/test/controllers/MeasurementsControllerTest.java b/test/controllers/MeasurementsControllerTest.java index 5a2cbfb..39a4c05 100644 --- a/test/controllers/MeasurementsControllerTest.java +++ b/test/controllers/MeasurementsControllerTest.java @@ -1,9 +1,9 @@ package controllers; import helpers.Helpers; -import models.MeasurementMetadata; -import models.MeasurementReadings; +import models.*; import org.bson.types.ObjectId; +import org.junit.Before; import org.junit.Test; import play.Application; import play.inject.guice.GuiceApplicationBuilder; @@ -13,22 +13,28 @@ import play.test.WithApplication; import repositories.generator.DataGenerator; import repositories.measurements.MeasurementsRepository; -import repositories.measurements.MeasurementsRepositoryMock; import repositories.projects.ProjectsRepository; -import repositories.projects.ProjectsRepositoryMock; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static play.inject.Bindings.bind; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.*; import static play.test.Helpers.*; public class MeasurementsControllerTest extends WithApplication { @Override protected Application provideApplication() { return new GuiceApplicationBuilder() - .overrides(bind(MeasurementsRepository.class).to(MeasurementsRepositoryMock.class)) - .overrides(bind(ProjectsRepository.class).to(ProjectsRepositoryMock.class)) - .build(); + .build(); + } + + @Before + public void setUp() { + final Http.RequestBuilder request = new Http.RequestBuilder() + .method(GET) + .uri("/reset"); + final Result result = route(app, request); + assertEquals(OK, result.status()); } @Test @@ -88,7 +94,7 @@ public void getMeasurementById_GetExisting_OK() { final MeasurementReadings measurementReadings = new MeasurementReadings(); final MeasurementsRepository repository = app.injector().instanceOf(MeasurementsRepository.class); final ObjectId newMeasurementId = repository.addMeasurement(measurementReadings); - final MeasurementReadings expectedReading = repository.getMeasurementReadings().next(); + final MeasurementReadings expectedReading = repository.getMeasurementReadingsById(newMeasurementId); final Http.RequestBuilder request = new Http.RequestBuilder() .method(GET) .uri("/measurements/" + newMeasurementId); @@ -116,4 +122,80 @@ public void getMeasurementById_InvalidObjectId_BadRequest() { final Result result = route(app, request); assertEquals(BAD_REQUEST, result.status()); } + + @Test + public void startMeasurement_StartFirst_IsActive() { + final ProjectsRepository projectsRepository = app.injector().instanceOf(ProjectsRepository.class); + final Project project = projectsRepository.getProjects().next(); + final Room room = project.getRooms().get(0); + final MeasurementMetadata measurementMetadata = room.getMeasurements().get(0); + + final Http.RequestBuilder request = new Http.RequestBuilder() + .method(PUT) + .uri("/measurements/active/" + measurementMetadata.getMeasurementId()); + final Result result = route(app, request); + assertEquals(OK, result.status()); + } + + @Test + public void addReadings_AddOne_ReadingAdded() { + final MeasurementMetadata activeMeasurement = getOrSetActiveMeasurement(); + + final Reading reading = DataGenerator.generateReading(); + final List readingList = new ArrayList<>(1); + readingList.add(reading); + final Http.RequestBuilder request = new Http.RequestBuilder() + .method(POST) + .uri("/measurements/active/readings") + .bodyJson(Json.toJson(readingList)); + final Result result = route(app, request); + assertEquals(OK, result.status()); + + final MeasurementsRepository repository = app.injector().instanceOf(MeasurementsRepository.class); + final MeasurementReadings measurementReadings = repository.getMeasurementReadingsById(activeMeasurement.getMeasurementId()); + assertTrue(measurementReadings.getReadings().contains(reading)); + } + + @Test + public void addReadings_AddMultiple_ReadingAdded() { + final int amountOfReadings = 10; + final MeasurementMetadata activeMeasurement = getOrSetActiveMeasurement(); + + final List readingList = DataGenerator.generateReadings(amountOfReadings); + final Http.RequestBuilder request = new Http.RequestBuilder() + .method(POST) + .uri("/measurements/active/readings") + .bodyJson(Json.toJson(readingList)); + final Result result = route(app, request); + assertEquals(OK, result.status()); + + final MeasurementsRepository repository = app.injector().instanceOf(MeasurementsRepository.class); + final MeasurementReadings measurementReadings = repository.getMeasurementReadingsById(activeMeasurement.getMeasurementId()); + assertTrue(measurementReadings.getReadings().containsAll(readingList)); + } + + private MeasurementMetadata getOrSetActiveMeasurement() { + final Http.RequestBuilder getActiveRequest = new Http.RequestBuilder() + .method(GET) + .uri("/measurements/active"); + final Result getResult = route(app, getActiveRequest); + + MeasurementMetadata measurementMetadata; + if(getResult.status() == OK) { + measurementMetadata = Helpers.convertFromJSON(getResult, MeasurementMetadata.class); + } else { + final ProjectsRepository projectsRepository = app.injector().instanceOf(ProjectsRepository.class); + final Project project = projectsRepository.getProjects().next(); + final Room room = project.getRooms().get(0); + measurementMetadata = room.getMeasurements().get(0); + + final Http.RequestBuilder setActiveRequest = new Http.RequestBuilder() + .method(PUT) + .uri("/measurements/active/" + measurementMetadata.getMeasurementId()); + final Result setActiveResult = route(app, setActiveRequest); + assertEquals(OK, setActiveResult.status()); + } + + return measurementMetadata; + } } \ No newline at end of file diff --git a/test/controllers/ProjectsControllerTest.java b/test/controllers/ProjectsControllerTest.java index 43f32ee..c69f62c 100644 --- a/test/controllers/ProjectsControllerTest.java +++ b/test/controllers/ProjectsControllerTest.java @@ -2,6 +2,7 @@ import helpers.Helpers; import models.Project; +import org.junit.Before; import org.junit.Test; import play.Application; import play.inject.guice.GuiceApplicationBuilder; @@ -10,26 +11,27 @@ import play.mvc.Result; import play.test.WithApplication; import repositories.generator.DataGenerator; -import repositories.measurements.MeasurementsRepository; -import repositories.measurements.MeasurementsRepositoryMock; -import repositories.projects.ProjectsRepository; -import repositories.projects.ProjectsRepositoryMock; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static play.inject.Bindings.bind; -import static play.mvc.Http.Status.CREATED; import static play.test.Helpers.*; public class ProjectsControllerTest extends WithApplication { @Override protected Application provideApplication() { return new GuiceApplicationBuilder() - .overrides(bind(MeasurementsRepository.class).to(MeasurementsRepositoryMock.class)) - .overrides(bind(ProjectsRepository.class).to(ProjectsRepositoryMock.class)) .build(); } + @Before + public void setUp() { + final Http.RequestBuilder request = new Http.RequestBuilder() + .method(GET) + .uri("/reset"); + final Result result = route(app, request); + assertEquals(OK, result.status()); + } + @Test public void createProjects_BestCase_OK() { final Project project = DataGenerator.generateProject(5); diff --git a/test/helpers/Helpers.java b/test/helpers/Helpers.java index b16a057..045be19 100644 --- a/test/helpers/Helpers.java +++ b/test/helpers/Helpers.java @@ -5,6 +5,11 @@ import play.mvc.Result; public class Helpers { + + private Helpers() { + + } + public static T convertFromJSON(final Result result, Class clazz) { final JsonNode node = Json.parse(play.test.Helpers.contentAsString(result)); return Json.fromJson(node, clazz);