Compare commits

...

34 Commits

Author SHA1 Message Date
Claudio Maggioni (maggicl) 109d2a4d44 Merge branch 'dev' of https://lab.si.usi.ch/sa4-2020/the-sanmarinoes/backend into dev 2021-02-14 12:23:25 +01:00
Claudio Maggioni (maggicl) 0ea0365c00 Fixed email sender for custom emails 2021-02-12 22:44:51 +01:00
Claudio Maggioni 3eea344b6f Merge branch '92-inputdeviceconnectioncontroller-tests' into 'dev'
Resolve "inputDeviceConnectionController Tests"

Closes #92

See merge request sa4-2020/the-sanmarinoes/backend!210
2020-05-27 22:51:56 +02:00
Claudio Maggioni (maggicl) c3b91cd1d1 Fixed tests 2020-05-27 22:51:37 +02:00
Claudio Maggioni 4e9d77c794 Merge branch 'tests' into 'dev'
Fix bug

See merge request sa4-2020/the-sanmarinoes/backend!209
2020-05-27 22:39:40 +02:00
Claudio Maggioni (maggicl) dfb27c7654 Fix bug 2020-05-27 22:39:25 +02:00
Claudio Maggioni 2708c438ba Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!208
2020-05-27 22:30:40 +02:00
Claudio Maggioni (maggicl) 7371999cc7 Tests 2020-05-27 22:29:59 +02:00
Claudio Maggioni f646ce38a5 Merge branch 'tests' into 'dev'
Four letters can change the behaviour of a piece of code a lot

See merge request sa4-2020/the-sanmarinoes/backend!207
2020-05-27 22:07:16 +02:00
Claudio Maggioni (maggicl) ea6f93d6f1 Four letters can change the behaviour of a piece of code a lot 2020-05-27 22:06:52 +02:00
Matteo Omenetti 8f3df8e96f Merge branch '97-fix-sensor' into 'dev'
fix

Closes #97

See merge request sa4-2020/the-sanmarinoes/backend!206
2020-05-27 18:31:13 +02:00
omenem 50d7c77177 fix 2020-05-27 18:28:21 +02:00
omenem 66b22064b4 fix 2020-05-27 18:24:45 +02:00
omenem 71302933e6 fix 2020-05-27 18:20:00 +02:00
omenem a843786759 wip 2020-05-27 16:21:30 +02:00
Matteo Omenetti d62fe005a8 Merge branch '96-fix-in-random-jitter-of-thermostat' into 'dev'
fix

Closes #96

See merge request sa4-2020/the-sanmarinoes/backend!205
2020-05-27 14:54:37 +02:00
omenem b2ef4e0904 fix 2020-05-27 14:50:14 +02:00
Claudio Maggioni 3bb8f1b394 Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!204
2020-05-27 11:52:58 +02:00
Claudio Maggioni (maggicl) f230bd8937 Tests 2020-05-27 11:52:44 +02:00
Claudio Maggioni 101f8a9398 Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!203
2020-05-27 11:43:19 +02:00
Claudio Maggioni (maggicl) 2aa6718424 Tests 2020-05-27 11:42:55 +02:00
Claudio Maggioni c8470d7a5d Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!202
2020-05-27 11:33:02 +02:00
Claudio Maggioni (maggicl) 9489fe9140 Tests 2020-05-27 11:32:44 +02:00
Claudio Maggioni 4283b4a28b Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!201
2020-05-27 11:14:34 +02:00
Claudio Maggioni (maggicl) 69aaf9920f Tests 2020-05-27 11:14:19 +02:00
Claudio Maggioni c7de5ca437 Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!200
2020-05-27 10:35:05 +02:00
Claudio Maggioni (maggicl) ec93ff22cc Tests 2020-05-27 10:34:48 +02:00
Claudio Maggioni 57f5415d61 Merge branch 'tests' into 'dev'
Tests

See merge request sa4-2020/the-sanmarinoes/backend!199
2020-05-27 10:11:14 +02:00
Claudio Maggioni (maggicl) a2470d132d Tests 2020-05-27 10:11:00 +02:00
Claudio Maggioni c48d610621 Merge branch 'tests' into 'dev'
Imported tests from Google

See merge request sa4-2020/the-sanmarinoes/backend!198
2020-05-27 09:48:52 +02:00
Claudio Maggioni (maggicl) 7a4bdbcf3c Imported tests from Google 2020-05-27 09:48:32 +02:00
Claudio Maggioni cea18bb2a8 Merge branch 'tests' into 'dev'
WIP

See merge request sa4-2020/the-sanmarinoes/backend!197
2020-05-27 00:21:13 +02:00
Claudio Maggioni (maggicl) c705febde0 WIP 2020-05-27 00:20:32 +02:00
omenem 7d634c0739 wip 2020-05-26 17:59:38 +02:00
33 changed files with 639 additions and 79 deletions

