Skip to content

Commit

Permalink
add TCK test for MicroProfile Context Propagation integration
Browse files Browse the repository at this point in the history
Signed-off-by: Ladislav Thon <[email protected]>
  • Loading branch information
Ladicek committed Jul 17, 2020
1 parent be6adc2 commit 5d86138
Show file tree
Hide file tree
Showing 8 changed files with 386 additions and 0 deletions.
8 changes: 8 additions & 0 deletions tck/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<arquillian.version>1.1.14.Final</arquillian.version>
<checkstyle.methodNameFormat>^_?[a-z][a-zA-Z0-9_]*$</checkstyle.methodNameFormat>
<microprofile-config-api.version>1.3</microprofile-config-api.version>
<microprofile-context-propagation-api.version>1.0.2</microprofile-context-propagation-api.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -75,6 +76,13 @@
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.eclipse.microprofile.context-propagation</groupId>
<artifactId>microprofile-context-propagation-api</artifactId>
<version>${microprofile-context-propagation-api.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<!-- actually only referenced in JavaDoc -->
<groupId>org.apache.geronimo.specs</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
*******************************************************************************
* 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.context.propagation;

import org.eclipse.microprofile.context.spi.ThreadContextProvider;
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.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.testng.SkipException;
import org.testng.annotations.Test;

import javax.inject.Inject;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.eclipse.microprofile.fault.tolerance.tck.asynchronous.CompletableFutureHelper.toCompletableFuture;
import static org.testng.Assert.assertEquals;

public class ContextPropagationTest extends Arquillian {
// configure identical defaults for both ManagedExecutor and ThreadContext, because implementations
// are free to use any of them to implement context propagation
private static final String CONTEXT_PROPAGATION_CONFIG = ""
+ "mp.context.ManagedExecutor.propagated=CDI,MyContext1\n"
+ "mp.context.ManagedExecutor.cleared=MyContext2\n"
+ "mp.context.ThreadContext.propagated=CDI,MyContext1\n"
+ "mp.context.ThreadContext.cleared=MyContext2\n";

@Deployment
public static WebArchive deploy() {
JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "ftContextPropagation.jar")
.addClasses(MyAppScopedBean.class, MyReqScopedBean.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");


if (contextPropagationPresent()) {
// if this was always added, deployment would fail at runtime
// when MP Context Propagation classes are not present

jar.addClasses(MyContext1.class, MyContext1Provider.class, MyContext2.class, MyContext2Provider.class)
.addAsServiceProvider(ThreadContextProvider.class, MyContext1Provider.class, MyContext2Provider.class)
.addAsManifestResource(new StringAsset(CONTEXT_PROPAGATION_CONFIG), "microprofile-config.properties");

}

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

@Inject
private MyAppScopedBean appScopedBean;

@Inject
private MyReqScopedBean reqScopedBean;

@Test
public void contextPropagation() throws InterruptedException, ExecutionException, TimeoutException {
assumeContextPropagationPresence();

MyContext1.set("foo");
MyContext2.set("bar");
reqScopedBean.set("quux");

assertEquals(MyContext1.get(), "foo");
assertEquals(MyContext2.get(), "bar");
assertEquals(reqScopedBean.get(), "quux");

// in the @Asynchronous method, CDI should be propagated, MyContext1 should be propagated,
// and MyContext2 should be cleared
String value = toCompletableFuture(appScopedBean.get()).get(1, TimeUnit.MINUTES);
assertEquals(value, "foo|[[NONE]]|quux");

assertEquals(MyContext1.get(), "foo");
assertEquals(MyContext2.get(), "bar");
assertEquals(reqScopedBean.get(), "quux");
}

private static void assumeContextPropagationPresence() {
if (!contextPropagationPresent()) {
throw new SkipException("Context Propagation not present, ignoring test");
}
}

private static boolean contextPropagationPresent() {
try {
Class.forName("org.eclipse.microprofile.context.ThreadContext");
return true;
}
catch (ClassNotFoundException e) {
return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
*******************************************************************************
* 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.context.propagation;

import org.eclipse.microprofile.faulttolerance.Asynchronous;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.util.concurrent.CompletionStage;

import static java.util.concurrent.CompletableFuture.completedFuture;

@ApplicationScoped
public class MyAppScopedBean {
@Inject
private MyReqScopedBean reqScopedBean;

@Asynchronous
public CompletionStage<String> get() {
return completedFuture(MyContext1.get() + "|" + MyContext2.get() + "|" + reqScopedBean.get());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
*******************************************************************************
* 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.context.propagation;

public class MyContext1 {
private static final ThreadLocal<String> CONTEXTUAL_VALUE = ThreadLocal.withInitial(() -> "<<none>>");

private MyContext1() {} // avoid instantiation

public static String get() {
return CONTEXTUAL_VALUE.get();
}

public static void set(String value) {
CONTEXTUAL_VALUE.set(value);
}

public static void remove() {
CONTEXTUAL_VALUE.remove();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*******************************************************************************
* 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.context.propagation;

import org.eclipse.microprofile.context.spi.ThreadContextProvider;
import org.eclipse.microprofile.context.spi.ThreadContextSnapshot;

import java.util.Map;

public class MyContext1Provider implements ThreadContextProvider {
@Override
public ThreadContextSnapshot currentContext(Map<String, String> props) {
String captured = MyContext1.get();
return () -> {
String movedOut = MyContext1.get();
MyContext1.set(captured);
return () -> {
MyContext1.set(movedOut);
};
};
}

@Override
public ThreadContextSnapshot clearedContext(Map<String, String> props) {
return () -> {
String movedOut = MyContext1.get();
MyContext1.remove();
return () -> {
MyContext1.set(movedOut);
};
};
}

@Override
public String getThreadContextType() {
return MyContext1.class.getSimpleName();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
*******************************************************************************
* 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.context.propagation;

public class MyContext2 {
private static final ThreadLocal<String> CONTEXTUAL_VALUE = ThreadLocal.withInitial(() -> "[[NONE]]");

private MyContext2() {} // avoid instantiation

public static String get() {
return CONTEXTUAL_VALUE.get();
}

public static void set(String value) {
CONTEXTUAL_VALUE.set(value);
}

public static void remove() {
CONTEXTUAL_VALUE.remove();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*******************************************************************************
* 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.context.propagation;

import org.eclipse.microprofile.context.spi.ThreadContextProvider;
import org.eclipse.microprofile.context.spi.ThreadContextSnapshot;

import java.util.Map;

public class MyContext2Provider implements ThreadContextProvider {
@Override
public ThreadContextSnapshot currentContext(Map<String, String> props) {
String captured = MyContext2.get();
return () -> {
String movedOut = MyContext2.get();
MyContext2.set(captured);
return () -> {
MyContext2.set(movedOut);
};
};
}

@Override
public ThreadContextSnapshot clearedContext(Map<String, String> props) {
return () -> {
String movedOut = MyContext2.get();
MyContext2.remove();
return () -> {
MyContext2.set(movedOut);
};
};
}

@Override
public String getThreadContextType() {
return MyContext2.class.getSimpleName();
}
}
Loading

0 comments on commit 5d86138

Please sign in to comment.