Java 11 migrate all remaining s (#1120)
* Moves saga to Java 11 * Moves semaphore to Java 11 * Moves servant to Java 11 * Moves serverless to Java 11 * Moves service-layer to Java 11 * Moves service-locator to Java 11 * Moves sharding to Java 11 * Moves singleton to Java 11 * Moves spatial-partition to Java 11 * Moves specification to Java 11 * Moves state to Java 11 * Moves step-builder to Java 11 * Moves strategy to Java 11 * Moves subclass-sandbox to Java 11 * Fixes checkstyle issues
This commit is contained in:
parent
310ae50248
commit
cd2a2e7711
@ -25,9 +25,9 @@ package com.iluwatar.saga.choreography;
|
||||
|
||||
|
||||
/**
|
||||
* ChoreographyChapter is an interface representing a contract for an external service.
|
||||
* In that case, a service needs to make a decision what to do further
|
||||
* hence the server needs to get all context representing {@link Saga}
|
||||
* ChoreographyChapter is an interface representing a contract for an external service. In that
|
||||
* case, a service needs to make a decision what to do further hence the server needs to get all
|
||||
* context representing {@link Saga}
|
||||
*/
|
||||
public interface ChoreographyChapter {
|
||||
|
||||
@ -41,6 +41,7 @@ public interface ChoreographyChapter {
|
||||
|
||||
/**
|
||||
* get name method.
|
||||
*
|
||||
* @return service name.
|
||||
*/
|
||||
String getName();
|
||||
|
@ -28,9 +28,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Saga representation.
|
||||
* Saga consists of chapters.
|
||||
* Every ChoreographyChapter is executed a certain service.
|
||||
* Saga representation. Saga consists of chapters. Every ChoreographyChapter is executed a certain
|
||||
* service.
|
||||
*/
|
||||
public class Saga {
|
||||
|
||||
@ -61,6 +60,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* add chapter to saga.
|
||||
*
|
||||
* @param name chapter name
|
||||
* @return this
|
||||
*/
|
||||
@ -71,6 +71,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* set value to last chapter.
|
||||
*
|
||||
* @param value invalue
|
||||
* @return this
|
||||
*/
|
||||
@ -84,6 +85,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* get value from current chapter.
|
||||
*
|
||||
* @return value
|
||||
*/
|
||||
public Object getCurrentValue() {
|
||||
@ -92,6 +94,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* set value to current chapter.
|
||||
*
|
||||
* @param value to set
|
||||
*/
|
||||
public void setCurrentValue(Object value) {
|
||||
@ -100,6 +103,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* set status for current chapter.
|
||||
*
|
||||
* @param result to set
|
||||
*/
|
||||
public void setCurrentStatus(ChapterResult result) {
|
||||
@ -145,8 +149,8 @@ public class Saga {
|
||||
}
|
||||
|
||||
/**
|
||||
* Class presents a chapter status and incoming
|
||||
* parameters(incoming parameter transforms to outcoming parameter).
|
||||
* Class presents a chapter status and incoming parameters(incoming parameter transforms to
|
||||
* outcoming parameter).
|
||||
*/
|
||||
public static class Chapter {
|
||||
private String name;
|
||||
@ -173,6 +177,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* set result.
|
||||
*
|
||||
* @param result {@link ChapterResult}
|
||||
*/
|
||||
public void setResult(ChapterResult result) {
|
||||
@ -181,6 +186,7 @@ public class Saga {
|
||||
|
||||
/**
|
||||
* the result for chapter is good.
|
||||
*
|
||||
* @return true if is good otherwise bad
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
|
@ -27,22 +27,19 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This pattern is used in distributed services to perform a group of operations atomically.
|
||||
* This is an analog of transaction in a database but in terms
|
||||
* of microservices architecture this is executed
|
||||
* in a distributed environment
|
||||
* This pattern is used in distributed services to perform a group of operations atomically. This is
|
||||
* an analog of transaction in a database but in terms of microservices architecture this is
|
||||
* executed in a distributed environment
|
||||
*
|
||||
* <p>A saga is a sequence of local transactions in a certain context.
|
||||
* If one transaction fails for some reason,
|
||||
* the saga executes compensating transactions(rollbacks)
|
||||
* If one transaction fails for some reason, the saga executes compensating transactions(rollbacks)
|
||||
* to undo the impact of the preceding transactions.
|
||||
*
|
||||
* <p>In this approach, there are no mediators or orchestrators services.
|
||||
* All chapters are handled and moved by services manually.
|
||||
*
|
||||
* <p>The major difference with choreography saga is an ability to handle crashed services
|
||||
* (otherwise in choreography services very hard to prevent a saga
|
||||
* if one of them has been crashed)
|
||||
* (otherwise in choreography services very hard to prevent a saga if one of them has been crashed)
|
||||
*
|
||||
* @see com.iluwatar.saga.choreography.Saga
|
||||
* @see Service
|
||||
@ -54,10 +51,10 @@ public class SagaApplication {
|
||||
* main method.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
ServiceDiscoveryService sd = serviceDiscovery();
|
||||
ChoreographyChapter service = sd.findAny();
|
||||
Saga goodOrderSaga = service.execute(newSaga("good_order"));
|
||||
Saga badOrderSaga = service.execute(newSaga("bad_order"));
|
||||
var sd = serviceDiscovery();
|
||||
var service = sd.findAny();
|
||||
var goodOrderSaga = service.execute(newSaga("good_order"));
|
||||
var badOrderSaga = service.execute(newSaga("bad_order"));
|
||||
LOGGER.info("orders: goodOrder is {}, badOrder is {}",
|
||||
goodOrderSaga.getResult(), badOrderSaga.getResult());
|
||||
|
||||
@ -74,7 +71,7 @@ public class SagaApplication {
|
||||
}
|
||||
|
||||
private static ServiceDiscoveryService serviceDiscovery() {
|
||||
ServiceDiscoveryService sd = new ServiceDiscoveryService();
|
||||
var sd = new ServiceDiscoveryService();
|
||||
return sd
|
||||
.discover(new OrderService(sd))
|
||||
.discover(new FlyBookingService(sd))
|
||||
|
@ -29,8 +29,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Common abstraction class representing services.
|
||||
* implementing a general contract @see {@link ChoreographyChapter}
|
||||
* Common abstraction class representing services. implementing a general contract @see {@link
|
||||
* ChoreographyChapter}
|
||||
*/
|
||||
public abstract class Service implements ChoreographyChapter {
|
||||
protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class);
|
||||
@ -43,9 +43,9 @@ public abstract class Service implements ChoreographyChapter {
|
||||
|
||||
@Override
|
||||
public Saga execute(Saga saga) {
|
||||
Saga nextSaga = saga;
|
||||
var nextSaga = saga;
|
||||
Object nextVal;
|
||||
String chapterName = saga.getCurrent().getName();
|
||||
var chapterName = saga.getCurrent().getName();
|
||||
if (chapterName.equals(getName())) {
|
||||
if (saga.isForward()) {
|
||||
nextSaga = process(saga);
|
||||
@ -67,7 +67,7 @@ public abstract class Service implements ChoreographyChapter {
|
||||
|
||||
nextSaga.setCurrentValue(nextVal);
|
||||
}
|
||||
Saga finalNextSaga = nextSaga;
|
||||
var finalNextSaga = nextSaga;
|
||||
|
||||
return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga))
|
||||
.orElseThrow(serviceNotFoundException(chapterName));
|
||||
@ -80,7 +80,7 @@ public abstract class Service implements ChoreographyChapter {
|
||||
|
||||
@Override
|
||||
public Saga process(Saga saga) {
|
||||
Object inValue = saga.getCurrentValue();
|
||||
var inValue = saga.getCurrentValue();
|
||||
LOGGER.info("The chapter '{}' has been started. "
|
||||
+ "The data {} has been stored or calculated successfully",
|
||||
getName(), inValue);
|
||||
@ -91,7 +91,7 @@ public abstract class Service implements ChoreographyChapter {
|
||||
|
||||
@Override
|
||||
public Saga rollback(Saga saga) {
|
||||
Object inValue = saga.getCurrentValue();
|
||||
var inValue = saga.getCurrentValue();
|
||||
LOGGER.info("The Rollback for a chapter '{}' has been started. "
|
||||
+ "The data {} has been rollbacked successfully",
|
||||
getName(), inValue);
|
||||
|
@ -39,7 +39,7 @@ public class WithdrawMoneyService extends Service {
|
||||
|
||||
@Override
|
||||
public Saga process(Saga saga) {
|
||||
Object inValue = saga.getCurrentValue();
|
||||
var inValue = saga.getCurrentValue();
|
||||
|
||||
if (inValue.equals("bad_order")) {
|
||||
LOGGER.info("The chapter '{}' has been started. But the exception has been raised."
|
||||
|
@ -32,6 +32,7 @@ public interface OrchestrationChapter<K> {
|
||||
|
||||
/**
|
||||
* method get name.
|
||||
*
|
||||
* @return service name.
|
||||
*/
|
||||
String getName();
|
||||
|
@ -27,9 +27,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Saga representation.
|
||||
* Saga consists of chapters.
|
||||
* Every ChoreographyChapter is executed by a certain service.
|
||||
* Saga representation. Saga consists of chapters. Every ChoreographyChapter is executed by a
|
||||
* certain service.
|
||||
*/
|
||||
public class Saga {
|
||||
|
||||
|
@ -27,23 +27,19 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This pattern is used in distributed services to perform
|
||||
* a group of operations atomically.
|
||||
* This is an analog of transaction in a database but in terms
|
||||
* of microservices architecture this is executed
|
||||
* in a distributed environment
|
||||
* This pattern is used in distributed services to perform a group of operations atomically. This is
|
||||
* an analog of transaction in a database but in terms of microservices architecture this is
|
||||
* executed in a distributed environment
|
||||
*
|
||||
* <p>A saga is a sequence of local transactions in a certain context.
|
||||
* If one transaction fails for some reason,
|
||||
* the saga executes compensating transactions(rollbacks)
|
||||
* If one transaction fails for some reason, the saga executes compensating transactions(rollbacks)
|
||||
* to undo the impact of the preceding transactions.
|
||||
*
|
||||
* <p>In this approach, there is an orchestrator @see {@link SagaOrchestrator}
|
||||
* that manages all the transactions and directs
|
||||
* the participant services to execute local transactions based on events.
|
||||
* The major difference with choreography saga is an ability to handle crashed services
|
||||
* (otherwise in choreography services very hard to prevent a saga
|
||||
* if one of them has been crashed)
|
||||
* that manages all the transactions and directs the participant services to execute local
|
||||
* transactions based on events. The major difference with choreography saga is an ability to handle
|
||||
* crashed services (otherwise in choreography services very hard to prevent a saga if one of them
|
||||
* has been crashed)
|
||||
*
|
||||
* @see Saga
|
||||
* @see SagaOrchestrator
|
||||
@ -56,7 +52,7 @@ public class SagaApplication {
|
||||
* method to show common saga logic.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());
|
||||
var sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());
|
||||
|
||||
Saga.Result goodOrder = sagaOrchestrator.execute("good_order");
|
||||
Saga.Result badOrder = sagaOrchestrator.execute("bad_order");
|
||||
@ -77,11 +73,10 @@ public class SagaApplication {
|
||||
}
|
||||
|
||||
private static ServiceDiscoveryService serviceDiscovery() {
|
||||
return
|
||||
new ServiceDiscoveryService()
|
||||
.discover(new OrderService())
|
||||
.discover(new FlyBookingService())
|
||||
.discover(new HotelBookingService())
|
||||
.discover(new WithdrawMoneyService());
|
||||
return new ServiceDiscoveryService()
|
||||
.discover(new OrderService())
|
||||
.discover(new FlyBookingService())
|
||||
.discover(new HotelBookingService())
|
||||
.discover(new WithdrawMoneyService());
|
||||
}
|
||||
}
|
||||
|
@ -23,18 +23,18 @@
|
||||
|
||||
package com.iluwatar.saga.orchestration;
|
||||
|
||||
import static com.iluwatar.saga.orchestration.Saga.Result;
|
||||
import static com.iluwatar.saga.orchestration.Saga.Result.CRASHED;
|
||||
import static com.iluwatar.saga.orchestration.Saga.Result.FINISHED;
|
||||
import static com.iluwatar.saga.orchestration.Saga.Result.ROLLBACK;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* The orchestrator that manages all the transactions and directs
|
||||
* the participant services to execute local transactions based on events.
|
||||
* The orchestrator that manages all the transactions and directs the participant services to
|
||||
* execute local transactions based on events.
|
||||
*/
|
||||
public class SagaOrchestrator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SagaOrchestrator.class);
|
||||
@ -45,8 +45,9 @@ public class SagaOrchestrator {
|
||||
|
||||
/**
|
||||
* Create a new service to orchetrate sagas.
|
||||
*
|
||||
* @param saga saga to process
|
||||
* @param sd service discovery @see {@link ServiceDiscoveryService}
|
||||
* @param sd service discovery @see {@link ServiceDiscoveryService}
|
||||
*/
|
||||
public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) {
|
||||
this.saga = saga;
|
||||
@ -59,30 +60,30 @@ public class SagaOrchestrator {
|
||||
*
|
||||
* @param value incoming value
|
||||
* @param <K> type for incoming value
|
||||
* @return result @see {@link Saga.Result}
|
||||
* @return result @see {@link Result}
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <K> Saga.Result execute(K value) {
|
||||
public <K> Result execute(K value) {
|
||||
state.cleanUp();
|
||||
LOGGER.info(" The new saga is about to start");
|
||||
Saga.Result result = FINISHED;
|
||||
var result = FINISHED;
|
||||
K tempVal = value;
|
||||
|
||||
while (true) {
|
||||
int next = state.current();
|
||||
Saga.Chapter ch = saga.get(next);
|
||||
Optional<OrchestrationChapter> srvOpt = sd.find(ch.name);
|
||||
var next = state.current();
|
||||
var ch = saga.get(next);
|
||||
var srvOpt = sd.find(ch.name);
|
||||
|
||||
if (!srvOpt.isPresent()) {
|
||||
if (srvOpt.isEmpty()) {
|
||||
state.directionToBack();
|
||||
state.back();
|
||||
continue;
|
||||
}
|
||||
|
||||
OrchestrationChapter srv = srvOpt.get();
|
||||
var srv = srvOpt.get();
|
||||
|
||||
if (state.isForward()) {
|
||||
ChapterResult processRes = srv.process(tempVal);
|
||||
var processRes = srv.process(tempVal);
|
||||
if (processRes.isSuccess()) {
|
||||
next = state.forward();
|
||||
tempVal = (K) processRes.getValue();
|
||||
@ -90,7 +91,7 @@ public class SagaOrchestrator {
|
||||
state.directionToBack();
|
||||
}
|
||||
} else {
|
||||
ChapterResult rlRes = srv.rollback(tempVal);
|
||||
var rlRes = srv.rollback(tempVal);
|
||||
if (rlRes.isSuccess()) {
|
||||
next = state.back();
|
||||
tempVal = (K) rlRes.getValue();
|
||||
|
@ -27,8 +27,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Common abstraction class representing services.
|
||||
* implementing a general contract @see {@link OrchestrationChapter}
|
||||
* Common abstraction class representing services. implementing a general contract @see {@link
|
||||
* OrchestrationChapter}
|
||||
*
|
||||
* @param <K> type of incoming param
|
||||
*/
|
||||
|
@ -33,10 +33,10 @@ public class SagaChoreographyTest {
|
||||
|
||||
@Test
|
||||
public void executeTest() {
|
||||
ServiceDiscoveryService sd = serviceDiscovery();
|
||||
ChoreographyChapter service = sd.findAny();
|
||||
Saga badOrderSaga = service.execute(newSaga("bad_order"));
|
||||
Saga goodOrderSaga = service.execute(newSaga("good_order"));
|
||||
var sd = serviceDiscovery();
|
||||
var service = sd.findAny();
|
||||
var badOrderSaga = service.execute(newSaga("bad_order"));
|
||||
var goodOrderSaga = service.execute(newSaga("good_order"));
|
||||
|
||||
Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED);
|
||||
Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED);
|
||||
@ -52,7 +52,7 @@ public class SagaChoreographyTest {
|
||||
}
|
||||
|
||||
private static ServiceDiscoveryService serviceDiscovery() {
|
||||
ServiceDiscoveryService sd = new ServiceDiscoveryService();
|
||||
var sd = new ServiceDiscoveryService();
|
||||
return sd
|
||||
.discover(new OrderService(sd))
|
||||
.discover(new FlyBookingService(sd))
|
||||
|
@ -24,8 +24,6 @@ package com.iluwatar.saga.orchestration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* empty test
|
||||
*/
|
||||
|
@ -22,11 +22,12 @@
|
||||
*/
|
||||
package com.iluwatar.saga.orchestration;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import static com.iluwatar.saga.orchestration.Saga.Result;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* test to test orchestration logic
|
||||
@ -37,17 +38,16 @@ public class SagaOrchestratorInternallyTest {
|
||||
|
||||
@Test
|
||||
public void executeTest() {
|
||||
SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());
|
||||
Saga.Result result = sagaOrchestrator.execute(1);
|
||||
Assert.assertEquals(result, Saga.Result.ROLLBACK);
|
||||
var sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery());
|
||||
var result = sagaOrchestrator.execute(1);
|
||||
Assert.assertEquals(result, Result.ROLLBACK);
|
||||
Assert.assertArrayEquals(
|
||||
records.toArray(new String[]{}),
|
||||
new String[]{"+1", "+2", "+3", "+4", "-4", "-3", "-2", "-1"});
|
||||
}
|
||||
|
||||
private static Saga newSaga() {
|
||||
return Saga
|
||||
.create()
|
||||
return Saga.create()
|
||||
.chapter("1")
|
||||
.chapter("2")
|
||||
.chapter("3")
|
||||
@ -55,12 +55,11 @@ public class SagaOrchestratorInternallyTest {
|
||||
}
|
||||
|
||||
private ServiceDiscoveryService serviceDiscovery() {
|
||||
return
|
||||
new ServiceDiscoveryService()
|
||||
.discover(new Service1())
|
||||
.discover(new Service2())
|
||||
.discover(new Service3())
|
||||
.discover(new Service4());
|
||||
return new ServiceDiscoveryService()
|
||||
.discover(new Service1())
|
||||
.discover(new Service2())
|
||||
.discover(new Service3())
|
||||
.discover(new Service4());
|
||||
}
|
||||
|
||||
class Service1 extends Service<Integer> {
|
||||
|
@ -38,7 +38,7 @@ public class App {
|
||||
* main method.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
FruitShop shop = new FruitShop();
|
||||
var shop = new FruitShop();
|
||||
new Customer("Peter", shop).start();
|
||||
new Customer("Paul", shop).start();
|
||||
new Customer("Mary", shop).start();
|
||||
|
@ -64,13 +64,14 @@ public class Customer extends Thread {
|
||||
public void run() {
|
||||
|
||||
while (fruitShop.countFruit() > 0) {
|
||||
FruitBowl bowl = fruitShop.takeBowl();
|
||||
Fruit fruit;
|
||||
|
||||
if (bowl != null && (fruit = bowl.take()) != null) {
|
||||
LOGGER.info("{} took an {}", name, fruit);
|
||||
fruitBowl.put(fruit);
|
||||
fruitShop.returnBowl(bowl);
|
||||
var bowl = fruitShop.takeBowl();
|
||||
if (bowl != null) {
|
||||
var fruit = bowl.take();
|
||||
if (fruit != null) {
|
||||
LOGGER.info("{} took an {}", name, fruit);
|
||||
fruitBowl.put(fruit);
|
||||
fruitShop.returnBowl(bowl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,11 +68,11 @@ public class FruitBowl {
|
||||
* toString method.
|
||||
*/
|
||||
public String toString() {
|
||||
int apples = 0;
|
||||
int oranges = 0;
|
||||
int lemons = 0;
|
||||
var apples = 0;
|
||||
var oranges = 0;
|
||||
var lemons = 0;
|
||||
|
||||
for (Fruit f : fruit) {
|
||||
for (var f : fruit) {
|
||||
switch (f.getType()) {
|
||||
case APPLE:
|
||||
apples++;
|
||||
|
@ -55,7 +55,7 @@ public class FruitShop {
|
||||
* FruitShop constructor.
|
||||
*/
|
||||
public FruitShop() {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
for (var i = 0; i < 100; i++) {
|
||||
bowls[0].put(new Fruit(Fruit.FruitType.APPLE));
|
||||
bowls[1].put(new Fruit(Fruit.FruitType.ORANGE));
|
||||
bowls[2].put(new Fruit(Fruit.FruitType.LEMON));
|
||||
|
@ -25,15 +25,12 @@ package com.iluwatar.semaphore;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Application Test Entrypoint
|
||||
*/
|
||||
public class AppTest {
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,12 @@
|
||||
|
||||
package com.iluwatar.semaphore;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test taking from and putting Fruit into a FruitBowl
|
||||
*/
|
||||
@ -36,16 +36,16 @@ public class FruitBowlTest {
|
||||
|
||||
@Test
|
||||
public void fruitBowlTest() {
|
||||
FruitBowl fbowl = new FruitBowl();
|
||||
|
||||
var fbowl = new FruitBowl();
|
||||
|
||||
assertEquals(0, fbowl.countFruit());
|
||||
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
|
||||
for (var i = 1; i <= 10; i++) {
|
||||
fbowl.put(new Fruit(Fruit.FruitType.LEMON));
|
||||
assertEquals(i, fbowl.countFruit());
|
||||
}
|
||||
|
||||
for (int i = 9; i >= 0; i--) {
|
||||
for (var i = 9; i >= 0; i--) {
|
||||
assertNotNull(fbowl.take());
|
||||
assertEquals(i, fbowl.countFruit());
|
||||
}
|
||||
|
@ -23,11 +23,11 @@
|
||||
|
||||
package com.iluwatar.semaphore;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test case for acquiring and releasing a Semaphore
|
||||
*/
|
||||
@ -35,11 +35,11 @@ public class SemaphoreTest {
|
||||
|
||||
@Test
|
||||
public void acquireReleaseTest() {
|
||||
Semaphore sphore = new Semaphore(3);
|
||||
var sphore = new Semaphore(3);
|
||||
|
||||
assertEquals(3, sphore.getAvailableLicenses());
|
||||
|
||||
for (int i = 2; i >= 0; i--) {
|
||||
for (var i = 2; i >= 0; i--) {
|
||||
try {
|
||||
sphore.acquire();
|
||||
assertEquals(i, sphore.getAvailableLicenses());
|
||||
@ -47,8 +47,8 @@ public class SemaphoreTest {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
|
||||
for (var i = 1; i <= 3; i++) {
|
||||
sphore.release();
|
||||
assertEquals(i, sphore.getAvailableLicenses());
|
||||
}
|
||||
|
@ -54,10 +54,10 @@ public class App {
|
||||
* Can add a List with enum Actions for variable scenarios.
|
||||
*/
|
||||
public static void scenario(Servant servant, int compliment) {
|
||||
King k = new King();
|
||||
Queen q = new Queen();
|
||||
var k = new King();
|
||||
var q = new Queen();
|
||||
|
||||
List<Royalty> guests = List.of(k, q);
|
||||
var guests = List.of(k, q);
|
||||
|
||||
// feed
|
||||
servant.feed(k);
|
||||
@ -69,9 +69,7 @@ public class App {
|
||||
servant.giveCompliments(guests.get(compliment));
|
||||
|
||||
// outcome of the night
|
||||
for (Royalty r : guests) {
|
||||
r.changeMood();
|
||||
}
|
||||
guests.forEach(Royalty::changeMood);
|
||||
|
||||
// check your luck
|
||||
if (servant.checkIfYouWillBeHanged(guests)) {
|
||||
|
@ -55,13 +55,6 @@ public class Servant {
|
||||
* Check if we will be hanged.
|
||||
*/
|
||||
public boolean checkIfYouWillBeHanged(List<Royalty> tableGuests) {
|
||||
boolean anotherDay = true;
|
||||
for (Royalty r : tableGuests) {
|
||||
if (!r.getMood()) {
|
||||
anotherDay = false;
|
||||
}
|
||||
}
|
||||
|
||||
return anotherDay;
|
||||
return tableGuests.stream().allMatch(Royalty::getMood);
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,12 @@ package com.iluwatar.servant;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Application test
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -23,11 +23,11 @@
|
||||
|
||||
package com.iluwatar.servant;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 9:40 PM
|
||||
*
|
||||
@ -37,14 +37,14 @@ public class KingTest {
|
||||
|
||||
@Test
|
||||
public void testHungrySoberUncomplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.changeMood();
|
||||
assertFalse(king.getMood());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFedSoberUncomplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.getFed();
|
||||
king.changeMood();
|
||||
assertFalse(king.getMood());
|
||||
@ -52,7 +52,7 @@ public class KingTest {
|
||||
|
||||
@Test
|
||||
public void testHungryDrunkUncomplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.getDrink();
|
||||
king.changeMood();
|
||||
assertFalse(king.getMood());
|
||||
@ -60,7 +60,7 @@ public class KingTest {
|
||||
|
||||
@Test
|
||||
public void testHungrySoberComplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.receiveCompliments();
|
||||
king.changeMood();
|
||||
assertFalse(king.getMood());
|
||||
@ -68,7 +68,7 @@ public class KingTest {
|
||||
|
||||
@Test
|
||||
public void testFedDrunkUncomplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.getFed();
|
||||
king.getDrink();
|
||||
king.changeMood();
|
||||
@ -77,7 +77,7 @@ public class KingTest {
|
||||
|
||||
@Test
|
||||
public void testFedSoberComplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.getFed();
|
||||
king.receiveCompliments();
|
||||
king.changeMood();
|
||||
@ -86,7 +86,7 @@ public class KingTest {
|
||||
|
||||
@Test
|
||||
public void testFedDrunkComplimentedKing() {
|
||||
final King king = new King();
|
||||
final var king = new King();
|
||||
king.getFed();
|
||||
king.getDrink();
|
||||
king.receiveCompliments();
|
||||
|
@ -24,11 +24,11 @@
|
||||
package com.iluwatar.servant;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 9:52 PM
|
||||
*
|
||||
@ -38,34 +38,34 @@ public class QueenTest {
|
||||
|
||||
@Test
|
||||
public void testNotFlirtyUncomplemented() {
|
||||
final Queen queen = new Queen();
|
||||
final var queen = new Queen();
|
||||
queen.setFlirtiness(false);
|
||||
queen.changeMood();
|
||||
assertFalse(queen.getMood());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNotFlirtyComplemented() {
|
||||
final Queen queen = new Queen();
|
||||
final var queen = new Queen();
|
||||
queen.setFlirtiness(false);
|
||||
queen.receiveCompliments();
|
||||
queen.changeMood();
|
||||
assertFalse(queen.getMood());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFlirtyUncomplemented() {
|
||||
final Queen queen = new Queen();
|
||||
final var queen = new Queen();
|
||||
queen.changeMood();
|
||||
assertFalse(queen.getMood());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFlirtyComplemented() {
|
||||
final Queen queen = new Queen();
|
||||
final var queen = new Queen();
|
||||
queen.receiveCompliments();
|
||||
queen.changeMood();
|
||||
assertTrue(queen.getMood());
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -23,16 +23,15 @@
|
||||
|
||||
package com.iluwatar.servant;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 10:02 PM
|
||||
*
|
||||
@ -42,8 +41,8 @@ public class ServantTest {
|
||||
|
||||
@Test
|
||||
public void testFeed() {
|
||||
final Royalty royalty = mock(Royalty.class);
|
||||
final Servant servant = new Servant("test");
|
||||
final var royalty = mock(Royalty.class);
|
||||
final var servant = new Servant("test");
|
||||
servant.feed(royalty);
|
||||
verify(royalty).getFed();
|
||||
verifyNoMoreInteractions(royalty);
|
||||
@ -51,8 +50,8 @@ public class ServantTest {
|
||||
|
||||
@Test
|
||||
public void testGiveWine() {
|
||||
final Royalty royalty = mock(Royalty.class);
|
||||
final Servant servant = new Servant("test");
|
||||
final var royalty = mock(Royalty.class);
|
||||
final var servant = new Servant("test");
|
||||
servant.giveWine(royalty);
|
||||
verify(royalty).getDrink();
|
||||
verifyNoMoreInteractions(royalty);
|
||||
@ -60,8 +59,8 @@ public class ServantTest {
|
||||
|
||||
@Test
|
||||
public void testGiveCompliments() {
|
||||
final Royalty royalty = mock(Royalty.class);
|
||||
final Servant servant = new Servant("test");
|
||||
final var royalty = mock(Royalty.class);
|
||||
final var servant = new Servant("test");
|
||||
servant.giveCompliments(royalty);
|
||||
verify(royalty).receiveCompliments();
|
||||
verifyNoMoreInteractions(royalty);
|
||||
@ -69,15 +68,15 @@ public class ServantTest {
|
||||
|
||||
@Test
|
||||
public void testCheckIfYouWillBeHanged() {
|
||||
final Royalty goodMoodRoyalty = mock(Royalty.class);
|
||||
final var goodMoodRoyalty = mock(Royalty.class);
|
||||
when(goodMoodRoyalty.getMood()).thenReturn(true);
|
||||
|
||||
final Royalty badMoodRoyalty = mock(Royalty.class);
|
||||
final var badMoodRoyalty = mock(Royalty.class);
|
||||
when(badMoodRoyalty.getMood()).thenReturn(true);
|
||||
|
||||
final List<Royalty> goodCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, goodMoodRoyalty);
|
||||
final var goodCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, goodMoodRoyalty);
|
||||
|
||||
final List<Royalty> badCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, badMoodRoyalty);
|
||||
final var badCompany = List.of(goodMoodRoyalty, goodMoodRoyalty, badMoodRoyalty);
|
||||
|
||||
assertTrue(new Servant("test").checkIfYouWillBeHanged(goodCompany));
|
||||
assertTrue(new Servant("test").checkIfYouWillBeHanged(badCompany));
|
||||
|
@ -24,14 +24,12 @@
|
||||
package com.iluwatar.serverless.baas.api;
|
||||
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
|
||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
|
||||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -50,7 +48,7 @@ public abstract class AbstractDynamoDbHandler<T extends Serializable> {
|
||||
}
|
||||
|
||||
private void initAmazonDynamoDb() {
|
||||
AmazonDynamoDB amazonDynamoDb = AmazonDynamoDBClientBuilder
|
||||
var amazonDynamoDb = AmazonDynamoDBClientBuilder
|
||||
.standard()
|
||||
.withRegion(Regions.US_EAST_1)
|
||||
.build();
|
||||
@ -71,10 +69,7 @@ public abstract class AbstractDynamoDbHandler<T extends Serializable> {
|
||||
}
|
||||
|
||||
protected Map<String, String> headers() {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Content-Type", "application/json");
|
||||
|
||||
return headers;
|
||||
return Map.of("Content-Type", "application/json");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,14 +80,11 @@ public abstract class AbstractDynamoDbHandler<T extends Serializable> {
|
||||
* @return - api gateway proxy response
|
||||
*/
|
||||
protected APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent(Integer statusCode, T body) {
|
||||
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent =
|
||||
new APIGatewayProxyResponseEvent().withHeaders(headers());
|
||||
var apiGatewayProxyResponseEvent = new APIGatewayProxyResponseEvent().withHeaders(headers());
|
||||
try {
|
||||
apiGatewayProxyResponseEvent
|
||||
.withStatusCode(statusCode)
|
||||
.withBody(getObjectMapper()
|
||||
.writeValueAsString(body));
|
||||
|
||||
.withBody(getObjectMapper().writeValueAsString(body));
|
||||
} catch (JsonProcessingException jsonProcessingException) {
|
||||
throw new RuntimeException(jsonProcessingException);
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
|
||||
import com.iluwatar.serverless.baas.model.Person;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -42,15 +41,15 @@ public class FindPersonApiHandler extends AbstractDynamoDbHandler<Person>
|
||||
private static final Integer SUCCESS_STATUS_CODE = 200;
|
||||
|
||||
@Override
|
||||
public APIGatewayProxyResponseEvent handleRequest(
|
||||
APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
|
||||
Map<String, String> pathParameters = apiGatewayProxyRequestEvent.getPathParameters();
|
||||
pathParameters.keySet().stream().map(key -> key + "=" + pathParameters.get(key))
|
||||
.forEach(LOG::info);
|
||||
|
||||
Person person = this.getDynamoDbMapper().load(Person.class, apiGatewayProxyRequestEvent
|
||||
.getPathParameters().get("id"));
|
||||
|
||||
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent req, Context ctx) {
|
||||
req.getPathParameters().forEach(FindPersonApiHandler::logKeyValue);
|
||||
var id = req.getPathParameters().get("id");
|
||||
var person = this.getDynamoDbMapper().load(Person.class, id);
|
||||
return apiGatewayProxyResponseEvent(SUCCESS_STATUS_CODE, person);
|
||||
}
|
||||
|
||||
private static void logKeyValue(String key, String value) {
|
||||
LOG.info(key + "=" + value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -43,19 +43,15 @@ public class SavePersonApiHandler extends AbstractDynamoDbHandler<Person>
|
||||
private static final Integer BAD_REQUEST_STATUS_CODE = 400;
|
||||
|
||||
@Override
|
||||
public APIGatewayProxyResponseEvent handleRequest(
|
||||
APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent, Context context) {
|
||||
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent;
|
||||
Person person;
|
||||
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent req, Context ctx) {
|
||||
try {
|
||||
person = getObjectMapper().readValue(apiGatewayProxyRequestEvent.getBody(), Person.class);
|
||||
var objectMapper = getObjectMapper();
|
||||
var person = objectMapper.readValue(req.getBody(), Person.class);
|
||||
getDynamoDbMapper().save(person);
|
||||
apiGatewayProxyResponseEvent = apiGatewayProxyResponseEvent(CREATED_STATUS_CODE, person);
|
||||
return apiGatewayProxyResponseEvent(CREATED_STATUS_CODE, person);
|
||||
} catch (IOException ioException) {
|
||||
LOG.error("unable to parse body", ioException);
|
||||
apiGatewayProxyResponseEvent = apiGatewayProxyResponseEvent(BAD_REQUEST_STATUS_CODE, null);
|
||||
return apiGatewayProxyResponseEvent(BAD_REQUEST_STATUS_CODE, null);
|
||||
}
|
||||
|
||||
return apiGatewayProxyResponseEvent;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ package com.iluwatar.serverless.baas.model;
|
||||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
|
||||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBDocument;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Address class Created by dheeraj.mummarareddy on 3/4/18.
|
||||
@ -96,30 +97,30 @@ public class Address implements Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
Address address = (Address) o;
|
||||
var address = (Address) o;
|
||||
|
||||
if (addressLineOne != null ? !addressLineOne.equals(address.addressLineOne) :
|
||||
address.addressLineOne != null) {
|
||||
if (!Objects.equals(addressLineOne, address.addressLineOne)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (addressLineTwo != null ? !addressLineTwo.equals(address.addressLineTwo) :
|
||||
address.addressLineTwo != null) {
|
||||
if (!Objects.equals(addressLineTwo, address.addressLineTwo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (city != null ? !city.equals(address.city) : address.city != null) {
|
||||
if (!Objects.equals(city, address.city)) {
|
||||
return false;
|
||||
}
|
||||
if (state != null ? !state.equals(address.state) : address.state != null) {
|
||||
|
||||
if (!Objects.equals(state, address.state)) {
|
||||
return false;
|
||||
}
|
||||
return zipCode != null ? zipCode.equals(address.zipCode) : address.zipCode == null;
|
||||
|
||||
return Objects.equals(zipCode, address.zipCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = addressLineOne != null ? addressLineOne.hashCode() : 0;
|
||||
var result = addressLineOne != null ? addressLineOne.hashCode() : 0;
|
||||
result = 31 * result + (addressLineTwo != null ? addressLineTwo.hashCode() : 0);
|
||||
result = 31 * result + (city != null ? city.hashCode() : 0);
|
||||
result = 31 * result + (state != null ? state.hashCode() : 0);
|
||||
|
@ -29,6 +29,7 @@ import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
|
||||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Person class Created by dheeraj.mummarareddy on 3/4/18.
|
||||
@ -92,15 +93,15 @@ public class Person implements Serializable {
|
||||
|
||||
Person person = (Person) o;
|
||||
|
||||
if (firstName != null ? !firstName.equals(person.firstName) : person.firstName != null) {
|
||||
if (!Objects.equals(firstName, person.firstName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) {
|
||||
if (!Objects.equals(lastName, person.lastName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return address != null ? address.equals(person.address) : person.address == null;
|
||||
return Objects.equals(address, person.address);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,10 +30,8 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Api gateway response.
|
||||
*
|
||||
* @param <T> serializable object
|
||||
*/
|
||||
public class ApiGatewayResponse<T extends Serializable> implements Serializable {
|
||||
public class ApiGatewayResponse implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1181159426782844892L;
|
||||
|
||||
@ -50,8 +48,12 @@ public class ApiGatewayResponse<T extends Serializable> implements Serializable
|
||||
* @param headers - response headers
|
||||
* @param isBase64Encoded - base64Encoded flag
|
||||
*/
|
||||
public ApiGatewayResponse(Integer statusCode, String body, Map<String, String> headers,
|
||||
Boolean isBase64Encoded) {
|
||||
public ApiGatewayResponse(
|
||||
Integer statusCode,
|
||||
String body,
|
||||
Map<String, String> headers,
|
||||
Boolean isBase64Encoded
|
||||
) {
|
||||
this.statusCode = statusCode;
|
||||
this.body = body;
|
||||
this.headers = headers;
|
||||
|
@ -24,6 +24,7 @@
|
||||
package com.iluwatar.serverless.faas;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Lambda context information.
|
||||
@ -110,28 +111,22 @@ public class LambdaInfo implements Serializable {
|
||||
|
||||
LambdaInfo that = (LambdaInfo) o;
|
||||
|
||||
if (awsRequestId != null ? !awsRequestId
|
||||
.equals(that.awsRequestId) : that.awsRequestId != null) {
|
||||
if (!Objects.equals(awsRequestId, that.awsRequestId)) {
|
||||
return false;
|
||||
}
|
||||
if (logGroupName != null ? !logGroupName
|
||||
.equals(that.logGroupName) : that.logGroupName != null) {
|
||||
if (!Objects.equals(logGroupName, that.logGroupName)) {
|
||||
return false;
|
||||
}
|
||||
if (logStreamName != null ? !logStreamName
|
||||
.equals(that.logStreamName) : that.logStreamName != null) {
|
||||
if (!Objects.equals(logStreamName, that.logStreamName)) {
|
||||
return false;
|
||||
}
|
||||
if (functionName != null ? !functionName
|
||||
.equals(that.functionName) : that.functionName != null) {
|
||||
if (!Objects.equals(functionName, that.functionName)) {
|
||||
return false;
|
||||
}
|
||||
if (functionVersion != null ? !functionVersion
|
||||
.equals(that.functionVersion) : that.functionVersion != null) {
|
||||
if (!Objects.equals(functionVersion, that.functionVersion)) {
|
||||
return false;
|
||||
}
|
||||
return memoryLimitInMb != null ? memoryLimitInMb
|
||||
.equals(that.memoryLimitInMb) : that.memoryLimitInMb == null;
|
||||
return Objects.equals(memoryLimitInMb, that.memoryLimitInMb);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,7 +27,6 @@ import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.RequestHandler;
|
||||
import com.iluwatar.serverless.faas.ApiGatewayResponse;
|
||||
import com.iluwatar.serverless.faas.LambdaInfo;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -46,13 +45,11 @@ public class LambdaInfoApiHandler
|
||||
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
|
||||
LOG.info("received: " + input);
|
||||
|
||||
return new ApiGatewayResponse
|
||||
.ApiGatewayResponseBuilder<LambdaInfo>()
|
||||
return new ApiGatewayResponse.ApiGatewayResponseBuilder<LambdaInfo>()
|
||||
.headers(headers())
|
||||
.statusCode(SUCCESS_STATUS_CODE)
|
||||
.body(lambdaInfo(context))
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,14 +66,10 @@ public class LambdaInfoApiHandler
|
||||
lambdaInfo.setLogGroupName(context.getLogGroupName());
|
||||
lambdaInfo.setLogStreamName(context.getLogStreamName());
|
||||
lambdaInfo.setMemoryLimitInMb(context.getMemoryLimitInMB());
|
||||
|
||||
return lambdaInfo;
|
||||
}
|
||||
|
||||
private Map<String, String> headers() {
|
||||
var headers = new HashMap<String, String>();
|
||||
headers.put("Content-Type", "application/json");
|
||||
|
||||
return headers;
|
||||
return Map.of("Content-Type", "application/json");
|
||||
}
|
||||
}
|
||||
|
@ -23,27 +23,23 @@
|
||||
|
||||
package com.iluwatar.serverless.baas.api;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||
import com.iluwatar.serverless.baas.api.FindPersonApiHandler;
|
||||
import com.iluwatar.serverless.baas.api.SavePersonApiHandler;
|
||||
import com.iluwatar.serverless.baas.model.Person;
|
||||
import java.util.Map;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for FindPersonApiHandler
|
||||
* Created by dheeraj.mummar on 3/5/18.
|
||||
* Unit tests for FindPersonApiHandler Created by dheeraj.mummar on 3/5/18.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FindPersonApiHandlerTest {
|
||||
@ -66,8 +62,7 @@ public class FindPersonApiHandlerTest {
|
||||
}
|
||||
|
||||
private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent() {
|
||||
return new APIGatewayProxyRequestEvent()
|
||||
.withPathParamters(Collections
|
||||
.singletonMap("id", "37e7a1fe-3544-473d-b764-18128f02d72d"));
|
||||
var request = new APIGatewayProxyRequestEvent();
|
||||
return request.withPathParamters(Map.of("id", "37e7a1fe-3544-473d-b764-18128f02d72d"));
|
||||
}
|
||||
}
|
||||
|
@ -23,13 +23,15 @@
|
||||
|
||||
package com.iluwatar.serverless.baas.api;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
|
||||
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.iluwatar.serverless.baas.api.SavePersonApiHandler;
|
||||
import com.iluwatar.serverless.baas.model.Address;
|
||||
import com.iluwatar.serverless.baas.model.Person;
|
||||
import org.junit.Assert;
|
||||
@ -39,11 +41,8 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* Unit tests for SavePersonApiHandler
|
||||
* Created by dheeraj.mummar on 3/4/18.
|
||||
* Unit tests for SavePersonApiHandler Created by dheeraj.mummar on 3/4/18.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SavePersonApiHandlerTest {
|
||||
@ -63,40 +62,40 @@ public class SavePersonApiHandlerTest {
|
||||
|
||||
@Test
|
||||
public void handleRequestSavePersonSuccessful() throws JsonProcessingException {
|
||||
Person person = newPerson();
|
||||
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent =
|
||||
this.savePersonApiHandler
|
||||
.handleRequest(apiGatewayProxyRequestEvent(objectMapper.writeValueAsString(person)), mock(Context.class));
|
||||
var person = newPerson();
|
||||
var body = objectMapper.writeValueAsString(person);
|
||||
var request = apiGatewayProxyRequestEvent(body);
|
||||
var ctx = mock(Context.class);
|
||||
var apiGatewayProxyResponseEvent = this.savePersonApiHandler.handleRequest(request, ctx);
|
||||
verify(dynamoDbMapper, times(1)).save(person);
|
||||
Assert.assertNotNull(apiGatewayProxyResponseEvent);
|
||||
Assert.assertEquals(new Integer(201), apiGatewayProxyResponseEvent.getStatusCode());
|
||||
Assert.assertEquals(Integer.valueOf(201), apiGatewayProxyResponseEvent.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleRequestSavePersonException() {
|
||||
APIGatewayProxyResponseEvent apiGatewayProxyResponseEvent =
|
||||
this.savePersonApiHandler
|
||||
.handleRequest(apiGatewayProxyRequestEvent("invalid sample request"), mock(Context.class));
|
||||
var request = apiGatewayProxyRequestEvent("invalid sample request");
|
||||
var ctx = mock(Context.class);
|
||||
var apiGatewayProxyResponseEvent = this.savePersonApiHandler.handleRequest(request, ctx);
|
||||
Assert.assertNotNull(apiGatewayProxyResponseEvent);
|
||||
Assert.assertEquals(new Integer(400), apiGatewayProxyResponseEvent.getStatusCode());
|
||||
Assert.assertEquals(Integer.valueOf(400), apiGatewayProxyResponseEvent.getStatusCode());
|
||||
}
|
||||
|
||||
private APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent(String body) {
|
||||
APIGatewayProxyRequestEvent apiGatewayProxyRequestEvent = new APIGatewayProxyRequestEvent();
|
||||
var apiGatewayProxyRequestEvent = new APIGatewayProxyRequestEvent();
|
||||
return apiGatewayProxyRequestEvent.withBody(body);
|
||||
}
|
||||
|
||||
private Person newPerson() {
|
||||
Person person = new Person();
|
||||
var person = new Person();
|
||||
person.setFirstName("Thor");
|
||||
person.setLastName("Odinson");
|
||||
Address address = new Address();
|
||||
var address = new Address();
|
||||
address.setAddressLineOne("1 Odin ln");
|
||||
address.setCity("Asgard");
|
||||
address.setState("country of the Gods");
|
||||
address.setZipCode("00001");
|
||||
person.setAddress(address);
|
||||
|
||||
return person;
|
||||
}
|
||||
}
|
||||
|
@ -23,16 +23,16 @@
|
||||
|
||||
package com.iluwatar.serverless.faas.api;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.IsNull.notNullValue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.amazonaws.services.lambda.runtime.Context;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for LambdaInfoApiHandler
|
||||
*/
|
||||
@ -41,8 +41,8 @@ public class LambdaInfoApiHandlerTest {
|
||||
|
||||
@Test
|
||||
public void handleRequestWithMockContext() {
|
||||
LambdaInfoApiHandler lambdaInfoApiHandler = new LambdaInfoApiHandler();
|
||||
Context context = mock(Context.class);
|
||||
var lambdaInfoApiHandler = new LambdaInfoApiHandler();
|
||||
var context = mock(Context.class);
|
||||
when(context.getAwsRequestId()).thenReturn("mock aws request id");
|
||||
|
||||
assertThat(lambdaInfoApiHandler.handleRequest(null, context), notNullValue());
|
||||
|
@ -31,7 +31,6 @@ import com.iluwatar.servicelayer.spellbook.Spellbook;
|
||||
import com.iluwatar.servicelayer.spellbook.SpellbookDaoImpl;
|
||||
import com.iluwatar.servicelayer.wizard.Wizard;
|
||||
import com.iluwatar.servicelayer.wizard.WizardDaoImpl;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -178,29 +177,21 @@ public class App {
|
||||
* Query the data.
|
||||
*/
|
||||
public static void queryData() {
|
||||
var service =
|
||||
new MagicServiceImpl(new WizardDaoImpl(), new SpellbookDaoImpl(), new SpellDaoImpl());
|
||||
var wizardDao = new WizardDaoImpl();
|
||||
var spellbookDao = new SpellbookDaoImpl();
|
||||
var spellDao = new SpellDaoImpl();
|
||||
var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
LOGGER.info("Enumerating all wizards");
|
||||
for (Wizard w : service.findAllWizards()) {
|
||||
LOGGER.info(w.getName());
|
||||
}
|
||||
service.findAllWizards().stream().map(Wizard::getName).forEach(LOGGER::info);
|
||||
LOGGER.info("Enumerating all spellbooks");
|
||||
for (Spellbook s : service.findAllSpellbooks()) {
|
||||
LOGGER.info(s.getName());
|
||||
}
|
||||
service.findAllSpellbooks().stream().map(Spellbook::getName).forEach(LOGGER::info);
|
||||
LOGGER.info("Enumerating all spells");
|
||||
for (Spell s : service.findAllSpells()) {
|
||||
LOGGER.info(s.getName());
|
||||
}
|
||||
service.findAllSpells().stream().map(Spell::getName).forEach(LOGGER::info);
|
||||
LOGGER.info("Find wizards with spellbook 'Book of Idores'");
|
||||
List<Wizard> wizardsWithSpellbook = service.findWizardsWithSpellbook("Book of Idores");
|
||||
for (Wizard w : wizardsWithSpellbook) {
|
||||
LOGGER.info("{} has 'Book of Idores'", w.getName());
|
||||
}
|
||||
var wizardsWithSpellbook = service.findWizardsWithSpellbook("Book of Idores");
|
||||
wizardsWithSpellbook.forEach(w -> LOGGER.info("{} has 'Book of Idores'", w.getName()));
|
||||
LOGGER.info("Find wizards with spell 'Fireball'");
|
||||
List<Wizard> wizardsWithSpell = service.findWizardsWithSpell("Fireball");
|
||||
for (Wizard w : wizardsWithSpell) {
|
||||
LOGGER.info("{} has 'Fireball'", w.getName());
|
||||
}
|
||||
var wizardsWithSpell = service.findWizardsWithSpell("Fireball");
|
||||
wizardsWithSpell.forEach(w -> LOGGER.info("{} has 'Fireball'", w.getName()));
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +52,9 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
|
||||
|
||||
@Override
|
||||
public E find(Long id) {
|
||||
var session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
E result = null;
|
||||
try {
|
||||
E result;
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
var criteria = session.createCriteria(persistentClass);
|
||||
criteria.add(Restrictions.idEq(id));
|
||||
@ -66,17 +65,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persist(E entity) {
|
||||
var session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
try {
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
session.persist(entity);
|
||||
tx.commit();
|
||||
@ -85,17 +81,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E merge(E entity) {
|
||||
var session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
E result = null;
|
||||
try {
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
result = (E) session.merge(entity);
|
||||
tx.commit();
|
||||
@ -104,17 +97,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(E entity) {
|
||||
var session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
try {
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
session.delete(entity);
|
||||
tx.commit();
|
||||
@ -123,17 +113,14 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> findAll() {
|
||||
var session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
List<E> result = null;
|
||||
try {
|
||||
List<E> result;
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
Criteria criteria = session.createCriteria(persistentClass);
|
||||
result = criteria.list();
|
||||
@ -142,8 +129,6 @@ public abstract class DaoBaseImpl<E extends BaseEntity> implements Dao<E> {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -54,14 +54,15 @@ public final class HibernateUtil {
|
||||
public static synchronized SessionFactory getSessionFactory() {
|
||||
if (sessionFactory == null) {
|
||||
try {
|
||||
sessionFactory =
|
||||
new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class)
|
||||
.addAnnotatedClass(Spell.class)
|
||||
.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
|
||||
.setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
|
||||
.setProperty("hibernate.current_session_context_class", "thread")
|
||||
.setProperty("hibernate.show_sql", "false")
|
||||
.setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory();
|
||||
sessionFactory = new Configuration()
|
||||
.addAnnotatedClass(Wizard.class)
|
||||
.addAnnotatedClass(Spellbook.class)
|
||||
.addAnnotatedClass(Spell.class)
|
||||
.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
|
||||
.setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1")
|
||||
.setProperty("hibernate.current_session_context_class", "thread")
|
||||
.setProperty("hibernate.show_sql", "false")
|
||||
.setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory();
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Initial SessionFactory creation failed.", ex);
|
||||
throw new ExceptionInInitializerError(ex);
|
||||
|
@ -35,7 +35,7 @@ public class SpellDaoImpl extends DaoBaseImpl<Spell> implements SpellDao {
|
||||
@Override
|
||||
public Spell findByName(String name) {
|
||||
Transaction tx = null;
|
||||
Spell result = null;
|
||||
Spell result;
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
var criteria = session.createCriteria(persistentClass);
|
||||
|
@ -34,24 +34,19 @@ public class SpellbookDaoImpl extends DaoBaseImpl<Spellbook> implements Spellboo
|
||||
|
||||
@Override
|
||||
public Spellbook findByName(String name) {
|
||||
var session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
Spellbook result = null;
|
||||
try {
|
||||
Spellbook result;
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
var criteria = session.createCriteria(persistentClass);
|
||||
criteria.add(Restrictions.eq("name", name));
|
||||
result = (Spellbook) criteria.uniqueResult();
|
||||
result.getSpells().size();
|
||||
result.getWizards().size();
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
if (tx != null) {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -24,9 +24,6 @@
|
||||
package com.iluwatar.servicelayer.wizard;
|
||||
|
||||
import com.iluwatar.servicelayer.common.DaoBaseImpl;
|
||||
import com.iluwatar.servicelayer.spellbook.Spellbook;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
|
||||
@ -37,25 +34,19 @@ public class WizardDaoImpl extends DaoBaseImpl<Wizard> implements WizardDao {
|
||||
|
||||
@Override
|
||||
public Wizard findByName(String name) {
|
||||
Session session = getSessionFactory().openSession();
|
||||
Transaction tx = null;
|
||||
Wizard result = null;
|
||||
try {
|
||||
Wizard result;
|
||||
try (var session = getSessionFactory().openSession()) {
|
||||
tx = session.beginTransaction();
|
||||
Criteria criteria = session.createCriteria(persistentClass);
|
||||
var criteria = session.createCriteria(persistentClass);
|
||||
criteria.add(Restrictions.eq("name", name));
|
||||
result = (Wizard) criteria.uniqueResult();
|
||||
for (Spellbook s : result.getSpellbooks()) {
|
||||
s.getSpells().size();
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
if (tx != null) {
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
session.close();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -28,16 +28,13 @@ import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Application test
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
|
@ -23,22 +23,20 @@
|
||||
|
||||
package com.iluwatar.servicelayer.common;
|
||||
|
||||
import com.iluwatar.servicelayer.hibernate.HibernateUtil;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import com.iluwatar.servicelayer.hibernate.HibernateUtil;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 10:53 PM
|
||||
* Test for Base Data Access Objects
|
||||
* Date: 12/28/15 - 10:53 PM Test for Base Data Access Objects
|
||||
*
|
||||
* @param <E> Type of Base Entity
|
||||
* @param <D> Type of Dao Base Implementation
|
||||
* @author Jeroen Meulemeester
|
||||
@ -79,8 +77,8 @@ public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
for (int i = 0; i < INITIAL_COUNT; i++) {
|
||||
final String className = dao.persistentClass.getSimpleName();
|
||||
final String entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet());
|
||||
final var className = dao.persistentClass.getSimpleName();
|
||||
final var entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet());
|
||||
this.dao.persist(this.factory.apply(entityName));
|
||||
}
|
||||
}
|
||||
@ -96,9 +94,9 @@ public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>
|
||||
|
||||
@Test
|
||||
public void testFind() {
|
||||
final List<E> all = this.dao.findAll();
|
||||
for (final E entity : all) {
|
||||
final E byId = this.dao.find(entity.getId());
|
||||
final var all = this.dao.findAll();
|
||||
for (final var entity : all) {
|
||||
final var byId = this.dao.find(entity.getId());
|
||||
assertNotNull(byId);
|
||||
assertEquals(byId.getId(), byId.getId());
|
||||
}
|
||||
@ -106,39 +104,39 @@ public abstract class BaseDaoTest<E extends BaseEntity, D extends DaoBaseImpl<E>
|
||||
|
||||
@Test
|
||||
public void testDelete() {
|
||||
final List<E> originalEntities = this.dao.findAll();
|
||||
final var originalEntities = this.dao.findAll();
|
||||
this.dao.delete(originalEntities.get(1));
|
||||
this.dao.delete(originalEntities.get(2));
|
||||
|
||||
final List<E> entitiesLeft = this.dao.findAll();
|
||||
final var entitiesLeft = this.dao.findAll();
|
||||
assertNotNull(entitiesLeft);
|
||||
assertEquals(INITIAL_COUNT - 2, entitiesLeft.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAll() {
|
||||
final List<E> all = this.dao.findAll();
|
||||
final var all = this.dao.findAll();
|
||||
assertNotNull(all);
|
||||
assertEquals(INITIAL_COUNT, all.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetId() {
|
||||
final E entity = this.factory.apply("name");
|
||||
final var entity = this.factory.apply("name");
|
||||
assertNull(entity.getId());
|
||||
|
||||
final Long expectedId = 1L;
|
||||
final var expectedId = 1L;
|
||||
entity.setId(expectedId);
|
||||
assertEquals(expectedId, entity.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetName() {
|
||||
final E entity = this.factory.apply("name");
|
||||
final var entity = this.factory.apply("name");
|
||||
assertEquals("name", entity.getName());
|
||||
assertEquals("name", entity.toString());
|
||||
|
||||
final String expectedName = "new name";
|
||||
final var expectedName = "new name";
|
||||
entity.setName(expectedName);
|
||||
assertEquals(expectedName, entity.getName());
|
||||
assertEquals(expectedName, entity.toString());
|
||||
|
@ -23,18 +23,6 @@
|
||||
|
||||
package com.iluwatar.servicelayer.magic;
|
||||
|
||||
import com.iluwatar.servicelayer.spell.Spell;
|
||||
import com.iluwatar.servicelayer.spell.SpellDao;
|
||||
import com.iluwatar.servicelayer.spellbook.Spellbook;
|
||||
import com.iluwatar.servicelayer.spellbook.SpellbookDao;
|
||||
import com.iluwatar.servicelayer.wizard.Wizard;
|
||||
import com.iluwatar.servicelayer.wizard.WizardDao;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.Matchers.eq;
|
||||
@ -44,6 +32,15 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.iluwatar.servicelayer.spell.Spell;
|
||||
import com.iluwatar.servicelayer.spell.SpellDao;
|
||||
import com.iluwatar.servicelayer.spellbook.Spellbook;
|
||||
import com.iluwatar.servicelayer.spellbook.SpellbookDao;
|
||||
import com.iluwatar.servicelayer.wizard.Wizard;
|
||||
import com.iluwatar.servicelayer.wizard.WizardDao;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/29/15 - 12:06 AM
|
||||
*
|
||||
@ -53,11 +50,11 @@ public class MagicServiceImplTest {
|
||||
|
||||
@Test
|
||||
public void testFindAllWizards() {
|
||||
final WizardDao wizardDao = mock(WizardDao.class);
|
||||
final SpellbookDao spellbookDao = mock(SpellbookDao.class);
|
||||
final SpellDao spellDao = mock(SpellDao.class);
|
||||
final var wizardDao = mock(WizardDao.class);
|
||||
final var spellbookDao = mock(SpellbookDao.class);
|
||||
final var spellDao = mock(SpellDao.class);
|
||||
|
||||
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
verifyZeroInteractions(wizardDao, spellbookDao, spellDao);
|
||||
|
||||
service.findAllWizards();
|
||||
@ -66,12 +63,12 @@ public class MagicServiceImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllSpellbooks() throws Exception {
|
||||
final WizardDao wizardDao = mock(WizardDao.class);
|
||||
final SpellbookDao spellbookDao = mock(SpellbookDao.class);
|
||||
final SpellDao spellDao = mock(SpellDao.class);
|
||||
public void testFindAllSpellbooks() {
|
||||
final var wizardDao = mock(WizardDao.class);
|
||||
final var spellbookDao = mock(SpellbookDao.class);
|
||||
final var spellDao = mock(SpellDao.class);
|
||||
|
||||
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
verifyZeroInteractions(wizardDao, spellbookDao, spellDao);
|
||||
|
||||
service.findAllSpellbooks();
|
||||
@ -80,12 +77,12 @@ public class MagicServiceImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllSpells() throws Exception {
|
||||
final WizardDao wizardDao = mock(WizardDao.class);
|
||||
final SpellbookDao spellbookDao = mock(SpellbookDao.class);
|
||||
final SpellDao spellDao = mock(SpellDao.class);
|
||||
public void testFindAllSpells() {
|
||||
final var wizardDao = mock(WizardDao.class);
|
||||
final var spellbookDao = mock(SpellbookDao.class);
|
||||
final var spellDao = mock(SpellDao.class);
|
||||
|
||||
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
verifyZeroInteractions(wizardDao, spellbookDao, spellDao);
|
||||
|
||||
service.findAllSpells();
|
||||
@ -94,26 +91,27 @@ public class MagicServiceImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindWizardsWithSpellbook() throws Exception {
|
||||
final String bookname = "bookname";
|
||||
final Spellbook spellbook = mock(Spellbook.class);
|
||||
final Set<Wizard> wizards = Set.of(
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class));
|
||||
public void testFindWizardsWithSpellbook() {
|
||||
final var bookname = "bookname";
|
||||
final var spellbook = mock(Spellbook.class);
|
||||
final var wizards = Set.of(
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class)
|
||||
);
|
||||
when(spellbook.getWizards()).thenReturn(wizards);
|
||||
|
||||
final SpellbookDao spellbookDao = mock(SpellbookDao.class);
|
||||
final var spellbookDao = mock(SpellbookDao.class);
|
||||
when(spellbookDao.findByName(eq(bookname))).thenReturn(spellbook);
|
||||
|
||||
final WizardDao wizardDao = mock(WizardDao.class);
|
||||
final SpellDao spellDao = mock(SpellDao.class);
|
||||
final var wizardDao = mock(WizardDao.class);
|
||||
final var spellDao = mock(SpellDao.class);
|
||||
|
||||
|
||||
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook);
|
||||
|
||||
final List<Wizard> result = service.findWizardsWithSpellbook(bookname);
|
||||
final var result = service.findWizardsWithSpellbook(bookname);
|
||||
verify(spellbookDao).findByName(eq(bookname));
|
||||
verify(spellbook).getWizards();
|
||||
|
||||
@ -125,27 +123,28 @@ public class MagicServiceImplTest {
|
||||
|
||||
@Test
|
||||
public void testFindWizardsWithSpell() throws Exception {
|
||||
final Set<Wizard> wizards = Set.of(
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class));
|
||||
final Spellbook spellbook = mock(Spellbook.class);
|
||||
final var wizards = Set.of(
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class),
|
||||
mock(Wizard.class)
|
||||
);
|
||||
final var spellbook = mock(Spellbook.class);
|
||||
when(spellbook.getWizards()).thenReturn(wizards);
|
||||
|
||||
final SpellbookDao spellbookDao = mock(SpellbookDao.class);
|
||||
final WizardDao wizardDao = mock(WizardDao.class);
|
||||
final var spellbookDao = mock(SpellbookDao.class);
|
||||
final var wizardDao = mock(WizardDao.class);
|
||||
|
||||
final Spell spell = mock(Spell.class);
|
||||
final var spell = mock(Spell.class);
|
||||
when(spell.getSpellbook()).thenReturn(spellbook);
|
||||
|
||||
final String spellName = "spellname";
|
||||
final SpellDao spellDao = mock(SpellDao.class);
|
||||
final var spellName = "spellname";
|
||||
final var spellDao = mock(SpellDao.class);
|
||||
when(spellDao.findByName(eq(spellName))).thenReturn(spell);
|
||||
|
||||
final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
final var service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao);
|
||||
verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook);
|
||||
|
||||
final List<Wizard> result = service.findWizardsWithSpell(spellName);
|
||||
final var result = service.findWizardsWithSpell(spellName);
|
||||
verify(spellDao).findByName(eq(spellName));
|
||||
verify(spellbook).getWizards();
|
||||
|
||||
|
@ -23,14 +23,12 @@
|
||||
|
||||
package com.iluwatar.servicelayer.spell;
|
||||
|
||||
import com.iluwatar.servicelayer.common.BaseDaoTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import com.iluwatar.servicelayer.common.BaseDaoTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 11:02 PM
|
||||
*
|
||||
@ -44,10 +42,10 @@ public class SpellDaoImplTest extends BaseDaoTest<Spell, SpellDaoImpl> {
|
||||
|
||||
@Test
|
||||
public void testFindByName() {
|
||||
final SpellDaoImpl dao = getDao();
|
||||
final List<Spell> allSpells = dao.findAll();
|
||||
for (final Spell spell : allSpells) {
|
||||
final Spell spellByName = dao.findByName(spell.getName());
|
||||
final var dao = getDao();
|
||||
final var allSpells = dao.findAll();
|
||||
for (final var spell : allSpells) {
|
||||
final var spellByName = dao.findByName(spell.getName());
|
||||
assertNotNull(spellByName);
|
||||
assertEquals(spell.getId(), spellByName.getId());
|
||||
assertEquals(spell.getName(), spellByName.getName());
|
||||
|
@ -23,14 +23,12 @@
|
||||
|
||||
package com.iluwatar.servicelayer.spellbook;
|
||||
|
||||
import com.iluwatar.servicelayer.common.BaseDaoTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import com.iluwatar.servicelayer.common.BaseDaoTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 11:44 PM
|
||||
*
|
||||
@ -44,10 +42,10 @@ public class SpellbookDaoImplTest extends BaseDaoTest<Spellbook, SpellbookDaoImp
|
||||
|
||||
@Test
|
||||
public void testFindByName() {
|
||||
final SpellbookDaoImpl dao = getDao();
|
||||
final List<Spellbook> allBooks = dao.findAll();
|
||||
for (final Spellbook book : allBooks) {
|
||||
final Spellbook spellByName = dao.findByName(book.getName());
|
||||
final var dao = getDao();
|
||||
final var allBooks = dao.findAll();
|
||||
for (final var book : allBooks) {
|
||||
final var spellByName = dao.findByName(book.getName());
|
||||
assertNotNull(spellByName);
|
||||
assertEquals(book.getId(), spellByName.getId());
|
||||
assertEquals(book.getName(), spellByName.getName());
|
||||
|
@ -23,14 +23,12 @@
|
||||
|
||||
package com.iluwatar.servicelayer.wizard;
|
||||
|
||||
import com.iluwatar.servicelayer.common.BaseDaoTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import com.iluwatar.servicelayer.common.BaseDaoTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/28/15 - 11:46 PM
|
||||
*
|
||||
@ -44,10 +42,10 @@ public class WizardDaoImplTest extends BaseDaoTest<Wizard, WizardDaoImpl> {
|
||||
|
||||
@Test
|
||||
public void testFindByName() {
|
||||
final WizardDaoImpl dao = getDao();
|
||||
final List<Wizard> allWizards = dao.findAll();
|
||||
for (final Wizard spell : allWizards) {
|
||||
final Wizard byName = dao.findByName(spell.getName());
|
||||
final var dao = getDao();
|
||||
final var allWizards = dao.findAll();
|
||||
for (final var spell : allWizards) {
|
||||
final var byName = dao.findByName(spell.getName());
|
||||
assertNotNull(byName);
|
||||
assertEquals(spell.getId(), byName.getId());
|
||||
assertEquals(spell.getName(), byName.getName());
|
||||
|
@ -53,15 +53,14 @@ public class ServiceCache {
|
||||
* @return {@link Service}
|
||||
*/
|
||||
public Service getService(String serviceName) {
|
||||
Service cachedService = null;
|
||||
for (String serviceJndiName : serviceCache.keySet()) {
|
||||
if (serviceJndiName.equals(serviceName)) {
|
||||
cachedService = serviceCache.get(serviceJndiName);
|
||||
LOGGER.info("(cache call) Fetched service {}({}) from cache... !",
|
||||
cachedService.getName(), cachedService.getId());
|
||||
}
|
||||
if (serviceCache.containsKey(serviceName)) {
|
||||
var cachedService = serviceCache.get(serviceName);
|
||||
var name = cachedService.getName();
|
||||
var id = cachedService.getId();
|
||||
LOGGER.info("(cache call) Fetched service {}({}) from cache... !", name, id);
|
||||
return cachedService;
|
||||
}
|
||||
return cachedService;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,15 +26,12 @@ package com.iluwatar.servicelocator;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Application test
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -23,14 +23,15 @@
|
||||
|
||||
package com.iluwatar.servicelocator;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/29/15 - 19:07 PM
|
||||
*
|
||||
@ -52,12 +53,10 @@ public class ServiceLocatorTest {
|
||||
*/
|
||||
@Test
|
||||
public void testServiceCache() {
|
||||
final String[] serviceNames = new String[]{
|
||||
"jndi/serviceA", "jndi/serviceB"
|
||||
};
|
||||
final var serviceNames = List.of("jndi/serviceA", "jndi/serviceB");
|
||||
|
||||
for (final String serviceName : serviceNames) {
|
||||
final Service service = ServiceLocator.getService(serviceName);
|
||||
for (final var serviceName : serviceNames) {
|
||||
final var service = ServiceLocator.getService(serviceName);
|
||||
assertNotNull(service);
|
||||
assertEquals(serviceName, service.getName());
|
||||
assertTrue(service.getId() > 0); // The id is generated randomly, but the minimum value is '1'
|
||||
|
@ -24,14 +24,14 @@
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
/**
|
||||
* Sharding pattern means dividing a data store into a set of horizontal partitions
|
||||
* or shards. This pattern can improve scalability when storing and accessing large
|
||||
* volumes of data.
|
||||
* Sharding pattern means dividing a data store into a set of horizontal partitions or shards. This
|
||||
* pattern can improve scalability when storing and accessing large volumes of data.
|
||||
*/
|
||||
public class App {
|
||||
|
||||
/**
|
||||
* Program main entry point.
|
||||
*
|
||||
* @param args program runtime arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
@ -45,7 +45,7 @@ public class App {
|
||||
var shard2 = new Shard(2);
|
||||
var shard3 = new Shard(3);
|
||||
|
||||
ShardManager manager = new LookupShardManager();
|
||||
var manager = new LookupShardManager();
|
||||
manager.addNewShard(shard1);
|
||||
manager.addNewShard(shard2);
|
||||
manager.addNewShard(shard3);
|
||||
@ -58,27 +58,27 @@ public class App {
|
||||
shard2.clearData();
|
||||
shard3.clearData();
|
||||
|
||||
manager = new RangeShardManager();
|
||||
manager.addNewShard(shard1);
|
||||
manager.addNewShard(shard2);
|
||||
manager.addNewShard(shard3);
|
||||
manager.storeData(data1);
|
||||
manager.storeData(data2);
|
||||
manager.storeData(data3);
|
||||
manager.storeData(data4);
|
||||
var rangeShardManager = new RangeShardManager();
|
||||
rangeShardManager.addNewShard(shard1);
|
||||
rangeShardManager.addNewShard(shard2);
|
||||
rangeShardManager.addNewShard(shard3);
|
||||
rangeShardManager.storeData(data1);
|
||||
rangeShardManager.storeData(data2);
|
||||
rangeShardManager.storeData(data3);
|
||||
rangeShardManager.storeData(data4);
|
||||
|
||||
shard1.clearData();
|
||||
shard2.clearData();
|
||||
shard3.clearData();
|
||||
|
||||
manager = new HashShardManager();
|
||||
manager.addNewShard(shard1);
|
||||
manager.addNewShard(shard2);
|
||||
manager.addNewShard(shard3);
|
||||
manager.storeData(data1);
|
||||
manager.storeData(data2);
|
||||
manager.storeData(data3);
|
||||
manager.storeData(data4);
|
||||
var hashShardManager = new HashShardManager();
|
||||
hashShardManager.addNewShard(shard1);
|
||||
hashShardManager.addNewShard(shard2);
|
||||
hashShardManager.addNewShard(shard3);
|
||||
hashShardManager.storeData(data1);
|
||||
hashShardManager.storeData(data2);
|
||||
hashShardManager.storeData(data3);
|
||||
hashShardManager.storeData(data4);
|
||||
|
||||
shard1.clearData();
|
||||
shard2.clearData();
|
||||
|
@ -58,8 +58,7 @@ public class LookupShardManager extends ShardManager {
|
||||
return lookupMap.get(key);
|
||||
} else {
|
||||
var shardCount = shardMap.size();
|
||||
var allocatedShardId = new Random().nextInt(shardCount - 1) + 1;
|
||||
return allocatedShardId;
|
||||
return new Random().nextInt(shardCount - 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ShardManager with range strategy. This strategy groups related items together
|
||||
* in the same shard, and orders them by shard key.
|
||||
* ShardManager with range strategy. This strategy groups related items together in the same shard,
|
||||
* and orders them by shard key.
|
||||
*/
|
||||
public class RangeShardManager extends ShardManager {
|
||||
|
||||
@ -46,21 +46,16 @@ public class RangeShardManager extends ShardManager {
|
||||
@Override
|
||||
protected int allocateShard(Data data) {
|
||||
var type = data.getType();
|
||||
var shardId = -1;
|
||||
switch (type) {
|
||||
case type1:
|
||||
shardId = 1;
|
||||
break;
|
||||
return 1;
|
||||
case type2:
|
||||
shardId = 2;
|
||||
break;
|
||||
return 2;
|
||||
case type3:
|
||||
shardId = 3;
|
||||
break;
|
||||
return 3;
|
||||
default:
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
return shardId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,8 +32,7 @@ public class AppTest {
|
||||
|
||||
@Test
|
||||
public void testMain() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,6 @@
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@ -57,7 +56,7 @@ public class LookupShardManagerTest {
|
||||
lookupShardManager.storeData(data);
|
||||
var field = LookupShardManager.class.getDeclaredField("lookupMap");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Integer> lookupMap = (Map<Integer, Integer>) field.get(lookupShardManager);
|
||||
var lookupMap = (Map<Integer, Integer>) field.get(lookupShardManager);
|
||||
var shardId = lookupMap.get(1);
|
||||
var shard = lookupShardManager.getShardById(shardId);
|
||||
Assert.assertEquals(data, shard.getDataById(1));
|
||||
|
@ -24,7 +24,6 @@
|
||||
package com.iluwatar.sharding;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -57,7 +56,7 @@ public class ShardManagerTest {
|
||||
shardManager.addNewShard(shard);
|
||||
var field = ShardManager.class.getDeclaredField("shardMap");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Shard> map = (Map<Integer, Shard>) field.get(shardManager);
|
||||
var map = (Map<Integer, Shard>) field.get(shardManager);
|
||||
Assert.assertEquals(1, map.size());
|
||||
Assert.assertEquals(shard, map.get(1));
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
@ -73,7 +72,7 @@ public class ShardManagerTest {
|
||||
boolean flag = shardManager.removeShardById(1);
|
||||
var field = ShardManager.class.getDeclaredField("shardMap");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Shard> map = (Map<Integer, Shard>) field.get(shardManager);
|
||||
var map = (Map<Integer, Shard>) field.get(shardManager);
|
||||
Assert.assertEquals(true, flag);
|
||||
Assert.assertEquals(0, map.size());
|
||||
} catch (IllegalAccessException | NoSuchFieldException e) {
|
||||
@ -83,9 +82,9 @@ public class ShardManagerTest {
|
||||
|
||||
@Test
|
||||
public void testGetShardById() {
|
||||
Shard shard = new Shard(1);
|
||||
var shard = new Shard(1);
|
||||
shardManager.addNewShard(shard);
|
||||
Shard tmpShard = shardManager.getShardById(1);
|
||||
var tmpShard = shardManager.getShardById(1);
|
||||
Assert.assertEquals(shard, tmpShard);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@ package com.iluwatar.sharding;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@ -48,7 +47,8 @@ public class ShardTest {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {}
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreData() {
|
||||
@ -56,7 +56,7 @@ public class ShardTest {
|
||||
shard.storeData(data);
|
||||
var field = Shard.class.getDeclaredField("dataStore");
|
||||
field.setAccessible(true);
|
||||
Map<Integer, Data> dataMap = (Map<Integer, Data>) field.get(shard);
|
||||
var dataMap = (Map<Integer, Data>) field.get(shard);
|
||||
Assert.assertEquals(1, dataMap.size());
|
||||
Assert.assertEquals(data, dataMap.get(1));
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
@ -68,13 +68,13 @@ public class ShardTest {
|
||||
@Test
|
||||
public void testClearData() {
|
||||
try {
|
||||
Map<Integer, Data> dataMap = new HashMap<>();
|
||||
var dataMap = new HashMap<Integer, Data>();
|
||||
dataMap.put(1, data);
|
||||
var field = Shard.class.getDeclaredField("dataStore");
|
||||
field.setAccessible(true);
|
||||
field.set(shard, dataMap);
|
||||
shard.clearData();
|
||||
dataMap = (Map<Integer, Data>) field.get(shard);
|
||||
dataMap = (HashMap<Integer, Data>) field.get(shard);
|
||||
Assert.assertEquals(0, dataMap.size());
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Assert.fail("Fail to modify field access.");
|
||||
|
@ -41,8 +41,8 @@ public enum EnumIvoryTower {
|
||||
Then in order to use
|
||||
|
||||
```java
|
||||
EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE;
|
||||
EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE;
|
||||
var enumIvoryTower1 = EnumIvoryTower.INSTANCE;
|
||||
var enumIvoryTower2 = EnumIvoryTower.INSTANCE;
|
||||
assertEquals(enumIvoryTower1, enumIvoryTower2); // true
|
||||
```
|
||||
|
||||
|
@ -45,8 +45,7 @@ import org.slf4j.LoggerFactory;
|
||||
* example is found in {@link EnumIvoryTower}. At first glance the code looks short and simple.
|
||||
* However, you should be aware of the downsides including committing to implementation strategy,
|
||||
* extending the enum class, serializability and restrictions to coding. These are extensively
|
||||
* discussed in Stack Overflow:
|
||||
* http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
|
||||
* discussed in Stack Overflow: http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
|
||||
* -a-singleton-with-javas-enum</p>
|
||||
*
|
||||
* <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
|
||||
@ -54,9 +53,9 @@ import org.slf4j.LoggerFactory;
|
||||
* synchronized.</p>
|
||||
*
|
||||
* <p>Another Singleton implementation that is initialized on demand is found in
|
||||
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than
|
||||
* {@link ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but
|
||||
* only the method internals on specific conditions.</p>
|
||||
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link
|
||||
* ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but only the
|
||||
* method internals on specific conditions.</p>
|
||||
*
|
||||
* <p>Yet another way to implement thread safe lazily initialized Singleton can be found in
|
||||
* {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
|
||||
@ -80,10 +79,8 @@ public class App {
|
||||
LOGGER.info("ivoryTower2={}", ivoryTower2);
|
||||
|
||||
// lazily initialized singleton
|
||||
var threadSafeIvoryTower1 =
|
||||
ThreadSafeLazyLoadedIvoryTower.getInstance();
|
||||
var threadSafeIvoryTower2 =
|
||||
ThreadSafeLazyLoadedIvoryTower.getInstance();
|
||||
var threadSafeIvoryTower1 = ThreadSafeLazyLoadedIvoryTower.getInstance();
|
||||
var threadSafeIvoryTower2 = ThreadSafeLazyLoadedIvoryTower.getInstance();
|
||||
LOGGER.info("threadSafeIvoryTower1={}", threadSafeIvoryTower1);
|
||||
LOGGER.info("threadSafeIvoryTower2={}", threadSafeIvoryTower2);
|
||||
|
||||
@ -100,11 +97,9 @@ public class App {
|
||||
LOGGER.info(dcl2.toString());
|
||||
|
||||
// initialize on demand holder idiom
|
||||
var demandHolderIdiom =
|
||||
InitializingOnDemandHolderIdiom.getInstance();
|
||||
var demandHolderIdiom = InitializingOnDemandHolderIdiom.getInstance();
|
||||
LOGGER.info(demandHolderIdiom.toString());
|
||||
var demandHolderIdiom2 =
|
||||
InitializingOnDemandHolderIdiom.getInstance();
|
||||
var demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance();
|
||||
LOGGER.info(demandHolderIdiom2.toString());
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ package com.iluwatar.singleton;
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class InitializingOnDemandHolderIdiomTest
|
||||
extends SingletonTest<InitializingOnDemandHolderIdiom> {
|
||||
extends SingletonTest<InitializingOnDemandHolderIdiom> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
|
@ -29,13 +29,11 @@ import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTimeout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
@ -73,9 +71,9 @@ public abstract class SingletonTest<S> {
|
||||
@Test
|
||||
public void testMultipleCallsReturnTheSameObjectInSameThread() {
|
||||
// Create several instances in the same calling thread
|
||||
S instance1 = this.singletonInstanceMethod.get();
|
||||
S instance2 = this.singletonInstanceMethod.get();
|
||||
S instance3 = this.singletonInstanceMethod.get();
|
||||
var instance1 = this.singletonInstanceMethod.get();
|
||||
var instance2 = this.singletonInstanceMethod.get();
|
||||
var instance3 = this.singletonInstanceMethod.get();
|
||||
// now check they are equal
|
||||
assertSame(instance1, instance2);
|
||||
assertSame(instance1, instance3);
|
||||
@ -89,19 +87,18 @@ public abstract class SingletonTest<S> {
|
||||
public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception {
|
||||
assertTimeout(ofMillis(10000), () -> {
|
||||
// Create 10000 tasks and inside each callable instantiate the singleton class
|
||||
final List<Callable<S>> tasks = new ArrayList<>();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
tasks.add(this.singletonInstanceMethod::get);
|
||||
}
|
||||
final var tasks = IntStream.range(0, 10000)
|
||||
.<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
// Use up to 8 concurrent threads to handle the tasks
|
||||
final ExecutorService executorService = Executors.newFixedThreadPool(8);
|
||||
final List<Future<S>> results = executorService.invokeAll(tasks);
|
||||
final var executorService = Executors.newFixedThreadPool(8);
|
||||
final var results = executorService.invokeAll(tasks);
|
||||
|
||||
// wait for all of the threads to complete
|
||||
final S expectedInstance = this.singletonInstanceMethod.get();
|
||||
for (Future<S> res : results) {
|
||||
final S instance = res.get();
|
||||
final var expectedInstance = this.singletonInstanceMethod.get();
|
||||
for (var res : results) {
|
||||
final var instance = res.get();
|
||||
assertNotNull(instance);
|
||||
assertSame(expectedInstance, instance);
|
||||
}
|
||||
|
@ -23,9 +23,7 @@
|
||||
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
@ -47,11 +45,10 @@ public class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDo
|
||||
*/
|
||||
@Test(expected = InvocationTargetException.class)
|
||||
public void testCreatingNewInstanceByRefection() throws Exception {
|
||||
ThreadSafeDoubleCheckLocking instance1 = ThreadSafeDoubleCheckLocking.getInstance();
|
||||
Constructor constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor();
|
||||
ThreadSafeDoubleCheckLocking.getInstance();
|
||||
var constructor = ThreadSafeDoubleCheckLocking.class.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
ThreadSafeDoubleCheckLocking instance2 =
|
||||
(ThreadSafeDoubleCheckLocking) constructor.newInstance(null);
|
||||
constructor.newInstance((Object[]) null);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ package com.iluwatar.singleton;
|
||||
* @author Jeroen Meulemeester
|
||||
*/
|
||||
public class ThreadSafeLazyLoadedIvoryTowerTest
|
||||
extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
|
||||
extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
|
@ -19,9 +19,9 @@ Say, you are building a war game with hundreds, or maybe even thousands of playe
|
||||
|
||||
```java
|
||||
public void handleMeLee(Unit units[], int numUnits) {
|
||||
for (int a = 0; a < numUnits - 1; a++)
|
||||
for (var a = 0; a < numUnits - 1; a++)
|
||||
{
|
||||
for (int b = a + 1; b < numUnits; b++)
|
||||
for (var b = a + 1; b < numUnits; b++)
|
||||
{
|
||||
if (units[a].position() == units[b].position())
|
||||
{
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Random;
|
||||
import org.slf4j.Logger;
|
||||
@ -62,58 +60,46 @@ import org.slf4j.LoggerFactory;
|
||||
public class App {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
|
||||
|
||||
static void noSpatialPartition(int height, int width,
|
||||
int numOfMovements, Hashtable<Integer, Bubble> bubbles) {
|
||||
ArrayList<Point> bubblesToCheck = new ArrayList<Point>();
|
||||
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) {
|
||||
bubblesToCheck.add(bubbles
|
||||
.get(e.nextElement())); //all bubbles have to be checked for collision for all bubbles
|
||||
}
|
||||
static void noSpatialPartition(int numOfMovements, Hashtable<Integer, Bubble> bubbles) {
|
||||
//all bubbles have to be checked for collision for all bubbles
|
||||
var bubblesToCheck = bubbles.values();
|
||||
|
||||
//will run numOfMovement times or till all bubbles have popped
|
||||
while (numOfMovements > 0 && !bubbles.isEmpty()) {
|
||||
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) {
|
||||
Integer i = e.nextElement();
|
||||
bubbles.forEach((i, bubble) -> {
|
||||
// bubble moves, new position gets updated
|
||||
// and collisions are checked with all bubbles in bubblesToCheck
|
||||
bubbles.get(i).move();
|
||||
bubbles.replace(i, bubbles.get(i));
|
||||
bubbles.get(i).handleCollision(bubblesToCheck, bubbles);
|
||||
}
|
||||
bubble.move();
|
||||
bubbles.replace(i, bubble);
|
||||
bubble.handleCollision(bubblesToCheck, bubbles);
|
||||
});
|
||||
numOfMovements--;
|
||||
}
|
||||
for (Integer key : bubbles.keySet()) {
|
||||
//bubbles not popped
|
||||
LOGGER.info("Bubble " + key + " not popped");
|
||||
}
|
||||
//bubbles not popped
|
||||
bubbles.keySet().stream().map(key -> "Bubble " + key + " not popped").forEach(LOGGER::info);
|
||||
}
|
||||
|
||||
static void withSpatialPartition(
|
||||
int height, int width, int numOfMovements, Hashtable<Integer, Bubble> bubbles) {
|
||||
//creating quadtree
|
||||
Rect rect = new Rect(width / 2, height / 2, width, height);
|
||||
QuadTree quadTree = new QuadTree(rect, 4);
|
||||
var rect = new Rect(width / 2, height / 2, width, height);
|
||||
var quadTree = new QuadTree(rect, 4);
|
||||
|
||||
//will run numOfMovement times or till all bubbles have popped
|
||||
while (numOfMovements > 0 && !bubbles.isEmpty()) {
|
||||
//quadtree updated each time
|
||||
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) {
|
||||
quadTree.insert(bubbles.get(e.nextElement()));
|
||||
}
|
||||
for (Enumeration<Integer> e = bubbles.keys(); e.hasMoreElements(); ) {
|
||||
Integer i = e.nextElement();
|
||||
bubbles.values().forEach(quadTree::insert);
|
||||
bubbles.forEach((i, bubble) -> {
|
||||
//bubble moves, new position gets updated, quadtree used to reduce computations
|
||||
bubbles.get(i).move();
|
||||
bubbles.replace(i, bubbles.get(i));
|
||||
SpatialPartitionBubbles sp = new SpatialPartitionBubbles(bubbles, quadTree);
|
||||
sp.handleCollisionsUsingQt(bubbles.get(i));
|
||||
}
|
||||
bubble.move();
|
||||
bubbles.replace(i, bubble);
|
||||
var sp = new SpatialPartitionBubbles(bubbles, quadTree);
|
||||
sp.handleCollisionsUsingQt(bubble);
|
||||
});
|
||||
numOfMovements--;
|
||||
}
|
||||
for (Integer key : bubbles.keySet()) {
|
||||
//bubbles not popped
|
||||
LOGGER.info("Bubble " + key + " not popped");
|
||||
}
|
||||
//bubbles not popped
|
||||
bubbles.keySet().stream().map(key -> "Bubble " + key + " not popped").forEach(LOGGER::info);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,23 +109,23 @@ public class App {
|
||||
*/
|
||||
|
||||
public static void main(String[] args) {
|
||||
Hashtable<Integer, Bubble> bubbles1 = new Hashtable<Integer, Bubble>();
|
||||
Hashtable<Integer, Bubble> bubbles2 = new Hashtable<Integer, Bubble>();
|
||||
Random rand = new Random();
|
||||
var bubbles1 = new Hashtable<Integer, Bubble>();
|
||||
var bubbles2 = new Hashtable<Integer, Bubble>();
|
||||
var rand = new Random();
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
Bubble b = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);
|
||||
var b = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);
|
||||
bubbles1.put(i, b);
|
||||
bubbles2.put(i, b);
|
||||
LOGGER.info("Bubble " + i + " with radius " + b.radius
|
||||
+ " added at (" + b.coordinateX + "," + b.coordinateY + ")");
|
||||
}
|
||||
|
||||
long start1 = System.currentTimeMillis();
|
||||
App.noSpatialPartition(300, 300, 20, bubbles1);
|
||||
long end1 = System.currentTimeMillis();
|
||||
long start2 = System.currentTimeMillis();
|
||||
var start1 = System.currentTimeMillis();
|
||||
App.noSpatialPartition(20, bubbles1);
|
||||
var end1 = System.currentTimeMillis();
|
||||
var start2 = System.currentTimeMillis();
|
||||
App.withSpatialPartition(300, 300, 20, bubbles2);
|
||||
long end2 = System.currentTimeMillis();
|
||||
var end2 = System.currentTimeMillis();
|
||||
LOGGER.info("Without spatial partition takes " + (end1 - start1) + "ms");
|
||||
LOGGER.info("With spatial partition takes " + (end2 - start2) + "ms");
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Random;
|
||||
import org.slf4j.Logger;
|
||||
@ -64,10 +64,10 @@ public class Bubble extends Point<Bubble> {
|
||||
allBubbles.remove(this.id);
|
||||
}
|
||||
|
||||
void handleCollision(ArrayList<Point> bubblesToCheck, Hashtable<Integer, Bubble> allBubbles) {
|
||||
boolean toBePopped = false; //if any other bubble collides with it, made true
|
||||
for (int i = 0; i < bubblesToCheck.size(); i++) {
|
||||
Integer otherId = bubblesToCheck.get(i).id;
|
||||
void handleCollision(Collection<? extends Point> toCheck, Hashtable<Integer, Bubble> allBubbles) {
|
||||
var toBePopped = false; //if any other bubble collides with it, made true
|
||||
for (var point : toCheck) {
|
||||
var otherId = point.id;
|
||||
if (allBubbles.get(otherId) != null && //the bubble hasn't been popped yet
|
||||
this.id != otherId && //the two bubbles are not the same
|
||||
this.touches(allBubbles.get(otherId))) { //the bubbles touch
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
@ -61,8 +61,8 @@ public abstract class Point<T> {
|
||||
/**
|
||||
* handling interactions/collisions with other objects.
|
||||
*
|
||||
* @param pointsToCheck contains the objects which need to be checked
|
||||
* @param allPoints contains hashtable of all points on field at this time
|
||||
* @param toCheck contains the objects which need to be checked
|
||||
* @param all contains hashtable of all points on field at this time
|
||||
*/
|
||||
abstract void handleCollision(ArrayList<Point> pointsToCheck, Hashtable<Integer, T> allPoints);
|
||||
abstract void handleCollision(Collection<? extends Point> toCheck, Hashtable<Integer, T> all);
|
||||
}
|
||||
|
@ -23,8 +23,7 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
@ -47,7 +46,7 @@ public class QuadTree {
|
||||
this.boundary = boundary;
|
||||
this.capacity = capacity;
|
||||
this.divided = false;
|
||||
this.points = new Hashtable<Integer, Point>();
|
||||
this.points = new Hashtable<>();
|
||||
this.northwest = null;
|
||||
this.northeast = null;
|
||||
this.southwest = null;
|
||||
@ -76,30 +75,29 @@ public class QuadTree {
|
||||
}
|
||||
|
||||
void divide() {
|
||||
double x = this.boundary.coordinateX;
|
||||
double y = this.boundary.coordinateY;
|
||||
double width = this.boundary.width;
|
||||
double height = this.boundary.height;
|
||||
Rect nw = new Rect(x - width / 4, y + height / 4, width / 2, height / 2);
|
||||
var x = this.boundary.coordinateX;
|
||||
var y = this.boundary.coordinateY;
|
||||
var width = this.boundary.width;
|
||||
var height = this.boundary.height;
|
||||
var nw = new Rect(x - width / 4, y + height / 4, width / 2, height / 2);
|
||||
this.northwest = new QuadTree(nw, this.capacity);
|
||||
Rect ne = new Rect(x + width / 4, y + height / 4, width / 2, height / 2);
|
||||
var ne = new Rect(x + width / 4, y + height / 4, width / 2, height / 2);
|
||||
this.northeast = new QuadTree(ne, this.capacity);
|
||||
Rect sw = new Rect(x - width / 4, y - height / 4, width / 2, height / 2);
|
||||
var sw = new Rect(x - width / 4, y - height / 4, width / 2, height / 2);
|
||||
this.southwest = new QuadTree(sw, this.capacity);
|
||||
Rect se = new Rect(x + width / 4, y - height / 4, width / 2, height / 2);
|
||||
var se = new Rect(x + width / 4, y - height / 4, width / 2, height / 2);
|
||||
this.southeast = new QuadTree(se, this.capacity);
|
||||
this.divided = true;
|
||||
}
|
||||
|
||||
ArrayList<Point> query(Rect r, ArrayList<Point> relevantPoints) {
|
||||
Collection<Point> query(Rect r, Collection<Point> relevantPoints) {
|
||||
//could also be a circle instead of a rectangle
|
||||
if (this.boundary.intersects(r)) {
|
||||
for (Enumeration<Integer> e = this.points.keys(); e.hasMoreElements(); ) {
|
||||
Integer i = e.nextElement();
|
||||
if (r.contains(this.points.get(i))) {
|
||||
relevantPoints.add(this.points.get(i));
|
||||
}
|
||||
}
|
||||
this.points
|
||||
.values()
|
||||
.stream()
|
||||
.filter(r::contains)
|
||||
.forEach(relevantPoints::add);
|
||||
if (this.divided) {
|
||||
this.northwest.query(r, relevantPoints);
|
||||
this.northeast.query(r, relevantPoints);
|
||||
|
@ -24,6 +24,7 @@
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
@ -44,8 +45,8 @@ public class SpatialPartitionBubbles extends SpatialPartitionGeneric<Bubble> {
|
||||
void handleCollisionsUsingQt(Bubble b) {
|
||||
// finding points within area of a square drawn with centre same as
|
||||
// centre of bubble and length = radius of bubble
|
||||
Rect rect = new Rect(b.coordinateX, b.coordinateY, 2 * b.radius, 2 * b.radius);
|
||||
ArrayList<Point> quadTreeQueryResult = new ArrayList<Point>();
|
||||
var rect = new Rect(b.coordinateX, b.coordinateY, 2 * b.radius, 2 * b.radius);
|
||||
var quadTreeQueryResult = new ArrayList<Point>();
|
||||
this.quadTree.query(rect, quadTreeQueryResult);
|
||||
//handling these collisions
|
||||
b.handleCollision(quadTreeQueryResult, this.bubbles);
|
||||
|
@ -23,62 +23,71 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Testing methods in Bubble class.
|
||||
*/
|
||||
* Testing methods in Bubble class.
|
||||
*/
|
||||
|
||||
class BubbleTest {
|
||||
|
||||
@Test
|
||||
void moveTest() {
|
||||
Bubble b = new Bubble(10,10,1,2);
|
||||
int initialX = b.coordinateX;
|
||||
int initialY = b.coordinateY;
|
||||
var b = new Bubble(10, 10, 1, 2);
|
||||
var initialX = b.coordinateX;
|
||||
var initialY = b.coordinateY;
|
||||
b.move();
|
||||
//change in x and y < |2|
|
||||
assertTrue((b.coordinateX - initialX < 2 && b.coordinateX - initialX > -2) && (b.coordinateY - initialY < 2 && b.coordinateY - initialY > -2));
|
||||
assertTrue(b.coordinateX - initialX < 2 && b.coordinateX - initialX > -2);
|
||||
assertTrue(b.coordinateY - initialY < 2 && b.coordinateY - initialY > -2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void touchesTest() {
|
||||
Bubble b1 = new Bubble(0,0,1,2);
|
||||
Bubble b2 = new Bubble(1,1,2,1);
|
||||
Bubble b3 = new Bubble(10,10,3,1);
|
||||
var b1 = new Bubble(0, 0, 1, 2);
|
||||
var b2 = new Bubble(1, 1, 2, 1);
|
||||
var b3 = new Bubble(10, 10, 3, 1);
|
||||
//b1 touches b2 but not b3
|
||||
assertTrue(b1.touches(b2) && !b1.touches(b3));
|
||||
assertTrue(b1.touches(b2));
|
||||
assertFalse(b1.touches(b3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void popTest() {
|
||||
Bubble b1 = new Bubble(10,10,1,2);
|
||||
Bubble b2 = new Bubble(0,0,2,2);
|
||||
Hashtable<Integer, Bubble> bubbles = new Hashtable<Integer, Bubble>();
|
||||
bubbles.put(1, b1);
|
||||
var b1 = new Bubble(10, 10, 1, 2);
|
||||
var b2 = new Bubble(0, 0, 2, 2);
|
||||
var bubbles = new Hashtable<Integer, Bubble>();
|
||||
bubbles.put(1, b1);
|
||||
bubbles.put(2, b2);
|
||||
b1.pop(bubbles);
|
||||
//after popping, bubble no longer in hashtable containing all bubbles
|
||||
assertTrue(bubbles.get(1) == null && bubbles.get(2) != null);
|
||||
assertNull(bubbles.get(1));
|
||||
assertNotNull(bubbles.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void handleCollisionTest() {
|
||||
Bubble b1 = new Bubble(0,0,1,2);
|
||||
Bubble b2 = new Bubble(1,1,2,1);
|
||||
Bubble b3 = new Bubble(10,10,3,1);
|
||||
Hashtable<Integer, Bubble> bubbles = new Hashtable<Integer, Bubble>();
|
||||
bubbles.put(1, b1);
|
||||
bubbles.put(2, b2);
|
||||
var b1 = new Bubble(0, 0, 1, 2);
|
||||
var b2 = new Bubble(1, 1, 2, 1);
|
||||
var b3 = new Bubble(10, 10, 3, 1);
|
||||
var bubbles = new Hashtable<Integer, Bubble>();
|
||||
bubbles.put(1, b1);
|
||||
bubbles.put(2, b2);
|
||||
bubbles.put(3, b3);
|
||||
ArrayList<Point> bubblesToCheck = new ArrayList<Point>();
|
||||
bubblesToCheck.add(b2);
|
||||
var bubblesToCheck = new ArrayList<Point>();
|
||||
bubblesToCheck.add(b2);
|
||||
bubblesToCheck.add(b3);
|
||||
b1.handleCollision(bubblesToCheck, bubbles);
|
||||
//b1 touches b2 and not b3, so b1, b2 will be popped
|
||||
assertTrue(bubbles.get(1) == null && bubbles.get(2) == null && bubbles.get(3) != null);
|
||||
assertNull(bubbles.get(1));
|
||||
assertNull(bubbles.get(2));
|
||||
assertNotNull(bubbles.get(3));
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,13 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
@ -39,41 +40,34 @@ class QuadTreeTest {
|
||||
|
||||
@Test
|
||||
void queryTest() {
|
||||
ArrayList<Point> points = new ArrayList<Point>();
|
||||
Random rand = new Random();
|
||||
var points = new ArrayList<Point>();
|
||||
var rand = new Random();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
Bubble p = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);
|
||||
var p = new Bubble(rand.nextInt(300), rand.nextInt(300), i, rand.nextInt(2) + 1);
|
||||
points.add(p);
|
||||
}
|
||||
Rect field = new Rect(150,150,300,300); //size of field
|
||||
Rect queryRange = new Rect(70,130,100,100); //result = all points lying in this rectangle
|
||||
var field = new Rect(150, 150, 300, 300); //size of field
|
||||
var queryRange = new Rect(70, 130, 100, 100); //result = all points lying in this rectangle
|
||||
//points found in the query range using quadtree and normal method is same
|
||||
assertTrue(QuadTreeTest.quadTreeTest(points, field, queryRange).equals(QuadTreeTest.verify(points, queryRange)));
|
||||
var points1 = QuadTreeTest.quadTreeTest(points, field, queryRange);
|
||||
var points2 = QuadTreeTest.verify(points, queryRange);
|
||||
assertEquals(points1, points2);
|
||||
}
|
||||
|
||||
static Hashtable<Integer, Point> quadTreeTest(ArrayList<Point> points, Rect field, Rect queryRange) {
|
||||
static Hashtable<Integer, Point> quadTreeTest(Collection<Point> points, Rect field, Rect queryRange) {
|
||||
//creating quadtree and inserting all points
|
||||
QuadTree qTree = new QuadTree(queryRange, 4);
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
qTree.insert(points.get(i));
|
||||
}
|
||||
var qTree = new QuadTree(queryRange, 4);
|
||||
points.forEach(qTree::insert);
|
||||
|
||||
ArrayList<Point> queryResult = qTree.query(field, new ArrayList<Point>());
|
||||
Hashtable<Integer, Point> result = new Hashtable<Integer, Point>();
|
||||
for (int i = 0; i < queryResult.size(); i++) {
|
||||
Point p = queryResult.get(i);
|
||||
result.put(p.id, p);
|
||||
}
|
||||
return result;
|
||||
return qTree
|
||||
.query(field, new ArrayList<>())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(p -> p.id, p -> p, (a, b) -> b, Hashtable::new));
|
||||
}
|
||||
|
||||
static Hashtable<Integer, Point> verify(ArrayList<Point> points, Rect queryRange) {
|
||||
Hashtable<Integer, Point> result = new Hashtable<Integer, Point>();
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
if (queryRange.contains(points.get(i))) {
|
||||
result.put(points.get(i).id, points.get(i));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
static Hashtable<Integer, Point> verify(Collection<Point> points, Rect queryRange) {
|
||||
return points.stream()
|
||||
.filter(queryRange::contains)
|
||||
.collect(Collectors.toMap(point -> point.id, point -> point, (a, b) -> b, Hashtable::new));
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,9 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
@ -34,19 +36,21 @@ class RectTest {
|
||||
|
||||
@Test
|
||||
void containsTest() {
|
||||
Rect r = new Rect(10,10,20,20);
|
||||
Bubble b1 = new Bubble(2,2,1,1);
|
||||
Bubble b2 = new Bubble(30,30,2,1);
|
||||
var r = new Rect(10, 10, 20, 20);
|
||||
var b1 = new Bubble(2, 2, 1, 1);
|
||||
var b2 = new Bubble(30, 30, 2, 1);
|
||||
//r contains b1 and not b2
|
||||
assertTrue(r.contains(b1) && !r.contains(b2));
|
||||
assertTrue(r.contains(b1));
|
||||
assertFalse(r.contains(b2));
|
||||
}
|
||||
|
||||
@Test
|
||||
void intersectsTest() {
|
||||
Rect r1 = new Rect(10,10,20,20);
|
||||
Rect r2 = new Rect(15,15,20,20);
|
||||
Rect r3 = new Rect(50,50,20,20);
|
||||
var r1 = new Rect(10, 10, 20, 20);
|
||||
var r2 = new Rect(15, 15, 20, 20);
|
||||
var r3 = new Rect(50, 50, 20, 20);
|
||||
//r1 intersects r2 and not r3
|
||||
assertTrue(r1.intersects(r2) && !r1.intersects(r3));
|
||||
assertTrue(r1.intersects(r2));
|
||||
assertFalse(r1.intersects(r3));
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,9 @@
|
||||
|
||||
package com.iluwatar.spatialpartition;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@ -35,24 +37,27 @@ class SpatialPartitionBubblesTest {
|
||||
|
||||
@Test
|
||||
void handleCollisionsUsingQtTest() {
|
||||
Bubble b1 = new Bubble(10,10,1,3);
|
||||
Bubble b2 = new Bubble(5,5,2,1);
|
||||
Bubble b3 = new Bubble(9,9,3,1);
|
||||
Bubble b4 = new Bubble(8,8,4,2);
|
||||
Hashtable<Integer, Bubble> bubbles = new Hashtable<Integer, Bubble>();
|
||||
bubbles.put(1, b1);
|
||||
bubbles.put(2, b2);
|
||||
bubbles.put(3, b3);
|
||||
var b1 = new Bubble(10, 10, 1, 3);
|
||||
var b2 = new Bubble(5, 5, 2, 1);
|
||||
var b3 = new Bubble(9, 9, 3, 1);
|
||||
var b4 = new Bubble(8, 8, 4, 2);
|
||||
var bubbles = new Hashtable<Integer, Bubble>();
|
||||
bubbles.put(1, b1);
|
||||
bubbles.put(2, b2);
|
||||
bubbles.put(3, b3);
|
||||
bubbles.put(4, b4);
|
||||
Rect r = new Rect(10,10,20,20);
|
||||
QuadTree qt = new QuadTree(r,4);
|
||||
qt.insert(b1);
|
||||
qt.insert(b2);
|
||||
qt.insert(b3);
|
||||
var r = new Rect(10, 10, 20, 20);
|
||||
var qt = new QuadTree(r, 4);
|
||||
qt.insert(b1);
|
||||
qt.insert(b2);
|
||||
qt.insert(b3);
|
||||
qt.insert(b4);
|
||||
SpatialPartitionBubbles sp = new SpatialPartitionBubbles(bubbles, qt);
|
||||
var sp = new SpatialPartitionBubbles(bubbles, qt);
|
||||
sp.handleCollisionsUsingQt(b1);
|
||||
//b1 touches b3 and b4 but not b2 - so b1,b3,b4 get popped
|
||||
assertTrue(bubbles.get(1) == null && bubbles.get(2) != null && bubbles.get(3) == null && bubbles.get(4) == null);
|
||||
assertNull(bubbles.get(1));
|
||||
assertNotNull(bubbles.get(2));
|
||||
assertNull(bubbles.get(3));
|
||||
assertNull(bubbles.get(4));
|
||||
}
|
||||
}
|
||||
|
@ -100,24 +100,24 @@ public class MassGreaterThanSelector extends AbstractSelector<Creature> {
|
||||
With these building blocks in place, we can perform a search for red creatures as follows:
|
||||
|
||||
```java
|
||||
List<Creature> redCreatures = creatures.stream().filter(new ColorSelector(Color.RED))
|
||||
var redCreatures = creatures.stream().filter(new ColorSelector(Color.RED))
|
||||
.collect(Collectors.toList());
|
||||
```
|
||||
|
||||
But we could also use our parameterized selector like this:
|
||||
|
||||
```java
|
||||
List<Creature> heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0)
|
||||
var heavyCreatures = creatures.stream().filter(new MassGreaterThanSelector(500.0)
|
||||
.collect(Collectors.toList());
|
||||
```
|
||||
|
||||
Our third option is to combine multiple selectors together. Performing a search for special creatures (defined as red, flying, and not small) could be done as follows:
|
||||
|
||||
```java
|
||||
AbstractSelector specialCreaturesSelector =
|
||||
var specialCreaturesSelector =
|
||||
new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)).and(new SizeSelector(Size.SMALL).not());
|
||||
|
||||
List<Creature> specialCreatures = creatures.stream().filter(specialCreaturesSelector)
|
||||
var specialCreatures = creatures.stream().filter(specialCreaturesSelector)
|
||||
.collect(Collectors.toList());
|
||||
```
|
||||
|
||||
|
@ -32,14 +32,14 @@ import com.iluwatar.specification.creature.Shark;
|
||||
import com.iluwatar.specification.creature.Troll;
|
||||
import com.iluwatar.specification.property.Color;
|
||||
import com.iluwatar.specification.property.Movement;
|
||||
import com.iluwatar.specification.selector.AbstractSelector;
|
||||
import com.iluwatar.specification.selector.ColorSelector;
|
||||
import com.iluwatar.specification.selector.MassEqualSelector;
|
||||
import com.iluwatar.specification.selector.MassGreaterThanSelector;
|
||||
import com.iluwatar.specification.selector.MassSmallerThanOrEqSelector;
|
||||
import com.iluwatar.specification.selector.MovementSelector;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -63,57 +63,47 @@ public class App {
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// initialize creatures list
|
||||
List<Creature> creatures = List.of(new Goblin(), new Octopus(), new Dragon(), new Shark(),
|
||||
new Troll(), new KillerBee());
|
||||
var creatures = List.of(
|
||||
new Goblin(),
|
||||
new Octopus(),
|
||||
new Dragon(),
|
||||
new Shark(),
|
||||
new Troll(),
|
||||
new KillerBee()
|
||||
);
|
||||
// so-called "hard-coded" specification
|
||||
LOGGER.info("Demonstrating hard-coded specification :");
|
||||
// find all walking creatures
|
||||
LOGGER.info("Find all walking creatures");
|
||||
List<Creature> walkingCreatures =
|
||||
creatures.stream().filter(new MovementSelector(Movement.WALKING))
|
||||
.collect(Collectors.toList());
|
||||
walkingCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
print(creatures, new MovementSelector(Movement.WALKING));
|
||||
// find all dark creatures
|
||||
LOGGER.info("Find all dark creatures");
|
||||
List<Creature> darkCreatures =
|
||||
creatures.stream().filter(new ColorSelector(Color.DARK)).collect(Collectors.toList());
|
||||
darkCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
|
||||
print(creatures, new ColorSelector(Color.DARK));
|
||||
LOGGER.info("\n");
|
||||
// so-called "parameterized" specification
|
||||
LOGGER.info("Demonstrating parameterized specification :");
|
||||
// find all creatures heavier than 500kg
|
||||
LOGGER.info("Find all creatures heavier than 600kg");
|
||||
List<Creature> heavyCreatures =
|
||||
creatures.stream().filter(new MassGreaterThanSelector(600.0))
|
||||
.collect(Collectors.toList());
|
||||
heavyCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
print(creatures, new MassGreaterThanSelector(600.0));
|
||||
// find all creatures heavier than 500kg
|
||||
LOGGER.info("Find all creatures lighter than or weighing exactly 500kg");
|
||||
List<Creature> lightCreatures =
|
||||
creatures.stream().filter(new MassSmallerThanOrEqSelector(500.0))
|
||||
.collect(Collectors.toList());
|
||||
lightCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
|
||||
print(creatures, new MassSmallerThanOrEqSelector(500.0));
|
||||
LOGGER.info("\n");
|
||||
// so-called "composite" specification
|
||||
LOGGER.info("Demonstrating composite specification :");
|
||||
// find all red and flying creatures
|
||||
LOGGER.info("Find all red and flying creatures");
|
||||
List<Creature> redAndFlyingCreatures =
|
||||
creatures.stream()
|
||||
.filter(new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING)))
|
||||
.collect(Collectors.toList());
|
||||
redAndFlyingCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
var redAndFlying = new ColorSelector(Color.RED).and(new MovementSelector(Movement.FLYING));
|
||||
print(creatures, redAndFlying);
|
||||
// find all creatures dark or red, non-swimming, and heavier than or equal to 400kg
|
||||
LOGGER.info("Find all scary creatures");
|
||||
AbstractSelector<Creature> scaryCreaturesSelector = new ColorSelector(Color.DARK)
|
||||
var scaryCreaturesSelector = new ColorSelector(Color.DARK)
|
||||
.or(new ColorSelector(Color.RED)).and(new MovementSelector(Movement.SWIMMING).not())
|
||||
.and(new MassGreaterThanSelector(400.0).or(new MassEqualSelector(400.0)));
|
||||
List<Creature> scaryCreatures =
|
||||
creatures.stream()
|
||||
.filter(scaryCreaturesSelector)
|
||||
.collect(Collectors.toList());
|
||||
scaryCreatures.forEach(c -> LOGGER.info(c.toString()));
|
||||
print(creatures, scaryCreaturesSelector);
|
||||
}
|
||||
|
||||
private static void print(List<? extends Creature> creatures, Predicate<Creature> selector) {
|
||||
creatures.stream().filter(selector).map(Objects::toString).forEach(LOGGER::info);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -83,27 +83,24 @@ public class CreatureTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataProvider")
|
||||
public void testGetColor(Creature testedCreature, String name, Size size, Movement movement,
|
||||
Color color) {
|
||||
Color color) {
|
||||
assertEquals(color, testedCreature.getColor());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataProvider")
|
||||
public void testGetMass(Creature testedCreature, String name, Size size, Movement movement,
|
||||
Color color, Mass mass) {
|
||||
Color color, Mass mass) {
|
||||
assertEquals(mass, testedCreature.getMass());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("dataProvider")
|
||||
public void testToString(Creature testedCreature, String name, Size size, Movement movement,
|
||||
Color color, Mass mass) {
|
||||
final String toString = testedCreature.toString();
|
||||
Color color, Mass mass) {
|
||||
final var toString = testedCreature.toString();
|
||||
assertNotNull(toString);
|
||||
assertEquals(
|
||||
String.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color,
|
||||
mass),
|
||||
toString
|
||||
);
|
||||
assertEquals(String
|
||||
.format("%s [size=%s, movement=%s, color=%s, mass=%s]", name, size, movement, color, mass), toString);
|
||||
}
|
||||
}
|
@ -44,13 +44,13 @@ public class ColorSelectorTest {
|
||||
*/
|
||||
@Test
|
||||
public void testColor() {
|
||||
final Creature greenCreature = mock(Creature.class);
|
||||
final var greenCreature = mock(Creature.class);
|
||||
when(greenCreature.getColor()).thenReturn(Color.GREEN);
|
||||
|
||||
final Creature redCreature = mock(Creature.class);
|
||||
final var redCreature = mock(Creature.class);
|
||||
when(redCreature.getColor()).thenReturn(Color.RED);
|
||||
|
||||
final ColorSelector greenSelector = new ColorSelector(Color.GREEN);
|
||||
final var greenSelector = new ColorSelector(Color.GREEN);
|
||||
assertTrue(greenSelector.test(greenCreature));
|
||||
assertFalse(greenSelector.test(redCreature));
|
||||
|
||||
|
@ -40,16 +40,16 @@ public class CompositeSelectorsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testAndComposition() {
|
||||
final Creature swimmingHeavyCreature = mock(Creature.class);
|
||||
final var swimmingHeavyCreature = mock(Creature.class);
|
||||
when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));
|
||||
|
||||
final Creature swimmingLightCreature = mock(Creature.class);
|
||||
final var swimmingLightCreature = mock(Creature.class);
|
||||
when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));
|
||||
|
||||
final AbstractSelector<Creature> lightAndSwimmingSelector = new MassSmallerThanOrEqSelector(
|
||||
50.0).and(new MovementSelector(Movement.SWIMMING));
|
||||
final var lightAndSwimmingSelector = new MassSmallerThanOrEqSelector(50.0)
|
||||
.and(new MovementSelector(Movement.SWIMMING));
|
||||
assertFalse(lightAndSwimmingSelector.test(swimmingHeavyCreature));
|
||||
assertTrue(lightAndSwimmingSelector.test(swimmingLightCreature));
|
||||
}
|
||||
@ -59,15 +59,15 @@ public class CompositeSelectorsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testOrComposition() {
|
||||
final Creature swimmingHeavyCreature = mock(Creature.class);
|
||||
final var swimmingHeavyCreature = mock(Creature.class);
|
||||
when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));
|
||||
|
||||
final Creature swimmingLightCreature = mock(Creature.class);
|
||||
final var swimmingLightCreature = mock(Creature.class);
|
||||
when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));
|
||||
|
||||
final AbstractSelector<Creature> lightOrSwimmingSelector = new MassSmallerThanOrEqSelector(50.0)
|
||||
final var lightOrSwimmingSelector = new MassSmallerThanOrEqSelector(50.0)
|
||||
.or(new MovementSelector(Movement.SWIMMING));
|
||||
assertTrue(lightOrSwimmingSelector.test(swimmingHeavyCreature));
|
||||
assertTrue(lightOrSwimmingSelector.test(swimmingLightCreature));
|
||||
@ -78,15 +78,15 @@ public class CompositeSelectorsTest {
|
||||
*/
|
||||
@Test
|
||||
public void testNotComposition() {
|
||||
final Creature swimmingHeavyCreature = mock(Creature.class);
|
||||
final var swimmingHeavyCreature = mock(Creature.class);
|
||||
when(swimmingHeavyCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
when(swimmingHeavyCreature.getMass()).thenReturn(new Mass(100.0));
|
||||
|
||||
final Creature swimmingLightCreature = mock(Creature.class);
|
||||
final var swimmingLightCreature = mock(Creature.class);
|
||||
when(swimmingLightCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
when(swimmingLightCreature.getMass()).thenReturn(new Mass(25.0));
|
||||
|
||||
final AbstractSelector<Creature> heavySelector = new MassSmallerThanOrEqSelector(50.0).not();
|
||||
final var heavySelector = new MassSmallerThanOrEqSelector(50.0).not();
|
||||
assertTrue(heavySelector.test(swimmingHeavyCreature));
|
||||
assertFalse(heavySelector.test(swimmingLightCreature));
|
||||
}
|
||||
|
@ -39,13 +39,13 @@ public class MassSelectorTest {
|
||||
*/
|
||||
@Test
|
||||
public void testMass() {
|
||||
final Creature lightCreature = mock(Creature.class);
|
||||
final var lightCreature = mock(Creature.class);
|
||||
when(lightCreature.getMass()).thenReturn(new Mass(50.0));
|
||||
|
||||
final Creature heavyCreature = mock(Creature.class);
|
||||
final var heavyCreature = mock(Creature.class);
|
||||
when(heavyCreature.getMass()).thenReturn(new Mass(2500.0));
|
||||
|
||||
final MassSmallerThanOrEqSelector lightSelector = new MassSmallerThanOrEqSelector(500.0);
|
||||
final var lightSelector = new MassSmallerThanOrEqSelector(500.0);
|
||||
assertTrue(lightSelector.test(lightCreature));
|
||||
assertFalse(lightSelector.test(heavyCreature));
|
||||
}
|
||||
|
@ -44,13 +44,13 @@ public class MovementSelectorTest {
|
||||
*/
|
||||
@Test
|
||||
public void testMovement() {
|
||||
final Creature swimmingCreature = mock(Creature.class);
|
||||
final var swimmingCreature = mock(Creature.class);
|
||||
when(swimmingCreature.getMovement()).thenReturn(Movement.SWIMMING);
|
||||
|
||||
final Creature flyingCreature = mock(Creature.class);
|
||||
final var flyingCreature = mock(Creature.class);
|
||||
when(flyingCreature.getMovement()).thenReturn(Movement.FLYING);
|
||||
|
||||
final MovementSelector swimmingSelector = new MovementSelector(Movement.SWIMMING);
|
||||
final var swimmingSelector = new MovementSelector(Movement.SWIMMING);
|
||||
assertTrue(swimmingSelector.test(swimmingCreature));
|
||||
assertFalse(swimmingSelector.test(flyingCreature));
|
||||
|
||||
|
@ -44,13 +44,13 @@ public class SizeSelectorTest {
|
||||
*/
|
||||
@Test
|
||||
public void testMovement() {
|
||||
final Creature normalCreature = mock(Creature.class);
|
||||
final var normalCreature = mock(Creature.class);
|
||||
when(normalCreature.getSize()).thenReturn(Size.NORMAL);
|
||||
|
||||
final Creature smallCreature = mock(Creature.class);
|
||||
final var smallCreature = mock(Creature.class);
|
||||
when(smallCreature.getSize()).thenReturn(Size.SMALL);
|
||||
|
||||
final SizeSelector normalSelector = new SizeSelector(Size.NORMAL);
|
||||
final var normalSelector = new SizeSelector(Size.NORMAL);
|
||||
assertTrue(normalSelector.test(normalCreature));
|
||||
assertFalse(normalSelector.test(smallCreature));
|
||||
}
|
||||
|
@ -26,15 +26,12 @@ package com.iluwatar.state;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Application test
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -23,20 +23,19 @@
|
||||
|
||||
package com.iluwatar.state;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
* Date: 12/29/15 - 8:27 PM
|
||||
*
|
||||
@ -62,27 +61,27 @@ public class MammothTest {
|
||||
*/
|
||||
@Test
|
||||
public void testTimePasses() {
|
||||
final Mammoth mammoth = new Mammoth();
|
||||
final var mammoth = new Mammoth();
|
||||
|
||||
mammoth.observe();
|
||||
assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage());
|
||||
assertEquals(1 , appender.getLogSize());
|
||||
assertEquals(1, appender.getLogSize());
|
||||
|
||||
mammoth.timePasses();
|
||||
assertEquals("The mammoth gets angry!", appender.getLastMessage());
|
||||
assertEquals(2 , appender.getLogSize());
|
||||
assertEquals(2, appender.getLogSize());
|
||||
|
||||
mammoth.observe();
|
||||
assertEquals("The mammoth is furious!", appender.getLastMessage());
|
||||
assertEquals(3 , appender.getLogSize());
|
||||
assertEquals(3, appender.getLogSize());
|
||||
|
||||
mammoth.timePasses();
|
||||
assertEquals("The mammoth calms down.", appender.getLastMessage());
|
||||
assertEquals(4 , appender.getLogSize());
|
||||
assertEquals(4, appender.getLogSize());
|
||||
|
||||
mammoth.observe();
|
||||
assertEquals("The mammoth is calm and peaceful.", appender.getLastMessage());
|
||||
assertEquals(5 , appender.getLogSize());
|
||||
assertEquals(5, appender.getLogSize());
|
||||
|
||||
}
|
||||
|
||||
@ -91,7 +90,7 @@ public class MammothTest {
|
||||
*/
|
||||
@Test
|
||||
public void testToString() {
|
||||
final String toString = new Mammoth().toString();
|
||||
final var toString = new Mammoth().toString();
|
||||
assertNotNull(toString);
|
||||
assertEquals("The mammoth", toString);
|
||||
}
|
||||
|
@ -67,21 +67,34 @@ public class App {
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
var warrior =
|
||||
CharacterStepBuilder.newBuilder().name("Amberjill").fighterClass("Paladin")
|
||||
.withWeapon("Sword").noAbilities().build();
|
||||
var warrior = CharacterStepBuilder
|
||||
.newBuilder()
|
||||
.name("Amberjill")
|
||||
.fighterClass("Paladin")
|
||||
.withWeapon("Sword")
|
||||
.noAbilities()
|
||||
.build();
|
||||
|
||||
LOGGER.info(warrior.toString());
|
||||
|
||||
var mage =
|
||||
CharacterStepBuilder.newBuilder().name("Riobard").wizardClass("Sorcerer")
|
||||
.withSpell("Fireball").withAbility("Fire Aura").withAbility("Teleport")
|
||||
.noMoreAbilities().build();
|
||||
var mage = CharacterStepBuilder
|
||||
.newBuilder()
|
||||
.name("Riobard")
|
||||
.wizardClass("Sorcerer")
|
||||
.withSpell("Fireball")
|
||||
.withAbility("Fire Aura")
|
||||
.withAbility("Teleport")
|
||||
.noMoreAbilities()
|
||||
.build();
|
||||
|
||||
LOGGER.info(mage.toString());
|
||||
|
||||
var thief =
|
||||
CharacterStepBuilder.newBuilder().name("Desmond").fighterClass("Rogue").noWeapon().build();
|
||||
var thief = CharacterStepBuilder
|
||||
.newBuilder()
|
||||
.name("Desmond")
|
||||
.fighterClass("Rogue")
|
||||
.noWeapon()
|
||||
.build();
|
||||
|
||||
LOGGER.info(thief.toString());
|
||||
}
|
||||
|
@ -91,15 +91,15 @@ public class Character {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
var sb = new StringBuilder();
|
||||
sb.append("This is a ")
|
||||
return new StringBuilder()
|
||||
.append("This is a ")
|
||||
.append(fighterClass != null ? fighterClass : wizardClass)
|
||||
.append(" named ")
|
||||
.append(name)
|
||||
.append(" armed with a ")
|
||||
.append(weapon != null ? weapon : spell != null ? spell : "with nothing")
|
||||
.append(abilities != null ? " and wielding " + abilities + " abilities" : "")
|
||||
.append('.');
|
||||
return sb.toString();
|
||||
.append('.')
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ public final class CharacterStepBuilder {
|
||||
|
||||
@Override
|
||||
public Character build() {
|
||||
Character character = new Character(name);
|
||||
var character = new Character(name);
|
||||
|
||||
if (fighterClass != null) {
|
||||
character.setFighterClass(fighterClass);
|
||||
|
@ -26,15 +26,12 @@ package com.iluwatar.stepbuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Application test
|
||||
*
|
||||
*/
|
||||
public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -23,15 +23,13 @@
|
||||
|
||||
package com.iluwatar.stepbuilder;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Date: 12/29/15 - 9:21 PM
|
||||
*
|
||||
@ -44,7 +42,7 @@ public class CharacterStepBuilderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testBuildWizard() {
|
||||
final Character character = CharacterStepBuilder.newBuilder()
|
||||
final var character = CharacterStepBuilder.newBuilder()
|
||||
.name("Merlin")
|
||||
.wizardClass("alchemist")
|
||||
.withSpell("poison")
|
||||
@ -58,7 +56,7 @@ public class CharacterStepBuilderTest {
|
||||
assertEquals("poison", character.getSpell());
|
||||
assertNotNull(character.toString());
|
||||
|
||||
final List<String> abilities = character.getAbilities();
|
||||
final var abilities = character.getAbilities();
|
||||
assertNotNull(abilities);
|
||||
assertEquals(2, abilities.size());
|
||||
assertTrue(abilities.contains("invisibility"));
|
||||
@ -72,7 +70,7 @@ public class CharacterStepBuilderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testBuildPoorWizard() {
|
||||
final Character character = CharacterStepBuilder.newBuilder()
|
||||
final var character = CharacterStepBuilder.newBuilder()
|
||||
.name("Merlin")
|
||||
.wizardClass("alchemist")
|
||||
.noSpell()
|
||||
@ -91,7 +89,7 @@ public class CharacterStepBuilderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testBuildWeakWizard() {
|
||||
final Character character = CharacterStepBuilder.newBuilder()
|
||||
final var character = CharacterStepBuilder.newBuilder()
|
||||
.name("Merlin")
|
||||
.wizardClass("alchemist")
|
||||
.withSpell("poison")
|
||||
@ -112,7 +110,7 @@ public class CharacterStepBuilderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testBuildWarrior() {
|
||||
final Character character = CharacterStepBuilder.newBuilder()
|
||||
final var character = CharacterStepBuilder.newBuilder()
|
||||
.name("Cuauhtemoc")
|
||||
.fighterClass("aztec")
|
||||
.withWeapon("spear")
|
||||
@ -126,7 +124,7 @@ public class CharacterStepBuilderTest {
|
||||
assertEquals("spear", character.getWeapon());
|
||||
assertNotNull(character.toString());
|
||||
|
||||
final List<String> abilities = character.getAbilities();
|
||||
final var abilities = character.getAbilities();
|
||||
assertNotNull(abilities);
|
||||
assertEquals(2, abilities.size());
|
||||
assertTrue(abilities.contains("speed"));
|
||||
@ -140,7 +138,7 @@ public class CharacterStepBuilderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testBuildPoorWarrior() {
|
||||
final Character character = CharacterStepBuilder.newBuilder()
|
||||
final var character = CharacterStepBuilder.newBuilder()
|
||||
.name("Poor warrior")
|
||||
.fighterClass("none")
|
||||
.noWeapon()
|
||||
@ -160,7 +158,7 @@ public class CharacterStepBuilderTest {
|
||||
*/
|
||||
@Test
|
||||
public void testBuildWeakWarrior() {
|
||||
final Character character = CharacterStepBuilder.newBuilder()
|
||||
final var character = CharacterStepBuilder.newBuilder()
|
||||
.name("Weak warrior")
|
||||
.fighterClass("none")
|
||||
.withWeapon("Slingshot")
|
||||
|
@ -32,7 +32,6 @@ public class AppTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ public class DragonSlayerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testGoToBattle() {
|
||||
final DragonSlayingStrategy strategy = mock(DragonSlayingStrategy.class);
|
||||
final DragonSlayer dragonSlayer = new DragonSlayer(strategy);
|
||||
final var strategy = mock(DragonSlayingStrategy.class);
|
||||
final var dragonSlayer = new DragonSlayer(strategy);
|
||||
|
||||
dragonSlayer.goToBattle();
|
||||
verify(strategy).execute();
|
||||
@ -54,13 +54,13 @@ public class DragonSlayerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testChangeStrategy() {
|
||||
final DragonSlayingStrategy initialStrategy = mock(DragonSlayingStrategy.class);
|
||||
final DragonSlayer dragonSlayer = new DragonSlayer(initialStrategy);
|
||||
final var initialStrategy = mock(DragonSlayingStrategy.class);
|
||||
final var dragonSlayer = new DragonSlayer(initialStrategy);
|
||||
|
||||
dragonSlayer.goToBattle();
|
||||
verify(initialStrategy).execute();
|
||||
|
||||
final DragonSlayingStrategy newStrategy = mock(DragonSlayingStrategy.class);
|
||||
final var newStrategy = mock(DragonSlayingStrategy.class);
|
||||
dragonSlayer.changeStrategy(newStrategy);
|
||||
|
||||
dragonSlayer.goToBattle();
|
||||
|
@ -28,11 +28,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@ -53,18 +51,18 @@ public class DragonSlayingStrategyTest {
|
||||
*/
|
||||
static Collection<Object[]> dataProvider() {
|
||||
return List.of(
|
||||
new Object[]{
|
||||
new MeleeStrategy(),
|
||||
"With your Excalibur you sever the dragon's head!"
|
||||
},
|
||||
new Object[]{
|
||||
new ProjectileStrategy(),
|
||||
"You shoot the dragon with the magical crossbow and it falls dead on the ground!"
|
||||
},
|
||||
new Object[]{
|
||||
new SpellStrategy(),
|
||||
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"
|
||||
}
|
||||
new Object[]{
|
||||
new MeleeStrategy(),
|
||||
"With your Excalibur you sever the dragon's head!"
|
||||
},
|
||||
new Object[]{
|
||||
new ProjectileStrategy(),
|
||||
"You shoot the dragon with the magical crossbow and it falls dead on the ground!"
|
||||
},
|
||||
new Object[]{
|
||||
new SpellStrategy(),
|
||||
"You cast the spell of disintegration and the dragon vaporizes in a pile of dust!"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ public class AppTest {
|
||||
|
||||
@Test
|
||||
public void testMain() {
|
||||
String[] args = {};
|
||||
App.main(args);
|
||||
App.main(new String[]{});
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ public class GroundDiveTest {
|
||||
public void testActivate() {
|
||||
log.clearLog();
|
||||
var groundDive = new GroundDive();
|
||||
groundDive.activate();;
|
||||
String[] logs = log.getLog().split("\n");
|
||||
groundDive.activate();
|
||||
var logs = log.getLog().split("\n");
|
||||
final var expectedSize = 3;
|
||||
final var log1 = logs[0].split("-")[1].trim() + " -" + logs[0].split("-")[2].trim();
|
||||
final var expectedLog1 = "Move to ( 0.0, 0.0, -20.0 )";
|
||||
|
@ -70,8 +70,8 @@ public class SkyLaunchTest {
|
||||
public void testActivate() {
|
||||
log.clearLog();
|
||||
var skyLaunch = new SkyLaunch();
|
||||
skyLaunch.activate();;
|
||||
String[] logs = log.getLog().split("\n");
|
||||
skyLaunch.activate();
|
||||
var logs = log.getLog().split("\n");
|
||||
final var expectedSize = 3;
|
||||
final var log1 = getLogContent(logs[0]);
|
||||
final var expectedLog1 = "Move to ( 0.0, 0.0, 20.0 )";
|
||||
|
Loading…
x
Reference in New Issue
Block a user