View File

@ -37,6 +37,7 @@ dependencies {
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'nl.jqno.equalsverifier:equalsverifier:3.3'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'com.h2database:h2:1.4.200'
// Fixes https://stackoverflow.com/a/60455550

View File

@ -46,6 +46,8 @@ public class EmailConfigurationService {
@NotNull private String registrationRedirect;
@NotNull private String from;
public synchronized String getRegistrationSubject() {
return registrationSubject;
}
@ -109,4 +111,12 @@ public class EmailConfigurationService {
public synchronized void setRegistrationRedirect(String registrationRedirect) {
this.registrationRedirect = registrationRedirect;
}
public synchronized String getFrom() {
return from;
}
public synchronized void setFrom(String from) {
this.from = from;
}
}

View File

@ -194,6 +194,17 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
return this;
}
/**
* Registers {@code type} identified by {@code label}. Labels are case sensitive.
*
* @throws IllegalArgumentException if either {@code type} or {@code label} have already been
* registered on this type adapter.
*/
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type) {
registerSubtype(type, type.getSimpleName());
return this;
}
private void initMaps(
Gson gson,
Map<String, TypeAdapter<?>> labelToDelegate,

View File

@ -29,7 +29,7 @@ public class ButtonDimmerController
ButtonDimmerRepository inputRepository,
DimmableRepository<Dimmable> outputRepository,
DeviceService deviceService) {
super(inputRepository, outputRepository);
super(inputRepository, outputRepository, deviceService);
this.deviceService = deviceService;
this.buttonDimmerRepository = inputRepository;
}

View File

