Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add TCK tests for configuring @Timeout attributes #555

Merged
merged 1 commit into from
Jun 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*******************************************************************************/

package org.eclipse.microprofile.fault.tolerance.tck.config;

import org.eclipse.microprofile.faulttolerance.Asynchronous;
import org.eclipse.microprofile.faulttolerance.Timeout;

import javax.enterprise.context.ApplicationScoped;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;

/**
* Suite of methods for testing the various parameters of Timeout
*/
@ApplicationScoped
public class TimeoutConfigBean {
@Timeout(value = 1, unit = ChronoUnit.MILLIS)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since @Timeout has a lot of advantages when used together with @Asynchronous, I am wondering add @Asynchronous on one of the endpoint might be good. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the config test?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're only testing timeout config here. Do you think we need a specific test for config when @Timeout and @Asynchronous are used together?

In general I prefer tests to remain focused. This class just tests Timeout + config while we have other tests for Timeout + async.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have Timeout + async + config? The reason is that timeout is better off to be used with @Asynchronous. We need to ensure the config works. I will be ok to skip Timeout with config and vote for Timeout+Asynchronous with config.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timeout is better off to be used with @asynchronous

Why is that?

We need to ensure the config works

We do. This PR does that. @Asynchronous makes no difference whatsoever.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Actually it might make a difference, depending on implementation, but so can putting the annotation on a class, or configuring an annotation parameter for all methods in a class, or configuring an annotation parameter globally. We decided to stick to this form of testing and I don't quite see how @Asynchronous is so very relevant.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case, I have just changed one test from synchronous to @Asynchronous.

public void serviceValue() throws InterruptedException {
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
}

@Timeout(value = 1000, unit = ChronoUnit.MICROS)
public void serviceUnit() throws InterruptedException {
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
}

@Timeout(value = 10, unit = ChronoUnit.MICROS)
@Asynchronous
public CompletionStage<Void> serviceBoth() throws InterruptedException {
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
return CompletableFuture.completedFuture(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
*******************************************************************************
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*******************************************************************************/

package org.eclipse.microprofile.fault.tolerance.tck.config;

import org.eclipse.microprofile.fault.tolerance.tck.asynchronous.CompletableFutureHelper;
import org.eclipse.microprofile.fault.tolerance.tck.util.Exceptions.ExceptionThrowingAction;
import org.eclipse.microprofile.fault.tolerance.tck.util.Packages;
import org.eclipse.microprofile.fault.tolerance.tck.util.TCKConfig;
import org.eclipse.microprofile.faulttolerance.Timeout;
import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.testng.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.testng.annotations.Test;

import javax.inject.Inject;
import java.time.Duration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import static org.eclipse.microprofile.fault.tolerance.tck.util.Exceptions.expect;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan;

/**
* Test that the various parameters of Timeout can be configured
*/
public class TimeoutConfigTest extends Arquillian {

@Deployment
public static WebArchive create() {
ConfigAnnotationAsset config = new ConfigAnnotationAsset()
.set(TimeoutConfigBean.class, "serviceValue", Timeout.class, "value",
TCKConfig.getConfig().getTimeoutInStr(1000))
// only changing value here to scale the original, not for the purpose of this test
.set(TimeoutConfigBean.class, "serviceUnit", Timeout.class, "value",
TCKConfig.getConfig().getTimeoutInStr(1000))
.set(TimeoutConfigBean.class, "serviceUnit", Timeout.class, "unit", "MILLIS")
.set(TimeoutConfigBean.class, "serviceBoth", Timeout.class, "value",
TCKConfig.getConfig().getTimeoutInStr(1000))
.set(TimeoutConfigBean.class, "serviceBoth", Timeout.class, "unit", "MILLIS");

JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "ftTimeoutConfig.jar")
.addClasses(TimeoutConfigBean.class)
.addPackage(Packages.UTILS)
.addAsManifestResource(config, "microprofile-config.properties")
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");

return ShrinkWrap.create(WebArchive.class, "ftTimeoutConfig.war")
.addAsLibrary(jar);
}

@Inject
private TimeoutConfigBean bean;

@Test
public void testConfigValue() {
// In annotation: value = 1
// unit = MILLIS
// In config: value = 1000
doTest(() -> bean.serviceValue());
}

@Test
public void testConfigUnit() {
// In annotation: value = 1000
// unit = MICROS
// In config: unit = MILLIS
doTest(() -> bean.serviceUnit());
}

@Test
public void testConfigBoth() {
// In annotation: value = 10
// unit = MICROS
// In config: value = 1000
// unit = MILLIS
doTest(() -> {
try {
CompletableFutureHelper.toCompletableFuture(bean.serviceBoth()).get(1, TimeUnit.MINUTES);
}
catch (ExecutionException e) {
if (e.getCause() instanceof Exception) {
throw (Exception) e.getCause();
}
throw e;
}
});
}

private void doTest(ExceptionThrowingAction action) {
long start = System.nanoTime();
expect(TimeoutException.class, action);
long end = System.nanoTime();

long durationInMillis = Duration.ofNanos(end - start).toMillis();
assertThat(durationInMillis, greaterThan(TCKConfig.getConfig().getTimeoutInMillis(800)));
assertThat(durationInMillis, lessThan(TCKConfig.getConfig().getTimeoutInMillis(2000)));
}
}