diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitMethodManager.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitMethodManager.java index 0ef390cf5..05b803d18 100644 --- a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitMethodManager.java +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitMethodManager.java @@ -93,7 +93,7 @@ private ThreadPoolExecutor createAsyncExecutor() { ASYNC_INIT_METHOD_EXECUTOR_BEAN_NAME, Supplier.class).get(); } - private void ensureAsyncTasksFinish() { + void ensureAsyncTasksFinish() { for (Future future : futures) { try { future.get(); diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvoker.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvoker.java index 2cb0a3840..850a1c55f 100644 --- a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvoker.java +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvoker.java @@ -85,8 +85,7 @@ public Object invoke(final MethodInvocation invocation) throws Throwable { } catch (Throwable e) { throw new RuntimeException(e); } finally { - initCountDownLatch.countDown(); - isAsyncCalling = false; + asyncMethodFinish(); } }); return null; @@ -101,4 +100,9 @@ public Object invoke(final MethodInvocation invocation) throws Throwable { } return invocation.getMethod().invoke(targetObject, invocation.getArguments()); } + + void asyncMethodFinish() { + this.initCountDownLatch.countDown(); + this.isAsyncCalling = false; + } } diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptor.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptor.java index ac36b4821..8b75cbf09 100644 --- a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptor.java +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/main/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptor.java @@ -61,9 +61,7 @@ public void afterRefresh(SofaGenericApplicationContext context, Throwable throwa ComponentInfo componentInfo = new SpringContextComponent(componentName, implementation, sofaRuntimeContext); componentManager.register(componentInfo); - } - - if (throwable != null) { + } else { Collection componentInfos = componentManager .getComponentInfosByApplicationContext(context); for (ComponentInfo componentInfo : componentInfos) { diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncInitMethodManagerTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncInitMethodManagerTests.java new file mode 100644 index 000000000..4c77e8302 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncInitMethodManagerTests.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.async; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.support.GenericApplicationContext; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Supplier; + +import static com.alipay.sofa.runtime.async.AsyncInitMethodManager.ASYNC_INIT_METHOD_EXECUTOR_BEAN_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +/** + * Tests for {@link AsyncInitMethodManager}. + * + * @author huzijie + * @version AsyncInitMethodManagerTests.java, v 0.1 2023年04月10日 10:39 AM huzijie Exp $ + */ +public class AsyncInitMethodManagerTests { + + @Test + void submitTaskSuccess() { + AsyncInitMethodManager manager = new AsyncInitMethodManager(); + ExecutorService executorService = Executors.newFixedThreadPool(3); + GenericApplicationContext applicationContext = new GenericApplicationContext(); + applicationContext.getBeanFactory().registerSingleton(ASYNC_INIT_METHOD_EXECUTOR_BEAN_NAME, (Supplier) () -> executorService); + applicationContext.refresh(); + manager.setApplicationContext(applicationContext); + // Submit 3 tasks + for (int i = 0; i < 3; i++) { + manager.submitTask(() -> { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + } + + manager.ensureAsyncTasksFinish(); + + // Verify that all tasks finished successfully + assertThat(manager.isStartUpFinish()).isTrue(); + + // Shut down the executor service + executorService.shutdown(); + } + + @Test + void submitTaskException() { + AsyncInitMethodManager manager = new AsyncInitMethodManager(); + ExecutorService executorService = Executors.newFixedThreadPool(3); + GenericApplicationContext applicationContext = new GenericApplicationContext(); + applicationContext.getBeanFactory().registerSingleton(ASYNC_INIT_METHOD_EXECUTOR_BEAN_NAME, (Supplier) () -> executorService); + applicationContext.refresh(); + manager.setApplicationContext(applicationContext); + // Submit 3 tasks + for (int i = 0; i < 3; i++) { + manager.submitTask(() -> { + throw new RuntimeException("task fail"); + }); + } + + assertThatThrownBy(manager::ensureAsyncTasksFinish) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Async init task finish fail") + .hasRootCauseMessage("task fail"); + + // Verify that all tasks finished successfully + assertThat(manager.isStartUpFinish()).isFalse(); + + // Shut down the executor service + executorService.shutdown(); + } + + @Test + void registerAsyncInitBean() { + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + AsyncInitMethodManager manager = new AsyncInitMethodManager(); + String beanName = "myBean"; + String asyncInitMethodName = "initAsync"; + manager.registerAsyncInitBean(beanFactory, beanName, asyncInitMethodName); + assertThat(manager.findAsyncInitMethod(beanFactory, beanName)).isEqualTo( + asyncInitMethodName); + } + +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvokerTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvokerTests.java new file mode 100644 index 000000000..c54851b5c --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncInitializeBeanMethodInvokerTests.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.async; + +import com.alipay.sofa.runtime.sample.SampleService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.aop.framework.ProxyFactory; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link AsyncInitializeBeanMethodInvoker}. + * + * @author huzijie + * @version AsyncInitializeBeanMethodInvokerTests.java, v 0.1 2023年04月10日 10:41 AM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class AsyncInitializeBeanMethodInvokerTests { + + @Mock + private AsyncInitMethodManager asyncInitMethodManager; + + private final String currentThreadName = Thread.currentThread().getName(); + + private final String beanName = "test"; + + private SampleService asyncSampleService; + + private AsyncInitializeBeanMethodInvoker asyncInitializeBeanMethodInvoker; + + @BeforeEach + void setUp() { + ProxyFactory proxyFactory = new ProxyFactory(); + proxyFactory.setInterfaces(SampleService.class); + asyncInitializeBeanMethodInvoker = new AsyncInitializeBeanMethodInvoker( + asyncInitMethodManager, new AsyncSampleServiceImpl(), beanName, "service"); + proxyFactory.addAdvice(asyncInitializeBeanMethodInvoker); + asyncSampleService = (SampleService) proxyFactory.getProxy(); + } + + @Test + void invokeNormal() { + when(asyncInitMethodManager.isStartUpFinish()).thenReturn(true); + assertThat(asyncSampleService.service()).isEqualTo(currentThreadName); + } + + @Test + void invokeCallOtherMethod() throws ExecutionException, InterruptedException { + when(asyncInitMethodManager.isStartUpFinish()).thenReturn(false); + assertThat(asyncSampleService.service()).isEqualTo(null); + CompletableFuture future = CompletableFuture.supplyAsync(() -> asyncSampleService.test()); + assertThat(future.isDone()).isFalse(); + asyncInitializeBeanMethodInvoker.asyncMethodFinish(); + assertThat(future.get()).isNotEqualTo(currentThreadName); + } + + @Test + void invokeTwice() throws ExecutionException, InterruptedException { + when(asyncInitMethodManager.isStartUpFinish()).thenReturn(false); + assertThat(asyncSampleService.service()).isEqualTo(null); + CompletableFuture future = CompletableFuture.supplyAsync(() -> asyncSampleService.service()); + assertThat(future.isDone()).isFalse(); + asyncInitializeBeanMethodInvoker.asyncMethodFinish(); + assertThat(future.get()).isNotEqualTo(currentThreadName); + assertThat(asyncSampleService.service()).isEqualTo(currentThreadName); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncSampleServiceImpl.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncSampleServiceImpl.java new file mode 100644 index 000000000..e85bc0d31 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/async/AsyncSampleServiceImpl.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.async; + +import com.alipay.sofa.runtime.sample.SampleService; + +/** + * @author huzijie + * @version AsyncSampleServiceImpl.java, v 0.1 2023年04月10日 10:54 AM huzijie Exp $ + */ +public class AsyncSampleServiceImpl implements SampleService { + + @Override + public String service() { + Thread thread = Thread.currentThread(); + return thread.getName(); + } + + @Override + public String test() { + Thread thread = Thread.currentThread(); + return thread.getName(); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptorTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptorTests.java new file mode 100644 index 000000000..3b4693db2 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/ComponentContextRefreshInterceptorTests.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.context; + +import com.alipay.sofa.boot.context.SofaGenericApplicationContext; +import com.alipay.sofa.runtime.api.component.ComponentName; +import com.alipay.sofa.runtime.model.ComponentType; +import com.alipay.sofa.runtime.spi.component.ComponentInfo; +import com.alipay.sofa.runtime.spi.component.ComponentManager; +import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; +import com.alipay.sofa.runtime.spi.component.SofaRuntimeManager; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.Collections; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; + +/** + * Tests for {@link ComponentContextRefreshInterceptor}. + * + * @author huzijie + * @version ComponentContextRefreshInterceptorTests.java, v 0.1 2023年04月10日 11:22 AM huzijie Exp $ + */ +public class ComponentContextRefreshInterceptorTests { + + @Test + void afterRefreshWithNullThrowableShouldRegisterComponent() { + // Arrange + SofaRuntimeManager sofaRuntimeManager = Mockito.mock(SofaRuntimeManager.class); + ComponentManager componentManager = Mockito.mock(ComponentManager.class); + Mockito.when(sofaRuntimeManager.getComponentManager()).thenReturn(componentManager); + SofaRuntimeContext sofaRuntimeContext = Mockito.mock(SofaRuntimeContext.class); + Mockito.when(sofaRuntimeManager.getSofaRuntimeContext()).thenReturn(sofaRuntimeContext); + SofaGenericApplicationContext context = new SofaGenericApplicationContext(); + ComponentContextRefreshInterceptor interceptor = new ComponentContextRefreshInterceptor( + sofaRuntimeManager); + + // Act + interceptor.afterRefresh(context, null); + + // Assert + Mockito.verify(componentManager, times(1)).register(any()); + } + + @Test + void afterRefreshWithThrowableShouldUnregisterComponents() { + // Arrange + SofaRuntimeManager sofaRuntimeManager = Mockito.mock(SofaRuntimeManager.class); + ComponentManager componentManager = Mockito.mock(ComponentManager.class); + Mockito.when(sofaRuntimeManager.getComponentManager()).thenReturn(componentManager); + SofaGenericApplicationContext context = new SofaGenericApplicationContext(); + ComponentInfo componentInfo = Mockito.mock(ComponentInfo.class); + Mockito.when(componentInfo.getName()).thenReturn( + new ComponentName(new ComponentType("test"), "TestComponent")); + Mockito.when(componentManager.getComponentInfosByApplicationContext(context)).thenReturn( + Collections.singletonList(componentInfo)); + ComponentContextRefreshInterceptor interceptor = new ComponentContextRefreshInterceptor( + sofaRuntimeManager); + + // Act + interceptor.afterRefresh(context, new Throwable()); + + // Assert + Mockito.verify(componentManager, times(1)).unregister(any()); + } + +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/SpringContextComponentTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/SpringContextComponentTests.java new file mode 100644 index 000000000..16437781a --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/SpringContextComponentTests.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.context; + +import com.alipay.sofa.runtime.api.ServiceRuntimeException; +import com.alipay.sofa.runtime.api.component.ComponentName; +import com.alipay.sofa.runtime.api.component.Property; +import com.alipay.sofa.runtime.model.ComponentStatus; +import com.alipay.sofa.runtime.model.ComponentType; +import com.alipay.sofa.runtime.spi.component.Implementation; +import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringContextComponent}. + * + * @author huzijie + * @version SpringContextComponentTests.java, v 0.1 2023年04月10日 11:28 AM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class SpringContextComponentTests { + + @Mock + private ComponentName componentName; + + @Mock + private Implementation implementation; + + @Mock + private SofaRuntimeContext sofaRuntimeContext; + + @Test + void getTypeShouldReturnSpringComponentType() { + // Arrange + SpringContextComponent component = new SpringContextComponent(componentName, + implementation, sofaRuntimeContext); + + // Act + ComponentType result = component.getType(); + + // Assert + assertThat(result).isEqualTo(SpringContextComponent.SPRING_COMPONENT_TYPE); + } + + @Test + void getPropertiesShouldReturnNull() { + // Arrange + SpringContextComponent component = new SpringContextComponent(componentName, + implementation, sofaRuntimeContext); + + // Act + Map result = component.getProperties(); + + // Assert + assertThat(result).isNull(); + } + + @Test + void getApplicationContextShouldReturnTarget() { + // Arrange + GenericApplicationContext applicationContext = new GenericApplicationContext(); + Implementation implementation = new SpringContextImplementation(applicationContext); + SpringContextComponent component = new SpringContextComponent(componentName, + implementation, sofaRuntimeContext); + + // Act + ApplicationContext result = component.getApplicationContext(); + + // Assert + assertThat(result).isEqualTo(applicationContext); + } + + @Test + void activateShouldSetComponentStatusToActivated() throws ServiceRuntimeException { + // Arrange + SpringContextComponent component = new SpringContextComponent(componentName, + implementation, sofaRuntimeContext); + + // Act + component.register(); + component.resolve(); + component.activate(); + + // Assert + assertThat(component.getState()).isEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void activateShouldNotSetComponentStatusToActivatedIfAlreadyResolved() + throws ServiceRuntimeException { + // Arrange + SpringContextComponent component = new SpringContextComponent(componentName, + implementation, sofaRuntimeContext); + + // Act + component.activate(); + + // Assert + assertThat(component.getState()).isEqualTo(ComponentStatus.UNREGISTERED); + } + + @Test + void deactivateShouldCloseApplicationContextAndSetComponentStatusToDeactivated() + throws ServiceRuntimeException { + // Arrange + GenericApplicationContext applicationContext = Mockito + .mock(GenericApplicationContext.class); + Implementation implementation = new SpringContextImplementation(applicationContext); + SpringContextComponent component = new SpringContextComponent(componentName, + implementation, sofaRuntimeContext); + + // Act + component.deactivate(); + + // Assert + Mockito.verify(applicationContext).close(); + assertThat(component.getState()).isEqualTo(ComponentStatus.UNREGISTERED); + } + +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/SpringContextImplementationTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/SpringContextImplementationTests.java new file mode 100644 index 000000000..6bea02be5 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/context/SpringContextImplementationTests.java @@ -0,0 +1,134 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.context; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.GenericApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringContextImplementation}. + * + * @author huzijie + * @version SpringContextImplementationTests.java, v 0.1 2023年04月10日 11:36 AM huzijie Exp $ + */ +public class SpringContextImplementationTests { + + @Test + void getNameShouldReturnDisplayNameOfApplicationContext() { + // Arrange + ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); + Mockito.when(applicationContext.getDisplayName()).thenReturn("TestContext"); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext); + + // Act + String result = implementation.getName(); + + // Assert + assertThat(result).isEqualTo("TestContext"); + } + + @Test + void getTargetShouldReturnApplicationContext() { + // Arrange + ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext); + + // Act + Object result = implementation.getTarget(); + + // Assert + assertThat(result).isEqualTo(applicationContext); + } + + @Test + void getTargetClassShouldReturnClassOfApplicationContext() { + // Arrange + ApplicationContext applicationContext = new GenericApplicationContext(); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext); + + // Act + Class result = implementation.getTargetClass(); + + // Assert + assertThat(result).isEqualTo(applicationContext.getClass()); + } + + @Test + void isSingletonShouldReturnFalse() { + // Arrange + ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext); + + // Act + boolean result = implementation.isSingleton(); + + // Assert + assertThat(result).isFalse(); + } + + @Test + void isLazyInitShouldReturnFalse() { + // Arrange + ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext); + + // Act + boolean result = implementation.isLazyInit(); + + // Assert + assertThat(result).isFalse(); + } + + @Test + void setTargetShouldSetApplicationContext() { + // Arrange + ApplicationContext applicationContext1 = Mockito.mock(ApplicationContext.class); + ApplicationContext applicationContext2 = Mockito.mock(ApplicationContext.class); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext1); + + // Act + implementation.setTarget(applicationContext2); + + // Assert + assertThat(implementation.getTarget()).isEqualTo(applicationContext2); + } + + @Test + void isFactoryShouldReturnFalse() { + // Arrange + ApplicationContext applicationContext = Mockito.mock(ApplicationContext.class); + SpringContextImplementation implementation = new SpringContextImplementation( + applicationContext); + + // Act + boolean result = implementation.isFactory(); + + // Assert + assertThat(result).isFalse(); + } + +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/client/ExtensionClientImplTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/client/ExtensionClientImplTests.java new file mode 100644 index 000000000..d77a8a9ff --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/client/ExtensionClientImplTests.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.ext.client; + +import com.alipay.sofa.runtime.api.client.param.ExtensionParam; +import com.alipay.sofa.runtime.api.client.param.ExtensionPointParam; +import com.alipay.sofa.runtime.ext.component.ExtensionComponent; +import com.alipay.sofa.runtime.ext.component.ExtensionPointComponent; +import com.alipay.sofa.runtime.spi.component.ComponentManager; +import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.w3c.dom.Element; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link ExtensionClientImpl}. + * + * @author huzijie + * @version ExtensionClientImplTests.java, v 0.1 2023年04月10日 11:46 AM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class ExtensionClientImplTests { + + @Mock + private ComponentManager componentManager; + + @Mock + private SofaRuntimeContext sofaRuntimeContext; + + @Mock + private Element element; + + @InjectMocks + private ExtensionClientImpl extensionClient; + + @Test + void publishExtensionShouldRegisterExtensionComponent() { + when(sofaRuntimeContext.getComponentManager()).thenReturn(componentManager); + // Arrange + ExtensionParam extensionParam = new ExtensionParam(); + extensionParam.setElement(element); + extensionParam.setTargetInstanceName("testInstance"); + extensionParam.setTargetName("testTarget"); + + // Act + extensionClient.publishExtension(extensionParam); + + // Assert + verify(componentManager).register(Mockito.any(ExtensionComponent.class)); + } + + @Test + void publishExtensionShouldThrowExceptionWhenExtensionParamIsNull() { + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtension(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("extensionParam can not be null."); + } + + @Test + void publishExtensionShouldThrowExceptionWhenContributionElementIsNull() { + // Arrange + ExtensionParam extensionParam = new ExtensionParam(); + + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtension(extensionParam)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Extension contribution element can not be null."); + } + + @Test + void publishExtensionShouldThrowExceptionWhenTargetInstanceNameIsNull() { + // Arrange + ExtensionParam extensionParam = new ExtensionParam(); + extensionParam.setElement(element); + + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtension(extensionParam)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Extension target instance name can not be null."); + } + + @Test + void publishExtensionShouldThrowExceptionWhenTargetNameIsNull() { + // Arrange + ExtensionParam extensionParam = new ExtensionParam(); + extensionParam.setElement(element); + extensionParam.setTargetInstanceName("testInstance"); + + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtension(extensionParam)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Extension target name can not be null."); + } + + @Test + void publishExtensionPoint_shouldRegisterExtensionPointComponent() { + when(sofaRuntimeContext.getComponentManager()).thenReturn(componentManager); + // Arrange + ExtensionPointParam extensionPointParam = new ExtensionPointParam(); + extensionPointParam.setName("testExtensionPoint"); + extensionPointParam.setContributionClass(this.getClass()); + extensionPointParam.setTargetName("testTarget"); + extensionPointParam.setTarget(new Object()); + + // Act + extensionClient.publishExtensionPoint(extensionPointParam); + + // Assert + verify(componentManager).register(Mockito.any(ExtensionPointComponent.class)); + } + + @Test + void publishExtensionPointShouldThrowExceptionWhenExtensionPointParamIsNull() { + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtensionPoint(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("extensionPointParam can not be null."); + } + + @Test + void publishExtensionPointShouldThrowExceptionWhenNameIsNull() { + // Arrange + ExtensionPointParam extensionPointParam = new ExtensionPointParam(); + + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtensionPoint(extensionPointParam)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Extension point name can not be null."); + } + + @Test + void publishExtensionPointShouldThrowExceptionWhenContributionClassIsNull() { + // Arrange + ExtensionPointParam extensionPointParam = new ExtensionPointParam(); + extensionPointParam.setName("testExtensionPoint"); + + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtensionPoint(extensionPointParam)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Extension point contribution can not be null."); + + } + + @Test + void publishExtensionPointShouldThrowExceptionWhenTargetIsNull() { + // Arrange + ExtensionPointParam extensionPointParam = new ExtensionPointParam(); + extensionPointParam.setName("testExtensionPoint"); + extensionPointParam.setContributionClass(this.getClass()); + + // Act & Assert + assertThatThrownBy(() -> extensionClient.publishExtensionPoint(extensionPointParam)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Extension point target can not be null."); + + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionComponentTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionComponentTests.java new file mode 100644 index 000000000..ab300cd29 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionComponentTests.java @@ -0,0 +1,348 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.ext.component; + +import com.alipay.sofa.runtime.api.component.ComponentName; +import com.alipay.sofa.runtime.ext.Extensible; +import com.alipay.sofa.runtime.ext.Extension; +import com.alipay.sofa.runtime.ext.ExtensionPoint; +import com.alipay.sofa.runtime.model.ComponentStatus; +import com.alipay.sofa.runtime.model.ComponentType; +import com.alipay.sofa.runtime.spi.component.ComponentInfo; +import com.alipay.sofa.runtime.spi.component.ComponentManager; +import com.alipay.sofa.runtime.spi.component.Implementation; +import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; +import com.alipay.sofa.runtime.spi.health.HealthResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link ExtensionComponent}. + * + * @author huzijie + * @version ExtensionComponentTests.java, v 0.1 2023年04月10日 2:20 PM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class ExtensionComponentTests { + + private final ComponentName extensionComponentName = new ComponentName(new ComponentType( + "ext"), "ext"); + + @Mock + private SofaRuntimeContext sofaRuntimeContext; + + @Mock + private ComponentManager componentManager; + + @Mock + private ExtensionInternal extension; + + @Mock + private ExtensionPointComponent componentInfo; + + @Mock + private Implementation implementation; + + private ExtensionComponent extensionComponent; + + @BeforeEach + public void setUp() { + when(extension.getTargetComponentName()).thenReturn(extensionComponentName); + extensionComponent = new ExtensionComponent(extension, sofaRuntimeContext); + } + + @Test + void getTypeShouldReturnExtensionComponentType() { + assertThat(extensionComponent.getType()).isEqualTo( + ExtensionComponent.EXTENSION_COMPONENT_TYPE); + } + + @Test + void getPropertiesShouldReturnNull() { + assertThat(extensionComponent.getProperties()).isNull(); + } + + @Test + void resolveExtensionComponent() { + boolean result = extensionComponent.resolve(); + assertThat(result).isFalse(); + + extensionComponent.register(); + + ComponentInfo componentInfo = mock(ComponentInfo.class); + when(sofaRuntimeContext.getComponentManager()).thenReturn(componentManager); + when(componentManager.getComponentInfo(extensionComponentName)).thenReturn(componentInfo); + when(componentInfo.isActivated()).thenReturn(false); + + result = extensionComponent.resolve(); + assertThat(result).isFalse(); + + when(componentInfo.isActivated()).thenReturn(true); + result = extensionComponent.resolve(); + assertThat(result).isTrue(); + assertThat(extensionComponent.getState()).isEqualTo(ComponentStatus.RESOLVED); + } + + @Test + void unActiveExtensionComponentWhenNotRegister() { + extensionComponent.activate(); + assertThat(extensionComponent.getState()).isNotEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void activeExtensionComponentWithExtensibleInterface() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleClass mockExtensibleClass = new MockExtensibleClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + extensionComponent.activate(); + assertThat(mockExtensibleClass.isRegister()).isTrue(); + assertThat(extensionComponent.getState()).isEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void activeExtensionComponentLoadContributionsSuccess() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleClass mockExtensibleClass = new MockExtensibleClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + ExtensionPointInternal extensionPoint = mock(ExtensionPointInternal.class); + when(componentInfo.getExtensionPoint()).thenReturn(extensionPoint); + when(extensionPoint.hasContribution()).thenReturn(true); + + extensionComponent.activate(); + assertThat(mockExtensibleClass.isRegister()).isTrue(); + assertThat(extensionComponent.getState()).isEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void activeExtensionComponentLoadContributionsException() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleClass mockExtensibleClass = new MockExtensibleClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + ExtensionPoint extensionPoint = mock(ExtensionPoint.class); + when(componentInfo.getExtensionPoint()).thenReturn(extensionPoint); + when(extensionPoint.hasContribution()).thenReturn(true); + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isExtensionFailureInsulating()).thenReturn(false); + when(properties.isSkipExtensionHealthCheck()).thenReturn(false); + + extensionComponent.activate(); + assertThat(mockExtensibleClass.isRegister()).isTrue(); + assertThat(extensionComponent.getState()).isEqualTo(ComponentStatus.ACTIVATED); + assertThat(extensionComponent.isHealthy().isHealthy()).isTrue(); + } + + @Test + void activeExtensionComponentLoadContributionsThrowException() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleClass mockExtensibleClass = new MockExtensibleClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + ExtensionPoint extensionPoint = mock(ExtensionPoint.class); + when(componentInfo.getExtensionPoint()).thenReturn(extensionPoint); + when(extensionPoint.hasContribution()).thenReturn(true); + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isExtensionFailureInsulating()).thenReturn(true); + when(properties.isSkipExtensionHealthCheck()).thenReturn(false); + + extensionComponent.activate(); + assertThat(mockExtensibleClass.isRegister()).isTrue(); + assertThat(extensionComponent.getState()).isEqualTo(ComponentStatus.ACTIVATED); + assertThat(extensionComponent.isHealthy().isHealthy()).isFalse(); + } + + @Test + void activeExtensionComponentWithNormalExtensibleClass() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleNormalClass mockExtensibleClass = new MockExtensibleNormalClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + extensionComponent.activate(); + assertThat(mockExtensibleClass.isRegister()).isTrue(); + assertThat(extensionComponent.getState()).isEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void activeExtensionComponentWithNormalClassNoExtensibleMethod() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + NoExtensibleNormalClass mockExtensibleClass = new NoExtensibleNormalClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + assertThatThrownBy(() -> extensionComponent.activate()).isInstanceOf(RuntimeException.class) + .hasRootCauseMessage("SOFA-BOOT-01-01001: Failed to find method 'registerExtension' in class [com.alipay.sofa.runtime.ext.component.ExtensionComponentTests.NoExtensibleNormalClass]"); + assertThat(extensionComponent.getState()).isNotEqualTo(ComponentStatus.ACTIVATED); + + } + + @Test + void activeExtensionComponentWithExtensionException() { + registerAndResolve(); + + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleClass mockExtensibleClass = new MockExtensibleClass(); + mockExtensibleClass.setThrowException(true); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + + assertThatThrownBy(() -> extensionComponent.activate()).isInstanceOf(RuntimeException.class) + .hasMessageContaining("01-01000") + .hasRootCauseMessage("extension fail"); + assertThat(extensionComponent.getState()).isNotEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void isHealthyWhenSkipCheck() { + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isSkipExtensionHealthCheck()).thenReturn(true); + + HealthResult healthResult = extensionComponent.isHealthy(); + assertThat(healthResult.isHealthy()).isTrue(); + } + + @Test + void isHealthyWhenException() { + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isSkipExtensionHealthCheck()).thenReturn(false); + extensionComponent.exception(new RuntimeException("fail")); + + HealthResult healthResult = extensionComponent.isHealthy(); + assertThat(healthResult.isHealthy()).isFalse(); + assertThat(healthResult.getHealthReport()).contains( + "Extension loadContributions error: fail"); + } + + @Test + void isHealthyWhenActive() { + registerAndResolve(); + when(componentInfo.getImplementation()).thenReturn(implementation); + MockExtensibleClass mockExtensibleClass = new MockExtensibleClass(); + when(implementation.getTarget()).thenReturn(mockExtensibleClass); + extensionComponent.activate(); + + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isSkipExtensionHealthCheck()).thenReturn(false); + + HealthResult healthResult = extensionComponent.isHealthy(); + assertThat(healthResult.isHealthy()).isTrue(); + } + + @Test + void isHealthyWhenUnResolve() { + extensionComponent.activate(); + + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isSkipExtensionHealthCheck()).thenReturn(false); + + HealthResult healthResult = extensionComponent.isHealthy(); + assertThat(healthResult.isHealthy()).isFalse(); + assertThat(healthResult.getHealthReport()).contains( + "Can not find corresponding ExtensionPoint"); + } + + @Test + void isHealthyWhenRegisterExtensionException() { + registerAndResolve(); + + SofaRuntimeContext.Properties properties = mock(SofaRuntimeContext.Properties.class); + when(sofaRuntimeContext.getProperties()).thenReturn(properties); + when(properties.isSkipExtensionHealthCheck()).thenReturn(false); + + HealthResult healthResult = extensionComponent.isHealthy(); + assertThat(healthResult.isHealthy()).isFalse(); + assertThat(healthResult.getHealthReport()).contains("Extension registerExtension error"); + } + + private void registerAndResolve() { + extensionComponent.register(); + when(sofaRuntimeContext.getComponentManager()).thenReturn(componentManager); + when(componentManager.getComponentInfo(extensionComponentName)).thenReturn(componentInfo); + when(componentInfo.isActivated()).thenReturn(true); + extensionComponent.resolve(); + } + + static class MockExtensibleClass implements Extensible { + + public boolean throwException = false; + + public boolean register = false; + + @Override + public void registerExtension(Extension extension) throws Exception { + if (throwException) { + throw new RuntimeException("extension fail"); + } + register = true; + } + + @Override + public void unregisterExtension(Extension extension) throws Exception { + + } + + public boolean isRegister() { + return register; + } + + public void setThrowException(boolean throwException) { + this.throwException = throwException; + } + } + + public static class MockExtensibleNormalClass { + + public boolean register = false; + + public void registerExtension(Extension extension) { + register = true; + } + + public boolean isRegister() { + return register; + } + } + + public static class NoExtensibleNormalClass { + + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionImplTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionImplTests.java new file mode 100644 index 000000000..90cabd1e8 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionImplTests.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.ext.component; + +import com.alipay.sofa.runtime.api.component.ComponentName; +import com.alipay.sofa.runtime.model.ComponentType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.w3c.dom.Element; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ExtensionImpl}. + * + * @author huzijie + * @version ExtensionImplTests.java, v 0.1 2023年04月10日 12:12 PM huzijie Exp $ + */ +public class ExtensionImplTests { + + private final ComponentName componentName = new ComponentName(new ComponentType("extension"), + "name"); + + private final ComponentName componentTarget = new ComponentName(new ComponentType("extension"), + "target"); + + private ExtensionImpl extension; + + @BeforeEach + void setUp() { + extension = new ExtensionImpl(componentName, "point"); + } + + @Test + void testDispose() { + extension.dispose(); + assertThat(extension.getElement()).isNull(); + assertThat(extension.getContributions()).isNull(); + } + + @Test + void testGettersAndSetters() { + extension.setElement(null); + assertThat(extension.getElement()).isNull(); + + extension.setElement(Mockito.mock(Element.class)); + assertThat(extension.getElement()).isNotNull(); + + assertThat(extension.getExtensionPoint()).isEqualTo("point"); + + assertThat(extension.getComponentName()).isEqualTo(componentName); + + assertThat(extension.getTargetComponentName()).isNull(); + + extension.setTargetComponentName(componentTarget); + assertThat(extension.getTargetComponentName()).isEqualTo(componentTarget); + + assertThat(extension.getContributions()).isNull(); + + Object[] contributions = new Object[] { "contrib1", "contrib2" }; + extension.setContributions(contributions); + assertThat(extension.getContributions()).isEqualTo(contributions); + + assertThat(extension.getAppClassLoader()).isNull(); + } + + @Test + void testToString() { + assertThat(extension.toString()).isEqualTo( + "ExtensionImpl {target: extension:name, point:point}"); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionPointComponentTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionPointComponentTests.java new file mode 100644 index 000000000..d0d702c5e --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionPointComponentTests.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.ext.component; + +import com.alipay.sofa.runtime.api.ServiceRuntimeException; +import com.alipay.sofa.runtime.ext.ExtensionPoint; +import com.alipay.sofa.runtime.model.ComponentStatus; +import com.alipay.sofa.runtime.spi.component.ComponentInfo; +import com.alipay.sofa.runtime.spi.component.ComponentManager; +import com.alipay.sofa.runtime.spi.component.Implementation; +import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link ExtensionPointComponent}. + * + * @author huzijie + * @version ExtensionPointComponentTests.java, v 0.1 2023年04月10日 3:24 PM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class ExtensionPointComponentTests { + + @Mock + private ExtensionPoint extensionPoint; + + @Mock + private ComponentManager componentManager; + + @Mock + private SofaRuntimeContext sofaRuntimeContext; + + @Mock + private Implementation implementation; + + private ExtensionPointComponent component; + + @BeforeEach + public void setUp() { + component = new ExtensionPointComponent(extensionPoint, sofaRuntimeContext, implementation); + } + + @Test + void testActivate() throws ServiceRuntimeException { + when(sofaRuntimeContext.getComponentManager()).thenReturn(componentManager); + List componentInfoList = new ArrayList<>(); + when(componentManager.getComponents()).thenReturn(componentInfoList); + component.register(); + component.resolve(); + component.activate(); + assertThat(component.getState()).isEqualTo(ComponentStatus.ACTIVATED); + } + + @Test + void testDeactivate() throws ServiceRuntimeException { + when(sofaRuntimeContext.getComponentManager()).thenReturn(componentManager); + List componentInfoList = new ArrayList<>(); + when(componentManager.getComponents()).thenReturn(componentInfoList); + component.register(); + component.resolve(); + component.activate(); + component.deactivate(); + assertThat(component.getState()).isEqualTo(ComponentStatus.RESOLVED); + } + + @Test + void testGetType() { + assertThat(component.getType()).isEqualTo( + ExtensionPointComponent.EXTENSION_POINT_COMPONENT_TYPE); + } + + @Test + void testGetProperties() { + assertThat(component.getProperties()).isNull(); + } + + @Test + void testGetExtensionPoint() { + assertThat(component.getExtensionPoint()).isEqualTo(extensionPoint); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionPointImplTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionPointImplTests.java new file mode 100644 index 000000000..cd7c4efda --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/component/ExtensionPointImplTests.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.ext.component; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.FilteredClassLoader; + +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ExtensionPointImpl}. + * + * @author huzijie + * @version ExtensionPointImplTests.java, v 0.1 2023年04月10日 2:07 PM huzijie Exp $ + */ +public class ExtensionPointImplTests { + + private final ClassLoader mockClassLoader = new FilteredClassLoader("ext"); + + @Test + void constructor_shouldInitializeFields() { + // given + String name = "testExtensionPoint"; + Class contributionClass = String.class; + + // when + ExtensionPointImpl extensionPoint = new ExtensionPointImpl(name, contributionClass); + + // then + assertThat(extensionPoint.name).isEqualTo(name); + assertThat(extensionPoint.contributions).containsExactly(contributionClass); + } + + @Test + void setBeanClassLoaderShouldSetClassLoader() { + // given + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + + // when + extensionPoint.setBeanClassLoader(mockClassLoader); + + // then + assertThat(extensionPoint.beanClassLoader).isEqualTo(mockClassLoader); + } + + @Test + void getContributionsShouldReturnContributions() { + // given + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + List> contributions = List.of(String.class, Integer.class); + extensionPoint.contributions = contributions; + + // when + List> result = extensionPoint.getContributions(); + + // then + assertThat(result).isEqualTo(contributions); + } + + @Test + void hasContributionShouldReturnTrueIfContributionsExist() { + // given + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + extensionPoint.contributions = Collections.singletonList(String.class); + + // when + boolean result = extensionPoint.hasContribution(); + + // then + assertThat(result).isTrue(); + } + + @Test + void hasContributionShouldReturnFalseIfNoContributionsExist() { + // given + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + + // when + boolean result = extensionPoint.hasContribution(); + + // then + assertThat(result).isFalse(); + } + + @Test + void getNameShouldReturnName() { + // given + String name = "testExtensionPoint"; + ExtensionPointImpl extensionPoint = new ExtensionPointImpl(name, null); + + // when + String result = extensionPoint.getName(); + + // then + assertThat(result).isEqualTo(name); + } + + @Test + void getDocumentationShouldReturnDocumentation() { + // given + String documentation = "testDocumentation"; + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + extensionPoint.documentation = documentation; + + // when + String result = extensionPoint.getDocumentation(); + + // then + assertThat(result).isEqualTo(documentation); + } + + @Test + void addContributionShouldAddContribution() { + // given + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + Class contributionClass1 = String.class; + Class contributionClass2 = Integer.class; + + // when + extensionPoint.addContribution(contributionClass1); + extensionPoint.addContribution(contributionClass2); + + // then + assertThat(extensionPoint.contributions).containsExactly(contributionClass1, + contributionClass2); + } + + @Test + void addContributionShouldResolveClassNameAndAddContribution() throws ClassNotFoundException { + // given + ExtensionPointImpl extensionPoint = new ExtensionPointImpl("testExtensionPoint", null); + String className = "java.lang.String"; + + // when + extensionPoint.addContribution(className); + + // then + assertThat(extensionPoint.contributions).containsExactly(String.class); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/spring/SpringImplementationImplTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/spring/SpringImplementationImplTests.java new file mode 100644 index 000000000..89a3e5c41 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/ext/spring/SpringImplementationImplTests.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.ext.spring; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.ApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link SpringImplementationImpl}. + * + * @author huzijie + * @version SpringImplementationImplTests.java, v 0.1 2023年04月10日 3:31 PM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class SpringImplementationImplTests { + + @Mock + private ApplicationContext applicationContext; + + @Test + void getTarget() { + SpringImplementationImpl implementation = new SpringImplementationImpl("testBean", + applicationContext); + Object target = new Object(); + implementation.setTarget(target); + assertThat(implementation.getTarget()).isSameAs(applicationContext.getBean("testBean")); + } + + @Test + void getTargetClass() { + SpringImplementationImpl implementation = new SpringImplementationImpl("testBean", + applicationContext); + when(applicationContext.getBean("testBean")).thenReturn(new Object()); + assertThat(implementation.getTargetClass()).isEqualTo( + applicationContext.getBean("testBean").getClass()); + } + + @Test + void getName() { + SpringImplementationImpl implementation = new SpringImplementationImpl("testBean", + applicationContext); + assertThat(implementation.getName()).isEqualTo("testBean"); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/filter/JvmFilterContextTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/filter/JvmFilterContextTests.java new file mode 100644 index 000000000..3fb6d2215 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/filter/JvmFilterContextTests.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.filter; + +import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; +import org.aopalliance.intercept.MethodInvocation; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link JvmFilterContext}. + * + * @author huzijie + * @version JvmFilterContextTests.java, v 0.1 2023年04月10日 11:39 AM huzijie Exp $ + */ +public class JvmFilterContextTests { + + @Test + void getInvokeResultShouldReturnSetInvokeResult() { + // Arrange + Object invokeResult = new Object(); + JvmFilterContext context = new JvmFilterContext(); + + // Act + context.setInvokeResult(invokeResult); + Object result = context.getInvokeResult(); + + // Assert + assertThat(result).isEqualTo(invokeResult); + } + + @Test + void getSofaRuntimeContextShouldReturnSetSofaRuntimeContext() { + // Arrange + SofaRuntimeContext sofaRuntimeContext = Mockito.mock(SofaRuntimeContext.class); + JvmFilterContext context = new JvmFilterContext(); + + // Act + context.setSofaRuntimeContext(sofaRuntimeContext); + SofaRuntimeContext result = context.getSofaRuntimeContext(); + + // Assert + assertThat(result).isEqualTo(sofaRuntimeContext); + } + + @Test + void getMethodInvocationShouldReturnSetMethodInvocation() { + // Arrange + MethodInvocation methodInvocation = Mockito.mock(MethodInvocation.class); + JvmFilterContext context = new JvmFilterContext(); + + // Act + context.setMethodInvocation(methodInvocation); + MethodInvocation result = context.getMethodInvocation(); + + // Assert + assertThat(result).isEqualTo(methodInvocation); + } + + @Test + void getExceptionShouldReturnSetException() { + // Arrange + Throwable exception = new Exception(); + JvmFilterContext context = new JvmFilterContext(); + + // Act + context.setException(exception); + Throwable result = context.getException(); + + // Assert + assertThat(result).isEqualTo(exception); + } + +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/ClientFactoryImplTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/ClientFactoryImplTests.java new file mode 100644 index 000000000..d73853511 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/ClientFactoryImplTests.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.impl; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collection; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ClientFactoryImpl}. + * + * @author huzijie + * @version ClientFactoryImplTests.java, v 0.1 2023年04月10日 4:06 PM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class ClientFactoryImplTests { + + @InjectMocks + private ClientFactoryImpl clientFactory; + + @Test + public void registerClient() { + // Given + Class clientType = String.class; + Object clientInstance = "test"; + + // When + clientFactory.registerClient(clientType, clientInstance); + + // Then + assertThat(clientFactory.getAllClientTypes()).contains(clientType); + } + + @Test + public void registerClientWithExistingClientType() { + // Given + Class clientType = String.class; + Object clientInstance1 = "test1"; + Object clientInstance2 = "test2"; + + // When + clientFactory.registerClient(clientType, clientInstance1); + clientFactory.registerClient(clientType, clientInstance2); + + // Then + assertThat(clientFactory.getAllClientTypes()).contains(clientType); + assertThat(clientFactory.getClient(clientType)).isEqualTo(clientInstance1); + } + + @Test + public void getClient() { + // Given + Class clientType = String.class; + Object clientInstance = "test"; + clientFactory.registerClient(clientType, clientInstance); + + // When + String client = (String) clientFactory.getClient(clientType); + + // Then + assertThat(client).isEqualTo(clientInstance); + } + + @Test + public void getAllClientTypes() { + // Given + Class clientType1 = String.class; + Class clientType2 = Integer.class; + Object clientInstance1 = "test"; + Object clientInstance2 = 123; + clientFactory.registerClient(clientType1, clientInstance1); + clientFactory.registerClient(clientType2, clientInstance2); + + // When + Collection> allClientTypes = clientFactory.getAllClientTypes(); + + // Then + assertThat(allClientTypes).containsExactlyInAnyOrder(clientType1, clientType2); + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/SofaRuntimeManagerShutDownTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/ComponentManagerImplTests.java similarity index 56% rename from sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/SofaRuntimeManagerShutDownTests.java rename to sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/ComponentManagerImplTests.java index 89c9374ba..378a1d4eb 100644 --- a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/SofaRuntimeManagerShutDownTests.java +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/ComponentManagerImplTests.java @@ -16,6 +16,8 @@ */ package com.alipay.sofa.runtime.impl; +import com.alipay.sofa.boot.util.LogOutPutUtils; +import com.alipay.sofa.runtime.api.ServiceRuntimeException; import com.alipay.sofa.runtime.api.component.ComponentName; import com.alipay.sofa.runtime.context.SpringContextComponent; import com.alipay.sofa.runtime.context.SpringContextImplementation; @@ -25,24 +27,133 @@ import com.alipay.sofa.runtime.spi.component.ComponentManager; import com.alipay.sofa.runtime.spi.component.ComponentNameFactory; import com.alipay.sofa.runtime.spi.component.SofaRuntimeContext; -import com.alipay.sofa.runtime.spi.component.SofaRuntimeManager; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.boot.test.system.CapturedOutput; +import org.springframework.boot.test.system.OutputCaptureExtension; import org.springframework.context.support.GenericApplicationContext; import static com.alipay.sofa.runtime.context.SpringContextComponent.SPRING_COMPONENT_TYPE; import static com.alipay.sofa.runtime.sample.DemoComponent.DEMO_COMPONENT_TYPE; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** - * Tests for {@link SofaRuntimeManager#shutdown()}. + * Tests for {@link ComponentManagerImpl}. * * @author huzijie - * @version SofaRuntimeManagerShutDownTests.java, v 0.1 2022年04月29日 5:19 PM huzijie Exp $ + * @version ComponentManagerImplTests.java, v 0.1 2023年04月10日 3:37 PM huzijie Exp $ */ -public class SofaRuntimeManagerShutDownTests { +@ExtendWith({ MockitoExtension.class, OutputCaptureExtension.class }) +public class ComponentManagerImplTests { + + static { + LogOutPutUtils.openOutPutForLoggers(ComponentManagerImpl.class); + } + + @Mock + private ClientFactoryInternal clientFactoryInternal; + + @Mock + private DemoComponent componentInfoA; + + @Mock + private DemoComponent componentInfoB; + + private ComponentManagerImpl componentManager; private final ClientFactoryInternal clientFactory = new ClientFactoryImpl(); + @BeforeEach + public void setUp() { + componentManager = new ComponentManagerImpl(clientFactoryInternal, this.getClass() + .getClassLoader()); + } + + @Test + public void registerAndGetComponents() { + componentInfoA = new DemoComponent("A"); + componentInfoB = new DemoComponent("B"); + componentManager.register(componentInfoA); + + assertThat(componentManager.registerAndGet(componentInfoB)).isEqualTo(componentInfoB); + assertThat(componentManager.getComponentInfos()).contains(componentInfoA, componentInfoB); + assertThat(componentManager.getComponents()).contains(componentInfoA, componentInfoB); + assertThat(componentManager.getComponentTypes()).containsExactly(componentInfoA.getType()); + assertThat(componentManager.getComponentInfosByType(componentInfoA.getType())) + .containsExactly(componentInfoA, componentInfoB); + assertThat(componentManager.getComponentInfo(componentInfoA.getName())).isEqualTo( + componentInfoA); + assertThat(componentManager.getComponentInfosByApplicationContext(null)).containsExactly( + componentInfoA, componentInfoB); + } + + @Test + public void unRegister() { + componentInfoA = new DemoComponent("A"); + componentManager.register(componentInfoA); + assertThat(componentManager.getComponents()).contains(componentInfoA); + assertThat(componentManager.getComponentInfosByType(componentInfoA.getType())) + .containsExactly(componentInfoA); + + componentManager.unregister(componentInfoA); + assertThat(componentManager.getComponents()).doesNotContain(componentInfoA); + assertThat(componentManager.getComponentInfosByType(componentInfoA.getType())) + .doesNotContain(componentInfoA); + } + + @Test + public void resolvePendingResolveComponent() { + componentInfoA = new DemoComponent("A"); + componentManager.register(componentInfoA); + componentInfoA.unresolve(); + + componentInfoA.setActivateException(true); + componentManager.resolvePendingResolveComponent(componentInfoA.getName()); + + componentInfoA.setActivateException(false); + componentInfoA.activate(); + assertThat(componentInfoA.isHealthy().isHealthy()).isFalse(); + assertThat(componentInfoA.isHealthy().getHealthReport()).contains("activate error"); + } + + @Test + public void registerDuplicate() { + componentInfoA = new DemoComponent("A"); + assertThat(componentManager.registerAndGet(componentInfoA)).isEqualTo(componentInfoA); + + componentInfoB = new DemoComponent("A"); + assertThat(componentManager.registerAndGet(componentInfoB)).isEqualTo(componentInfoA); + + componentInfoB.setCanBeDuplicate(false); + assertThatThrownBy(() -> componentManager.register(componentInfoB)).isInstanceOf(ServiceRuntimeException.class) + .hasMessageContaining("01-03002"); + } + + @Test + public void registerException(CapturedOutput capturedOutput) { + componentInfoA = new DemoComponent("A"); + componentInfoA.setRegisterException(true); + + assertThat(componentManager.registerAndGet(componentInfoA)).isNull(); + assertThat(capturedOutput.getOut()).contains("01-03003"); + assertThat(capturedOutput.getOut()).contains(componentInfoA.getName().toString()); + } + + @Test + public void resolveException(CapturedOutput capturedOutput) { + componentInfoA = new DemoComponent("A"); + componentInfoA.setResolveException(true); + + assertThat(componentManager.registerAndGet(componentInfoA)).isEqualTo(componentInfoA); + assertThat(componentInfoA.isHealthy().isHealthy()).isFalse(); + assertThat(capturedOutput.getOut()).contains("01-03004"); + assertThat(capturedOutput.getOut()).contains(componentInfoA.getName().toString()); + } + @Test public void normalShutdown() { ComponentManager componentManager = initComponentManager(false, false); diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/StandardSofaRuntimeManagerTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/StandardSofaRuntimeManagerTests.java new file mode 100644 index 000000000..401fba572 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/impl/StandardSofaRuntimeManagerTests.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.impl; + +import com.alipay.sofa.boot.context.SofaGenericApplicationContext; +import com.alipay.sofa.runtime.spi.client.ClientFactoryInternal; +import com.alipay.sofa.runtime.spi.spring.RuntimeShutdownAware; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.context.support.GenericApplicationContext; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link StandardSofaRuntimeManager}. + * + * @author huzijie + * @version StandardSofaRuntimeManagerTests.java, v 0.1 2023年04月10日 4:10 PM huzijie Exp $ + */ +@ExtendWith(MockitoExtension.class) +public class StandardSofaRuntimeManagerTests { + + @Mock + private ClientFactoryInternal clientFactoryInternal; + + private StandardSofaRuntimeManager sofaRuntimeManager; + + @BeforeEach + public void setUp() { + GenericApplicationContext applicationContext = new SofaGenericApplicationContext(); + sofaRuntimeManager = new StandardSofaRuntimeManager("testApp", this.getClass() + .getClassLoader(), clientFactoryInternal); + sofaRuntimeManager.setApplicationContext(applicationContext); + } + + @Test + public void getters() { + assertThat(sofaRuntimeManager.getAppName()).isEqualTo("testApp"); + assertThat(sofaRuntimeManager.getAppClassLoader()).isEqualTo( + this.getClass().getClassLoader()); + assertThat(sofaRuntimeManager.getClientFactoryInternal()).isEqualTo(clientFactoryInternal); + } + + @Test + public void shutdown() { + // Given + TestRuntimeShutdownAware shutdownAware1 = new TestRuntimeShutdownAware(); + TestRuntimeShutdownAware shutdownAware2 = new TestRuntimeShutdownAware(); + sofaRuntimeManager.registerShutdownAware(shutdownAware1); + sofaRuntimeManager.registerShutdownAware(shutdownAware2); + + // When + sofaRuntimeManager.shutdown(); + + // Then + assertThat(shutdownAware1.isShutdown()).isTrue(); + assertThat(shutdownAware2.isShutdown()).isTrue(); + assertThat(sofaRuntimeManager.getComponentManager()).isNull(); + assertThat(sofaRuntimeManager.getSofaRuntimeContext()).isNull(); + assertThat(sofaRuntimeManager.getClientFactoryInternal()).isNull(); + } + + @Test + public void shutDownExternally() { + // When + sofaRuntimeManager.shutDownExternally(); + + // Then + assertThat(sofaRuntimeManager.getAppClassLoader()).isNull(); + } + + static class TestRuntimeShutdownAware implements RuntimeShutdownAware { + + private boolean shutdown = false; + + @Override + public void shutdown() { + shutdown = true; + } + + public boolean isShutdown() { + return shutdown; + } + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/DemoComponent.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/DemoComponent.java index 001513a8c..a395ea059 100644 --- a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/DemoComponent.java +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/DemoComponent.java @@ -31,10 +31,22 @@ public class DemoComponent extends AbstractComponent { public static ComponentType DEMO_COMPONENT_TYPE = new ComponentType("Demo"); + private boolean canBeDuplicate = true; + + private boolean registerException = false; + + private boolean resolveException = false; + + private boolean activateException = false; + public DemoComponent() { this.componentName = ComponentNameFactory.createComponentName(DEMO_COMPONENT_TYPE, "demo"); } + public DemoComponent(String name) { + this.componentName = ComponentNameFactory.createComponentName(DEMO_COMPONENT_TYPE, name); + } + @Override public ComponentType getType() { return DEMO_COMPONENT_TYPE; @@ -44,4 +56,49 @@ public ComponentType getType() { public Map getProperties() { return null; } + + @Override + public void register() { + if (registerException) { + throw new RuntimeException("register error"); + } + super.register(); + } + + @Override + public boolean resolve() { + if (resolveException) { + throw new RuntimeException("resolve error"); + } + return super.resolve(); + } + + @Override + public void activate() { + if (activateException) { + throw new RuntimeException("activate error"); + } + super.activate(); + } + + @Override + public boolean canBeDuplicate() { + return canBeDuplicate; + } + + public void setCanBeDuplicate(boolean canBeDuplicate) { + this.canBeDuplicate = canBeDuplicate; + } + + public void setRegisterException(boolean registerException) { + this.registerException = registerException; + } + + public void setResolveException(boolean resolveException) { + this.resolveException = resolveException; + } + + public void setActivateException(boolean activateException) { + this.activateException = activateException; + } } diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/SampleService.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/SampleService.java index a14291fa3..c7da39175 100644 --- a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/SampleService.java +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/sample/SampleService.java @@ -22,4 +22,8 @@ */ public interface SampleService { String service(); + + default String test() { + return "test"; + } } \ No newline at end of file diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/AsyncInitBeanFactoryPostProcessorTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/AsyncInitBeanFactoryPostProcessorTests.java new file mode 100644 index 000000000..856d0e1a8 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/AsyncInitBeanFactoryPostProcessorTests.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.spring; + +import com.alipay.sofa.runtime.api.annotation.SofaAsyncInit; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.stereotype.Component; + +import static com.alipay.sofa.runtime.async.AsyncInitMethodManager.ASYNC_INIT_METHOD_NAME; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link AsyncInitBeanFactoryPostProcessor}. + * + * @author huzijie + * @version AsyncInitBeanFactoryPostProcessorTests.java, v 0.1 2023年04月10日 4:29 PM huzijie Exp $ + */ +public class AsyncInitBeanFactoryPostProcessorTests { + + private GenericApplicationContext genericApplicationContext; + + @BeforeEach + public void setUp() { + genericApplicationContext = new AnnotationConfigApplicationContext(); + genericApplicationContext.registerBean(AsyncInitBeanFactoryPostProcessor.class); + } + + @Test + public void parseAnnotationOnClass() { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(NormalClass.class); + rootBeanDefinition.setInitMethodName("init"); + genericApplicationContext.registerBeanDefinition("bean", rootBeanDefinition); + genericApplicationContext.refresh(); + + assertThat(rootBeanDefinition.getAttribute(ASYNC_INIT_METHOD_NAME)).isEqualTo("init"); + } + + @Test + public void parseAnnotationOnMethod() { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(NormalMethodClass.class); + genericApplicationContext.registerBeanDefinition("bean", rootBeanDefinition); + genericApplicationContext.refresh(); + + BeanDefinition beanDefinition = genericApplicationContext.getBeanFactory() + .getBeanDefinition("normalClass"); + + assertThat(beanDefinition.getAttribute(ASYNC_INIT_METHOD_NAME)).isEqualTo("init"); + } + + @Test + public void parseAnnotationOnClassWithFalse() { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(NormalFalseClass.class); + rootBeanDefinition.setInitMethodName("init"); + genericApplicationContext.registerBeanDefinition("bean", rootBeanDefinition); + genericApplicationContext.refresh(); + + assertThat(rootBeanDefinition.getAttribute(ASYNC_INIT_METHOD_NAME)).isNull(); + } + + @SofaAsyncInit + static class NormalClass { + + public void init() { + + } + } + + @SofaAsyncInit(value = false) + static class NormalFalseClass { + + public void init() { + + } + } + + @Component + static class NormalMethodClass { + + @Bean(initMethod = "init") + @SofaAsyncInit + public NormalClass normalClass() { + return new NormalClass(); + } + } +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/AsyncProxyBeanPostProcessorTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/AsyncProxyBeanPostProcessorTests.java new file mode 100644 index 000000000..1cac1a672 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/AsyncProxyBeanPostProcessorTests.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.spring; + +import com.alipay.sofa.runtime.async.AsyncInitMethodManager; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.support.GenericApplicationContext; + +import static com.alipay.sofa.runtime.async.AsyncInitMethodManager.ASYNC_INIT_METHOD_NAME; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link AsyncProxyBeanPostProcessor}. + * + * @author huzijie + * @version AsyncProxyBeanPostProcessorTests.java, v 0.1 2023年04月10日 4:44 PM huzijie Exp $ + */ +public class AsyncProxyBeanPostProcessorTests { + + private GenericApplicationContext genericApplicationContext; + + @BeforeEach + public void setUp() { + genericApplicationContext = new AnnotationConfigApplicationContext(); + } + + @Test + public void registerAsyncBeans() { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(AsyncClass.class); + rootBeanDefinition.setAttribute(ASYNC_INIT_METHOD_NAME, "init"); + genericApplicationContext.registerBean(AsyncProxyBeanPostProcessor.class); + genericApplicationContext.registerBean(AsyncInitMethodManager.class); + genericApplicationContext.registerBeanDefinition("bean", rootBeanDefinition); + genericApplicationContext.refresh(); + + Object object = genericApplicationContext.getBean("bean"); + assertThat(AopUtils.isCglibProxy(object)).isTrue(); + } + + @Test + public void wrapAsyncBeans() throws Exception { + AsyncInitMethodManager asyncInitMethodManager = new AsyncInitMethodManager(); + AsyncProxyBeanPostProcessor asyncProxyBeanPostProcessor = new AsyncProxyBeanPostProcessor( + asyncInitMethodManager); + asyncProxyBeanPostProcessor.setBeanFactory(genericApplicationContext.getBeanFactory()); + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(AsyncClass.class); + rootBeanDefinition.setAttribute(ASYNC_INIT_METHOD_NAME, "init"); + genericApplicationContext.getBeanFactory().registerSingleton("asyncProxyBeanPostProcessor", + asyncProxyBeanPostProcessor); + genericApplicationContext.registerBeanDefinition("bean", rootBeanDefinition); + genericApplicationContext.refresh(); + asyncProxyBeanPostProcessor.afterPropertiesSet(); + + String initMethodName = asyncInitMethodManager.findAsyncInitMethod( + genericApplicationContext.getBeanFactory(), "bean"); + assertThat(initMethodName).isEqualTo("init"); + + } + + static class AsyncClass { + + public void init() { + + } + } + +} diff --git a/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/bean/SofaParameterNameDiscovererTests.java b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/bean/SofaParameterNameDiscovererTests.java new file mode 100644 index 000000000..a7c543c15 --- /dev/null +++ b/sofa-boot-project/sofa-boot-core/runtime-sofa-boot/src/test/java/com/alipay/sofa/runtime/spring/bean/SofaParameterNameDiscovererTests.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.alipay.sofa.runtime.spring.bean; + +import com.alipay.sofa.boot.annotation.AnnotationWrapper; +import com.alipay.sofa.boot.annotation.DefaultPlaceHolderBinder; +import com.alipay.sofa.runtime.api.annotation.SofaReference; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.mock.env.MockEnvironment; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SofaParameterNameDiscoverer}. + * + * @author huzijie + * @version SofaParameterNameDiscovererTests.java, v 0.1 2023年04月10日 5:00 PM huzijie Exp $ + */ +public class SofaParameterNameDiscovererTests { + + private SofaParameterNameDiscoverer parameterNameDiscoverer; + + private AnnotationWrapper annotationWrapper; + + private MockEnvironment mockEnvironment; + + @BeforeEach + public void setUp() { + mockEnvironment = new MockEnvironment(); + annotationWrapper = AnnotationWrapper.create(SofaReference.class) + .withEnvironment(mockEnvironment).withBinder(DefaultPlaceHolderBinder.INSTANCE); + parameterNameDiscoverer = new SofaParameterNameDiscoverer(annotationWrapper); + } + + @Test + public void getParameterNamesOnMethods() { + Method method = ReflectionUtils.findMethod(SofaReferenceOnMethod.class, "hello", + String.class); + String[] parameters = parameterNameDiscoverer.getParameterNames(method); + assertThat(parameters).hasSize(1); + assertThat(parameters[0]).isEqualTo("ReferenceFactoryBean#java.lang.String:a"); + } + + @Test + public void getParameterNamesOnConstructs() throws NoSuchMethodException { + Constructor constructor = ReflectionUtils.accessibleConstructor( + SofaReferenceOnConstructs.class, String.class); + String[] parameters = parameterNameDiscoverer.getParameterNames(constructor); + assertThat(parameters).hasSize(1); + assertThat(parameters[0]).isEqualTo("ReferenceFactoryBean#java.lang.String:a"); + } + + @Test + public void getParameterNamesOnConstruct() { + + } + + static class SofaReferenceOnMethod { + + public void hello(@SofaReference(uniqueId = "a") String b) { + + } + } + + static class SofaReferenceOnConstructs { + + public SofaReferenceOnConstructs(@SofaReference(uniqueId = "a") String b) { + + } + } +} diff --git a/sofa-boot-project/sofa-boot-parent/pom.xml b/sofa-boot-project/sofa-boot-parent/pom.xml index e06e925d3..53bffcc6c 100644 --- a/sofa-boot-project/sofa-boot-parent/pom.xml +++ b/sofa-boot-project/sofa-boot-parent/pom.xml @@ -197,6 +197,7 @@ com/alipay/sofa/smoke/tests/** + com/alipay/sofa/common/xmap/** false diff --git a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaGenericApplicationContext.java b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaGenericApplicationContext.java index 0d36ea39f..8a7761182 100644 --- a/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaGenericApplicationContext.java +++ b/sofa-boot-project/sofa-boot/src/main/java/com/alipay/sofa/boot/context/SofaGenericApplicationContext.java @@ -65,6 +65,10 @@ public class SofaGenericApplicationContext extends GenericApplicationContext { } } + public SofaGenericApplicationContext() { + this(new SofaDefaultListableBeanFactory()); + } + /** * Create a new SofaApplicationContext with the given DefaultListableBeanFactory. * @param beanFactory the DefaultListableBeanFactory instance to use for this context diff --git a/sofa-boot-tests/sofa-boot-jacoco-report/pom.xml b/sofa-boot-tests/sofa-boot-jacoco-report/pom.xml index 898f20b02..439e331ba 100644 --- a/sofa-boot-tests/sofa-boot-jacoco-report/pom.xml +++ b/sofa-boot-tests/sofa-boot-jacoco-report/pom.xml @@ -91,6 +91,7 @@ false com/alipay/sofa/smoke/tests/** + com/alipay/sofa/common/xmap/**