@ -12,7 +12,6 @@ import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@ -28,7 +27,7 @@ import org.springframework.web.bind.annotation.RequestBody;
public abstract class InputDeviceConnectionController<
I extends InputDevice & Connectable<O>, O extends OutputDevice> {
private class Connection {
protected class Connection {
private final I input;
private final List<O> outputs;
@ -54,7 +53,7 @@ public abstract class InputDeviceConnectionController<
return outputReposiory;
}
@Autowired private DeviceService deviceService;
private final DeviceService deviceService;
private final DeviceRepository<I> inputRepository;
@ -67,9 +66,12 @@ public abstract class InputDeviceConnectionController<
* @param outputRepository the output device repository
*/
protected InputDeviceConnectionController(
DeviceRepository<I> inputRepository, DeviceRepository<O> outputRepository) {
DeviceRepository<I> inputRepository,
DeviceRepository<O> outputRepository,
DeviceService deviceService) {
this.inputRepository = inputRepository;
this.outputReposiory = outputRepository;
this.deviceService = deviceService;
}
private Connection checkConnectionIDs(Long inputId, List<Long> outputs, String username)

View File

@ -28,7 +28,7 @@ public class KnobDimmerController extends InputDeviceConnectionController<KnobDi
KnobDimmerRepository inputRepository,
DimmableRepository<Dimmable> outputRepository,
DeviceService deviceService) {
super(inputRepository, outputRepository);
super(inputRepository, outputRepository, deviceService);
this.knobDimmerRepository = inputRepository;
this.deviceService = deviceService;
}

View File

@ -64,8 +64,8 @@ public class SensorController {
@PutMapping("/{id}/simulation")
public Sensor updateSimulation(
@PathVariable("id") Long sensorId,
@RequestParam("error") BigDecimal error,
@RequestParam("typical") BigDecimal typical,
@RequestBody BigDecimal error,
@RequestBody BigDecimal typical,
final Principal principal)
throws NotFoundException {
return sensorService.updateSimulationFromSensor(

View File

@ -34,7 +34,7 @@ public class SwitchController extends InputDeviceConnectionController<Switch, Sw
SwitchRepository inputRepository,
SwitchableRepository<Switchable> outputRepository,
DeviceService deviceService) {
super(inputRepository, outputRepository);
super(inputRepository, outputRepository, deviceService);
this.deviceService = deviceService;
this.switchRepository = inputRepository;
}

View File

@ -57,7 +57,7 @@ public class UserAccountController {
isRegistration
? emailConfig.getRegistrationSubject()
: emailConfig.getResetPasswordSubject());
mailMessage.setFrom("smarthut.sm@gmail.com");
mailMessage.setFrom(emailConfig.getFrom());
mailMessage.setText(
(isRegistration ? emailConfig.getRegistration() : emailConfig.getResetPassword())
+ " "

View File

@ -20,10 +20,6 @@ public class SensorSaveRequest {
@NotNull private BigDecimal value;
private BigDecimal error;
private BigDecimal typical;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.

View File

@ -9,7 +9,7 @@ import lombok.NonNull;
@Data
@Entity
public class ConfirmationToken {
public final class ConfirmationToken {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@ -55,7 +55,6 @@ public class ConfirmationToken {
if (o == null || getClass() != o.getClass()) return false;
ConfirmationToken that = (ConfirmationToken) o;
return resetPassword == that.resetPassword
&& Objects.equals(id, that.id)
&& confirmToken.equals(that.confirmToken)
&& createdDate.equals(that.createdDate)
&& Objects.equals(user, that.user);
@ -63,6 +62,6 @@ public class ConfirmationToken {
@Override
public int hashCode() {
return Objects.hash(id, confirmToken, createdDate, user, resetPassword);
return Objects.hash(confirmToken, createdDate, user, resetPassword);
}
}

View File

@ -6,6 +6,7 @@ import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.persistence.*;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@ -56,6 +57,7 @@ public class User {
@GsonExclude
@Getter
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<User> guests = new HashSet<>();
@ManyToMany(cascade = CascadeType.DETACH)
@ -66,6 +68,7 @@ public class User {
@GsonExclude
@Getter
@ToString.Exclude
@EqualsAndHashCode.Exclude
private Set<User> hosts = new HashSet<>();
/** Determines whether a guest can access security cameras */

View File

@ -19,20 +19,33 @@ import org.springframework.stereotype.Component;
*/
@Component
public class UpdateTasks {
private final MotionSensorRepository motionSensorRepository;
@Autowired private SensorRepository sensorRepository;
private final SmartPlugRepository smartPlugRepository;
@Autowired private MotionSensorRepository motionSensorRepository;
private final SensorService sensorService;
@Autowired private SmartPlugRepository smartPlugRepository;
private final ThermostatService thermostatService;
@Autowired private SensorService sensorService;
private final MotionSensorService motionSensorService;
@Autowired private ThermostatService thermostatService;
private final SensorSocketEndpoint sensorSocketEndpoint;
@Autowired private MotionSensorService motionSensorService;
@Autowired private SensorSocketEndpoint sensorSocketEndpoint;
@Autowired
public UpdateTasks(
MotionSensorRepository motionSensorRepository,
SmartPlugRepository smartPlugRepository,
SensorService sensorService,
ThermostatService thermostatService,
MotionSensorService motionSensorService,
SensorSocketEndpoint sensorSocketEndpoint) {
this.motionSensorRepository = motionSensorRepository;
this.smartPlugRepository = smartPlugRepository;
this.sensorService = sensorService;
this.thermostatService = thermostatService;
this.motionSensorService = motionSensorService;
this.sensorSocketEndpoint = sensorSocketEndpoint;
}
/** Generates fake sensor updates every two seconds with a +/- 2.5% error */
@Scheduled(fixedRate = 2000)
@ -78,7 +91,7 @@ public class UpdateTasks {
c.forEach(
s ->
sensorSocketEndpoint.queueDeviceUpdate(
s, sensorRepository.findUser(s.getId()), false, null, false));
s, smartPlugRepository.findUser(s.getId()), false, null, false));
}
/** Sends device updates through sensor socket in batch every one second */

View File

@ -148,7 +148,7 @@ public class DevicePropagationService {
}
if (causedByTrigger) {
endpoint.queueDeviceUpdate(device, user, false, user.getId(), false);
endpoint.queueDeviceUpdate(device, user, false, null, false);
}
}
}

View File

@ -4,6 +4,7 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SensorRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -11,24 +12,39 @@ import org.springframework.stereotype.Component;
@Component
public class SensorService {
@Autowired private SensorRepository sensorRepository;
private final SensorRepository sensorRepository;
@Autowired private DeviceService deviceService;
private final DeviceService deviceService;
@Autowired private ThermostatService thermostatService;
private final ThermostatService thermostatService;
@Autowired private SensorSocketEndpoint endpoint;
private final SensorSocketEndpoint endpoint;
private Random ran = new Random();
private final Random ran = new Random();
@Autowired
public SensorService(
SensorRepository sensorRepository,
DeviceService deviceService,
ThermostatService thermostatService,
SensorSocketEndpoint endpoint) {
this.sensorRepository = sensorRepository;
this.deviceService = deviceService;
this.thermostatService = thermostatService;
this.endpoint = endpoint;
}
private void randomJitter(Sensor sensor) {
BigDecimal x =
sensor.getTypical()
.subtract(
sensor.getError()
.divide(BigDecimal.valueOf(2), RoundingMode.CEILING))
.add(
BigDecimal.valueOf(
ran.nextDouble() * sensor.getError().doubleValue() * 2));
double x;
x =
(ran.nextInt(sensor.getTypical().intValue()) + sensor.getError().intValue()) * 0.975
+ 1;
updateValueFromSensor(sensor, BigDecimal.valueOf(x));
updateValueFromSensor(sensor, x);
}
public void sensorFakeUpdate() {

View File

@ -5,6 +5,7 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
import ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Optional;
import java.util.Random;
@ -38,12 +39,18 @@ public class ThermostatService {
private void randomJitter(Thermostat thermostat) {
double x;
x =
(ran.nextInt(thermostat.getTypical().intValue()) + thermostat.getErr().intValue())
* 0.975
+ 1;
updateValueForThermostat(thermostat, BigDecimal.valueOf(x));
BigDecimal x =
thermostat
.getTypical()
.subtract(
thermostat
.getErr()
.divide(BigDecimal.valueOf(2), RoundingMode.CEILING))
.add(
BigDecimal.valueOf(
ran.nextDouble() * thermostat.getErr().doubleValue() * 2));
updateValueForThermostat(thermostat, x);
}
private void updateValueForThermostat(Thermostat thermostat, BigDecimal value) {

View File

@ -13,17 +13,19 @@ spring.jpa.properties.hibernate.format_sql=true
jwt.secret=thiskeymustbeverylongorthethingcomplainssoiamjustgoingtowritehereabunchofgarbageciaomamma
spring.mail.test-connection=true
spring.mail.host=smtp.gmail.com
spring.mail.host=smtp.example.com
spring.mail.port=587
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.username=smarthut.sm@gmail.com
spring.mail.password=dcadvbagqfkwbfts
spring.mail.username=me@example.com
spring.mail.password=example-password
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
email.from=me@example.com
email.registrationSubject=Complete your SmartHut.sm registration
email.registration=To confirm your registration, please click here:
email.registrationPath=http://localhost:8080/register/confirm-account?token=

View File

@ -28,6 +28,8 @@ spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
email.from=${MAIL_FROM}
# Registration email properties
email.registrationSubject=Complete your SmartHut.sm registration
email.registration=To confirm your registration, please click here:

View File

@ -0,0 +1,22 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import org.junit.jupiter.api.Test;
public class EmailConfigurationServiceTests {
@Test
public void test() {
final EmailConfigurationService s = new EmailConfigurationService();
s.setResetPasswordSubject("s");
s.setResetPassword("s");
s.setResetPasswordPath("s");
s.setResetPasswordRedirect("s");
s.setRegistrationRedirect("s");
assertThat(s.getResetPasswordSubject()).isEqualTo("s");
assertThat(s.getResetPassword()).isEqualTo("s");
assertThat(s.getResetPasswordPath()).isEqualTo("s");
assertThat(s.getResetPasswordRedirect()).isEqualTo("s");
assertThat(s.getRegistrationRedirect()).isEqualTo("s");
}
}

View File

@ -0,0 +1,39 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.util.ReflectionTestUtils;
@ExtendWith({MockitoExtension.class})
public class JWTTokenUtilsTests {
@InjectMocks private JWTTokenUtils utils;
@Mock private UserDetails userDetails;
@Test
public void testGenerateToken() {
ReflectionTestUtils.setField(
utils,
"secret",
"One, seven, three, four, six, seven\n"
+ "Three, two, one, four, seven, six, charlie, three\n"
+ "Two, seven, eight, nine, seven, seven, seven\n"
+ "Six, four, three, tango, seven, three, two, victor, seven\n"
+ "Three, one, one, seven, eight, eight, eight, seven, three\n"
+ "Two, four, seven, six, seven, eight, nine\n"
+ "Seven, six, four, three, seven, six\n"
+ "Lock");
when(userDetails.getUsername()).thenReturn("username");
String token = utils.generateToken(userDetails);
assertThat(token).isNotNull();
assertThat(utils.validateToken(token, userDetails)).isTrue();
assertThat(utils.getUsernameFromToken(token)).isEqualTo("username");
}
}

View File

@ -0,0 +1,224 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
import static org.junit.jupiter.api.Assertions.*;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapterFactory;
import org.junit.jupiter.api.Test;
/**
* Copyright (C) 2011 Google Inc.
*
* <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
public final class RuntimeTypeAdapterFactoryTests {
@Test
public void testRuntimeTypeAdapter() {
RuntimeTypeAdapterFactory<BillingInstrument> rta =
RuntimeTypeAdapterFactory.of(BillingInstrument.class)
.registerSubtype(CreditCard.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(rta).create();
CreditCard original = new CreditCard("Jesse", 234);
assertEquals(
"{\"type\":\"CreditCard\",\"cvv\":234,\"ownerName\":\"Jesse\"}",
gson.toJson(original, BillingInstrument.class));
BillingInstrument deserialized =
gson.fromJson(
"{type:'CreditCard',cvv:234,ownerName:'Jesse'}", BillingInstrument.class);
assertEquals("Jesse", deserialized.ownerName);
assertTrue(deserialized instanceof CreditCard);
}
@Test
public void testRuntimeTypeIsBaseType() {
TypeAdapterFactory rta =
RuntimeTypeAdapterFactory.of(BillingInstrument.class, "type", false)
.registerSubtype(BillingInstrument.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(rta).create();
BillingInstrument original = new BillingInstrument("Jesse");
assertEquals(
"{\"type\":\"BillingInstrument\",\"ownerName\":\"Jesse\"}",
gson.toJson(original, BillingInstrument.class));
BillingInstrument deserialized =
gson.fromJson(
"{type:'BillingInstrument',ownerName:'Jesse'}", BillingInstrument.class);
assertEquals("Jesse", deserialized.ownerName);
}
@Test
public void testNullBaseType() {
try {
RuntimeTypeAdapterFactory.of(null);
fail();
} catch (NullPointerException expected) {
}
}
@Test
public void testNullTypeFieldName() {
try {
RuntimeTypeAdapterFactory.of(BillingInstrument.class, null);
fail();
} catch (NullPointerException expected) {
}
}
@Test
public void testNullSubtype() {
RuntimeTypeAdapterFactory<BillingInstrument> rta =
RuntimeTypeAdapterFactory.of(BillingInstrument.class);
try {
rta.registerSubtype(null);
fail();
} catch (NullPointerException expected) {
}
}
@Test
public void testNullLabel() {
RuntimeTypeAdapterFactory<BillingInstrument> rta =
RuntimeTypeAdapterFactory.of(BillingInstrument.class);
try {
rta.registerSubtype(CreditCard.class, null);
fail();
} catch (NullPointerException expected) {
}
}
@Test
public void testDuplicateSubtype() {
RuntimeTypeAdapterFactory<BillingInstrument> rta =
RuntimeTypeAdapterFactory.of(BillingInstrument.class);
rta.registerSubtype(CreditCard.class, "CC");
try {
rta.registerSubtype(CreditCard.class, "Visa");
fail();
} catch (IllegalArgumentException expected) {
}
}
@Test
public void testDuplicateLabel() {
RuntimeTypeAdapterFactory<BillingInstrument> rta =
RuntimeTypeAdapterFactory.of(BillingInstrument.class);
rta.registerSubtype(CreditCard.class, "CC");
try {
rta.registerSubtype(BankTransfer.class, "CC");
fail();
} catch (IllegalArgumentException expected) {
}
}
@Test
public void testDeserializeMissingTypeField() {
TypeAdapterFactory billingAdapter =
RuntimeTypeAdapterFactory.of(BillingInstrument.class)
.registerSubtype(CreditCard.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(billingAdapter).create();
try {
gson.fromJson("{ownerName:'Jesse'}", BillingInstrument.class);
fail();
} catch (JsonParseException expected) {
}
}
@Test
public void testDeserializeMissingSubtype() {
TypeAdapterFactory billingAdapter =
RuntimeTypeAdapterFactory.of(BillingInstrument.class)
.registerSubtype(BankTransfer.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(billingAdapter).create();
try {
gson.fromJson("{type:'CreditCard',ownerName:'Jesse'}", BillingInstrument.class);
fail();
} catch (JsonParseException expected) {
}
}
@Test
public void testSerializeMissingSubtype() {
TypeAdapterFactory billingAdapter =
RuntimeTypeAdapterFactory.of(BillingInstrument.class)
.registerSubtype(BankTransfer.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(billingAdapter).create();
try {
gson.toJson(new CreditCard("Jesse", 456), BillingInstrument.class);
fail();
} catch (JsonParseException expected) {
}
}
@Test
public void testSerializeCollidingTypeFieldName() {
TypeAdapterFactory billingAdapter =
RuntimeTypeAdapterFactory.of(BillingInstrument.class, "cvv")
.registerSubtype(CreditCard.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(billingAdapter).create();
try {
gson.toJson(new CreditCard("Jesse", 456), BillingInstrument.class);
fail();
} catch (JsonParseException expected) {
}
}
@Test
public void testSerializeWrappedNullValue() {
TypeAdapterFactory billingAdapter =
RuntimeTypeAdapterFactory.of(BillingInstrument.class)
.registerSubtype(CreditCard.class)
.registerSubtype(BankTransfer.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(billingAdapter).create();
String serialized =
gson.toJson(new BillingInstrumentWrapper(null), BillingInstrumentWrapper.class);
BillingInstrumentWrapper deserialized =
gson.fromJson(serialized, BillingInstrumentWrapper.class);
assertNull(deserialized.instrument);
}
static class BillingInstrumentWrapper {
BillingInstrument instrument;
BillingInstrumentWrapper(BillingInstrument instrument) {
this.instrument = instrument;
}
}
static class BillingInstrument {
private final String ownerName;
BillingInstrument(String ownerName) {
this.ownerName = ownerName;
}
}
static class CreditCard extends BillingInstrument {
int cvv;
CreditCard(String ownerName, int cvv) {
super(ownerName);
this.cvv = cvv;
}
}
static class BankTransfer extends BillingInstrument {
int bankAccount;
BankTransfer(String ownerName, int bankAccount) {
super(ownerName);
this.bankAccount = bankAccount;
}
}
}

View File

@ -105,7 +105,7 @@ public class DeviceControllerTests {
public void getAllEmptyTest() {
when(mockPrincipal.getName()).thenReturn("user");
List<Device> l = deviceController.getAll(user.getId(), mockPrincipal);
assertThat(l.isEmpty());
assertThat(l.isEmpty()).isTrue();
}
@DisplayName("check if list contains elements added")
@ -118,7 +118,6 @@ public class DeviceControllerTests {
Device d2 = new SmartPlug();
deviceService.saveAsOwner(d2, mockPrincipal.getName());
assertThat(
deviceController.getAll(user.getId(), mockPrincipal).containsAll(List.of(d1, d2)));
assertThat(deviceController.getAll(user.getId(), mockPrincipal)).isNotNull();
}
}

View File

@ -0,0 +1,64 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.ArgumentMatchers.anyIterable;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.DeviceService;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.test.context.support.WithMockUser;
@ExtendWith(MockitoExtension.class)
@WithMockUser(username = "user")
public class InputDeviceConnectionControllerTests {
@Mock private DeviceService deviceService;
@Mock private KnobDimmerRepository inputRepository;
@Mock private DimmableRepository<Dimmable> outputRepository;
private KnobDimmerController knobDimmerController;
@Mock private Principal mockPrincipal;
@BeforeEach
public void setup() {
when(mockPrincipal.getName()).thenReturn("user");
}
@Test
public void testConnection() throws NotFoundException {
KnobDimmer knobDimmer = new KnobDimmer();
DimmableLight dimmableLight = new DimmableLight();
knobDimmer.addDimmable(dimmableLight);
when(inputRepository.findByIdAndUsername(anyLong(), anyString()))
.thenReturn(java.util.Optional.of(knobDimmer));
when(outputRepository.findByIdAndUsername(anyLong(), anyString()))
.thenReturn(java.util.Optional.of(dimmableLight));
when(deviceService.saveAllAsOwner(anyIterable(), anyString()))
.thenReturn(List.of(new DimmableLight()));
List<Long> l = new ArrayList<>();
l.add(10L);
knobDimmerController =
new KnobDimmerController(inputRepository, outputRepository, deviceService);
assertDoesNotThrow(() -> knobDimmerController.addLight(1L, l, mockPrincipal));
}
}

View File

@ -58,7 +58,7 @@ public class RegularLightControllerTests {
@Test
public void testGetAll() {
when(regularLightRepository.findAll()).thenReturn(List.of());
assertThat(regularLightController.findAll().isEmpty());
assertThat(regularLightController.findAll()).isEmpty();
}
@Test

View File

@ -42,17 +42,29 @@ public class RoomControllerTests {
private final User u;
private final User h;
public RoomControllerTests() {
u = new User();
u.setName("user");
u.setUsername("user");
u.setId(1L);
h = new User();
h.setUsername("host");
h.setId(2L);
u.getHosts().add(h);
h.getGuests().add(u);
}
@Test
public void testGetAll() throws NotFoundException {
when(mockPrincipal.getName()).thenReturn("user");
when(roomRepository.findByUsername("user")).thenReturn(List.of());
when(roomRepository.findByUserId(2L)).thenReturn(List.of());
when(userRepository.findById(2L)).thenReturn(Optional.of(h));
when(userRepository.findByUsername("user")).thenReturn(u);
assertThat(roomController.findAll(null, mockPrincipal)).isEmpty();
assertThat(roomController.findAll(2L, mockPrincipal)).isEmpty();
}
@Test
@ -67,10 +79,20 @@ public class RoomControllerTests {
}
private void equalToRequest(Room created, RoomSaveRequest a) {
assertThat(created.getName()).isEqualTo(a.getName());
if (a.getName() != null) {
assertThat(created.getName()).isEqualTo(a.getName());
}
assertThat(created.getUserId()).isEqualTo(1L);
assertThat(created.getIcon()).isEqualTo(a.getIcon());
assertThat(created.getImage()).isEqualTo(a.getImage());
if (a.getIcon() != null) {
assertThat(created.getIcon()).isEqualTo(a.getIcon());
}
if (a.getImage() != null) {
if (a.getImage().isEmpty()) {
assertThat(created.getImage()).isNull();
} else {
assertThat(created.getImage()).isEqualTo(a.getImage());
}
}
}
@Test
@ -97,13 +119,21 @@ public class RoomControllerTests {
when(roomRepository.findByIdAndUsername(42L, "user")).thenReturn(Optional.of(old));
when(roomRepository.findByIdAndUsername(43L, "user")).thenReturn(Optional.empty());
RoomSaveRequest roomSaveRequest = new RoomSaveRequest(42L, Icon.BEER, null, "New Room");
RoomSaveRequest roomSaveRequest = new RoomSaveRequest(42L, Icon.BEER, "image", "New Room");
Room created =
roomController.update(roomSaveRequest.getId(), roomSaveRequest, mockPrincipal);
assertThat(created.getId()).isEqualTo(42L);
equalToRequest(created, roomSaveRequest);
roomSaveRequest.setImage("");
roomSaveRequest.setIcon(null);
roomSaveRequest.setName(null);
created = roomController.update(roomSaveRequest.getId(), roomSaveRequest, mockPrincipal);
assertThat(created.getId()).isEqualTo(42L);
equalToRequest(created, roomSaveRequest);
roomSaveRequest.setId(43L);
assertThatThrownBy(
() ->
@ -119,11 +149,15 @@ public class RoomControllerTests {
final Room toDelete = new Room();
toDelete.setId(42L);
final Device d = new Thermostat();
d.setId(2020L);
doNothing().when(switchRepository).deleteAllByRoomId(42L);
doNothing().when(knobDimmerRepository).deleteAllByRoomId(42L);
doNothing().when(buttonDimmerRepository).deleteAllByRoomId(42L);
when(roomRepository.findByIdAndUsername(42L, "user")).thenReturn(Optional.of(toDelete));
when(deviceService.findAll(42L, null, "user")).thenReturn(List.of());
when(deviceService.findAll(42L, null, "user")).thenReturn(List.of(d));
doNothing().when(deviceService).deleteByIdAsOwner(2020L, "user");
doNothing().when(roomRepository).delete(toDelete);
try {
@ -132,4 +166,11 @@ public class RoomControllerTests {
fail(e.getMessage());
}
}
@Test
public void testGetDevices() throws NotFoundException {
when(mockPrincipal.getName()).thenReturn("user");
when(deviceService.findAll(2020L, 10L, "user")).thenReturn(List.of());
assertThat(roomController.getDevices(2020L, mockPrincipal, 10L)).isNotNull();
}
}

View File

@ -69,12 +69,7 @@ public class SensorControllerTests {
final SensorSaveRequest toSend =
new SensorSaveRequest(
Sensor.SensorType.TEMPERATURE,
BigDecimal.ZERO,
BigDecimal.ZERO,
BigDecimal.ZERO,
42L,
"Test sensor");
Sensor.SensorType.TEMPERATURE, BigDecimal.ZERO, 42L, "Test sensor");
final Sensor created = sensorController.create(toSend, mockPrincipal);
checkSensorAgainstRequest(created, toSend);

View File

@ -30,13 +30,7 @@ public class SensorSaveRequestTests {
@DisplayName("test constructor")
public void testConstructorNotEmpty() {
SensorSaveRequest newSaveRequest =
new SensorSaveRequest(
Sensor.SensorType.HUMIDITY,
new BigDecimal(12),
BigDecimal.ZERO,
BigDecimal.ZERO,
12L,
"name");
new SensorSaveRequest(Sensor.SensorType.HUMIDITY, new BigDecimal(12), 12L, "name");
assertNotNull(newSaveRequest.getSensor());
assertNotNull(newSaveRequest.getName());
assertNotNull(newSaveRequest.getRoomId());

View File

@ -3,6 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Date;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@ -47,7 +48,7 @@ public class ConfirmationTokenTests {
@DisplayName("test setTimeStamp")
public void testSetTimeStamp() {
Date date = new Date();
date.setTime(86400000l);
date.setTime(86400000L);
token.setCreatedDate(date);
assertEquals(date, token.getCreatedDate());
}
@ -66,12 +67,27 @@ public class ConfirmationTokenTests {
public void equals() {
User user = new User();
user.setName("Tizio Sempronio");
user.setId(42l);
user.setId(42L);
user.setUsername("xXCoolUserNameXx");
user.setEmail("realMail@service.ext");
user.setPassword("alpaca");
ConfirmationToken t = new ConfirmationToken(user);
ConfirmationToken t = new ConfirmationToken();
t.setUser(user);
assertFalse(t.equals(token));
assertNotEquals(t, token);
}
@Test
public void testEqualsHashCode() {
final User u = new User();
u.setId(1L);
final User t = new User();
t.setId(2L);
EqualsVerifier.forClass(ConfirmationToken.class)
.withNonnullFields("createdDate")
.withNonnullFields("confirmToken")
.withPrefabValues(User.class, u, t)
.verify();
assertDoesNotThrow(() -> new ConfirmationToken().hashCode());
}
}

View File

@ -0,0 +1,39 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.scheduled;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SmartPlug;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SmartPlugRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class UpdateTasksTests {
@InjectMocks private UpdateTasks updateTasks;
@Mock private SmartPlugRepository smartPlugRepository;
@Mock private SensorSocketEndpoint sensorSocketEndpoint;
@Test
public void testSmartPlugConsumptionFakeUpdate() {
final User u = new User();
final SmartPlug s = new SmartPlug();
s.setId(20L);
doReturn(u).when(smartPlugRepository).findUser(20L);
doNothing()
.when(smartPlugRepository)
.updateTotalConsumption(SmartPlug.AVERAGE_CONSUMPTION_KW);
when(smartPlugRepository.findByOn(true)).thenReturn(List.of(s));
doNothing().when(sensorSocketEndpoint).queueDeviceUpdate(s, u, false, null, false);
assertDoesNotThrow(() -> updateTasks.smartPlugConsumptionFakeUpdate());
}
}

View File

@ -1,5 +1,6 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
@ -38,6 +39,6 @@ public class DevicePopulationServiceTests {
list.add(t1);
list.add(light2);
doNothing().when(populationService).populateMeasuredTemperature(t1);
service.populateComputedFields(list);
assertDoesNotThrow(() -> service.populateComputedFields(list));
}
}

View File

@ -210,9 +210,7 @@ public class DevicePropagationServiceTests {
doAnswer(i -> counter[0]++)
.when(endpoint)
.queueDeviceUpdate(d, guest, false, host.getId(), false);
doAnswer(i -> counter[0]++)
.when(endpoint)
.queueDeviceUpdate(d, host, false, host.getId(), false);
doAnswer(i -> counter[0]++).when(endpoint).queueDeviceUpdate(d, host, false, null, false);
devicePropagationService.propagateUpdateAsOwner(d, "host", false);
assertThat(counter[0]).isEqualTo(1);

View File

@ -174,7 +174,7 @@ public class DeviceServiceTests {
currentDeviceService.saveAllAsOwner(devices, "user", true, false);
assertThat(count[0]).isEqualTo(0);
currentDeviceService.saveAllAsOwner(devices, "user", false, false);
currentDeviceService.saveAllAsOwner(devices, "user");
assertThat(count[0]).isEqualTo(2);
}

View File

@ -0,0 +1,66 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SensorRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User;
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.test.context.support.WithMockUser;
@ExtendWith(MockitoExtension.class)
@WithMockUser(username = "user")
public class SensorServiceTests {
@InjectMocks private SensorService sensorService;
@Mock private DeviceService deviceService;
@Mock private SensorSocketEndpoint endpoint;
@Mock private SensorRepository sensorRepository;
@Mock private ThermostatService thermostatService;
@Test
public void testRandomJitter() {
final Sensor s = new Sensor();
s.setTypical(BigDecimal.ZERO);
s.setError(BigDecimal.ONE);
s.setId(42L);
final User u = new User();
u.setUsername("user");
doNothing().when(thermostatService).updateStates();
when(deviceService.saveAsOwner(s, "user")).thenReturn(s);
when(sensorRepository.findUser(42L)).thenReturn(u);
when(sensorRepository.findAll()).thenReturn(List.of(s));
doNothing().when(endpoint).queueDeviceUpdate(s, u, false, null, false);
assertDoesNotThrow(() -> sensorService.sensorFakeUpdate());
}
@Test
public void testSimulation() {
final SensorService se = Mockito.spy(sensorService);
final Sensor s = new Sensor();
s.setError(BigDecimal.ONE);
s.setTypical(BigDecimal.ZERO);
doReturn(s).when(se).update(s);
se.updateSimulationFromSensor(s, null, null);
assertThat(s.getError()).isEqualTo(BigDecimal.ONE);
assertThat(s.getTypical()).isEqualTo(BigDecimal.ZERO);
se.updateSimulationFromSensor(s, BigDecimal.ZERO, BigDecimal.ONE);
assertThat(s.getError()).isEqualTo(BigDecimal.ZERO);
assertThat(s.getTypical()).isEqualTo(BigDecimal.ONE);
}
}