More Unit Tests and better logging
This commit is contained in:
parent
8112ee1993
commit
a9acb1b915
11 changed files with 250 additions and 19 deletions
|
@ -68,6 +68,7 @@ public final class Constants {
|
|||
public static final Character EQUALITY_SIGN = '=';
|
||||
public static final Character LIST_SEPARATOR_CHAR = COMMA;
|
||||
public static final Character COMPLEX_VALUE_SEPARATOR = COLON;
|
||||
public static final Character HASH_TAG = '#';
|
||||
|
||||
public static final String NULL = "null";
|
||||
public static final String PERCENTAGE_STRING = Constants.PERCENTAGE.toString();
|
||||
|
@ -80,6 +81,7 @@ public final class Constants {
|
|||
public static final String URL_PORT_SEPARATOR = COLON.toString();
|
||||
public static final String URL_ADDRESS_SEPARATOR = COLON.toString() + SLASH.toString() + SLASH.toString();
|
||||
public static final String URL_PATH_SEPARATOR = SLASH.toString();
|
||||
public static final String HASH_TAG_STRING = HASH_TAG.toString();
|
||||
|
||||
public static final String DYN_HTML_ATTR_OPEN = "%%_";
|
||||
public static final String DYN_HTML_ATTR_CLOSE = "_%%";
|
||||
|
|
|
@ -34,6 +34,8 @@ import java.util.function.Predicate;
|
|||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
@ -540,10 +542,15 @@ public final class Utils {
|
|||
|
||||
public static RGB toRGB(final String rgbString) {
|
||||
if (StringUtils.isNotBlank(rgbString)) {
|
||||
|
||||
final String rgbVal = (rgbString.startsWith(Constants.HASH_TAG_STRING))
|
||||
? rgbString.substring(1)
|
||||
: rgbString;
|
||||
|
||||
return new RGB(
|
||||
Integer.parseInt(rgbString.substring(0, 2), 16),
|
||||
Integer.parseInt(rgbString.substring(2, 4), 16),
|
||||
Integer.parseInt(rgbString.substring(4, 6), 16));
|
||||
Integer.parseInt(rgbVal.substring(0, 2), 16),
|
||||
Integer.parseInt(rgbVal.substring(2, 4), 16),
|
||||
Integer.parseInt(rgbVal.substring(4, 6), 16));
|
||||
} else {
|
||||
return new RGB(255, 255, 255);
|
||||
}
|
||||
|
@ -564,7 +571,11 @@ public final class Utils {
|
|||
return e.getCause().getClass().getName() + " : " + e.getCause().getMessage();
|
||||
}
|
||||
|
||||
public static boolean darkColor(final RGB rgb) {
|
||||
/** Indicates if a dark background or contrast color must be used for the given text or foreground color.
|
||||
*
|
||||
* @param rgb foreground or text color
|
||||
* @return true of the background color for given foreground color shall be dark or false if it shall be light */
|
||||
public static boolean darkColorContrast(final RGB rgb) {
|
||||
return rgb.red + rgb.green + rgb.blue > DARK_COLOR_THRESHOLD;
|
||||
}
|
||||
|
||||
|
@ -596,6 +607,10 @@ public final class Utils {
|
|||
}
|
||||
|
||||
public static String toAppFormUrlEncodedBody(final MultiValueMap<String, String> attributes) {
|
||||
if (attributes == null) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
return attributes
|
||||
.entrySet()
|
||||
.stream()
|
||||
|
@ -619,7 +634,11 @@ public final class Utils {
|
|||
.toString();
|
||||
}
|
||||
|
||||
public static String toAppFormUrlEncodedBody(final String name, final Collection<String> array) {
|
||||
public static String toAppFormUrlEncodedBody(@NotNull final String name, final Collection<String> array) {
|
||||
if (array == null) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
final String _name = name.contains(String.valueOf(Constants.SQUARE_BRACE_OPEN)) || array.size() <= 1
|
||||
? name
|
||||
: name + Constants.SQUARE_BRACE_OPEN + Constants.SQUARE_BRACE_CLOSE;
|
||||
|
@ -704,4 +723,16 @@ public final class Utils {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static StringBuilder formatStackTracePrint(final int length, final StackTraceElement[] stackTrace) {
|
||||
final int size = Math.min(stackTrace.length, length);
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < size; i++) {
|
||||
builder.append(" --> ").append(stackTrace[i].toString());
|
||||
if (i + 1 < size) {
|
||||
builder.append(Constants.CARRIAGE_RETURN);
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ public class ExamFormIndicators implements TemplateComposer {
|
|||
.append("<span style='padding: 2px 5px 2px 5px; background-color: #")
|
||||
.append(threshold.color)
|
||||
.append("; ")
|
||||
.append((Utils.darkColor(Utils.parseRGB(threshold.color)))
|
||||
.append((Utils.darkColorContrast(Utils.parseRGB(threshold.color)))
|
||||
? "color: #4a4a4a; "
|
||||
: "color: #FFFFFF;")
|
||||
.append("'>")
|
||||
|
|
|
@ -48,7 +48,7 @@ public class ColorData {
|
|||
}
|
||||
|
||||
Color getStatusTextColor(final Color statusColor) {
|
||||
return Utils.darkColor(statusColor.getRGB()) ? this.darkColor : this.lightColor;
|
||||
return Utils.darkColorContrast(statusColor.getRGB()) ? this.darkColor : this.lightColor;
|
||||
}
|
||||
|
||||
int statusWeight(final ClientConnectionData connectionData) {
|
||||
|
|
|
@ -41,7 +41,7 @@ final class IndicatorData {
|
|||
this.index = index;
|
||||
this.tableIndex = tableIndex;
|
||||
this.defaultColor = new Color(display, Utils.toRGB(indicator.defaultColor), 255);
|
||||
this.defaultTextColor = Utils.darkColor(this.defaultColor.getRGB())
|
||||
this.defaultTextColor = Utils.darkColorContrast(this.defaultColor.getRGB())
|
||||
? colorData.darkColor
|
||||
: colorData.lightColor;
|
||||
|
||||
|
@ -91,7 +91,7 @@ final class IndicatorData {
|
|||
protected ThresholdColor(final Threshold threshold, final Display display, final ColorData colorData) {
|
||||
this.value = threshold.value;
|
||||
this.color = new Color(display, Utils.toRGB(threshold.color), 255);
|
||||
this.textColor = Utils.darkColor(this.color.getRGB())
|
||||
this.textColor = Utils.darkColorContrast(this.color.getRGB())
|
||||
? colorData.darkColor
|
||||
: colorData.lightColor;
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ public final class ColorSelection extends Composite implements Selection {
|
|||
if (this.selection != null) {
|
||||
this.colorField.setBackground(new Color(this.getDisplay(), this.selection));
|
||||
this.colorLabel.setText(Utils.parseColorString(this.selection));
|
||||
this.colorLabel.setData(RWT.CUSTOM_VARIANT, (Utils.darkColor(this.selection))
|
||||
this.colorLabel.setData(RWT.CUSTOM_VARIANT, (Utils.darkColorContrast(this.selection))
|
||||
? CustomVariant.DARK_COLOR_LABEL.key
|
||||
: CustomVariant.LIGHT_COLOR_LABEL.key);
|
||||
} else {
|
||||
|
|
|
@ -190,6 +190,12 @@ public interface ExamSessionService {
|
|||
Result<Exam> updateExamCache(Long examId);
|
||||
|
||||
/** Flush all the caches for an specified Exam.
|
||||
*
|
||||
* <pre>
|
||||
* - Exam
|
||||
* - Exam Configuration
|
||||
* - All ClientConnection of the running exam
|
||||
* </pre>
|
||||
*
|
||||
* @param exam The Exam instance
|
||||
* @return Result with reference to the given Exam or to an error if happened */
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
|
@ -25,6 +26,8 @@ import org.springframework.security.oauth2.provider.token.TokenStore;
|
|||
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
|
||||
|
||||
public class CachableJdbcTokenStore implements TokenStore {
|
||||
|
||||
public static final String ACCESS_TOKEN_CACHE_NAME = "ACCESS_TOKEN_CACHE";
|
||||
|
@ -56,8 +59,9 @@ public class CachableJdbcTokenStore implements TokenStore {
|
|||
key = "#token",
|
||||
unless = "#result == null")
|
||||
public OAuth2Authentication readAuthentication(final OAuth2AccessToken token) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Read authentication from persistent and cache if available");
|
||||
log.debug("Read authentication from persistent and cache if available: {}", token.getValue());
|
||||
}
|
||||
|
||||
return this.jdbcTokenStore.readAuthentication(token);
|
||||
|
@ -65,7 +69,17 @@ public class CachableJdbcTokenStore implements TokenStore {
|
|||
|
||||
@Override
|
||||
public OAuth2Authentication readAuthentication(final String token) {
|
||||
return this.jdbcTokenStore.readAuthentication(token);
|
||||
final OAuth2Authentication authentication = this.jdbcTokenStore.readAuthentication(token);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
if (authentication == null) {
|
||||
log.debug(Utils.formatStackTracePrint(10, Thread.currentThread().getStackTrace()).toString());
|
||||
} else {
|
||||
log.debug("Read authentication from persistent: {}", token);
|
||||
}
|
||||
}
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,16 +88,27 @@ public class CachableJdbcTokenStore implements TokenStore {
|
|||
key = "#tokenValue",
|
||||
unless = "#result == null")
|
||||
public OAuth2AccessToken readAccessToken(final String tokenValue) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Read access token from persistent and cache if available: {}", tokenValue);
|
||||
}
|
||||
|
||||
return this.jdbcTokenStore.readAccessToken(tokenValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CacheEvict(
|
||||
cacheNames = AUTHENTICATION_TOKEN_CACHE,
|
||||
key = "#token")
|
||||
@Caching(evict = {
|
||||
@CacheEvict(
|
||||
cacheNames = AUTHENTICATION_TOKEN_CACHE,
|
||||
key = "#token"),
|
||||
@CacheEvict(
|
||||
cacheNames = ACCESS_TOKEN_CACHE_NAME,
|
||||
key = "#token.value")
|
||||
})
|
||||
public void removeAccessToken(final OAuth2AccessToken token) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Evict token from cache and remove it also from persistent store");
|
||||
log.debug("Evict token from cache and remove it also from persistent store: {}", token.getValue());
|
||||
}
|
||||
|
||||
this.jdbcTokenStore.removeAccessToken(token);
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
|||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||
|
||||
// TODO check if we can apply some caching here to get better performance for SEB client connection attempts
|
||||
public class DefaultTokenServicesFallback extends DefaultTokenServices {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultTokenServicesFallback.class);
|
||||
|
|
|
@ -15,6 +15,7 @@ logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl=INFO
|
|||
logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.session=DEBUG
|
||||
logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.proctoring=INFO
|
||||
logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.session.impl.indicator=DEBUG
|
||||
logging.level.ch.ethz.seb.sebserver.webservice.weblayer.oauth=DEBUG
|
||||
#logging.level.ch.ethz.seb.sebserver.webservice.servicelayer.dao.impl=DEBUG
|
||||
#logging.level.ch.ethz.seb.sebserver.webservice.datalayer.batis=DEBUG
|
||||
#logging.level.ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper=DEBUG
|
||||
|
|
|
@ -8,14 +8,20 @@
|
|||
|
||||
package ch.ethz.seb.sebserver.gbl.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.joda.time.DateTimeUtils;
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
import ch.ethz.seb.sebserver.gbl.Constants;
|
||||
|
||||
public class UtilsTest {
|
||||
|
||||
|
@ -47,6 +53,83 @@ public class UtilsTest {
|
|||
assertEquals("[ONE, TWO]", r5.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEscapeHTML_XML_EcmaScript() {
|
||||
assertEquals("test", Utils.escapeHTML_XML_EcmaScript("test"));
|
||||
assertEquals("test&lt;test&gt;", Utils.escapeHTML_XML_EcmaScript("test<test>"));
|
||||
assertEquals("test;test", Utils.escapeHTML_XML_EcmaScript("test;test"));
|
||||
assertEquals("test-test", Utils.escapeHTML_XML_EcmaScript("test-test"));
|
||||
assertEquals("test+test", Utils.escapeHTML_XML_EcmaScript("test+test"));
|
||||
assertEquals("test&amp;test", Utils.escapeHTML_XML_EcmaScript("test&test"));
|
||||
assertEquals("test[test]", Utils.escapeHTML_XML_EcmaScript("test[test]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreventResponseSplittingAttack() {
|
||||
assertEquals("test", Utils.preventResponseSplittingAttack("test"));
|
||||
try {
|
||||
Utils.preventResponseSplittingAttack("test\nergerg");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
assertEquals("Illegal argument: test\n"
|
||||
+ "ergerg", e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
Utils.preventResponseSplittingAttack("test\rergerg");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
assertEquals("Illegal argument: test\r"
|
||||
+ "ergerg", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHash_SHA_256_Base_16() {
|
||||
assertEquals(
|
||||
"9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
|
||||
Utils.hash_SHA_256_Base_16("test"));
|
||||
assertEquals(
|
||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
Utils.hash_SHA_256_Base_16(""));
|
||||
|
||||
assertNull(Utils.hash_SHA_256_Base_16(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruePredicate() {
|
||||
assertTrue(Utils.truePredicate().test("some"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFalsePredicate() {
|
||||
assertFalse(Utils.falsePredicate().test("some"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToSeconds() {
|
||||
assertEquals("60", String.valueOf(Utils.toSeconds(Constants.MINUTE_IN_MILLIS)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToRGB() {
|
||||
final String rgbString1 = null;
|
||||
final String rgbString2 = "";
|
||||
final String rgbString3 = "wrfgwr";
|
||||
final String rgbString4 = "#aabbcc";
|
||||
final String rgbString5 = "aabbcc";
|
||||
|
||||
assertEquals("RGB {255, 255, 255}", Utils.toRGB(rgbString1).toString());
|
||||
assertEquals("RGB {255, 255, 255}", Utils.toRGB(rgbString2).toString());
|
||||
try {
|
||||
assertEquals("RGB {255, 255, 255}", Utils.toRGB(rgbString3).toString());
|
||||
fail("NumberFormatException expected here");
|
||||
} catch (final NumberFormatException e) {
|
||||
assertEquals("For input string: \"wr\"", e.getMessage());
|
||||
}
|
||||
assertEquals("RGB {170, 187, 204}", Utils.toRGB(rgbString4).toString());
|
||||
assertEquals("RGB {170, 187, 204}", Utils.toRGB(rgbString5).toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseRGB() {
|
||||
String colorString = "FFFFFF";
|
||||
|
@ -60,11 +143,35 @@ public class UtilsTest {
|
|||
Utils.parseRGB(colorString).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetErrorCauseMessage() {
|
||||
assertEquals("--", Utils.getErrorCauseMessage(null));
|
||||
assertEquals("--", Utils.getErrorCauseMessage(new RuntimeException("origMessage")));
|
||||
assertEquals("java.lang.RuntimeException : null",
|
||||
Utils.getErrorCauseMessage(new RuntimeException("origMessage", new RuntimeException())));
|
||||
assertEquals("java.lang.RuntimeException : causeMessage",
|
||||
Utils.getErrorCauseMessage(new RuntimeException("origMessage", new RuntimeException("causeMessage"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDarkColor() {
|
||||
final RGB color = new RGB(255, 255, 255);
|
||||
final RGB color1 = new RGB(101, 100, 200);
|
||||
final RGB color2 = new RGB(100, 100, 200);
|
||||
final RGB color3 = new RGB(0, 0, 0);
|
||||
|
||||
assertTrue(Utils.darkColorContrast(color));
|
||||
assertTrue(Utils.darkColorContrast(color1));
|
||||
assertFalse(Utils.darkColorContrast(color2));
|
||||
assertFalse(Utils.darkColorContrast(color3));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseColorString() {
|
||||
final RGB color = new RGB(255, 255, 255);
|
||||
assertEquals("ffffff", Utils.parseColorString(color));
|
||||
|
||||
assertNull(Utils.parseColorString(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -76,4 +183,64 @@ public class UtilsTest {
|
|||
System.out.println("************* div: " + (millisecondsNow - currentTimeMillis));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToAppFormUrlEncodedBody() {
|
||||
String appFormUrlEncodedBody = Utils.toAppFormUrlEncodedBody("attr1", Arrays.asList("1", "2", "3"));
|
||||
assertEquals("attr1[]=1&attr1[]=2&attr1[]=3", appFormUrlEncodedBody);
|
||||
|
||||
appFormUrlEncodedBody = Utils.toAppFormUrlEncodedBody("attr1", Collections.emptyList());
|
||||
assertEquals("", appFormUrlEncodedBody);
|
||||
|
||||
appFormUrlEncodedBody = Utils.toAppFormUrlEncodedBody("attr1", null);
|
||||
assertEquals("", appFormUrlEncodedBody);
|
||||
|
||||
final LinkedMultiValueMap<String, String> linkedMultiValueMap = new LinkedMultiValueMap<>();
|
||||
linkedMultiValueMap.add("attr1", "value1");
|
||||
linkedMultiValueMap.add("attr2", "value2");
|
||||
linkedMultiValueMap.add("attr3", "value3");
|
||||
appFormUrlEncodedBody = Utils.toAppFormUrlEncodedBody(linkedMultiValueMap);
|
||||
assertEquals("attr1=value1&attr2=value2&attr3=value3", appFormUrlEncodedBody);
|
||||
|
||||
appFormUrlEncodedBody = Utils.toAppFormUrlEncodedBody(new LinkedMultiValueMap<>());
|
||||
assertEquals("", appFormUrlEncodedBody);
|
||||
|
||||
appFormUrlEncodedBody = Utils.toAppFormUrlEncodedBody(null);
|
||||
assertEquals("", appFormUrlEncodedBody);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPingHost() {
|
||||
assertTrue(Utils.pingHost("https://www.google.com"));
|
||||
assertFalse(Utils.pingHost("www.google.com"));
|
||||
assertFalse(Utils.pingHost("some"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToCSVString() {
|
||||
final String nullString = Utils.toCSVString(null);
|
||||
final String emptyString = Utils.toCSVString("");
|
||||
assertEquals(StringUtils.EMPTY, nullString);
|
||||
assertEquals(StringUtils.EMPTY, emptyString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOrEmptyDisplayValue() {
|
||||
final String nullValue = Utils.getOrEmptyDisplayValue(null);
|
||||
final String emptyString = Utils.getOrEmptyDisplayValue("");
|
||||
final String someString = Utils.getOrEmptyDisplayValue("some");
|
||||
|
||||
assertEquals(Constants.EMPTY_NOTE, nullValue);
|
||||
assertEquals(Constants.EMPTY_NOTE, emptyString);
|
||||
assertEquals("some", someString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatStackTracePrint() {
|
||||
final StringBuilder formatStackTracePrint =
|
||||
Utils.formatStackTracePrint(10, Thread.currentThread().getStackTrace());
|
||||
assertTrue(formatStackTracePrint.toString()
|
||||
.contains("ch.ethz.seb.sebserver.gbl.util.UtilsTest.testFormatStackTracePrint"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue