# WARNING: head commit changed in the meantime

Merge remote-tracking branch 'origin/master' into dev-1.3
plus more unit tests
plus CircuitBreaker fix
This commit is contained in:
anhefti 2022-03-02 17:09:37 +01:00
parent 501db30fa8
commit c21f0ef463
11 changed files with 269 additions and 20 deletions

View file

@ -18,7 +18,7 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
<sebserver-version>1.3-rc2</sebserver-version> <sebserver-version>1.3-rc3</sebserver-version>
<build-version>${sebserver-version}</build-version> <build-version>${sebserver-version}</build-version>
<revision>${sebserver-version}</revision> <revision>${sebserver-version}</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

View file

@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.gbl.util.Utils;
/** A circuit breaker with three states (CLOSED, HALF_OPEN, OPEN) /** A circuit breaker with three states (CLOSED, HALF_OPEN, OPEN)
* <p> * <p>
@ -70,6 +71,7 @@ public final class CircuitBreaker<T> {
private State state = State.CLOSED; private State state = State.CLOSED;
private final AtomicInteger failingCount = new AtomicInteger(0); private final AtomicInteger failingCount = new AtomicInteger(0);
private long lastSuccessTime; private long lastSuccessTime;
private long lastOpenTime;
/** Create new CircuitBreakerSupplier. /** Create new CircuitBreakerSupplier.
* *
@ -99,6 +101,8 @@ public final class CircuitBreaker<T> {
this.maxFailingAttempts = maxFailingAttempts; this.maxFailingAttempts = maxFailingAttempts;
this.maxBlockingTime = maxBlockingTime; this.maxBlockingTime = maxBlockingTime;
this.timeToRecover = timeToRecover; this.timeToRecover = timeToRecover;
// Initialize with creation time to get expected cool-down phase time if never was successful since
this.lastOpenTime = Utils.getMillisecondsNow();
} }
public int getMaxFailingAttempts() { public int getMaxFailingAttempts() {
@ -122,7 +126,7 @@ public final class CircuitBreaker<T> {
} }
public synchronized Result<T> protectedRun(final Supplier<T> supplier) { public synchronized Result<T> protectedRun(final Supplier<T> supplier) {
final long currentTime = System.currentTimeMillis(); final long currentTime = Utils.getMillisecondsNow();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Called on: {} current state is: {} failing count: {}", log.debug("Called on: {} current state is: {} failing count: {}",
@ -163,7 +167,7 @@ public final class CircuitBreaker<T> {
log.debug("Attempt failed. failing count: {}", this.failingCount); log.debug("Attempt failed. failing count: {}", this.failingCount);
} }
final long currentBlockingTime = System.currentTimeMillis() - startTime; final long currentBlockingTime = Utils.getMillisecondsNow() - startTime;
final int failing = this.failingCount.incrementAndGet(); final int failing = this.failingCount.incrementAndGet();
if (failing > this.maxFailingAttempts || currentBlockingTime > this.maxBlockingTime) { if (failing > this.maxFailingAttempts || currentBlockingTime > this.maxBlockingTime) {
// brake thought to HALF_OPEN state and return error // brake thought to HALF_OPEN state and return error
@ -174,14 +178,14 @@ public final class CircuitBreaker<T> {
this.state = State.HALF_OPEN; this.state = State.HALF_OPEN;
this.failingCount.set(0); this.failingCount.set(0);
return Result.ofError(new RuntimeException( return Result.ofError(new RuntimeException(
"Set CircuitBeaker to half-open state. Cause: " + result.getError().getMessage(), "Set CircuitBeaker to half-open state. Cause: " + result.getError(),
result.getError())); result.getError()));
} else { } else {
// try again // try again
return protectedRun(supplier); return protectedRun(supplier);
} }
} else { } else {
this.lastSuccessTime = System.currentTimeMillis(); this.lastSuccessTime = Utils.getMillisecondsNow();
return result; return result;
} }
} }
@ -202,9 +206,10 @@ public final class CircuitBreaker<T> {
log.debug("Changing state from Half Open to Open and return cached value"); log.debug("Changing state from Half Open to Open and return cached value");
} }
this.lastOpenTime = Utils.getMillisecondsNow();
this.state = State.OPEN; this.state = State.OPEN;
return Result.ofError(new RuntimeException( return Result.ofError(new RuntimeException(
"Set CircuitBeaker to open state. Cause: " + result.getError().getMessage(), "Set CircuitBeaker to open state. Cause: " + result.getError(),
result.getError())); result.getError()));
} else { } else {
// on success go to CLOSED state // on success go to CLOSED state
@ -228,7 +233,7 @@ public final class CircuitBreaker<T> {
log.debug("Handle Open on: {}", startTime); log.debug("Handle Open on: {}", startTime);
} }
if (startTime - this.lastSuccessTime >= this.timeToRecover) { if (startTime - this.lastOpenTime >= this.timeToRecover) {
// if cool-down period is over, go back to HALF_OPEN state and try again // if cool-down period is over, go back to HALF_OPEN state and try again
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("Time to recover reached. Changing state from Open to Half Open"); log.debug("Time to recover reached. Changing state from Open to Half Open");
@ -247,6 +252,7 @@ public final class CircuitBreaker<T> {
return Result.of(future.get(this.maxBlockingTime, TimeUnit.MILLISECONDS)); return Result.of(future.get(this.maxBlockingTime, TimeUnit.MILLISECONDS));
} catch (final Exception e) { } catch (final Exception e) {
future.cancel(false); future.cancel(false);
log.warn("Max blocking timeout exceeded: {}, {}", this.maxBlockingTime, this.state);
return Result.ofError(e); return Result.ofError(e);
} }
} }

View file

@ -818,7 +818,8 @@ public class ExamDAOImpl implements ExamDAO {
log.debug("Using short-name: {} for recovering", shortname); log.debug("Using short-name: {} for recovering", shortname);
final QuizData recoveredQuizData = this.lmsAPIService.getLmsAPITemplate(lmsSetup.id) final QuizData recoveredQuizData = this.lmsAPIService
.getLmsAPITemplate(lmsSetup.id)
.map(template -> template.getQuizzes(new FilterMap()) .map(template -> template.getQuizzes(new FilterMap())
.getOrThrow() .getOrThrow()
.stream() .stream()

View file

@ -80,7 +80,7 @@ public abstract class AbstractCourseAccess {
environment.getProperty( environment.getProperty(
"sebserver.webservice.circuitbreaker.quizzesRequest.blockingTime", "sebserver.webservice.circuitbreaker.quizzesRequest.blockingTime",
Long.class, Long.class,
Constants.MINUTE_IN_MILLIS), Constants.SECOND_IN_MILLIS * 10),
environment.getProperty( environment.getProperty(
"sebserver.webservice.circuitbreaker.quizzesRequest.timeToRecover", "sebserver.webservice.circuitbreaker.quizzesRequest.timeToRecover",
Long.class, Long.class,
@ -94,7 +94,7 @@ public abstract class AbstractCourseAccess {
environment.getProperty( environment.getProperty(
"sebserver.webservice.circuitbreaker.quizzesRequest.blockingTime", "sebserver.webservice.circuitbreaker.quizzesRequest.blockingTime",
Long.class, Long.class,
Constants.MINUTE_IN_MILLIS), Constants.SECOND_IN_MILLIS * 10),
environment.getProperty( environment.getProperty(
"sebserver.webservice.circuitbreaker.quizzesRequest.timeToRecover", "sebserver.webservice.circuitbreaker.quizzesRequest.timeToRecover",
Long.class, Long.class,
@ -112,7 +112,7 @@ public abstract class AbstractCourseAccess {
environment.getProperty( environment.getProperty(
"sebserver.webservice.circuitbreaker.chaptersRequest.timeToRecover", "sebserver.webservice.circuitbreaker.chaptersRequest.timeToRecover",
Long.class, Long.class,
Constants.MINUTE_IN_MILLIS)); Constants.SECOND_IN_MILLIS * 30));
this.accountDetailRequest = asyncService.createCircuitBreaker( this.accountDetailRequest = asyncService.createCircuitBreaker(
environment.getProperty( environment.getProperty(
@ -126,19 +126,28 @@ public abstract class AbstractCourseAccess {
environment.getProperty( environment.getProperty(
"sebserver.webservice.circuitbreaker.accountDetailRequest.timeToRecover", "sebserver.webservice.circuitbreaker.accountDetailRequest.timeToRecover",
Long.class, Long.class,
Constants.SECOND_IN_MILLIS * 10)); Constants.SECOND_IN_MILLIS * 30));
} }
public Result<List<QuizData>> protectedQuizzesRequest(final FilterMap filterMap) { public Result<List<QuizData>> protectedQuizzesRequest(final FilterMap filterMap) {
return this.allQuizzesRequest.protectedRun(allQuizzesSupplier(filterMap)); return this.allQuizzesRequest.protectedRun(allQuizzesSupplier(filterMap))
.onError(error -> log.error(
"Failed to run protectedQuizzesRequest: {}",
error.getMessage()));
} }
public Result<Collection<QuizData>> protectedQuizzesRequest(final Set<String> ids) { public Result<Collection<QuizData>> protectedQuizzesRequest(final Set<String> ids) {
return this.quizzesRequest.protectedRun(quizzesSupplier(ids)); return this.quizzesRequest.protectedRun(quizzesSupplier(ids))
.onError(error -> log.error(
"Failed to run protectedQuizzesRequest: {}",
error.getMessage()));
} }
public Result<QuizData> protectedQuizRequest(final String id) { public Result<QuizData> protectedQuizRequest(final String id) {
return this.quizRequest.protectedRun(quizSupplier(id)); return this.quizRequest.protectedRun(quizSupplier(id))
.onError(error -> log.error(
"Failed to run protectedQuizRequest: {}",
error.getMessage()));
} }
public Result<ExamineeAccountDetails> getExamineeAccountDetails(final String examineeSessionId) { public Result<ExamineeAccountDetails> getExamineeAccountDetails(final String examineeSessionId) {
@ -165,7 +174,10 @@ public abstract class AbstractCourseAccess {
} }
public Result<Chapters> getCourseChapters(final String courseId) { public Result<Chapters> getCourseChapters(final String courseId) {
return this.chaptersRequest.protectedRun(getCourseChaptersSupplier(courseId)); return this.chaptersRequest.protectedRun(getCourseChaptersSupplier(courseId))
.onError(error -> log.error(
"Failed to run getCourseChapters: {}",
error.getMessage()));
} }
protected abstract Supplier<ExamineeAccountDetails> accountDetailsSupplier(final String examineeSessionId); protected abstract Supplier<ExamineeAccountDetails> accountDetailsSupplier(final String examineeSessionId);

View file

@ -9,8 +9,10 @@
package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.mockup; package ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.mockup;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ch.ethz.seb.sebserver.gbl.async.AsyncService;
import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType; import ch.ethz.seb.sebserver.gbl.model.institution.LmsSetup.LmsType;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Result; import ch.ethz.seb.sebserver.gbl.util.Result;
@ -24,9 +26,17 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplateFactory;
@WebServiceProfile @WebServiceProfile
public class MockLmsAPITemplateFactory implements LmsAPITemplateFactory { public class MockLmsAPITemplateFactory implements LmsAPITemplateFactory {
private final AsyncService asyncService;
private final WebserviceInfo webserviceInfo; private final WebserviceInfo webserviceInfo;
private final Environment environment;
public MockLmsAPITemplateFactory(final WebserviceInfo webserviceInfo) { public MockLmsAPITemplateFactory(
final AsyncService asyncService,
final Environment environment,
final WebserviceInfo webserviceInfo) {
this.environment = environment;
this.asyncService = asyncService;
this.webserviceInfo = webserviceInfo; this.webserviceInfo = webserviceInfo;
} }
@ -38,6 +48,8 @@ public class MockLmsAPITemplateFactory implements LmsAPITemplateFactory {
@Override @Override
public Result<LmsAPITemplate> create(final APITemplateDataSupplier apiTemplateDataSupplier) { public Result<LmsAPITemplate> create(final APITemplateDataSupplier apiTemplateDataSupplier) {
return Result.tryCatch(() -> new MockupLmsAPITemplate( return Result.tryCatch(() -> new MockupLmsAPITemplate(
this.asyncService,
this.environment,
apiTemplateDataSupplier, apiTemplateDataSupplier,
this.webserviceInfo)); this.webserviceInfo));
} }

View file

@ -12,6 +12,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -19,9 +20,11 @@ import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import ch.ethz.seb.sebserver.gbl.Constants; import ch.ethz.seb.sebserver.gbl.Constants;
import ch.ethz.seb.sebserver.gbl.api.APIMessage; import ch.ethz.seb.sebserver.gbl.api.APIMessage;
import ch.ethz.seb.sebserver.gbl.async.AsyncService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials; import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP; import ch.ethz.seb.sebserver.gbl.model.Domain.LMS_SETUP;
import ch.ethz.seb.sebserver.gbl.model.exam.Chapters; import ch.ethz.seb.sebserver.gbl.model.exam.Chapters;
@ -38,6 +41,7 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.APITemplateDataSupplier;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPIService;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.LmsAPITemplate;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.AbstractCourseAccess;
import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException; import ch.ethz.seb.sebserver.webservice.servicelayer.lms.impl.NoSEBRestrictionException;
public class MockupLmsAPITemplate implements LmsAPITemplate { public class MockupLmsAPITemplate implements LmsAPITemplate {
@ -48,7 +52,11 @@ public class MockupLmsAPITemplate implements LmsAPITemplate {
private final WebserviceInfo webserviceInfo; private final WebserviceInfo webserviceInfo;
private final APITemplateDataSupplier apiTemplateDataSupplier; private final APITemplateDataSupplier apiTemplateDataSupplier;
private final AbstractCourseAccess abstractCourseAccess;
MockupLmsAPITemplate( MockupLmsAPITemplate(
final AsyncService asyncService,
final Environment environment,
final APITemplateDataSupplier apiTemplateDataSupplier, final APITemplateDataSupplier apiTemplateDataSupplier,
final WebserviceInfo webserviceInfo) { final WebserviceInfo webserviceInfo) {
@ -56,6 +64,37 @@ public class MockupLmsAPITemplate implements LmsAPITemplate {
this.webserviceInfo = webserviceInfo; this.webserviceInfo = webserviceInfo;
this.mockups = new ArrayList<>(); this.mockups = new ArrayList<>();
this.abstractCourseAccess = new AbstractCourseAccess(asyncService, environment) {
@Override
protected Supplier<ExamineeAccountDetails> accountDetailsSupplier(final String examineeSessionId) {
return () -> MockupLmsAPITemplate.this
.getExamineeAccountDetails_protected(examineeSessionId)
.getOrThrow();
}
@Override
protected Supplier<List<QuizData>> allQuizzesSupplier(final FilterMap filterMap) {
return () -> MockupLmsAPITemplate.this.getQuizzes_protected(filterMap).getOrThrow();
}
@Override
protected Supplier<Collection<QuizData>> quizzesSupplier(final Set<String> ids) {
return () -> MockupLmsAPITemplate.this.getQuizzes_protected(ids).getOrThrow();
}
@Override
protected Supplier<QuizData> quizSupplier(final String id) {
return () -> MockupLmsAPITemplate.this.getQuiz_protected(id).getOrThrow();
}
@Override
protected Supplier<Chapters> getCourseChaptersSupplier(final String courseId) {
return () -> MockupLmsAPITemplate.this.getCourseChapters_protected(courseId).getOrThrow();
}
};
final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup(); final LmsSetup lmsSetup = this.apiTemplateDataSupplier.getLmsSetup();
final Long lmsSetupId = lmsSetup.id; final Long lmsSetupId = lmsSetup.id;
final Long institutionId = lmsSetup.getInstitutionId(); final Long institutionId = lmsSetup.getInstitutionId();
@ -149,6 +188,10 @@ public class MockupLmsAPITemplate implements LmsAPITemplate {
@Override @Override
public Result<List<QuizData>> getQuizzes(final FilterMap filterMap) { public Result<List<QuizData>> getQuizzes(final FilterMap filterMap) {
return this.abstractCourseAccess.protectedQuizzesRequest(filterMap);
}
private Result<List<QuizData>> getQuizzes_protected(final FilterMap filterMap) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
if (!authenticate()) { if (!authenticate()) {
throw new IllegalArgumentException("Wrong clientId or secret"); throw new IllegalArgumentException("Wrong clientId or secret");
@ -164,6 +207,10 @@ public class MockupLmsAPITemplate implements LmsAPITemplate {
@Override @Override
public Result<QuizData> getQuiz(final String id) { public Result<QuizData> getQuiz(final String id) {
return this.abstractCourseAccess.protectedQuizRequest(id);
}
private Result<QuizData> getQuiz_protected(final String id) {
return Result.of(this.mockups return Result.of(this.mockups
.stream() .stream()
.filter(q -> id.equals(q.id)) .filter(q -> id.equals(q.id))
@ -173,6 +220,11 @@ public class MockupLmsAPITemplate implements LmsAPITemplate {
@Override @Override
public Result<Collection<QuizData>> getQuizzes(final Set<String> ids) { public Result<Collection<QuizData>> getQuizzes(final Set<String> ids) {
return this.abstractCourseAccess.protectedQuizzesRequest(ids);
}
private Result<Collection<QuizData>> getQuizzes_protected(final Set<String> ids) {
return Result.tryCatch(() -> { return Result.tryCatch(() -> {
if (!authenticate()) { if (!authenticate()) {
throw new IllegalArgumentException("Wrong clientId or secret"); throw new IllegalArgumentException("Wrong clientId or secret");
@ -193,11 +245,19 @@ public class MockupLmsAPITemplate implements LmsAPITemplate {
@Override @Override
public Result<Chapters> getCourseChapters(final String courseId) { public Result<Chapters> getCourseChapters(final String courseId) {
return this.abstractCourseAccess.getCourseChapters(courseId);
}
private Result<Chapters> getCourseChapters_protected(final String courseId) {
return Result.ofError(new UnsupportedOperationException()); return Result.ofError(new UnsupportedOperationException());
} }
@Override @Override
public Result<ExamineeAccountDetails> getExamineeAccountDetails(final String examineeSessionId) { public Result<ExamineeAccountDetails> getExamineeAccountDetails(final String examineeSessionId) {
return this.abstractCourseAccess.getExamineeAccountDetails(examineeSessionId);
}
private Result<ExamineeAccountDetails> getExamineeAccountDetails_protected(final String examineeSessionId) {
return Result.ofError(new UnsupportedOperationException()); return Result.ofError(new UnsupportedOperationException());
} }

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2022 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;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.core.env.Environment;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentialService;
import ch.ethz.seb.sebserver.gbl.client.ClientCredentials;
import ch.ethz.seb.sebserver.gbl.client.ProxyData;
import ch.ethz.seb.sebserver.gbl.util.Result;
public class ClientHttpRequestFactoryServiceTest {
@Mock
Environment environment;
@Mock
ClientCredentialService clientCredentialService;
@Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetClientHttpRequestFactory() {
final ClientHttpRequestFactoryService clientHttpRequestFactoryService = new ClientHttpRequestFactoryService(
this.environment,
this.clientCredentialService,
1, 1, 1);
final ProxyData proxyData = new ProxyData("testPoxy", 8000, new ClientCredentials("test", "test"));
Mockito.when(this.environment.getActiveProfiles()).thenReturn(new String[] { "dev-gui", "test" });
Mockito.when(this.clientCredentialService.getPlainClientSecret(Mockito.any())).thenReturn(Result.of("test"));
Result<ClientHttpRequestFactory> clientHttpRequestFactory = clientHttpRequestFactoryService
.getClientHttpRequestFactory();
assertNotNull(clientHttpRequestFactory);
assertFalse(clientHttpRequestFactory.hasError());
ClientHttpRequestFactory instance = clientHttpRequestFactory.get();
assertTrue(instance instanceof HttpComponentsClientHttpRequestFactory);
clientHttpRequestFactory = clientHttpRequestFactoryService
.getClientHttpRequestFactory(proxyData);
assertNotNull(clientHttpRequestFactory);
assertFalse(clientHttpRequestFactory.hasError());
instance = clientHttpRequestFactory.get();
assertTrue(instance instanceof HttpComponentsClientHttpRequestFactory);
Mockito.when(this.environment.getActiveProfiles()).thenReturn(new String[] { "prod-gui", "prod-ws" });
clientHttpRequestFactory = clientHttpRequestFactoryService
.getClientHttpRequestFactory();
assertNotNull(clientHttpRequestFactory);
assertFalse(clientHttpRequestFactory.hasError());
instance = clientHttpRequestFactory.get();
assertTrue(instance instanceof HttpComponentsClientHttpRequestFactory);
clientHttpRequestFactory = clientHttpRequestFactoryService
.getClientHttpRequestFactory(proxyData);
assertNotNull(clientHttpRequestFactory);
assertFalse(clientHttpRequestFactory.hasError());
instance = clientHttpRequestFactory.get();
assertTrue(instance instanceof HttpComponentsClientHttpRequestFactory);
}
}

View file

@ -76,7 +76,7 @@ public class CircuitBreakerTest {
assertEquals(CircuitBreaker.OPEN_STATE_EXCEPTION, result.getError()); assertEquals(CircuitBreaker.OPEN_STATE_EXCEPTION, result.getError());
// wait time to recover // wait time to recover
Thread.sleep(500); Thread.sleep(1000);
result = circuitBreaker.protectedRun(tester); // 11. call... result = circuitBreaker.protectedRun(tester); // 11. call...
assertEquals(State.CLOSED, circuitBreaker.getState()); assertEquals(State.CLOSED, circuitBreaker.getState());
assertEquals("Hello back again", result.get()); assertEquals("Hello back again", result.get());

View file

@ -77,7 +77,7 @@ public class MemoizingCircuitBreakerTest {
assertEquals(State.OPEN, circuitBreaker.getState()); assertEquals(State.OPEN, circuitBreaker.getState());
// wait time to recover // wait time to recover
Thread.sleep(500); Thread.sleep(1000);
result = circuitBreaker.get(); // 11. call... result = circuitBreaker.get(); // 11. call...
assertEquals(State.CLOSED, circuitBreaker.getState()); assertEquals(State.CLOSED, circuitBreaker.getState());
assertEquals("Hello back again", result.get()); assertEquals("Hello back again", result.get());

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2022 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.integration.api.admin;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Collection;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.jdbc.Sql;
import com.fasterxml.jackson.core.type.TypeReference;
import ch.ethz.seb.sebserver.gbl.api.API;
import ch.ethz.seb.sebserver.gbl.model.EntityName;
@Sql(scripts = { "classpath:schema-test.sql", "classpath:data-test.sql" })
public class WebserviceInfoTest extends AdministrationAPIIntegrationTester {
@Test
public void testGetLogo() throws Exception {
String result = new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT)
.withPath("/inst1")
.withMethod(HttpMethod.GET)
.withExpectedStatus(HttpStatus.OK)
.getAsString();
assertEquals("", result);
result = new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(API.INFO_ENDPOINT + API.LOGO_PATH_SEGMENT)
.withPath("/inst2")
.withMethod(HttpMethod.GET)
.withExpectedStatus(HttpStatus.OK)
.getAsString();
assertEquals("AAA", result);
}
@Test
public void test_getInstitutionInfo() throws Exception {
final Collection<EntityName> result = new RestAPITestHelper()
.withAccessToken(getAdminInstitution1Access())
.withPath(API.INFO_ENDPOINT + API.INFO_INST_PATH_SEGMENT)
.withMethod(HttpMethod.GET)
.withExpectedStatus(HttpStatus.OK)
.getAsObject(new TypeReference<Collection<EntityName>>() {
});
assertNotNull(result);
assertTrue(result.stream().filter(en -> "Institution1".equals(en.name)).findFirst().isPresent());
assertTrue(result.stream().filter(en -> "Institution2".equals(en.name)).findFirst().isPresent());
assertFalse(result.stream().filter(en -> "Institution3".equals(en.name)).findFirst().isPresent());
}
}

View file

@ -1,6 +1,6 @@
INSERT INTO institution VALUES INSERT INTO institution VALUES
(1, 'Institution1', 'inst1', null, null, 1), (1, 'Institution1', 'inst1', null, null, 1),
(2, 'Institution2', 'inst2', null, null, 1), (2, 'Institution2', 'inst2', 'AAA', null, 1),
(3, 'Institution3', 'inst3', null, null, 0) (3, 'Institution3', 'inst3', null, null, 0)
; ;