SEBSERV-136 battary and wlan status indicator impl and tests

This commit is contained in:
anhefti 2020-11-25 11:57:36 +01:00
parent 7c5a2da59d
commit 448c4d26b5
22 changed files with 478 additions and 154 deletions

View file

@ -101,6 +101,9 @@ public final class API {
public static final String EXAM_API_EVENT_ENDPOINT = "/seblog";
public static final String LOG_EVENT_TAG_BATTERY_STATUS = "<battery>";
public static final String LOG_EVENT_TAG_WLAN_STATUS = "<wlan>";
// *************************
// ** Domain Object API
// *************************

View file

@ -35,23 +35,31 @@ public final class Indicator implements Entity {
public static final String FILTER_ATTR_EXAM_ID = "examId";
public enum IndicatorType {
LAST_PING(Names.LAST_PING, true, true),
ERROR_COUNT(Names.ERROR_COUNT, true, false),
WARN_COUNT(Names.WARN_COUNT, true, false),
INFO_COUNT(Names.INFO_COUNT, true, false);
LAST_PING(Names.LAST_PING, true, true, false, false),
ERROR_COUNT(Names.ERROR_COUNT, true, false, true, false),
WARN_COUNT(Names.WARN_COUNT, true, false, true, false),
INFO_COUNT(Names.INFO_COUNT, true, false, true, false),
BATTERY_STATUS(Names.BATTERY_STATUS, true, true, true, true),
WLAN_STATUS(Names.WLAN_STATUS, true, true, true, true);
public final String name;
public final boolean integerValue;
public final boolean showOnlyInActiveState;
public final boolean tags;
public final boolean tagsReadonly;
IndicatorType(
final String name,
final boolean integerValue,
final boolean showOnlyInActiveState) {
final boolean showOnlyInActiveState,
final boolean tags,
final boolean tagsReadonly) {
this.name = name;
this.integerValue = integerValue;
this.showOnlyInActiveState = showOnlyInActiveState;
this.tags = tags;
this.tagsReadonly = tagsReadonly;
}
@Override
@ -64,6 +72,8 @@ public final class Indicator implements Entity {
String ERROR_COUNT = "ERROR_COUNT";
String WARN_COUNT = "WARN_COUNT";
String INFO_COUNT = "INFO_COUNT";
String BATTERY_STATUS = "BATTERY_STATUS";
String WLAN_STATUS = "WLAN_STATUS";
}
}

View file

@ -1,133 +0,0 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.SqlCriterion;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper;
public abstract class AbstractLogLevelCountIndicator extends AbstractClientIndicator {
private final Set<EventType> observed;
private final List<Integer> eventTypeIds;
private final ClientEventRecordMapper clientEventRecordMapper;
protected String[] tags;
protected AbstractLogLevelCountIndicator(
final ClientEventRecordMapper clientEventRecordMapper,
final EventType... eventTypes) {
this.clientEventRecordMapper = clientEventRecordMapper;
this.observed = Collections.unmodifiableSet(EnumSet.of(eventTypes[0], eventTypes));
this.eventTypeIds = Utils.immutableListOf(Arrays.stream(eventTypes)
.map(et -> et.id)
.collect(Collectors.toList()));
}
@Override
public void init(final Indicator indicatorDefinition, final Long connectionId, final boolean cachingEnabled) {
super.init(indicatorDefinition, connectionId, cachingEnabled);
if (indicatorDefinition == null || indicatorDefinition.tags == null) {
this.tags = null;
} else {
this.tags = StringUtils.split(indicatorDefinition.tags, Constants.COMMA);
for (int i = 0; i < this.tags.length; i++) {
this.tags[i] = Constants.ANGLE_BRACE_OPEN + this.tags[i] + Constants.ANGLE_BRACE_CLOSE;
}
}
}
@Override
public double computeValueAt(final long timestamp) {
final Long errors = this.clientEventRecordMapper.countByExample()
.where(ClientEventRecordDynamicSqlSupport.clientConnectionId, isEqualTo(this.connectionId))
.and(ClientEventRecordDynamicSqlSupport.type, isIn(this.eventTypeIds))
.and(ClientEventRecordDynamicSqlSupport.serverTime, isLessThan(timestamp))
.and(
ClientEventRecordDynamicSqlSupport.text,
isLikeWhenPresent(getfirstTagSQL()),
getSubTagSQL())
.build()
.execute();
return errors.doubleValue();
}
private String getfirstTagSQL() {
if (this.tags == null || this.tags.length == 0) {
return null;
}
return Utils.toSQLWildcard(this.tags[0]);
}
@SuppressWarnings("unchecked")
private SqlCriterion<String>[] getSubTagSQL() {
if (this.tags == null || this.tags.length == 0 || this.tags.length == 1) {
return new SqlCriterion[0];
}
final SqlCriterion<String>[] result = new SqlCriterion[this.tags.length - 1];
for (int i = 1; i < this.tags.length; i++) {
result[i - 1] = SqlBuilder.or(
ClientEventRecordDynamicSqlSupport.text,
isLike(Utils.toSQLWildcard(this.tags[1])));
}
return result;
}
@Override
public void notifyValueChange(final ClientEvent event) {
if (this.tags == null || this.tags.length == 0) {
this.currentValue = getValue() + 1d;
} else if (hasTag(event.text)) {
this.currentValue = getValue() + 1d;
}
}
private boolean hasTag(final String text) {
if (text == null) {
return false;
}
for (int i = 0; i < this.tags.length; i++) {
if (text.startsWith(this.tags[i])) {
return true;
}
}
return false;
}
@Override
public Set<EventType> observedEvents() {
return this.observed;
}
}

View file

@ -24,6 +24,7 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.PendingNotificationIndication;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.PingIntervalClientIndicator;
public class ClientConnectionDataInternal extends ClientConnectionData {
@ -74,7 +75,7 @@ public class ClientConnectionDataInternal extends ClientConnectionData {
@Override
@JsonProperty(ATTR_MISSING_PING)
public Boolean getMissingPing() {
return this.pingIndicator.missingPing;
return this.pingIndicator.isMissingPing();
}
@Override

View file

@ -28,6 +28,7 @@ import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.IndicatorDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.ClientIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.PingIntervalClientIndicator;
@Lazy
@Component
@ -93,7 +94,7 @@ public class ClientIndicatorFactory {
if (!pingIndicatorAvailable) {
final PingIntervalClientIndicator pingIndicator = this.applicationContext
.getBean(PingIntervalClientIndicator.class);
pingIndicator.hidden = true;
pingIndicator.setHidden();
final Indicator indicator = new Indicator(
null,
clientConnection.examId,

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.gbl.util.Utils;
public abstract class AbstractLogIndicator extends AbstractClientIndicator {
protected final Set<EventType> observed;
protected final List<Integer> eventTypeIds;
protected String[] tags;
protected AbstractLogIndicator(final EventType... eventTypes) {
this.observed = Collections.unmodifiableSet(EnumSet.of(eventTypes[0], eventTypes));
this.eventTypeIds = Utils.immutableListOf(Arrays.stream(eventTypes)
.map(et -> et.id)
.collect(Collectors.toList()));
}
@Override
public void init(final Indicator indicatorDefinition, final Long connectionId, final boolean cachingEnabled) {
super.init(indicatorDefinition, connectionId, cachingEnabled);
if (indicatorDefinition == null || indicatorDefinition.tags == null) {
this.tags = null;
} else {
this.tags = StringUtils.split(indicatorDefinition.tags, Constants.COMMA);
for (int i = 0; i < this.tags.length; i++) {
this.tags[i] = Constants.ANGLE_BRACE_OPEN + this.tags[i] + Constants.ANGLE_BRACE_CLOSE;
}
}
}
protected boolean hasTag(final String text) {
if (text == null) {
return false;
}
for (int i = 0; i < this.tags.length; i++) {
if (text.startsWith(this.tags[i])) {
return true;
}
}
return false;
}
@Override
public Set<EventType> observedEvents() {
return this.observed;
}
}

View file

@ -0,0 +1,92 @@
/*
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.SqlCriterion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper;
public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicator {
private static final Logger log = LoggerFactory.getLogger(AbstractLogLevelCountIndicator.class);
protected final ClientEventRecordMapper clientEventRecordMapper;
protected AbstractLogLevelCountIndicator(
final ClientEventRecordMapper clientEventRecordMapper,
final EventType... eventTypes) {
super(eventTypes);
this.clientEventRecordMapper = clientEventRecordMapper;
}
@Override
public void notifyValueChange(final ClientEvent event) {
if (this.tags == null || this.tags.length == 0) {
this.currentValue = getValue() + 1d;
} else if (hasTag(event.text)) {
this.currentValue = getValue() + 1d;
}
}
@Override
public double computeValueAt(final long timestamp) {
try {
final Long errors = this.clientEventRecordMapper.countByExample()
.where(ClientEventRecordDynamicSqlSupport.clientConnectionId, isEqualTo(this.connectionId))
.and(ClientEventRecordDynamicSqlSupport.type, isIn(this.eventTypeIds))
.and(ClientEventRecordDynamicSqlSupport.serverTime, isLessThan(timestamp))
.and(
ClientEventRecordDynamicSqlSupport.text,
isLikeWhenPresent(getfirstTagSQL()),
getSubTagSQL())
.build()
.execute();
return errors.doubleValue();
} catch (final Exception e) {
log.error("Failed to get indicator count from persistent storage: ", e);
return this.currentValue;
}
}
private String getfirstTagSQL() {
if (this.tags == null || this.tags.length == 0) {
return null;
}
return Utils.toSQLWildcard(this.tags[0]);
}
@SuppressWarnings("unchecked")
private SqlCriterion<String>[] getSubTagSQL() {
if (this.tags == null || this.tags.length == 0 || this.tags.length == 1) {
return new SqlCriterion[0];
}
final SqlCriterion<String>[] result = new SqlCriterion[this.tags.length - 1];
for (int i = 1; i < this.tags.length; i++) {
result[i - 1] = SqlBuilder.or(
ClientEventRecordDynamicSqlSupport.text,
isLike(Utils.toSQLWildcard(this.tags[1])));
}
return result;
}
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import java.util.List;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.SqlCriterion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordDynamicSqlSupport;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator {
private static final Logger log = LoggerFactory.getLogger(AbstractLogNumberIndicator.class);
protected final ClientEventRecordMapper clientEventRecordMapper;
protected AbstractLogNumberIndicator(
final ClientEventRecordMapper clientEventRecordMapper,
final EventType... eventTypes) {
super(eventTypes);
this.clientEventRecordMapper = clientEventRecordMapper;
}
@Override
public void notifyValueChange(final ClientEvent event) {
if (this.tags == null || this.tags.length == 0) {
this.currentValue = event.getValue();
} else if (hasTag(event.text)) {
this.currentValue = event.getValue();
}
}
@Override
public double computeValueAt(final long timestamp) {
try {
final List<ClientEventRecord> execute = this.clientEventRecordMapper.selectByExample()
.where(ClientEventRecordDynamicSqlSupport.clientConnectionId, isEqualTo(this.connectionId))
.and(ClientEventRecordDynamicSqlSupport.type, isIn(this.eventTypeIds))
.and(ClientEventRecordDynamicSqlSupport.serverTime, isLessThan(timestamp))
.and(
ClientEventRecordDynamicSqlSupport.text,
isLikeWhenPresent(getfirstTagSQL()),
getSubTagSQL())
.orderBy(ClientEventRecordDynamicSqlSupport.serverTime.descending())
.build()
.execute();
return execute.get(execute.size() - 1).getNumericValue().doubleValue();
} catch (final Exception e) {
log.error("Failed to get indicator number from persistent storage: ", e);
return this.currentValue;
}
}
private String getfirstTagSQL() {
if (this.tags == null || this.tags.length == 0) {
return null;
}
return Utils.toSQLWildcard(this.tags[0]);
}
@SuppressWarnings("unchecked")
private SqlCriterion<String>[] getSubTagSQL() {
if (this.tags == null || this.tags.length == 0 || this.tags.length == 1) {
return new SqlCriterion[0];
}
final SqlCriterion<String>[] result = new SqlCriterion[this.tags.length - 1];
for (int i = 1; i < this.tags.length; i++) {
result[i - 1] = SqlBuilder.or(
ClientEventRecordDynamicSqlSupport.text,
isLike(Utils.toSQLWildcard(this.tags[1])));
}
return result;
}
}

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
import static org.mybatis.dynamic.sql.SqlBuilder.isLessThan;

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper;
@Lazy
@Component(IndicatorType.Names.BATTERY_STATUS)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class BatteryStatusIndicator extends AbstractLogNumberIndicator {
protected BatteryStatusIndicator(final ClientEventRecordMapper clientEventRecordMapper) {
super(clientEventRecordMapper, EventType.INFO_LOG);
super.tags = new String[] { API.LOG_EVENT_TAG_BATTERY_STATUS };
}
@Override
public IndicatorType getType() {
return IndicatorType.BATTERY_STATUS;
}
}

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Lazy;

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Lazy;

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import java.math.BigDecimal;
import java.util.Comparator;
@ -20,6 +20,8 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.annotation.JsonIgnore;
import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
@ -62,6 +64,21 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
}
}
@JsonIgnore
public final boolean isMissingPing() {
return this.missingPing;
}
@JsonIgnore
public final boolean isHidden() {
return this.hidden;
}
@JsonIgnore
public final void setHidden() {
this.hidden = true;
}
@Override
public IndicatorType getType() {
return IndicatorType.LAST_PING;

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator.IndicatorType;
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper;
@Lazy
@Component(IndicatorType.Names.WLAN_STATUS)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class WLANStatusIndicator extends AbstractLogNumberIndicator {
protected WLANStatusIndicator(final ClientEventRecordMapper clientEventRecordMapper) {
super(clientEventRecordMapper, EventType.INFO_LOG);
super.tags = new String[] { API.LOG_EVENT_TAG_WLAN_STATUS };
}
@Override
public IndicatorType getType() {
return IndicatorType.WLAN_STATUS;
}
}

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Lazy;

View file

@ -916,6 +916,10 @@ public class UserAPITest extends AdministrationAPIIntegrationTester {
.header("Authorization", "Bearer " + examAdminToken))
.andExpect(status().isForbidden());
if ("0".equals(timeNow)) {
System.out.println("******");
}
// With SEB Administrator it should work
final String sebAdminToken = getSebAdminAccess();
final EntityProcessingReport report = this.jsonMapper.readValue(

View file

@ -36,9 +36,9 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecord
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientEventRecordMapper;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientConnectionRecord;
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ClientEventRecord;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.AbstractPingIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.ClientConnectionDataInternal;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.ExamSessionCacheService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.AbstractPingIndicator;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" })
public class SebConnectionTest extends ExamAPIIntegrationTester {

View file

@ -29,7 +29,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientEventDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.AbstractLogLevelCountIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.AbstractLogIndicator;
import ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator.AbstractLogLevelCountIndicator;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql", "classpath:data-test-additional.sql" })
public class ClientEventServiceTest extends AdministrationAPIIntegrationTester {
@ -160,4 +161,55 @@ public class ClientEventServiceTest extends AdministrationAPIIntegrationTester {
}
@Test
public void testBatteryStatusIndicator() {
final ClientConnection connection = this.clientConnectionDAO
.createNew(new ClientConnection(null, 1L, 2L, ConnectionStatus.ACTIVE, "token3", "userId", "", "", 1L,
null, false))
.getOrThrow();
assertNotNull(connection.id);
final ClientConnectionData connectionData =
this.sebClientConnectionService.getExamSessionService().getConnectionData("token3")
.getOrThrow();
assertNotNull(connectionData);
final Optional<? extends IndicatorValue> findFirst = connectionData.indicatorValues
.stream()
.filter(indicator -> indicator.getType() == IndicatorType.BATTERY_STATUS)
.findFirst();
assertTrue(findFirst.isPresent());
final IndicatorValue clientIndicator = findFirst.get();
assertEquals("0", IndicatorValue.getDisplayValue(clientIndicator));
this.sebClientConnectionService.notifyClientEvent(
"token3",
new ClientEvent(null, connection.id, EventType.INFO_LOG, 1L, 1L, 1.0, "some info other"));
this.sebClientConnectionService.notifyClientEvent(
"token3",
new ClientEvent(null, connection.id, EventType.INFO_LOG, 1L, 1L, 1.0, "<vip> some info other"));
assertEquals("0", IndicatorValue.getDisplayValue(clientIndicator));
this.sebClientConnectionService.notifyClientEvent(
"token3",
new ClientEvent(null, connection.id, EventType.INFO_LOG, 1L, 1L, 90.0, "<battery> some info other"));
assertEquals("90", IndicatorValue.getDisplayValue(clientIndicator));
this.sebClientConnectionService.notifyClientEvent(
"token3",
new ClientEvent(null, connection.id, EventType.INFO_LOG, 1L, 1L, 40.0, "<battery> some info other"));
assertEquals("40", IndicatorValue.getDisplayValue(clientIndicator));
// test reset indicator value and load it from persistent storage
((AbstractLogIndicator) clientIndicator).reset();
assertEquals("40", IndicatorValue.getDisplayValue(clientIndicator));
}
}

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 ETH Zürich, Educational Development and Technology (LET)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import ch.ethz.seb.sebserver.gbl.api.JSONMapper;
public class IndicatorValueJSONTest {
@Test
public void testJSONForExtendedIndicatorValue() throws JsonProcessingException {
final JSONMapper jsonMapper = new JSONMapper();
final ErrorLogCountClientIndicator indicator = new ErrorLogCountClientIndicator(null);
final String json = jsonMapper.writeValueAsString(indicator);
assertEquals("{\"indicatorType\":\"ERROR_COUNT\",\"indicatorValue\":\"NaN\"}", json);
}
}

View file

@ -6,11 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl;
package ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator;
import static org.junit.Assert.assertEquals;
import org.joda.time.DateTimeUtils;
import org.junit.After;
import org.junit.Test;
import org.mockito.Mockito;
@ -21,10 +22,15 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.ClientEventExtensionMapp
public class PingIntervalClientIndicatorTest {
@After
public void cleanup() {
DateTimeUtils.setCurrentMillisProvider(DateTimeUtils.SYSTEM_MILLIS_PROVIDER);
}
@Test
public void testCreation() {
DateTimeUtils.setCurrentMillisFixed(1);
DateTimeUtils.setCurrentMillisProvider(() -> 1L);
final ClientEventExtensionMapper clientEventExtensionMapper = Mockito.mock(ClientEventExtensionMapper.class);
@ -35,7 +41,8 @@ public class PingIntervalClientIndicatorTest {
@Test
public void testInterval() {
DateTimeUtils.setCurrentMillisFixed(1);
DateTimeUtils.setCurrentMillisProvider(() -> 1L);
final ClientEventExtensionMapper clientEventExtensionMapper = Mockito.mock(ClientEventExtensionMapper.class);
@ -43,14 +50,14 @@ public class PingIntervalClientIndicatorTest {
new PingIntervalClientIndicator(clientEventExtensionMapper);
assertEquals("0.0", String.valueOf(pingIntervalClientIndicator.getValue()));
DateTimeUtils.setCurrentMillisFixed(10);
DateTimeUtils.setCurrentMillisProvider(() -> 10L);
assertEquals("9.0", String.valueOf(pingIntervalClientIndicator.getValue()));
}
@Test
public void testSerialization() throws JsonProcessingException {
DateTimeUtils.setCurrentMillisFixed(1);
DateTimeUtils.setCurrentMillisProvider(() -> 1L);
final ClientEventExtensionMapper clientEventExtensionMapper = Mockito.mock(ClientEventExtensionMapper.class);

View file

@ -14,7 +14,8 @@ INSERT IGNORE INTO exam VALUES
INSERT IGNORE INTO indicator VALUES
(1, 2, 'LAST_PING', 'Ping', 'dcdcdc', null, null),
(2, 2, 'ERROR_COUNT', 'errors', 'dcdcdc', null, null),
(3, 2, 'INFO_COUNT', 'errors <vip,top>', 'dcdcdc', null, 'vip,top')
(3, 2, 'INFO_COUNT', 'errors <vip,top>', 'dcdcdc', null, 'vip,top'),
(4, 2, 'BATTERY_STATUS', 'battery status', 'dcdcdc', null, 'battery')
;
INSERT IGNORE INTO threshold VALUES